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 iteration, std::vector<GlobalVector*>
const& x)
249 for (
auto const& output : outputs)
251 output.doOutputNonlinearIteration(process, process_id, timestep,
256 auto const nonlinear_solver_status =
257 nonlinear_solver.solve(x, x_prev, post_iteration_callback, process_id);
259 if (!nonlinear_solver_status.error_norms_met)
261 return nonlinear_solver_status;
264 process.postNonLinearSolver(x, x_prev, t, delta_t, process_id);
266 return nonlinear_solver_status;
270 std::vector<Output>&& outputs,
271 std::vector<std::unique_ptr<ProcessData>>&& per_process_data,
272 std::unique_ptr<NumLib::StaggeredCoupling>&& staggered_coupling,
274 : _outputs{std::move(outputs)},
275 _per_process_data(std::move(per_process_data)),
276 _start_time(start_time),
278 _staggered_coupling(std::move(staggered_coupling))
288 if (time == timestep_algorithm.
begin())
296 const double prev_dt,
NumLib::Time& t, std::size_t& accepted_steps,
297 std::size_t& rejected_steps,
298 std::vector<TimeStepConstraintCallback>
const& time_step_constraints)
300 bool all_process_steps_accepted =
true;
303 constexpr double eps = std::numeric_limits<double>::epsilon();
305 bool const is_initial_step =
307 [](
auto const& ppd) ->
bool
308 { return ppd->timestep_current.timeStepNumber() == 0; });
313 auto& timestep_algorithm = *ppd.timestep_algorithm.get();
318 const double solution_error =
322 ppd.conv_crit.get() ? ppd.conv_crit->getVectorNormType()
326 ppd.timestep_current.setAccepted(
327 ppd.nonlinear_solver_status.error_norms_met);
329 auto [previous_step_accepted, timestepper_dt] = timestep_algorithm.next(
330 solution_error, ppd.nonlinear_solver_status.number_iterations,
331 ppd.timestep_previous, ppd.timestep_current);
333 if (!previous_step_accepted)
336 all_process_steps_accepted =
false;
339 if (!ppd.nonlinear_solver_status.error_norms_met)
342 "Time step will be rejected due to nonlinear solver "
344 all_process_steps_accepted =
false;
347 if (timestepper_dt > eps || t < timestep_algorithm.end())
353 if (all_process_steps_accepted)
362 bool last_step_rejected =
false;
363 if (!is_initial_step)
365 if (all_process_steps_accepted)
368 last_step_rejected =
false;
376 last_step_rejected =
true;
382 for (
auto const& time_step_constraint : time_step_constraints)
385 std::min(dt(), time_step_constraint(t, dt()))};
389 if (std::abs(dt() - prev_dt) < eps)
391 if (last_step_rejected)
394 "The new step size of {} is the same as that of the previous "
395 "rejected time step. \nPlease re-run ogs with a proper "
396 "adjustment in the numerical settings, \ne.g. those for time "
397 "stepper, local or global non-linear solver.",
402 DBUG(
"The time stepping is stabilized with the step size of {}.",
411 if (all_process_steps_accepted)
415 ppd.timestep_current);
416 auto& timestep_algorithm = ppd.timestep_algorithm;
417 timestep_algorithm->resetCurrentTimeStep(
418 dt(), ppd.timestep_previous, ppd.timestep_current);
423 if (all_process_steps_accepted)
432 "Time step {:d} was rejected {:d} times and it will be "
433 "repeated with a reduced step size.",
440 return {dt, last_step_rejected};
443std::vector<TimeLoop::TimeStepConstraintCallback>
445 std::vector<double>&& fixed_times)
const
447 std::vector<TimeStepConstraintCallback>
const time_step_constraints{
448 [fixed_times = std::move(fixed_times)](
NumLib::Time const& t,
double dt)
458 return time_step_constraints;
466 auto& pcs = process_data->process;
469 output.addProcess(pcs);
474 if (
auto* conv_crit =
476 process_data->conv_crit.get()))
478 int const process_id = process_data->process_id;
479 conv_crit->setDOFTable(pcs.getDOFTable(process_id), pcs.getMesh());
514 time_timestep.
start();
520 INFO(
"=== Time stepping at step #{:d} and time {} with step size {}",
527 INFO(
"[time] Time step #{:d} took {:g} s.", timesteps,
534 const double prev_dt =
_dt();
554 ERR(
"Time step size of {} is too small.\n"
555 "Time stepping stops at step {:d} and at time of {}.",
571 "The whole computation of the time stepping took {:d} steps, in which\n"
572 "\t the accepted steps are {:d}, and the rejected steps are {:d}.\n",
584 std::size_t
const timesteps)
592 nonlinear_solver_status =
597 nonlinear_solver_status =
621 const NumLib::Time& t,
const double dt,
const std::size_t timestep_id,
622 ProcessData const& process_data, std::vector<GlobalVector*>& x,
623 std::vector<GlobalVector*>
const& x_prev,
624 std::vector<Output>
const& outputs)
627 time_timestep_process.
start();
630 x, x_prev, timestep_id, t(), dt, process_data, outputs);
632 INFO(
"[time] Solving process #{:d} took {:g} s in time step #{:d}",
635 return nonlinear_solver_status;
639 "Time stepper cannot reduce the time step size further.";
642 const NumLib::Time& t,
const double dt,
const std::size_t timestep_id)
648 auto const process_id = process_data->process_id;
653 process_data->nonlinear_solver_status = nonlinear_solver_status;
656 ERR(
"The nonlinear solver failed in time step #{:d} at t = {} s "
657 "for process #{:d}.",
658 timestep_id, t, process_id);
660 if (!process_data->timestep_algorithm->canReduceTimestepSize(
661 process_data->timestep_current,
662 process_data->timestep_previous))
667 output.doOutputAlways(
668 process_data->process, process_id, timestep_id, t,
669 process_data->nonlinear_solver_status.number_iterations,
675 return nonlinear_solver_status;
679 return nonlinear_solver_status;
684 const NumLib::Time& t,
const double dt,
const std::size_t timestep_id)
686 auto const nonlinear_solver_status =
696 auto& pcs = process_data->process;
697 int const process_id = process_data->process_id;
698 auto& ode_sys = *process_data->tdisc_ode_sys;
705 return nonlinear_solver_status;
708template <
typename OutputClassMember>
710 OutputClassMember output_class_member)
const
716 if (!process_data->nonlinear_solver_status.error_norms_met)
721 auto const process_id = process_data->process_id;
722 auto const& pcs = process_data->process;
724 for (
auto const& output_object :
_outputs)
726 (output_object.*output_class_member)(
728 process_data->nonlinear_solver_status.number_iterations,
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)
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 doOutputLastTimestep(Process const &process, const int process_id, int const timestep, const NumLib::Time &t, int const iteration, std::vector< GlobalVector * > const &xs) const
void doOutput(Process const &process, const int process_id, int const timestep, const NumLib::Time &t, int const iteration, 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