ode_iv_solve.h

00001 /*
00002   -------------------------------------------------------------------
00003   
00004   Copyright (C) 2006, 2007, 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 #ifndef O2SCL_ODE_IV_SOLVE_H
00024 #define O2SCL_ODE_IV_SOLVE_H
00025 
00026 #include <string>
00027 #include <o2scl/collection.h>
00028 #include <o2scl/adapt_step.h>
00029 #include <o2scl/gsl_astep.h>
00030 
00031 #ifndef DOXYGENP
00032 namespace o2scl {
00033 #endif
00034 
00035   /** 
00036       \brief Base for solving initial-value ODE problems
00037       
00038       \todo Consider modifying so that this can handle tables
00039       which are two small by removing o2sclf the rows and doubling
00040       the stepsize.
00041       \todo Decide what to do if the adaptive stepper fails. (1/18/07 
00042       - two approaches: continue no matter what, or just stop)
00043       \todo Convert to using \c astep_derivs()?
00044       
00045   */
00046   template<class param_t, class func_t, class vec_t=ovector_view, 
00047     class alloc_vec_t=ovector, class alloc_t=ovector_alloc, 
00048     class adapt_step=gsl_astep<param_t,func_t,vec_t,alloc_vec_t,alloc_t> > 
00049     class ode_iv_solve 
00050     
00051     {
00052       public:
00053       
00054       ode_iv_solve() {
00055         verbose=0;
00056       }
00057       
00058       virtual ~ode_iv_solve() {}
00059       
00060       /** 
00061           \brief Solve the initial-value problem and output a table 
00062 
00063           Initially, \c xsol should be a vector of size \c nsol, and
00064           \c ysol should be a two-dimensional array
00065           (i.e. omatrix_view) of size \c [nsol][n]. On exit, \c nsol
00066           will will be the size of the solution table, less than or
00067           equal to the original value of \c nsol.
00068       */
00069       template<class mat_t>
00070       int solve_table(double x0, double x1, double h, size_t n,
00071                       vec_t &ystart, size_t &nsol, vec_t &xsol, 
00072                       mat_t &ysol, param_t &pa, func_t &derivs) 
00073       {
00074         int ret=0, nmax=nsol, i;
00075         size_t j;
00076   
00077         xsol[0]=x0;
00078         for(j=0;j<n;j++) ysol[0][j]=ystart[j];
00079         if (verbose>0) print_iter(xsol[0],n,ystart);
00080   
00081         for(i=1;i<nmax && xsol[i-1]<x1 && ret==0;i++) {
00082     
00083           xsol[i]=xsol[i-1];
00084           for(j=0;j<n;j++) ysol[i][j]=ysol[i-1][j];
00085     
00086           omatrix_row ar(ysol,i);
00087           ret=astepper.astep(xsol[i],h,x1,n,ar,pa,derivs);
00088     
00089           if (verbose>0) print_iter(xsol[i],n,ar);
00090         }
00091 
00092         nsol=i;
00093 
00094         if (ret!=0) return ret;
00095 
00096         if (i==nmax && xsol[i-1]<x1) {
00097           set_err("Ran out of space in ode_iv_solve::solve_table().",
00098                   gsl_etable);
00099           return gsl_etable;
00100         }
00101         return 0;
00102       }
00103 
00104       /** \brief Solve the initial-value problem from \c x0 
00105           to \c x1 over a grid 
00106 
00107           Initially, \c xsol should be an array of size \c nsol, and \c
00108           ysol should be a \c omatrix of size \c [nsol][n].
00109 
00110           This function never takes a step larger than the grid
00111           size. This could cause inaccuracy if the grid size is too
00112           fine.
00113       */
00114       template<class mat_t>
00115       int solve_grid(double x0, double x1, double h, size_t n,
00116                      vec_t &ystart, size_t nsol, vec_t &xsol, mat_t &ysol,
00117                      param_t &pa, func_t &derivs) 
00118       {
00119         double x=x0, xnext;
00120         int ret=0;
00121         size_t j;
00122 
00123         xsol[0]=x0;
00124         for(j=0;j<n;j++) ysol[0][j]=ystart[j];
00125         if (verbose>0) print_iter(xsol[0],n,ystart);
00126 
00127         for(size_t i=1;i<nsol && ret==0;i++) {
00128     
00129           xsol[i]=xsol[i-1];
00130           for(j=0;j<n;j++) ysol[i][j]=ysol[i-1][j];
00131 
00132           xnext=x0+(x1-x0)*((double)i)/((double)(nsol-1));
00133     
00134           while(xsol[i]<xnext && ret==0) {
00135             omatrix_row ar(ysol,i);
00136             ret=astepper.astep(xsol[i],h,xnext,n,ar,pa,derivs);
00137             if (verbose>0) print_iter(xsol[i],n,ar);
00138           }
00139 
00140         }
00141         if (ret!=0) return ret;
00142         return 0;
00143       }
00144 
00145       /** \brief Solve the initial-value problem 
00146           to get the final value 
00147 
00148           For a partiular adaptive stepper, this will likely be the
00149           fastest approach, but it provides no information about 
00150           the solution other than the final value at x=x1.
00151       */
00152       int solve_final_value(double x0, double x1, double h, size_t n,
00153                             vec_t &ystart, vec_t &yend, 
00154                             param_t &pa, func_t &derivs) 
00155       {
00156         double x=x0;
00157         int ret=0;
00158         if (verbose>0) print_iter(x0,n,ystart);
00159 
00160         for(size_t i=0;i<n;i++) yend[i]=ystart[i];
00161 
00162         while(x<x1 && ret==0) {
00163           
00164           ret=astepper.astep(x,h,x1,n,yend,pa,derivs);
00165           
00166           if (verbose>0) print_iter(x,n,yend);
00167         }
00168 
00169         if (ret!=0) return ret;
00170         return 0;
00171       }
00172       
00173       /// Set output level
00174       int verbose;
00175 
00176       /// The adaptive stepper utilized
00177       adapt_step astepper;
00178       
00179 #ifndef DOXYGEN_INTERNAL
00180 
00181       protected:
00182       
00183       /// Print out iteration information
00184       virtual int print_iter(double x, size_t nv, vec_t &y) {
00185         std::cout << x << " ";
00186         for(size_t i=0;i<nv;i++) std::cout << y[i] << " ";
00187         std::cout << std::endl;
00188         if (verbose>1) {
00189           char ch;
00190           std::cin >> ch;
00191         }
00192         return 0;
00193       }
00194   
00195 #endif
00196 
00197     };
00198 
00199 #ifndef DOXYGENP
00200 }
00201 #endif
00202 
00203 #endif

Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.