6#include <range/v3/algorithm/any_of.hpp>
7#include <range/v3/algorithm/contains.hpp>
22 std::vector<std::unique_ptr<ProcessLib::ProcessData>>
const&
26 for (
auto& process_data : per_process_data)
28 process_data->process.updateDeactivatedSubdomains(
29 t, process_data->process_id);
43 return ranges::any_of(outputs, [timestep, t](
auto const& output)
44 {
return output.isOutputStep(timestep, t); });
48 int const timestep,
NumLib::Time const& t,
double const dt,
50 std::vector<std::unique_ptr<ProcessLib::ProcessData>>
const&
52 std::vector<GlobalVector*>
const& process_solutions,
53 std::vector<GlobalVector*>
const& process_solutions_prev,
54 std::vector<ProcessLib::Output>
const& outputs)
61 for (
auto& process_data : per_process_data)
63 auto const process_id = process_data->process_id;
64 auto& pcs = process_data->process;
66 pcs.preOutput(t(), dt, process_solutions, process_solutions_prev,
76 std::vector<std::unique_ptr<ProcessData>>
const& per_process_data,
77 std::vector<GlobalVector*>
const& _process_solutions)
79 for (
auto& process_data : per_process_data)
81 auto const process_id = process_data->process_id;
82 auto& pcs = process_data->process;
83 pcs.preTimestep(_process_solutions, t(), dt, process_id);
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)
93 for (
auto& process_data : per_process_data)
95 auto const process_id = process_data->process_id;
96 auto& pcs = process_data->process;
98 pcs.computeSecondaryVariable(t(), dt, process_solutions,
99 *process_solutions_prev[process_id],
101 pcs.postTimestep(process_solutions, process_solutions_prev, t(), dt,
106template <NumLib::ODESystemTag ODETag>
130 else if ((
dynamic_cast<NonlinearSolverNewton*
>(
141 if (
auto* ode_newton =
dynamic_cast<ODENewton*
>(&ode_sys))
150 "You are trying to solve a non-Newton-ready ODE with the"
151 " Newton-Raphson method. Aborting");
156 OGS_FATAL(
"Encountered unknown nonlinear solver type. Aborting");
165std::pair<std::vector<GlobalVector*>, std::vector<GlobalVector*>>
168 std::vector<std::unique_ptr<ProcessData>>
const& per_process_data)
170 std::vector<GlobalVector*> process_solutions;
171 std::vector<GlobalVector*> process_solutions_prev;
173 for (
auto const& process_data : per_process_data)
175 auto const process_id = process_data->process_id;
176 auto& ode_sys = *process_data->tdisc_ode_sys;
179 process_solutions.emplace_back(
181 ode_sys.getMatrixSpecifications(process_id)));
182 process_solutions_prev.emplace_back(
184 ode_sys.getMatrixSpecifications(process_id)));
187 for (
auto const& process_data : per_process_data)
189 auto& pcs = process_data->process;
190 auto const process_id = process_data->process_id;
191 pcs.setInitialConditions(process_solutions, process_solutions_prev,
194 auto& time_disc = *process_data->time_disc;
195 time_disc.setInitialState(t0());
198 return {process_solutions, process_solutions_prev};
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)
206 for (
auto const& process_data : per_process_data)
208 auto& nonlinear_solver = process_data->nonlinear_solver;
211 nonlinear_solver.calculateNonEquilibriumInitialResiduum(
212 process_solutions, process_solutions_prev,
213 process_data->process_id);
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)
222 auto& process = process_data.
process;
223 int const process_id = process_data.
process_id;
224 auto& time_disc = *process_data.
time_disc;
234 time_disc.nextTimestep(t, delta_t);
236 auto const post_iteration_callback =
237 [&](
int const iteration,
bool const converged,
238 std::vector<GlobalVector*>
const& x)
243 for (
auto const& output : outputs)
245 output.doOutputNonlinearIteration(process, process_id, timestep,
251 auto const nonlinear_solver_status =
252 nonlinear_solver.solve(x, x_prev, post_iteration_callback, process_id);
254 if (!nonlinear_solver_status.error_norms_met)
256 return nonlinear_solver_status;
259 process.postNonLinearSolver(x, x_prev, t, delta_t, process_id);
261 return nonlinear_solver_status;
265 std::vector<Output>&& outputs,
266 std::vector<std::unique_ptr<ProcessData>>&& per_process_data,
267 std::unique_ptr<NumLib::StaggeredCoupling>&& staggered_coupling,
283 if (time == timestep_algorithm.
begin())
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)
295 bool all_process_steps_accepted =
true;
298 constexpr double eps = std::numeric_limits<double>::epsilon();
300 bool const is_initial_step =
302 [](
auto const& ppd) ->
bool
303 { return ppd->timestep_current.timeStepNumber() == 0; });
308 auto& timestep_algorithm = *ppd.timestep_algorithm.get();
313 const double solution_error =
317 ppd.conv_crit.get() ? ppd.conv_crit->getVectorNormType()
321 ppd.timestep_current.setAccepted(
322 ppd.nonlinear_solver_status.error_norms_met);
324 auto const timestepper_dt = timestep_algorithm.next(
325 solution_error, ppd.nonlinear_solver_status.number_iterations,
326 ppd.timestep_previous, ppd.timestep_current);
328 if (!ppd.timestep_current.isAccepted())
331 all_process_steps_accepted =
false;
334 if (!ppd.nonlinear_solver_status.error_norms_met)
337 "Time step will be rejected due to nonlinear solver "
339 all_process_steps_accepted =
false;
342 if (timestepper_dt > eps || t < timestep_algorithm.end())
348 if (all_process_steps_accepted)
357 bool last_step_rejected =
false;
358 if (!is_initial_step)
360 if (all_process_steps_accepted)
363 last_step_rejected =
false;
371 last_step_rejected =
true;
377 for (
auto const& time_step_constraint : time_step_constraints)
380 std::min(dt(), time_step_constraint(t, dt()))};
384 if (std::abs(dt() - prev_dt) < eps)
386 if (last_step_rejected)
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.",
397 DBUG(
"The time stepping is stabilized with the step size of {}.",
406 if (all_process_steps_accepted)
410 ppd.timestep_current);
415 if (all_process_steps_accepted)
424 "Time step {:d} was rejected {:d} times and it will be "
425 "repeated with a reduced step size.",
432 return {dt, last_step_rejected};
435std::vector<TimeLoop::TimeStepConstraintCallback>
437 std::vector<double>&& fixed_times)
const
439 std::vector<TimeStepConstraintCallback>
const time_step_constraints{
440 [fixed_times = std::move(fixed_times)](
NumLib::Time const& t,
double dt)
450 return time_step_constraints;
458 auto& pcs = process_data->process;
461 output.addProcess(pcs);
466 if (
auto* conv_crit =
468 process_data->conv_crit.get()))
470 int const process_id = process_data->process_id;
471 conv_crit->setDOFTable(pcs.getDOFTable(process_id), pcs.getMesh());
506 time_timestep.
start();
512 INFO(
"Time step #{:d} started. Time: {}. Step size: {}.", timesteps,
519 INFO(
"[time] Time step #{:d} took {:g} s.", timesteps,
526 const double prev_dt =
_dt();
550 DBUG(
"current time == previous time + dt : {:a} == {:a} + {:a} = {:a}",
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 {}.",
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",
583 std::size_t
const timesteps)
591 nonlinear_solver_status =
596 nonlinear_solver_status =
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)
626 time_timestep_process.
start();
631 x, x_prev, timestep_id, t(), dt, process_data, outputs);
633 INFO(
"[time] Solving process #{:d} took {:g} s in time step #{:d}",
636 return nonlinear_solver_status;
640 "Time stepper cannot reduce the time step size further.";
643 const NumLib::Time& t,
const double dt,
const std::size_t timestep_id)
649 auto const process_id = process_data->process_id;
654 process_data->nonlinear_solver_status = nonlinear_solver_status;
657 ERR(
"The nonlinear solver failed in time step #{:d} at t = {} s "
658 "for process #{:d}.",
659 timestep_id, t, process_id);
661 if (!process_data->timestep_algorithm->canReduceTimestepSize(
662 process_data->timestep_current,
663 process_data->timestep_previous))
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,
677 return nonlinear_solver_status;
681 return nonlinear_solver_status;
686 const NumLib::Time& t,
const double dt,
const std::size_t timestep_id)
688 auto const nonlinear_solver_status =
697 auto& pcs = process_data->process;
698 int const process_id = process_data->process_id;
699 auto& ode_sys = *process_data->tdisc_ode_sys;
701 t(), dt, ode_sys, process_id);
704 return nonlinear_solver_status;
707template <
typename OutputClassMember>
709 OutputClassMember output_class_member)
const
715 if (!process_data->nonlinear_solver_status.error_norms_met)
720 auto const process_id = process_data->process_id;
721 auto const& pcs = process_data->process;
723 for (
auto const& output_object :
_outputs)
725 (output_object.*output_class_member)(
727 process_data->nonlinear_solver_status.number_iterations,
728 process_data->nonlinear_solver_status.error_norms_met,
747 const double dt)
const
753 if (!process_data->nonlinear_solver_status.error_norms_met)
758 auto const process_id = process_data->process_id;
759 auto& pcs = process_data->process;
761 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)
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
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