OGS
TimeLoop.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4#include "TimeLoop.h"
5
6#include <range/v3/algorithm/any_of.hpp>
7#include <range/v3/algorithm/contains.hpp>
8
9#include "BaseLib/Error.h"
10#include "BaseLib/RunTime.h"
17#include "ProcessData.h"
18
19namespace
20{
22 std::vector<std::unique_ptr<ProcessLib::ProcessData>> const&
23 per_process_data,
24 double const t)
25{
26 for (auto& process_data : per_process_data)
27 {
28 process_data->process.updateDeactivatedSubdomains(
29 t, process_data->process_id);
30 }
31}
32
33bool isOutputStep(std::vector<ProcessLib::Output> const& outputs,
34 const int timestep, const NumLib::Time& t,
35 const NumLib::Time& end_time)
36{
37 if (end_time == t)
38 {
39 // the last timestep is an output step
40 return true;
41 }
42
43 return ranges::any_of(outputs, [timestep, t](auto const& output)
44 { return output.isOutputStep(timestep, t); });
45}
46
48 int const timestep, NumLib::Time const& t, double const dt,
49 const NumLib::Time& end_time,
50 std::vector<std::unique_ptr<ProcessLib::ProcessData>> const&
51 per_process_data,
52 std::vector<GlobalVector*> const& process_solutions,
53 std::vector<GlobalVector*> const& process_solutions_prev,
54 std::vector<ProcessLib::Output> const& outputs)
55{
56 if (!isOutputStep(outputs, timestep, t, end_time))
57 {
58 return;
59 }
60
61 for (auto& process_data : per_process_data)
62 {
63 auto const process_id = process_data->process_id;
64 auto& pcs = process_data->process;
65
66 pcs.preOutput(t(), dt, process_solutions, process_solutions_prev,
67 process_id);
68 }
69}
70} // namespace
71
72namespace ProcessLib
73{
75 NumLib::Time const& t, double const dt,
76 std::vector<std::unique_ptr<ProcessData>> const& per_process_data,
77 std::vector<GlobalVector*> const& _process_solutions)
78{
79 for (auto& process_data : per_process_data)
80 {
81 auto const process_id = process_data->process_id;
82 auto& pcs = process_data->process;
83 pcs.preTimestep(_process_solutions, t(), dt, process_id);
84 }
85}
86
88 NumLib::Time const& t, double const dt,
89 std::vector<std::unique_ptr<ProcessData>> const& per_process_data,
90 std::vector<GlobalVector*> const& process_solutions,
91 std::vector<GlobalVector*> const& process_solutions_prev)
92{
93 for (auto& process_data : per_process_data)
94 {
95 auto const process_id = process_data->process_id;
96 auto& pcs = process_data->process;
97
98 pcs.computeSecondaryVariable(t(), dt, process_solutions,
99 *process_solutions_prev[process_id],
100 process_id);
101 pcs.postTimestep(process_solutions, process_solutions_prev, t(), dt,
102 process_id);
103 }
104}
105
106template <NumLib::ODESystemTag ODETag>
108 ProcessData& process_data,
110{
111 using Tag = NumLib::NonlinearSolverTag;
112 // A concrete Picard solver
113 using NonlinearSolverPicard = NumLib::NonlinearSolver<Tag::Picard>;
114 // A concrete Newton solver
115 using NonlinearSolverNewton = NumLib::NonlinearSolver<Tag::Newton>;
116
117 if (dynamic_cast<NonlinearSolverPicard*>(&process_data.nonlinear_solver))
118 {
119 // The Picard solver can also work with a Newton-ready ODE,
120 // because the Newton ODESystem derives from the Picard ODESystem.
121 // So no further checks are needed here.
122
123 process_data.tdisc_ode_sys = std::make_unique<
125 process_data.process_id, ode_sys, *process_data.time_disc);
126 }
127 // TODO (naumov) Provide a function to nonlinear_solver to distinguish the
128 // types. Could be handy, because a nonlinear solver could handle both types
129 // like PETScSNES.
130 else if ((dynamic_cast<NonlinearSolverNewton*>(
131 &process_data.nonlinear_solver) != nullptr)
132#ifdef USE_PETSC
133 || (dynamic_cast<NumLib::PETScNonlinearSolver*>(
134 &process_data.nonlinear_solver) != nullptr)
135#endif // USE_PETSC
136 )
137 {
138 // The Newton-Raphson method needs a Newton-ready ODE.
139
141 if (auto* ode_newton = dynamic_cast<ODENewton*>(&ode_sys))
142 {
143 process_data.tdisc_ode_sys = std::make_unique<
145 process_data.process_id, *ode_newton, *process_data.time_disc);
146 }
147 else
148 {
149 OGS_FATAL(
150 "You are trying to solve a non-Newton-ready ODE with the"
151 " Newton-Raphson method. Aborting");
152 }
153 }
154 else
155 {
156 OGS_FATAL("Encountered unknown nonlinear solver type. Aborting");
157 }
158}
159
161{
162 setTimeDiscretizedODESystem(process_data, process_data.process);
163}
164
165std::pair<std::vector<GlobalVector*>, std::vector<GlobalVector*>>
167 NumLib::Time const& t0,
168 std::vector<std::unique_ptr<ProcessData>> const& per_process_data)
169{
170 std::vector<GlobalVector*> process_solutions;
171 std::vector<GlobalVector*> process_solutions_prev;
172
173 for (auto const& process_data : per_process_data)
174 {
175 auto const process_id = process_data->process_id;
176 auto& ode_sys = *process_data->tdisc_ode_sys;
177
178 // append a solution vector of suitable size
179 process_solutions.emplace_back(
181 ode_sys.getMatrixSpecifications(process_id)));
182 process_solutions_prev.emplace_back(
184 ode_sys.getMatrixSpecifications(process_id)));
185 }
186
187 for (auto const& process_data : per_process_data)
188 {
189 auto& pcs = process_data->process;
190 auto const process_id = process_data->process_id;
191 pcs.setInitialConditions(process_solutions, process_solutions_prev,
192 t0(), process_id);
193
194 auto& time_disc = *process_data->time_disc;
195 time_disc.setInitialState(t0()); // push IC
196 }
197
198 return {process_solutions, process_solutions_prev};
199}
200
202 std::vector<std::unique_ptr<ProcessData>> const& per_process_data,
203 std::vector<GlobalVector*> const& process_solutions,
204 std::vector<GlobalVector*> const& process_solutions_prev)
205{
206 for (auto const& process_data : per_process_data)
207 {
208 auto& nonlinear_solver = process_data->nonlinear_solver;
209
210 setEquationSystem(*process_data);
211 nonlinear_solver.calculateNonEquilibriumInitialResiduum(
212 process_solutions, process_solutions_prev,
213 process_data->process_id);
214 }
215}
216
218 std::vector<GlobalVector*>& x, std::vector<GlobalVector*> const& x_prev,
219 std::size_t const timestep, double const t, double const delta_t,
220 ProcessData const& process_data, std::vector<Output> const& outputs)
221{
222 auto& process = process_data.process;
223 int const process_id = process_data.process_id;
224 auto& time_disc = *process_data.time_disc;
225 auto& nonlinear_solver = process_data.nonlinear_solver;
226
227 setEquationSystem(process_data);
228
229 // Note: Order matters!
230 // First advance to the next timestep, then set known solutions at that
231 // time, afterwards pass the right solution vector and time to the
232 // preTimestep() hook.
233
234 time_disc.nextTimestep(t, delta_t);
235
236 auto const post_iteration_callback =
237 [&](int const iteration, bool const converged,
238 std::vector<GlobalVector*> const& x)
239 {
240 // Note: We don't call the postNonLinearSolver(), preOutput(),
241 // computeSecondaryVariable() and postTimestep() hooks here. This might
242 // lead to some inconsistencies in the data compared to regular output.
243 for (auto const& output : outputs)
244 {
245 output.doOutputNonlinearIteration(process, process_id, timestep,
246 NumLib::Time(t), iteration,
247 converged, x);
248 }
249 };
250
251 auto const nonlinear_solver_status =
252 nonlinear_solver.solve(x, x_prev, post_iteration_callback, process_id);
253
254 if (!nonlinear_solver_status.error_norms_met)
255 {
256 return nonlinear_solver_status;
257 }
258
259 process.postNonLinearSolver(x, x_prev, t, delta_t, process_id);
260
261 return nonlinear_solver_status;
262}
263
265 std::vector<Output>&& outputs,
266 std::vector<std::unique_ptr<ProcessData>>&& per_process_data,
267 std::unique_ptr<NumLib::StaggeredCoupling>&& staggered_coupling,
268 const NumLib::Time& start_time, const NumLib::Time& end_time)
269 : _outputs{std::move(outputs)},
270 _per_process_data(std::move(per_process_data)),
271 _start_time(start_time),
272 _end_time(end_time),
273 _staggered_coupling(std::move(staggered_coupling))
274{
275}
276
278 NumLib::TimeStepAlgorithm const& timestep_algorithm,
279 NumLib::Time const& time)
280{
281 // for the first time step we can't compute the changes to the previous
282 // time step
283 if (time == timestep_algorithm.begin())
284 {
285 return false;
286 }
287 return timestep_algorithm.isSolutionErrorComputationNeeded();
288}
289
290std::pair<NumLib::TimeIncrement, bool> TimeLoop::computeTimeStepping(
291 const double prev_dt, NumLib::Time& t, std::size_t& accepted_steps,
292 std::size_t& rejected_steps,
293 std::vector<TimeStepConstraintCallback> const& time_step_constraints)
294{
295 bool all_process_steps_accepted = true;
296 // Get minimum time step size among step sizes of all processes.
297 NumLib::TimeIncrement dt{std::numeric_limits<double>::max()};
298 constexpr double eps = std::numeric_limits<double>::epsilon();
299
300 bool const is_initial_step =
301 std::any_of(_per_process_data.begin(), _per_process_data.end(),
302 [](auto const& ppd) -> bool
303 { return ppd->timestep_current.timeStepNumber() == 0; });
304
305 for (std::size_t i = 0; i < _per_process_data.size(); i++)
306 {
307 auto& ppd = *_per_process_data[i];
308 auto& timestep_algorithm = *ppd.timestep_algorithm.get();
309
310 auto const& x = *_process_solutions[i];
311 auto const& x_prev = *_process_solutions_prev[i];
312
313 const double solution_error =
314 computationOfChangeNeeded(timestep_algorithm, t)
316 x, x_prev,
317 ppd.conv_crit.get() ? ppd.conv_crit->getVectorNormType()
319 : 0.0;
320
321 ppd.timestep_current.setAccepted(
322 ppd.nonlinear_solver_status.error_norms_met);
323
324 auto const timestepper_dt = timestep_algorithm.next(
325 solution_error, ppd.nonlinear_solver_status.number_iterations,
326 ppd.timestep_previous, ppd.timestep_current);
327
328 if (!ppd.timestep_current.isAccepted())
329 {
330 // Not all processes have accepted steps.
331 all_process_steps_accepted = false;
332 }
333
334 if (!ppd.nonlinear_solver_status.error_norms_met)
335 {
336 WARN(
337 "Time step will be rejected due to nonlinear solver "
338 "divergence.");
339 all_process_steps_accepted = false;
340 }
341
342 if (timestepper_dt > eps || t < timestep_algorithm.end())
343 {
344 dt = NumLib::TimeIncrement{std::min(timestepper_dt, dt())};
345 }
346 }
347
348 if (all_process_steps_accepted)
349 {
351 }
352 else
353 {
355 }
356
357 bool last_step_rejected = false;
358 if (!is_initial_step)
359 {
360 if (all_process_steps_accepted)
361 {
362 accepted_steps++;
363 last_step_rejected = false;
364 }
365 else
366 {
367 if (t <= _end_time)
368 {
369 t -= prev_dt;
370 rejected_steps++;
371 last_step_rejected = true;
372 }
373 }
374 }
375
376 // adjust step size considering external communciation_point_calculators
377 for (auto const& time_step_constraint : time_step_constraints)
378 {
380 std::min(dt(), time_step_constraint(t, dt()))};
381 }
382
383 // Check whether the time stepping is stabilized
384 if (std::abs(dt() - prev_dt) < eps)
385 {
386 if (last_step_rejected)
387 {
388 OGS_FATAL(
389 "The new step size of {} is the same as that of the previous "
390 "rejected time step. \nPlease re-run ogs with a proper "
391 "adjustment in the numerical settings, \ne.g. those for time "
392 "stepper, local or global non-linear solver.",
393 dt);
394 }
395 else
396 {
397 DBUG("The time stepping is stabilized with the step size of {}.",
398 dt);
399 }
400 }
401
402 // Reset the time step with the minimum step size, dt
403 // Update the solution of the previous time step.
404 for (std::size_t i = 0; i < _per_process_data.size(); i++)
405 {
406 if (all_process_steps_accepted)
407 {
408 auto& ppd = *_per_process_data[i];
409 NumLib::updateTimeSteps(dt(), ppd.timestep_previous,
410 ppd.timestep_current);
411 }
412
413 auto& x = *_process_solutions[i];
414 auto& x_prev = *_process_solutions_prev[i];
415 if (all_process_steps_accepted)
416 {
417 MathLib::LinAlg::copy(x, x_prev); // pushState
418 }
419 else
420 {
421 if (t <= _end_time)
422 {
423 WARN(
424 "Time step {:d} was rejected {:d} times and it will be "
425 "repeated with a reduced step size.",
426 accepted_steps + 1, _repeating_times_of_rejected_step);
427 MathLib::LinAlg::copy(x_prev, x); // popState
428 }
429 }
430 }
431
432 return {dt, last_step_rejected};
433}
434
435std::vector<TimeLoop::TimeStepConstraintCallback>
437 std::vector<double>&& fixed_times) const
438{
439 std::vector<TimeStepConstraintCallback> const time_step_constraints{
440 [fixed_times = std::move(fixed_times)](NumLib::Time const& t, double dt)
441 { return NumLib::possiblyClampDtToNextFixedTime(t, dt, fixed_times); },
442 [this](NumLib::Time const& t, double dt) -> double
443 {
444 if (t < _end_time && _end_time < t + dt)
445 {
446 return _end_time() - t();
447 }
448 return dt;
449 }};
450 return time_step_constraints;
451}
452
455{
456 for (auto const& process_data : _per_process_data)
457 {
458 auto& pcs = process_data->process;
459 for (auto& output : _outputs)
460 {
461 output.addProcess(pcs);
462 }
463
464 setTimeDiscretizedODESystem(*process_data);
465
466 if (auto* conv_crit =
468 process_data->conv_crit.get()))
469 {
470 int const process_id = process_data->process_id;
471 conv_crit->setDOFTable(pcs.getDOFTable(process_id), pcs.getMesh());
472 }
473 }
474
475 // initial solution storage
478
480 {
481 _staggered_coupling->initializeCoupledSolutions(_process_solutions);
482 }
483
484 updateDeactivatedSubdomains(_per_process_data, _start_time());
485
486 auto const time_step_constraints = generateOutputTimeStepConstraints(
488
489 std::tie(_dt, _last_step_rejected) =
491 _rejected_steps, time_step_constraints);
492
493 // Output initial conditions
494 {
497 }
498
501}
502
504{
505 BaseLib::RunTime time_timestep;
506 time_timestep.start();
507
508 _current_time += _dt();
509
510 const std::size_t timesteps = _accepted_steps + 1;
511 // TODO(wenqing): , input option for time unit.
512 INFO("Time step #{:d} started. Time: {}. Step size: {}.", timesteps,
514
515 updateDeactivatedSubdomains(_per_process_data, _current_time());
516
519 INFO("[time] Time step #{:d} took {:g} s.", timesteps,
520 time_timestep.elapsed());
522}
523
525{
526 const double prev_dt = _dt();
527 // keep a copy of _current_time to check if a new point in time is computed
528 auto const current_time = _current_time;
529
530 const std::size_t timesteps = _accepted_steps + 1;
531
532 auto const time_step_constraints = generateOutputTimeStepConstraints(
534
535 // _last_step_rejected is also checked in computeTimeStepping.
536 std::tie(_dt, _last_step_rejected) =
538 _rejected_steps, time_step_constraints);
539
541 {
542 outputSolutions(timesteps, current_time(), &Output::doOutput);
543 }
544
545 // check if the newly computed time point (=_current_time + _dt()) differs
546 // from the previously computed time point (current_time) saved at the
547 // beginning of the method
548 if (current_time == (_current_time + _dt()))
549 {
550 DBUG("current time == previous time + dt : {:a} == {:a} + {:a} = {:a}",
551 current_time(), _current_time(), _dt(), _current_time() + _dt());
552 ERR("The time increment {} results in exactly the same time {} as the "
553 "last rejected time step.\n"
554 "Time stepping stops at time step {:d} and time {}.",
555 _dt, current_time, timesteps, _current_time);
556 return false;
557 }
558
560 {
561 return false;
562 }
563
564 return true;
565}
566
568{
569 INFO(
570 "The whole computation of the time stepping took {:d} steps, in which\n"
571 "\t the accepted steps are {:d}, and the rejected steps are {:d}.\n",
573
574 // output last time step
576 {
579 }
580}
581
583 std::size_t const timesteps)
584{
586
587 NumLib::NonlinearSolverStatus nonlinear_solver_status;
588
590 {
591 nonlinear_solver_status =
593 }
594 else
595 {
596 nonlinear_solver_status =
597 solveUncoupledEquationSystems(t, dt, timesteps);
598 }
599
600 // Run post time step only if the last iteration was successful.
601 // Otherwise it runs the risks to get the same errors as in the last
602 // iteration, an exception thrown in assembly, for example.
603 if (nonlinear_solver_status.error_norms_met)
604 {
605 // Later on, the timestep_algorithm might reject the timestep. We assume
606 // that this is a rare case, so still, we call preOutput() here. We
607 // don't expect a large overhead from it.
608 preOutputForAllProcesses(timesteps, t, dt, _end_time, _per_process_data,
610 _outputs);
611
615 }
616 return nonlinear_solver_status.error_norms_met;
617}
618
620 const NumLib::Time& t, const double dt, const std::size_t timestep_id,
621 ProcessData const& process_data, std::vector<GlobalVector*>& x,
622 std::vector<GlobalVector*> const& x_prev,
623 std::vector<Output> const& outputs)
624{
625 BaseLib::RunTime time_timestep_process;
626 time_timestep_process.start();
627
628 INFO("Solving process #{:d} started.", process_data.process_id);
629
630 auto const nonlinear_solver_status = solveOneTimeStepOneProcess(
631 x, x_prev, timestep_id, t(), dt, process_data, outputs);
632
633 INFO("[time] Solving process #{:d} took {:g} s in time step #{:d}",
634 process_data.process_id, time_timestep_process.elapsed(), timestep_id);
635
636 return nonlinear_solver_status;
637}
638
639static constexpr std::string_view timestepper_cannot_reduce_dt =
640 "Time stepper cannot reduce the time step size further.";
641
643 const NumLib::Time& t, const double dt, const std::size_t timestep_id)
644{
645 NumLib::NonlinearSolverStatus nonlinear_solver_status;
646
647 for (auto const& process_data : _per_process_data)
648 {
649 auto const process_id = process_data->process_id;
650 nonlinear_solver_status = solveMonolithicProcess(
651 t, dt, timestep_id, *process_data, _process_solutions,
653
654 process_data->nonlinear_solver_status = nonlinear_solver_status;
655 if (!nonlinear_solver_status.error_norms_met)
656 {
657 ERR("The nonlinear solver failed in time step #{:d} at t = {} s "
658 "for process #{:d}.",
659 timestep_id, t, process_id);
660
661 if (!process_data->timestep_algorithm->canReduceTimestepSize(
662 process_data->timestep_current,
663 process_data->timestep_previous))
664 {
665 // save unsuccessful solution
666 for (auto const& output : _outputs)
667 {
668 output.doOutputAlways(
669 process_data->process, process_id, timestep_id, t,
670 process_data->nonlinear_solver_status.number_iterations,
671 process_data->nonlinear_solver_status.error_norms_met,
673 }
675 }
676
677 return nonlinear_solver_status;
678 }
679 }
680
681 return nonlinear_solver_status;
682}
683
686 const NumLib::Time& t, const double dt, const std::size_t timestep_id)
687{
688 auto const nonlinear_solver_status =
690 t(), dt, timestep_id, _process_solutions, _process_solutions_prev,
692
693 _last_step_rejected = nonlinear_solver_status.error_norms_met;
694
695 for (auto const& process_data : _per_process_data)
696 {
697 auto& pcs = process_data->process;
698 int const process_id = process_data->process_id;
699 auto& ode_sys = *process_data->tdisc_ode_sys;
700 pcs.solveReactionEquation(_process_solutions, _process_solutions_prev,
701 t(), dt, ode_sys, process_id);
702 }
703
704 return nonlinear_solver_status;
705}
706
707template <typename OutputClassMember>
708void TimeLoop::outputSolutions(unsigned timestep, const double t,
709 OutputClassMember output_class_member) const
710{
711 for (auto const& process_data : _per_process_data)
712 {
713 // If nonlinear solver diverged, the solution has already been
714 // saved.
715 if (!process_data->nonlinear_solver_status.error_norms_met)
716 {
717 continue;
718 }
719
720 auto const process_id = process_data->process_id;
721 auto const& pcs = process_data->process;
722
723 for (auto const& output_object : _outputs)
724 {
725 (output_object.*output_class_member)(
726 pcs, process_id, timestep, NumLib::Time(t),
727 process_data->nonlinear_solver_status.number_iterations,
728 process_data->nonlinear_solver_status.error_norms_met,
730 }
731 }
732}
733
735{
736 for (auto* x : _process_solutions)
737 {
739 }
740 for (auto* x : _process_solutions_prev)
741 {
743 }
744}
745
747 const double dt) const
748{
749 for (auto const& process_data : _per_process_data)
750 {
751 // If nonlinear solver diverged, the solution has already been
752 // saved.
753 if (!process_data->nonlinear_solver_status.error_norms_met)
754 {
755 continue;
756 }
757
758 auto const process_id = process_data->process_id;
759 auto& pcs = process_data->process;
760
761 process_data->time_disc->nextTimestep(t(), dt);
762
763 pcs.preTimestep(_process_solutions, _start_time(), dt, process_id);
764
765 pcs.preOutput(_start_time(), dt, _process_solutions,
766 _process_solutions_prev, process_id);
767
768 // Update secondary variables, which might be uninitialized, before
769 // output.
770 pcs.computeSecondaryVariable(_start_time(), dt, _process_solutions,
771 *_process_solutions_prev[process_id],
772 process_id);
773 }
774}
775} // namespace ProcessLib
#define OGS_FATAL(...)
Definition Error.h:19
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:28
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:22
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:34
Count the running time.
Definition RunTime.h:18
double elapsed() const
Get the elapsed time in seconds.
Definition RunTime.h:31
void start()
Start the timer.
Definition RunTime.h:21
Interface of time stepping algorithms.
Time begin() const
return the beginning of time steps
virtual bool isSolutionErrorComputationNeeded() const
void doOutput(Process const &process, const int process_id, int const timestep, const NumLib::Time &t, int const iteration, bool const converged, std::vector< GlobalVector * > const &xs) const
void doOutputLastTimestep(Process const &process, const int process_id, int const timestep, const NumLib::Time &t, int const iteration, bool const converged, std::vector< GlobalVector * > const &xs) const
NumLib::NonlinearSolverStatus solveUncoupledEquationSystems(const NumLib::Time &t, const double dt, const std::size_t timestep_id)
Member to solver non coupled systems of equations, which can be a single system of equations,...
Definition TimeLoop.cpp:642
void outputLastTimeStep() const
Definition TimeLoop.cpp:567
void preOutputInitialConditions(NumLib::Time const &t, const double dt) const
Definition TimeLoop.cpp:746
NumLib::TimeIncrement _dt
Definition TimeLoop.h:133
NumLib::Time _current_time
Definition TimeLoop.h:130
std::pair< NumLib::TimeIncrement, bool > computeTimeStepping(const double prev_dt, NumLib::Time &t, std::size_t &accepted_steps, std::size_t &rejected_steps, std::vector< TimeStepConstraintCallback > const &time_step_constraints)
Definition TimeLoop.cpp:290
TimeLoop(std::vector< Output > &&outputs, std::vector< std::unique_ptr< ProcessData > > &&per_process_data, std::unique_ptr< NumLib::StaggeredCoupling > &&staggered_coupling, const NumLib::Time &start_time, const NumLib::Time &end_time)
Definition TimeLoop.cpp:264
std::vector< std::unique_ptr< ProcessData > > _per_process_data
Definition TimeLoop.h:126
void outputSolutions(unsigned timestep, const double t, OutputClassMember output_class_member) const
Definition TimeLoop.cpp:708
std::vector< Output > _outputs
Definition TimeLoop.h:125
std::size_t _accepted_steps
Definition TimeLoop.h:131
std::vector< GlobalVector * > _process_solutions
Definition TimeLoop.h:123
std::unique_ptr< NumLib::StaggeredCoupling > _staggered_coupling
Definition TimeLoop.h:137
void initialize()
initialize output, convergence criterion, etc.
Definition TimeLoop.cpp:454
int _repeating_times_of_rejected_step
Definition TimeLoop.h:134
std::size_t _rejected_steps
Definition TimeLoop.h:132
const NumLib::Time _end_time
Definition TimeLoop.h:129
bool preTsNonlinearSolvePostTs(NumLib::Time const &t, double const dt, std::size_t const timesteps)
Definition TimeLoop.cpp:582
NumLib::NonlinearSolverStatus solveCoupledEquationSystemsByStaggeredScheme(const NumLib::Time &t, const double dt, const std::size_t timestep_id)
Member to solver coupled systems of equations by the staggered scheme.
Definition TimeLoop.cpp:685
std::vector< TimeStepConstraintCallback > generateOutputTimeStepConstraints(std::vector< double > &&fixed_times) const
Definition TimeLoop.cpp:436
const NumLib::Time _start_time
Definition TimeLoop.h:128
std::vector< GlobalVector * > _process_solutions_prev
Definition TimeLoop.h:124
NonlinearSolverTag
Tag used to specify which nonlinear solver will be used.
Definition Types.h:13
void copy(PETScVector const &x, PETScVector &y)
Definition LinAlg.cpp:30
double computeRelativeNorm(VectorType const &x, VectorType const &y, MathLib::VecNormType norm_type)
Definition LinAlg.h:292
void updateTimeSteps(double const dt, TimeStep &previous_timestep, TimeStep &current_timestep)
Definition TimeStep.h:101
double possiblyClampDtToNextFixedTime(Time const &t, double const dt, std::vector< double > const &fixed_output_times)
static constexpr std::string_view timestepper_cannot_reduce_dt
Definition TimeLoop.cpp:639
void setTimeDiscretizedODESystem(ProcessData &process_data, NumLib::ODESystem< ODETag, NumLib::NonlinearSolverTag::Picard > &ode_sys)
Definition TimeLoop.cpp:107
void calculateNonEquilibriumInitialResiduum(std::vector< std::unique_ptr< ProcessData > > const &per_process_data, std::vector< GlobalVector * > const &process_solutions, std::vector< GlobalVector * > const &process_solutions_prev)
Definition TimeLoop.cpp:201
bool computationOfChangeNeeded(NumLib::TimeStepAlgorithm const &timestep_algorithm, NumLib::Time const &time)
Definition TimeLoop.cpp:277
NumLib::NonlinearSolverStatus solveOneTimeStepOneProcess(std::vector< GlobalVector * > &x, std::vector< GlobalVector * > const &x_prev, std::size_t const timestep, double const t, double const delta_t, ProcessData const &process_data, std::vector< Output > const &outputs)
Definition TimeLoop.cpp:217
void preTimestepForAllProcesses(NumLib::Time const &t, double const dt, std::vector< std::unique_ptr< ProcessData > > const &per_process_data, std::vector< GlobalVector * > const &_process_solutions)
Definition TimeLoop.cpp:74
void postTimestepForAllProcesses(NumLib::Time const &t, double const dt, std::vector< std::unique_ptr< ProcessData > > const &per_process_data, std::vector< GlobalVector * > const &process_solutions, std::vector< GlobalVector * > const &process_solutions_prev)
Definition TimeLoop.cpp:87
std::pair< std::vector< GlobalVector * >, std::vector< GlobalVector * > > setInitialConditions(NumLib::Time const &t0, std::vector< std::unique_ptr< ProcessData > > const &per_process_data)
Definition TimeLoop.cpp:166
void setEquationSystem(ProcessData const &process_data)
std::vector< double > calculateUniqueFixedTimesForAllOutputs(std::vector< Output > const &outputs)
static NumLib::NonlinearSolverStatus solveMonolithicProcess(const NumLib::Time &t, const double dt, const std::size_t timestep_id, ProcessData const &process_data, std::vector< GlobalVector * > &x, std::vector< GlobalVector * > const &x_prev, std::vector< Output > const &outputs)
Definition TimeLoop.cpp:619
void preOutputForAllProcesses(int const timestep, NumLib::Time const &t, double const dt, const NumLib::Time &end_time, std::vector< std::unique_ptr< ProcessLib::ProcessData > > const &per_process_data, std::vector< GlobalVector * > const &process_solutions, std::vector< GlobalVector * > const &process_solutions_prev, std::vector< ProcessLib::Output > const &outputs)
Definition TimeLoop.cpp:47
bool isOutputStep(std::vector< ProcessLib::Output > const &outputs, const int timestep, const NumLib::Time &t, const NumLib::Time &end_time)
Definition TimeLoop.cpp:33
void updateDeactivatedSubdomains(std::vector< std::unique_ptr< ProcessLib::ProcessData > > const &per_process_data, double const t)
Definition TimeLoop.cpp:21
static NUMLIB_EXPORT VectorProvider & provider
Status of the non-linear solver.
std::unique_ptr< NumLib::TimeDiscretization > time_disc
Definition ProcessData.h:55
NumLib::NonlinearSolverBase & nonlinear_solver
Definition ProcessData.h:51
std::unique_ptr< NumLib::EquationSystem > tdisc_ode_sys
type-erased time-discretized ODE system
Definition ProcessData.h:57