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 tau_max_ = std::numeric_limits<Number>::max();
69 add_parameter(
"tau_max", tau_max_,
"Largest time step size allowed.");
71 if (ParabolicSystem::is_identity)
75 add_parameter(
"time stepping scheme",
76 time_stepping_scheme_,
77 "Time stepping scheme: ssprk 22, ssprk 33, erk 11, erk 22, "
78 "erk 33, erk 43, erk "
79 "54, strang ssprk 33 cn, strang erk 33 cn, strang erk 43 cn, "
80 "imex 11, imex 22, imex 33");
84 template <
typename Description,
int dim,
typename Number>
88 std::cout <<
"TimeIntegrator<dim, Number>::prepare()" << std::endl;
93 switch (time_stepping_scheme_) {
150 for (
auto &it : temp_) {
151 Vectors::reinit_state_vector<Description>(it, *offline_data_);
156 AssertThrow(cfl_min_ > 0., ExcMessage(
"cfl min must be a positive value"));
157 AssertThrow(cfl_max_ >= cfl_min_,
158 ExcMessage(
"cfl max must be greater than or equal to cfl min"));
161 acceptable_tau_max_ratio_ >= 1.0,
163 "acceptable tau_max ratio must be greater than or equal to 1."));
165 hyperbolic_module_->cfl(cfl_max_);
166 hyperbolic_module_->acceptable_tau_max_ratio(acceptable_tau_max_ratio_);
168 const auto check_whether_timestepping_makes_sense = [&]() {
173 switch (time_stepping_scheme_) {
188 ParabolicSystem::is_identity,
190 "The selected equation consists of a hyperbolic and nontrivial "
191 "parabolic subsystem and requires an IMEX timestepping "
192 "scheme such as »strang erk 33 cn«."));
207 !ParabolicSystem::is_identity,
209 "The selected equation has a trivial parabolic subsystem and "
210 "should not be run with an IMEX timestepping scheme."));
216 check_whether_timestepping_makes_sense();
217 this->parse_parameters_call_back.connect(
218 check_whether_timestepping_makes_sense);
229 template <
typename Description,
int dim,
typename Number>
233 if (!ParabolicSystem::is_identity)
234 parabolic_module_->prepare_state_vector(state_vector, t);
235 hyperbolic_module_->prepare_state_vector(state_vector, t);
246 template <
typename Description,
int dim,
typename Number>
253 std::min(tau_max_, t_final - t);
256 std::cout <<
"TimeIntegrator<dim, Number>::step()" << std::endl;
257 std::cout <<
" enforcing tau_max <= " << tau_max << std::endl;
260 const auto single_step = [&]() {
261 switch (time_stepping_scheme_) {
263 return step_ssprk_22(state_vector, t, tau_max);
265 return step_ssprk_33(state_vector, t, tau_max);
267 return step_erk_11(state_vector, t, tau_max);
269 return step_erk_22(state_vector, t, tau_max);
271 return step_erk_33(state_vector, t, tau_max);
273 return step_erk_43(state_vector, t, tau_max);
275 return step_erk_54(state_vector, t, tau_max);
277 return step_strang_ssprk_33_cn(state_vector, t, tau_max);
279 return step_strang_erk_33_cn(state_vector, t, tau_max);
281 return step_strang_erk_43_cn(state_vector, t, tau_max);
283 return step_imex_11(state_vector, t, tau_max);
285 return step_imex_22(state_vector, t, tau_max);
287 return step_imex_33(state_vector, t, tau_max);
289 __builtin_unreachable();
294 hyperbolic_module_->id_violation_strategy_ =
296 parabolic_module_->id_violation_strategy_ =
298 hyperbolic_module_->cfl(cfl_max_);
302 return single_step();
304 }
catch (
const Restart &restart) {
307 dealii::ExcInternalError());
316 <<
" restart with bang bang control: setting cfl to cfl_min"
319 hyperbolic_module_->cfl(cfl_min_);
326 <<
" restart with cruise control: using suggested_tau_max"
340 std::min(tau_max, efficiency_ * Number(restart.suggested_tau_max));
343 return single_step();
355 template <
typename Description,
int dim,
typename Number>
357 StateVector &state_vector, Number t, Number tau_max)
362 std::cout <<
"TimeIntegrator<dim, Number>::step_ssprk_22()" << std::endl;
365 Assert(efficiency_ == 1., dealii::ExcInternalError());
368 Number tau = hyperbolic_module_->template step<0>(
369 state_vector, {}, {}, temp_[0], Number(0.), tau_max);
372 hyperbolic_module_->prepare_state_vector(temp_[0], t + 1.0 * tau);
373 hyperbolic_module_->template step<0>(temp_[0], {}, {}, temp_[1], tau);
376 sadd(temp_[1], Number(1.0 / 2.0), Number(1.0 / 2.0), state_vector);
378 state_vector.swap(temp_[1]);
383 template <
typename Description,
int dim,
typename Number>
385 StateVector &state_vector, Number t, Number tau_max)
390 std::cout <<
"TimeIntegrator<dim, Number>::step_ssprk_33()" << std::endl;
393 Assert(efficiency_ == 1., dealii::ExcInternalError());
396 Number tau = hyperbolic_module_->template step<0>(
397 state_vector, {}, {}, temp_[0], Number(0.), tau_max);
400 hyperbolic_module_->prepare_state_vector(temp_[0], t + 1.0 * tau);
401 hyperbolic_module_->template step<0>(temp_[0], {}, {}, temp_[1], tau);
404 sadd(temp_[1], Number(1.0 / 4.0), Number(3.0 / 4.0), state_vector);
407 hyperbolic_module_->prepare_state_vector(temp_[1], t + 0.5 * tau);
408 hyperbolic_module_->template step<0>(temp_[1], {}, {}, temp_[0], tau);
411 sadd(temp_[0], Number(2.0 / 3.0), Number(1.0 / 3.0), state_vector);
413 state_vector.swap(temp_[0]);
418 template <
typename Description,
int dim,
typename Number>
420 StateVector &state_vector, Number , Number tau_max)
423 std::cout <<
"TimeIntegrator<dim, Number>::step_erk_11()" << std::endl;
426 Assert(efficiency_ == 1., dealii::ExcInternalError());
429 Number tau = hyperbolic_module_->template step<0>(
430 state_vector, {}, {}, temp_[0], Number(0.), tau_max);
432 state_vector.swap(temp_[0]);
437 template <
typename Description,
int dim,
typename Number>
439 StateVector &state_vector, Number t, Number tau_max)
442 std::cout <<
"TimeIntegrator<dim, Number>::step_erk_22()" << std::endl;
445 Assert(efficiency_ == 2., dealii::ExcInternalError());
448 Number tau = hyperbolic_module_->template step<0>(
449 state_vector, {}, {}, temp_[0], Number(.0), tau_max / efficiency_);
452 hyperbolic_module_->prepare_state_vector(temp_[0], t + 1.0 * tau);
453 hyperbolic_module_->template step<1>(
454 temp_[0], {{state_vector}}, {{Number(-1.)}}, temp_[1], tau);
456 state_vector.swap(temp_[1]);
457 return efficiency_ * tau;
461 template <
typename Description,
int dim,
typename Number>
463 StateVector &state_vector, Number t, Number tau_max)
466 std::cout <<
"TimeIntegrator<dim, Number>::step_erk_33()" << std::endl;
469 Assert(efficiency_ == 3., dealii::ExcInternalError());
472 Number tau = hyperbolic_module_->template step<0>(
473 state_vector, {}, {}, temp_[0], Number(0.), tau_max / efficiency_);
476 hyperbolic_module_->prepare_state_vector(temp_[0], t + 1.0 * tau);
477 hyperbolic_module_->template step<1>(
478 temp_[0], {{state_vector}}, {{Number(-1.)}}, temp_[1], tau);
484 hyperbolic_module_->prepare_state_vector(temp_[1], t + 2.0 * tau);
485 hyperbolic_module_->template step<2>(temp_[1],
486 {{state_vector, temp_[0]}},
487 {{Number(0.75), Number(-2.)}},
491 state_vector.swap(temp_[2]);
492 return efficiency_ * tau;
496 template <
typename Description,
int dim,
typename Number>
498 StateVector &state_vector, Number t, Number tau_max)
501 std::cout <<
"TimeIntegrator<dim, Number>::step_erk_43()" << std::endl;
504 Assert(efficiency_ == 4., dealii::ExcInternalError());
507 Number tau = hyperbolic_module_->template step<0>(
508 state_vector, {}, {}, temp_[0], Number(0.), tau_max / efficiency_);
511 hyperbolic_module_->prepare_state_vector(temp_[0], t + 1.0 * tau);
512 hyperbolic_module_->template step<1>(
513 temp_[0], {{state_vector}}, {{Number(-1.)}}, temp_[1], tau);
516 hyperbolic_module_->prepare_state_vector(temp_[1], t + 2.0 * tau);
517 hyperbolic_module_->template step<1>(
518 temp_[1], {{temp_[0]}}, {{Number(-1.)}}, temp_[2], tau);
524 hyperbolic_module_->prepare_state_vector(temp_[2], t + 3.0 * tau);
525 hyperbolic_module_->template step<2>(temp_[2],
526 {{temp_[0], temp_[1]}},
527 {{Number(5. / 3.), Number(-10. / 3.)}},
531 state_vector.swap(temp_[3]);
532 return efficiency_ * tau;
536 template <
typename Description,
int dim,
typename Number>
538 StateVector &state_vector, Number t, Number tau_max)
541 std::cout <<
"TimeIntegrator<dim, Number>::step_erk_54()" << std::endl;
544 Assert(efficiency_ == 5., dealii::ExcInternalError());
546 constexpr Number c = 0.2;
547 constexpr Number a_21 = +0.2;
548 constexpr Number a_31 = +0.26075582269554909;
549 constexpr Number a_32 = +0.13924417730445096;
550 constexpr Number a_41 = -0.25856517872570289;
551 constexpr Number a_42 = +0.91136274166280729;
552 constexpr Number a_43 = -0.05279756293710430;
553 constexpr Number a_51 = +0.21623276431503774;
554 constexpr Number a_52 = +0.51534223099602405;
555 constexpr Number a_53 = -0.81662794199265554;
556 constexpr Number a_54 = +0.88505294668159373;
557 constexpr Number a_61 = -0.10511678454691901;
558 constexpr Number a_62 = +0.87880047152100838;
559 constexpr Number a_63 = -0.58903404061484477;
560 constexpr Number a_64 = +0.46213380485434047;
561 constexpr Number a_65 [[maybe_unused]] = +0.35321654878641495;
564 Number tau = hyperbolic_module_->template step<0>(
565 state_vector, {}, {}, temp_[0], Number(0.), tau_max / efficiency_);
568 hyperbolic_module_->prepare_state_vector(temp_[0], t + 1.0 * tau);
569 hyperbolic_module_->template step<1>(
570 temp_[0], {{state_vector}}, {{(a_31 - a_21) / c}}, temp_[1], tau);
573 hyperbolic_module_->prepare_state_vector(temp_[1], t + 2.0 * tau);
574 hyperbolic_module_->template step<2>(
576 {{state_vector, temp_[0]}},
577 {{(a_41 - a_31) / c, (a_42 - a_32) / c}},
582 hyperbolic_module_->prepare_state_vector(temp_[2], t + 3.0 * tau);
583 hyperbolic_module_->template step<3>(
585 {{state_vector, temp_[0], temp_[1]}},
586 {{(a_51 - a_41) / c, (a_52 - a_42) / c, (a_53 - a_43) / c}},
591 hyperbolic_module_->prepare_state_vector(temp_[3], t + 4.0 * tau);
592 hyperbolic_module_->template step<4>(
594 {{state_vector, temp_[0], temp_[1], temp_[2]}},
602 state_vector.swap(temp_[4]);
603 return efficiency_ * tau;
607 template <
typename Description,
int dim,
typename Number>
609 StateVector &state_vector, Number t, Number tau_max)
614 std::cout <<
"TimeIntegrator<dim, Number>::step_strang_ssprk_33_cn()"
618 Assert(efficiency_ == 2., dealii::ExcInternalError());
622 Number tau = hyperbolic_module_->template step<0>(
623 state_vector, {}, {}, temp_[0], Number(0.0), tau_max / efficiency_);
625 hyperbolic_module_->prepare_state_vector(temp_[0], t + 1.0 * tau);
626 hyperbolic_module_->template step<0>(temp_[0], {}, {}, temp_[1], tau);
627 sadd(temp_[1], Number(1.0 / 4.0), Number(3.0 / 4.0), state_vector);
629 hyperbolic_module_->prepare_state_vector(temp_[1], t + 0.5 * tau);
630 hyperbolic_module_->template step<0>(temp_[1], {}, {}, temp_[0], tau);
631 sadd(temp_[0], Number(2.0 / 3.0), Number(1.0 / 3.0), state_vector);
636 parabolic_module_->crank_nicolson_step(temp_[0], t, temp_[2], 2.0 * tau);
645 hyperbolic_module_->prepare_state_vector( temp_[2], t + 1.0 * tau);
646 hyperbolic_module_->template step<0>( temp_[2], {}, {}, temp_[0], tau);
648 hyperbolic_module_->prepare_state_vector(temp_[0], t + 2.0 * tau);
649 hyperbolic_module_->template step<0>(temp_[0], {}, {}, temp_[1], tau);
650 sadd(temp_[1], Number(1.0 / 4.0), Number(3.0 / 4.0), temp_[2]);
652 hyperbolic_module_->prepare_state_vector(temp_[1], t + 1.5 * tau);
653 hyperbolic_module_->template step<0>(temp_[1], {}, {}, temp_[0], tau);
654 sadd(temp_[0], Number(2.0 / 3.0), Number(1.0 / 3.0), temp_[2]);
656 state_vector.swap(temp_[0]);
657 return efficiency_ * tau;
661 template <
typename Description,
int dim,
typename Number>
663 StateVector &state_vector, Number t, Number tau_max)
668 std::cout <<
"TimeIntegrator<dim, Number>::step_strang_erk_33_cn()"
672 Assert(efficiency_ == 6., dealii::ExcInternalError());
676 Number tau = hyperbolic_module_->template step<0>(
677 state_vector, {}, {}, temp_[0], Number(0.), tau_max / efficiency_);
679 hyperbolic_module_->prepare_state_vector(temp_[0], t + 1.0 * tau);
680 hyperbolic_module_->template step<1>(
681 temp_[0], {{state_vector}}, {{Number(-1.)}}, temp_[1], tau);
683 hyperbolic_module_->prepare_state_vector(temp_[1], t + 2.0 * tau);
684 hyperbolic_module_->template step<2>(temp_[1],
685 {{state_vector, temp_[0]}},
686 {{Number(0.75), Number(-2.)}},
693 parabolic_module_->crank_nicolson_step(temp_[2], t, temp_[3], 6.0 * tau);
702 hyperbolic_module_->prepare_state_vector(temp_[3], t + 3.0 * tau);
703 hyperbolic_module_->template step<0>(
704 temp_[3], {}, {}, temp_[0], tau);
706 hyperbolic_module_->prepare_state_vector(temp_[0], t + 4.0 * tau);
707 hyperbolic_module_->template step<1>(
708 temp_[0], {{ temp_[3]}}, {{Number(-1.)}}, temp_[1], tau);
710 hyperbolic_module_->prepare_state_vector(temp_[1], t + 5.0 * tau);
711 hyperbolic_module_->template step<2>(temp_[1],
712 {{ temp_[3], temp_[0]}},
713 {{Number(0.75), Number(-2.)}},
717 state_vector.swap(temp_[2]);
718 return efficiency_ * tau;
722 template <
typename Description,
int dim,
typename Number>
724 StateVector &state_vector, Number t, Number tau_max)
729 std::cout <<
"TimeIntegrator<dim, Number>::step_strang_erk_43_cn()"
733 Assert(efficiency_ == 8., dealii::ExcInternalError());
737 Number tau = hyperbolic_module_->template step<0>(
738 state_vector, {}, {}, temp_[0], Number(0.), tau_max / efficiency_);
740 hyperbolic_module_->prepare_state_vector(temp_[0], t + 1.0 * tau);
741 hyperbolic_module_->template step<1>(
742 temp_[0], {{state_vector}}, {{Number(-1.)}}, temp_[1], tau);
744 hyperbolic_module_->prepare_state_vector(temp_[1], t + 2.0 * tau);
745 hyperbolic_module_->template step<1>(
746 temp_[1], {{temp_[0]}}, {{Number(-1.)}}, temp_[2], tau);
748 hyperbolic_module_->prepare_state_vector(temp_[2], t + 3.0 * tau);
749 hyperbolic_module_->template step<2>(temp_[2],
750 {{temp_[0], temp_[1]}},
751 {{Number(5. / 3.), Number(-10. / 3.)}},
758 parabolic_module_->crank_nicolson_step(temp_[3], t, temp_[2], 8.0 * tau);
767 hyperbolic_module_->prepare_state_vector(temp_[2], t + 4.0 * tau);
768 hyperbolic_module_->template step<0>(
769 temp_[2], {}, {}, temp_[0], tau);
771 hyperbolic_module_->prepare_state_vector(temp_[0], t + 5.0 * tau);
772 hyperbolic_module_->template step<1>(
773 temp_[0], {{ temp_[2]}}, {{Number(-1.)}}, temp_[1], tau);
775 hyperbolic_module_->prepare_state_vector(temp_[1], t + 6.0 * tau);
776 hyperbolic_module_->template step<1>(
777 temp_[1], {{temp_[0]}}, {{Number(-1.)}}, temp_[2], tau);
779 hyperbolic_module_->prepare_state_vector(temp_[2], t + 7.0 * tau);
780 hyperbolic_module_->template step<2>(temp_[2],
781 {{temp_[0], temp_[1]}},
782 {{Number(5. / 3.), Number(-10. / 3.)}},
786 state_vector.swap(temp_[3]);
787 return efficiency_ * tau;
791 template <
typename Description,
int dim,
typename Number>
793 StateVector &state_vector, Number t, Number tau_max)
796 std::cout <<
"TimeIntegrator<dim, Number>::step_imex_11()" << std::endl;
799 Assert(efficiency_ == 1., dealii::ExcInternalError());
802 Number tau = hyperbolic_module_->template step<0>(
803 state_vector, {}, {}, temp_[0], Number(0.), tau_max);
806 parabolic_module_->template backward_euler_step<0>(
807 temp_[0], t, {}, {}, temp_[1], 1.0 * tau);
809 state_vector.swap(temp_[1]);
814 template <
typename Description,
int dim,
typename Number>
816 StateVector &state_vector, Number t, Number tau_max)
819 std::cout <<
"TimeIntegrator<dim, Number>::step_imex_22()" << std::endl;
822 Assert(efficiency_ == 2., dealii::ExcInternalError());
825 Number tau = hyperbolic_module_->template step<0>(
826 state_vector, {}, {}, temp_[0], Number(0.), tau_max / efficiency_);
829 parabolic_module_->template backward_euler_step<0>(
830 temp_[0], t, {}, {}, temp_[1], tau);
833 hyperbolic_module_->prepare_state_vector(temp_[1], t + 1.0 * tau);
834 hyperbolic_module_->template step<1>(
835 temp_[1], {{state_vector}}, {{Number(-1.)}}, temp_[2], tau);
838 parabolic_module_->template backward_euler_step<1>(temp_[2],
845 state_vector.swap(temp_[3]);
846 return efficiency_ * tau;
850 template <
typename Description,
int dim,
typename Number>
852 StateVector &state_vector, Number t, Number tau_max)
855 std::cout <<
"TimeIntegrator<dim, Number>::step_imex_33()" << std::endl;
858 Assert(efficiency_ == 3., dealii::ExcInternalError());
862 const Number gamma = Number(0.5) + std::sqrt(Number(3.0)) / Number(6.0);
865 Number tau = hyperbolic_module_->template step<0>(
866 state_vector, {}, {}, temp_[0], Number(0.), tau_max / efficiency_);
869 parabolic_module_->template backward_euler_step<1>(
873 {{Number(1. - 3. * gamma)}},
878 hyperbolic_module_->prepare_state_vector(temp_[1], t + 1.0 * tau);
879 hyperbolic_module_->template step<1>(
880 temp_[1], {{state_vector}}, {{Number(-1.)}}, temp_[2], tau);
886 parabolic_module_->template backward_euler_step<2>(
889 {{state_vector, temp_[1]}},
890 {{Number(6. * gamma - 1.), Number(2. - 9 * gamma)}},
895 hyperbolic_module_->prepare_state_vector(temp_[3], t + 2. * tau);
896 hyperbolic_module_->template step<2>(temp_[3],
897 {{state_vector, temp_[1]}},
898 {{Number(0.75), Number(-2.)}},
903 parabolic_module_->template backward_euler_step<3>(
906 {{state_vector, temp_[1], temp_[3]}},
907 {{Number(0.75 - 3. * gamma),
908 Number(6. * gamma - 2.),
909 Number(9. / 4. - 3. * gamma)}},
913 state_vector.swap(temp_[5]);
914 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)