Sandals  v0.0.0
A C++ library for ODEs/DAEs integration
Loading...
Searching...
No Matches
Problem.hh
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
2 * Copyright (c) 2025, Davide Stocco and Enrico Bertolazzi. *
3 * *
4 * The Sandals project is distributed under the BSD 2-Clause License. *
5 * *
6 * Davide Stocco Enrico Bertolazzi *
7 * University of Trento University of Trento *
8 * e-mail: davide.stocco@unitn.it e-mail: enrico.bertolazzi@unitn.it *
9\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10
11#ifndef SANDALS_PROBLEM_HH
12#define SANDALS_PROBLEM_HH
13
14#include <Sandals/RungeKutta.hh>
15
16namespace Sandals
17{
18
19 /*\
20 |. ____ _ _
21 |. | _ \ _ __ ___ | |__ | | ___ _ __ ___
22 |. | |_) | '__/ _ \| '_ \| |/ _ \ '_ ` _ \
23 |. | __/| | | (_) | |_) | | __/ | | | | |
24 |. |_| |_| \___/|_.__/|_|\___|_| |_| |_|
25 |.
26 \*/
27
37 template <typename Real, Integer N, Integer M, typename Integrator>
38 class Problem
39 {
40 public:
42 const Real SQRT_EPSILON{std::sqrt(EPSILON)}; \
43
45 using IntegratorPtr = std::shared_ptr<Integrator>;
46 using SolutionPtr = std::shared_ptr<Solution<Real, N, M>>;
47
48 using VectorX = typename Integrator::VectorX;
49 using MatrixJX = typename Integrator::MatrixJX;
52
53 private:
54 std::string m_name{"(undefined)"};
58
59 bool m_verbose{false};
60 Real m_tolerance{EPSILON_HIGH};
62
63 public:
70 Problem(std::string t_name, SystemPtr t_system, IntegratorPtr t_integrator)
71 : m_name(t_name), m_integrator(t_integrator)
72 {
73 this->m_integrator->system(t_system);
74 this->m_solution = std::make_shared<Solution<Real, N, M>>();
75 }
76
80 virtual ~Problem() {}
81
86 std::string name() const {return this->m_name;}
87
92 void name(std::string const t_name) {this->m_name = t_name;}
93
98 SystemPtr system() {return this->m_integrator->system();}
99
104 void system(SystemPtr t_system) {this->m_integrator->system(t_system);}
105
110 IntegratorPtr integrator() {return this->m_integrator;}
111
116 void integrator(IntegratorPtr t_integrator) {this->m_integrator = t_integrator;}
117
122 SolutionPtr const solution() const {return this->m_solution;}
123
128 bool verbose_mode() {return this->m_verbose;}
129
134 void verbose_mode(bool t_verbose) {
135 this->m_verbose = t_verbose;
136 this->m_integrator->verbose_mode(t_verbose);
137 }
138
142 void enable_verbose_mode() {this->verbose_mode(true);}
143
147 void disable_verbose_mode() {this->verbose_mode(false);}
148
153 Real tolerance() {return this->m_tolerance;}
154
159 void tolerance(Real const t_tolerance)
160 {this->m_tolerance = t_tolerance;}
161
166 Integer & max_iterations() {return this->m_max_iterations;}
167
172 void max_iterations(Integer const t_max_iterations)
173 {this->m_max_iterations = t_max_iterations;}
174
182 virtual VectorF b(VectorF const & x_ini, VectorF const & x_end) const = 0;
183
192 virtual MatrixJF Jb_x_ini(VectorF const & x_ini, VectorF const & x_end) const = 0;
193
202 virtual MatrixJF Jb_x_end(VectorF const & x_ini, VectorF const & x_end) const = 0;
203
213 bool single_shooting(VectorX const & t_mesh, VectorF const & ics)
214 {
215 using ShootingF = Eigen::Matrix<Real, 2*N, 1>;
216 using ShootingJF = Eigen::Matrix<Real, 2*N, 2*N>;
217
218 #define CMD "Sandals::Problem::single_shooting(...): "
219
220 // Temporary variables
221 VectorF bcs, x_ini, x_end;
222 ShootingF x_sol, x_step, b;
223 ShootingJF A(ShootingJF::Zero());
224 A.template block<N, N>(0, N) = MatrixJX::Identity();
225
226 // Initialize the guess and the solution
227 x_sol << ics, ics;
228 this->m_solution->clear();
229
230 // Solve the boundary value problem using a linearized Newton method
231 MatrixJX Jx(MatrixJX::Identity());
232 Eigen::FullPivLU<ShootingJF> lu;
233 for (Integer i{0}; i < this->m_max_iterations; ++i) {
234
235 /* Single shooting method
236 [A] {x} = {f}
237 / -Jx I \ / \ / x_end - x_sol_end \
238 | | | dx | = | |
239 \ Jb_x_ini Jb_x_end / \ / \ -b /
240 */
241
242 // Integrate the system and propagate the Jacobian
243 if (!this->m_integrator->solve(t_mesh, x_sol.template head<N>(), *this->m_solution, Jx)) {
244 SANDALS_ERROR(CMD "failed to integrate the system " << this->m_integrator->name() << ".");
245 return false;
246 }
247
248 // Retrieve the initial and final states
249 x_ini = x_sol.template head<N>();
250 x_end = this->m_solution->x.col(this->m_solution->t.size() - 1);
251
252 // Evaluate the residual of the boundary conditions
253 bcs = this->b(x_ini, x_end);
254
255 // Print the iteration info
256 if (this->m_verbose) {
257 std::cout << "Iteration " << i << ": |b| = " << bcs.norm() << std::endl
258 << " x(" << t_mesh.template head<1>() << ") = " << x_ini.transpose() << std::endl
259 << " x(" << t_mesh.template tail<1>() << ") = " << x_end.transpose() << std::endl;
260 }
261
262 // Check if the solution is found (i.e., if the boundary conditions are satisfied)
263 if (bcs.norm() < this->m_tolerance) {return true;}
264
265 // Build the linear system
266 b.template head<N>() = x_end - x_sol.template tail<N>();
267 b.template tail<N>() = -bcs;
268 A.template block<N, N>(0, 0) = -Jx;
269 A.template block<N, N>(N, 0) = this->Jb_x_ini(x_ini, x_end);
270 A.template block<N, N>(N, N) = this->Jb_x_end(x_ini, x_end);
271
272 // Compute the solution of the linear system
273 lu.compute(A);
274 SANDALS_ASSERT(lu.rank() == 2*N, CMD "singular Jacobian detected.");
275 x_step = lu.solve(b);
276
277 // Update the solution
278 x_sol += x_step;
279 }
280
281 // If the loop completes without returning, indicate failure
282 if (this->m_verbose) {SANDALS_WARNING(CMD "maximum number of iterations reached.");}
283 return false;
284
285 #undef CMD
286 }
287
288 }; // class Problem
289
290} // namespace Sandals
291
292#endif // SANDALS_PROBLEM_HH
#define CMD
#define SANDALS_BASIC_CONSTANTS(Real)
Definition Sandals.hh:70
#define SANDALS_ERROR(MSG)
Definition Sandals.hh:34
#define SANDALS_ASSERT(COND, MSG)
Definition Sandals.hh:44
#define SANDALS_WARNING(MSG)
Definition Sandals.hh:53
Eigen::Matrix< Real, N, N > MatrixJF
Definition Implicit.hh:47
Eigen::Vector< Real, N > VectorF
Definition Implicit.hh:46
std::shared_ptr< Implicit< Real, N, M > > Pointer
Definition Implicit.hh:45
void verbose_mode(bool t_verbose)
Definition Problem.hh:134
SolutionPtr m_solution
Definition Problem.hh:57
IntegratorPtr m_integrator
Definition Problem.hh:56
typename Implicit< Real, N, M >::MatrixJF MatrixJF
Definition Problem.hh:51
void name(std::string const t_name)
Definition Problem.hh:92
bool m_verbose
Definition Problem.hh:59
virtual ~Problem()
Definition Problem.hh:80
void system(SystemPtr t_system)
Definition Problem.hh:104
IntegratorPtr integrator()
Definition Problem.hh:110
Problem(std::string t_name, SystemPtr t_system, IntegratorPtr t_integrator)
Definition Problem.hh:70
Integer & max_iterations()
Definition Problem.hh:166
void integrator(IntegratorPtr t_integrator)
Definition Problem.hh:116
typename Integrator::VectorX VectorX
Definition Problem.hh:48
typename Implicit< Real, N, M >::VectorF VectorF
Definition Problem.hh:50
Integer m_max_iterations
Definition Problem.hh:61
SystemPtr m_system
Definition Problem.hh:55
virtual MatrixJF Jb_x_ini(VectorF const &x_ini, VectorF const &x_end) const =0
virtual VectorF b(VectorF const &x_ini, VectorF const &x_end) const =0
void max_iterations(Integer const t_max_iterations)
Definition Problem.hh:172
bool verbose_mode()
Definition Problem.hh:128
void disable_verbose_mode()
Definition Problem.hh:147
Real m_tolerance
Definition Problem.hh:60
const Real SQRT_EPSILON
Definition Problem.hh:42
bool single_shooting(VectorX const &t_mesh, VectorF const &ics)
Definition Problem.hh:213
typename Integrator::MatrixJX MatrixJX
Definition Problem.hh:49
void tolerance(Real const t_tolerance)
Definition Problem.hh:159
std::shared_ptr< Integrator > IntegratorPtr
Definition Problem.hh:45
std::string m_name
Definition Problem.hh:54
SolutionPtr const solution() const
Definition Problem.hh:122
SystemPtr system()
Definition Problem.hh:98
typename Implicit< Real, N, M >::Pointer SystemPtr
Definition Problem.hh:44
std::shared_ptr< Solution< Real, N, M > > SolutionPtr
Definition Problem.hh:46
void enable_verbose_mode()
Definition Problem.hh:142
Real tolerance()
Definition Problem.hh:153
std::string name() const
Definition Problem.hh:86
virtual MatrixJF Jb_x_end(VectorF const &x_ini, VectorF const &x_end) const =0
The namespace for the Sandals library.
Definition Sandals.hh:89
SANDALS_DEFAULT_INTEGER_TYPE Integer
The Integer type as used for the API.
Definition Sandals.hh:97