13#include <range/v3/algorithm/any_of.hpp>
14#include <range/v3/algorithm/contains.hpp>
29 std::vector<std::unique_ptr<ProcessLib::ProcessData>>
const&
33 for (
auto& process_data : per_process_data)
35 process_data->process.updateDeactivatedSubdomains(
36 t, process_data->process_id);
50 return ranges::any_of(outputs, [timestep, t](
auto const& output)
51 {
return output.isOutputStep(timestep, t); });
55 int const timestep,
NumLib::Time const& t,
double const dt,
57 std::vector<std::unique_ptr<ProcessLib::ProcessData>>
const&
59 std::vector<GlobalVector*>
const& process_solutions,
60 std::vector<GlobalVector*>
const& process_solutions_prev,
61 std::vector<ProcessLib::Output>
const& outputs)
68 for (
auto& process_data : per_process_data)
70 auto const process_id = process_data->process_id;
71 auto& pcs = process_data->process;
73 pcs.preOutput(t(), dt, process_solutions, process_solutions_prev,
83 std::vector<std::unique_ptr<ProcessData>>
const& per_process_data,
84 std::vector<GlobalVector*>
const& _process_solutions)
86 for (
auto& process_data : per_process_data)
88 auto const process_id = process_data->process_id;
89 auto& pcs = process_data->process;
90 pcs.preTimestep(_process_solutions, t(), dt, process_id);
96 std::vector<std::unique_ptr<ProcessData>>
const& per_process_data,
97 std::vector<GlobalVector*>
const& process_solutions,
98 std::vector<GlobalVector*>
const& process_solutions_prev)
100 for (
auto& process_data : per_process_data)
102 auto const process_id = process_data->process_id;
103 auto& pcs = process_data->process;
105 pcs.computeSecondaryVariable(t(), dt, process_solutions,
106 *process_solutions_prev[process_id],
108 pcs.postTimestep(process_solutions, process_solutions_prev, t(), dt,
113template <NumLib::ODESystemTag ODETag>
137 else if ((
dynamic_cast<NonlinearSolverNewton*
>(
148 if (
auto* ode_newton =
dynamic_cast<ODENewton*
>(&ode_sys))
157 "You are trying to solve a non-Newton-ready ODE with the"
158 " Newton-Raphson method. Aborting");
163 OGS_FATAL(
"Encountered unknown nonlinear solver type. Aborting");
172std::pair<std::vector<GlobalVector*>, std::vector<GlobalVector*>>
175 std::vector<std::unique_ptr<ProcessData>>
const& per_process_data)
177 std::vector<GlobalVector*> process_solutions;
178 std::vector<GlobalVector*> process_solutions_prev;
180 for (
auto const& process_data : per_process_data)
182 auto const process_id = process_data->process_id;
183 auto& ode_sys = *process_data->tdisc_ode_sys;
186 process_solutions.emplace_back(
188 ode_sys.getMatrixSpecifications(process_id)));
189 process_solutions_prev.emplace_back(
191 ode_sys.getMatrixSpecifications(process_id)));
194 for (
auto const& process_data : per_process_data)
196 auto& pcs = process_data->process;
197 auto const process_id = process_data->process_id;
198 pcs.setInitialConditions(process_solutions, process_solutions_prev,
201 auto& time_disc = *process_data->time_disc;
202 time_disc.setInitialState(t0());
205 return {process_solutions, process_solutions_prev};
209 std::vector<std::unique_ptr<ProcessData>>
const& per_process_data,
210 std::vector<GlobalVector*>
const& process_solutions,
211 std::vector<GlobalVector*>
const& process_solutions_prev)
213 for (
auto const& process_data : per_process_data)
215 auto& nonlinear_solver = process_data->nonlinear_solver;
218 nonlinear_solver.calculateNonEquilibriumInitialResiduum(
219 process_solutions, process_solutions_prev,
220 process_data->process_id);
225 std::vector<GlobalVector*>& x, std::vector<GlobalVector*>
const& x_prev,
226 std::size_t
const timestep,
double const t,
double const delta_t,
227 ProcessData const& process_data, std::vector<Output>
const& outputs)
229 auto& process = process_data.
process;
230 int const process_id = process_data.
process_id;
231 auto& time_disc = *process_data.
time_disc;
241 time_disc.nextTimestep(t, delta_t);
243 auto const post_iteration_callback =
244 [&](
int const iteration,
bool const converged,
245 std::vector<GlobalVector*>
const& x)
250 for (
auto const& output : outputs)
252 output.doOutputNonlinearIteration(process, process_id, timestep,
258 auto const nonlinear_solver_status =
259 nonlinear_solver.solve(x, x_prev, post_iteration_callback, process_id);
261 if (!nonlinear_solver_status.error_norms_met)
263 return nonlinear_solver_status;
266 process.postNonLinearSolver(x, x_prev, t, delta_t, process_id);
268 return nonlinear_solver_status;
272 std::vector<Output>&& outputs,
273 std::vector<std::unique_ptr<ProcessData>>&& per_process_data,
274 std::unique_ptr<NumLib::StaggeredCoupling>&& staggered_coupling,
276 : _outputs{std::move(outputs)},
277 _per_process_data(std::move(per_process_data)),
278 _start_time(start_time),
280 _staggered_coupling(std::move(staggered_coupling))
290 if (time == timestep_algorithm.
begin())
298 const double prev_dt,
NumLib::Time& t, std::size_t& accepted_steps,
299 std::size_t& rejected_steps,
300 std::vector<TimeStepConstraintCallback>
const& time_step_constraints)
302 bool all_process_steps_accepted =
true;
305 constexpr double eps = std::numeric_limits<double>::epsilon();
307 bool const is_initial_step =
309 [](
auto const& ppd) ->
bool
310 { return ppd->timestep_current.timeStepNumber() == 0; });
315 auto& timestep_algorithm = *ppd.timestep_algorithm.get();
320 const double solution_error =
324 ppd.conv_crit.get() ? ppd.conv_crit->getVectorNormType()
328 ppd.timestep_current.setAccepted(
329 ppd.nonlinear_solver_status.error_norms_met);
331 auto [previous_step_accepted, timestepper_dt] = timestep_algorithm.next(
332 solution_error, ppd.nonlinear_solver_status.number_iterations,
333 ppd.timestep_previous, ppd.timestep_current);
335 if (!previous_step_accepted)
338 all_process_steps_accepted =
false;
341 if (!ppd.nonlinear_solver_status.error_norms_met)
344 "Time step will be rejected due to nonlinear solver "
346 all_process_steps_accepted =
false;
349 if (timestepper_dt > eps || t < timestep_algorithm.end())
355 if (all_process_steps_accepted)
364 bool last_step_rejected =
false;
365 if (!is_initial_step)
367 if (all_process_steps_accepted)
370 last_step_rejected =
false;
378 last_step_rejected =
true;
384 for (
auto const& time_step_constraint : time_step_constraints)
387 std::min(dt(), time_step_constraint(t, dt()))};
391 if (std::abs(dt() - prev_dt) < eps)
393 if (last_step_rejected)
396 "The new step size of {} is the same as that of the previous "
397 "rejected time step. \nPlease re-run ogs with a proper "
398 "adjustment in the numerical settings, \ne.g. those for time "
399 "stepper, local or global non-linear solver.",
404 DBUG(
"The time stepping is stabilized with the step size of {}.",
413 if (all_process_steps_accepted)
417 ppd.timestep_current);
418 auto& timestep_algorithm = ppd.timestep_algorithm;
419 timestep_algorithm->resetCurrentTimeStep(
420 dt(), ppd.timestep_previous, ppd.timestep_current);
425 if (all_process_steps_accepted)
434 "Time step {:d} was rejected {:d} times and it will be "
435 "repeated with a reduced step size.",
442 return {dt, last_step_rejected};
445std::vector<TimeLoop::TimeStepConstraintCallback>
447 std::vector<double>&& fixed_times)
const
449 std::vector<TimeStepConstraintCallback>
const time_step_constraints{
450 [fixed_times = std::move(fixed_times)](
NumLib::Time const& t,
double dt)
460 return time_step_constraints;
468 auto& pcs = process_data->process;
471 output.addProcess(pcs);
476 if (
auto* conv_crit =
478 process_data->conv_crit.get()))
480 int const process_id = process_data->process_id;
481 conv_crit->setDOFTable(pcs.getDOFTable(process_id), pcs.getMesh());
516 time_timestep.
start();
522 INFO(
"=== Time stepping at step #{:d} and time {} with step size {}",
529 INFO(
"[time] Time step #{:d} took {:g} s.", timesteps,
536 const double prev_dt =
_dt();
556 ERR(
"Time step size of {} is too small.\n"
557 "Time stepping stops at step {:d} and at time of {}.",
573 "The whole computation of the time stepping took {:d} steps, in which\n"
574 "\t the accepted steps are {:d}, and the rejected steps are {:d}.\n",
586 std::size_t
const timesteps)
594 nonlinear_solver_status =
599 nonlinear_solver_status =
623 const NumLib::Time& t,
const double dt,
const std::size_t timestep_id,
624 ProcessData const& process_data, std::vector<GlobalVector*>& x,
625 std::vector<GlobalVector*>
const& x_prev,
626 std::vector<Output>
const& outputs)
629 time_timestep_process.
start();
632 x, x_prev, timestep_id, t(), dt, process_data, outputs);
634 INFO(
"[time] Solving process #{:d} took {:g} s in time step #{:d}",
637 return nonlinear_solver_status;
641 "Time stepper cannot reduce the time step size further.";
644 const NumLib::Time& t,
const double dt,
const std::size_t timestep_id)
650 auto const process_id = process_data->process_id;
655 process_data->nonlinear_solver_status = nonlinear_solver_status;
658 ERR(
"The nonlinear solver failed in time step #{:d} at t = {} s "
659 "for process #{:d}.",
660 timestep_id, t, process_id);
662 if (!process_data->timestep_algorithm->canReduceTimestepSize(
663 process_data->timestep_current,
664 process_data->timestep_previous))
669 output.doOutputAlways(
670 process_data->process, process_id, timestep_id, t,
671 process_data->nonlinear_solver_status.number_iterations,
672 process_data->nonlinear_solver_status.error_norms_met,
678 return nonlinear_solver_status;
682 return nonlinear_solver_status;
687 const NumLib::Time& t,
const double dt,
const std::size_t timestep_id)
689 auto const nonlinear_solver_status =
699 auto& pcs = process_data->process;
700 int const process_id = process_data->process_id;
701 auto& ode_sys = *process_data->tdisc_ode_sys;
708 return nonlinear_solver_status;
711template <
typename OutputClassMember>
713 OutputClassMember output_class_member)
const
719 if (!process_data->nonlinear_solver_status.error_norms_met)
724 auto const process_id = process_data->process_id;
725 auto const& pcs = process_data->process;
727 for (
auto const& output_object :
_outputs)
729 (output_object.*output_class_member)(
731 process_data->nonlinear_solver_status.number_iterations,
732 process_data->nonlinear_solver_status.error_norms_met,
751 const double dt)
const
757 if (!process_data->nonlinear_solver_status.error_norms_met)
762 auto const process_id = process_data->process_id;
763 auto& pcs = process_data->process;
765 process_data->time_disc->nextTimestep(t(), dt);
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition of the RunTime class.
double elapsed() const
Get the elapsed time in seconds.
void start()
Start the timer.
Interface of time stepping algorithms.
Time begin() const
return the beginning of time steps
virtual bool isSolutionErrorComputationNeeded() const
virtual void releaseVector(GlobalVector const &x)=0
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,...
void outputLastTimeStep() const
void preOutputInitialConditions(NumLib::Time const &t, const double dt) const
NumLib::TimeIncrement _dt
NumLib::Time _current_time
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)
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)
std::vector< std::unique_ptr< ProcessData > > _per_process_data
void outputSolutions(unsigned timestep, const double t, OutputClassMember output_class_member) const
std::vector< Output > _outputs
std::size_t _accepted_steps
bool successful_time_step
std::vector< GlobalVector * > _process_solutions
std::unique_ptr< NumLib::StaggeredCoupling > _staggered_coupling
void initialize()
initialize output, convergence criterion, etc.
int _repeating_times_of_rejected_step
std::size_t _rejected_steps
bool calculateNextTimeStep()
const NumLib::Time _end_time
bool preTsNonlinearSolvePostTs(NumLib::Time const &t, double const dt, std::size_t const timesteps)
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.
std::vector< TimeStepConstraintCallback > generateOutputTimeStepConstraints(std::vector< double > &&fixed_times) const
const NumLib::Time _start_time
std::vector< GlobalVector * > _process_solutions_prev
NonlinearSolverTag
Tag used to specify which nonlinear solver will be used.
void copy(PETScVector const &x, PETScVector &y)
double computeRelativeNorm(VectorType const &x, VectorType const &y, MathLib::VecNormType norm_type)
void updateTimeSteps(double const dt, TimeStep &previous_timestep, TimeStep ¤t_timestep)
double possiblyClampDtToNextFixedTime(Time const &t, double const dt, std::vector< double > const &fixed_output_times)
static constexpr std::string_view timestepper_cannot_reduce_dt
void setTimeDiscretizedODESystem(ProcessData &process_data, NumLib::ODESystem< ODETag, NumLib::NonlinearSolverTag::Picard > &ode_sys)
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)
bool computationOfChangeNeeded(NumLib::TimeStepAlgorithm const ×tep_algorithm, NumLib::Time const &time)
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)
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)
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)
std::pair< std::vector< GlobalVector * >, std::vector< GlobalVector * > > setInitialConditions(NumLib::Time const &t0, std::vector< std::unique_ptr< ProcessData > > const &per_process_data)
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)
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)
bool isOutputStep(std::vector< ProcessLib::Output > const &outputs, const int timestep, const NumLib::Time &t, const NumLib::Time &end_time)
void updateDeactivatedSubdomains(std::vector< std::unique_ptr< ProcessLib::ProcessData > > const &per_process_data, double const t)
static NUMLIB_EXPORT VectorProvider & provider
Status of the non-linear solver.
std::unique_ptr< NumLib::TimeDiscretization > time_disc
NumLib::NonlinearSolverBase & nonlinear_solver
std::unique_ptr< NumLib::EquationSystem > tdisc_ode_sys
type-erased time-discretized ODE system