Heidelberg Educational Numerics Library  Version 0.24 (from 9 September 2011)
ode.hh
Go to the documentation of this file.
1 // -*- tab-width: 4; indent-tabs-mode: nil -*-
2 #ifndef HDNUM_ODE_HH
3 #define HDNUM_ODE_HH
4 
5 #include<vector>
6 #include "newton.hh"
7 
12 namespace hdnum {
13 
22  template<class M>
23  class EE
24  {
25  public:
27  typedef typename M::size_type size_type;
28 
30  typedef typename M::time_type time_type;
31 
33  typedef typename M::number_type number_type;
34 
36  EE (const M& model_)
37  : model(model_), u(model.size()), f(model.size())
38  {
39  model.initialize(t,u);
40  dt = 0.1;
41  }
42 
44  void set_dt (time_type dt_)
45  {
46  dt = dt_;
47  }
48 
50  void step ()
51  {
52  model.f(t,u,f); // evaluate model
53  u.update(dt,f); // advance state
54  t += dt; // advance time
55  }
56 
58  void set_state (time_type t_, const Vector<number_type>& u_)
59  {
60  t = t_;
61  u = u_;
62  }
63 
66  {
67  return u;
68  }
69 
71  time_type get_time () const
72  {
73  return t;
74  }
75 
77  time_type get_dt () const
78  {
79  return dt;
80  }
81 
83  size_type get_order () const
84  {
85  return 1;
86  }
87 
88  private:
89  const M& model;
90  time_type t, dt;
93  };
94 
103  template<class M>
105  {
106  public:
108  typedef typename M::size_type size_type;
109 
111  typedef typename M::time_type time_type;
112 
114  typedef typename M::number_type number_type;
115 
117  ModifiedEuler (const M& model_)
118  : model(model_), u(model.size()), w(model.size()), k1(model.size()), k2(model.size())
119  {
120  c2 = 0.5;
121  a21 = 0.5;
122  b2 = 1.0;
123  model.initialize(t,u);
124  dt = 0.1;
125  }
126 
128  void set_dt (time_type dt_)
129  {
130  dt = dt_;
131  }
132 
134  void step ()
135  {
136  // stage 1
137  model.f(t,u,k1);
138 
139  // stage 2
140  w = u;
141  w.update(dt*a21,k1);
142  model.f(t+c2*dt,w,k2);
143 
144  // final
145  u.update(dt*b2,k2);
146  t += dt;
147  }
148 
150  void set_state (time_type t_, const Vector<number_type>& u_)
151  {
152  t = t_;
153  u = u_;
154  }
155 
158  {
159  return u;
160  }
161 
163  time_type get_time () const
164  {
165  return t;
166  }
167 
169  time_type get_dt () const
170  {
171  return dt;
172  }
173 
175  size_type get_order () const
176  {
177  return 2;
178  }
179 
180  private:
181  const M& model;
182  time_type t, dt;
183  time_type c2,a21,b2;
185  Vector<number_type> k1,k2;
186  };
187 
188 
197  template<class M>
198  class Heun2
199  {
200  public:
202  typedef typename M::size_type size_type;
203 
205  typedef typename M::time_type time_type;
206 
208  typedef typename M::number_type number_type;
209 
211  Heun2 (const M& model_)
212  : model(model_), u(model.size()), w(model.size()), k1(model.size()), k2(model.size())
213  {
214  c2 = 1.0;
215  a21 = 1.0;
216  b1 = 0.5;
217  b2 = 0.5;
218  model.initialize(t,u);
219  dt = 0.1;
220  }
221 
223  void set_dt (time_type dt_)
224  {
225  dt = dt_;
226  }
227 
229  void step ()
230  {
231  // stage 1
232  model.f(t,u,k1);
233 
234  // stage 2
235  w = u;
236  w.update(dt*a21,k1);
237  model.f(t+c2*dt,w,k2);
238 
239  // final
240  u.update(dt*b1,k1);
241  u.update(dt*b2,k2);
242  t += dt;
243  }
244 
246  void set_state (time_type t_, const Vector<number_type>& u_)
247  {
248  t = t_;
249  u = u_;
250  }
251 
254  {
255  return u;
256  }
257 
259  time_type get_time () const
260  {
261  return t;
262  }
263 
265  time_type get_dt () const
266  {
267  return dt;
268  }
269 
271  size_type get_order () const
272  {
273  return 2;
274  }
275 
276  private:
277  const M& model;
278  time_type t, dt;
279  time_type c2,a21,b1,b2;
281  Vector<number_type> k1,k2;
282  };
283 
284 
293  template<class M>
294  class Heun3
295  {
296  public:
298  typedef typename M::size_type size_type;
299 
301  typedef typename M::time_type time_type;
302 
304  typedef typename M::number_type number_type;
305 
307  Heun3 (const M& model_)
308  : model(model_), u(model.size()), w(model.size()), k1(model.size()),
309  k2(model.size()), k3(model.size())
310  {
311  c2 = time_type(1.0)/time_type(3.0);
312  c3 = time_type(2.0)/time_type(3.0);
313  a21 = time_type(1.0)/time_type(3.0);
314  a32 = time_type(2.0)/time_type(3.0);
315  b1 = 0.25;
316  b2 = 0.0;
317  b3 = 0.75;
318  model.initialize(t,u);
319  dt = 0.1;
320  }
321 
323  void set_dt (time_type dt_)
324  {
325  dt = dt_;
326  }
327 
329  void step ()
330  {
331  // stage 1
332  model.f(t,u,k1);
333 
334  // stage 2
335  w = u;
336  w.update(dt*a21,k1);
337  model.f(t+c2*dt,w,k2);
338 
339  // stage 3
340  w = u;
341  w.update(dt*a32,k2);
342  model.f(t+c3*dt,w,k3);
343 
344  // final
345  u.update(dt*b1,k1);
346  u.update(dt*b3,k3);
347  t += dt;
348  }
349 
351  void set_state (time_type t_, const Vector<number_type>& u_)
352  {
353  t = t_;
354  u = u_;
355  }
356 
359  {
360  return u;
361  }
362 
364  time_type get_time () const
365  {
366  return t;
367  }
368 
370  time_type get_dt () const
371  {
372  return dt;
373  }
374 
376  size_type get_order () const
377  {
378  return 3;
379  }
380 
381  private:
382  const M& model;
383  time_type t, dt;
384  time_type c2,c3,a21,a31,a32,b1,b2,b3;
386  Vector<number_type> k1,k2,k3;
387  };
388 
397  template<class M>
398  class Kutta3
399  {
400  public:
402  typedef typename M::size_type size_type;
403 
405  typedef typename M::time_type time_type;
406 
408  typedef typename M::number_type number_type;
409 
411  Kutta3 (const M& model_)
412  : model(model_), u(model.size()), w(model.size()), k1(model.size()),
413  k2(model.size()), k3(model.size())
414  {
415  c2 = 0.5;
416  c3 = 1.0;
417  a21 = 0.5;
418  a31 = -1.0;
419  a32 = 2.0;
420  b1 = time_type(1.0)/time_type(6.0);
421  b2 = time_type(4.0)/time_type(6.0);
422  b3 = time_type(1.0)/time_type(6.0);
423  model.initialize(t,u);
424  dt = 0.1;
425  }
426 
428  void set_dt (time_type dt_)
429  {
430  dt = dt_;
431  }
432 
434  void step ()
435  {
436  // stage 1
437  model.f(t,u,k1);
438 
439  // stage 2
440  w = u;
441  w.update(dt*a21,k1);
442  model.f(t+c2*dt,w,k2);
443 
444  // stage 3
445  w = u;
446  w.update(dt*a31,k1);
447  w.update(dt*a32,k2);
448  model.f(t+c3*dt,w,k3);
449 
450  // final
451  u.update(dt*b1,k1);
452  u.update(dt*b2,k2);
453  u.update(dt*b3,k3);
454  t += dt;
455  }
456 
458  void set_state (time_type t_, const Vector<number_type>& u_)
459  {
460  t = t_;
461  u = u_;
462  }
463 
466  {
467  return u;
468  }
469 
471  time_type get_time () const
472  {
473  return t;
474  }
475 
477  time_type get_dt () const
478  {
479  return dt;
480  }
481 
483  size_type get_order () const
484  {
485  return 3;
486  }
487 
488  private:
489  const M& model;
490  time_type t, dt;
491  time_type c2,c3,a21,a31,a32,b1,b2,b3;
493  Vector<number_type> k1,k2,k3;
494  };
495 
504  template<class M>
506  {
507  public:
509  typedef typename M::size_type size_type;
510 
512  typedef typename M::time_type time_type;
513 
515  typedef typename M::number_type number_type;
516 
518  RungeKutta4 (const M& model_)
519  : model(model_), u(model.size()), w(model.size()), k1(model.size()),
520  k2(model.size()), k3(model.size()), k4(model.size())
521  {
522  c2 = 0.5;
523  c3 = 0.5;
524  c4 = 1.0;
525  a21 = 0.5;
526  a32 = 0.5;
527  a43 = 1.0;
528  b1 = time_type(1.0)/time_type(6.0);
529  b2 = time_type(2.0)/time_type(6.0);
530  b3 = time_type(2.0)/time_type(6.0);
531  b4 = time_type(1.0)/time_type(6.0);
532  model.initialize(t,u);
533  dt = 0.1;
534  }
535 
537  void set_dt (time_type dt_)
538  {
539  dt = dt_;
540  }
541 
543  void step ()
544  {
545  // stage 1
546  model.f(t,u,k1);
547 
548  // stage 2
549  w = u;
550  w.update(dt*a21,k1);
551  model.f(t+c2*dt,w,k2);
552 
553  // stage 3
554  w = u;
555  w.update(dt*a32,k2);
556  model.f(t+c3*dt,w,k3);
557 
558  // stage 4
559  w = u;
560  w.update(dt*a43,k3);
561  model.f(t+c4*dt,w,k4);
562 
563  // final
564  u.update(dt*b1,k1);
565  u.update(dt*b2,k2);
566  u.update(dt*b3,k3);
567  u.update(dt*b4,k4);
568  t += dt;
569  }
570 
572  void set_state (time_type t_, const Vector<number_type>& u_)
573  {
574  t = t_;
575  u = u_;
576  }
577 
580  {
581  return u;
582  }
583 
585  time_type get_time () const
586  {
587  return t;
588  }
589 
591  time_type get_dt () const
592  {
593  return dt;
594  }
595 
597  size_type get_order () const
598  {
599  return 4;
600  }
601 
602  private:
603  const M& model;
604  time_type t, dt;
605  time_type c2,c3,c4,a21,a32,a43,b1,b2,b3,b4;
607  Vector<number_type> k1,k2,k3,k4;
608  };
609 
614  template<class M>
615  class RKF45
616  {
617  public:
619  typedef typename M::size_type size_type;
620 
622  typedef typename M::time_type time_type;
623 
625  typedef typename M::number_type number_type;
626 
628  RKF45 (const M& model_)
629  : model(model_), u(model.size()), w(model.size()), ww(model.size()), k1(model.size()),
630  k2(model.size()), k3(model.size()), k4(model.size()), k5(model.size()), k6(model.size()),
631  steps(0), rejected(0)
632  {
633  TOL = time_type(0.0001);
634  rho = time_type(0.8);
635  alpha = time_type(0.25);
636  beta = time_type(4.0);
637  dt_min = 1E-12;
638 
639  c2 = time_type(1.0)/time_type(4.0);
640  c3 = time_type(3.0)/time_type(8.0);
641  c4 = time_type(12.0)/time_type(13.0);
642  c5 = time_type(1.0);
643  c6 = time_type(1.0)/time_type(2.0);
644 
645  a21 = time_type(1.0)/time_type(4.0);
646 
647  a31 = time_type(3.0)/time_type(32.0);
648  a32 = time_type(9.0)/time_type(32.0);
649 
650  a41 = time_type(1932.0)/time_type(2197.0);
651  a42 = time_type(-7200.0)/time_type(2197.0);
652  a43 = time_type(7296.0)/time_type(2197.0);
653 
654  a51 = time_type(439.0)/time_type(216.0);
655  a52 = time_type(-8.0);
656  a53 = time_type(3680.0)/time_type(513.0);
657  a54 = time_type(-845.0)/time_type(4104.0);
658 
659  a61 = time_type(-8.0)/time_type(27.0);
660  a62 = time_type(2.0);
661  a63 = time_type(-3544.0)/time_type(2565.0);
662  a64 = time_type(1859.0)/time_type(4104.0);
663  a65 = time_type(-11.0)/time_type(40.0);
664 
665  b1 = time_type(25.0)/time_type(216.0);
666  b2 = time_type(0.0);
667  b3 = time_type(1408.0)/time_type(2565.0);
668  b4 = time_type(2197.0)/time_type(4104.0);
669  b5 = time_type(-1.0)/time_type(5.0);
670 
671  bb1 = time_type(16.0)/time_type(135.0);
672  bb2 = time_type(0.0);
673  bb3 = time_type(6656.0)/time_type(12825.0);
674  bb4 = time_type(28561.0)/time_type(56430.0);
675  bb5 = time_type(-9.0)/time_type(50.0);
676  bb6 = time_type(2.0)/time_type(55.0);
677 
678  model.initialize(t,u);
679  dt = 0.1;
680  }
681 
683  void set_dt (time_type dt_)
684  {
685  dt = dt_;
686  }
687 
689  void set_TOL (time_type TOL_)
690  {
691  TOL = TOL_;
692  }
693 
695  void step ()
696  {
697  steps++;
698 
699  // stage 1
700  model.f(t,u,k1);
701 
702  // stage 2
703  w = u;
704  w.update(dt*a21,k1);
705  model.f(t+c2*dt,w,k2);
706 
707  // stage 3
708  w = u;
709  w.update(dt*a31,k1);
710  w.update(dt*a32,k2);
711  model.f(t+c3*dt,w,k3);
712 
713  // stage 4
714  w = u;
715  w.update(dt*a41,k1);
716  w.update(dt*a42,k2);
717  w.update(dt*a43,k3);
718  model.f(t+c4*dt,w,k4);
719 
720  // stage 5
721  w = u;
722  w.update(dt*a51,k1);
723  w.update(dt*a52,k2);
724  w.update(dt*a53,k3);
725  w.update(dt*a54,k4);
726  model.f(t+c5*dt,w,k5);
727 
728  // stage 6
729  w = u;
730  w.update(dt*a61,k1);
731  w.update(dt*a62,k2);
732  w.update(dt*a63,k3);
733  w.update(dt*a64,k4);
734  w.update(dt*a65,k5);
735  model.f(t+c6*dt,w,k6);
736 
737  // compute order 4 approximation
738  w = u;
739  w.update(dt*b1,k1);
740  w.update(dt*b2,k2);
741  w.update(dt*b3,k3);
742  w.update(dt*b4,k4);
743  w.update(dt*b5,k5);
744 
745  // compute order 5 approximation
746  ww = u;
747  ww.update(dt*bb1,k1);
748  ww.update(dt*bb2,k2);
749  ww.update(dt*bb3,k3);
750  ww.update(dt*bb4,k4);
751  ww.update(dt*bb5,k5);
752  ww.update(dt*bb6,k6);
753 
754  // estimate local error
755  w -= ww;
756  time_type error(norm(w));
757  time_type dt_opt(dt*pow(rho*TOL/error,0.2));
758  dt_opt = std::min(beta*dt,std::max(alpha*dt,dt_opt));
759  //std::cout << "est. error=" << error << " dt_opt=" << dt_opt << std::endl;
760 
761  if (error<=TOL)
762  {
763  t += dt;
764  u = ww;
765  dt = dt_opt;
766  }
767  else
768  {
769  rejected++;
770  dt = dt_opt;
771  if (dt>dt_min) step();
772  }
773  }
774 
777  {
778  return u;
779  }
780 
782  time_type get_time () const
783  {
784  return t;
785  }
786 
788  time_type get_dt () const
789  {
790  return dt;
791  }
792 
794  size_type get_order () const
795  {
796  return 5;
797  }
798 
800  void get_info () const
801  {
802  std::cout << "RE: steps=" << steps << " rejected=" << rejected << std::endl;
803  }
804 
805  private:
806  const M& model;
807  time_type t, dt;
808  time_type TOL,rho,alpha,beta,dt_min;
809  time_type c2,c3,c4,c5,c6;
810  time_type a21,a31,a32,a41,a42,a43,a51,a52,a53,a54,a61,a62,a63,a64,a65;
811  time_type b1,b2,b3,b4,b5; // 4th order
812  time_type bb1,bb2,bb3,bb4,bb5,bb6; // 5th order
813  Vector<number_type> u,w,ww;
814  Vector<number_type> k1,k2,k3,k4,k5,k6;
815  mutable size_type steps, rejected;
816  };
817 
818 
824  template<class M, class S>
825  class RE
826  {
827  public:
829  typedef typename M::size_type size_type;
830 
832  typedef typename M::time_type time_type;
833 
835  typedef typename M::number_type number_type;
836 
838  RE (const M& model_, S& solver_)
839  : model(model_), solver(solver_), u(model.size()),
840  wlow(model.size()), whigh(model.size()), ww(model.size()),
841  steps(0), rejected(0)
842  {
843  model.initialize(t,u); // initialize state
844  dt = 0.1; // set initial time step
845  two_power_m = 1.0;
846  for (size_type i=0; i<solver.get_order(); i++)
847  two_power_m *= 2.0;
848  TOL = time_type(0.0001);
849  rho = time_type(0.8);
850  alpha = time_type(0.25);
851  beta = time_type(4.0);
852  dt_min = 1E-12;
853  }
854 
856  void set_dt (time_type dt_)
857  {
858  dt = dt_;
859  }
860 
862  void set_TOL (time_type TOL_)
863  {
864  TOL = TOL_;
865  }
866 
868  void step ()
869  {
870  // count steps done
871  steps++;
872 
873  // do 1 step with 2*dt
874  time_type H(2.0*dt);
875  solver.set_state(t,u);
876  solver.set_dt(H);
877  solver.step();
878  wlow = solver.get_state();
879 
880  // do 2 steps with dt
881  solver.set_state(t,u);
882  solver.set_dt(dt);
883  solver.step();
884  solver.step();
885  whigh = solver.get_state();
886 
887  // estimate local error
888  ww = wlow;
889  ww -= whigh;
890  time_type error(norm(ww)/(pow(H,1.0+solver.get_order())*(1.0-1.0/two_power_m)));
891  time_type dt_opt(pow(rho*TOL/error,1.0/((time_type)solver.get_order())));
892  dt_opt = std::min(beta*dt,std::max(alpha*dt,dt_opt));
893  //std::cout << "est. error=" << error << " dt_opt=" << dt_opt << std::endl;
894 
895  if (dt<=dt_opt)
896  {
897  t += H;
898  u = whigh;
899  u *= two_power_m;
900  u -= wlow;
901  u /= two_power_m-1.0;
902  dt = dt_opt;
903  }
904  else
905  {
906  rejected++;
907  dt = dt_opt;
908  if (dt>dt_min) step();
909  }
910  }
911 
914  {
915  return u;
916  }
917 
919  time_type get_time () const
920  {
921  return t;
922  }
923 
925  time_type get_dt () const
926  {
927  return dt;
928  }
929 
931  size_type get_order () const
932  {
933  return solver.get_order()+1;
934  }
935 
937  void get_info () const
938  {
939  std::cout << "RE: steps=" << steps << " rejected=" << rejected << std::endl;
940  }
941 
942  private:
943  const M& model;
944  S& solver;
945  time_type t, dt;
946  time_type two_power_m;
947  Vector<number_type> u,wlow,whigh,ww;
948  time_type TOL,rho,alpha,beta,dt_min;
949  mutable size_type steps, rejected;
950  };
951 
952 
962  template<class M, class S>
963  class IE
964  {
966  // h_n f(t_n, y_n) - y_n + y_{n-1} = 0
967  class NonlinearProblem
968  {
969  public:
971  typedef typename M::size_type size_type;
972 
974  typedef typename M::number_type number_type;
975 
977  NonlinearProblem (const M& model_, const Vector<number_type>& yold_,
978  typename M::time_type tnew_, typename M::time_type dt_)
979  : model(model_), yold(yold_), tnew(tnew_), dt(dt_)
980  {}
981 
983  std::size_t size () const
984  {
985  return model.size();
986  }
987 
989  void F (const Vector<number_type>& x, Vector<number_type>& result) const
990  {
991  model.f(tnew,x,result);
992  result *= dt;
993  result -= x;
994  result += yold;
995  }
996 
998  void F_x (const Vector<number_type>& x, DenseMatrix<number_type>& result) const
999  {
1000  model.f_x(tnew,x,result);
1001  result *= dt;
1002  for (size_type i=0; i<model.size(); i++) result[i][i] -= number_type(1.0);
1003  }
1004 
1005  void set_tnew_dt (typename M::time_type tnew_, typename M::time_type dt_)
1006  {
1007  tnew = tnew_;
1008  dt = dt_;
1009  }
1010 
1011  private:
1012  const M& model;
1013  const Vector<number_type>& yold;
1014  typename M::time_type tnew;
1015  typename M::time_type dt;
1016  };
1017 
1018  public:
1020  typedef typename M::size_type size_type;
1021 
1023  typedef typename M::time_type time_type;
1024 
1026  typedef typename M::number_type number_type;
1027 
1029  IE (const M& model_, const S& newton_)
1030  : verbosity(0), model(model_), newton(newton_), u(model.size()), unew(model.size())
1031  {
1032  model.initialize(t,u);
1033  dt = dtmax = 0.1;
1034  }
1035 
1037  void set_dt (time_type dt_)
1038  {
1039  dt = dtmax = dt_;
1040  }
1041 
1043  void set_verbosity (size_type verbosity_)
1044  {
1045  verbosity = verbosity_;
1046  }
1047 
1049  void step ()
1050  {
1051  if (verbosity>=2)
1052  std::cout << "IE: step" << " t=" << t << " dt=" << dt << std::endl;
1053  NonlinearProblem nlp(model,u,t+dt,dt);
1054  bool reduced = false;
1055  error = false;
1056  while (1)
1057  {
1058  unew = u;
1059  newton.solve(nlp,unew);
1060  if (newton.has_converged())
1061  {
1062  u = unew;
1063  t += dt;
1064  if (!reduced && dt<dtmax-1e-13)
1065  {
1066  dt = std::min(2.0*dt,dtmax);
1067  if (verbosity>0)
1068  std::cout << "IE: increasing time step to " << dt << std::endl;
1069  }
1070  return;
1071  }
1072  else
1073  {
1074  if (dt<1e-12)
1075  {
1076  HDNUM_ERROR("time step too small in implicit Euler");
1077  error = true;
1078  break;
1079  }
1080  dt *= 0.5;
1081  reduced = true;
1082  nlp.set_tnew_dt(t+dt,dt);
1083  if (verbosity>0) std::cout << "IE: reducing time step to " << dt << std::endl;
1084  }
1085  }
1086  }
1087 
1089  bool get_error () const
1090  {
1091  return error;
1092  }
1093 
1095  void set_state (time_type t_, const Vector<number_type>& u_)
1096  {
1097  t = t_;
1098  u = u_;
1099  }
1100 
1103  {
1104  return u;
1105  }
1106 
1108  time_type get_time () const
1109  {
1110  return t;
1111  }
1112 
1114  time_type get_dt () const
1115  {
1116  return dt;
1117  }
1118 
1120  size_type get_order () const
1121  {
1122  return 1;
1123  }
1124 
1126  void get_info () const
1127  {
1128  }
1129 
1130  private:
1131  size_type verbosity;
1132  const M& model;
1133  const S& newton;
1134  time_type t, dt, dtmax;
1135  number_type reduction;
1136  size_type linesearchsteps;
1138  Vector<number_type> unew;
1139  mutable bool error;
1140  };
1141 
1152  template<class M, class S>
1153  class DIRK
1154  {
1155  public:
1156 
1158  typedef typename M::size_type size_type;
1159 
1161  typedef typename M::time_type time_type;
1162 
1164  typedef typename M::number_type number_type;
1165 
1168 
1169  private:
1170 
1173  static ButcherTableau initTableau(const std::string method)
1174  {
1175  if(method.find("Implicit Euler") != std::string::npos){
1176  ButcherTableau butcher(2,2,0.0);
1177  butcher[1][1] = 1;
1178  butcher[0][1] = 1;
1179  butcher[0][0] = 1;
1180 
1181  return butcher;
1182  }
1183  else if(method.find("Alexander") != std::string::npos){
1184  ButcherTableau butcher(3,3,0.0);
1185  const number_type alpha = 1. - sqrt(2.)/2.;
1186  butcher[0][0] = alpha;
1187  butcher[0][1] = alpha;
1188 
1189  butcher[1][0] = 1.;
1190  butcher[1][1] = 1. - alpha;
1191  butcher[1][2] = alpha;
1192 
1193  butcher[2][1] = 1. - alpha;
1194  butcher[2][2] = alpha;
1195 
1196  return butcher;
1197  }
1198  else if(method.find("Crouzieux") != std::string::npos){
1199  ButcherTableau butcher(3,3,0.0);
1200  const number_type beta = 1./2./sqrt(3);
1201  butcher[0][0] = 0.5 + beta;
1202  butcher[0][1] = 0.5 + beta;
1203 
1204  butcher[1][0] = 0.5 - beta;
1205  butcher[1][1] = -1. / sqrt(3);
1206  butcher[1][2] = 0.5 + beta;
1207 
1208  butcher[2][1] = 0.5;
1209  butcher[2][2] = 0.5;
1210 
1211  return butcher;
1212  }
1213  else if(method.find("Midpoint Rule") != std::string::npos){
1214  ButcherTableau butcher(2,2,0.0);
1215  butcher[0][0] = 0.5;
1216  butcher[0][1] = 0.5;
1217  butcher[1][1] = 1;
1218 
1219  return butcher;
1220  }
1221  else if(method.find("Fractional Step Theta") != std::string::npos){
1222  ButcherTableau butcher(5,5,0.0);
1223  const number_type theta = 1 - sqrt(2.)/2.;
1224  const number_type alpha = 2. - sqrt(2.);
1225  const number_type beta = 1. - alpha;
1226  butcher[1][0] = theta;
1227  butcher[1][1] = beta * theta;
1228  butcher[1][2] = alpha * theta;
1229 
1230  butcher[2][0] = 1.-theta;
1231  butcher[2][1] = beta * theta;
1232  butcher[2][2] = alpha * (1.-theta);
1233  butcher[2][3] = alpha * theta;
1234 
1235  butcher[3][0] = 1.;
1236  butcher[3][1] = beta * theta;
1237  butcher[3][2] = alpha * (1.-theta);
1238  butcher[3][3] = (alpha + beta) * theta;
1239  butcher[3][4] = alpha * theta;
1240 
1241  butcher[4][1] = beta * theta;
1242  butcher[4][2] = alpha * (1.-theta);
1243  butcher[4][3] = (alpha + beta) * theta;
1244  butcher[4][4] = alpha * theta;
1245 
1246  return butcher;
1247  }
1248  else{
1249  HDNUM_ERROR("Order not available for Runge Kutta solver.");
1250  }
1251  }
1252 
1253  static int initOrder(const std::string method)
1254  {
1255  if(method.find("Implicit Euler") != std::string::npos){
1256  return 1;
1257  }
1258  else if(method.find("Alexander") != std::string::npos){
1259  return 2;
1260  }
1261  else if(method.find("Crouzieux") != std::string::npos){
1262  return 3;
1263  }
1264  else if(method.find("Midpoint Rule") != std::string::npos){
1265  return 2;
1266  }
1267  else if(method.find("Fractional Step Theta") != std::string::npos){
1268  return 2;
1269  }
1270  else{
1271  HDNUM_ERROR("Order not available for Runge Kutta solver.");
1272  }
1273  }
1274 
1275 
1277  // h_n f(t_n, y_n) - y_n + y_{n-1} = 0
1278  class NonlinearProblem
1279  {
1280  public:
1282  typedef typename M::size_type size_type;
1283 
1285  typedef typename M::number_type number_type;
1286 
1288  NonlinearProblem (const M& model_, const Vector<number_type>& yold_,
1289  typename M::time_type told_, typename M::time_type dt_,
1290  const ButcherTableau & butcher_, const int rk_step_,
1291  const std::vector< Vector<number_type> > & k_)
1292  : model(model_), yold(yold_), told(told_),
1293  dt(dt_), butcher(butcher_), rk_step(rk_step_), k_old(model.size(),0)
1294  {
1295  for(int i=0; i<rk_step; ++i)
1296  k_old.update(butcher[rk_step][1+i] * dt, k_[i]);
1297  }
1298 
1300  std::size_t size () const
1301  {
1302  return model.size();
1303  }
1304 
1306  void F (const Vector<number_type>& x, Vector<number_type>& result) const
1307  {
1308  result = k_old;
1309 
1310  Vector<number_type> current_z(x);
1311  current_z.update(1.,yold);
1312 
1313  const number_type tnew = told + butcher[rk_step][0] * dt;
1314 
1315  Vector<number_type> current_k(model.size(),0.);
1316  model.f(tnew,current_z,current_k);
1317  result.update(butcher[rk_step][rk_step+1] * dt, current_k);
1318 
1319  result.update(-1.,x);
1320  }
1321 
1323  void F_x (const Vector<number_type>& x, DenseMatrix<number_type>& result) const
1324  {
1325  const number_type tnew = told + butcher[rk_step][0] * dt;
1326 
1327  Vector<number_type> current_z(x);
1328  current_z.update(1.,yold);
1329 
1330  model.f_x(tnew,current_z,result);
1331 
1332  result *= dt * butcher[rk_step][rk_step+1];
1333 
1334  for (size_type i=0; i<model.size(); i++) result[i][i] -= number_type(1.0);
1335  }
1336 
1337  void set_told_dt (typename M::time_type told_, typename M::time_type dt_)
1338  {
1339  told = told_;
1340  dt = dt_;
1341  }
1342 
1343  private:
1344  const M& model;
1345  const Vector<number_type>& yold;
1346  typename M::time_type told;
1347  typename M::time_type dt;
1348  const ButcherTableau & butcher;
1349  const int rk_step;
1350  Vector<number_type> k_old;
1351  };
1352 
1353  public:
1354 
1357  DIRK (const M& model_, const S& newton_, const ButcherTableau & butcher_, const int order_)
1358  : verbosity(0), butcher(butcher_), model(model_), newton(newton_),
1359  u(model.size()), order(order_)
1360  {
1361  model.initialize(t,u);
1362  dt = dtmax = 0.1;
1363  }
1364 
1367  DIRK (const M& model_, const S& newton_, const std::string method)
1368  : verbosity(0), butcher(initTableau(method)), model(model_), newton(newton_), u(model.size()),
1369  order(initOrder(method))
1370  {
1371  model.initialize(t,u);
1372  dt = dtmax = 0.1;
1373  }
1374 
1375 
1377  void set_dt (time_type dt_)
1378  {
1379  dt = dtmax = dt_;
1380  }
1381 
1383  void set_verbosity (size_type verbosity_)
1384  {
1385  verbosity = verbosity_;
1386  }
1387 
1389  void step ()
1390  {
1391 
1392  const size_type R = butcher.colsize()-1;
1393 
1394  bool reduced = false;
1395  error = false;
1396  if(verbosity>=2)
1397  std::cout << "DIRK: step to" << " t+dt=" << t+dt << " dt=" << dt << std::endl;
1398 
1399  while (1)
1400  {
1401  bool converged = true;
1402 
1403  // Perform R Runge-Kutta steps
1404  std::vector< Vector<number_type> > k;
1405  for(size_type i=0; i<R; ++i) {
1406  if (verbosity>=2)
1407  std::cout << "DIRK: step nr "<< i << std::endl;
1408 
1409  Vector<number_type> current_z(model.size(),0.0);
1410 
1411  // Set starting value of k_i
1412  // model.f(t,u,current_k);
1413 
1414  // Solve nonlinear problem
1415  NonlinearProblem nlp(model,u,t,dt,butcher,i,k);
1416 
1417  newton.solve(nlp,current_z);
1418 
1419  converged = converged && newton.has_converged();
1420  if(!converged)
1421  break;
1422 
1423  current_z.update(1., u);
1424  const number_type t_i = t + butcher[i][0] * dt;
1425  Vector<number_type>current_k(model.size(),0.);
1426  model.f(t_i,current_z,current_k);
1427 
1428  k.push_back( current_k );
1429  }
1430 
1431  if (converged)
1432  {
1433  if(verbosity >= 2)
1434  std::cout << "DIRK finished"<< std::endl;
1435 
1436  // Update to new solution
1437  for(size_type i=0; i<R; ++i)
1438  u.update(dt*butcher[R][1+i],k[i]);
1439 
1440  t += dt;
1441  if (!reduced && dt<dtmax-1e-13)
1442  {
1443  dt = std::min(2.0*dt,dtmax);
1444  if (verbosity>0)
1445  std::cout << "DIRK: increasing time step to " << dt << std::endl;
1446  }
1447  return;
1448  }
1449  else
1450  {
1451  if (dt<1e-12)
1452  {
1453  HDNUM_ERROR("time step too small in implicit Euler");
1454  error = true;
1455  break;
1456  }
1457  dt *= 0.5;
1458  reduced = true;
1459  if (verbosity>0) std::cout << "DIRK: reducing time step to " << dt << std::endl;
1460  }
1461  }
1462  }
1463 
1465  bool get_error () const
1466  {
1467  return error;
1468  }
1469 
1471  void set_state (time_type t_, const Vector<number_type>& u_)
1472  {
1473  t = t_;
1474  u = u_;
1475  }
1476 
1479  {
1480  return u;
1481  }
1482 
1484  time_type get_time () const
1485  {
1486  return t;
1487  }
1488 
1490  time_type get_dt () const
1491  {
1492  return dt;
1493  }
1494 
1496  size_type get_order () const
1497  {
1498  return order;
1499  }
1500 
1502  void get_info () const
1503  {
1504  }
1505 
1506  private:
1507  size_type verbosity;
1508  const DenseMatrix<number_type> butcher;
1509  const M& model;
1510  const S& newton;
1511  time_type t, dt, dtmax;
1512  number_type reduction;
1513  size_type linesearchsteps;
1515  int order;
1516  mutable bool error;
1517  };
1518 
1520  template<class T, class N>
1521  inline void gnuplot (const std::string& fname, const std::vector<T> t, const std::vector<Vector<N> > u)
1522  {
1523  std::fstream f(fname.c_str(),std::ios::out);
1524  for (typename std::vector<T>::size_type n=0; n<t.size(); n++)
1525  {
1526  f << std::scientific << std::showpoint
1527  << std::setprecision(16) << t[n];
1528  for (typename Vector<N>::size_type i=0; i<u[n].size(); i++)
1529  f << " " << std::scientific << std::showpoint
1530  << std::setprecision(u[n].precision()) << u[n][i];
1531  f << std::endl;
1532  }
1533  f.close();
1534  }
1535 
1537  template<class T, class N>
1538  inline void gnuplot (const std::string& fname, const std::vector<T> t, const std::vector<Vector<N> > u, const std::vector<T> dt)
1539  {
1540  std::fstream f(fname.c_str(),std::ios::out);
1541  for (typename std::vector<T>::size_type n=0; n<t.size(); n++)
1542  {
1543  f << std::scientific << std::showpoint
1544  << std::setprecision(16) << t[n];
1545  for (typename Vector<N>::size_type i=0; i<u[n].size(); i++)
1546  f << " " << std::scientific << std::showpoint
1547  << std::setprecision(u[n].precision()) << u[n][i];
1548  f << " " << std::scientific << std::showpoint
1549  << std::setprecision(16) << dt[n];
1550  f << std::endl;
1551  }
1552  f.close();
1553  }
1554 
1555 } // namespace hdnum
1556 
1557 #endif
const Vector< number_type > & get_state() const
get current state
Definition: ode.hh:1102
Implicit Euler using Newton&#39;s method to solve nonlinear system.
Definition: ode.hh:963
const Vector< number_type > & get_state() const
get current state
Definition: ode.hh:358
Implementation of a general Diagonal Implicit Runge-Kutta method.
Definition: ode.hh:1153
time_type get_time() const
get current time
Definition: ode.hh:364
const Vector< number_type > & get_state() const
get current state
Definition: ode.hh:1478
time_type get_time() const
get current time
Definition: ode.hh:163
DenseMatrix< number_type > ButcherTableau
the type of a Butcher tableau
Definition: ode.hh:1167
void set_dt(time_type dt_)
set time step for subsequent steps
Definition: ode.hh:683
time_type get_time() const
get current time
Definition: ode.hh:471
const Vector< number_type > & get_state() const
get current state
Definition: ode.hh:579
void set_TOL(time_type TOL_)
set tolerance for adaptive computation
Definition: ode.hh:689
Adaptive Runge-Kutta-Fehlberg method.
Definition: ode.hh:615
time_type get_dt() const
get dt used in last step (i.e. to compute current state)
Definition: ode.hh:1114
M::time_type time_type
export time_type
Definition: ode.hh:622
void set_dt(time_type dt_)
set time step for subsequent steps
Definition: ode.hh:128
M::time_type time_type
export time_type
Definition: ode.hh:1023
size_type get_order() const
return consistency order of the method
Definition: ode.hh:1120
DIRK(const M &model_, const S &newton_, const ButcherTableau &butcher_, const int order_)
Definition: ode.hh:1357
size_type get_order() const
return consistency order of the method
Definition: ode.hh:483
bool get_error() const
get current state
Definition: ode.hh:1089
Adaptive one-step method using Richardson extrapolation.
Definition: ode.hh:825
time_type get_dt() const
get dt used in last step (i.e. to compute current state)
Definition: ode.hh:77
void step()
do one step
Definition: ode.hh:50
M::size_type size_type
export size_type
Definition: ode.hh:829
M::size_type size_type
export size_type
Definition: ode.hh:509
void set_state(time_type t_, const Vector< number_type > &u_)
set current state
Definition: ode.hh:351
Explicit Euler method as an example for an ODE solver.
Definition: ode.hh:23
M::size_type size_type
export size_type
Definition: ode.hh:298
RKF45(const M &model_)
constructor stores reference to the model
Definition: ode.hh:628
time_type get_dt() const
get dt used in last step (i.e. to compute current state)
Definition: ode.hh:591
M::size_type size_type
export size_type
Definition: ode.hh:202
Kutta method (order 3 with 3 stages)
Definition: ode.hh:398
size_type get_order() const
return consistency order of the method
Definition: ode.hh:175
void get_info() const
print some information
Definition: ode.hh:1502
size_type get_order() const
return consistency order of the method
Definition: ode.hh:271
DIRK(const M &model_, const S &newton_, const std::string method)
Definition: ode.hh:1367
void step()
do one step
Definition: ode.hh:434
size_type get_order() const
return consistency order of the method
Definition: ode.hh:376
const Vector< number_type > & get_state() const
get current state
Definition: ode.hh:253
void set_dt(time_type dt_)
set time step for subsequent steps
Definition: ode.hh:428
M::number_type number_type
export number_type
Definition: ode.hh:114
size_type get_order() const
return consistency order of the method
Definition: ode.hh:597
M::time_type time_type
export time_type
Definition: ode.hh:405
void set_dt(time_type dt_)
set time step for subsequent steps
Definition: ode.hh:1037
void step()
do one step
Definition: ode.hh:868
time_type get_dt() const
get dt used in last step (i.e. to compute current state)
Definition: ode.hh:1490
M::size_type size_type
export size_type
Definition: ode.hh:1158
M::number_type number_type
export number_type
Definition: ode.hh:408
size_type get_order() const
return consistency order of the method
Definition: ode.hh:794
time_type get_dt() const
get dt used in last step (i.e. to compute current state)
Definition: ode.hh:925
void set_dt(time_type dt_)
set time step for subsequent steps
Definition: ode.hh:856
void set_dt(time_type dt_)
set time step for subsequent steps
Definition: ode.hh:223
ModifiedEuler(const M &model_)
constructor stores reference to the model
Definition: ode.hh:117
const Vector< number_type > & get_state() const
get current state
Definition: ode.hh:465
Heun method (order 3 with 3 stages)
Definition: ode.hh:294
Vector & update(const REAL alpha, const Vector &y)
Update vector by addition of a scaled vector (x += a y )
Definition: vector.hh:194
M::time_type time_type
export time_type
Definition: ode.hh:1161
const Vector< number_type > & get_state() const
get current state
Definition: ode.hh:65
time_type get_dt() const
get dt used in last step (i.e. to compute current state)
Definition: ode.hh:477
time_type get_time() const
get current time
Definition: ode.hh:1108
M::time_type time_type
export time_type
Definition: ode.hh:832
void set_state(time_type t_, const Vector< number_type > &u_)
set current state
Definition: ode.hh:58
time_type get_dt() const
get dt used in last step (i.e. to compute current state)
Definition: ode.hh:788
M::size_type size_type
export size_type
Definition: ode.hh:1020
bool get_error() const
get current state
Definition: ode.hh:1465
void set_state(time_type t_, const Vector< number_type > &u_)
set current state
Definition: ode.hh:150
void set_state(time_type t_, const Vector< number_type > &u_)
set current state
Definition: ode.hh:1095
void step()
do one step
Definition: ode.hh:1049
size_type get_order() const
return consistency order of the method
Definition: ode.hh:83
void step()
do one step
Definition: ode.hh:543
Modified Euler method (order 2 with 2 stages)
Definition: ode.hh:104
void step()
do one step
Definition: ode.hh:134
Heun2(const M &model_)
constructor stores reference to the model
Definition: ode.hh:211
void set_dt(time_type dt_)
set time step for subsequent steps
Definition: ode.hh:537
size_type get_order() const
return consistency order of the method
Definition: ode.hh:1496
void set_TOL(time_type TOL_)
set tolerance for adaptive computation
Definition: ode.hh:862
M::number_type number_type
export number_type
Definition: ode.hh:33
M::time_type time_type
export time_type
Definition: ode.hh:111
Newton&#39;s method with line search.
void get_info() const
print some information
Definition: ode.hh:1126
void step()
do one step
Definition: ode.hh:329
RungeKutta4(const M &model_)
constructor stores reference to the model
Definition: ode.hh:518
void set_state(time_type t_, const Vector< number_type > &u_)
set current state
Definition: ode.hh:1471
Kutta3(const M &model_)
constructor stores reference to the model
Definition: ode.hh:411
time_type get_time() const
get current time
Definition: ode.hh:1484
time_type get_time() const
get current time
Definition: ode.hh:585
RE(const M &model_, S &solver_)
constructor stores reference to the model
Definition: ode.hh:838
void step()
do one step
Definition: ode.hh:1389
M::number_type number_type
export number_type
Definition: ode.hh:515
time_type get_dt() const
get dt used in last step (i.e. to compute current state)
Definition: ode.hh:370
void set_dt(time_type dt_)
set time step for subsequent steps
Definition: ode.hh:1377
time_type get_dt() const
get dt used in last step (i.e. to compute current state)
Definition: ode.hh:169
time_type get_time() const
get current time
Definition: ode.hh:71
void set_state(time_type t_, const Vector< number_type > &u_)
set current state
Definition: ode.hh:246
void set_dt(time_type dt_)
set time step for subsequent steps
Definition: ode.hh:44
void set_dt(time_type dt_)
set time step for subsequent steps
Definition: ode.hh:323
const Vector< number_type > & get_state() const
get current state
Definition: ode.hh:157
EE(const M &model_)
constructor stores reference to the model
Definition: ode.hh:36
M::size_type size_type
export size_type
Definition: ode.hh:108
M::number_type number_type
export number_type
Definition: ode.hh:625
classical Runge-Kutta method (order 4 with 4 stages)
Definition: ode.hh:505
time_type get_time() const
get current time
Definition: ode.hh:782
void step()
do one step
Definition: ode.hh:229
time_type get_dt() const
get dt used in last step (i.e. to compute current state)
Definition: ode.hh:265
time_type get_time() const
get current time
Definition: ode.hh:919
M::number_type number_type
export number_type
Definition: ode.hh:1164
M::number_type number_type
export number_type
Definition: ode.hh:304
void set_state(time_type t_, const Vector< number_type > &u_)
set current state
Definition: ode.hh:572
M::time_type time_type
export time_type
Definition: ode.hh:301
time_type get_time() const
get current time
Definition: ode.hh:259
void get_info() const
print some information
Definition: ode.hh:937
M::time_type time_type
export time_type
Definition: ode.hh:30
void step()
do one step
Definition: ode.hh:695
void get_info() const
print some information
Definition: ode.hh:800
M::number_type number_type
export number_type
Definition: ode.hh:835
M::number_type number_type
export number_type
Definition: ode.hh:208
Definition: densematrix.hh:21
M::time_type time_type
export time_type
Definition: ode.hh:205
size_type get_order() const
return consistency order of the method
Definition: ode.hh:931
M::size_type size_type
export size_type
Definition: ode.hh:402
void set_verbosity(size_type verbosity_)
set verbosity level
Definition: ode.hh:1383
Heun method (order 2 with 2 stages)
Definition: ode.hh:198
IE(const M &model_, const S &newton_)
constructor stores reference to the model
Definition: ode.hh:1029
M::size_type size_type
export size_type
Definition: ode.hh:619
Heun3(const M &model_)
constructor stores reference to the model
Definition: ode.hh:307
const Vector< number_type > & get_state() const
get current state
Definition: ode.hh:913
std::size_t size_type
Type used for array indices.
Definition: vector.hh:32
M::time_type time_type
export time_type
Definition: ode.hh:512
const Vector< number_type > & get_state() const
get current state
Definition: ode.hh:776
M::number_type number_type
export number_type
Definition: ode.hh:1026
M::size_type size_type
export size_type
Definition: ode.hh:27
void set_state(time_type t_, const Vector< number_type > &u_)
set current state
Definition: ode.hh:458
void set_verbosity(size_type verbosity_)
set verbosity level
Definition: ode.hh:1043