00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00039
00040
00041 template<class param_t, class func_t, class vec_t=ovector_view,
00042 class alloc_vec_t=ovector, class alloc_t=ovector_alloc,
00043 class vec_int_t=ovector_int_view> class ode_bv_solve {
00044
00045 public:
00046
00047 ode_bv_solve() {
00048 oisp=&def_ois;
00049 mrootp=&def_mroot;
00050 verbose=0;
00051 }
00052
00053 virtual ~ode_bv_solve() {}
00054
00055
00056
00057
00058 virtual int solve(double x0, double x1, double h, size_t n,
00059 vec_t &ystart, vec_t ¥d, vec_int_t &index,
00060 param_t &pa, func_t &derivs) {
00061 set_err_ret("Missing function in ode_bv_solve::solve().",gsl_nobase);
00062 }
00063
00064
00065
00066
00067 static const int unk=0;
00068
00069 static const int right=1;
00070
00071 static const int left=2;
00072
00073 static const int both=3;
00074
00075
00076
00077
00078
00079 int set_iv(ode_iv_solve<param_t,func_t,vec_t,alloc_vec_t,alloc_t> &ois) {
00080 oisp=&ois;
00081 return 0;
00082 }
00083
00084
00085 int set_mroot(mroot<param_t,mm_funct<param_t> > &root) {
00086 mrootp=&root;
00087 return 0;
00088 }
00089
00090
00091 ode_iv_solve<param_t,func_t,vec_t,alloc_vec_t,alloc_t> def_ois;
00092
00093
00094 gsl_mroot_hybrids<param_t,mm_funct<param_t> > def_mroot;
00095
00096
00097 int verbose;
00098
00099 #ifndef DOXYGEN_INTERNAL
00100
00101 protected:
00102
00103
00104
00105
00106 ode_iv_solve<param_t,func_t,vec_t,alloc_vec_t,alloc_t> *oisp;
00107
00108
00109 mroot<param_t,mm_funct<param_t> > *mrootp;
00110
00111
00112 vec_int_t *l_index;
00113
00114
00115 vec_t *l_ystart;
00116
00117
00118 vec_t *l_yend;
00119
00120
00121 double l_x0;
00122
00123
00124 double l_x1;
00125
00126
00127 double l_h;
00128
00129
00130 func_t *l_derivs;
00131
00132
00133 size_t l_n;
00134
00135 #endif
00136
00137 };
00138
00139
00140
00141
00142
00143 template<class param_t, class func_t, class vec_t=ovector_view,
00144 class alloc_vec_t=ovector, class alloc_t=ovector_alloc,
00145 class vec_int_t=ovector_int_view>
00146 class ode_bv_shoot : public ode_bv_solve<param_t,func_t,vec_t,
00147 alloc_vec_t,alloc_t,vec_int_t> {
00148
00149 public:
00150
00151 ode_bv_shoot() {}
00152
00153 virtual ~ode_bv_shoot() {}
00154
00155
00156
00157
00158 virtual int solve(double x0, double x1, double h, size_t n,
00159 vec_t &ystart, vec_t ¥d, vec_int_t &index,
00160 param_t &pa, func_t &derivs) {
00161 this->l_index=&index;
00162 this->l_ystart=&ystart;
00163 this->l_yend=¥d;
00164 this->l_x0=x0;
00165 this->l_x1=x1;
00166 this->l_h=h;
00167 this->l_derivs=&derivs;
00168 this->l_n=n;
00169
00170 int nsolve=0, nsolve2=0, j;
00171
00172
00173 for (size_t i=0;i<n;i++) {
00174 if (index[i]<2) nsolve++;
00175 if (index[i]%2==1) nsolve2++;
00176 }
00177
00178
00179 if (nsolve!=nsolve2) {
00180 set_err("Incorrect boundary conditions in ode_bv_shoot::solve",
00181 gsl_einval);
00182 return gsl_einval;
00183 }
00184
00185
00186 ovector sx(nsolve), sy(nsolve);
00187
00188
00189 j=0;
00190 for (size_t i=0;i<n;i++) {
00191 if (index[i]<2) {
00192 sx[j]=ystart[i];
00193 j++;
00194 }
00195 }
00196
00197
00198 mm_funct_mfptr<ode_bv_shoot<param_t,func_t,vec_t,alloc_vec_t,
00199 alloc_t,vec_int_t>,param_t >
00200 mfm(this,&ode_bv_shoot<param_t,func_t,vec_t,
00201 alloc_vec_t,alloc_t,vec_int_t>::solve_fun);
00202 int ret=this->mrootp->msolve(nsolve,sx,pa,mfm);
00203 solve_fun(nsolve,sx,sy,pa);
00204
00205
00206 j=0;
00207 for (size_t i=0;i<n;i++) {
00208 if (index[i]<2) {
00209 ystart[i]=sx[j];
00210 j++;
00211 }
00212 }
00213
00214 if (ret!=0) {
00215 add_err("Solver failed in ode_bv_shoot::solve().",ret);
00216 }
00217 return ret;
00218 }
00219
00220 #ifndef DOXYGEN_INTERNAL
00221
00222 protected:
00223
00224
00225
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
00232
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
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
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
00259 (*this->l_yend)[i]=y2[i];
00260 }
00261 }
00262
00263 return 0;
00264 }
00265 #endif
00266
00267 };
00268
00269 #ifdef NEVER_DEFINED
00270
00271
00272
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
00285
00286
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