NewtonRaphson.h

Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 /***************************************************************************
00006  *   Copyright (C) 2009 by Clark Sims                                      *
00007  *   http://AcumenSoftwareInc.com/WhoWeAre/Clark_Sims.html                 *
00008  *   ClarkSims@AcumenSoftwareInc.com                                       *
00009  *                                                                         *
00010  *   This program is free software; you can redistribute it and/or modify  *
00011  *   it under the terms of the GNU General Public License as published by  *
00012  *   the Free Software Foundation; either version 2 of the License, or     *
00013  *   (at your option) any later version.                                   *
00014  *                                                                         *
00015  *   This program is distributed in the hope that it will be useful,       *
00016  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00017  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00018  *   GNU General Public License for more details.                          *
00019  *                                                                         *
00020  *   You should have received a copy of the GNU General Public License     *
00021  *   along with this program; if not, write to the                         *
00022  *   Free Software Foundation, Inc.,                                       *
00023  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00024  ***************************************************************************/
00025 #ifndef NewtonRaphson_hpp
00026 #define NewtonRaphson_hpp
00027 
00028 #include <iostream>
00029 #include <vector>
00030 
00031 using namespace std;
00032 
00040 template<class functor, class real>
00041 class NewtonRaphsonSolve0 {
00042  protected:
00043   // key attributes
00044 
00047   int _max_iter;
00048 
00051   real _x0;
00052 
00054   real _epsilon;
00055 
00057   real _fsolve;
00058 
00060   bool _twice_df;
00061 
00063   real (functor::*_f)(real);
00064 
00066   real (functor::*_df)(real);
00067 
00069   real (functor::*_d2f)(real);
00070 
00072   functor& _F;
00073 
00074   // functional attributes
00076   bool _check_boundary;
00077 
00079   real _min_x;
00080 
00082   real _max_x;
00083 
00084 
00085   // derived attributes
00087   mutable real _x_converge;
00089   mutable real _f_converge;
00091   mutable vector<real> _x;
00093   mutable vector<real> _F_x;
00095   mutable vector<real> _abs_F_x;
00097   mutable vector<real> _dF_x;
00099   mutable bool _converged;
00101   mutable bool _diverged;
00103   mutable bool _boundary_solution;
00105   mutable int _number_boundary_hits;
00107   mutable bool _lower_boundary_hit;
00109   mutable bool _upper_boundary_hit;
00111   mutable bool _boundary_hit;
00112 
00114   int check_boundary( real & x, real df_dx) {
00115 
00116     if (_check_boundary) {
00117       _lower_boundary_hit = _upper_boundary_hit = false;
00118       if (x < _min_x) {
00119         x = _min_x + 2 * _epsilon / df_dx;
00120         _lower_boundary_hit = true;
00121         _number_boundary_hits++;      
00122       } else if (x > _max_x) {
00123         x = _max_x - 2 * _epsilon / df_dx;
00124         _upper_boundary_hit = true;
00125         _number_boundary_hits++;
00126       }
00127       _boundary_hit = _lower_boundary_hit || _upper_boundary_hit;
00128     }
00129     
00130     return _number_boundary_hits;
00131   }
00132 
00133  public:  
00134 
00136   bool get_boundary_solution() const {
00137     return _boundary_solution;
00138   }
00139 
00141   void set_d2f( real (functor::*d2f)(real)) {
00142     _d2f = d2f;
00143   }
00144 
00146   void set_check_boundary( bool check_boundary) {
00147     _check_boundary = check_boundary;
00148   }
00149 
00151   void set_min_x( real min_x) {
00152     _min_x = min_x;
00153   }
00154 
00156   void set_max_x( real max_x) {
00157     _max_x = max_x;
00158   }
00159 
00161   real get_x_converge() const {
00162     return _x_converge;
00163   }
00164 
00166   real get_f_converge() const {
00167     return _f_converge;
00168   }
00169 
00171   functor& get_functor() { return _F;}
00172 
00173    
00185   NewtonRaphsonSolve0( 
00186     real X0, 
00187     real Epsilon, 
00188     bool Twice_df,
00189     unsigned int max_iter, 
00190     functor& F, 
00191     real (functor::*f)(real), 
00192     real (functor::*df)(real),  
00193     real (functor::*d2f)(real) = NULL,
00194     real fsolve = 0,
00195     bool check_boundary = false,
00196     real min_x = 0,
00197     real max_x = 0)
00198     :  _x0( X0), _epsilon( Epsilon), _twice_df( Twice_df), _max_iter(max_iter), _F(F), _f(f), _df(df), _d2f(d2f), _fsolve(fsolve), _check_boundary(check_boundary), _min_x(min_x), _max_x(max_x), 
00199     _x_converge(0), _f_converge(0), 
00200     _x(max_iter), _F_x(max_iter), _abs_F_x(max_iter), _dF_x(max_iter), _converged(false), _diverged(false), 
00201     _lower_boundary_hit(false), _upper_boundary_hit(false), _boundary_hit(false)
00202   {
00203 
00204   }
00205 
00207   void do_iteration( ostream* output) {
00208     int i;
00209 
00210     _converged = _diverged = _boundary_solution = false;
00211 
00212     _x[0] = _x0;
00213 
00214     for (i=_number_boundary_hits=0; ;) {
00215       _F_x[i]       = (_F.*_f)( _x[i]) - _fsolve;
00216 
00217       _abs_F_x[i] = (_F_x[i] > 0)? _F_x[i] : -_F_x[i];
00218 
00219       if (_abs_F_x[i] < _epsilon) {
00220         _x_converge = _x[i];
00221         _f_converge = _F_x[i];
00222         _converged = true;
00223         break;
00224       }
00225 
00226       if (i>0 && _abs_F_x[i] > _abs_F_x[i-1]) {
00227         _diverged = true;
00228         break;
00229       }
00230 
00231       if (output) {
00232         *output << i << " " << _x[i] << " " << _F_x[i] << " " << _dF_x[i] << endl;
00233       } 
00234 
00235       _dF_x[i] = (_F.*_df)( _x[i]);
00236 
00237       ++i;
00238       if (i >= _max_iter) break;
00239 
00240       if (_d2f != 0) {  
00241         real dx = (_F_x[i-1]) / _dF_x[i-1];
00242         real df2_dx2 = (_F.*_d2f) ( _x[i-1]);
00243         _dF_x[i-1] -= .5 * dx * df2_dx2;
00244       } else if (_twice_df) {
00245         _x[i] = _x[i-1] - (_F_x[i-1]) / _dF_x[i-1];
00246         if (check_boundary( _x[i], _dF_x[i-1])>2) {
00247           goto boundary;
00248         }
00249 
00250         if (_boundary_hit) {
00251           _dF_x[i-1] = (_F.*_df)( _x[i]);
00252         } else {
00253           real df_dx = (_F.*_df)( _x[i]);
00254           _dF_x[i-1] = .5 * (_dF_x[i-1] + df_dx);
00255         }
00256       }
00257 
00258       _x[i] = _x[i-1] - (_F_x[i-1]) / _dF_x[i-1];
00259       
00260       if (check_boundary( _x[i], _dF_x[i-1])>2) {
00261         goto boundary;
00262       }
00263 
00264       continue;
00265 
00266     boundary:
00267       if (_lower_boundary_hit) {
00268         _boundary_solution = true;
00269         _x_converge = _min_x;
00270         _f_converge = (_F.*_f)( _min_x);
00271         break;
00272       }
00273 
00274       if (_upper_boundary_hit) {
00275         _boundary_solution = true;
00276         _x_converge = _max_x;
00277         _f_converge = (_F.*_f)( _max_x);
00278         break;
00279       }
00280     }
00281 
00282     if (_diverged && output) {
00283       *output << "answer diverged" << endl;
00284     }
00285 
00286     if (_boundary_solution && output) {
00287       *output << i << " " << _x_converge << " " << _f_converge << " boundary_solution" << endl;
00288     } else if (_converged && output) {
00289       *output << i << " " << _x[i] << " " << _F_x[i] << " answer converged" << endl;
00290     }
00291   }
00292 };
00293 
00294 
00295 #endif

Generated on Sat Sep 12 20:10:46 2009 for NewtonRaphson by  doxygen 1.5.1