source/numeric/diff.cxx

Go to the documentation of this file.
00001 /*************************************************************************
00002  *
00003  *  The Contents of this file are made available subject to
00004  *  the terms of GNU Lesser General Public License Version 2.1.
00005  *
00006  *
00007  *    GNU Lesser General Public License Version 2.1
00008  *    =============================================
00009  *    Copyright 2005-2008 by Kohei Yoshida.
00010  *    1039 Kingsway Dr., Apex, NC 27502, USA
00011  *
00012  *    This library is free software; you can redistribute it and/or
00013  *    modify it under the terms of the GNU Lesser General Public
00014  *    License version 2.1, as published by the Free Software Foundation.
00015  *
00016  *    This library is distributed in the hope that it will be useful,
00017  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019  *    Lesser General Public License for more details.
00020  *
00021  *    You should have received a copy of the GNU Lesser General Public
00022  *    License along with this library; if not, write to the Free Software
00023  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00024  *    MA  02111-1307  USA
00025  *
00026  ************************************************************************/
00027 
00028 #include "numeric/diff.hxx"
00029 #include "numeric/funcobj.hxx"
00030 #include "tool/global.hxx"
00031 #include <iostream>
00032 #include <stdexcept>
00033 #include <cmath>
00034 
00035 using ::std::vector;
00036 using ::std::cout;
00037 using ::std::endl;
00038 
00039 namespace scsolver { namespace numeric {
00040 
00041 const double NumericalDiffer::OMEGA = 2.0;
00042 
00043 NumericalDiffer::NumericalDiffer() : 
00044         m_nPrec(2), 
00045         m_bSecondOrder(false),
00046     m_pFuncObj(NULL)
00047 {
00048 }
00049 
00050 NumericalDiffer::~NumericalDiffer() throw()
00051 {
00052 }
00053 
00054 void NumericalDiffer::setPrecision( unsigned long n )
00055 {
00056         m_nPrec = n;
00057 }
00058 
00059 void NumericalDiffer::setSecondOrder( bool b )
00060 {
00061         m_bSecondOrder = b;
00062         setDirty();
00063 }
00064 
00065 void NumericalDiffer::setVariable(double var)
00066 {
00067         m_var = var;
00068         setDirty();
00069 }
00070 
00071 void NumericalDiffer::setFuncObject(SingleVarFuncObj* pFuncObj)
00072 {
00073     m_pFuncObj = pFuncObj;
00074     setDirty();
00075 }
00076 
00077 void NumericalDiffer::initialize()
00078 {
00079         const double fInitH = 0.0512;
00080         m_cnH.clear();
00081         m_cnH.push_back( fInitH );
00082         m_cnH.push_back( fInitH / 3.0 * 2.0 );
00083 }
00084 
00085 void NumericalDiffer::setDirty()
00086 {
00087         m_cnT.clear();
00088 }
00089 
00090 void NumericalDiffer::appendNewH()
00091 {
00092         m_cnH.push_back( m_cnH.at( m_cnH.size() - 2 ) / 2.0 );
00093 }
00094 
00095 void NumericalDiffer::setT( unsigned long m, unsigned long i, double fVal )
00096 {
00097         size_t nTSize = m_cnT.size();
00098         if ( nTSize < m + 1 )
00099                 for ( unsigned long nIdx = 0; nIdx < m + 1 - nTSize; ++nIdx )
00100                 {
00101                         vector<double> cn;
00102                         m_cnT.push_back( cn );
00103                 }
00104 
00105         vector<double>& cnRow = m_cnT.at( m );
00106         size_t nRowSize = cnRow.size();
00107         if ( nRowSize < i + 1 )
00108                 for ( unsigned long nIdx = 0; nIdx < i + 1 - nRowSize; ++nIdx )
00109                         cnRow.push_back( 0.0 );
00110 
00111         cnRow.at( i ) = fVal;
00112 }
00113 
00114 double NumericalDiffer::getT( unsigned long m, unsigned long i )
00115 {
00116         if ( m_cnT.empty() || m_cnT.size() - 1 < m )
00117                 throw std::out_of_range( "" );
00118 
00119         vector<double> cnRow = m_cnT.at( m );
00120         if ( cnRow.empty() || cnRow.size() - 1 < i )
00121                 throw std::out_of_range( "" );
00122 
00123         return cnRow.at( i );
00124 }
00125 
00126 double NumericalDiffer::T0( unsigned long i )
00127 {
00128     SingleVarFuncObj& rFuncObj = *m_pFuncObj;
00129         double fXOrig = m_var;
00130         double fVal = 0.0;
00131         double fH = m_cnH.at(i);
00132     rFuncObj.setVar(m_var);
00133 
00134         if (m_bSecondOrder)
00135         {
00136         rFuncObj.setVar(fXOrig + fH);
00137         fVal = rFuncObj.eval();
00138         rFuncObj.setVar(fXOrig);
00139                 fVal -= 2.0*rFuncObj.eval();
00140         rFuncObj.setVar(fXOrig - fH);
00141                 fVal += rFuncObj.eval();
00142                 fVal /= fH*fH;
00143         }
00144         else
00145         {
00146         rFuncObj.setVar(fXOrig + fH);
00147                 fVal = rFuncObj.eval();
00148         rFuncObj.setVar(fXOrig - fH);
00149                 fVal -= rFuncObj.eval();
00150                 fVal /= 2.0*fH;
00151         }
00152 
00153         setT(0, i, fVal);
00154         return fVal;
00155 }
00156 
00157 double NumericalDiffer::Tm()
00158 {
00159         unsigned long m = m_cnH.size() - 1;
00160         return Tm( m );
00161 }
00162 
00163 double NumericalDiffer::Tm( unsigned long m, unsigned long i )
00164 {
00165         if ( m_cnH.empty() )
00166                 throw ::std::exception();
00167 
00168         try
00169         {
00170                 return getT( m, i );
00171         }
00172         catch( const std::out_of_range& )
00173         {
00174         }
00175 
00176         if ( m == 0 )
00177                 return T0( i );
00178 
00179         double fT1 = Tm( m-1, i+1 );
00180         double fT2 = Tm( m-1, i );
00181         double fVal = fT1 + ( fT1 - fT2 ) / ( pow( m_cnH.at( i )/m_cnH.at( i+m ), NumericalDiffer::OMEGA ) - 1 );
00182         setT( m, i, fVal );
00183 
00184         return fVal;
00185 }
00186 
00187 double NumericalDiffer::run()
00188 {
00189         if ( m_pFuncObj == NULL )
00190                 throw FuncObjectNotSet();
00191 
00192         initialize();
00193         double fVal = Tm();
00194         double fOldVal = fVal;
00195 
00196         double fTor = 1.0;      
00197         for ( unsigned long n = 0; n < m_nPrec; ++n )
00198                 fTor /= 10.0;
00199         while ( true )
00200         {
00201                 appendNewH();
00202                 fVal = Tm();
00203                 double fDiff = fabs( fVal - fOldVal );
00204                 if ( fDiff <= fTor )
00205                         return fVal;
00206                 fOldVal = fVal;
00207         }
00208         
00209     throw ::std::exception();
00210 }
00211 
00212 }}
00213 

Generated on Mon Jul 28 09:13:20 2008 for scsolver by  doxygen 1.5.3