7#include <range/v3/algorithm/any_of.hpp>
8#include <range/v3/algorithm/contains.hpp>
23 std::vector<std::unique_ptr<ProcessLib::ProcessData>>
const&
27 for (
auto& process_data : per_process_data)
29 process_data->process.updateDeactivatedSubdomains(
30 t, process_data->process_id);
44 return ranges::any_of(outputs, [timestep, t](
auto const& output)
45 {
return output.isOutputStep(timestep, t); });
49 int const timestep,
NumLib::Time const& t,
double const dt,
51 std::vector<std::unique_ptr<ProcessLib::ProcessData>>
const&
53 std::vector<GlobalVector*>
const& process_solutions,
54 std::vector<GlobalVector*>
const& process_solutions_prev,
55 std::vector<ProcessLib::Output>
const& outputs)
62 for (
auto& process_data : per_process_data)
64 auto const process_id = process_data->process_id;
65 auto& pcs = process_data->process;
67 pcs.preOutput(t(), dt, process_solutions, process_solutions_prev,
77 std::vector<std::unique_ptr<ProcessData>>
const& per_process_data,
78 std::vector<GlobalVector*>
const& _process_solutions)
80 for (
auto& process_data : per_process_data)
82 auto const process_id = process_data->process_id;
83 auto& pcs = process_data->process;
84 pcs.preTimestep(_process_solutions, t(), dt, process_id);
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)
94 for (
auto& process_data : per_process_data)
96 auto const process_id = process_data->process_id;
97 auto& pcs = process_data->process;
99 pcs.computeSecondaryVariable(t(), dt, process_solutions,
100 *process_solutions_prev[process_id],
102 pcs.postTimestep(process_solutions, process_solutions_prev, t(), dt,
107template <NumLib::ODESystemTag ODETag>
131 else if ((
dynamic_cast<NonlinearSolverNewton*
>(
142 if (
auto* ode_newton =
dynamic_cast<ODENewton*
>(&ode_sys))
151 "You are trying to solve a non-Newton-ready ODE with the"
152 " Newton-Raphson method. Aborting");
157 OGS_FATAL(
"Encountered unknown nonlinear solver type. Aborting");
166std::pair<std::vector<GlobalVector*>, std::vector<GlobalVector*>>
169 std::vector<std::unique_ptr<ProcessData>>
const& per_process_data)
171 std::vector<GlobalVector*> process_solutions;
172 std::vector<GlobalVector*> process_solutions_prev;
174 for (
auto const& process_data : per_process_data)
176 auto const process_id = process_data->process_id;
177 auto& ode_sys = *process_data->tdisc_ode_sys;
180 process_solutions.emplace_back(
182 ode_sys.getMatrixSpecifications(process_id)));
183 process_solutions_prev.emplace_back(
185 ode_sys.getMatrixSpecifications(process_id)));
188 for (
auto const& process_data : per_process_data)
190 auto& pcs = process_data->process;
191 auto const process_id = process_data->process_id;
192 pcs.setInitialConditions(process_solutions, process_solutions_prev,
195 auto& time_disc = *process_data->time_disc;
196 time_disc.setInitialState(t0());
199 return {process_solutions, process_solutions_prev};
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)
207 for (
auto const& process_data : per_process_data)
209 auto& nonlinear_solver = process_data->nonlinear_solver;
212 nonlinear_solver.calculateNonEquilibriumInitialResiduum(
213 process_solutions, process_solutions_prev,
214 process_data->process_id);
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)
223 auto& process = process_data.
process;
224 int const process_id = process_data.
process_id;
225 auto& time_disc = *process_data.
time_disc;
235 time_disc.nextTimestep(t, delta_t);
237 auto const post_iteration_callback =
238 [&](
int const iteration, std::vector<GlobalVector*>
const& x)
243 for (
auto const& output : outputs)
245 output.doOutputNonlinearIteration(process, process_id, timestep,
250 auto const nonlinear_solver_status =
251 nonlinear_solver.solve(x, x_prev, post_iteration_callback, process_id);
253 if (!nonlinear_solver_status.error_norms_met)
255 return nonlinear_solver_status;
258 process.postNonLinearSolver(x, x_prev, t, delta_t, process_id);
260 return nonlinear_solver_status;
264 std::vector<Output>&& outputs,
265 std::vector<std::unique_ptr<ProcessData>>&& per_process_data,
266 std::unique_ptr<NumLib::StaggeredCoupling>&& staggered_coupling,
282 if (time == timestep_algorithm.
begin())
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)
294 bool all_process_steps_accepted =
true;
297 constexpr double eps = std::numeric_limits<double>::epsilon();
299 bool const is_initial_step =
301 [](
auto const& ppd) ->
bool
302 { return ppd->timestep_current.timeStepNumber() == 0; });
307 int staggered_number_iterations = 0;
310 auto const ppd_max_iterations = std::ranges::max_element(
312 {
return ppd->nonlinear_solver_status.number_iterations; });
313 staggered_number_iterations = std::max(
315 (*ppd_max_iterations)->nonlinear_solver_status.number_iterations);
321 auto& timestep_algorithm = *ppd.timestep_algorithm.get();
326 const double solution_error =
330 ppd.conv_crit.get() ? ppd.conv_crit->getVectorNormType()
334 ppd.timestep_current.setAccepted(
335 ppd.nonlinear_solver_status.error_norms_met);
337 int const number_iterations =
339 : ppd.nonlinear_solver_status.number_iterations;
341 auto const timestepper_dt = timestep_algorithm.next(
342 solution_error, number_iterations, ppd.timestep_previous,
343 ppd.timestep_current);
345 if (!ppd.timestep_current.isAccepted())
348 all_process_steps_accepted =
false;
351 if (!ppd.nonlinear_solver_status.error_norms_met)
354 "Time step will be rejected due to nonlinear solver "
356 all_process_steps_accepted =
false;
359 if (timestepper_dt > eps || t < timestep_algorithm.end())
365 if (all_process_steps_accepted)
374 bool previous_step_rejected =
false;
375 if (!is_initial_step)
377 if (all_process_steps_accepted)
380 previous_step_rejected =
false;
388 previous_step_rejected =
true;
394 for (
auto const& time_step_constraint : time_step_constraints)
397 std::min(dt(), time_step_constraint(t, dt()))};
401 if (std::abs(dt() - prev_dt) < eps)
403 if (previous_step_rejected)
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.",
414 DBUG(
"The time stepping is stabilized with the step size of {}.",
423 if (all_process_steps_accepted)
427 ppd.timestep_current);
432 if (all_process_steps_accepted)
441 "Time step {:d} was rejected {:d} times and it will be "
442 "repeated with a reduced step size.",
449 return {dt, previous_step_rejected};
452std::vector<TimeLoop::TimeStepConstraintCallback>
454 std::vector<double>&& fixed_times)
const
456 std::vector<TimeStepConstraintCallback>
const time_step_constraints{
457 [fixed_times = std::move(fixed_times)](
NumLib::Time const& t,
double dt)
467 return time_step_constraints;
475 auto& pcs = process_data->process;
478 output.addProcess(pcs);
483 if (
auto* conv_crit =
485 process_data->conv_crit.get()))
487 int const process_id = process_data->process_id;
488 conv_crit->setDOFTable(pcs.getDOFTable(process_id), pcs.getMesh());
523 time_timestep.
start();
529 INFO(
"Time step #{:d} started. Time: {}. Step size: {}.", timesteps,
536 INFO(
"[time] Time step #{:d} took {:g} s.", timesteps,
543 const double prev_dt =
_dt();
567 DBUG(
"current time == previous time + dt : {:a} == {:a} + {:a} = {:a}",
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 {}.",
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",
600 std::size_t
const timesteps)
608 nonlinear_solver_status =
613 nonlinear_solver_status =
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)
643 time_timestep_process.
start();
648 x, x_prev, timestep_id, t(), dt, process_data, outputs);
650 INFO(
"[time] Solving process #{:d} took {:g} s in time step #{:d}",
653 return nonlinear_solver_status;
657 "Time stepper cannot reduce the time step size further.";
660 const NumLib::Time& t,
const double dt,
const std::size_t timestep_id)
666 auto const process_id = process_data->process_id;
671 process_data->nonlinear_solver_status = nonlinear_solver_status;
674 ERR(
"The nonlinear solver failed in time step #{:d} at t = {} s "
675 "for process #{:d}.",
676 timestep_id, t, process_id);
678 if (!process_data->timestep_algorithm->canReduceTimestepSize(
679 process_data->timestep_current,
680 process_data->timestep_previous))
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,
694 return nonlinear_solver_status;
698 return nonlinear_solver_status;
703 const NumLib::Time& t,
const double dt,
const std::size_t timestep_id)
705 auto const nonlinear_solver_status =
717 auto& pcs = process_data->process;
718 int const process_id = process_data->process_id;
719 auto& ode_sys = *process_data->tdisc_ode_sys;
721 t(), dt, ode_sys, process_id);
724 return nonlinear_solver_status;
727template <
typename OutputClassMember>
729 OutputClassMember output_class_member)
const
735 if (!process_data->nonlinear_solver_status.error_norms_met)
740 auto const process_id = process_data->process_id;
741 auto const& pcs = process_data->process;
743 for (
auto const& output_object :
_outputs)
745 (output_object.*output_class_member)(
747 process_data->nonlinear_solver_status.number_iterations,
748 process_data->nonlinear_solver_status.error_norms_met,
767 const double dt)
const
773 if (!process_data->nonlinear_solver_status.error_norms_met)
778 auto const process_id = process_data->process_id;
779 auto& pcs = process_data->process;
781 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
int _global_coupling_number_iterations
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.
bool _previous_step_rejected
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