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