OGS
NumLib::StaggeredCoupling Class Reference

Detailed Description

A class designed to manage the solution of coupled equations using the staggered method.

Definition at line 38 of file StaggeredCoupling.h.

#include <StaggeredCoupling.h>

Public Member Functions

 StaggeredCoupling (const int global_coupling_max_iterations, std::vector< CouplingNodeVariant > &&coupling_nodes)
 ~StaggeredCoupling ()
void initializeCoupledSolutions (std::vector< GlobalVector * > const &process_solutions)
template<typename ProcessData, typename Output>
NumLib::NonlinearSolverStatus execute (const double t, const double dt, const std::size_t timestep_id, std::vector< GlobalVector * > &process_solutions, std::vector< GlobalVector * > const &process_solutions_prev, std::vector< std::unique_ptr< ProcessData > > const &per_process_data, std::vector< Output > const &outputs, ProcessSolver< ProcessData, Output > const &solve_one_time_step_one_process)

Private Types

template<typename ProcessData, typename Output>
using ProcessSolver
using CouplingNodeVariant = std::variant<CouplingNode, RootCouplingNode>

Private Member Functions

template<typename ProcessData, typename Output>
std::tuple< NumLib::NonlinearSolverStatus, bool > executeConcrete (std::vector< CouplingNodeVariant > &coupling_nodes, const int max_iterations, const double t, const double dt, const std::size_t timestep_id, std::vector< GlobalVector * > &process_solutions, std::vector< GlobalVector * > const &process_solutions_prev, std::vector< std::unique_ptr< ProcessData > > const &per_process_data, std::vector< Output > const &outputs, ProcessSolver< ProcessData, Output > const &solve_one_time_step_one_process)
template<typename ProcessData, typename Output>
std::tuple< NumLib::NonlinearSolverStatus, bool > executeSubCoupling (CouplingNodeVariant &coupling_node, const double t, const double dt, const std::size_t timestep_id, std::vector< GlobalVector * > &process_solutions, std::vector< GlobalVector * > const &process_solutions_prev, std::vector< std::unique_ptr< ProcessData > > const &per_process_data, std::vector< Output > const &outputs, ProcessSolver< ProcessData, Output > const &solve_one_time_step_one_process)
template<typename ProcessData, typename Output>
NumLib::NonlinearSolverStatus executeSingleIteration (int const global_coupling_iteration, CouplingNode const &regular_coupling_node, const double t, const double dt, const std::size_t timestep_id, std::vector< GlobalVector * > &process_solutions, std::vector< GlobalVector * > const &process_solutions_prev, std::vector< std::unique_ptr< ProcessData > > const &per_process_data, std::vector< Output > const &outputs, ProcessSolver< ProcessData, Output > const &solve_one_time_step_one_process)
void setFirstIterationIndicator (std::vector< CouplingNodeVariant > const &coupling_nodes)
 Set the indicator of the first staggered coupling iteration be true.
void resetCouplingConvergenceCriteria (std::vector< CouplingNodeVariant > const &coupling_nodes)
bool checkCouplingConvergence (const bool convergence_of_last_process, CouplingNode const &coupling_node, GlobalVector const &x) const
void updatePreviousSolution (int const process_id, GlobalVector const &x)

Private Attributes

const int global_coupling_max_iterations_
 Maximum iteration number of the coupling loop of the staggered scheme.
std::vector< CouplingNodeVariantcoupling_nodes_
std::vector< GlobalVector * > solutions_of_last_cpl_iteration_

Member Typedef Documentation

◆ CouplingNodeVariant

Definition at line 48 of file StaggeredCoupling.h.

◆ ProcessSolver

template<typename ProcessData, typename Output>
using NumLib::StaggeredCoupling::ProcessSolver
private
Initial value:
std::vector<GlobalVector*>& ,
std::vector<GlobalVector*> const& ,
std::size_t const , double const ,
double const , ProcessData const& ,
std::vector<Output> const& )>
Status of the non-linear solver.

Definition at line 41 of file StaggeredCoupling.h.

Constructor & Destructor Documentation

◆ StaggeredCoupling()

NumLib::StaggeredCoupling::StaggeredCoupling ( const int global_coupling_max_iterations,
std::vector< CouplingNodeVariant > && coupling_nodes )
inline

Definition at line 51 of file StaggeredCoupling.h.

53 : global_coupling_max_iterations_(global_coupling_max_iterations),
54 coupling_nodes_(std::move(coupling_nodes))
55 {
56 }
const int global_coupling_max_iterations_
Maximum iteration number of the coupling loop of the staggered scheme.
std::vector< CouplingNodeVariant > coupling_nodes_

References coupling_nodes_, and global_coupling_max_iterations_.

◆ ~StaggeredCoupling()

NumLib::StaggeredCoupling::~StaggeredCoupling ( )

Definition at line 16 of file StaggeredCoupling.cpp.

17{
19 {
21 }
22}
std::vector< GlobalVector * > solutions_of_last_cpl_iteration_
virtual void releaseVector(GlobalVector const &x)=0
static NUMLIB_EXPORT VectorProvider & provider

References NumLib::GlobalVectorProvider::provider, and solutions_of_last_cpl_iteration_.

Member Function Documentation

◆ checkCouplingConvergence()

bool NumLib::StaggeredCoupling::checkCouplingConvergence ( const bool convergence_of_last_process,
CouplingNode const & coupling_node,
GlobalVector const & x ) const
private

Definition at line 65 of file StaggeredCoupling.cpp.

69{
70 bool is_coupling_iteration_converged = convergence_of_last_process;
71
72 auto& x_old = *solutions_of_last_cpl_iteration_[coupling_node.process_id];
73 // Since x_old can be immediately refreshed after computing dx,
74 // it is assigned with dx to save memory usage
75 MathLib::LinAlg::axpy(x_old, -1.0, x); // save dx = x - x_old to x_old.
76 INFO(
77 "------- Checking convergence criterion for coupled "
78 "solution of process {:s} with ID {:d} -------",
79 coupling_node.process_name, coupling_node.process_id);
80 // Note: x_old stores dx
81 coupling_node.convergence_criterion->checkDeltaX(x_old, x);
82
83 is_coupling_iteration_converged =
84 is_coupling_iteration_converged &&
85 coupling_node.convergence_criterion->isSatisfied();
86
87 return is_coupling_iteration_converged;
88}
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:28
void axpy(PETScVector &y, PetscScalar const a, PETScVector const &x)
Definition LinAlg.cpp:50

References MathLib::LinAlg::axpy(), NumLib::CouplingNode::convergence_criterion, INFO(), NumLib::CouplingNode::process_id, NumLib::CouplingNode::process_name, and solutions_of_last_cpl_iteration_.

Referenced by executeConcrete().

◆ execute()

template<typename ProcessData, typename Output>
NumLib::NonlinearSolverStatus NumLib::StaggeredCoupling::execute ( const double t,
const double dt,
const std::size_t timestep_id,
std::vector< GlobalVector * > & process_solutions,
std::vector< GlobalVector * > const & process_solutions_prev,
std::vector< std::unique_ptr< ProcessData > > const & per_process_data,
std::vector< Output > const & outputs,
ProcessSolver< ProcessData, Output > const & solve_one_time_step_one_process )

It solves the equations of all coupled processes by the staggered method, and it returns nonlinear solver status.

Definition at line 14 of file StaggeredCoupling-impl.h.

21{
22 auto const [nonlinear_solver_status, coupling_iteration_converged] =
24 timestep_id, process_solutions, process_solutions_prev,
25 per_process_data, outputs,
26 solve_one_time_step_one_process);
27
28 if (!coupling_iteration_converged)
29 {
30 WARN(
31 "The coupling iterations reaches its maximum number in time step "
32 "#{:d} at t = {:g}",
33 timestep_id, t);
34 }
35
36 return nonlinear_solver_status;
37}
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:34
std::tuple< NumLib::NonlinearSolverStatus, bool > executeConcrete(std::vector< CouplingNodeVariant > &coupling_nodes, const int max_iterations, const double t, const double dt, const std::size_t timestep_id, std::vector< GlobalVector * > &process_solutions, std::vector< GlobalVector * > const &process_solutions_prev, std::vector< std::unique_ptr< ProcessData > > const &per_process_data, std::vector< Output > const &outputs, ProcessSolver< ProcessData, Output > const &solve_one_time_step_one_process)

References coupling_nodes_, executeConcrete(), global_coupling_max_iterations_, and WARN().

◆ executeConcrete()

template<typename ProcessData, typename Output>
std::tuple< NumLib::NonlinearSolverStatus, bool > NumLib::StaggeredCoupling::executeConcrete ( std::vector< CouplingNodeVariant > & coupling_nodes,
const int max_iterations,
const double t,
const double dt,
const std::size_t timestep_id,
std::vector< GlobalVector * > & process_solutions,
std::vector< GlobalVector * > const & process_solutions_prev,
std::vector< std::unique_ptr< ProcessData > > const & per_process_data,
std::vector< Output > const & outputs,
ProcessSolver< ProcessData, Output > const & solve_one_time_step_one_process )
private

It solves the equation of each coupling process (treated as a coupling node) via function recursion, and it returns nonlinear solver status, and an indicator of coupling iteration convergence.

Definition at line 74 of file StaggeredCoupling-impl.h.

82{
83 setFirstIterationIndicator(coupling_nodes);
84
85 NumLib::NonlinearSolverStatus nonlinear_solver_status{true, -1};
86
87 bool coupling_iteration_converged = true;
88 for (int global_coupling_iteration = 0;
89 global_coupling_iteration < max_iterations;
90 global_coupling_iteration++,
92 {
93 coupling_iteration_converged = true;
94
95 INFO("Global coupling iteration #{:d} started.",
96 global_coupling_iteration);
97 BaseLib::RunTime coupling_iteration_timer;
98 coupling_iteration_timer.start();
99
100 for (auto& coupling_node : coupling_nodes)
101 {
102 // For the dummy root node, perform sub-coupling computation.
103 if (std::holds_alternative<RootCouplingNode>(coupling_node))
104 {
105 auto const [local_nonlinear_solver_status,
106 local_coupling_iteration_converged] =
108 coupling_node, t, dt, timestep_id, process_solutions,
109 process_solutions_prev, per_process_data, outputs,
110 solve_one_time_step_one_process);
111
112 if (!local_nonlinear_solver_status.error_norms_met)
113 {
114 coupling_iteration_converged = false;
115 return {local_nonlinear_solver_status,
116 coupling_iteration_converged};
117 }
118
119 coupling_iteration_converged =
120 coupling_iteration_converged &&
121 local_coupling_iteration_converged;
122 continue;
123 }
124
125 CouplingNode const& regular_coupling_node =
126 std::get<CouplingNode>(coupling_node);
127
128 nonlinear_solver_status = executeSingleIteration(
129 global_coupling_iteration, regular_coupling_node, t, dt,
130 timestep_id, process_solutions, process_solutions_prev,
131 per_process_data, outputs, solve_one_time_step_one_process);
132
133 if (!nonlinear_solver_status.error_norms_met)
134 {
135 WARN(
136 "The nonlinear solver failed in time step #{:d} at t = "
137 "{:g} s for process {:s}.",
138 timestep_id, t, regular_coupling_node.process_name);
139 coupling_iteration_converged = false;
140 return {nonlinear_solver_status, coupling_iteration_converged};
141 }
142
143 auto const& x =
144 *process_solutions[regular_coupling_node.process_id];
145
146 // It is unnecessary to check convergence for a process at the first
147 // iteration
148 if (global_coupling_iteration > 0)
149 {
150 coupling_iteration_converged = checkCouplingConvergence(
151 coupling_iteration_converged, regular_coupling_node, x);
152 }
153
154 updatePreviousSolution(regular_coupling_node.process_id, x);
155
156 } // end of for (auto& process_data : _per_process_data)
157
158 // At least to run two coupling iterations, meaning that the coupling
159 // has at least two coupling nodes.
160 INFO("Global coupling iteration #{:d} took {:g} s.",
161 global_coupling_iteration, coupling_iteration_timer.elapsed());
162 if (coupling_iteration_converged && global_coupling_iteration > 0)
163 {
164 break;
165 }
166 }
167
168 return {nonlinear_solver_status, coupling_iteration_converged};
169}
double elapsed() const
Get the elapsed time in seconds.
Definition RunTime.h:31
void start()
Start the timer.
Definition RunTime.h:21
NumLib::NonlinearSolverStatus executeSingleIteration(int const global_coupling_iteration, CouplingNode const &regular_coupling_node, const double t, const double dt, const std::size_t timestep_id, std::vector< GlobalVector * > &process_solutions, std::vector< GlobalVector * > const &process_solutions_prev, std::vector< std::unique_ptr< ProcessData > > const &per_process_data, std::vector< Output > const &outputs, ProcessSolver< ProcessData, Output > const &solve_one_time_step_one_process)
void resetCouplingConvergenceCriteria(std::vector< CouplingNodeVariant > const &coupling_nodes)
void setFirstIterationIndicator(std::vector< CouplingNodeVariant > const &coupling_nodes)
Set the indicator of the first staggered coupling iteration be true.
bool checkCouplingConvergence(const bool convergence_of_last_process, CouplingNode const &coupling_node, GlobalVector const &x) const
std::tuple< NumLib::NonlinearSolverStatus, bool > executeSubCoupling(CouplingNodeVariant &coupling_node, const double t, const double dt, const std::size_t timestep_id, std::vector< GlobalVector * > &process_solutions, std::vector< GlobalVector * > const &process_solutions_prev, std::vector< std::unique_ptr< ProcessData > > const &per_process_data, std::vector< Output > const &outputs, ProcessSolver< ProcessData, Output > const &solve_one_time_step_one_process)
void updatePreviousSolution(int const process_id, GlobalVector const &x)

References checkCouplingConvergence(), BaseLib::RunTime::elapsed(), NumLib::NonlinearSolverStatus::error_norms_met, executeSingleIteration(), executeSubCoupling(), INFO(), NumLib::CouplingNode::process_id, NumLib::CouplingNode::process_name, resetCouplingConvergenceCriteria(), setFirstIterationIndicator(), BaseLib::RunTime::start(), updatePreviousSolution(), and WARN().

Referenced by execute(), and executeSubCoupling().

◆ executeSingleIteration()

template<typename ProcessData, typename Output>
NumLib::NonlinearSolverStatus NumLib::StaggeredCoupling::executeSingleIteration ( int const global_coupling_iteration,
CouplingNode const & regular_coupling_node,
const double t,
const double dt,
const std::size_t timestep_id,
std::vector< GlobalVector * > & process_solutions,
std::vector< GlobalVector * > const & process_solutions_prev,
std::vector< std::unique_ptr< ProcessData > > const & per_process_data,
std::vector< Output > const & outputs,
ProcessSolver< ProcessData, Output > const & solve_one_time_step_one_process )
private

Definition at line 40 of file StaggeredCoupling-impl.h.

49{
50 BaseLib::RunTime time_timestep_process;
51 time_timestep_process.start();
52
53 auto const process_id = regular_coupling_node.process_id;
54 auto const& process_name = regular_coupling_node.process_name;
55 INFO("Solve process #{:d} (named as {:s})", process_id, process_name);
56
57 auto& process_data = *(per_process_data[process_id]);
58
59 process_data.nonlinear_solver_status = solve_one_time_step_one_process(
60 process_solutions, process_solutions_prev, timestep_id, t, dt,
61 process_data, outputs);
62
63 INFO(
64 "[time] Solving process #{:d} (named as {:s}) took {:g} s in "
65 "time step #{} coupling iteration #{}.",
66 process_id, process_name, time_timestep_process.elapsed(), timestep_id,
67 global_coupling_iteration);
68
69 return process_data.nonlinear_solver_status;
70}

References BaseLib::RunTime::elapsed(), INFO(), NumLib::CouplingNode::process_id, NumLib::CouplingNode::process_name, and BaseLib::RunTime::start().

Referenced by executeConcrete().

◆ executeSubCoupling()

template<typename ProcessData, typename Output>
std::tuple< NumLib::NonlinearSolverStatus, bool > NumLib::StaggeredCoupling::executeSubCoupling ( CouplingNodeVariant & coupling_node,
const double t,
const double dt,
const std::size_t timestep_id,
std::vector< GlobalVector * > & process_solutions,
std::vector< GlobalVector * > const & process_solutions_prev,
std::vector< std::unique_ptr< ProcessData > > const & per_process_data,
std::vector< Output > const & outputs,
ProcessSolver< ProcessData, Output > const & solve_one_time_step_one_process )
private

Definition at line 173 of file StaggeredCoupling-impl.h.

181{
182 INFO("--- Execute sub-coupling:");
183 RootCouplingNode& root_coupling_node =
184 std::get<RootCouplingNode>(coupling_node);
185 const int local_max_iterations =
186 std::get<CouplingNode>(root_coupling_node.sub_coupling_nodes.front())
187 .max_iterations;
188
189 auto const [sub_nonlinear_solver_status, sub_coupling_iteration_converged] =
191 root_coupling_node.sub_coupling_nodes, local_max_iterations, t, dt,
192 timestep_id, process_solutions, process_solutions_prev,
193 per_process_data, outputs, solve_one_time_step_one_process);
194
195 INFO("--- End sub-coupling.");
196 return {sub_nonlinear_solver_status, sub_coupling_iteration_converged};
197}

References executeConcrete(), INFO(), and NumLib::RootCouplingNode::sub_coupling_nodes.

Referenced by executeConcrete().

◆ initializeCoupledSolutions()

void NumLib::StaggeredCoupling::initializeCoupledSolutions ( std::vector< GlobalVector * > const & process_solutions)

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 24 of file StaggeredCoupling.cpp.

26{
27 for (auto const* const x : process_solutions)
28 {
29 // Create a vector to store the solution of the last coupling iteration
32
33 // append a solution vector of suitable size
34 solutions_of_last_cpl_iteration_.emplace_back(&x0);
35 }
36}
virtual GlobalVector & getVector(std::size_t &id)=0
Get an uninitialized vector with the given id.
void copy(PETScVector const &x, PETScVector &y)
Definition LinAlg.cpp:30

References MathLib::LinAlg::copy(), NumLib::GlobalVectorProvider::provider, and solutions_of_last_cpl_iteration_.

◆ resetCouplingConvergenceCriteria()

void NumLib::StaggeredCoupling::resetCouplingConvergenceCriteria ( std::vector< CouplingNodeVariant > const & coupling_nodes)
private

Definition at line 52 of file StaggeredCoupling.cpp.

54{
55 auto is_regular_node = [](const CouplingNodeVariant& node)
56 { return std::holds_alternative<CouplingNode>(node); };
57
58 for (auto& coupling_node :
59 coupling_nodes | ranges::views::filter(is_regular_node))
60 {
61 std::get<CouplingNode>(coupling_node).convergence_criterion->reset();
62 }
63}
std::variant< CouplingNode, RootCouplingNode > CouplingNodeVariant

Referenced by executeConcrete().

◆ setFirstIterationIndicator()

void NumLib::StaggeredCoupling::setFirstIterationIndicator ( std::vector< CouplingNodeVariant > const & coupling_nodes)
private

Set the indicator of the first staggered coupling iteration be true.

Definition at line 38 of file StaggeredCoupling.cpp.

40{
41 auto is_regular_node = [](const CouplingNodeVariant& node)
42 { return std::holds_alternative<CouplingNode>(node); };
43
44 for (auto const& coupling_node :
45 coupling_nodes | ranges::views::filter(is_regular_node))
46 {
47 std::get<CouplingNode>(coupling_node)
48 .convergence_criterion->preFirstIteration();
49 }
50}

Referenced by executeConcrete().

◆ updatePreviousSolution()

void NumLib::StaggeredCoupling::updatePreviousSolution ( int const process_id,
GlobalVector const & x )
private

Definition at line 90 of file StaggeredCoupling.cpp.

92{
93 auto& x_old = *solutions_of_last_cpl_iteration_[process_id];
94 MathLib::LinAlg::copy(x, x_old);
95}

References MathLib::LinAlg::copy(), and solutions_of_last_cpl_iteration_.

Referenced by executeConcrete().

Member Data Documentation

◆ coupling_nodes_

std::vector<CouplingNodeVariant> NumLib::StaggeredCoupling::coupling_nodes_
private

Coupling graph for the staggered scheme. It looks like:

x ... x o o / \ / \ / \ / \ x ... x x ... x

where x represents a coupling node, and o represents a dummy root coupling node.

Definition at line 97 of file StaggeredCoupling.h.

Referenced by StaggeredCoupling(), and execute().

◆ global_coupling_max_iterations_

const int NumLib::StaggeredCoupling::global_coupling_max_iterations_
private

Maximum iteration number of the coupling loop of the staggered scheme.

Definition at line 85 of file StaggeredCoupling.h.

Referenced by StaggeredCoupling(), and execute().

◆ solutions_of_last_cpl_iteration_

std::vector<GlobalVector*> NumLib::StaggeredCoupling::solutions_of_last_cpl_iteration_
private

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

Definition at line 142 of file StaggeredCoupling.h.

Referenced by ~StaggeredCoupling(), checkCouplingConvergence(), initializeCoupledSolutions(), and updatePreviousSolution().


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