JSBSim Flight Dynamics Model 1.3.0 (09 Apr 2026)
An Open Source Flight Dynamics and Control Software Library in C++
Loading...
Searching...
No Matches
FGRungeKutta.cpp
1/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3 Header: FGRungeKutta.cpp
4 Author: Thomas Kreitler
5 Date started: 04/9/2010
6
7 ------------- Copyright (C) -------------
8
9 This program is free software; you can redistribute it and/or modify it under
10 the terms of the GNU Lesser General Public License as published by the Free Software
11 Foundation; either version 2 of the License, or (at your option) any later
12 version.
13
14 This program is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
17 details.
18
19 You should have received a copy of the GNU Lesser General Public License along with
20 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21 Place - Suite 330, Boston, MA 02111-1307, USA.
22
23 Further information about the GNU Lesser General Public License can also be found on
24 the world wide web at http://www.gnu.org.
25
26
27
28%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
29 INCLUDES
30%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
31
32#include <cstdio>
33#include <iostream>
34#include <cmath>
35
36#include "FGJSBBase.h"
37#include "FGRungeKutta.h"
38#include "input_output/FGLog.h"
39
40/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 DEFINITIONS
42 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
43
44namespace JSBSim {
45
46const double FGRungeKutta::RealLimit = 1e30;
47
48/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
49CLASS IMPLEMENTATION
50%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
51
52FGRungeKutta::~FGRungeKutta() { };
53
54int FGRungeKutta::init(double x_start, double x_end, int intervals)
55{
56 x0 = x_start;
57 x1 = x_end;
58 h = (x_end - x_start)/intervals;
59 safer_x1 = x1 - h*1e-6; // avoid 'intervals*h < x1'
60 h05 = h*0.5;
61 err = 0.0;
62
63 if (x0>=x1) {
64 status &= eFaultyInit;
65 }
66 return status;
67}
68
69//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
70
71/*
72 Make sure that a numerical result is within +/-RealLimit.
73 This is a hapless try to be portable.
74 (There will be at least one architecture/compiler combination
75 where this will fail.)
76*/
77
78bool FGRungeKutta::sane_val(double x)
79{
80 // assuming +/- inf behave as expected and 'nan' comparisons yield to false
81 if ( x < RealLimit && x > -RealLimit ) return true;
82 return false;
83}
84
85//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
86
87double FGRungeKutta::evolve(double y_0, FGRungeKuttaProblem *pf)
88{
89 double x = x0;
90 double y = y_0;
91 pfo = pf;
92
93 iterations = 0;
94
95 if (!trace_values) {
96 while (x<safer_x1) {
97 y = approximate(x,y);
98 if (!sane_val(y)) { status &= eMathError; }
99 x += h;
100 iterations++;
101 }
102 } else {
103 FGLogging log(LogLevel::DEBUG);
104 while (x<safer_x1) {
105 log << x << " " << y << "\n";
106 y = approximate(x,y);
107 if (!sane_val(y)) { status &= eMathError; }
108 x += h;
109 iterations++;
110 }
111 log << x << " " << y << "\n";
112 }
113
114 x_end = x; // twimc, store the last x used.
115 return y;
116}
117
118
119
120/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
121CLASS IMPLEMENTATION
122%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
123
124FGRK4::~FGRK4() { };
125
126//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
127
128double FGRK4::approximate(double x, double y)
129{
130 double k1,k2,k3,k4;
131
132 k1 = pfo->pFunc(x , y );
133 k2 = pfo->pFunc(x + h05, y + h05*k1);
134 k3 = pfo->pFunc(x + h05, y + h05*k2);
135 k4 = pfo->pFunc(x + h , y + h *k3);
136
137 y += h/6.0 * ( k1 + 2.0*k2 + 2.0*k3 + k4 );
138
139 return y;
140}
141
142
143/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
144CLASS IMPLEMENTATION
145%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
146
147// Butcher tableau
148const double FGRKFehlberg::A2[] = { 0.0, 1.0/4.0 };
149const double FGRKFehlberg::A3[] = { 0.0, 3.0/32.0, 9.0/32.0 };
150const double FGRKFehlberg::A4[] = { 0.0, 1932.0/2197.0, -7200.0/2197.0, 7296.0/2197.0 };
151const double FGRKFehlberg::A5[] = { 0.0, 439.0/216.0, -8.0, 3680.0/513.0, -845.0/4104.0 };
152const double FGRKFehlberg::A6[] = { 0.0, -8.0/27.0, 2.0, -3544.0/2565.0, 1859.0/4104.0, -11.0/40.0 };
153
154const double FGRKFehlberg::C[] = { 0.0, 0.0, 1.0/4.0, 3.0/8.0, 12.0/13.0, 1.0, 1.0/2.0 };
155
156const double FGRKFehlberg::B[] = { 0.0, 16.0/135.0, 0.0, 6656.0/12825.0, 28561.0/56430.0, -9.0/50.0, 2.0/55.0 };
157const double FGRKFehlberg::Bs[] = { 0.0, 25.0/216.0, 0.0, 1408.0/2565.0, 2197.0/4104.0, -1.0/5.0, 0.0 };
158
159// use this if truncation is an issue
160// const double Ee[] = { 0.0, 1.0/360.0, 0.0, -128.0/4275.0, -2197.0/75240.0, 1.0/50.0, 2.0/55.0 };
161
162FGRKFehlberg::~FGRKFehlberg() { };
163
164double FGRKFehlberg::approximate(double x, double y)
165{
166
167 double k1,k2,k3,k4,k5,k6, as;
168
169 double y4_val;
170 double y5_val;
171 double abs_err;
172 double est_step;
173 int done = 0;
174
175
176 while (!done) {
177
178 err = h*h*h*h*h; // h might change
179
180 k1 = pfo->pFunc(x , y );
181
182 as = h*A2[1]*k1;
183 k2 = pfo->pFunc(x + C[2]*h , y + as );
184
185 as = h*(A3[1]*k1 + A3[2]*k2);
186 k3 = pfo->pFunc(x + C[3]*h , y + as );
187
188 as = h*(A4[1]*k1 + A4[2]*k2 + A4[3]*k3);
189 k4 = pfo->pFunc(x + C[4]*h , y + as );
190
191 as = h*(A5[1]*k1 + A5[2]*k2 + A5[3]*k3 + A5[4]*k4);
192 k5 = pfo->pFunc(x + C[5]*h , y + as );
193
194 as = h*(A6[1]*k1 + A6[2]*k2 + A6[3]*k3 + A6[4]*k4 + A6[5]*k5);
195 k6 = pfo->pFunc(x + C[6]*h , y + as );
196
197 /* B[2]*k2 and Bs[2]*k2 are zero */
198 y5_val = y + h * ( B[1]*k1 + B[3]*k3 + B[4]*k4 + B[5]*k5 + B[6]*k6);
199 y4_val = y + h * (Bs[1]*k1 + Bs[3]*k3 + Bs[4]*k4 + Bs[5]*k5);
200
201 abs_err = fabs(y4_val-y5_val);
202 // same in green
203 // abs_err = h * (Ee[1] * k1 + Ee[3] * k3 + Ee[4] * k4 + Ee[5] * k5 + Ee[6] * k6);
204
205 // estimate step size
206 if (abs_err > epsilon) {
207 est_step = sqrt(sqrt(epsilon*h/abs_err));
208 } else {
209 est_step=2.0*h; // cheat
210 }
211
212 // check if a smaller step size is proposed
213
214 if (shrink_avail>0 && est_step<h) {
215 h/=2.0;
216 shrink_avail--;
217 } else {
218 done = 1;
219 }
220
221 }
222
223 return y4_val;
224}
225
226} // namespace JSBSim
Main namespace for the JSBSim Flight Dynamics Model.
Definition FGFDMExec.cpp:71