Object-oriented Scientific Computing Library: Version 0.910
gsl_astep_old.h
00001 /*
00002   -------------------------------------------------------------------
00003   
00004   Copyright (C) 2006-2012, Andrew W. Steiner
00005   
00006   This file is part of O2scl.
00007   
00008   O2scl is free software; you can redistribute it and/or modify
00009   it under the terms of the GNU General Public License as published by
00010   the Free Software Foundation; either version 3 of the License, or
00011   (at your option) any later version.
00012   
00013   O2scl is distributed in the hope that it will be useful,
00014   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016   GNU General Public License for more details.
00017   
00018   You should have received a copy of the GNU General Public License
00019   along with O2scl. If not, see <http://www.gnu.org/licenses/>.
00020 
00021   -------------------------------------------------------------------
00022 */
00023 /* ode-initval/evolve.c
00024  * 
00025  * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman
00026  * 
00027  * This program is free software; you can redistribute it and/or modify
00028  * it under the terms of the GNU General Public License as published by
00029  * the Free Software Foundation; either version 3 of the License, or (at
00030  * your option) any later version.
00031  * 
00032  * This program is distributed in the hope that it will be useful, but
00033  * WITHOUT ANY WARRANTY; without even the implied warranty of
00034  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00035  * General Public License for more details.
00036  * 
00037  * You should have received a copy of the GNU General Public License
00038  * along with this program; if not, write to the Free Software
00039  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
00040  * 02110-1301, USA.
00041  */
00042 #ifndef O2SCL_GSL_ASTEP_OLD_H
00043 #define O2SCL_GSL_ASTEP_OLD_H
00044 
00045 #include <string>
00046 
00047 #include <gsl/gsl_math.h>
00048 #include <gsl/gsl_odeiv.h>
00049 
00050 #include <o2scl/adapt_step.h>
00051 #include <o2scl/gsl_astep.h>
00052 
00053 #ifndef DOXYGENP
00054 namespace o2scl {
00055 #endif
00056 
00057   /** \brief Adaptive ODE stepper (GSL)
00058 
00059       [This is the stepper from \o2 version 0.908 which is 
00060       kept around for diagnostic purposes and some legacy code.]
00061       
00062       This class performs an adaptive step of a system of ODEs. To
00063       modify the ODE stepper which is used, use the function
00064       \ref adapt_step::set_step().
00065 
00066       There is an example for the usage of this class in
00067       <tt>examples/ex_ode.cpp</tt> documented in the \ref ex_ode_sect
00068       section.
00069 
00070       Default template arguments
00071       - \c func_t - \ref ode_funct
00072       - \c vec_t - \ref ovector_base
00073       - \c alloc_vec_t - \ref ovector
00074       - \c alloc_t - \ref ovector_alloc
00075   */
00076   template<class func_t=ode_funct<>, 
00077     class vec_t=ovector_base, class alloc_vec_t=ovector, 
00078     class alloc_t=ovector_alloc> class gsl_astep_old : 
00079   public adapt_step<func_t,vec_t,alloc_vec_t,alloc_t> {
00080     
00081 #ifndef DOXYGEN_INTERNAL
00082     
00083     protected:
00084     
00085     /// Memory allocator for objects of type \c alloc_vec_t
00086     alloc_t ao;
00087     
00088     /// Temporary storage for yout
00089     alloc_vec_t yout;
00090 
00091     /// Internal storage for dydx
00092     alloc_vec_t dydx_int;
00093     
00094     /// The size of the last step
00095     double last_step;
00096 
00097     /// The number of steps
00098     unsigned long int count;
00099 
00100     /// The number of failed steps
00101     unsigned long int failed_steps;
00102 
00103     /// The size of the allocated vectors
00104     size_t msize;
00105 
00106     /// Apply the evolution for the next adaptive step
00107     int evolve_apply(double t0, double &t, double &h, double t1, size_t nvar,
00108                      vec_t &y, vec_t &dydx, vec_t &yout2, vec_t &yerr,
00109                      vec_t &dydx_out2, func_t &derivs) {
00110       
00111       double h0 = h;
00112       int step_status;
00113       int final_step = 0;
00114       /* remaining step size, possibly less than h */
00115       double dt = t1 - t0;  
00116     
00117       if ((dt < 0.0 && h0 > 0.0) || (dt > 0.0 && h0 < 0.0)) {
00118         std::string str="Interval direction (t1-t0="+dtos(dt)+
00119           ") does not match step direction (h="+dtos(h)+
00120           " in gsl_astep_old::evolve_apply().";
00121         O2SCL_ERR_RET(str.c_str(),gsl_einval);
00122       }
00123       
00124       bool try_step_again=true;
00125       while(try_step_again) {
00126 
00127         if ((dt >= 0.0 && h0 > dt) || (dt < 0.0 && h0 < dt)) {
00128           h0 = dt;
00129           final_step = 1;
00130         } else{
00131           final_step = 0;
00132         }
00133         
00134         step_status=this->stepp->step(t0,h0,nvar,y,dydx,yout2,yerr,
00135                                       dydx_out2,derivs);
00136         
00137         /* Check for stepper internal failure */
00138         if (step_status != gsl_success) {
00139           // Notify user which step-size caused the failure
00140           h=h0;
00141           return step_status;
00142         }
00143   
00144         count++;
00145         last_step = h0;
00146         if (final_step) {
00147           t = t1;
00148         } else{
00149           t = t0 + h0;
00150         }
00151   
00152         /* Check error and attempt to adjust the step. */
00153         const int hadjust_status=con.hadjust(nvar,this->stepp->get_order(),
00154                                              yout2,yerr,dydx_out2,h0);
00155         
00156         if (hadjust_status == GSL_ODEIV_HADJ_DEC) {
00157           
00158           /* Step was decreased. Undo and go back to try again. */
00159           failed_steps++;
00160           try_step_again=true;
00161         } else {
00162           try_step_again=false;
00163         }
00164 
00165       }
00166         
00167       /* suggest step size for next time-step */
00168       h = h0;  
00169   
00170       // This used to be return step_status, but the code never 
00171       // reaches this point if step_status is anything other than zero.
00172       return gsl_success;
00173     }
00174       
00175 #endif
00176     
00177     public:
00178       
00179     gsl_astep_old() {
00180       this->verbose=0;
00181       msize=0;
00182     }
00183       
00184     virtual ~gsl_astep_old() {
00185       if (msize>0) {
00186         ao.free(yout);
00187         ao.free(dydx_int);
00188       }
00189     }
00190     
00191     /// Control specification
00192     gsl_ode_control<vec_t> con;
00193     
00194     /** \brief Make an adaptive integration step of the system 
00195         \c derivs with derivatives
00196           
00197         This attempts to take a step of size \c h from the point \c x
00198         of an \c n-dimensional system \c derivs starting with \c y and
00199         given the initial derivatives \c dydx. On exit, \c x, \c y and
00200         \c dydx contain the new values at the end of the step, \c h
00201         contains the size of the step, \c dydx contains the derivative
00202         at the end of the step, and \c yerr contains the estimated
00203         error at the end of the step.
00204 
00205         If the base stepper returns a non-zero value, the step is
00206         aborted and \c y is unmodified. The error handler is never
00207         called.
00208     */
00209     virtual int astep_derivs(double &x, double xmax, double &h, 
00210                              size_t n, vec_t &y, vec_t &dydx, 
00211                              vec_t &yerr, func_t &derivs) {
00212       count=0;
00213       failed_steps=0;
00214       last_step=0.0;
00215 
00216       if (n!=msize) {
00217         ao.allocate(yout,n);
00218         ao.allocate(dydx_int,n);
00219         msize=n;
00220       }
00221 
00222       int ret=evolve_apply(x,x,h,xmax,n,y,dydx,yout,yerr,dydx_int,
00223                            derivs);
00224 
00225       if (ret==gsl_success) {
00226         for(size_t i=0;i<n;i++) {
00227           y[i]=yout[i];
00228           dydx[i]=dydx_int[i];
00229         }
00230       }
00231         
00232       if (this->verbose>0) {
00233         std::cout << x << " ";
00234         for(size_t j=0;j<n;j++) std::cout << y[j] << " ";
00235         std::cout << std::endl;
00236       }
00237 
00238       return ret;
00239     }
00240   
00241     /** \brief Make an adaptive integration step of the system 
00242         \c derivs
00243 
00244         This function performs an adaptive integration step with the
00245         \c n-dimensional system \c derivs and parameter \c pa. It
00246         Begins at \c x with initial stepsize \c h, ensuring that the
00247         step goes no farther than \c xmax. At the end of the step, the
00248         size of the step taken is \c h and the new value of \c x is in
00249         \c x_out. Initially, the function values and derivatives
00250         should be specified in \c y and \c dydx. The function values,
00251         derivatives, and the error at the end of the step are given in
00252         \c yout, \c yerr, and \c dydx_out. Unlike in \c ode_step
00253         objects, the objects \c y, \c yout, \c dydx, and \c dydx_out
00254         must all be distinct.
00255 
00256         If the base stepper returns a non-zero value, the step is
00257         aborted. The error handler is never called.
00258 
00259         This adaptive stepper function is faster than astep() or
00260         astep_derivs() because it does not require any copying of
00261         vectors.
00262     */
00263     virtual int astep_full(double x, double xmax, double &x_out, double &h, 
00264                            size_t n, vec_t &y, vec_t &dydx, 
00265                            vec_t &yout2, vec_t &yerr, vec_t &dydx_out, 
00266                            func_t &derivs) {
00267 
00268       count=0;
00269       failed_steps=0;
00270       last_step=0.0;
00271     
00272       int ret=evolve_apply(x,x_out,h,xmax,n,y,dydx,yout2,yerr,dydx_out,
00273                            derivs);
00274     
00275       if (this->verbose>0) {
00276         std::cout << x_out << " ";
00277         for(size_t j=0;j<n;j++) std::cout << yout2[j] << " ";
00278         std::cout << std::endl;
00279       }
00280 
00281       return ret;
00282     }
00283       
00284     /** \brief Make an adaptive integration step of the system 
00285         \c derivs 
00286           
00287         This attempts to take a step of size \c h from the point \c
00288         x of an \c n-dimensional system \c derivs starting with \c
00289         y. On exit, \c x and \c y contain the new values at the end
00290         of the step, \c h contains the size of the step, \c dydx_out
00291         contains the derivative at the end of the step, and \c yerr
00292         contains the estimated error at the end of the step.
00293 
00294         If the system \c derivs or the base stepper return a non-zero 
00295         value, the adaptive step is aborted and \c y is unmodified. 
00296         The error handler is never called.
00297     */
00298     virtual int astep(double &x, double xmax, double &h, 
00299                       size_t n, vec_t &y, vec_t &dydx_out,
00300                       vec_t &yerr, func_t &derivs) {
00301       count=0;
00302       failed_steps=0;
00303       last_step=0.0;
00304 
00305       if (n!=msize) {
00306         ao.allocate(yout,n);
00307         ao.allocate(dydx_int,n);
00308         msize=n;
00309       }
00310       
00311       int ret=derivs(x,n,y,dydx_int);
00312       if (ret!=0) return ret;
00313       
00314       ret=evolve_apply(x,x,h,xmax,n,y,dydx_int,yout,yerr,dydx_out,
00315                        derivs);
00316 
00317       if (ret==gsl_success) {
00318         for(size_t i=0;i<n;i++) {
00319           y[i]=yout[i];
00320         }
00321       }
00322 
00323       if (this->verbose>0) {
00324         std::cout << x << " ";
00325         for(size_t j=0;j<n;j++) std::cout << y[j] << " ";
00326         std::cout << std::endl;
00327       }
00328 
00329       return ret;
00330     }
00331       
00332   };
00333 
00334 #ifndef DOXYGENP
00335 }
00336 #endif
00337 
00338 #endif
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).

Get Object-oriented Scientific Computing
Lib at SourceForge.net. Fast, secure and Free Open Source software
downloads.