00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 2008, 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_BV_SOLVE_H 00024 #define O2SCL_ODE_BV_SOLVE_H 00025 #include <string> 00026 #include <o2scl/collection.h> 00027 #include <o2scl/ovector_tlate.h> 00028 #include <o2scl/adapt_step.h> 00029 #include <o2scl/gsl_astep.h> 00030 #include <o2scl/ode_iv_solve.h> 00031 #include <o2scl/gsl_mroot_hybrids.h> 00032 00033 #ifndef DOXYGENP 00034 namespace o2scl { 00035 #endif 00036 00037 /** 00038 \brief Solve boundary-value ODE problems 00039 */ 00040 template<class param_t, class func_t, class vec_t=ovector_view, 00041 class alloc_vec_t=ovector, class alloc_t=ovector_alloc, 00042 class vec_int_t=ovector_int_view> class ode_bv_solve { 00043 00044 public: 00045 00046 ode_bv_solve() { 00047 oisp=&def_ois; 00048 mrootp=&def_mroot; 00049 verbose=0; 00050 } 00051 00052 virtual ~ode_bv_solve() {} 00053 00054 /** 00055 \brief Solve the boundary-value problem 00056 */ 00057 virtual int solve(double x0, double x1, double h, size_t n, 00058 vec_t &ystart, vec_t ¥d, vec_int_t &index, 00059 param_t &pa, func_t &derivs)=0; 00060 00061 /** \name Values for the index array */ 00062 //@{ 00063 /// Unknown on both the left and right boundaries 00064 static const int unk=0; 00065 /// Known on the right boundary 00066 static const int right=1; 00067 /// Known on the left boundary 00068 static const int left=2; 00069 /// Known on both the left and right boundaries 00070 static const int both=3; 00071 //@} 00072 00073 /** 00074 \brief Set initial value solver 00075 */ 00076 int set_iv(ode_iv_solve<param_t,func_t,vec_t,alloc_vec_t,alloc_t> &ois) { 00077 oisp=&ois; 00078 return 0; 00079 } 00080 00081 /** \brief Set the equation solver */ 00082 int set_mroot(mroot<param_t,mm_funct<param_t> > &root) { 00083 mrootp=&root; 00084 return 0; 00085 } 00086 00087 /// The default initial value solver 00088 ode_iv_solve<param_t,func_t,vec_t,alloc_vec_t,alloc_t> def_ois; 00089 00090 /// The default equation solver 00091 gsl_mroot_hybrids<param_t,mm_funct<param_t> > def_mroot; 00092 00093 /// Set output level 00094 int verbose; 00095 00096 #ifndef DOXYGEN_INTERNAL 00097 00098 protected: 00099 00100 //friend class io_tlate<ode_bv_solve>; 00101 00102 /// The solver for the initial value problem 00103 ode_iv_solve<param_t,func_t,vec_t,alloc_vec_t,alloc_t> *oisp; 00104 00105 /// The equation solver 00106 mroot<param_t,mm_funct<param_t> > *mrootp; 00107 00108 /// The index defining the boundary conditions 00109 vec_int_t *l_index; 00110 00111 /// Storage for the starting vector 00112 vec_t *l_ystart; 00113 00114 /// Storage for the ending vector 00115 vec_t *l_yend; 00116 00117 /// Storage for the starting point 00118 double l_x0; 00119 00120 /// Storage for the ending abcissa 00121 double l_x1; 00122 00123 /// Storage for the stepsize 00124 double l_h; 00125 00126 /// The functions to integrate 00127 func_t *l_derivs; 00128 00129 /// The number of functions 00130 size_t l_n; 00131 00132 #endif 00133 00134 }; 00135 00136 /** 00137 \brief Solve boundary-value ODE problems by shooting 00138 00139 \future Implement shooting from an internal point, either 00140 using a different class or using this one. 00141 */ 00142 template<class param_t, class func_t, class vec_t=ovector_view, 00143 class alloc_vec_t=ovector, class alloc_t=ovector_alloc, 00144 class vec_int_t=ovector_int_view> 00145 class ode_bv_shoot : public ode_bv_solve<param_t,func_t,vec_t, 00146 alloc_vec_t,alloc_t,vec_int_t> { 00147 00148 public: 00149 00150 ode_bv_shoot() {} 00151 00152 virtual ~ode_bv_shoot() {} 00153 00154 /** 00155 \brief Solve the boundary-value problem 00156 */ 00157 virtual int solve(double x0, double x1, double h, size_t n, 00158 vec_t &ystart, vec_t ¥d, vec_int_t &index, 00159 param_t &pa, func_t &derivs) { 00160 this->l_index=&index; 00161 this->l_ystart=&ystart; 00162 this->l_yend=¥d; 00163 this->l_x0=x0; 00164 this->l_x1=x1; 00165 this->l_h=h; 00166 this->l_derivs=&derivs; 00167 this->l_n=n; 00168 00169 int nsolve=0, nsolve2=0, j; 00170 00171 // Count the number of variables we'll need to solve for: 00172 for (size_t i=0;i<n;i++) { 00173 if (index[i]<2) nsolve++; 00174 if (index[i]%2==1) nsolve2++; 00175 } 00176 00177 // Make sure that the boundary conditions make sense: 00178 if (nsolve!=nsolve2) { 00179 set_err("Incorrect boundary conditions in ode_bv_shoot::solve", 00180 gsl_einval); 00181 return gsl_einval; 00182 } 00183 00184 // Make space for the solution 00185 ovector sx(nsolve), sy(nsolve); 00186 00187 // Copy initial guesses from ystart 00188 j=0; 00189 for (size_t i=0;i<n;i++) { 00190 if (index[i]<2) { 00191 sx[j]=ystart[i]; 00192 j++; 00193 } 00194 } 00195 00196 // Solve 00197 mm_funct_mfptr<ode_bv_shoot<param_t,func_t,vec_t,alloc_vec_t, 00198 alloc_t,vec_int_t>,param_t > 00199 mfm(this,&ode_bv_shoot<param_t,func_t,vec_t, 00200 alloc_vec_t,alloc_t,vec_int_t>::solve_fun); 00201 int ret=this->mrootp->msolve(nsolve,sx,pa,mfm); 00202 solve_fun(nsolve,sx,sy,pa); 00203 00204 // Copy the solution back to ystart and yend 00205 j=0; 00206 for (size_t i=0;i<n;i++) { 00207 if (index[i]<2) { 00208 ystart[i]=sx[j]; 00209 j++; 00210 } 00211 } 00212 00213 if (ret!=0) { 00214 add_err("Solver failed in ode_bv_shoot::solve().",ret); 00215 } 00216 return ret; 00217 } 00218 00219 #ifndef DOXYGEN_INTERNAL 00220 00221 protected: 00222 00223 //friend class io_tlate<ode_bv_shoot>; 00224 00225 /// Desc 00226 int solve_fun(size_t nv, const vec_t &sx, vec_t &sy, 00227 param_t &pa) { 00228 int j; 00229 ovector y(this->l_n), y2(this->l_n); 00230 00231 // Create leftmost point from combination of 00232 // starting array and proposed solution 00233 j=0; 00234 for(size_t i=0;i<this->l_n;i++) { 00235 if ((*this->l_index)[i]<2) { 00236 y[i]=sx[j]; 00237 j++; 00238 } else { 00239 y[i]=(*this->l_ystart)[i]; 00240 } 00241 } 00242 00243 // Shoot across 00244 this->oisp->solve_final_value(this->l_x0,this->l_x1,this->l_h, 00245 this->l_n,y,y2,pa,*this->l_derivs); 00246 00247 j=0; 00248 for(size_t i=0;i<this->l_n;i++) { 00249 if ((*this->l_index)[i]%2==1) { 00250 // Construct the equations from the rightmost point 00251 if ((*this->l_yend)[i]==0.0) { 00252 sy[j]=y2[i]; 00253 } else { 00254 sy[j]=(y2[i]-(*this->l_yend)[i])/(*this->l_yend)[i]; 00255 } 00256 j++; 00257 } else { 00258 // Otherwise copy the final values from y2 to *l_yend 00259 (*this->l_yend)[i]=y2[i]; 00260 } 00261 } 00262 00263 return 0; 00264 } 00265 #endif 00266 00267 }; 00268 00269 #ifdef O2SCL_NEVER_DEFINED 00270 00271 /** 00272 \brief Solve boundary-value ODE problems by relaxation 00273 00274 */ 00275 00276 class ode_bv_relax : public ode_bv_solve { 00277 public: 00278 00279 ode_bv_relax(); 00280 00281 virtual ~ode_bv_relax(); 00282 00283 /** 00284 \brief Solve the boundary-value problem 00285 00286 How to specify the boundary conditions? 00287 00288 */ 00289 virtual int solve(double x0, double x1, double h, size_t n, 00290 param_t &pa, func_t &derivs); 00291 00292 #ifndef DOXYGENP 00293 00294 protected: 00295 00296 friend class io_tlate<ode_bv_relax>; 00297 00298 #endif 00299 00300 }; 00301 00302 #endif 00303 00304 #ifndef DOXYGENP 00305 } 00306 #endif 00307 00308 #endif
Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.
Project hosting provided by
,
O2scl Sourceforge Project Page