OGS
ProcessLib::TimeLoop Class Reference

Detailed Description

Time loop capable of time-integrating several processes at once.

Definition at line 36 of file TimeLoop.h.

#include <TimeLoop.h>

Public Member Functions

 TimeLoop (std::unique_ptr< Output > &&output, std::vector< std::unique_ptr< ProcessData > > &&per_process_data, const int global_coupling_max_iterations, std::vector< std::unique_ptr< NumLib::ConvergenceCriterion > > &&global_coupling_conv_crit, const double start_time, const double end_time)
 
void initialize ()
 initialize output, convergence criterion, etc. More...
 
void outputLastTimeStep () const
 
 ~TimeLoop ()
 
bool executeTimeStep ()
 
bool calculateNextTimeStep ()
 
double endTime () const
 
double currentTime () const
 

Public Attributes

bool successful_time_step = false
 

Private Member Functions

bool doNonlinearIteration (double const t, double const dt, std::size_t const timesteps)
 
void setCoupledSolutions ()
 
NumLib::NonlinearSolverStatus solveUncoupledEquationSystems (const double 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, or several systems of equations without any dependency among the different systems. More...
 
NumLib::NonlinearSolverStatus solveCoupledEquationSystemsByStaggeredScheme (const double t, const double dt, const std::size_t timestep_id)
 Member to solver coupled systems of equations by the staggered scheme. More...
 
std::pair< double, bool > computeTimeStepping (const double prev_dt, double &t, std::size_t &accepted_steps, std::size_t &rejected_steps, std::vector< std::function< double(double, double)> > const &time_step_constraints)
 
template<typename OutputClass , typename OutputClassMember >
void outputSolutions (bool const output_initial_condition, unsigned timestep, const double t, OutputClass &output_object, OutputClassMember output_class_member) const
 

Private Attributes

std::vector< GlobalVector * > _process_solutions
 
std::vector< GlobalVector * > _process_solutions_prev
 
std::unique_ptr< Output_output
 
std::vector< std::unique_ptr< ProcessData > > _per_process_data
 
const double _start_time
 
const double _end_time
 
double _current_time = _start_time
 
std::size_t _accepted_steps = 0
 
std::size_t _rejected_steps = 0
 
double _dt = 0
 
int _repeating_times_of_rejected_step = 0
 
bool _last_step_rejected = false
 
const int _global_coupling_max_iterations
 Maximum iterations of the global coupling. More...
 
std::vector< std::unique_ptr< NumLib::ConvergenceCriterion > > _global_coupling_conv_crit
 Convergence criteria of processes for the global coupling iterations. More...
 
std::vector< GlobalVector * > _solutions_of_last_cpl_iteration
 
std::vector< std::size_t > _xdot_vector_ids
 

Constructor & Destructor Documentation

◆ TimeLoop()

ProcessLib::TimeLoop::TimeLoop ( std::unique_ptr< Output > &&  output,
std::vector< std::unique_ptr< ProcessData > > &&  per_process_data,
const int  global_coupling_max_iterations,
std::vector< std::unique_ptr< NumLib::ConvergenceCriterion > > &&  global_coupling_conv_crit,
const double  start_time,
const double  end_time 
)

Definition at line 276 of file TimeLoop.cpp.

282 : _output(std::move(output)),
283 _per_process_data(std::move(per_process_data)),
284 _start_time(start_time),
285 _end_time(end_time),
286 _global_coupling_max_iterations(global_coupling_max_iterations),
287 _global_coupling_conv_crit(std::move(global_coupling_conv_crit))
288{
289}
const double _start_time
Definition: TimeLoop.h:127
std::vector< std::unique_ptr< ProcessData > > _per_process_data
Definition: TimeLoop.h:125
const double _end_time
Definition: TimeLoop.h:128
std::vector< std::unique_ptr< NumLib::ConvergenceCriterion > > _global_coupling_conv_crit
Convergence criteria of processes for the global coupling iterations.
Definition: TimeLoop.h:140
const int _global_coupling_max_iterations
Maximum iterations of the global coupling.
Definition: TimeLoop.h:137
std::unique_ptr< Output > _output
Definition: TimeLoop.h:124

◆ ~TimeLoop()

ProcessLib::TimeLoop::~TimeLoop ( )

Definition at line 928 of file TimeLoop.cpp.

929{
930 for (auto* x : _process_solutions)
931 {
933 }
934 for (auto* x : _process_solutions_prev)
935 {
937 }
938
940 {
942 }
943}
virtual void releaseVector(GlobalVector const &x)=0
std::vector< GlobalVector * > _solutions_of_last_cpl_iteration
Definition: TimeLoop.h:144
std::vector< GlobalVector * > _process_solutions
Definition: TimeLoop.h:122
std::vector< GlobalVector * > _process_solutions_prev
Definition: TimeLoop.h:123
static NUMLIB_EXPORT VectorProvider & provider

References _process_solutions, _process_solutions_prev, _solutions_of_last_cpl_iteration, NumLib::GlobalVectorProvider::provider, and NumLib::VectorProvider::releaseVector().

Member Function Documentation

◆ calculateNextTimeStep()

bool ProcessLib::TimeLoop::calculateNextTimeStep ( )

Definition at line 565 of file TimeLoop.cpp.

566{
567 const double prev_dt = _dt;
568 double const current_time = _current_time;
569
570 const std::size_t timesteps = _accepted_steps + 1;
571
572 auto const& fixed_times = _output->getFixedOutputTimes();
573 std::vector<std::function<double(double, double)>> time_step_constraints{
574 [&fixed_times](double t, double dt)
575 { return NumLib::possiblyClampDtToNextFixedTime(t, dt, fixed_times); },
576 [this](double t, double dt)
577 {
578 if (t < _end_time && t + dt > _end_time)
579 {
580 return _end_time - t;
581 }
582 return dt;
583 }};
584
585 // _last_step_rejected is also checked in computeTimeStepping.
586 std::tie(_dt, _last_step_rejected) =
588 _rejected_steps, time_step_constraints);
589
591 {
592 const bool output_initial_condition = false;
593 outputSolutions(output_initial_condition, timesteps, current_time,
595 }
596
597 if (std::abs(_current_time - _end_time) <
598 std::numeric_limits<double>::epsilon() ||
600 {
601 return false;
602 }
603
604 if (_dt < std::numeric_limits<double>::epsilon())
605 {
606 WARN(
607 "Time step size of {:g} is too small.\n"
608 "Time stepping stops at step {:d} and at time of {:g}.",
609 _dt, timesteps, _current_time);
610 return false;
611 }
612
613 return true;
614}
void WARN(char const *fmt, Args const &... args)
Definition: Logging.h:39
void doOutput(Process const &process, const int process_id, int const timestep, const double t, int const iteration, std::vector< GlobalVector * > const &xs)
Definition: Output.cpp:478
std::pair< double, bool > computeTimeStepping(const double prev_dt, double &t, std::size_t &accepted_steps, std::size_t &rejected_steps, std::vector< std::function< double(double, double)> > const &time_step_constraints)
Definition: TimeLoop.cpp:306
void outputSolutions(bool const output_initial_condition, unsigned timestep, const double t, OutputClass &output_object, OutputClassMember output_class_member) const
Definition: TimeLoop.cpp:851
std::size_t _accepted_steps
Definition: TimeLoop.h:130
std::size_t _rejected_steps
Definition: TimeLoop.h:131
static const double t
double possiblyClampDtToNextFixedTime(double const t, double const dt, std::vector< double > const &fixed_output_times)

References _accepted_steps, _current_time, _dt, _end_time, _last_step_rejected, _output, _rejected_steps, computeTimeStepping(), ProcessLib::Output::doOutput(), outputSolutions(), NumLib::possiblyClampDtToNextFixedTime(), MathLib::t, and WARN().

◆ computeTimeStepping()

std::pair< double, bool > ProcessLib::TimeLoop::computeTimeStepping ( const double  prev_dt,
double &  t,
std::size_t &  accepted_steps,
std::size_t &  rejected_steps,
std::vector< std::function< double(double, double)> > const &  time_step_constraints 
)
private

Find the minimum time step size among the predicted step sizes of processes and step it as common time step size.

Parameters
prev_dtPrevious time step size.
tCurrent time.
accepted_stepsAccepted time steps that are counted in this function.
rejected_stepsRejected time steps that are counted in this function.
time_step_constraintsFunctions that are evaluate to influence the time step size (for instance a fixed output time)
Returns
the time step size and the information if the last time step was rejected

Definition at line 306 of file TimeLoop.cpp.

311{
312 bool all_process_steps_accepted = true;
313 // Get minimum time step size among step sizes of all processes.
314 double dt = std::numeric_limits<double>::max();
315 constexpr double eps = std::numeric_limits<double>::epsilon();
316
317 bool const is_initial_step =
319 [](auto const& ppd) -> bool
320 { return ppd->timestep_current.timeStepNumber() == 0; });
321
322 auto computeSolutionError = [this, t](auto const i) -> double
323 {
324 auto const& ppd = *_per_process_data[i];
325 const auto& timestep_algorithm = ppd.timestep_algorithm;
326 if (!timestep_algorithm->isSolutionErrorComputationNeeded())
327 {
328 return 0.0;
329 }
330 if (t == timestep_algorithm->begin())
331 {
332 // Always accepts the zeroth step
333 return 0.0;
334 }
335
336 auto const& x = *_process_solutions[i];
337 auto const& x_prev = *_process_solutions_prev[i];
338
339 auto const& conv_crit = ppd.conv_crit;
340 const MathLib::VecNormType norm_type =
341 (conv_crit) ? conv_crit->getVectorNormType()
343
344 const double solution_error =
346 norm_type);
347 return solution_error;
348 };
349
350 for (std::size_t i = 0; i < _per_process_data.size(); i++)
351 {
352 auto& ppd = *_per_process_data[i];
353 const auto& timestep_algorithm = ppd.timestep_algorithm;
354
355 const double solution_error = computeSolutionError(i);
356
357 ppd.timestep_current.setAccepted(
358 ppd.nonlinear_solver_status.error_norms_met);
359
360 auto [previous_step_accepted, timestepper_dt] =
361 timestep_algorithm->next(
362 solution_error, ppd.nonlinear_solver_status.number_iterations,
363 ppd.timestep_previous, ppd.timestep_current);
364
365 if (!previous_step_accepted &&
366 // In case of FixedTimeStepping, which makes
367 // timestep_algorithm->next(...) return false when the ending time
368 // is reached.
369 t + eps < timestep_algorithm->end())
370 {
371 // Not all processes have accepted steps.
372 all_process_steps_accepted = false;
373 }
374
375 if (!ppd.nonlinear_solver_status.error_norms_met)
376 {
377 WARN(
378 "Time step will be rejected due to nonlinear solver "
379 "divergence.");
380 all_process_steps_accepted = false;
381 }
382
383 if (timestepper_dt > eps ||
384 std::abs(t - timestep_algorithm->end()) < eps)
385 {
386 dt = std::min(timestepper_dt, dt);
387 }
388 }
389
390 if (all_process_steps_accepted)
391 {
393 }
394 else
395 {
397 }
398
399 bool last_step_rejected = false;
400 if (!is_initial_step)
401 {
402 if (all_process_steps_accepted)
403 {
404 accepted_steps++;
405 last_step_rejected = false;
406 }
407 else
408 {
409 if (t < _end_time || std::abs(t - _end_time) < eps)
410 {
411 t -= prev_dt;
412 rejected_steps++;
413 last_step_rejected = true;
414 }
415 }
416 }
417
418 // adjust step size considering external communciation_point_calculators
419 for (auto const& time_step_constain : time_step_constraints)
420 {
421 dt = std::min(dt, time_step_constain(t, dt));
422 }
423
424 // Check whether the time stepping is stabilized
425 if (std::abs(dt - prev_dt) < eps)
426 {
427 if (last_step_rejected)
428 {
429 OGS_FATAL(
430 "The new step size of {:g} is the same as that of the previous "
431 "rejected time step. \nPlease re-run ogs with a proper "
432 "adjustment in the numerical settings, \ne.g those for time "
433 "stepper, local or global non-linear solver.",
434 dt);
435 }
436 else
437 {
438 DBUG("The time stepping is stabilized with the step size of {:g}.",
439 dt);
440 }
441 }
442
443 // Reset the time step with the minimum step size, dt
444 // Update the solution of the previous time step.
445 for (std::size_t i = 0; i < _per_process_data.size(); i++)
446 {
447 auto& ppd = *_per_process_data[i];
448 auto& timestep_algorithm = ppd.timestep_algorithm;
449 if (all_process_steps_accepted)
450 {
451 NumLib::updateTimeSteps(dt, ppd.timestep_previous,
452 ppd.timestep_current);
453 timestep_algorithm->resetCurrentTimeStep(dt, ppd.timestep_previous,
454 ppd.timestep_current);
455 }
456
457 if (t == timestep_algorithm->begin())
458 {
459 continue;
460 }
461
462 auto& x = *_process_solutions[i];
463 auto& x_prev = *_process_solutions_prev[i];
464 if (all_process_steps_accepted)
465 {
466 MathLib::LinAlg::copy(x, x_prev); // pushState
467 }
468 else
469 {
470 if (t < _end_time || std::abs(t - _end_time) < eps)
471 {
472 WARN(
473 "Time step {:d} was rejected {:d} times and it will be "
474 "repeated with a reduced step size.",
475 accepted_steps + 1, _repeating_times_of_rejected_step);
476 MathLib::LinAlg::copy(x_prev, x); // popState
477 }
478 }
479 }
480
481 return {dt, last_step_rejected};
482}
#define OGS_FATAL(...)
Definition: Error.h:26
void DBUG(char const *fmt, Args const &... args)
Definition: Logging.h:29
int _repeating_times_of_rejected_step
Definition: TimeLoop.h:133
constexpr bool any_of(List const &values)
Checks if any of the elements in the given list is true.
Definition: Algorithm.h:325
void copy(PETScVector const &x, PETScVector &y)
Definition: LinAlg.cpp:37
VecNormType
Norm type. Not declared as class type in order to use the members as integers.
Definition: LinAlgEnums.h:22
void updateTimeSteps(double const dt, TimeStep &previous_timestep, TimeStep &current_timestep)
Definition: TimeStep.h:112
double computeRelativeChangeFromPreviousTimestep(GlobalVector const &x, GlobalVector const &x_old, MathLib::VecNormType norm_type)

References _end_time, _per_process_data, _process_solutions, _process_solutions_prev, _repeating_times_of_rejected_step, BaseLib::any_of(), NumLib::computeRelativeChangeFromPreviousTimestep(), MathLib::LinAlg::copy(), DBUG(), MathLib::NORM2, OGS_FATAL, MathLib::t, NumLib::updateTimeSteps(), and WARN().

Referenced by calculateNextTimeStep(), and initialize().

◆ currentTime()

double ProcessLib::TimeLoop::currentTime ( ) const
inline

Definition at line 54 of file TimeLoop.h.

54{ return _current_time; }

References _current_time.

◆ doNonlinearIteration()

bool ProcessLib::TimeLoop::doNonlinearIteration ( double const  t,
double const  dt,
std::size_t const  timesteps 
)
private

Definition at line 633 of file TimeLoop.cpp.

635{
637
638 // All _per_process_data share the first process.
639 bool const is_staggered_coupling =
641 NumLib::NonlinearSolverStatus nonlinear_solver_status;
642
643 if (is_staggered_coupling)
644 {
645 nonlinear_solver_status =
647 }
648 else
649 {
650 nonlinear_solver_status =
651 solveUncoupledEquationSystems(t, dt, timesteps);
652 }
653
654 // Run post time step only if the last iteration was successful.
655 // Otherwise it runs the risks to get the same errors as in the last
656 // iteration, an exception thrown in assembly, for example.
657 if (nonlinear_solver_status.error_norms_met)
658 {
662 }
663 return nonlinear_solver_status.error_norms_met;
664}
std::vector< std::size_t > _xdot_vector_ids
Definition: TimeLoop.h:149
NumLib::NonlinearSolverStatus solveUncoupledEquationSystems(const double 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:687
NumLib::NonlinearSolverStatus solveCoupledEquationSystemsByStaggeredScheme(const double t, const double dt, const std::size_t timestep_id)
Member to solver coupled systems of equations by the staggered scheme.
Definition: TimeLoop.cpp:730
void preTimestepForAllProcesses(double const t, double const dt, std::vector< std::unique_ptr< ProcessData > > const &per_process_data, std::vector< GlobalVector * > const &_process_solutions)
Definition: TimeLoop.cpp:45
void postTimestepForAllProcesses(double 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::vector< std::size_t > &xdot_vector_ids)
Definition: TimeLoop.cpp:58
bool isMonolithicProcess(ProcessLib::ProcessData const &process_data)
Definition: TimeLoop.cpp:24
Status of the non-linear solver.

References _per_process_data, _process_solutions, _process_solutions_prev, _xdot_vector_ids, NumLib::NonlinearSolverStatus::error_norms_met, anonymous_namespace{TimeLoop.cpp}::isMonolithicProcess(), ProcessLib::postTimestepForAllProcesses(), ProcessLib::preTimestepForAllProcesses(), solveCoupledEquationSystemsByStaggeredScheme(), solveUncoupledEquationSystems(), and MathLib::t.

Referenced by executeTimeStep().

◆ endTime()

double ProcessLib::TimeLoop::endTime ( ) const
inline

Definition at line 53 of file TimeLoop.h.

53{ return _end_time; }

References _end_time.

◆ executeTimeStep()

bool ProcessLib::TimeLoop::executeTimeStep ( )

Definition at line 545 of file TimeLoop.cpp.

546{
547 BaseLib::RunTime time_timestep;
548 time_timestep.start();
549
551
552 const std::size_t timesteps = _accepted_steps + 1;
553 // TODO(wenqing): , input option for time unit.
554 INFO("=== Time stepping at step #{:d} and time {:g} with step size {:g}",
555 timesteps, _current_time, _dt);
556
558
560 INFO("[time] Time step #{:d} took {:g} s.", timesteps,
561 time_timestep.elapsed());
563}
void INFO(char const *fmt, Args const &... args)
Definition: Logging.h:34
Count the running time.
Definition: RunTime.h:29
double elapsed() const
Get the elapsed time in seconds.
Definition: RunTime.h:42
void start()
Start the timer.
Definition: RunTime.h:32
bool doNonlinearIteration(double const t, double const dt, std::size_t const timesteps)
Definition: TimeLoop.cpp:633
bool successful_time_step
Definition: TimeLoop.h:55
void updateDeactivatedSubdomains(std::vector< std::unique_ptr< ProcessLib::ProcessData > > const &per_process_data, double const t)
Definition: TimeLoop.cpp:29

References _accepted_steps, _current_time, _dt, _per_process_data, doNonlinearIteration(), BaseLib::RunTime::elapsed(), INFO(), BaseLib::RunTime::start(), successful_time_step, and anonymous_namespace{TimeLoop.cpp}::updateDeactivatedSubdomains().

◆ initialize()

void ProcessLib::TimeLoop::initialize ( )

initialize output, convergence criterion, etc.

Definition at line 485 of file TimeLoop.cpp.

486{
487 for (auto& process_data : _per_process_data)
488 {
489 auto& pcs = process_data->process;
490 int const process_id = process_data->process_id;
491 _output->addProcess(pcs);
492
493 setTimeDiscretizedODESystem(*process_data);
494
495 if (auto* conv_crit =
497 process_data->conv_crit.get()))
498 {
499 conv_crit->setDOFTable(pcs.getDOFTable(process_id), pcs.getMesh());
500 }
501 }
502
503 // initial solution storage
506
507 // All _per_process_data share the first process.
508 bool const is_staggered_coupling =
510
511 if (is_staggered_coupling)
512 {
514 }
515
516 // Output initial conditions
517 {
518 const bool output_initial_condition = true;
519 outputSolutions(output_initial_condition, 0, _start_time, *_output,
521 }
522
523 auto const& fixed_times = _output->getFixedOutputTimes();
524 std::vector<std::function<double(double, double)>> time_step_constraints{
525 [&fixed_times](double t, double dt)
526 { return NumLib::possiblyClampDtToNextFixedTime(t, dt, fixed_times); },
527 [this](double t, double dt)
528 {
529 if (t < _end_time && t + dt > _end_time)
530 {
531 return _end_time - t;
532 }
533 return dt;
534 }};
535 std::tie(_dt, _last_step_rejected) =
537 _rejected_steps, time_step_constraints);
538
540
543}
void setCoupledSolutions()
Definition: TimeLoop.cpp:291
void setTimeDiscretizedODESystem(ProcessData &process_data, NumLib::ODESystem< ODETag, NumLib::NonlinearSolverTag::Picard > &ode_sys)
Definition: TimeLoop.cpp:112
void calculateNonEquilibriumInitialResiduum(std::vector< std::unique_ptr< ProcessData > > const &per_process_data, std::vector< GlobalVector * > process_solutions, std::vector< GlobalVector * > const &process_solutions_prev)
Definition: TimeLoop.cpp:206
std::pair< std::vector< GlobalVector * >, std::vector< GlobalVector * > > setInitialConditions(double const t0, std::vector< std::unique_ptr< ProcessData > > const &per_process_data)
Definition: TimeLoop.cpp:171

References _accepted_steps, _current_time, _dt, _end_time, _last_step_rejected, _output, _per_process_data, _process_solutions, _process_solutions_prev, _rejected_steps, _start_time, ProcessLib::calculateNonEquilibriumInitialResiduum(), computeTimeStepping(), ProcessLib::Output::doOutput(), anonymous_namespace{TimeLoop.cpp}::isMonolithicProcess(), outputSolutions(), NumLib::possiblyClampDtToNextFixedTime(), setCoupledSolutions(), ProcessLib::setInitialConditions(), ProcessLib::setTimeDiscretizedODESystem(), MathLib::t, and anonymous_namespace{TimeLoop.cpp}::updateDeactivatedSubdomains().

◆ outputLastTimeStep()

void ProcessLib::TimeLoop::outputLastTimeStep ( ) const

Definition at line 616 of file TimeLoop.cpp.

617{
618 INFO(
619 "The whole computation of the time stepping took {:d} steps, in which\n"
620 "\t the accepted steps are {:d}, and the rejected steps are {:d}.\n",
622
623 // output last time step
625 {
626 const bool output_initial_condition = false;
627 outputSolutions(output_initial_condition,
630 }
631}
void doOutputLastTimestep(Process const &process, const int process_id, int const timestep, const double t, int const iteration, std::vector< GlobalVector * > const &xs)
Definition: Output.cpp:497

References _accepted_steps, _current_time, _output, _rejected_steps, ProcessLib::Output::doOutputLastTimestep(), INFO(), outputSolutions(), and successful_time_step.

◆ outputSolutions()

template<typename OutputClass , typename OutputClassMember >
void ProcessLib::TimeLoop::outputSolutions ( bool const  output_initial_condition,
unsigned  timestep,
const double  t,
OutputClass &  output_object,
OutputClassMember  output_class_member 
) const
private

Definition at line 851 of file TimeLoop.cpp.

855{
856 // All _per_process_data share the first process.
857 bool const is_staggered_coupling =
859
860 for (auto& process_data : _per_process_data)
861 {
862 // If nonlinear solver diverged, the solution has already been
863 // saved.
864 if (!process_data->nonlinear_solver_status.error_norms_met)
865 {
866 continue;
867 }
868
869 auto const process_id = process_data->process_id;
870 auto& pcs = process_data->process;
871
872 if (!is_staggered_coupling && output_initial_condition)
873 {
874 auto const& ode_sys = *process_data->tdisc_ode_sys;
875 // dummy value to handle the time derivative terms more or less
876 // correctly, i.e. to ignore them.
877 double const dt = 1;
878 process_data->time_disc->nextTimestep(t, dt);
879
881 ode_sys.getMatrixSpecifications(process_id));
882 x_dot.setZero();
883
884 pcs.preTimestep(_process_solutions, _start_time, dt, process_id);
885 // Update secondary variables, which might be uninitialized, before
886 // output.
887 pcs.computeSecondaryVariable(_start_time, dt, _process_solutions,
888 x_dot, process_id);
889
891 }
892 if (is_staggered_coupling && output_initial_condition)
893 {
894 CoupledSolutionsForStaggeredScheme coupled_solutions(
896
897 process_data->process.setCoupledSolutionsForStaggeredScheme(
898 &coupled_solutions);
899 process_data->process
900 .setCoupledTermForTheStaggeredSchemeToLocalAssemblers(
901 process_id);
902
903 auto const& ode_sys = *process_data->tdisc_ode_sys;
904 // dummy value to handle the time derivative terms more or less
905 // correctly, i.e. to ignore them.
906 double const dt = 1;
907 process_data->time_disc->nextTimestep(t, dt);
908
910 ode_sys.getMatrixSpecifications(process_id));
911 x_dot.setZero();
912
913 pcs.preTimestep(_process_solutions, _start_time, dt, process_id);
914 // Update secondary variables, which might be uninitialized, before
915 // output.
916 pcs.computeSecondaryVariable(_start_time, dt, _process_solutions,
917 x_dot, process_id);
918
920 }
921 (output_object.*output_class_member)(
922 pcs, process_id, timestep, t,
923 process_data->nonlinear_solver_status.number_iterations,
925 }
926}
virtual GlobalVector & getVector(std::size_t &id)=0
Get an uninitialized vector with the given id.

References _per_process_data, _process_solutions, _start_time, NumLib::VectorProvider::getVector(), anonymous_namespace{TimeLoop.cpp}::isMonolithicProcess(), NumLib::GlobalVectorProvider::provider, NumLib::VectorProvider::releaseVector(), MathLib::EigenVector::setZero(), and MathLib::t.

Referenced by calculateNextTimeStep(), initialize(), and outputLastTimeStep().

◆ setCoupledSolutions()

void ProcessLib::TimeLoop::setCoupledSolutions ( )
private

This function fills the vector of solutions of coupled processes of processes, _solutions_of_coupled_processes, and initializes the vector of solutions of the previous coupling iteration, _solutions_of_last_cpl_iteration.

Definition at line 291 of file TimeLoop.cpp.

292{
293 for (auto& process_data : _per_process_data)
294 {
295 auto const& x = *_process_solutions[process_data->process_id];
296
297 // Create a vector to store the solution of the last coupling iteration
300
301 // append a solution vector of suitable size
302 _solutions_of_last_cpl_iteration.emplace_back(&x0);
303 }
304}

References _per_process_data, _process_solutions, _solutions_of_last_cpl_iteration, MathLib::LinAlg::copy(), NumLib::VectorProvider::getVector(), and NumLib::GlobalVectorProvider::provider.

Referenced by initialize().

◆ solveCoupledEquationSystemsByStaggeredScheme()

NumLib::NonlinearSolverStatus ProcessLib::TimeLoop::solveCoupledEquationSystemsByStaggeredScheme ( const double  t,
const double  dt,
const std::size_t  timestep_id 
)
private

Member to solver coupled systems of equations by the staggered scheme.

Parameters
tCurrent time
dtTime step size
timestep_idIndex of the time step
Returns
true: if all nonlinear solvers convergence. false: if any of nonlinear solvers divergences.

Definition at line 730 of file TimeLoop.cpp.

732{
733 // Coupling iteration
735 {
736 // Set the flag of the first iteration be true.
737 for (auto& conv_crit : _global_coupling_conv_crit)
738 {
739 conv_crit->preFirstIteration();
740 }
741 }
742 auto resetCouplingConvergenceCriteria = [&]()
743 {
744 for (auto& conv_crit : _global_coupling_conv_crit)
745 {
746 conv_crit->reset();
747 }
748 };
749
750 NumLib::NonlinearSolverStatus nonlinear_solver_status{false, -1};
751 bool coupling_iteration_converged = true;
752 for (int global_coupling_iteration = 0;
753 global_coupling_iteration < _global_coupling_max_iterations;
754 global_coupling_iteration++, resetCouplingConvergenceCriteria())
755 {
756 // TODO(wenqing): use process name
757 coupling_iteration_converged = true;
758 _xdot_vector_ids.resize(_per_process_data.size());
759 std::size_t cnt = 0;
760 for (auto& process_data : _per_process_data)
761 {
762 auto const process_id = process_data->process_id;
763 BaseLib::RunTime time_timestep_process;
764 time_timestep_process.start();
765
766 // The following setting of coupled_solutions can be removed only if
767 // the CoupledSolutionsForStaggeredScheme and related functions are
768 // removed totally from the computation of the secondary variable
769 // and from post-time functions.
770 CoupledSolutionsForStaggeredScheme coupled_solutions(
772
773 process_data->process.setCoupledSolutionsForStaggeredScheme(
774 &coupled_solutions);
775
776 nonlinear_solver_status = solveOneTimeStepOneProcess(
778 *process_data, *_output, _xdot_vector_ids[cnt]);
779 cnt++;
780 process_data->nonlinear_solver_status = nonlinear_solver_status;
781
782 INFO(
783 "[time] Solving process #{:d} took {:g} s in time step #{:d} "
784 "coupling iteration #{:d}",
785 process_id, time_timestep_process.elapsed(), timestep_id,
786 global_coupling_iteration);
787
788 if (!nonlinear_solver_status.error_norms_met)
789 {
790 WARN(
791 "The nonlinear solver failed in time step #{:d} at t = "
792 "{:g} s for process #{:d}.",
793 timestep_id, t, process_id);
794 _last_step_rejected = true;
795 return nonlinear_solver_status;
796 }
797
798 // Check the convergence of the coupling iteration
799 auto& x = *_process_solutions[process_id];
800 auto& x_old = *_solutions_of_last_cpl_iteration[process_id];
801 if (global_coupling_iteration > 0)
802 {
803 MathLib::LinAlg::axpy(x_old, -1.0, x); // save dx to x_old
804 INFO(
805 "------- Checking convergence criterion for coupled "
806 "solution of process #{:d} -------",
807 process_id);
808 _global_coupling_conv_crit[process_id]->checkDeltaX(x_old, x);
809 coupling_iteration_converged =
810 coupling_iteration_converged &&
811 _global_coupling_conv_crit[process_id]->isSatisfied();
812 }
813 MathLib::LinAlg::copy(x, x_old);
814 } // end of for (auto& process_data : _per_process_data)
815
816 if (coupling_iteration_converged && global_coupling_iteration > 0)
817 {
818 break;
819 }
820
821 if (!nonlinear_solver_status.error_norms_met)
822 {
823 return nonlinear_solver_status;
824 }
825 }
826
827 if (!coupling_iteration_converged)
828 {
829 WARN(
830 "The coupling iterations reaches its maximum number in time step "
831 "#{:d} at t = {:g} s",
832 timestep_id, t);
833 }
834
835 {
836 for (auto& process_data : _per_process_data)
837 {
838 auto& pcs = process_data->process;
839 int const process_id = process_data->process_id;
840 auto& ode_sys = *process_data->tdisc_ode_sys;
841 pcs.solveReactionEquation(_process_solutions,
842 _process_solutions_prev, t, dt, ode_sys,
843 process_id);
844 }
845 }
846
847 return nonlinear_solver_status;
848}
void axpy(PETScVector &y, PetscScalar const a, PETScVector const &x)
Definition: LinAlg.cpp:57
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, Output &output_control, std::size_t &xdot_id)
Definition: TimeLoop.cpp:229

References _global_coupling_conv_crit, _global_coupling_max_iterations, _last_step_rejected, _output, _per_process_data, _process_solutions, _process_solutions_prev, _solutions_of_last_cpl_iteration, _xdot_vector_ids, MathLib::LinAlg::axpy(), MathLib::LinAlg::copy(), BaseLib::RunTime::elapsed(), INFO(), ProcessLib::solveOneTimeStepOneProcess(), BaseLib::RunTime::start(), MathLib::t, and WARN().

Referenced by doNonlinearIteration().

◆ solveUncoupledEquationSystems()

NumLib::NonlinearSolverStatus ProcessLib::TimeLoop::solveUncoupledEquationSystems ( const double  t,
const double  dt,
const std::size_t  timestep_id 
)
private

Member to solver non coupled systems of equations, which can be a single system of equations, or several systems of equations without any dependency among the different systems.

Parameters
tCurrent time
dtTime step size
timestep_idIndex of the time step
Returns
true: if all nonlinear solvers convergence. false: if any of nonlinear solvers divergences.

Definition at line 687 of file TimeLoop.cpp.

689{
690 NumLib::NonlinearSolverStatus nonlinear_solver_status;
691
692 _xdot_vector_ids.resize(_per_process_data.size());
693 std::size_t cnt = 0;
694
695 for (auto& process_data : _per_process_data)
696 {
697 auto const process_id = process_data->process_id;
698 nonlinear_solver_status = solveMonolithicProcess(
699 t, dt, timestep_id, *process_data, _process_solutions,
701 cnt++;
702
703 process_data->nonlinear_solver_status = nonlinear_solver_status;
704 if (!nonlinear_solver_status.error_norms_met)
705 {
706 ERR("The nonlinear solver failed in time step #{:d} at t = {:g} s "
707 "for process #{:d}.",
708 timestep_id, t, process_id);
709
710 if (!process_data->timestep_algorithm->canReduceTimestepSize(
711 process_data->timestep_current,
712 process_data->timestep_previous))
713 {
714 // save unsuccessful solution
715 _output->doOutputAlways(
716 process_data->process, process_id, timestep_id, t,
717 process_data->nonlinear_solver_status.number_iterations,
720 }
721
722 return nonlinear_solver_status;
723 }
724 }
725
726 return nonlinear_solver_status;
727}
void ERR(char const *fmt, Args const &... args)
Definition: Logging.h:44
static NumLib::NonlinearSolverStatus solveMonolithicProcess(const double t, const double dt, const std::size_t timestep_id, ProcessData const &process_data, std::vector< GlobalVector * > &x, std::vector< GlobalVector * > const &x_prev, Output &output, std::size_t &xdot_id)
Definition: TimeLoop.cpp:666
static constexpr std::string_view timestepper_cannot_reduce_dt
Definition: TimeLoop.cpp:684

References _output, _per_process_data, _process_solutions, _process_solutions_prev, _xdot_vector_ids, ERR(), NumLib::NonlinearSolverStatus::error_norms_met, OGS_FATAL, ProcessLib::solveMonolithicProcess(), MathLib::t, and ProcessLib::timestepper_cannot_reduce_dt.

Referenced by doNonlinearIteration().

Member Data Documentation

◆ _accepted_steps

std::size_t ProcessLib::TimeLoop::_accepted_steps = 0
private

Definition at line 130 of file TimeLoop.h.

Referenced by calculateNextTimeStep(), executeTimeStep(), initialize(), and outputLastTimeStep().

◆ _current_time

double ProcessLib::TimeLoop::_current_time = _start_time
private

◆ _dt

double ProcessLib::TimeLoop::_dt = 0
private

Definition at line 132 of file TimeLoop.h.

Referenced by calculateNextTimeStep(), executeTimeStep(), and initialize().

◆ _end_time

const double ProcessLib::TimeLoop::_end_time
private

Definition at line 128 of file TimeLoop.h.

Referenced by calculateNextTimeStep(), computeTimeStepping(), endTime(), and initialize().

◆ _global_coupling_conv_crit

std::vector<std::unique_ptr<NumLib::ConvergenceCriterion> > ProcessLib::TimeLoop::_global_coupling_conv_crit
private

Convergence criteria of processes for the global coupling iterations.

Definition at line 140 of file TimeLoop.h.

Referenced by solveCoupledEquationSystemsByStaggeredScheme().

◆ _global_coupling_max_iterations

const int ProcessLib::TimeLoop::_global_coupling_max_iterations
private

Maximum iterations of the global coupling.

Definition at line 137 of file TimeLoop.h.

Referenced by solveCoupledEquationSystemsByStaggeredScheme().

◆ _last_step_rejected

bool ProcessLib::TimeLoop::_last_step_rejected = false
private

◆ _output

std::unique_ptr<Output> ProcessLib::TimeLoop::_output
private

◆ _per_process_data

std::vector<std::unique_ptr<ProcessData> > ProcessLib::TimeLoop::_per_process_data
private

◆ _process_solutions

◆ _process_solutions_prev

std::vector<GlobalVector*> ProcessLib::TimeLoop::_process_solutions_prev
private

◆ _rejected_steps

std::size_t ProcessLib::TimeLoop::_rejected_steps = 0
private

Definition at line 131 of file TimeLoop.h.

Referenced by calculateNextTimeStep(), initialize(), and outputLastTimeStep().

◆ _repeating_times_of_rejected_step

int ProcessLib::TimeLoop::_repeating_times_of_rejected_step = 0
private

Definition at line 133 of file TimeLoop.h.

Referenced by computeTimeStepping().

◆ _solutions_of_last_cpl_iteration

std::vector<GlobalVector*> ProcessLib::TimeLoop::_solutions_of_last_cpl_iteration
private

Solutions of the previous coupling iteration for the convergence criteria of the coupling iteration.

Definition at line 144 of file TimeLoop.h.

Referenced by ~TimeLoop(), setCoupledSolutions(), and solveCoupledEquationSystemsByStaggeredScheme().

◆ _start_time

const double ProcessLib::TimeLoop::_start_time
private

Definition at line 127 of file TimeLoop.h.

Referenced by initialize(), and outputSolutions().

◆ _xdot_vector_ids

std::vector<std::size_t> ProcessLib::TimeLoop::_xdot_vector_ids
private

store the ids of the global xdot vectors in the global vector provider for reuse, needed in postTimestepForAllProcesses the length of the vector is the size of _per_process_data

Definition at line 149 of file TimeLoop.h.

Referenced by doNonlinearIteration(), solveCoupledEquationSystemsByStaggeredScheme(), and solveUncoupledEquationSystems().

◆ successful_time_step

bool ProcessLib::TimeLoop::successful_time_step = false

Definition at line 55 of file TimeLoop.h.

Referenced by executeTimeStep(), and outputLastTimeStep().


The documentation for this class was generated from the following files: