• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdeedu
  • Sitemap
  • Contact Us
 

step/stepcore

eulersolver.cc

Go to the documentation of this file.
00001 /* This file is part of StepCore library.
00002    Copyright (C) 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com>
00003 
00004    StepCore library is free software; you can redistribute it and/or modify
00005    it under the terms of the GNU General Public License as published by
00006    the Free Software Foundation; either version 2 of the License, or
00007    (at your option) any later version.
00008 
00009    StepCore library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012    GNU General Public License for more details.
00013 
00014    You should have received a copy of the GNU General Public License
00015    along with StepCore; if not, write to the Free Software
00016    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00017 */
00018 
00019 #include "eulersolver.h"
00020 #include "util.h"
00021 
00022 #include <cmath>
00023 #include <cstring>
00024 
00025 namespace StepCore {
00026 
00027 STEPCORE_META_OBJECT(GenericEulerSolver, "Generic Euler solver", MetaObject::ABSTRACT, STEPCORE_SUPER_CLASS(Solver),)
00028 STEPCORE_META_OBJECT(EulerSolver, "Non-adaptive Euler solver", 0, STEPCORE_SUPER_CLASS(GenericEulerSolver),)
00029 STEPCORE_META_OBJECT(AdaptiveEulerSolver, "Adaptive Euler solver", 0, STEPCORE_SUPER_CLASS(GenericEulerSolver),)
00030 
00031 void GenericEulerSolver::init()
00032 {
00033     _yerr  = new double[_dimension];
00034     _ytemp = new double[_dimension];
00035     _ydiff = new double[_dimension];
00036     _ytempvar = new double[_dimension];
00037     _ydiffvar = new double[_dimension];
00038 }
00039 
00040 void GenericEulerSolver::fini()
00041 {
00042     delete[] _ydiffvar;
00043     delete[] _ytempvar;
00044     delete[] _ydiff;
00045     delete[] _ytemp;
00046     delete[] _yerr;
00047 }
00048 
00049 int GenericEulerSolver::doCalcFn(double* t, const double* y,
00050                     const double* yvar, double* f, double* fvar)
00051 {
00052     int ret = _function(*t, y, yvar, f ? f : _ydiff, fvar, _params);
00053     //if(f != NULL) std::memcpy(f, _ydiff, _dimension*sizeof(*f));
00054     return ret;
00055 }
00056 
00057 int GenericEulerSolver::doStep(double t, double stepSize, double* y, double* yvar)
00058 {
00059     _localError = 0;
00060     _localErrorRatio = 0;
00061 
00062     //int ret = _function(t, y, _ydiff, _params);
00063     //if(ret != OK) return ret;
00064 
00065     double* ytempvar = yvar ? _ytempvar : 0;
00066     double* ydiffvar = yvar ? _ydiffvar : 0;
00067 
00068     for(int i=0; i<_dimension; ++i) {
00069         // Error estimation: integration with timestep = stepSize
00070         _yerr[i] = - y[i] - stepSize*_ydiff[i];
00071         // First integration with timestep = stepSize/2
00072         _ytemp[i] = y[i] + stepSize*_ydiff[i]/2;
00073     }
00074 
00075     if(yvar) { // error calculation
00076         for(int i=0; i<_dimension; ++i)
00077             ytempvar[i] = square(sqrt(yvar[i])+ydiffvar[i]*stepSize/2);
00078     }
00079 
00080     int ret = _function(t + stepSize/2, _ytemp, ytempvar, _ydiff, ydiffvar, _params);
00081     if(ret != OK) return ret;
00082 
00083     for(int i=0; i<_dimension; ++i) {
00084         // Second integration with timestep = stepSize/2
00085         _ytemp[i] += stepSize/2*_ydiff[i];
00086         // Error estimation and solution improve
00087         _yerr[i] += _ytemp[i];
00088         // Solution improvement
00089         _ytemp[i] += _yerr[i];
00090         // Maximal error calculation
00091         double error = fabs(_yerr[i]);
00092         if(error > _localError) _localError = error;
00093         // Maximal error ration calculation
00094         double errorRatio = error / (_toleranceAbs + _toleranceRel * fabs(_ytemp[i]));
00095         if(errorRatio > _localErrorRatio) _localErrorRatio = errorRatio;
00096     }
00097 
00098     if(_localErrorRatio > 1.1) return ToleranceError;
00099 
00100     // XXX
00101     ret = _function(t + stepSize, _ytemp, ytempvar, _ydiff, ydiffvar, _params);
00102     if(ret != OK) return ret;
00103 
00104     std::memcpy(y, _ytemp, _dimension*sizeof(*y));
00105 
00106     if(yvar) { // error calculation
00107         // XXX: Strictly speaking yerr are correlated between steps.
00108         // For now we are using the following formula which
00109         // assumes that yerr are equal and correlated on adjacent steps
00110         // TODO: improve this formula
00111         for(int i=0; i<_dimension; ++i)
00112             yvar[i] = square(sqrt(ytempvar[i])+ydiffvar[i]*stepSize/2)
00113                       + 3*square(_yerr[i]);
00114     }
00115 
00116     return OK;
00117 }
00118 
00119 int GenericEulerSolver::doEvolve(double* t, double t1, double* y, double* yvar)
00120 {
00121     // XXX: add better checks
00122     // XXX: replace asserts by error codes here
00123     //      or by check in world
00124     // XXX: do the same checks in doStep
00125     STEPCORE_ASSERT_NOABORT(*t + _stepSize != *t);
00126     STEPCORE_ASSERT_NOABORT(*t != t1);
00127 
00128     #ifndef NDEBUG
00129     double realStepSize = fmin( _stepSize, t1 - *t );
00130     #endif
00131 
00132     const double S = 0.9;
00133     int result;
00134 
00135     double* ydiffvar = yvar ? _ydiffvar : 0;
00136 
00137     result = _function(*t, y, yvar, _ydiff, ydiffvar, _params);
00138     if(result != OK) return result;
00139 
00140     while(*t < t1) {
00141         STEPCORE_ASSERT_NOABORT(t1-*t > realStepSize/1000);
00142 
00143         //double t11 = _stepSize < t1-*t ? *t + _stepSize : t1;
00144         double t11 = t1 - *t > _stepSize*1.01 ? *t + _stepSize : t1;
00145         result = doStep(*t, t11 - *t, y, yvar);
00146 
00147         if(result != OK && result != ToleranceError) return result;
00148 
00149         if(_adaptive) {
00150             if(_localErrorRatio > 1.1) {
00151                 double r = S / _localErrorRatio;
00152                 if(r<0.2) r = 0.2;
00153                 _stepSize *= r;
00154             } else if(_localErrorRatio < 0.5) {
00155                 double r = S / pow(_localErrorRatio, 0.5);
00156                 if(r>5.0) r = 5.0;
00157                 if(r<1.0) r = 1.0;
00158                 double newStepSize = _stepSize*r;
00159                 if(newStepSize < t1 - t11) _stepSize = newStepSize;
00160             }
00161             if(result != OK) {
00162                 result = _function(*t, y, yvar, _ydiff, ydiffvar, _params);
00163                 if(result != OK) return result;
00164                 continue;
00165             }
00166         } else {
00167             if(result != OK) return ToleranceError;
00168         }
00169 
00170         *t = t11;
00171     }
00172     return OK;
00173 }
00174 
00175 } // namespace StepCore
00176 

step/stepcore

Skip menu "step/stepcore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdeedu

Skip menu "kdeedu"
  • kalzium
  • kanagram
  • kig
  •   lib
  • klettres
  • kstars
  • libkdeedu
  •   keduvocdocument
  •   docs
  •   src
  • parley
  •   stepcore
Generated for kdeedu by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal