LCOV - code coverage report
Current view: top level - math - FGRungeKutta.cpp (source / functions) Hit Total Coverage
Test: JSBSim-Coverage-Statistics Lines: 1 70 1.4 %
Date: 2010-08-24 Functions: 3 17 17.6 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 3 54 5.6 %

           Branch data     Line data    Source code
       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 "FGRungeKutta.h"
      37                 :            : 
      38                 :            : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      39                 :            :   DEFINITIONS
      40                 :            :   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
      41                 :            : 
      42                 :            : using std::cout;
      43                 :            : using std::endl;
      44                 :            : 
      45                 :            : namespace JSBSim {
      46                 :            :   
      47                 :            : static const char *IdSrc = "$Id: FGRungeKutta.cpp,v 1.1 2010/06/02 04:05:13 jberndt Exp $";
      48                 :            : static const char *IdHdr = ID_RUNGEKUTTA;
      49                 :            : 
      50                 :            : const double FGRungeKutta::RealLimit = 1e30;
      51                 :            : 
      52                 :            : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      53                 :            : CLASS IMPLEMENTATION
      54                 :            : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
      55                 :            : 
      56 [ #  # ][ #  # ]:          0 : FGRungeKutta::~FGRungeKutta() { };
                 [ #  # ]
      57                 :            : 
      58                 :          0 : int FGRungeKutta::init(double x_start, double x_end, int intervals)
      59                 :            : {
      60                 :          0 :   x0 = x_start;
      61                 :          0 :   x1 = x_end;
      62                 :          0 :   h  = (x_end - x_start)/intervals;
      63                 :          0 :   safer_x1 = x1 - h*1e-6; // avoid 'intervals*h < x1'
      64                 :          0 :   h05 = h*0.5;
      65                 :          0 :   err = 0.0;
      66                 :            :   
      67         [ #  # ]:          0 :   if (x0>=x1) {
      68                 :          0 :     status &= eFaultyInit;
      69                 :            :   }
      70                 :          0 :   return status;
      71                 :            : }
      72                 :            : 
      73                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      74                 :            : 
      75                 :            : /*
      76                 :            :    Make sure that a numerical result is within +/-RealLimit.
      77                 :            :    This is a hapless try to be portable.
      78                 :            :    (There will be at least one architecture/compiler combination 
      79                 :            :    where this will fail.)
      80                 :            : */
      81                 :            : 
      82                 :          0 : bool FGRungeKutta::sane_val(double x)
      83                 :            : {
      84                 :            :   // assuming +/- inf behave as expected and 'nan' comparisons yield to false
      85 [ #  # ][ #  # ]:          0 :   if ( x < RealLimit && x > -RealLimit ) return true;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
      86                 :          0 :   return false;
      87                 :            : }
      88                 :            : 
      89                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      90                 :            : 
      91                 :          0 : double FGRungeKutta::evolve(double y_0, FGRungeKuttaProblem *pf)
      92                 :            : {
      93                 :          0 :   double x = x0;
      94                 :          0 :   double y = y_0;
      95                 :          0 :   pfo = pf;
      96                 :            : 
      97                 :          0 :   iterations = 0;
      98                 :            :   
      99         [ #  # ]:          0 :   if (!trace_values) {
     100         [ #  # ]:          0 :     while (x<safer_x1) {
     101                 :          0 :       y  = approximate(x,y);
     102         [ #  # ]:          0 :       if (!sane_val(y)) { status &= eMathError; }
     103                 :          0 :       x += h;
     104                 :          0 :       iterations++;
     105                 :            :     }
     106                 :            :   } else {
     107         [ #  # ]:          0 :     while (x<safer_x1) {
     108                 :          0 :       cout << x << " " << y << endl;
     109                 :          0 :       y = approximate(x,y);
     110         [ #  # ]:          0 :       if (!sane_val(y)) { status &= eMathError; }
     111                 :          0 :       x += h;
     112                 :          0 :       iterations++;
     113                 :            :     }
     114                 :          0 :     cout << x << " " << y << endl;
     115                 :            :   }
     116                 :            : 
     117                 :          0 :   x_end = x; // twimc, store the last x used.
     118                 :          0 :   return y;
     119                 :            : }
     120                 :            : 
     121                 :            : 
     122                 :            : 
     123                 :            : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     124                 :            : CLASS IMPLEMENTATION
     125                 :            : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
     126                 :            : 
     127 [ #  # ][ #  # ]:          0 : FGRK4::~FGRK4() { };
                 [ #  # ]
     128                 :            : 
     129                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     130                 :            : 
     131                 :          0 : double FGRK4::approximate(double x, double y)
     132                 :            : {
     133                 :            :   double k1,k2,k3,k4;
     134                 :            : 
     135                 :          0 :   k1   =  pfo->pFunc(x      , y         ); 
     136                 :          0 :   k2   =  pfo->pFunc(x + h05, y + h05*k1);
     137                 :          0 :   k3   =  pfo->pFunc(x + h05, y + h05*k2);
     138                 :          0 :   k4   =  pfo->pFunc(x + h  , y + h  *k3);
     139                 :            : 
     140                 :          0 :   y   +=  h/6.0 * ( k1 + 2.0*k2 + 2.0*k3 + k4 );
     141                 :            : 
     142                 :          0 :   return y;
     143                 :            : }
     144                 :            :  
     145                 :            : 
     146                 :            : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     147                 :            : CLASS IMPLEMENTATION
     148                 :            : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
     149                 :            : 
     150                 :            : // Butcher tableau
     151                 :            : const double FGRKFehlberg::A2[] = { 0.0,     1.0/4.0 };
     152                 :            : const double FGRKFehlberg::A3[] = { 0.0,     3.0/32.0,       9.0/32.0 };
     153                 :            : const double FGRKFehlberg::A4[] = { 0.0,  1932.0/2197.0, -7200.0/2197.0,   7296.0/2197.0 };
     154                 :            : const double FGRKFehlberg::A5[] = { 0.0,   439.0/216.0,     -8.0,          3680.0/513.0,    -845.0/4104.0  };
     155                 :            : const double FGRKFehlberg::A6[] = { 0.0,    -8.0/27.0,       2.0,         -3544.0/2565.0,   1859.0/4104.0,  -11.0/40.0 };
     156                 :            : 
     157                 :            : const 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 };
     158                 :            : 
     159                 :            : const 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 };
     160                 :            : const 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 };
     161                 :            : 
     162                 :            : // use this if truncation is an issue
     163                 :            : // 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 };
     164                 :            : 
     165 [ #  # ][ #  # ]:          0 : FGRKFehlberg::~FGRKFehlberg() { };
                 [ #  # ]
     166                 :            : 
     167                 :          0 : double FGRKFehlberg::approximate(double x, double y)
     168                 :            : {
     169                 :            : 
     170                 :            :   double k1,k2,k3,k4,k5,k6, as;
     171                 :            : 
     172                 :            :   double y4_val;
     173                 :            :   double y5_val;
     174                 :            :   double abs_err;
     175                 :            :   double est_step;
     176                 :          0 :   int done = 0;
     177                 :            : 
     178                 :            : 
     179         [ #  # ]:          0 :   while (!done) {
     180                 :            : 
     181                 :          0 :     err  =  h*h*h*h*h; // h might change
     182                 :            : 
     183                 :          0 :     k1   =  pfo->pFunc(x          , y      ); 
     184                 :            : 
     185                 :          0 :     as   =  h*A2[1]*k1;
     186                 :          0 :     k2   =  pfo->pFunc(x + C[2]*h , y + as ); 
     187                 :            : 
     188                 :          0 :     as   =  h*(A3[1]*k1 + A3[2]*k2);
     189                 :          0 :     k3   =  pfo->pFunc(x + C[3]*h , y + as ); 
     190                 :            : 
     191                 :          0 :     as   =  h*(A4[1]*k1 + A4[2]*k2 + A4[3]*k3);
     192                 :          0 :     k4   =  pfo->pFunc(x + C[4]*h , y + as ); 
     193                 :            : 
     194                 :          0 :     as   =  h*(A5[1]*k1 + A5[2]*k2 + A5[3]*k3 + A5[4]*k4);
     195                 :          0 :     k5   =  pfo->pFunc(x + C[5]*h , y + as ); 
     196                 :            : 
     197                 :          0 :     as   =  h*(A6[1]*k1 + A6[2]*k2 + A6[3]*k3 + A6[4]*k4 + A6[5]*k5);
     198                 :          0 :     k6   =  pfo->pFunc(x + C[6]*h , y + as ); 
     199                 :            : 
     200                 :            :     /* B[2]*k2 and Bs[2]*k2 are zero */
     201                 :          0 :     y5_val  =  y + h * ( B[1]*k1 +  B[3]*k3 +  B[4]*k4 +  B[5]*k5 + B[6]*k6);
     202                 :          0 :     y4_val  =  y + h * (Bs[1]*k1 + Bs[3]*k3 + Bs[4]*k4 + Bs[5]*k5);
     203                 :            : 
     204                 :          0 :     abs_err = fabs(y4_val-y5_val);
     205                 :            :     // same in green
     206                 :            :     // abs_err = h * (Ee[1] * k1 + Ee[3] * k3 + Ee[4] * k4 + Ee[5] * k5 + Ee[6] * k6);
     207                 :            : 
     208                 :            :     // estimate step size 
     209         [ #  # ]:          0 :     if (abs_err > epsilon) {
     210                 :          0 :       est_step = sqrt(sqrt(epsilon*h/abs_err));
     211                 :            :     } else {
     212                 :          0 :       est_step=2.0*h; // cheat
     213                 :            :     }
     214                 :            : 
     215                 :            :     // check if a smaller step size is proposed
     216                 :            : 
     217 [ #  # ][ #  # ]:          0 :     if (shrink_avail>0 && est_step<h) {
     218                 :          0 :         h/=2.0;
     219                 :          0 :         shrink_avail--;
     220                 :            :     } else {
     221                 :          0 :       done = 1;
     222                 :            :     }
     223                 :            : 
     224                 :            :   }
     225                 :            : 
     226                 :          0 :   return y4_val;
     227                 :            : }
     228                 :            : 
     229                 :            : 
     230 [ +  + ][ +  - ]:         12 : } // namespace JSBSim

Generated by: LCOV version 1.9