12 using namespace dealii;
14 template <
typename StateVector,
typename Number>
18 auto &dst_U = std::get<0>(dst);
19 auto &src_U = std::get<0>(src);
20 dst_U.sadd(s, b, src_U);
22 auto &dst_V = std::get<2>(dst);
23 auto &src_V = std::get<2>(src);
24 dst_V.sadd(s, b, src_V);
28 template <
typename Description,
int dim,
typename Number>
34 const std::string &subsection )
35 : ParameterAcceptor(subsection)
36 , mpi_ensemble_(mpi_ensemble)
37 , offline_data_(&offline_data)
38 , hyperbolic_module_(&hyperbolic_module)
39 , parabolic_module_(¶bolic_module)
41 cfl_min_ = Number(0.45);
45 "Minimal admissible relative CFL constant. How this parameter is used "
46 "depends on the chosen CFL recovery strategy");
48 cfl_max_ = Number(0.90);
52 "Maximal admissible relative CFL constant. How this parameter is used "
53 "depends on the chosen CFL recovery strategy");
56 add_parameter(
"cfl recovery strategy",
57 cfl_recovery_strategy_,
58 "CFL/invariant domain violation recovery strategy: none, "
59 "bang bang control, cruise control");
61 acceptable_tau_max_ratio_ = Number(2.0);
62 add_parameter(
"acceptable tau_max ratio",
63 acceptable_tau_max_ratio_,
64 "Maximal acceptable discrepancy between computed tau_max of "
65 "a (sub)step and enforced time-step size tau. If the ratio "
66 "is violated then a restart will be singnalled.");
68 if (ParabolicSystem::is_identity)
72 add_parameter(
"time stepping scheme",
73 time_stepping_scheme_,
74 "Time stepping scheme: ssprk 22, ssprk 33, erk 11, erk 22, "
75 "erk 33, erk 43, erk "
76 "54, strang ssprk 33 cn, strang erk 33 cn, strang erk 43 cn, "
77 "imex 11, imex 22, imex 33");
81 template <
typename Description,
int dim,
typename Number>
85 std::cout <<
"TimeIntegrator<dim, Number>::prepare()" << std::endl;
90 switch (time_stepping_scheme_) {
147 for (
auto &it : temp_) {
148 Vectors::reinit_state_vector<Description>(it, *offline_data_);
153 AssertThrow(cfl_min_ > 0., ExcMessage(
"cfl min must be a positive value"));
154 AssertThrow(cfl_max_ >= cfl_min_,
155 ExcMessage(
"cfl max must be greater than or equal to cfl min"));
158 acceptable_tau_max_ratio_ >= 1.0,
160 "acceptable tau_max ratio must be greater than or equal to 1."));
162 hyperbolic_module_->cfl(cfl_max_);
163 hyperbolic_module_->acceptable_tau_max_ratio(acceptable_tau_max_ratio_);
165 const auto check_whether_timestepping_makes_sense = [&]() {
170 switch (time_stepping_scheme_) {
185 ParabolicSystem::is_identity,
187 "The selected equation consists of a hyperbolic and nontrivial "
188 "parabolic subsystem and requires an IMEX timestepping "
189 "scheme such as »strang erk 33 cn«."));
204 !ParabolicSystem::is_identity,
206 "The selected equation has a trivial parabolic subsystem and "
207 "should not be run with an IMEX timestepping scheme."));
213 check_whether_timestepping_makes_sense();
214 this->parse_parameters_call_back.connect(
215 check_whether_timestepping_makes_sense);
226 template <
typename Description,
int dim,
typename Number>
230 if (!ParabolicSystem::is_identity)
231 parabolic_module_->prepare_state_vector(state_vector, t);
232 hyperbolic_module_->prepare_state_vector(state_vector, t);
243 template <
typename Description,
int dim,
typename Number>
249 Number tau_max = t_final - t;
252 std::cout <<
"TimeIntegrator<dim, Number>::step()" << std::endl;
253 std::cout <<
" enforcing tau_max <= " << tau_max << std::endl;
256 const auto single_step = [&]() {
257 switch (time_stepping_scheme_) {
259 return step_ssprk_22(state_vector, t, tau_max);
261 return step_ssprk_33(state_vector, t, tau_max);
263 return step_erk_11(state_vector, t, tau_max);
265 return step_erk_22(state_vector, t, tau_max);
267 return step_erk_33(state_vector, t, tau_max);
269 return step_erk_43(state_vector, t, tau_max);
271 return step_erk_54(state_vector, t, tau_max);
273 return step_strang_ssprk_33_cn(state_vector, t, tau_max);
275 return step_strang_erk_33_cn(state_vector, t, tau_max);
277 return step_strang_erk_43_cn(state_vector, t, tau_max);
279 return step_imex_11(state_vector, t, tau_max);
281 return step_imex_22(state_vector, t, tau_max);
283 return step_imex_33(state_vector, t, tau_max);
285 __builtin_unreachable();
290 hyperbolic_module_->id_violation_strategy_ =
292 parabolic_module_->id_violation_strategy_ =
294 hyperbolic_module_->cfl(cfl_max_);
298 return single_step();
300 }
catch (
const Restart &restart) {
303 dealii::ExcInternalError());
312 <<
" restart with bang bang control: setting cfl to cfl_min"
315 hyperbolic_module_->cfl(cfl_min_);
322 <<
" restart with cruise control: using suggested_tau_max"
336 std::min(tau_max, efficiency_ * Number(restart.suggested_tau_max));
339 return single_step();
351 template <
typename Description,
int dim,
typename Number>
353 StateVector &state_vector, Number t, Number tau_max)
358 std::cout <<
"TimeIntegrator<dim, Number>::step_ssprk_22()" << std::endl;
361 Assert(efficiency_ == 1., dealii::ExcInternalError());
364 Number tau = hyperbolic_module_->template step<0>(
365 state_vector, {}, {}, temp_[0], Number(0.), tau_max);
368 hyperbolic_module_->prepare_state_vector(temp_[0], t + 1.0 * tau);
369 hyperbolic_module_->template step<0>(temp_[0], {}, {}, temp_[1], tau);
372 sadd(temp_[1], Number(1.0 / 2.0), Number(1.0 / 2.0), state_vector);
374 state_vector.swap(temp_[1]);
379 template <
typename Description,
int dim,
typename Number>
381 StateVector &state_vector, Number t, Number tau_max)
386 std::cout <<
"TimeIntegrator<dim, Number>::step_ssprk_33()" << std::endl;
389 Assert(efficiency_ == 1., dealii::ExcInternalError());
392 Number tau = hyperbolic_module_->template step<0>(
393 state_vector, {}, {}, temp_[0], Number(0.), tau_max);
396 hyperbolic_module_->prepare_state_vector(temp_[0], t + 1.0 * tau);
397 hyperbolic_module_->template step<0>(temp_[0], {}, {}, temp_[1], tau);
400 sadd(temp_[1], Number(1.0 / 4.0), Number(3.0 / 4.0), state_vector);
403 hyperbolic_module_->prepare_state_vector(temp_[1], t + 0.5 * tau);
404 hyperbolic_module_->template step<0>(temp_[1], {}, {}, temp_[0], tau);
407 sadd(temp_[0], Number(2.0 / 3.0), Number(1.0 / 3.0), state_vector);
409 state_vector.swap(temp_[0]);
414 template <
typename Description,
int dim,
typename Number>
416 StateVector &state_vector, Number , Number tau_max)
419 std::cout <<
"TimeIntegrator<dim, Number>::step_erk_11()" << std::endl;
422 Assert(efficiency_ == 1., dealii::ExcInternalError());
425 Number tau = hyperbolic_module_->template step<0>(
426 state_vector, {}, {}, temp_[0], Number(0.), tau_max);
428 state_vector.swap(temp_[0]);
433 template <
typename Description,
int dim,
typename Number>
435 StateVector &state_vector, Number t, Number tau_max)
438 std::cout <<
"TimeIntegrator<dim, Number>::step_erk_22()" << std::endl;
441 Assert(efficiency_ == 2., dealii::ExcInternalError());
444 Number tau = hyperbolic_module_->template step<0>(
445 state_vector, {}, {}, temp_[0], Number(.0), tau_max / efficiency_);
448 hyperbolic_module_->prepare_state_vector(temp_[0], t + 1.0 * tau);
449 hyperbolic_module_->template step<1>(
450 temp_[0], {{state_vector}}, {{Number(-1.)}}, temp_[1], tau);
452 state_vector.swap(temp_[1]);
453 return efficiency_ * tau;
457 template <
typename Description,
int dim,
typename Number>
459 StateVector &state_vector, Number t, Number tau_max)
462 std::cout <<
"TimeIntegrator<dim, Number>::step_erk_33()" << std::endl;
465 Assert(efficiency_ == 3., dealii::ExcInternalError());
468 Number tau = hyperbolic_module_->template step<0>(
469 state_vector, {}, {}, temp_[0], Number(0.), tau_max / efficiency_);
472 hyperbolic_module_->prepare_state_vector(temp_[0], t + 1.0 * tau);
473 hyperbolic_module_->template step<1>(
474 temp_[0], {{state_vector}}, {{Number(-1.)}}, temp_[1], tau);
480 hyperbolic_module_->prepare_state_vector(temp_[1], t + 2.0 * tau);
481 hyperbolic_module_->template step<2>(temp_[1],
482 {{state_vector, temp_[0]}},
483 {{Number(0.75), Number(-2.)}},
487 state_vector.swap(temp_[2]);
488 return efficiency_ * tau;
492 template <
typename Description,
int dim,
typename Number>
494 StateVector &state_vector, Number t, Number tau_max)
497 std::cout <<
"TimeIntegrator<dim, Number>::step_erk_43()" << std::endl;
500 Assert(efficiency_ == 4., dealii::ExcInternalError());
503 Number tau = hyperbolic_module_->template step<0>(
504 state_vector, {}, {}, temp_[0], Number(0.), tau_max / efficiency_);
507 hyperbolic_module_->prepare_state_vector(temp_[0], t + 1.0 * tau);
508 hyperbolic_module_->template step<1>(
509 temp_[0], {{state_vector}}, {{Number(-1.)}}, temp_[1], tau);
512 hyperbolic_module_->prepare_state_vector(temp_[1], t + 2.0 * tau);
513 hyperbolic_module_->template step<1>(
514 temp_[1], {{temp_[0]}}, {{Number(-1.)}}, temp_[2], tau);
520 hyperbolic_module_->prepare_state_vector(temp_[2], t + 3.0 * tau);
521 hyperbolic_module_->template step<2>(temp_[2],
522 {{temp_[0], temp_[1]}},
523 {{Number(5. / 3.), Number(-10. / 3.)}},
527 state_vector.swap(temp_[3]);
528 return efficiency_ * tau;
532 template <
typename Description,
int dim,
typename Number>
534 StateVector &state_vector, Number t, Number tau_max)
537 std::cout <<
"TimeIntegrator<dim, Number>::step_erk_54()" << std::endl;
540 Assert(efficiency_ == 5., dealii::ExcInternalError());
542 constexpr Number c = 0.2;
543 constexpr Number a_21 = +0.2;
544 constexpr Number a_31 = +0.26075582269554909;
545 constexpr Number a_32 = +0.13924417730445096;
546 constexpr Number a_41 = -0.25856517872570289;
547 constexpr Number a_42 = +0.91136274166280729;
548 constexpr Number a_43 = -0.05279756293710430;
549 constexpr Number a_51 = +0.21623276431503774;
550 constexpr Number a_52 = +0.51534223099602405;
551 constexpr Number a_53 = -0.81662794199265554;
552 constexpr Number a_54 = +0.88505294668159373;
553 constexpr Number a_61 = -0.10511678454691901;
554 constexpr Number a_62 = +0.87880047152100838;
555 constexpr Number a_63 = -0.58903404061484477;
556 constexpr Number a_64 = +0.46213380485434047;
557 constexpr Number a_65 [[maybe_unused]] = +0.35321654878641495;
560 Number tau = hyperbolic_module_->template step<0>(
561 state_vector, {}, {}, temp_[0], Number(0.), tau_max / efficiency_);
564 hyperbolic_module_->prepare_state_vector(temp_[0], t + 1.0 * tau);
565 hyperbolic_module_->template step<1>(
566 temp_[0], {{state_vector}}, {{(a_31 - a_21) / c}}, temp_[1], tau);
569 hyperbolic_module_->prepare_state_vector(temp_[1], t + 2.0 * tau);
570 hyperbolic_module_->template step<2>(
572 {{state_vector, temp_[0]}},
573 {{(a_41 - a_31) / c, (a_42 - a_32) / c}},
578 hyperbolic_module_->prepare_state_vector(temp_[2], t + 3.0 * tau);
579 hyperbolic_module_->template step<3>(
581 {{state_vector, temp_[0], temp_[1]}},
582 {{(a_51 - a_41) / c, (a_52 - a_42) / c, (a_53 - a_43) / c}},
587 hyperbolic_module_->prepare_state_vector(temp_[3], t + 4.0 * tau);
588 hyperbolic_module_->template step<4>(
590 {{state_vector, temp_[0], temp_[1], temp_[2]}},
598 state_vector.swap(temp_[4]);
599 return efficiency_ * tau;
603 template <
typename Description,
int dim,
typename Number>
605 StateVector &state_vector, Number t, Number tau_max)
610 std::cout <<
"TimeIntegrator<dim, Number>::step_strang_ssprk_33_cn()"
614 Assert(efficiency_ == 2., dealii::ExcInternalError());
618 Number tau = hyperbolic_module_->template step<0>(
619 state_vector, {}, {}, temp_[0], Number(0.0), tau_max / efficiency_);
621 hyperbolic_module_->prepare_state_vector(temp_[0], t + 1.0 * tau);
622 hyperbolic_module_->template step<0>(temp_[0], {}, {}, temp_[1], tau);
623 sadd(temp_[1], Number(1.0 / 4.0), Number(3.0 / 4.0), state_vector);
625 hyperbolic_module_->prepare_state_vector(temp_[1], t + 0.5 * tau);
626 hyperbolic_module_->template step<0>(temp_[1], {}, {}, temp_[0], tau);
627 sadd(temp_[0], Number(2.0 / 3.0), Number(1.0 / 3.0), state_vector);
632 parabolic_module_->crank_nicolson_step(temp_[0], t, temp_[2], 2.0 * tau);
641 hyperbolic_module_->prepare_state_vector( temp_[2], t + 1.0 * tau);
642 hyperbolic_module_->template step<0>( temp_[2], {}, {}, temp_[0], tau);
644 hyperbolic_module_->prepare_state_vector(temp_[0], t + 2.0 * tau);
645 hyperbolic_module_->template step<0>(temp_[0], {}, {}, temp_[1], tau);
646 sadd(temp_[1], Number(1.0 / 4.0), Number(3.0 / 4.0), temp_[2]);
648 hyperbolic_module_->prepare_state_vector(temp_[1], t + 1.5 * tau);
649 hyperbolic_module_->template step<0>(temp_[1], {}, {}, temp_[0], tau);
650 sadd(temp_[0], Number(2.0 / 3.0), Number(1.0 / 3.0), temp_[2]);
652 state_vector.swap(temp_[0]);
653 return efficiency_ * tau;
657 template <
typename Description,
int dim,
typename Number>
659 StateVector &state_vector, Number t, Number tau_max)
664 std::cout <<
"TimeIntegrator<dim, Number>::step_strang_erk_33_cn()"
668 Assert(efficiency_ == 6., dealii::ExcInternalError());
672 Number tau = hyperbolic_module_->template step<0>(
673 state_vector, {}, {}, temp_[0], Number(0.), tau_max / efficiency_);
675 hyperbolic_module_->prepare_state_vector(temp_[0], t + 1.0 * tau);
676 hyperbolic_module_->template step<1>(
677 temp_[0], {{state_vector}}, {{Number(-1.)}}, temp_[1], tau);
679 hyperbolic_module_->prepare_state_vector(temp_[1], t + 2.0 * tau);
680 hyperbolic_module_->template step<2>(temp_[1],
681 {{state_vector, temp_[0]}},
682 {{Number(0.75), Number(-2.)}},
689 parabolic_module_->crank_nicolson_step(temp_[2], t, temp_[3], 6.0 * tau);
698 hyperbolic_module_->prepare_state_vector(temp_[3], t + 3.0 * tau);
699 hyperbolic_module_->template step<0>(
700 temp_[3], {}, {}, temp_[0], tau);
702 hyperbolic_module_->prepare_state_vector(temp_[0], t + 4.0 * tau);
703 hyperbolic_module_->template step<1>(
704 temp_[0], {{ temp_[3]}}, {{Number(-1.)}}, temp_[1], tau);
706 hyperbolic_module_->prepare_state_vector(temp_[1], t + 5.0 * tau);
707 hyperbolic_module_->template step<2>(temp_[1],
708 {{ temp_[3], temp_[0]}},
709 {{Number(0.75), Number(-2.)}},
713 state_vector.swap(temp_[2]);
714 return efficiency_ * tau;
718 template <
typename Description,
int dim,
typename Number>
720 StateVector &state_vector, Number t, Number tau_max)
725 std::cout <<
"TimeIntegrator<dim, Number>::step_strang_erk_43_cn()"
729 Assert(efficiency_ == 8., dealii::ExcInternalError());
733 Number tau = hyperbolic_module_->template step<0>(
734 state_vector, {}, {}, temp_[0], Number(0.), tau_max / efficiency_);
736 hyperbolic_module_->prepare_state_vector(temp_[0], t + 1.0 * tau);
737 hyperbolic_module_->template step<1>(
738 temp_[0], {{state_vector}}, {{Number(-1.)}}, temp_[1], tau);
740 hyperbolic_module_->prepare_state_vector(temp_[1], t + 2.0 * tau);
741 hyperbolic_module_->template step<1>(
742 temp_[1], {{temp_[0]}}, {{Number(-1.)}}, temp_[2], tau);
744 hyperbolic_module_->prepare_state_vector(temp_[2], t + 3.0 * tau);
745 hyperbolic_module_->template step<2>(temp_[2],
746 {{temp_[0], temp_[1]}},
747 {{Number(5. / 3.), Number(-10. / 3.)}},
754 parabolic_module_->crank_nicolson_step(temp_[3], t, temp_[2], 8.0 * tau);
763 hyperbolic_module_->prepare_state_vector(temp_[2], t + 4.0 * tau);
764 hyperbolic_module_->template step<0>(
765 temp_[2], {}, {}, temp_[0], tau);
767 hyperbolic_module_->prepare_state_vector(temp_[0], t + 5.0 * tau);
768 hyperbolic_module_->template step<1>(
769 temp_[0], {{ temp_[2]}}, {{Number(-1.)}}, temp_[1], tau);
771 hyperbolic_module_->prepare_state_vector(temp_[1], t + 6.0 * tau);
772 hyperbolic_module_->template step<1>(
773 temp_[1], {{temp_[0]}}, {{Number(-1.)}}, temp_[2], tau);
775 hyperbolic_module_->prepare_state_vector(temp_[2], t + 7.0 * tau);
776 hyperbolic_module_->template step<2>(temp_[2],
777 {{temp_[0], temp_[1]}},
778 {{Number(5. / 3.), Number(-10. / 3.)}},
782 state_vector.swap(temp_[3]);
783 return efficiency_ * tau;
787 template <
typename Description,
int dim,
typename Number>
789 StateVector &state_vector, Number t, Number tau_max)
792 std::cout <<
"TimeIntegrator<dim, Number>::step_imex_11()" << std::endl;
795 Assert(efficiency_ == 1., dealii::ExcInternalError());
798 Number tau = hyperbolic_module_->template step<0>(
799 state_vector, {}, {}, temp_[0], Number(0.), tau_max);
802 parabolic_module_->template backward_euler_step<0>(
803 temp_[0], t, {}, {}, temp_[1], 1.0 * tau);
805 state_vector.swap(temp_[1]);
810 template <
typename Description,
int dim,
typename Number>
812 StateVector &state_vector, Number t, Number tau_max)
815 std::cout <<
"TimeIntegrator<dim, Number>::step_imex_22()" << std::endl;
818 Assert(efficiency_ == 2., dealii::ExcInternalError());
821 Number tau = hyperbolic_module_->template step<0>(
822 state_vector, {}, {}, temp_[0], Number(0.), tau_max / efficiency_);
825 parabolic_module_->template backward_euler_step<0>(
826 temp_[0], t, {}, {}, temp_[1], tau);
829 hyperbolic_module_->prepare_state_vector(temp_[1], t + 1.0 * tau);
830 hyperbolic_module_->template step<1>(
831 temp_[1], {{state_vector}}, {{Number(-1.)}}, temp_[2], tau);
834 parabolic_module_->template backward_euler_step<1>(temp_[2],
841 state_vector.swap(temp_[3]);
842 return efficiency_ * tau;
846 template <
typename Description,
int dim,
typename Number>
848 StateVector &state_vector, Number t, Number tau_max)
851 std::cout <<
"TimeIntegrator<dim, Number>::step_imex_33()" << std::endl;
854 Assert(efficiency_ == 3., dealii::ExcInternalError());
858 const Number gamma = Number(0.5) + std::sqrt(Number(3.0)) / Number(6.0);
861 Number tau = hyperbolic_module_->template step<0>(
862 state_vector, {}, {}, temp_[0], Number(0.), tau_max / efficiency_);
865 parabolic_module_->template backward_euler_step<1>(
869 {{Number(1. - 3. * gamma)}},
874 hyperbolic_module_->prepare_state_vector(temp_[1], t + 1.0 * tau);
875 hyperbolic_module_->template step<1>(
876 temp_[1], {{state_vector}}, {{Number(-1.)}}, temp_[2], tau);
882 parabolic_module_->template backward_euler_step<2>(
885 {{state_vector, temp_[1]}},
886 {{Number(6. * gamma - 1.), Number(2. - 9 * gamma)}},
891 hyperbolic_module_->prepare_state_vector(temp_[3], t + 2. * tau);
892 hyperbolic_module_->template step<2>(temp_[3],
893 {{state_vector, temp_[1]}},
894 {{Number(0.75), Number(-2.)}},
899 parabolic_module_->template backward_euler_step<3>(
902 {{state_vector, temp_[1], temp_[3]}},
903 {{Number(0.75 - 3. * gamma),
904 Number(6. * gamma - 2.),
905 Number(9. / 4. - 3. * gamma)}},
909 state_vector.swap(temp_[5]);
910 return efficiency_ * tau;
Number step_imex_33(StateVector &state_vector, Number t, Number tau_max)
TimeIntegrator(const MPIEnsemble &mpi_ensemble, const OfflineData< dim, Number > &offline_data, const HyperbolicModule< Description, dim, Number > &hyperbolic_module, const ParabolicModule< Description, dim, Number > ¶bolic_module, const std::string &subsection="/TimeIntegrator")
Number step_strang_ssprk_33_cn(StateVector &state_vector, Number t, Number tau_max)
Number step_erk_22(StateVector &state_vector, Number t, Number tau_max)
Number step_imex_11(StateVector &state_vector, Number t, Number tau_max)
Number step_strang_erk_43_cn(StateVector &state_vector, Number t, Number tau_max)
Number step_erk_54(StateVector &state_vector, Number t, Number tau_max)
Number step_erk_33(StateVector &state_vector, Number t, Number tau_max)
Number step_erk_43(StateVector &state_vector, Number t, Number tau_max)
Number step_imex_22(StateVector &state_vector, Number t, Number tau_max)
typename View::StateVector StateVector
Number step_erk_11(StateVector &state_vector, Number t, Number tau_max)
Number step_ssprk_22(StateVector &state_vector, Number t, Number tau_max)
Number step_ssprk_33(StateVector &state_vector, Number t, Number tau_max)
void prepare_state_vector(StateVector &state_vector, Number t) const
Number step(StateVector &state_vector, Number t, Number t_final=std::numeric_limits< Number >::max())
Number step_strang_erk_33_cn(StateVector &state_vector, Number t, Number tau_max)
std::tuple< MultiComponentVector< Number, problem_dim >, MultiComponentVector< Number, prec_dim >, BlockVector< Number > > StateVector
void sadd(StateVector &dst, const Number s, const Number b, const StateVector &src)