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...
 
bool loop ()
 
 ~TimeLoop ()
 

Private Member Functions

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...
 
double computeTimeStepping (const double prev_dt, double &t, std::size_t &accepted_steps, std::size_t &rejected_steps)
 
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
 
bool _last_step_rejected = false
 
int _repeating_times_of_rejected_step = 0
 
const double _start_time
 
const double _end_time
 
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 328 of file TimeLoop.cpp.

334  : _output(std::move(output)),
335  _per_process_data(std::move(per_process_data)),
336  _start_time(start_time),
337  _end_time(end_time),
338  _global_coupling_max_iterations(global_coupling_max_iterations),
339  _global_coupling_conv_crit(std::move(global_coupling_conv_crit))
340 {
341 }
const double _start_time
Definition: TimeLoop.h:115
std::vector< std::unique_ptr< ProcessData > > _per_process_data
Definition: TimeLoop.h:111
const double _end_time
Definition: TimeLoop.h:116
std::vector< std::unique_ptr< NumLib::ConvergenceCriterion > > _global_coupling_conv_crit
Convergence criteria of processes for the global coupling iterations.
Definition: TimeLoop.h:122
const int _global_coupling_max_iterations
Maximum iterations of the global coupling.
Definition: TimeLoop.h:119
std::unique_ptr< Output > _output
Definition: TimeLoop.h:110

◆ ~TimeLoop()

ProcessLib::TimeLoop::~TimeLoop ( )

Definition at line 945 of file TimeLoop.cpp.

946 {
947  for (auto* x : _process_solutions)
948  {
950  }
951  for (auto* x : _process_solutions_prev)
952  {
954  }
955 
956  for (auto* x : _solutions_of_last_cpl_iteration)
957  {
959  }
960 }
virtual void releaseVector(GlobalVector const &x)=0
std::vector< GlobalVector * > _solutions_of_last_cpl_iteration
Definition: TimeLoop.h:126
std::vector< GlobalVector * > _process_solutions
Definition: TimeLoop.h:108
std::vector< GlobalVector * > _process_solutions_prev
Definition: TimeLoop.h:109
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

◆ computeTimeStepping()

double ProcessLib::TimeLoop::computeTimeStepping ( const double  prev_dt,
double &  t,
std::size_t &  accepted_steps,
std::size_t &  rejected_steps 
)
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.

Definition at line 358 of file TimeLoop.cpp.

361 {
362  bool all_process_steps_accepted = true;
363  // Get minimum time step size among step sizes of all processes.
364  double dt = std::numeric_limits<double>::max();
365 
366  bool is_initial_step = false;
367  for (std::size_t i = 0; i < _per_process_data.size(); i++)
368  {
369  auto& ppd = *_per_process_data[i];
370  const auto& timestepper = ppd.timestepper;
371  if (timestepper->getTimeStep().steps() == 0)
372  {
373  is_initial_step = true;
374  }
375 
376  auto& time_disc = ppd.time_disc;
377  auto const& x = *_process_solutions[i];
378  auto const& x_prev = *_process_solutions_prev[i];
379 
380  auto const& conv_crit = ppd.conv_crit;
381  const MathLib::VecNormType norm_type =
382  (conv_crit) ? conv_crit->getVectorNormType()
384 
385  const double solution_error =
386  (timestepper->isSolutionErrorComputationNeeded())
387  ? ((t == timestepper->begin())
388  ? 0. // Always accepts the zeroth step
389  : time_disc->computeRelativeChangeFromPreviousTimestep(
390  x, x_prev, norm_type))
391  : 0.;
392 
393  if (!ppd.nonlinear_solver_status.error_norms_met)
394  {
395  timestepper->setAcceptedOrNot(false);
396  }
397  else
398  {
399  timestepper->setAcceptedOrNot(true);
400  }
401 
402  auto [step_accepted, timestepper_dt] = timestepper->next(
403  solution_error, ppd.nonlinear_solver_status.number_iterations);
404 
405  if (!step_accepted &&
406  // In case of FixedTimeStepping, which makes timestepper->next(...)
407  // return false when the ending time is reached.
408  t + std::numeric_limits<double>::epsilon() < timestepper->end())
409  {
410  // Not all processes have accepted steps.
411  all_process_steps_accepted = false;
412  }
413 
414  if (!ppd.nonlinear_solver_status.error_norms_met)
415  {
416  WARN(
417  "Time step will be rejected due to nonlinear solver "
418  "divergence.");
419  all_process_steps_accepted = false;
420  }
421 
422  if (timestepper_dt > std::numeric_limits<double>::epsilon() ||
423  std::abs(t - timestepper->end()) <
424  std::numeric_limits<double>::epsilon())
425  {
426  dt = std::min(timestepper_dt, dt);
427  }
428  }
429 
430  if (all_process_steps_accepted)
431  {
433  }
434  else
435  {
437  }
438 
439  if (!is_initial_step)
440  {
441  if (all_process_steps_accepted)
442  {
443  accepted_steps++;
444  _last_step_rejected = false;
445  }
446  else
447  {
448  if (t < _end_time || std::abs(t - _end_time) <
449  std::numeric_limits<double>::epsilon())
450  {
451  t -= prev_dt;
452  rejected_steps++;
453  _last_step_rejected = true;
454  }
455  }
456  }
457 
458  // Adjust step size if t < _end_time, while t+dt exceeds the end time
459  if (t < _end_time && t + dt > _end_time)
460  {
461  dt = _end_time - t;
462  }
463 
465  _output->getFixedOutputTimes());
466  // Check whether the time stepping is stabilized
467  if (std::abs(dt - prev_dt) < std::numeric_limits<double>::epsilon())
468  {
470  {
471  OGS_FATAL(
472  "The new step size of {:g} is the same as that of the previous "
473  "rejected time step. \nPlease re-run ogs with a proper "
474  "adjustment in the numerical settings, \ne.g those for time "
475  "stepper, local or global non-linear solver.",
476  dt);
477  }
478  else
479  {
480  DBUG("The time stepping is stabilized with the step size of {:g}.",
481  dt);
482  }
483  }
484 
485  // Reset the time step with the minimum step size, dt
486  // Update the solution of the previous time step.
487  for (std::size_t i = 0; i < _per_process_data.size(); i++)
488  {
489  const auto& ppd = *_per_process_data[i];
490  auto& timestepper = ppd.timestepper;
491  if (all_process_steps_accepted)
492  {
493  timestepper->resetCurrentTimeStep(dt);
494  }
495 
496  if (t == timestepper->begin())
497  {
498  continue;
499  }
500 
501  auto& x = *_process_solutions[i];
502  auto& x_prev = *_process_solutions_prev[i];
503  if (all_process_steps_accepted)
504  {
505  MathLib::LinAlg::copy(x, x_prev); // pushState
506  }
507  else
508  {
509  if (t < _end_time || std::abs(t - _end_time) <
510  std::numeric_limits<double>::epsilon())
511  {
512  WARN(
513  "Time step {:d} was rejected {:d} times and it will be "
514  "repeated with a reduced step size.",
515  accepted_steps + 1, _repeating_times_of_rejected_step);
516  MathLib::LinAlg::copy(x_prev, x); // popState
517  }
518  }
519  }
520 
521  return dt;
522 }
#define OGS_FATAL(...)
Definition: Error.h:26
void DBUG(char const *fmt, Args const &... args)
Definition: Logging.h:27
void WARN(char const *fmt, Args const &... args)
Definition: Logging.h:37
int _repeating_times_of_rejected_step
Definition: TimeLoop.h:114
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
double possiblyClampDtToNextFixedTime(double const t, double const dt, std::vector< double > const &fixed_output_times)

References _end_time, _last_step_rejected, _output, _per_process_data, _process_solutions, _process_solutions_prev, _repeating_times_of_rejected_step, MathLib::LinAlg::copy(), DBUG(), MathLib::NORM2, OGS_FATAL, NumLib::possiblyClampDtToNextFixedTime(), and WARN().

Referenced by loop().

◆ initialize()

void ProcessLib::TimeLoop::initialize ( )

initialize output, convergence criterion, etc.

Definition at line 525 of file TimeLoop.cpp.

526 {
527  for (auto& process_data : _per_process_data)
528  {
529  auto& pcs = process_data->process;
530  int const process_id = process_data->process_id;
531  _output->addProcess(pcs);
532 
533  setTimeDiscretizedODESystem(*process_data);
534 
535  if (auto* conv_crit =
537  process_data->conv_crit.get()))
538  {
539  conv_crit->setDOFTable(pcs.getDOFTable(process_id), pcs.getMesh());
540  }
541  }
542 
543  // initial solution storage
546 
547  // All _per_process_data share the first process.
548  bool const is_staggered_coupling =
550 
551  if (is_staggered_coupling)
552  {
554  }
555 
556  // Output initial conditions
557  {
558  const bool output_initial_condition = true;
559  outputSolutions(output_initial_condition, 0, _start_time, *_output,
561  }
562 }
void doOutput(Process const &process, const int process_id, int const timestep, const double t, int const iteration, std::vector< GlobalVector * > const &x)
Definition: Output.cpp:399
void outputSolutions(bool const output_initial_condition, unsigned timestep, const double t, OutputClass &output_object, OutputClassMember output_class_member) const
Definition: TimeLoop.cpp:868
void setCoupledSolutions()
Definition: TimeLoop.cpp:343
void setTimeDiscretizedODESystem(ProcessData &process_data, NumLib::ODESystem< ODETag, NumLib::NonlinearSolverTag::Picard > &ode_sys)
Definition: TimeLoop.cpp:157
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:216
bool isMonolithicProcess(ProcessLib::ProcessData const &process_data)
Definition: TimeLoop.cpp:82

References _output, _per_process_data, _process_solutions, _process_solutions_prev, _start_time, ProcessLib::Output::doOutput(), anonymous_namespace{TimeLoop.cpp}::isMonolithicProcess(), outputSolutions(), setCoupledSolutions(), ProcessLib::setInitialConditions(), and ProcessLib::setTimeDiscretizedODESystem().

Referenced by main().

◆ loop()

bool ProcessLib::TimeLoop::loop ( )

Definition at line 572 of file TimeLoop.cpp.

573 {
574  // All _per_process_data share the first process.
575  bool const is_staggered_coupling =
577 
578  bool non_equilibrium_initial_residuum_computed = false;
579  double t = _start_time;
580  std::size_t accepted_steps = 0;
581  std::size_t rejected_steps = 0;
582  NumLib::NonlinearSolverStatus nonlinear_solver_status;
583 
584  double dt = computeTimeStepping(0.0, t, accepted_steps, rejected_steps);
585 
586  while (t < _end_time)
587  {
588  BaseLib::RunTime time_timestep;
589  time_timestep.start();
590 
591  t += dt;
592  const double prev_dt = dt;
593 
594  const std::size_t timesteps = accepted_steps + 1;
595  // TODO(wenqing): , input option for time unit.
596  INFO(
597  "=== Time stepping at step #{:d} and time {:g} with step size {:g}",
598  timesteps, t, dt);
599 
600  // Check element deactivation:
601  for (auto& process_data : _per_process_data)
602  {
603  process_data->process.updateDeactivatedSubdomains(
604  t, process_data->process_id);
605  }
606 
607  if (!non_equilibrium_initial_residuum_computed)
608  {
611  non_equilibrium_initial_residuum_computed = true;
612  }
613 
616 
617  if (is_staggered_coupling)
618  {
619  nonlinear_solver_status =
621  }
622  else
623  {
624  nonlinear_solver_status =
625  solveUncoupledEquationSystems(t, dt, timesteps);
626  }
627 
628  // Run post time step only if the last iteration was successful.
629  // Otherwise it runs the risks to get the same errors as in the last
630  // iteration, an exception thrown in assembly, for example.
631  if (nonlinear_solver_status.error_norms_met)
632  {
636  }
637 
638  INFO("[time] Time step #{:d} took {:g} s.", timesteps,
639  time_timestep.elapsed());
640 
641  double const current_time = t;
642  // _last_step_rejected is also checked in computeTimeStepping.
643  dt = computeTimeStepping(prev_dt, t, accepted_steps, rejected_steps);
644 
645  if (!_last_step_rejected)
646  {
647  const bool output_initial_condition = false;
648  outputSolutions(output_initial_condition, timesteps, current_time,
650  }
651 
652  if (std::abs(t - _end_time) < std::numeric_limits<double>::epsilon() ||
653  t + dt > _end_time)
654  {
655  break;
656  }
657 
658  if (dt < std::numeric_limits<double>::epsilon())
659  {
660  WARN(
661  "Time step size of {:g} is too small.\n"
662  "Time stepping stops at step {:d} and at time of {:g}.",
663  dt, timesteps, t);
664  break;
665  }
666  }
667 
668  INFO(
669  "The whole computation of the time stepping took {:d} steps, in which\n"
670  "\t the accepted steps are {:d}, and the rejected steps are {:d}.\n",
671  accepted_steps + rejected_steps, accepted_steps, rejected_steps);
672 
673  // output last time step
674  if (nonlinear_solver_status.error_norms_met)
675  {
676  const bool output_initial_condition = false;
677  outputSolutions(output_initial_condition,
678  accepted_steps + rejected_steps, t, *_output,
680  }
681 
682  return nonlinear_solver_status.error_norms_met;
683 }
void INFO(char const *fmt, Args const &... args)
Definition: Logging.h:32
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
void doOutputLastTimestep(Process const &process, const int process_id, int const timestep, const double t, int const iteration, std::vector< GlobalVector * > const &x)
Definition: Output.cpp:418
std::vector< std::size_t > _xdot_vector_ids
Definition: TimeLoop.h:131
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:706
double computeTimeStepping(const double prev_dt, double &t, std::size_t &accepted_steps, std::size_t &rejected_steps)
Definition: TimeLoop.cpp:358
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:747
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:103
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:251
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:90
Status of the non-linear solver.

References _end_time, _last_step_rejected, _output, _per_process_data, _process_solutions, _process_solutions_prev, _start_time, _xdot_vector_ids, ProcessLib::calculateNonEquilibriumInitialResiduum(), computeTimeStepping(), ProcessLib::Output::doOutput(), ProcessLib::Output::doOutputLastTimestep(), BaseLib::RunTime::elapsed(), NumLib::NonlinearSolverStatus::error_norms_met, INFO(), anonymous_namespace{TimeLoop.cpp}::isMonolithicProcess(), outputSolutions(), ProcessLib::postTimestepForAllProcesses(), ProcessLib::preTimestepForAllProcesses(), solveCoupledEquationSystemsByStaggeredScheme(), solveUncoupledEquationSystems(), BaseLib::RunTime::start(), and WARN().

◆ 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 868 of file TimeLoop.cpp.

872 {
873  // All _per_process_data share the first process.
874  bool const is_staggered_coupling =
876 
877  for (auto& process_data : _per_process_data)
878  {
879  // If nonlinear solver diverged, the solution has already been
880  // saved.
881  if (!process_data->nonlinear_solver_status.error_norms_met)
882  {
883  continue;
884  }
885 
886  auto const process_id = process_data->process_id;
887  auto& pcs = process_data->process;
888 
889  if (!is_staggered_coupling && output_initial_condition)
890  {
891  auto const& ode_sys = *process_data->tdisc_ode_sys;
892  // dummy value to handle the time derivative terms more or less
893  // correctly, i.e. to ignore them.
894  double const dt = 1;
895  process_data->time_disc->nextTimestep(t, dt);
896 
898  ode_sys.getMatrixSpecifications(process_id));
899  x_dot.setZero();
900 
901  pcs.preTimestep(_process_solutions, _start_time, dt, process_id);
902  // Update secondary variables, which might be uninitialized, before
903  // output.
904  pcs.computeSecondaryVariable(_start_time, dt, _process_solutions,
905  x_dot, process_id);
906 
908  }
909  if (is_staggered_coupling && output_initial_condition)
910  {
911  CoupledSolutionsForStaggeredScheme coupled_solutions(
913 
914  process_data->process.setCoupledSolutionsForStaggeredScheme(
915  &coupled_solutions);
916  process_data->process
917  .setCoupledTermForTheStaggeredSchemeToLocalAssemblers(
918  process_id);
919 
920  auto const& ode_sys = *process_data->tdisc_ode_sys;
921  // dummy value to handle the time derivative terms more or less
922  // correctly, i.e. to ignore them.
923  double const dt = 1;
924  process_data->time_disc->nextTimestep(t, dt);
925 
927  ode_sys.getMatrixSpecifications(process_id));
928  x_dot.setZero();
929 
930  pcs.preTimestep(_process_solutions, _start_time, dt, process_id);
931  // Update secondary variables, which might be uninitialized, before
932  // output.
933  pcs.computeSecondaryVariable(_start_time, dt, _process_solutions,
934  x_dot, process_id);
935 
937  }
938  (output_object.*output_class_member)(
939  pcs, process_id, timestep, t,
940  process_data->nonlinear_solver_status.number_iterations,
942  }
943 }
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(), and MathLib::EigenVector::setZero().

Referenced by initialize(), and loop().

◆ 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 343 of file TimeLoop.cpp.

344 {
345  for (auto& process_data : _per_process_data)
346  {
347  auto const& x = *_process_solutions[process_data->process_id];
348 
349  // Create a vector to store the solution of the last coupling iteration
351  MathLib::LinAlg::copy(x, x0);
352 
353  // append a solution vector of suitable size
354  _solutions_of_last_cpl_iteration.emplace_back(&x0);
355  }
356 }

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 747 of file TimeLoop.cpp.

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

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(), and WARN().

Referenced by loop().

◆ 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 706 of file TimeLoop.cpp.

708 {
709  NumLib::NonlinearSolverStatus nonlinear_solver_status;
710 
711  _xdot_vector_ids.resize(_per_process_data.size());
712  std::size_t cnt = 0;
713 
714  for (auto& process_data : _per_process_data)
715  {
716  auto const process_id = process_data->process_id;
717  nonlinear_solver_status = solveMonolithicProcess(
718  t, dt, timestep_id, *process_data, _process_solutions,
720  cnt++;
721 
722  process_data->nonlinear_solver_status = nonlinear_solver_status;
723  if (!nonlinear_solver_status.error_norms_met)
724  {
725  ERR("The nonlinear solver failed in time step #{:d} at t = {:g} s "
726  "for process #{:d}.",
727  timestep_id, t, process_id);
728 
729  if (!process_data->timestepper->canReduceTimestepSize())
730  {
731  // save unsuccessful solution
732  _output->doOutputAlways(
733  process_data->process, process_id, timestep_id, t,
734  process_data->nonlinear_solver_status.number_iterations,
737  }
738 
739  return nonlinear_solver_status;
740  }
741  }
742 
743  return nonlinear_solver_status;
744 }
void ERR(char const *fmt, Args const &... args)
Definition: Logging.h:42
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:685
static constexpr std::string_view timestepper_cannot_reduce_dt
Definition: TimeLoop.cpp:703

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

Referenced by loop().

Member Data Documentation

◆ _end_time

const double ProcessLib::TimeLoop::_end_time
private

Definition at line 116 of file TimeLoop.h.

Referenced by computeTimeStepping(), and loop().

◆ _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 122 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 119 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

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

◆ _process_solutions_prev

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

◆ _repeating_times_of_rejected_step

int ProcessLib::TimeLoop::_repeating_times_of_rejected_step = 0
private

Definition at line 114 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 126 of file TimeLoop.h.

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

◆ _start_time

const double ProcessLib::TimeLoop::_start_time
private

Definition at line 115 of file TimeLoop.h.

Referenced by initialize(), loop(), 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 131 of file TimeLoop.h.

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


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