Plugins
limex_integrator.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 - 2020: G-CSC, Goethe University Frankfurt
3  * Author: Arne Naegel
4  *
5  * This file is part of UG4.
6  *
7  * UG4 is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License version 3 (as published by the
9  * Free Software Foundation) with the following additional attribution
10  * requirements (according to LGPL/GPL v3 §7):
11  *
12  * (1) The following notice must be displayed in the Appropriate Legal Notices
13  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14  *
15  * (2) The following notice must be displayed at a prominent place in the
16  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17  *
18  * (3) The following bibliography is recommended for citation and must be
19  * preserved in all covered files:
20  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21  * parallel geometric multigrid solver on hierarchically distributed grids.
22  * Computing and visualization in science 16, 4 (2013), 151-164"
23  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24  * flexible software system for simulating pde based models on high performance
25  * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30  * GNU Lesser General Public License for more details.
31  */
32 
33 #ifndef LIMEX_INTEGRATOR_HPP_
34 #define LIMEX_INTEGRATOR_HPP_
35 /*
36 #define XMTHREAD_BOOST
37 #ifdef XMTHREAD_BOOST
38 #include <boost/thread/thread.hpp>
39 #endif
40 */
41 #include <string>
42 
43 #include "common/stopwatch.h"
44 
49 
51 #include "lib_disc/assemble_interface.h" // TODO: missing IAssemble in following file:
58 #include "lib_disc/function_spaces/grid_function_util.h" // SaveVectorForConnectionViewer
60 #include "lib_disc/io/vtkoutput.h"
61 
63 
64 
65 // own headers
66 #include "time_extrapolation.h"
67 #include "time_integrator.hpp"
68 #include "../limex_tools.h"
69 //#include "../multi_thread_tools.h"
70 
71 
72 #ifdef UG_JSON
73 #include <nlohmann/json.hpp>
74 #endif
75 
76 #undef LIMEX_MULTI_THREAD
77 
78 namespace ug {
79 
80 
81 /*
82 template<class TI>
83 class TimeIntegratorThread : public TI
84 {
85  TimeIntegratorThread(SmartPtr<grid_function_type> u1, number t1, ConstSmartPtr<grid_function_type> u0, number t0)
86  {
87 
88  }
89 
90  // thre
91  void apply()
92  {
93  TI::apply(u1, t1, u0, t0);
94  }
95 
96 
97 };*/
98 
99 static void MyPrintError(UGError &err)
100 {
101  for(size_t i=0;i<err.num_msg();++i)
102  {
103  UG_LOG("MYERROR "<<i<<":"<<err.get_msg(i)<<std::endl);
104  UG_LOG(" [at "<<err.get_file(i)<<
105  ", line "<<err.get_line(i)<<"]\n");
106  }
107 }
108 
110 {
111  virtual ~ILimexRefiner(){};
112 
113 protected:
115 };
116 
118 
120 {
121 public:
124 
126  virtual void update_cost(std::vector<number> &costA, const std::vector<size_t> &vSteps, const size_t nstages) = 0;
127 };
128 
129 
132 {
133 public:
135  void update_cost(std::vector<number> &m_costA, const std::vector<size_t> &m_vSteps, const size_t nstages)
136  {
137  UG_ASSERT(m_costA.size() >= nstages, "Huhh: Vectors match in size:" << m_costA.size() << "vs." << nstages);
138 
139  UG_LOG("A_0="<< m_vSteps[0] << std::endl);
140  m_costA[0] = (1.0)*m_vSteps[0];
141  for (size_t i=1; i<nstages; ++i)
142  {
143  m_costA[i] = m_costA[i-1] + (1.0)*m_vSteps[i];
144  UG_LOG("A_i="<< m_vSteps[i] << std::endl);
145  }
146  }
147 };
148 
151 {
152 public:
154  m_cAssemble (1.0), m_cMatAdd(0.0), m_cSolution(1.0), m_useGamma(1)
155  {}
156 
157  void update_cost(std::vector<number> &m_costA, const std::vector<size_t> &nSteps, const size_t nstages)
158  {
159  UG_ASSERT(m_costA.size() >= nstages, "Huhh: Vectors match in size:" << m_costA.size() << "vs." << nstages);
160 
161  // 3 assemblies (M0, J0, Gamma0)
162  m_costA[0] = (2.0+m_useGamma)*m_cAssemble + nSteps[0]*((1.0+m_useGamma)*m_cMatAdd + m_cSolution);
163  for (size_t i=1; i<=nstages; ++i)
164  {
165  // n-1 assemblies for Mk, 2n MatAdds, n solutions
166  m_costA[i] = m_costA[i-1] + (nSteps[i]-1) * m_cAssemble + nSteps[i]*((1.0+m_useGamma)*m_cMatAdd + m_cSolution);
167  }
168  }
169 
170 protected:
171  double m_cAssemble;
172  double m_cMatAdd;
173  double m_cSolution;
174 
176 
177 };
178 
179 
181 
182 {
183 public:
185  : m_nstages(2),
186  m_tol(0.01),
187  m_rhoSafety(0.8),
188  m_sigmaReduction(0.5),
190  m_max_reductions(2),
191  m_asymptotic_order(1000),
192  m_useCachedMatrices(false),
193  m_conservative(0)
194  {}
195 
196  LimexTimeIntegratorConfig(unsigned int nstages)
197  : m_nstages(nstages),
198  m_tol(0.01),
199  m_rhoSafety(0.8),
200  m_sigmaReduction(0.5),
202  m_max_reductions(2),
203  m_asymptotic_order(1000),
204  m_useCachedMatrices(false),
205  m_conservative(0)
206  {}
207 
208 
209 protected:
210  unsigned int m_nstages;
211  double m_tol;
212  double m_rhoSafety;
214 
216 
219 
221  unsigned int m_conservative; // stepping back?
222 
223 #ifdef UG_JSON
224  NLOHMANN_DEFINE_TYPE_INTRUSIVE(LimexTimeIntegratorConfig,
228 #endif
229 public:
230  std::string config_string() const {
231  #ifdef UG_JSON
232  try{
233  nlohmann::json j(*this);
234  // to_json(j, *this);
235  return j.dump();
236  } catch (...) {
237  return std::string("EXCEPTION!!!");
238  }
239  #else
240  return std::string("LimexTimeIntegratorConfig::config_string()");
241  #endif
242  }
243 
244 };
245 
247 template<class TDomain, class TAlgebra>
249 : public INonlinearTimeIntegrator<TDomain, TAlgebra>,
250  public VectorDebugWritingObject<typename TAlgebra::vector_type>,
251  public LimexTimeIntegratorConfig // TODO: should become a 'has a'.
252 {
253 
254 
255 public:
256  typedef TAlgebra algebra_type;
262 
269 
272  {
273  //typedef boost::thread thread_type;
274  public:
275 
277  : m_stepper(spTimeStep)
278  {}
279 
282  { return m_stepper; }
283 
284 
286  { m_solver = solver;}
287 
289  { return m_solver;}
290 
291  void set_error(int e)
292  { m_error=e; }
293 
294 
295  void get_error()
296  { /*return m_error;*/ }
297 
298 
300  { m_sol = sol;}
301 
303  { return m_sol;}
304 
306  { m_dot = sol;}
307 
309  { return m_dot;}
310 
311  protected:
312  // includes time step series
315 
318  int m_error;
319  };
320 
321  typedef std::vector<SmartPtr<ThreadData> > thread_vector_type;
322 
323 public:
324 
327  {
328  for(size_t i=0; i<m_vThreadData.size(); ++i)
329  {
330  m_vThreadData[i].get_time_stepper()->set_debug(spDebugWriter);
331  }
332  UG_LOG("set_debug:" << m_vThreadData.size());
333  }
334 
336 protected:
338 
339 
340 
341 public:
342  LimexTimeIntegrator(int nstages):
343  LimexTimeIntegratorConfig(nstages),
344  m_gamma(m_nstages+1),
345  m_costA(m_nstages+1),
346  m_monitor(((m_nstages)*(m_nstages))), // TODO: wasting memory here!
352  m_spBanachSpace(new AlgebraicSpace<grid_function_type>()), // default algebraic space
353  m_bInterrupt(false),
354  m_limex_step(1)
355  {
356  m_vThreadData.reserve(m_nstages);
357  m_vSteps.reserve(m_nstages);
358  init_gamma(); // init exponents (i.e. k+1, k, 2k+1, ...)
359  }
360 
361 
362 
364  void set_tolerance(double tol) { m_tol = tol;}
365  void set_stepsize_safety_factor(double rho) { m_rhoSafety = rho;}
366  void set_stepsize_reduction_factor(double sigma) { m_sigmaReduction = sigma;}
368 
369  void set_max_reductions(size_t nred) { m_max_reductions = nred;}
371 
374  { m_spErrorEstimator = spErrorEstim; }
375 
378  {
379  UG_ASSERT(m_vThreadData.size() == m_vSteps.size(), "ERROR: m_vThreadData and m_vSteps differ in size!");
380 
381  UG_ASSERT(m_vThreadData.empty() || m_vSteps.back()<nsteps, "ERROR: Sequence of steps must be increasing." );
382 
383  // all entries have been set
384  if (m_vThreadData.size() == m_nstages)
385  { return; }
386 
387 
388  // a) set number of steps
389  m_vSteps.push_back(nsteps);
390 
391  // b) set time-stepper
392  SmartPtr<timestep_type> limexStepSingleton;
393 #ifndef LIMEX_MULTI_THREAD
394 
395  if(m_vThreadData.size()>0) {
396  // re-use time-stepper (if applicable)
397  limexStepSingleton = m_vThreadData.back().get_time_stepper();
398  }
399  else
400  {
401  // create time-stepper
402 #endif
403  // for mult-threading, each info object has own time-stepper
404  if (spGamma.invalid()) {
405  limexStepSingleton = make_sp(new timestep_type(spDD));
406  } else {
407  limexStepSingleton = make_sp(new timestep_type(spDD, spDD, spGamma));
408  }
409  UG_ASSERT(limexStepSingleton.valid(), "Huhh: Invalid pointer")
410 #ifndef LIMEX_MULTI_THREAD
411  }
412 #endif
413  // propagate debug info
414  limexStepSingleton->set_debug(VectorDebugWritingObject<vector_type>::vector_debug_writer());
415  m_vThreadData.push_back(ThreadData(limexStepSingleton));
416 
417  // c) set solver
418  UG_ASSERT(solver.valid(), "Huhh: Need to supply solver!");
419  m_vThreadData.back().set_solver(solver);
420  UG_ASSERT(m_vThreadData.back().get_solver().valid(), "Huhh: Need to supply solver!");
421  }
422 
424  { add_stage_base(nsteps, solver, spDD); }
425 
427  { add_stage_base(nsteps, solver, spDD, spGamma); }
428 
430  void add_stage(size_t i, size_t nsteps, SmartPtr<domain_discretization_type> spDD, SmartPtr<solver_type> solver)
431  {
432  UG_LOG("WARNING: add_stage(i, nsteps ,...) is deprecated. Please use 'add_stage(nsteps ,...) instead!'");
433  add_stage(nsteps, solver, spDD);
434  }
435 
438  {
439  UG_ASSERT(i<m_vThreadData.size(), "Huhh: Invalid entry");
440  return m_vThreadData[i].get_time_stepper();
441  }
442 
443 
444 
445 
446 protected:
449 
451  int apply_integrator_threads(number dtcurr, ConstSmartPtr<grid_function_type> u0, number t0, size_t nstages);
452 
455 
458 
461 
462 public:
465 
466  number get_cost(size_t i) { return m_costA[i]; }
467  number get_gamma(size_t i) { return m_gamma[i]; }
468  number get_workload(size_t i) { return m_workload[i]; }
469 
470 
471 protected:
472  number& monitor(size_t k, size_t q) {
473  UG_ASSERT(k<m_nstages, "Huhh: k mismatch");
474  UG_ASSERT(q<m_nstages, "Huhh: q mismatch");
475  return m_monitor[k+(m_nstages)*q];
476  }
477 
479  void init_gamma()
480  {
481  for (size_t k=0; k<=m_nstages; ++k)
482  {
483  m_gamma[k] = 2.0+k;
484  }
485  }
486 
488  // (depends on m_vSteps, which must have been initialized!)
489  void update_cost()
490  {
491  m_spCostStrategy->update_cost(m_costA, m_vSteps, m_nstages);
492  }
493 
495  // (depends on cost, which must have been initialized!)
497  {
498  UG_ASSERT(m_costA.size()>= m_nstages, "Cost vector too small!")
499  for (size_t k=0; k<m_nstages-1; ++k)
500  {
501  UG_LOG("k= "<< k<< ", A[k]=" << m_costA[k] << ", gamma[k]=" << m_gamma[k] << "\t");
502  for (size_t q=0; q<m_nstages-1; ++q)
503  {
504  // Deuflhard: Order and stepsize, ... eq. (3.7)
505  double gamma = (m_costA[k+1] - m_costA[0] + 1.0)/(m_costA[q+1] - m_costA[0] + 1.0);
506  double alpha = pow(m_tol, gamma);
507 
508  // for fixed order q, the monitor indicates the performance penalty compared to a strategy using k stages only
509  // cf. eq. (4.6)
510  monitor(k,q) = pow(alpha/(m_tol * m_rhoSafety), 1.0/m_gamma[k]);
511  UG_LOG(monitor(k,q) << "[" << pow(alpha/(m_tol), 1.0/m_gamma[k]) <<"," << gamma<< ","<< m_costA[k+1] << "," << m_costA[q+1]<< ","<< alpha << "]" << "\t");
512  // UG_LOG( << "\t");
513 
514  }
515  UG_LOG(std::endl);
516  }
517 
518  }
519 
520  // Find row k=1, ..., ntest-1 minimizing (estimated) error eps[kmin]
521  // Also: predict column q with minimal workload W_{k+1,k} = A_{k+1} * lambda_{k+1}
522  size_t find_optimal_solution(const std::vector<number>& eps, size_t ntest, /*size_t &kf,*/ size_t &qpred);
523 
524 public:
527 
530 
533 
534 
537 
539  { m_spCostStrategy = cost;}
540 
541 
544  {
545  m_spBanachSpace = spSpace;
546  UG_LOG("set_space:" << m_spBanachSpace->config_string());
547  }
548 
550  void interrupt() {m_bInterrupt = true;}
551 
552  void set_conservative(bool c)
553  { m_conservative = (c) ? 1 : 0; }
554 
555  std::string config_string() const
557 
558 protected:
559 
560  SmartPtr<error_estim_type> m_spErrorEstimator; // (smart ptr for) error estimator
561 
562  std::vector<size_t> m_vSteps;
563  std::vector<ThreadData> m_vThreadData;
564 
565  std::vector<number> m_gamma;
566 
567  std::vector<number> m_costA;
568  std::vector<number> m_monitor;
569 
570  std::vector<number> m_workload;
571  std::vector<number> m_lambda;
572 
573  std::vector<size_t> m_num_reductions;
574 
575  std::vector<number> m_consistency_error;
576 
578 
580 
583 
586 
587 
588 };
589 
590 
592 template<class TDomain, class TAlgebra>
594 {
595  PROFILE_FUNC_GROUP("limex");
596  const int nstages = m_vThreadData.size()-1;
597  for (int i=nstages; i>=0; --i)
598  {
599  m_vThreadData[i].set_solution(u->clone());
600  m_vThreadData[i].set_derivative(u->clone());
601  m_vThreadData[i].get_time_stepper()->set_matrix_cache(m_useCachedMatrices);
602  }
603 }
604 
606 template<class TDomain, class TAlgebra>
608 {
609  PROFILE_FUNC_GROUP("limex");
610  const int nstages = m_vThreadData.size()-1;
611  for (int i=nstages; i>=0; --i)
612  {
613  m_vThreadData[i].set_solution(SPNULL);
614  m_vThreadData[i].set_derivative(SPNULL);
615  // m_vThreadData[i].get_time_stepper()->set_matrix_cache(m_useCachedMatrices);
616  }
617 }
618 
619 
620 // create (& execute) threads
621 /*boost::thread_group g;
622  typename thread_vector_type::reverse_iterator rit=m_vThreadData.rbegin();
623  for (rit++; rit!= m_vThreadData.rend(); ++rit)
624  {
625 
626  boost::thread *t =new boost::thread(boost::bind(&ThreadSafeTimeIntegrator::apply, *rit));
627  //g.add_thread(t);
628 
629  g.create_thread(boost::bind(&ThreadSafeTimeIntegrator::apply, *rit));
630 
631  }*/
632 
633 
634 /* TODO: PARALLEL execution?*/
635 template<class TDomain, class TAlgebra>
637 {
638  PROFILE_FUNC_GROUP("limex");
639  update_cost(); // compute cost A_i (alternative: measure times?)
640  update_monitor(); // convergence monitor
641 
642  /*
643  int tn = omp_get_thread_num();
644  int nt = omp_get_num_threads();
645  omp_set_num_threads(nstages);
646  */
647  int error = 0;
648  //const int nstages = m_vThreadData.size()-1;
649  // #pragma omp for private(i) // shared (nstages, u1) schedule(static)
650  for (int i=0; i<=(int)nstages; ++i)
651  {
652  /*
653  std::cerr << "I am " << tn << " of " << nt << " ("<< i<< "/" << nstages<<")!" << std::endl;
654  UGMultiThreadEnvironment mt_env;
655  */
656 
657  // copy data to private structure (one-to-many)
658  //m_vThreadData[i].set_solution(u1->clone());
659 
660  // switch to "child" comm
661  // mt_env.begin();
662 
663  // integrate (t0, t0+dtcurr)
664  time_integrator_type integrator(m_vThreadData[i].get_time_stepper());
665  integrator.set_time_step(dtcurr/m_vSteps[i]);
666  integrator.set_dt_min(dtcurr/m_vSteps[i]);
667  integrator.set_dt_max(dtcurr/m_vSteps[i]);
668  integrator.set_reduction_factor(0.0); // quit immediately, if step fails
669  integrator.set_solver(m_vThreadData[i].get_solver());
670  integrator.set_derivative(m_vThreadData[i].get_derivative());
671 
672  UG_ASSERT(m_spBanachSpace.valid(), "Huhh: Need valid (default) banach space");
673  integrator.set_banach_space(m_spBanachSpace);
674  UG_LOG("Set space:" << m_spBanachSpace->config_string());
675 
676  bool exec = true;
677  try
678  {
679  exec = integrator.apply(m_vThreadData[i].get_solution(), t0+dtcurr, u0, t0);
680  m_consistency_error[i] = integrator.get_consistency_error();
681  }
682  catch(ug::UGError& err)
683  {
684 
685  exec = false;
686  error += (1 << i);
687  UG_LOGN("Step "<< i<< " failed on stage " << i << ": " << err.get_msg());
688  MyPrintError(err);
689 
690  }
691 
692  if (!exec)
693  {
694  // Additional actions at failure
695  }
696 
697  // switch to "parent" comm
698  //mt_env.end();
699  } /*for all stages loop*/
700 
701 
702 
703  return error;
704 }
705 
706 
707 template<class TDomain, class TAlgebra>
709 {
710  // join all threads
711  // g.join_all();
712  const int nstages = m_vThreadData.size()-1;
713  for (int i=nstages; i>=0; --i)
714  {
715  m_vThreadData[i].get_time_stepper()->invalidate();
716  }
717 }
718 
719 
720 template<class TDomain, class TAlgebra>
722 {
723  const int nstages = m_vThreadData.size()-1;
724  for (int i=nstages; i>=0; --i)
725  {
726  UG_ASSERT(m_vThreadData[i].get_solution()->size()==ucommon->size(), "LIMEX: Vectors must match in size!")
727  *m_vThreadData[i].get_solution() = *ucommon;
728  }
729 }
730 
731 template<class TDomain, class TAlgebra>
733 find_optimal_solution(const std::vector<number>& eps, size_t ntest, /*size_t &kf,*/ size_t &qpred)
734 {
735 
736  const size_t qold=qpred;
737 
738  size_t jbest = 1;
739  qpred = 1;
740 
741  size_t j=1;
742  size_t k=j-1;
743 
744  m_lambda[k] = pow(m_rhoSafety*m_tol/eps[j], 1.0/m_gamma[k]); // 1/epsilon(k)
745  m_workload[k] = m_costA[j]/m_lambda[k];
746  UG_LOG("j=" << j << ": eps=" << eps[j] << ", lambda(j)=" <<m_lambda[k] << ", epsilon(j)=" <<1.0/m_lambda[k] << "<= alpha(k, qcurr)=" << monitor(k,qold-1) << "< alpha(k, qcurr+1)=" << monitor(k,qold) <<", A="<< m_costA[j] << ", W="<< m_workload[k] <<std::endl);
747 
748  for (j=2; j<ntest; ++j)
749  {
750  k = j-1;
751  m_lambda[k] = pow(m_rhoSafety*m_tol/eps[j], 1.0/m_gamma[k]);
752  m_workload[k] = m_costA[j]/m_lambda[k];
753  UG_LOG("j=" << j << ": eps=" << eps[j] << ", lambda(j)=" <<m_lambda[k] << ", epsilon(j)=" <<1.0/m_lambda[k] << "<= alpha(k, qcurr)=" << monitor(k,qold-1) << "< alpha(k, qcurr+1)=" << monitor(k,qold) <<", A="<< m_costA[j] << ", W="<< m_workload[k] <<std::endl);
754 
755 
756  // TODO: Convergence monitor
757 
758  qpred = (m_workload[qpred-1] > m_workload[k]) ? j : qpred;
759  jbest = (eps[jbest] > eps [j]) ? j : jbest;
760  }
761 
762  return jbest;
763 }
764 
765 template<class TDomain, class TAlgebra>
768 {
769  PROFILE_FUNC_GROUP("limex");
770 #ifdef UG_OPENMP
771  // create multi-threading environment
772  //int nt = std::min(omp_get_max_threads(), m_nstages);
773 
774 #endif
775 
776  // NOTE: we use u as common storage for future (and intermediate) solution(s)
777  if (u.get() != u0.get()) // only copy if not already identical, otherwise: PST_UNDEFINED!
778  *u = *u0;
779 
780  // initialize integrator threads
781  // (w/ solutions)
782  init_integrator_threads(u0);
783 
784 
785  // write_debug
786  for (unsigned int i=0; i<m_vThreadData.size(); ++i)
787  {
788  std::ostringstream ossName;
789  ossName << std::setfill('0') << std::setw(4);
790  ossName << "Limex_Init_iter" << 0 << "_stage" << i;
791  write_debug(*m_vThreadData[i].get_solution(), ossName.str().c_str());
792  }
793 
794  number t = t0;
796 
797  size_t kmax = m_vThreadData.size(); // maximum number of stages
798  size_t qpred = kmax-1; // predicted optimal order
799  size_t qcurr = qpred; // current order
800 
801  // for Gustafsson/lundh/Soederlind type PID controller
802  /*size_t qlast = 0;
803  double dtlast = 0.0;
804  std::vector<double> epslast(kmax, m_rhoSafety*m_tol);
805 */
806 
807  // time integration loop
809  size_t limex_total = 1;
810  size_t limex_success = 0;
811  size_t ntest;
812  size_t jbest;
813 
814  m_bInterrupt = false;
815  //bool bProbation = false;
816  bool bAsymptoticReduction = false;
817 
818  const size_t nSwitchHistory=16;
819  const size_t nSwitchLookBack=5;
820  int vSwitchHistory[nSwitchHistory] ={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
821 
822  timex_type timex(m_vSteps);
823  while ((t < t1) && ((t1-t) > base_type::m_precisionBound))
824  {
825  int err = 0;
826 
827  //UG_DLOG(LIB_LIMEX, 5, "+++ LimexTimestep +++" << limex_step << "\n");
828  UG_LOG("+++ LimexTimestep +++" << m_limex_step << "\n");
829 
830 
831  // save time stamp for limex step start
832  Stopwatch stopwatch;
833  stopwatch.start();
834 
835 
836  // determine step size
837  number dt = std::min(dtcurr, t1-t);
838  UG_COND_THROW(dt < base_type::get_dt_min(), "Time step size below minimum. ABORTING! dt=" << dt << "; dt_min=" << base_type::get_dt_min() << "\n");
839 
840 
841  // Notify init observers. (NOTE: u = u(t))¸
842  itime_integrator_type::notify_init_step(u, m_limex_step, t, dt);
843 
844 
845  // determine number of stages to investigate
846  qcurr = qpred;
847  ntest = std::min(kmax, qcurr+1);
848  UG_LOG("ntest="<< ntest << std::endl);
849 
850  // checks
851  UG_ASSERT(m_vSteps.size() >= ntest, "Huhh: sizes do not match: " << m_vSteps.size() << "<"<<ntest);
852  UG_ASSERT(m_vThreadData.size() >= ntest, "Huhh: sizes do not match: " << m_vThreadData.size() << "< "<< ntest);
853 
855  // PARALLEL EXECUTION: BEGIN
856 
857  // write_debug
858  for (size_t i=0; i<ntest; ++i)
859  {
860  std::ostringstream ossName;
861  ossName << std::setfill('0') << std::setw(4);
862  ossName << "Limex_BeforeSerial_iter" << m_limex_step << "_stage" << i << "_total" << limex_total;
863  write_debug(*m_vThreadData[i].get_solution(), ossName.str().c_str());
864  }
865 
866  // integrate: t -> t+dt
867  err = apply_integrator_threads(dt, u, t, ntest-1);
868 
869  // write_debug
870  for (size_t i=0; i<ntest; ++i)
871  {
872  std::ostringstream ossName;
873  ossName << std::setfill('0') << std::setw(4);
874  ossName << "Limex_AfterSerial_iter" << m_limex_step << "_stage" << i << "_total" << limex_total;
875  write_debug(*m_vThreadData[i].get_solution(), ossName.str().c_str());
876  }
877 
878  join_integrator_threads();
879  // PARALLEL EXECUTION: END
881 
882 
884  // SERIAL EXECUTION: BEGIN
885 
886  // sanity checks
887  UG_ASSERT(m_spErrorEstimator.valid(), "Huhh: Invalid Error estimator?");
888 
889  double epsmin = 0.0;
890 
891  bool limexConverged = false;
892  if (err==0)
893  { // Compute extrapolation at t+dtcurr (SERIAL)
894  // Consistency check.
895  for (unsigned int i=1; i<ntest; ++i)
896  {
897  UG_LOG("Checking consistency:" <<m_consistency_error[i] <<"/" << m_consistency_error[i-1] << "="<< m_consistency_error[i]/m_consistency_error[i-1] << std::endl);
898  }
899 
900  // Extrapolation.
901  timex.set_error_estimate(m_spErrorEstimator);
902  for (unsigned int i=0; i<ntest; ++i)
903  {
904  UG_ASSERT(m_vThreadData[i].get_solution().valid(), "Huhh: no valid solution?");
905  timex.set_solution(m_vThreadData[i].get_solution(), i);
906  }
907  timex.apply(ntest);
908 
909  // write_debug
910  for (size_t i=0; i<ntest; ++i)
911  {
912  std::ostringstream ossName;
913  ossName << std::setfill('0') << std::setw(4);
914  ossName << "Limex_Extrapolates_iter" << m_limex_step << "_stage" << i << "_total" << limex_total;
915  write_debug(*m_vThreadData[i].get_solution(), ossName.str().c_str());
916  }
917  limex_total++;
918 
919  // Obtain sub-diagonal error estimates.
920  const std::vector<number>& eps = timex.get_error_estimates();
921  UG_ASSERT(ntest<=eps.size(), "Huhh: Not enough solutions?");
922 
923  // select optimal solution (w.r.t error) AND
924  // predict optimal order (w.r.t. workload) for next step
925  jbest = find_optimal_solution(eps, ntest, qpred);
926  UG_ASSERT(jbest < ntest, "Huhh: Not enough solutions?");
927 
928  // best solution
929  ubest = timex.get_solution(jbest-m_conservative).template cast_dynamic<grid_function_type>();
930  epsmin = eps[jbest];
931 
932  // check for convergence
933  limexConverged = (epsmin <= m_tol) ;
934 
935 
936  if (limex_success>3)
937  {
938 
939  vSwitchHistory[m_limex_step%nSwitchHistory] = (qpred - qcurr);
940  UG_DLOG(LIB_LIMEX, 5, "LIMEX-ASYMPTOTIC-ORDER switch: = " << (qpred - qcurr)<< std::endl);
941 
942  size_t nSwitches=0;
943  for (int s=nSwitchLookBack-1; s>=0; s--)
944  {
945  nSwitches += std::abs(vSwitchHistory[(m_limex_step-s)%nSwitchHistory]);
946  UG_DLOG(LIB_LIMEX, 6, "LIMEX-ASYMPTOTIC-ORDER: s[" << s<< "] = " << vSwitchHistory[(m_limex_step-s)%nSwitchHistory] << std::endl);
947  }
948  UG_DLOG(LIB_LIMEX, 5,"LIMEX-ASYMPTOTIC-ORDER: nSwitches = " << nSwitches << std::endl);
949 
950 
951  /*
952  if (bProbation)
953  {
954 
955  if ((qpred < qcurr) || (!limexConverged)) // consecutive (follow-up) order decrease
956  {
957  bProbation = true;
958  m_num_reductions[0]++;
959  UG_LOG("LIMEX-ASYMPTOTIC-ORDER: Decrease on parole detected: "<< qcurr << " -> " << qpred << "("<< m_num_reductions[0]<<")"<<std::endl);
960 
961  }
962  else
963  {
964  // reset all counters
965  bProbation = false;
966  UG_LOG("LIMEX-ASYMPTOTIC-ORDER: Probation off!"<<std::endl);
967 
968  }
969  }
970  else
971  {
972  if ((qpred < qcurr) || (!limexConverged))// 1st order decrease
973  {
974  bProbation = true;
975  m_num_reductions[0]++;
976  UG_LOG("LIMEX-ASYMPTOTIC-ORDER: Decrease detected: "<< qcurr << " -> " << qpred << "("<< m_num_reductions[0]<<")"<<std::endl);
977  }
978  else
979  {
980  m_num_reductions[0] = 0;
981  UG_LOG("LIMEX-ASYMPTOTIC-ORDER: I am totally free!"<<std::endl);
982  }
983 
984 
985  }
986 */
987 
988  // bAsymptoticReduction = (m_num_reductions[0] >= m_max_reductions) || bAsymptoticReduction;
989 
990  // bAsymptoticReduction = (nSwitches >= m_max_reductions) || bAsymptoticReduction;
991 
992  if (nSwitches >= m_max_reductions) {
993 
994 
995  m_asymptotic_order = std::min<size_t>(m_asymptotic_order-1, 2);
996  bAsymptoticReduction = true;
997 
998  for (int s=nSwitchLookBack-1; s>=0; s--)
999  { vSwitchHistory[(m_limex_step-s)%nSwitchHistory]=0; }
1000 
1001 
1002  }
1003 
1004 
1005 
1006  // asymptotic order reduction
1007  //if (m_num_reductions[0] >= m_max_reductions)
1008  if (bAsymptoticReduction)
1009  {
1010  kmax = (kmax >= m_asymptotic_order ) ? m_asymptotic_order : kmax;
1011  qpred = kmax - 1;
1012  UG_DLOG(LIB_LIMEX, 5, "LIMEX-ASYMPTOTIC-ORDER: Reduction: "<< qpred );
1013  UG_DLOG(LIB_LIMEX, 5, "(kmax=" << kmax << ", asymptotic"<< m_asymptotic_order <<") after "<<m_max_reductions<< std::endl);
1014  }
1015 
1016  } // (limex_success>3)
1017 
1018  /*
1019  // adjust for order bound history
1020  if ((m_num_reductions[qpred] > m_max_reductions) && (qpred > 1))
1021  {
1022  UG_LOG("prohibited q:"<< qpred << "(" << m_num_reductions[qpred] << ")"<<std::endl);
1023  //qpred--;
1024  qpred = kmax = 2;
1025  } else
1026  {
1027  UG_LOG("keeping q:"<< qpred << "(" << m_num_reductions[qpred] << ")"<<std::endl);
1028  }
1029  */
1030 
1031  //double pid = 1.0;
1032 
1033  // constant order?
1034  /*if (qcurr == qlast)
1035  {
1036  double dtRatio =dtcurr/dtlast;
1037  // Dd, Band 3 (DE), p. 360
1038  int k = ntest-1;
1039  while (k--) {
1040  double epsRatio =eps[k+1]/epslast[k+1];
1041 
1042  double qopt = log(epsRatio) / log(dtRatio); // take dtcurr here, as dt may be smaller
1043 
1044  UG_LOG("effective p["<< k << "]="<< qopt-1.0 <<","<< eps[k+1] <<","<< epslast[k+1] <<"," << epsRatio << "("<< log(epsRatio) << ","<< pow(epsRatio, 1.0/m_gamma[k]) <<")"<< dtcurr <<","<< dtlast << "," << dtRatio << "," <<log(dtRatio) << std::endl);
1045  }
1046 
1047 
1048  double epsRatio = eps[qcurr]/epslast[qcurr];
1049  pid = dtRatio/pow(epsRatio, 1.0/m_gamma[qcurr-1]);
1050 
1051  UG_LOG("pid=" << pid << std::endl);
1052 
1053  }*/
1054 
1055 
1056  // select (predicted) order for next step
1057  double dtpred = dtcurr*std::min(m_lambda[qpred-1], itime_integrator_type::get_increase_factor());
1058  //double dtpred = dtcurr*m_lambda[qpred-1];
1059  UG_LOG("+++++\nget_increase_factor() gives "<<itime_integrator_type::get_increase_factor()<<" \n+++++++")
1060  UG_LOG("koptim=\t" << jbest << ",\t eps(k)=" << epsmin << ",\t q=\t" << qpred<< "("<< ntest << "), lambda(q)=" << m_lambda[qpred-1] << ", alpha(q-1,q)=" << monitor(qpred-1, qpred) << "dt(q)=" << dtpred<< std::endl);
1061 
1062  // EXTENSIONS: convergence model
1063  if (limexConverged)
1064  {
1065  limex_success++;
1066 
1067  // a) aim for order increase in next step
1068  if ((qpred+1==ntest) /* increase by one possible? */
1069  // && (m_lambda[qpred-1]>1.0)
1070  // && (m_num_reductions[qpred+1] <= m_max_reductions)
1071  && (kmax>ntest)) /* still below max? */
1072  {
1073  const double alpha = monitor(qpred-1, qpred);
1074  UG_LOG("CHECKING for order increase: "<< m_costA[qpred] << "*" << alpha << ">" << m_costA[qpred+1]);
1075  // check, whether further increase could still be efficient
1076  if (m_costA[qpred] * alpha > m_costA[qpred+1])
1077  {
1078  qpred++; // go for higher order
1079  if (m_greedyOrderIncrease >0.0) {
1080  dtpred *= (1.0-m_greedyOrderIncrease) + m_greedyOrderIncrease*alpha; // & adapt time step // TODO: check required!
1081  }
1082  UG_LOG("... yes.\n")
1083 
1084  // update history
1085  vSwitchHistory[m_limex_step%nSwitchHistory] = (qpred - qcurr);
1086  UG_LOG("LIMEX-ASYMPTOTIC-ORDER switch update: = " << (qpred - qcurr)<< std::endl);
1087 
1088  } else {
1089  UG_LOG("... nope.\n")
1090  }
1091 
1092  }
1093 
1094 
1095  // b) monitor convergence (a-priori check!)
1096 
1097  }
1098 
1099  // parameters for subsequent step
1100  dtcurr = std::min(dtpred, itime_integrator_type::get_dt_max());
1101 
1102 
1103  }
1104  else
1105  {
1106  // solver failed -> cut time step
1107  dtcurr *= m_sigmaReduction;
1108  }
1109 
1110  // output compute time for Limex step
1111  number watchTime = stopwatch.ms()/1000.0;
1112  UG_LOGN("Time: " << std::setprecision(3) << watchTime << "s");
1113 
1114  if ((err==0) && limexConverged)
1115  {
1116  // ACCEPT time step
1117  UG_LOG("+++ LimexTimestep +++" << m_limex_step << " ACCEPTED"<< std::endl);
1118  UG_LOG(" :\t time \t dt (success) \t dt (pred) \tq=\t order (curr)" << qcurr+1 << std::endl);
1119  UG_LOG("LIMEX-ACCEPTING:\t" << t <<"\t"<< dt << "\t" << dtcurr << "\tq=\t" << qcurr+1 << std::endl);
1120 
1121 
1122  // update PID controller
1123  /*qlast = qcurr;
1124  epslast = timex.get_error_estimates(); // double check ???
1125  dtlast = dt;
1126 */
1127  // Compute time derivatives (by extrapolation)
1128  if (this->has_time_derivative())
1129  {
1130  UG_LOG("Computing derivative" << std::endl);
1131  grid_function_type &udot = *get_time_derivative();
1132 
1133  for (size_t i=0; i<=jbest; ++i)
1134  {
1135  timex.set_solution(m_vThreadData[i].get_derivative(), i);
1136  }
1137  timex.apply(jbest+1, false); // do not compute error
1138 
1139  udot = *timex.get_solution(jbest).template cast_dynamic<grid_function_type>();
1140 
1141  std::ostringstream ossName;
1142  ossName << std::setfill('0');
1143  ossName << "Limex_Derivative_iter" << m_limex_step << "_total" << limex_total;
1144  write_debug(udot, ossName.str().c_str());
1145  }
1146 
1147 
1148  // Copy best solution.
1149  UG_ASSERT(ubest.valid(), "Huhh: Invalid error estimate?");
1150  *u = *ubest;
1151  t += dt;
1152 
1153  // Initiate post process.
1154  itime_integrator_type::notify_finalize_step(u, m_limex_step++, t, dt);
1155 
1156  // make sure that all threads continue
1157  // with identical initial value u(t)
1158  // update_integrator_threads(ubest, t);
1159 
1160 
1161  // working on last row => increase order
1162  //if (ntest == q+1) ntest++;
1163  }
1164  else
1165  {
1166  // DISCARD time step
1167  UG_LOG("+++ LimexTimestep +++" << m_limex_step << " FAILED" << std::endl);
1168  UG_LOG("LIMEX-REJECTING:\t" << t <<"\t"<< dt << "\t" << dtcurr << std::endl);
1169 
1170  itime_integrator_type::notify_rewind_step(ubest, m_limex_step, t+dt, dt);
1171 
1172  }
1173 
1174  // interrupt if interruption flag set
1175  if (m_bInterrupt)
1176  {
1177  UG_LOGN("Limex interrupted by external command.");
1178  break;
1179  }
1180 
1181  // SERIAL EXECUTION: END
1183  update_integrator_threads(u, t);
1184 
1185 
1186  // SOLVE
1187 
1188  // ESTIMATE
1189 
1190  // MARK
1191 
1192  // REFINE
1193 
1194 
1195  } // time integration loop
1196 
1197  dispose_integrator_threads();
1198 
1199  return true;
1200 } // apply
1201 
1202 
1203 } // namespace ug
1204 
1205 #endif /* TIME_INTEGRATOR_HPP_ */
const T * get() const
T * get()
bool valid() const
Definition: time_extrapolation.h:973
void set_error_estimate(SmartPtr< ISubDiagErrorEst< vector_type > > subdiag)
set error estimator
Definition: time_extrapolation.h:1011
void apply(size_t nstages, bool with_error=true)
best error estimate
Definition: time_extrapolation.h:1052
void set_solution(SmartPtr< vector_type > soli, int i)
set solution (for stage i)
Definition: time_extrapolation.h:1003
const std::vector< number > & get_error_estimates() const
Definition: time_extrapolation.h:1017
SmartPtr< vector_type > get_solution(size_t i)
get solution (on stage i)
Definition: time_extrapolation.h:1007
Abstract class for the cost of a limex stage.
Definition: limex_integrator.hpp:120
virtual ~ILimexCostStrategy()
destructor
Definition: limex_integrator.hpp:123
virtual void update_cost(std::vector< number > &costA, const std::vector< size_t > &vSteps, const size_t nstages)=0
provides the cost for all 0...nstages stages.
Definition: limex_integrator.hpp:110
SmartPtr< IRefiner > m_spRefiner
Definition: limex_integrator.hpp:111
virtual ~ILimexRefiner()
Definition: limex_integrator.hpp:111
integration of non-linear systems (with bounds on dt)
Definition: time_integrator.hpp:1097
void set_dt_min(double min)
Definition: time_integrator.hpp:1116
void set_solver(SmartPtr< solver_type > solver)
Definition: time_integrator.hpp:1107
void set_reduction_factor(double dec)
Definition: time_integrator.hpp:1122
void set_dt_max(double max)
Definition: time_integrator.hpp:1119
Interface for sub-diagonal error estimator (w.r.t time in Aitken-Neville scheme)
Definition: time_extrapolation.h:142
void set_time_step(double dt)
Set initial time step.
Definition: time_integrator.hpp:570
double get_time_step()
Definition: time_integrator.hpp:573
Cost is identical to (summation over) number of steps.
Definition: limex_integrator.hpp:132
LimexDefaultCost()
Definition: limex_integrator.hpp:134
void update_cost(std::vector< number > &m_costA, const std::vector< size_t > &m_vSteps, const size_t nstages)
provides the cost for all 0...nstages stages.
Definition: limex_integrator.hpp:135
For.
Definition: limex_integrator.hpp:151
double m_cMatAdd
! Cost for matrix assembly
Definition: limex_integrator.hpp:172
double m_cAssemble
Definition: limex_integrator.hpp:171
void update_cost(std::vector< number > &m_costA, const std::vector< size_t > &nSteps, const size_t nstages)
provides the cost for all 0...nstages stages.
Definition: limex_integrator.hpp:157
int m_useGamma
! Cost for solving Jx=b
Definition: limex_integrator.hpp:175
double m_cSolution
! Cost for J=A+B
Definition: limex_integrator.hpp:173
LimexNonlinearCost()
Definition: limex_integrator.hpp:153
Contains all data for parallel execution of time steps.
Definition: limex_integrator.hpp:272
void get_error()
Definition: limex_integrator.hpp:295
ThreadData(SmartPtr< timestep_type > spTimeStep)
Definition: limex_integrator.hpp:276
SmartPtr< grid_function_type > get_solution()
Definition: limex_integrator.hpp:302
SmartPtr< grid_function_type > m_dot
Definition: limex_integrator.hpp:317
SmartPtr< solver_type > m_solver
Definition: limex_integrator.hpp:314
void set_derivative(SmartPtr< grid_function_type > sol)
Definition: limex_integrator.hpp:305
SmartPtr< timestep_type > get_time_stepper()
Definition: limex_integrator.hpp:281
void set_error(int e)
Definition: limex_integrator.hpp:291
ThreadData()
Definition: limex_integrator.hpp:280
SmartPtr< timestep_type > m_stepper
Definition: limex_integrator.hpp:313
int m_error
Definition: limex_integrator.hpp:318
void set_solution(SmartPtr< grid_function_type > sol)
Definition: limex_integrator.hpp:299
SmartPtr< solver_type > get_solver()
Definition: limex_integrator.hpp:288
void set_solver(SmartPtr< solver_type > solver)
Definition: limex_integrator.hpp:285
SmartPtr< grid_function_type > m_sol
Definition: limex_integrator.hpp:316
SmartPtr< grid_function_type > get_derivative()
Definition: limex_integrator.hpp:308
Definition: limex_integrator.hpp:182
unsigned int m_nstages
Number of Aitken-Neville stages.
Definition: limex_integrator.hpp:210
size_t m_asymptotic_order
For PDEs, we may apply an symptotic order reduction.
Definition: limex_integrator.hpp:218
LimexTimeIntegratorConfig(unsigned int nstages)
Definition: limex_integrator.hpp:196
double m_greedyOrderIncrease
Definition: limex_integrator.hpp:215
std::string config_string() const
Definition: limex_integrator.hpp:230
double m_tol
Definition: limex_integrator.hpp:211
double m_rhoSafety
Definition: limex_integrator.hpp:212
bool m_useCachedMatrices
Definition: limex_integrator.hpp:220
unsigned int m_conservative
Definition: limex_integrator.hpp:221
size_t m_max_reductions
Definition: limex_integrator.hpp:217
LimexTimeIntegratorConfig()
Definition: limex_integrator.hpp:184
double m_sigmaReduction
Definition: limex_integrator.hpp:213
Base class for LIMEX time integrator.
Definition: limex_integrator.hpp:252
void add_stage(size_t nsteps, SmartPtr< solver_type > solver, SmartPtr< domain_discretization_type > spDD)
Definition: limex_integrator.hpp:423
INonlinearTimeIntegrator< TDomain, TAlgebra > itime_integrator_type
Definition: limex_integrator.hpp:266
GridFunction< TDomain, TAlgebra > grid_function_type
Definition: limex_integrator.hpp:259
void add_stage_ext(size_t nsteps, SmartPtr< solver_type > solver, SmartPtr< domain_discretization_type > spDD, SmartPtr< domain_discretization_type > spGamma)
Definition: limex_integrator.hpp:426
bool apply(SmartPtr< grid_function_type > u, number t1, ConstSmartPtr< grid_function_type > u0, number t0)
Integrating from t0 -> t1.
Definition: limex_integrator.hpp:767
void set_debug_for_timestepper(SmartPtr< IDebugWriter< algebra_type > > spDebugWriter)
forward debug info to time integrators
Definition: limex_integrator.hpp:326
SmartPtr< grid_function_type > m_spDtSol
Time derivative.
Definition: limex_integrator.hpp:577
SmartPtr< error_estim_type > m_spErrorEstimator
Definition: limex_integrator.hpp:560
void set_stepsize_greedy_order_factor(double sigma)
Definition: limex_integrator.hpp:367
void init_gamma()
aux: compute exponents gamma_k (for roots)
Definition: limex_integrator.hpp:479
std::vector< number > m_costA
Cost A_i (for completing stage i)
Definition: limex_integrator.hpp:567
TAlgebra algebra_type
Definition: limex_integrator.hpp:256
std::vector< number > m_gamma
gamma_i: exponent
Definition: limex_integrator.hpp:565
SmartPtr< IGridFunctionSpace< grid_function_type > > m_spBanachSpace
metric space
Definition: limex_integrator.hpp:582
void add_error_estimator(SmartPtr< error_estim_type > spErrorEstim)
add an error estimator
Definition: limex_integrator.hpp:373
base_type::solver_type solver_type
Definition: limex_integrator.hpp:261
void set_tolerance(double tol)
tolerance
Definition: limex_integrator.hpp:364
std::vector< ThreadData > m_vThreadData
vector with thread information
Definition: limex_integrator.hpp:563
void select_cost_strategy(SmartPtr< ILimexCostStrategy > cost)
Definition: limex_integrator.hpp:538
ISubDiagErrorEst< vector_type > error_estim_type
Definition: limex_integrator.hpp:268
SmartPtr< ILimexCostStrategy > m_spCostStrategy
Definition: limex_integrator.hpp:579
size_t find_optimal_solution(const std::vector< number > &eps, size_t ntest, size_t &qpred)
Definition: limex_integrator.hpp:733
std::vector< size_t > m_num_reductions
history of reductions
Definition: limex_integrator.hpp:573
int m_limex_step
Current counter.
Definition: limex_integrator.hpp:585
std::vector< number > m_monitor
Convergence monitor \alpha.
Definition: limex_integrator.hpp:568
AitkenNevilleTimex< vector_type > timex_type
Definition: limex_integrator.hpp:265
SimpleTimeIntegrator< TDomain, TAlgebra > time_integrator_type
Definition: limex_integrator.hpp:267
std::vector< SmartPtr< ThreadData > > thread_vector_type
Definition: limex_integrator.hpp:321
number get_workload(size_t i)
Definition: limex_integrator.hpp:468
void set_time_derivative(SmartPtr< grid_function_type > udot)
setter for time derivative info (optional for setting $\Gamma$)
Definition: limex_integrator.hpp:526
void add_stage(size_t i, size_t nsteps, SmartPtr< domain_discretization_type > spDD, SmartPtr< solver_type > solver)
! TODO: remove this function!
Definition: limex_integrator.hpp:430
std::vector< number > m_consistency_error
Consistency error.
Definition: limex_integrator.hpp:575
void dispose_integrator_threads()
Dispose integrator threads (w/ solutions)
Definition: limex_integrator.hpp:607
void disable_matrix_cache()
Select approximate Newton (default)
Definition: limex_integrator.hpp:536
void set_max_reductions(size_t nred)
Definition: limex_integrator.hpp:369
IDomainDiscretization< algebra_type > domain_discretization_type
Definition: limex_integrator.hpp:263
algebra_type::matrix_type matrix_type
Definition: limex_integrator.hpp:257
std::vector< size_t > m_vSteps
generating sequence for extrapolation
Definition: limex_integrator.hpp:562
std::vector< number > m_lambda
Definition: limex_integrator.hpp:571
void set_space(SmartPtr< IGridFunctionSpace< grid_function_type > > spSpace)
set banach space (e.g. for computing consistency error)
Definition: limex_integrator.hpp:543
bool has_time_derivative()
status for time derivative info (optional for setting $\Gamma$)
Definition: limex_integrator.hpp:532
SmartPtr< timestep_type > get_time_stepper(size_t i)
Definition: limex_integrator.hpp:437
LimexTimeIntegrator(int nstages)
Definition: limex_integrator.hpp:342
void update_integrator_threads(ConstSmartPtr< grid_function_type > ucommon, number t)
Override thread-wise solutions with common solution.
Definition: limex_integrator.hpp:721
LinearImplicitEuler< algebra_type > timestep_type
Definition: limex_integrator.hpp:264
void enable_matrix_cache()
Select classic LIMEX.
Definition: limex_integrator.hpp:535
void interrupt()
interrupt execution of apply() by external call via observer
Definition: limex_integrator.hpp:550
void set_stepsize_safety_factor(double rho)
Definition: limex_integrator.hpp:365
number get_cost(size_t i)
Definition: limex_integrator.hpp:466
void update_monitor()
convergence monitor
Definition: limex_integrator.hpp:496
number & monitor(size_t k, size_t q)
Definition: limex_integrator.hpp:472
std::string config_string() const
Definition: limex_integrator.hpp:555
void set_conservative(bool c)
Definition: limex_integrator.hpp:552
number get_gamma(size_t i)
Definition: limex_integrator.hpp:467
algebra_type::vector_type vector_type
Definition: limex_integrator.hpp:258
void init_integrator_threads(ConstSmartPtr< grid_function_type > u)
Initialize integrator threads (w/ solutions)
Definition: limex_integrator.hpp:593
void update_cost()
Updating workloads A_i for computing T_ii.
Definition: limex_integrator.hpp:489
void add_stage_base(size_t nsteps, SmartPtr< solver_type > solver, SmartPtr< domain_discretization_type > spDD, SmartPtr< domain_discretization_type > spGamma=SPNULL)
add a new stage (at end of list)
Definition: limex_integrator.hpp:377
bool m_bInterrupt
Definition: limex_integrator.hpp:584
SmartPtr< grid_function_type > get_time_derivative()
getter for time derivative info (optional for setting $\Gamma$)
Definition: limex_integrator.hpp:529
INonlinearTimeIntegrator< TDomain, TAlgebra > base_type
Definition: limex_integrator.hpp:260
std::vector< number > m_workload
Definition: limex_integrator.hpp:570
int apply_integrator_threads(number dtcurr, ConstSmartPtr< grid_function_type > u0, number t0, size_t nstages)
(Tentatively) apply integrators
Definition: limex_integrator.hpp:636
void join_integrator_threads()
e.g. wait for all threads to complete
Definition: limex_integrator.hpp:708
void set_asymptotic_order(size_t q)
Definition: limex_integrator.hpp:370
void set_stepsize_reduction_factor(double sigma)
Definition: limex_integrator.hpp:366
Definition: linear_implicit_timestep.h:74
Integrate (a non-linear problem) over a given time interval.
Definition: simple_integrator.hpp:11
number get_consistency_error() const
Definition: simple_integrator.hpp:53
void set_banach_space(SmartPtr< IGridFunctionSpace< grid_function_type > > spSpace)
Definition: simple_integrator.hpp:56
void set_derivative(SmartPtr< grid_function_type > udot)
Definition: simple_integrator.hpp:47
bool apply(SmartPtr< grid_function_type > u1, number t1, ConstSmartPtr< grid_function_type > u0, number t0)
Definition: simple_integrator.hpp:38
const std::string & get_file(size_t i) const
unsigned long get_line(size_t i) const
const std::string & get_msg() const
size_t num_msg() const
ParallelMatrix< SparseMatrix< double > > matrix_type
ParallelVector< Vector< double > > vector_type
StringTable s
const NullSmartPtr SPNULL
#define UG_ASSERT(expr, msg)
#define UG_DLOG(__debugID__, level, msg)
#define UG_LOG(msg)
#define UG_LOGN(msg)
#define UG_COND_THROW(cond, msg)
double number
static void MyPrintError(UGError &err)
Definition: limex_integrator.hpp:99
DebugID LIB_LIMEX("LIB_LIMEX")
Definition: limex_tools.h:51
#define PROFILE_FUNC_GROUP(groups)
SmartPtr< T, FreePolicy > make_sp(T *inst)
function ProblemDisc new(problemDesc, dom)