OGS
NumLib::StaggeredCoupling Class Reference

Detailed Description

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

Definition at line 46 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 56 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 49 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 59 of file StaggeredCoupling.h.

61 : global_coupling_max_iterations_(global_coupling_max_iterations),
62 coupling_nodes_(std::move(coupling_nodes))
63 {
64 }
const int global_coupling_max_iterations_
Maximum iteration number of the coupling loop of the staggered scheme.
std::vector< CouplingNodeVariant > coupling_nodes_

◆ ~StaggeredCoupling()

NumLib::StaggeredCoupling::~StaggeredCoupling ( )

Definition at line 23 of file StaggeredCoupling.cpp.

24{
26 {
28 }
29}
std::vector< GlobalVector * > solutions_of_last_cpl_iteration_
virtual void releaseVector(GlobalVector const &x)=0
static NUMLIB_EXPORT VectorProvider & provider

References NumLib::GlobalVectorProvider::provider, NumLib::VectorProvider::releaseVector(), 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 72 of file StaggeredCoupling.cpp.

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

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 21 of file StaggeredCoupling-impl.h.

28{
29 auto const [nonlinear_solver_status, coupling_iteration_converged] =
31 timestep_id, process_solutions, process_solutions_prev,
32 per_process_data, outputs,
33 solve_one_time_step_one_process);
34
35 if (!coupling_iteration_converged)
36 {
37 WARN(
38 "The coupling iterations reaches its maximum number in time step "
39 "#{:d} at t = {:g} s",
40 timestep_id, t);
41 }
42
43 return nonlinear_solver_status;
44}
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
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 81 of file StaggeredCoupling-impl.h.

89{
90 setFirstIterationIndicator(coupling_nodes);
91
92 NumLib::NonlinearSolverStatus nonlinear_solver_status{true, -1};
93
94 bool coupling_iteration_converged = true;
95 for (int global_coupling_iteration = 0;
96 global_coupling_iteration < max_iterations;
97 global_coupling_iteration++,
99 {
100 coupling_iteration_converged = true;
101 for (auto& coupling_node : coupling_nodes)
102 {
103 // For the dummy root node, perform sub-coupling computation.
104 if (std::holds_alternative<RootCouplingNode>(coupling_node))
105 {
106 auto const [local_nonlinear_solver_status,
107 local_coupling_iteration_converged] =
109 coupling_node, t, dt, timestep_id, process_solutions,
110 process_solutions_prev, per_process_data, outputs,
111 solve_one_time_step_one_process);
112
113 if (!local_nonlinear_solver_status.error_norms_met)
114 {
115 coupling_iteration_converged = false;
116 return {local_nonlinear_solver_status,
117 coupling_iteration_converged};
118 }
119
120 coupling_iteration_converged =
121 coupling_iteration_converged &&
122 local_coupling_iteration_converged;
123 continue;
124 }
125
126 CouplingNode const& regular_coupling_node =
127 std::get<CouplingNode>(coupling_node);
128
129 nonlinear_solver_status = executeSingleIteration(
130 global_coupling_iteration, regular_coupling_node, t, dt,
131 timestep_id, process_solutions, process_solutions_prev,
132 per_process_data, outputs, solve_one_time_step_one_process);
133
134 if (!nonlinear_solver_status.error_norms_met)
135 {
136 WARN(
137 "The nonlinear solver failed in time step #{:d} at t = "
138 "{:g} s for process {:s}.",
139 timestep_id, t, regular_coupling_node.process_name);
140 coupling_iteration_converged = false;
141 return {nonlinear_solver_status, coupling_iteration_converged};
142 }
143
144 auto const& x =
145 *process_solutions[regular_coupling_node.process_id];
146
147 // It is unnecessary to check convergence for a process at the first
148 // iteration
149 if (global_coupling_iteration > 0)
150 {
151 coupling_iteration_converged = checkCouplingConvergence(
152 coupling_iteration_converged, regular_coupling_node, x);
153 }
154
155 updatePreviousSolution(regular_coupling_node.process_id, x);
156
157 } // end of for (auto& process_data : _per_process_data)
158
159 // At least to run two coupling iterations, meaning that the coupling
160 // has at least two coupling nodes.
161 if (coupling_iteration_converged && global_coupling_iteration > 0)
162 {
163 break;
164 }
165 }
166
167 return {nonlinear_solver_status, coupling_iteration_converged};
168}
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(), executeSingleIteration(), executeSubCoupling(), NumLib::CouplingNode::process_id, NumLib::CouplingNode::process_name, resetCouplingConvergenceCriteria(), setFirstIterationIndicator(), 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 47 of file StaggeredCoupling-impl.h.

56{
57 BaseLib::RunTime time_timestep_process;
58 time_timestep_process.start();
59
60 auto const process_id = regular_coupling_node.process_id;
61 auto const& process_name = regular_coupling_node.process_name;
62 INFO("Solve process #{:d} (named as {:s})", process_id, process_name);
63
64 auto& process_data = *(per_process_data[process_id]);
65
66 process_data.nonlinear_solver_status = solve_one_time_step_one_process(
67 process_solutions, process_solutions_prev, timestep_id, t, dt,
68 process_data, outputs);
69
70 INFO(
71 "[time] Solving process #{:d} (named as {:s}) took {:g} s in "
72 "time step #{} coupling iteration #{}.",
73 process_id, process_name, time_timestep_process.elapsed(), timestep_id,
74 global_coupling_iteration);
75
76 return process_data.nonlinear_solver_status;
77}
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

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 172 of file StaggeredCoupling-impl.h.

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

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

33{
34 for (auto const* const x : process_solutions)
35 {
36 // Create a vector to store the solution of the last coupling iteration
39
40 // append a solution vector of suitable size
41 solutions_of_last_cpl_iteration_.emplace_back(&x0);
42 }
43}
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:37

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

◆ resetCouplingConvergenceCriteria()

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

Definition at line 59 of file StaggeredCoupling.cpp.

61{
62 auto is_regular_node = [](const CouplingNodeVariant& node)
63 { return std::holds_alternative<CouplingNode>(node); };
64
65 for (auto& coupling_node :
66 coupling_nodes | ranges::views::filter(is_regular_node))
67 {
68 std::get<CouplingNode>(coupling_node).convergence_criterion->reset();
69 }
70}
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 45 of file StaggeredCoupling.cpp.

47{
48 auto is_regular_node = [](const CouplingNodeVariant& node)
49 { return std::holds_alternative<CouplingNode>(node); };
50
51 for (auto const& coupling_node :
52 coupling_nodes | ranges::views::filter(is_regular_node))
53 {
54 std::get<CouplingNode>(coupling_node)
55 .convergence_criterion->preFirstIteration();
56 }
57}

Referenced by executeConcrete().

◆ updatePreviousSolution()

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

Definition at line 97 of file StaggeredCoupling.cpp.

99{
100 auto& x_old = *solutions_of_last_cpl_iteration_[process_id];
101 MathLib::LinAlg::copy(x, x_old);
102}

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 105 of file StaggeredCoupling.h.

Referenced by 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 93 of file StaggeredCoupling.h.

Referenced by 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 150 of file StaggeredCoupling.h.

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


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