ODEBND
|
00001 // Copyright (C) 2012-2014 Benoit Chachuat, Imperial College London. 00002 // All Rights Reserved. 00003 // This code is published under the Eclipse Public License. 00004 00005 #ifndef MC__ODEBND_GSL_HPP 00006 #define MC__ODEBND_GSL_HPP 00007 00008 #undef MC__ODEBND_GSL_PM_DEBUG 00009 #undef MC__ODEBND_GSL_SAMPLE_DEBUG 00010 #undef MC__ODEBND_GSL_LINTR_DEBUG 00011 #define MC__ODEBND_GSL_LINTR_PMJAC 00012 #undef MC__ODEBND_GSL_ELLTR_SCALED 00013 #undef MC__ODEBND_GSL_DINEQI_DEBUG 00014 00015 #include <stdexcept> 00016 #include <cassert> 00017 #include <cmath> 00018 #include <fstream> 00019 #include <vector> 00020 #include <sys/time.h> 00021 00022 #include "ellipsoid.hpp" 00023 #include "tmodel.hpp" 00024 #include "cmodel.hpp" 00025 00026 #include "odeslv_gsl.hpp" 00027 00028 namespace mc 00029 { 00042 template <typename T, typename PMT=mc::TModel<T>, typename PVT=mc::TVar<T> > 00043 class ODEBND_GSL: public BASE_GSL 00044 { 00045 private: 00046 typedef Ellipsoid E; 00047 00049 gsl_odeiv2_system _sys_dineqI; 00050 00052 gsl_odeiv2_driver *_driver_dineqI; 00053 00055 gsl_odeiv2_system _sys_dineqPM; 00056 00058 gsl_odeiv2_driver *_driver_dineqPM; 00059 00061 ODESLV_GSL<T>* _ODESLV_GSL; 00062 00064 std::list<const FFOp*> _opRHS; 00065 00067 std::list<const FFOp*> *_opRHSi; 00068 00070 std::list<const FFOp*> _opJAC; 00071 00073 std::list<const FFOp*> _opIC; 00074 00076 T* _IRHS; 00077 00079 T* _IJAC; 00080 00082 PVT* _PMRHS; 00083 00085 PVT* _PMJAC; 00086 00088 const FFVar* _pRHS; 00089 00091 const FFVar* _pJAC; 00092 00094 const FFVar* _pIC; 00095 00097 unsigned int _nVAR; 00098 00100 FFVar* _pVAR; 00101 00103 T *_IVAR; 00104 00106 T *_Ix; 00107 00109 T *_Ip; 00110 00112 PMT *_PMenv; 00113 00115 PVT *_PMVAR; 00116 00118 PVT *_PMx; 00119 00121 PVT *_PMp; 00122 00124 PVT *_PMxdot; 00125 00127 double *_RxLdot; 00128 00130 double *_RxUdot; 00131 00133 double *_pref; 00134 00136 double *_xref; 00137 00139 double *_A; 00140 00142 double *_B; 00143 00145 T *_Id; 00146 00148 T *_Idfdx; 00149 00151 E _Ed; 00152 00154 double *_Q; 00155 00157 double *_xrefdot; 00158 00160 double *_Bdot; 00161 00163 T *_Iddot; 00164 00166 T *_Ixdot; 00167 00169 double *_Qdot; 00170 00172 PMT *_MVXPenv; 00173 00175 PVT *_MVXPd; 00176 00178 PVT *_MVXPf; 00179 00181 PVT *_MVXPdfdx; 00182 00184 PVT *_MVXPVAR; 00185 00187 PVT *_MVXPx; 00188 00190 PVT *_MVXPp; 00191 00193 PMT *_MVPenv; 00194 00196 PVT *_MVPp; 00197 00199 PVT *_MVPx; 00200 00201 public: 00205 00206 ODEBND_GSL(); 00207 00209 virtual ~ODEBND_GSL(); 00210 00212 struct Results 00213 { 00215 Results 00216 ( const double tk, const unsigned int nxk, const T*Ixk ): 00217 t( tk ), nx( nxk ) 00218 { X = new T[nx]; 00219 for( unsigned int ix=0; ix<nx; ix++ ) X[ix] = Ixk[ix]; } 00220 Results 00221 ( const double tk, const unsigned int nxk, const PVT*PMxk ): 00222 t( tk ), nx( nxk ) 00223 { X = new T[nx]; 00224 for( unsigned int ix=0; ix<nx; ix++ ) X[ix] = PMxk[ix].B(); } 00225 Results 00226 ( const Results&res ): 00227 t( res.t ), nx( res.nx ) 00228 { X = new T[nx]; 00229 for( unsigned int ix=0; ix<nx; ix++ ) X[ix] = res.X[ix]; } 00231 ~Results() 00232 { delete[] X; } 00234 double t; 00236 unsigned int nx; 00238 T* X; 00239 }; 00240 00242 struct Options: public BASE_GSL::Options 00243 { 00245 Options(): 00246 BASE_GSL::Options(), WRAPMIT(ELLIPS), ORDMIT(2), PMOPT(typename PMT::Options()), 00247 ODESLVOPT(typename ODESLV_GSL<T>::Options()), QTOL(machprec()), USEINV(true), 00248 DISPLAY(1), RESRECORD(false) 00249 {} 00251 Options& operator= 00252 ( Options&options ){ 00253 BASE_GSL::Options::operator=(options); 00254 WRAPMIT = options.WRAPMIT; 00255 ORDMIT = options.ORDMIT; 00256 PMOPT = options.PMOPT; 00257 ODESLVOPT = options.ODESLVOPT; 00258 QTOL = options.QTOL; 00259 USEINV = options.USEINV; 00260 DISPLAY = options.DISPLAY; 00261 RESRECORD = options.RESRECORD; 00262 return *this; 00263 } 00265 enum WRAPPING_STRATEGY{ 00266 NONE=0, 00267 DINEQ, 00268 ELLIPS 00269 }; 00271 WRAPPING_STRATEGY WRAPMIT; 00273 unsigned int ORDMIT; 00275 typename PMT::Options PMOPT; 00277 typename ODESLV_GSL<T>::Options ODESLVOPT; 00279 double QTOL; 00281 bool USEINV; 00283 int DISPLAY; 00285 bool RESRECORD; 00286 } options; 00287 00289 class Exceptions 00290 { 00291 public: 00293 enum TYPE{ 00294 REINIT=1, 00295 UNDEF=-33 00296 }; 00298 Exceptions( TYPE ierr ) : _ierr( ierr ){} 00300 int ierr(){ return _ierr; } 00302 std::string what(){ 00303 switch( _ierr ){ 00304 case REINIT: 00305 return "ODEBND_GSL::Exceptions State reinitialization at intermediate stage not allowed"; 00306 case UNDEF: default: 00307 return "ODEBND_GSL::Exceptions Calling a feature not yet implemented"; 00308 } 00309 } 00310 private: 00311 TYPE _ierr; 00312 }; 00313 00315 Stats stats_traj; 00316 00318 STATUS bounds 00319 ( const unsigned int ns, const double*tk, const T*Ip, T**Ixk, 00320 std::ostream&os=std::cout ); 00321 00323 STATUS bounds 00324 ( const unsigned int ns, const double*tk, const PVT*PMp, PVT**PMxk, 00325 E*Exk=0, std::ostream&os=std::cout ); 00326 00328 STATUS hausdorff 00329 ( const unsigned int ns, const double*tk, const T*Ip, double**Hxk, 00330 const unsigned int nsamp, std::ostream&os=std::cout ); 00331 00333 STATUS hausdorff 00334 ( const unsigned int ns, const double*tk, const PVT*PMp, double**Hxk, 00335 const unsigned int nsamp, std::ostream&os=std::cout ); 00336 00338 void record 00339 ( std::ofstream&bndrec, const unsigned int iprec=5 ) const; 00340 00342 double final_time() const 00343 { return _t; }; 00346 00347 static ODEBND_GSL<T,PMT,PVT> *pODEBND_GSL; 00348 00349 private: 00350 00352 std::vector< Results > _results; 00353 00355 void _GSL_term(); 00356 00358 void _GSL_init 00359 ( gsl_odeiv2_system &sys, gsl_odeiv2_driver *&driver ); 00360 00362 STATUS _remainders 00363 ( const unsigned int ns, const double*tk, const T*Ip, const PVT*const*PMxk, 00364 T**Rxk, const unsigned int nsamp, std::ostream&os=std::cout ); 00365 00367 STATUS _remainders 00368 ( const unsigned int ns, const double*tk, const T*Ip, const PVT*const*PMxk, 00369 T**Rxk, const unsigned int nsamp, unsigned int* vsamp, 00370 const unsigned int ip, double*p, double**xk, std::ostream&os ); 00371 00373 void _GSL_init 00374 ( const T*Ip ); 00375 00377 void _init 00378 ( T*Ix0 ); 00379 00381 bool _set_RHS_dineqI 00382 ( const unsigned int iRHS ); 00383 00385 void _I2vec 00386 ( const double*dL, const double*dU, double*vec ); 00387 00389 void _I2vec 00390 ( const T*Id, double*vec ); 00391 00393 void _E2vec 00394 ( const double*xref, const double*Q, const double*B, double*vec ); 00395 00397 void _vec2I 00398 ( const double*vec, T*Ix ); 00399 00401 void _vec2E 00402 ( const double*vec, T*Ix ); 00403 00405 template<typename U> void _ep2x 00406 ( const U*d, const U*p, U*x ) const; 00407 00409 void _ep2x 00410 ( const double*Q, E&Ed, T*Id, const T*Ip, T*Ix ) const; 00411 00413 static int MC_GSLRHSI__ 00414 ( double t, const double* x, double* xdot, void* user_data ); 00415 00417 int _ODEBND_GSL_RHSI 00418 ( double t, const double* x, double* xdot, void* user_data ); 00419 00421 static int MC_GSLJACI__ 00422 ( double t, const double* x, double* jac, double* xdot, void* user_data ); 00423 00425 int _ODEBND_GSL_JACI 00426 ( double t, const double* x, double* jac, double* xdot, void* user_data ); 00427 00429 bool _GSL_init 00430 ( const PVT*PMp ); 00431 00433 void _init 00434 ( PVT*PMx0 ); 00435 00437 bool _set_RHS_dineqPM 00438 ( const unsigned int iRHS ); 00439 00441 void _PMI2vec 00442 ( const PVT*PM, const double*RxL, const double*RxU, double*vec ); 00443 00445 void _PMI2vec 00446 ( const PVT*PM, const T*D, double*vec ); 00447 00449 void _PMI2vec 00450 ( const PVT*PM, double*vec ); 00451 00453 void _PME2vec 00454 ( const PVT*PM, const double*Q, double*vec ); 00455 00457 void _vec2PMI 00458 ( const double*vec, PVT*PM ); 00459 00461 void _vec2PME 00462 ( const double*vec, PVT*PM ); 00463 00465 template<typename U> void _d2x 00466 ( const U*d, U*x, const bool reinit=true ) const; 00467 00469 template<typename U> void _e2x 00470 ( const U*d, U*x, const bool reinit=true ) const; 00471 00473 void _e2x 00474 ( const double*Q, E&Ed, T*Id ) const; 00475 00477 static int MC_GSLRHSPM__ 00478 ( double t, const double* x, double* xdot, void* user_data ); 00479 00481 int _ODEBND_GSL_RHSPM 00482 ( double t, const double* x, double* xdot, void* user_data ); 00483 00485 void _PROP_PM_ELL0 00486 ( const double t ); 00487 00489 void _PROP_PM_ELL1 00490 ( const double t ); 00491 00493 void _PROP_PM_ELL2 00494 ( const double t ); 00495 00497 static int MC_GSLJACPM__ 00498 ( double t, const double* x, double* jac, double* xdot, void* user_data ); 00499 00501 int _ODEBND_GSL_JACPM 00502 ( double t, const double* x, double* jac, double* xdot, void* user_data ); 00503 00505 template<typename U> void _print_interm 00506 ( const double t, const U*x, const std::string&var, std::ostream&os=std::cout ) const; 00507 00509 template<typename U, typename V> void _print_interm 00510 ( const double t, const U*x, const V&r, const std::string&var, std::ostream&os=std::cout ) const; 00511 00513 unsigned int _ndxLT 00514 ( const unsigned int i, const unsigned int j ) const 00515 { return( i<j? _ndxLT(j,i): i+j*_nx-j*(j+1)/2 ); } 00516 00518 ODEBND_GSL(const ODEBND_GSL&); 00519 ODEBND_GSL& operator=(const ODEBND_GSL&); 00520 }; 00521 00522 template <typename T, typename PMT, typename PVT> 00523 ODEBND_GSL<T,PMT,PVT>* ODEBND_GSL<T,PMT,PVT>::pODEBND_GSL = 0; 00524 00525 template <typename T, typename PMT, typename PVT> inline 00526 ODEBND_GSL<T,PMT,PVT>::ODEBND_GSL 00527 () 00528 : BASE_GSL(), _pRHS(0), _pJAC(0), _pIC(0), _nVAR(0), _pVAR(0) 00529 { 00530 // Initalize state/parameter arrays 00531 _opRHSi = 0; 00532 _IRHS = _IJAC = _IVAR = _Ix = _Ip = 0; 00533 _PMRHS = _PMJAC = _PMVAR = _PMp = _PMx = _PMxdot = 0; 00534 _PMenv = 0; 00535 00536 // Initialize parameterization arrays 00537 _pref = _xref = _xrefdot = 0; 00538 _A = _B = _Bdot = _Q = _Qdot = 0; 00539 _Id = _Idfdx = _Iddot = _Ixdot = 0; 00540 _RxLdot = _RxUdot = 0; 00541 00542 // Initialize polynomial model environments 00543 _MVXPenv = _MVPenv = 0; 00544 _MVXPd = _MVXPf = _MVXPdfdx = _MVXPVAR = _MVXPx = _MVXPp = _MVPp = _MVPx = 0; 00545 00546 // Initialize ellipsoidal calculus 00547 E::options.PSDCHK = false; 00548 00549 // Initalize GSL 00550 _driver_dineqI = 0; 00551 _driver_dineqPM = 0; 00552 _ODESLV_GSL = new ODESLV_GSL<T>(); 00553 } 00554 00555 template <typename T, typename PMT, typename PVT> inline 00556 ODEBND_GSL<T,PMT,PVT>::~ODEBND_GSL 00557 () 00558 { 00559 /* DO NOT FREE _pRHS */ 00560 delete[] _opRHSi; 00561 delete[] _IRHS; 00562 delete[] _PMRHS; 00563 delete[] _IJAC; 00564 delete[] _PMJAC; 00565 delete[] _pJAC; 00566 delete[] _pVAR; 00567 00568 // Free state arrays -- Do *NOT* delete _p _Ip _PMp _PMenv 00569 delete[] _IVAR; // **DO NOT DELETE _Ix, _Ip** 00570 delete[] _PMVAR; // **DO NOT DELETE _PMx, _PMp** 00571 delete[] _PMxdot; 00572 delete[] _RxLdot; 00573 delete[] _RxUdot; 00574 00575 // Free linear transformation arrays 00576 delete[] _pref; 00577 delete[] _xref; 00578 delete[] _A; 00579 delete[] _B; 00580 delete[] _Id; 00581 delete[] _Idfdx; 00582 delete[] _Q; 00583 delete[] _xrefdot; 00584 delete[] _Bdot; 00585 delete[] _Iddot; 00586 delete[] _Ixdot; 00587 delete[] _Qdot; 00588 delete[] _MVXPd; 00589 delete[] _MVXPf; 00590 delete[] _MVXPdfdx; 00591 delete[] _MVXPVAR; // **DO NOT DELETE _MVXPx, _MVXPp** 00592 delete _MVXPenv; 00593 delete[] _MVPp; 00594 delete[] _MVPx; 00595 delete _MVPenv; 00596 00597 // Free GSL arrays 00598 if( _driver_dineqI ) gsl_odeiv2_driver_free( _driver_dineqI ); 00599 if( _driver_dineqPM ) gsl_odeiv2_driver_free( _driver_dineqPM ); 00600 delete _ODESLV_GSL; 00601 } 00602 00603 template <typename T, typename PMT, typename PVT> inline void 00604 ODEBND_GSL<T,PMT,PVT>::_GSL_init 00605 ( gsl_odeiv2_system &sys, gsl_odeiv2_driver *&driver ) 00606 { 00607 // Set GSL driver 00608 if( driver ) gsl_odeiv2_driver_free( driver ); 00609 switch( options.INTMETH ){ 00610 case Options::RK8PD: 00611 driver = gsl_odeiv2_driver_alloc_y_new( &sys, gsl_odeiv2_step_rk8pd, 00612 options.H0, options.ATOL, options.RTOL ); 00613 break; 00614 case Options::MSADAMS: 00615 driver = gsl_odeiv2_driver_alloc_y_new( &sys, gsl_odeiv2_step_msadams, 00616 options.H0, options.ATOL, options.RTOL ); 00617 break; 00618 case Options::MSBDF: 00619 driver = gsl_odeiv2_driver_alloc_y_new( &sys, gsl_odeiv2_step_msbdf, 00620 options.H0, options.ATOL, options.RTOL ); 00621 break; 00622 case Options::RKF45: default: 00623 driver = gsl_odeiv2_driver_alloc_y_new( &sys, gsl_odeiv2_step_rkf45, 00624 options.H0, options.ATOL, options.RTOL ); 00625 break; 00626 } 00627 gsl_odeiv2_driver_set_hmin( driver, options.HMIN ); 00628 gsl_odeiv2_driver_set_nmax( driver, options.NMAX ); 00629 00630 // Set state storage 00631 delete [] _vec_state; 00632 _vec_state = new double[ sys.dimension ]; 00633 } 00634 00635 template <typename T, typename PMT, typename PVT> inline void 00636 ODEBND_GSL<T,PMT,PVT>::_GSL_term() 00637 { 00638 // Get final CPU time 00639 _final_stats( stats_traj ); 00640 } 00641 00642 template <typename T, typename PMT, typename PVT> inline void 00643 ODEBND_GSL<T,PMT,PVT>::_vec2I 00644 ( const double*vec, T*Ix ) 00645 { 00646 for( unsigned int ix=0, ivec=0; ix<_nx; ix++ ){ 00647 Ix[ix] = T( vec[ivec], vec[ivec+1] ); 00648 ivec+=2; 00649 } 00650 return; 00651 } 00652 00653 template <typename T, typename PMT, typename PVT> template<typename U> inline void 00654 ODEBND_GSL<T,PMT,PVT>::_ep2x 00655 ( const U*d, const U*p, U*x ) const 00656 { 00657 for( unsigned int ix=0; ix<_nx; ix++ ){ 00658 x[ix] = _xref[ix] + d[ix]; 00659 for( unsigned int jp=0; jp<_np; jp++ ) 00660 x[ix] += ( p[jp] - _pref[jp] ) * _B[jp*_nx+ix]; 00661 } 00662 return; 00663 } 00664 00665 template <typename T, typename PMT, typename PVT> inline void 00666 ODEBND_GSL<T,PMT,PVT>::_ep2x 00667 ( const double*Q, E&Ed, T*Id, const T*Ip, T*Ix ) const 00668 { 00669 Ed.set( _nx, Q ); 00670 #ifdef MC__ODEBND_GSL_LINTR_DEBUG 00671 std::cout << "Ed =" << Ed << std::endl; 00672 #endif 00673 for( unsigned int ix=0; ix<_nx; ix++ ) 00674 Id[ix] = T( Ed.l(ix), Ed.u(ix) ); 00675 _ep2x( Id, Ip, Ix ); 00676 00677 #ifdef MC__ODEBND_GSL_LINTR_DEBUG 00678 for( unsigned int ix=0; ix<_nx; ix++ ) 00679 std::cout << "Id[" << ix << "] = " << _Id[ix] << std::endl; 00680 for( unsigned int ix=0; ix<_nx; ix++ ) 00681 std::cout << "Ix[" << ix << "] = " << Ix[ix] << std::endl; 00682 { int dum; std::cin >> dum; } 00683 #endif 00684 return; 00685 } 00686 00687 template <typename T, typename PMT, typename PVT> inline void 00688 ODEBND_GSL<T,PMT,PVT>::_vec2E 00689 ( const double*vec, T*Ix ) 00690 { 00691 unsigned int ivec = 0; 00692 for( unsigned int ix=0; ix<_nx; ix++ ) 00693 _xref[ix] = vec[ivec++]; 00694 for( unsigned int iQ=0; iQ<_nx*(_nx+1)/2; iQ++ ) 00695 _Q[iQ] = vec[ivec++]; 00696 for( unsigned int iB=0; iB<_nx*_np; iB++ ) 00697 _B[iB] = vec[ivec++]; 00698 return _ep2x( _Q, _Ed, _Id, _Ip, Ix ); 00699 } 00700 00701 template <typename T, typename PMT, typename PVT> inline void 00702 ODEBND_GSL<T,PMT,PVT>::_I2vec 00703 ( const double*xL, const double*xU, double*vec ) 00704 { 00705 for( unsigned int ix=0, ivec=0; ix<_nx; ix++ ){ 00706 vec[ivec++] = xL[ix]; 00707 vec[ivec++] = xU[ix]; 00708 } 00709 return; 00710 } 00711 00712 template <typename T, typename PMT, typename PVT> inline void 00713 ODEBND_GSL<T,PMT,PVT>::_I2vec 00714 ( const T*Ix, double*vec ) 00715 { 00716 for( unsigned int ix=0, ivec=0; ix<_nx; ix++ ){ 00717 vec[ivec++] = Op<T>::l( Ix[ix] ); 00718 vec[ivec++] = Op<T>::u( Ix[ix] ); 00719 } 00720 return; 00721 } 00722 00723 template <typename T, typename PMT, typename PVT> inline void 00724 ODEBND_GSL<T,PMT,PVT>::_E2vec 00725 ( const double*xref, const double*Q, const double*B, double*vec ) 00726 { 00727 unsigned int ivec = 0; 00728 for( unsigned int ix=0; ix<_nx; ix++ ) 00729 vec[ivec++] = xref[ix]; 00730 for( unsigned int iQ=0; iQ<_nx*(_nx+1)/2; iQ++ ) 00731 vec[ivec++] = Q[iQ]; 00732 for( unsigned int iB=0; iB<_nx*_np; iB++ ) 00733 vec[ivec++] = B[iB]; 00734 return; 00735 } 00736 00737 template <typename T, typename PMT, typename PVT> inline void 00738 ODEBND_GSL<T,PMT,PVT>::_init 00739 ( T*Ix0 ) 00740 { 00741 switch( options.WRAPMIT){ 00742 00743 case Options::NONE: 00744 case Options::DINEQ: 00745 _pDAG->eval( _opIC, _nx, _pIC, Ix0, _np, _pVAR+_nx, _Ip ); 00746 return _I2vec( Ix0, _vec_state ); 00747 00748 case Options::ELLIPS: 00749 default: 00750 for( unsigned int ip=0; ip<_np; ip++ ){ 00751 _pref[ip] = Op<T>::mid( _Ip[ip] ); 00752 _MVPp[ip].set( _MVPenv, ip, _Ip[ip] ); 00753 } 00754 _pDAG->eval( _opIC, _nx, _pIC, _MVPx, _np, _pVAR+_nx, _MVPp ); 00755 00756 double trR2 = 0.; 00757 for( unsigned int ix=0, iQ=0; ix<_nx; ix++ ){ 00758 _xref[ix] = _MVPx[ix].constant(); 00759 for( unsigned int jp=0; jp<_np; jp++ ) _B[jp*_nx+ix] = _MVPx[ix].linear( jp ); 00760 Ix0[ix] = _MVPx[ix].bound(); 00761 trR2 += sqr( Op<T>::diam( _MVPx[ix].remainder() ) / 2. ); 00762 _Q[iQ++] = Op<T>::diam( _MVPx[ix].remainder() ) / 2.; 00763 for( unsigned int jx=ix+1; jx<_nx; jx++ ) _Q[iQ++] = 0.; 00764 } 00765 for( unsigned int ix=0, iQ=0; ix<_nx; ix++, iQ+=_nx-ix ) _Q[iQ] *= std::sqrt( trR2 ); 00766 #ifdef MC__ODEBND_GSL_LINTR_DEBUG 00767 E Ex0( _nx, _Q, _xref ); 00768 std::cout << "Ex0 =" << Ex0 << std::endl; 00769 #endif 00770 return _E2vec( _xref, _Q, _B, _vec_state ); 00771 } 00772 } 00773 00774 template <typename T, typename PMT, typename PVT> inline int 00775 ODEBND_GSL<T,PMT,PVT>::_ODEBND_GSL_RHSI 00776 ( double t, const double* x, double* xdot, void* user_data ) 00777 { 00778 if( !_pRHS ) return GSL_EBADFUNC; 00779 stats_traj.numRHS++; 00780 00781 switch( options.WRAPMIT){ 00782 case Options::NONE: 00783 _vec2I( x, _Ix ); // set current state bounds 00784 _IVAR[_nx+_np] = t; // set current time 00785 _pDAG->eval( _opRHS, _IRHS, _nx, _pRHS, _Ixdot, _nVAR, _pVAR, _IVAR ); 00786 _I2vec( _Ixdot, xdot ); 00787 return GSL_SUCCESS; 00788 00789 case Options::DINEQ: 00790 if( !_opRHSi ) return GSL_EBADFUNC; 00791 _vec2I( x, _Ix ); // set current state bounds 00792 _IVAR[_nx+_np] = t; // set current time 00793 for( unsigned int ix=0, ivec=0; ix<_nx; ix++ ){ 00794 T Ixi = _Ix[ix]; 00795 _Ix[ix] = Op<T>::l( Ixi ); 00796 _pDAG->eval( _opRHSi[ix], _IRHS, 1, _pRHS+ix, _Ixdot+ix, _nVAR, _pVAR, _IVAR ); 00797 xdot[ivec++] = Op<T>::l( _Ixdot[ix] ); 00798 _Ix[ix] = Op<T>::u( Ixi ); 00799 _pDAG->eval( _opRHSi[ix], _IRHS, 1, _pRHS+ix, _Ixdot+ix, _nVAR, _pVAR, _IVAR ); 00800 xdot[ivec++] = Op<T>::u( _Ixdot[ix] ); 00801 _Ix[ix] = Ixi; 00802 } 00803 return GSL_SUCCESS; 00804 00805 case Options::ELLIPS:{ 00806 default: 00807 _vec2E( x, _Ix ); // set current state enclosure 00808 #ifdef MC__ODEBND_GSL_DINEQI_DEBUG 00809 std::cout << "@t=" << t << std::endl; 00810 //E::options.PSDCHK = true; 00811 for( unsigned int ix=0; ix<_nx; ix++ ) 00812 std::cout << "xref[" << ix << "] = " << _xref[ix] << std::endl; 00813 for( unsigned int ix=0; ix<_nx; ix++ ){ 00814 std::cout << "B[" << ix << ",#] = "; 00815 for( unsigned int jp=0; jp<_np; jp++ ) 00816 std::cout << _B[jp*_np+ix] << " "; 00817 std::cout << std::endl; 00818 } 00819 std::cout << "Ed = " << _Ed << std::endl; 00820 { int dum; std::cin >> dum; } 00821 #endif 00822 double trQ = 0.; 00823 for( unsigned int ix=0; ix<_nx; ix++ ) 00824 trQ += ( _Q[_ndxLT(ix,ix)]>0? _Q[_ndxLT(ix,ix)]: machprec() ); 00825 00826 // Compute polynomial expansion of ODE's RHS 00827 for( unsigned int jx=0; jx<_nx; jx++ ) 00828 _MVXPd[jx].set( _MVXPenv, jx, _Id[jx] ); 00829 for( unsigned int jp=0; jp<_np; jp++ ) 00830 _MVXPp[jp].set( _MVXPenv, _nx+jp, _Ip[jp] ); 00831 _ep2x( _MVXPd, _MVXPp, _MVXPx ); 00832 #ifdef MC__ODEBND_GSL_DINEQI_DEBUG 00833 for( unsigned int ix=0; ix<_nx; ix++ ) 00834 std::cout << "MVXPx[ " << ix << "] = " << _MVXPx[ix] << std::endl; 00835 { int dum; std::cin >> dum; } 00836 #endif 00837 _MVXPVAR[_nx+_np] = t; // set current time 00838 _pDAG->eval( _opRHS, _PMRHS, _nx, _pRHS, _MVXPf, _nVAR, _pVAR, _MVXPVAR ); 00839 /* 00840 // Extract time derivatives of constant, linear and remainder parts 00841 double sumkappa = 0.; 00842 for( unsigned int ix=0; ix<_nx; ix++ ){ 00843 #ifdef MC__ODEBND_GSL_DINEQI_DEBUG 00844 std::cout << "MVXPf[" << ix << "] = " << _MVXPf[ix] << std::endl; 00845 #endif 00846 _xrefdot[ix] = _MVXPf[ix].constant() + Op<T>::mid( _MVXPf[ix].remainder() ); 00847 _Iddot[ix] = _MVXPf[ix].remainder() - Op<T>::mid( _MVXPf[ix].remainder() ); 00848 for( unsigned int iord=2; iord<=_MVXPenv->nord(); iord++ ){ 00849 _xrefdot[ix] += Op<T>::mid( _MVXPf[ix].bndord( iord ) ); 00850 _Iddot[ix] += _MVXPf[ix].bndord( iord ) 00851 - Op<T>::mid( _MVXPf[ix].bndord( iord ) ); 00852 } 00853 #ifdef MC__ODEBND_GSL_DINEQI_DEBUG 00854 std::cout << "xrefdot[" << ix << "] = " << _xrefdot[ix] << std::endl; 00855 std::cout << "Iddot[" << ix << "] = " << _Iddot[ix] 00856 << " : " << Op<T>::mid(_Iddot[ix]) << std::endl; 00857 std::cout << "kappa[" << ix << "] = " 00858 << Op<T>::diam( _Iddot[ix] ) / 2. 00859 / ( std::sqrt( trQ ) + options.QTOL ) << std::endl; 00860 #endif 00861 sumkappa += ( Op<T>::diam( _Iddot[ix] ) / 2. ) 00862 / ( std::sqrt( trQ ) + options.QTOL ); 00863 for( unsigned int jx=0; jx<_nx; jx++ ) 00864 _A[ix+jx*_nx] = _MVXPf[ix].linear(jx); 00865 #ifdef MC__ODEBND_GSL_DINEQI_DEBUG 00866 std::cout << "A[" << ix << ",#] = "; 00867 for( unsigned int jx=0; jx<_nx; jx++ ) 00868 std::cout << _A[ix+jx*_nx] << " "; 00869 std::cout << std::endl; 00870 #endif 00871 for( unsigned int jp=0; jp<_np; jp++ ) 00872 _Bdot[ix+jp*_nx] = _MVXPf[ix].linear(_nx+jp); 00873 #ifdef MC__ODEBND_GSL_DINEQI_DEBUG 00874 std::cout << "Bdot[" << ix << ",#] = "; 00875 for( unsigned int jp=0; jp<_np; jp++ ) 00876 std::cout << _Bdot[ix+jp*_nx] << " "; 00877 std::cout << std::endl; 00878 #endif 00879 } 00880 */ 00881 // Extract time derivatives of constant, linear and remainder parts 00882 //sumkappa = 0.; 00883 double sumkappa = 0.; 00884 for( unsigned int ix=0; ix<_nx; ix++ ){ 00885 #ifdef MC__ODEBND_GSL_DINEQI_DEBUG 00886 std::cout << "MVXPf[" << ix << "] = " << _MVXPf[ix] << std::endl; 00887 #endif 00888 for( unsigned int jx=0; jx<_nx; jx++ ) 00889 _A[ix+jx*_nx] = _MVXPf[ix].linear(jx,true); 00890 #ifdef MC__ODEBND_GSL_DINEQI_DEBUG 00891 std::cout << "A[" << ix << ",#] = "; 00892 for( unsigned int jx=0; jx<_nx; jx++ ) 00893 std::cout << _A[ix+jx*_nx] << " "; 00894 std::cout << std::endl; 00895 #endif 00896 for( unsigned int jp=0; jp<_np; jp++ ) 00897 _Bdot[ix+jp*_nx] = _MVXPf[ix].linear(_nx+jp,true); 00898 #ifdef MC__ODEBND_GSL_DINEQI_DEBUG 00899 std::cout << "Bdot[" << ix << ",#] = "; 00900 for( unsigned int jp=0; jp<_np; jp++ ) 00901 std::cout << _Bdot[ix+jp*_nx] << " "; 00902 std::cout << std::endl; 00903 #endif 00904 #ifdef MC__ODEBND_GSL_DINEQI_DEBUG 00905 std::cout << "MVXPf[" << ix << "] = " << _MVXPf[ix] << std::endl; 00906 #endif 00907 T Rfi = _MVXPf[ix].B(); 00908 _xrefdot[ix] = Op<T>::mid(Rfi); 00909 _Iddot[ix] = Rfi - Op<T>::mid(Rfi); 00910 #ifdef MC__ODEBND_GSL_DINEQI_DEBUG 00911 std::cout << "xrefdot[" << ix << "] = " << _xrefdot[ix] << std::endl; 00912 std::cout << "Iddot[" << ix << "] = " << _Iddot[ix] 00913 << " : " << Op<T>::mid(_Iddot[ix]) << std::endl; 00914 std::cout << "kappa[" << ix << "] = " 00915 << Op<T>::diam( _Iddot[ix] ) / 2. 00916 / ( std::sqrt( trQ ) + options.QTOL ) << std::endl; 00917 #endif 00918 sumkappa += ( Op<T>::diam( _Iddot[ix] ) / 2. ) 00919 / ( std::sqrt( trQ ) + options.QTOL ); 00920 } 00921 00922 for( unsigned int jx=0; jx<_nx; jx++ ){ 00923 for( unsigned int ix=jx; ix<_nx; ix++ ){ 00924 _Qdot[_ndxLT(ix,jx)] = sumkappa * _Q[_ndxLT(ix,jx)]; 00925 for( unsigned int kx=0; kx<_nx; kx++ ) 00926 _Qdot[_ndxLT(ix,jx)] += _Q[_ndxLT(ix,kx)] * _A[jx+kx*_nx] 00927 + _A[ix+kx*_nx] * _Q[_ndxLT(kx,jx)]; 00928 } 00929 _Qdot[_ndxLT(jx,jx)] += ( Op<T>::diam( _Iddot[jx] ) / 2. ) 00930 * ( std::sqrt( trQ ) + options.QTOL ); 00931 } 00932 #ifdef MC__ODEBND_GSL_DINEQI_DEBUG 00933 for( unsigned int ix=0; ix<_nx; ix++ ){ 00934 std::cout << "Qdot[" << ix << ",#] = "; 00935 for( unsigned int jx=0; jx<=ix; jx++ ) 00936 std::cout << _Qdot[_ndxLT(ix,jx)] << " "; 00937 std::cout << std::endl; 00938 } 00939 E Exdot( _nx, _Qdot, _xrefdot ); 00940 std::cout << "Exdot =" << Exdot << std::endl; 00941 { int dum; std::cin >> dum; } 00942 #endif 00943 00944 // Copy time derivative in GSL array 00945 _E2vec( _xrefdot, _Qdot, _Bdot, xdot ); 00946 00947 return GSL_SUCCESS; 00948 } 00949 } 00950 } 00951 00952 template <typename T, typename PMT, typename PVT> inline int 00953 ODEBND_GSL<T,PMT,PVT>::MC_GSLRHSI__ 00954 ( double t, const double* x, double* xdot, void* user_data ) 00955 { 00956 ODEBND_GSL<T,PMT,PVT> *pODEBND_GSL = ODEBND_GSL<T,PMT,PVT>::pODEBND_GSL; 00957 int flag = pODEBND_GSL->_ODEBND_GSL_RHSI( t, x, xdot, user_data ); 00958 ODEBND_GSL<T,PMT,PVT>::pODEBND_GSL = pODEBND_GSL; 00959 return flag; 00960 } 00961 00962 template <typename T, typename PMT, typename PVT> inline int 00963 ODEBND_GSL<T,PMT,PVT>::_ODEBND_GSL_JACI 00964 ( double t, const double* x, double* jac, double* xdot, void* user_data ) 00965 { 00966 // Jacobian not (yet) implemented -- Use RK methods 00967 return GSL_EBADFUNC; 00968 } 00969 00970 template <typename T, typename PMT, typename PVT> inline int 00971 ODEBND_GSL<T,PMT,PVT>::MC_GSLJACI__ 00972 ( double t, const double* x, double* jac, double* xdot, void* user_data ) 00973 { 00974 ODEBND_GSL<T,PMT,PVT> *pODEBND_GSL = ODEBND_GSL<T,PMT,PVT>::pODEBND_GSL; 00975 int flag = pODEBND_GSL->_ODEBND_GSL_JACI( t, x, jac, xdot, user_data ); 00976 ODEBND_GSL<T,PMT,PVT>::pODEBND_GSL = pODEBND_GSL; 00977 return flag; 00978 } 00979 00980 template <typename T, typename PMT, typename PVT> inline void 00981 ODEBND_GSL<T,PMT,PVT>::_GSL_init 00982 ( const T* Ip ) 00983 { 00984 // Set GSL driver 00985 _sys_dineqI.function = MC_GSLRHSI__; 00986 _sys_dineqI.jacobian = MC_GSLJACI__; 00987 _sys_dineqI.params = 0; 00988 _sys_dineqI.dimension = 0; 00989 switch( options.WRAPMIT){ 00990 case Options::NONE: 00991 case Options::DINEQ: 00992 _sys_dineqI.dimension += 2*_nx; 00993 break; 00994 case Options::ELLIPS: 00995 default: 00996 _sys_dineqI.dimension += _nx*(1+_np)+_nx*(_nx+1)/2; 00997 break; 00998 } 00999 _GSL_init( _sys_dineqI, _driver_dineqI ); 01000 01001 // Size and set DAG evaluation arrays 01002 _nVAR = _nx+_np+1; 01003 delete[] _pVAR; _pVAR = new FFVar[_nVAR]; 01004 delete[] _IVAR; _IVAR = new T[_nVAR]; 01005 for( unsigned ix=0; ix<_nx; ix++ ) _pVAR[ix] = _pX[ix]; 01006 for( unsigned ip=0; ip<_np; ip++ ) _pVAR[_nx+ip] = _pP[ip]; 01007 _pVAR[_nx+_np] = (_pT? *_pT: 0. ); 01008 for( unsigned ip=0; ip<_np; ip++ ) _IVAR[_nx+ip] = Ip[ip]; 01009 _Ix = _IVAR; 01010 _Ip = _IVAR + _nx; 01011 01012 // Reset _MVXPVenv and related variables 01013 if( _MVXPenv && ( _MVXPenv->nord() != options.ORDMIT 01014 || _MVXPenv->nvar() != _nx+_np ) ){ 01015 delete[] _MVXPf; _MVXPf = 0; 01016 delete[] _MVXPd; _MVXPd = 0; 01017 delete[] _MVXPVAR; _MVXPVAR = 0; 01018 delete _MVXPenv; _MVXPenv = 0; 01019 } 01020 01021 // Reset _MVPVenv and related variables 01022 if( _MVPenv && ( _MVPenv->nord() != 1 01023 || _MVPenv->nvar() != _np ) ){ 01024 delete[] _MVXPx; _MVPx = 0; 01025 delete[] _MVXPp; _MVPp = 0; 01026 delete _MVPenv; _MVPenv = 0; 01027 } 01028 01029 // Set parameterization variables 01030 switch( options.WRAPMIT){ 01031 case Options::NONE: 01032 case Options::DINEQ: 01033 if( !_Ixdot ) _Ixdot = new T[_nx]; 01034 break; 01035 01036 case Options::ELLIPS: 01037 default: 01038 if( !_pref ) _pref = new double[_np]; 01039 if( !_xref ) _xref = new double[_nx]; 01040 if( !_A ) _A = new double[_nx*_nx]; 01041 if( !_B ) _B = new double[_nx*_np]; 01042 if( !_Q ) _Q = new double[_nx*(_nx+1)/2]; 01043 if( !_Id ) _Id = new T[_nx]; 01044 if( !_xrefdot ) _xrefdot = new double[_nx]; 01045 if( !_Bdot ) _Bdot = new double[_nx*_np]; 01046 if( !_Qdot ) _Qdot = new double[_nx*(_nx+1)/2]; 01047 if( !_Iddot ) _Iddot = new T[_nx]; 01048 if( !_MVXPenv ) _MVXPenv = new PMT( _nx+_np, options.ORDMIT ); 01049 _MVXPenv->options = options.PMOPT; 01050 if( !_MVXPd ) _MVXPd = new PVT[_nx]; 01051 if( !_MVXPf ) _MVXPf = new PVT[_nx]; 01052 if( !_MVXPVAR ) _MVXPVAR = new PVT[_nVAR]; 01053 _MVXPp = _MVXPVAR + _nx; 01054 _MVXPx = _MVXPVAR; 01055 if( !_MVPenv ) _MVPenv = new PMT( _np, 1 ); 01056 _MVPenv->options = options.PMOPT; 01057 if( !_MVPp ) _MVPp = new PVT[_np]; 01058 if( !_MVPx ) _MVPx = new PVT[_nx]; 01059 break; 01060 } 01061 01062 // Reset result record and statistics 01063 _results.clear(); 01064 _init_stats( stats_traj ); 01065 } 01066 01067 template <typename T, typename PMT, typename PVT> inline bool 01068 ODEBND_GSL<T,PMT,PVT>::_set_RHS_dineqI 01069 ( const unsigned int iRHS ) 01070 { 01071 if( _vRHS.size() <= iRHS ) return false; 01072 01073 _pRHS = _vRHS.at( iRHS ); 01074 _opRHS = _pDAG->subgraph( _nx, _pRHS ); 01075 01076 delete[] _IRHS; _IRHS = 0; 01077 delete[] _PMRHS; _PMRHS = 0; 01078 delete[] _opRHSi; _opRHSi = 0; 01079 switch( options.WRAPMIT){ 01080 case Options::NONE: 01081 _IRHS = new T[ _opRHS.size() ]; break; 01082 case Options::DINEQ: 01083 _opRHSi = new std::list<const FFOp*>[_nx]; 01084 for( unsigned ix=0; ix<_nx; ix++ ) 01085 _opRHSi[ix] = _pDAG->subgraph( 1, _pRHS+ix ); 01086 _IRHS = new T[ _opRHS.size() ]; break; 01087 case Options::ELLIPS: 01088 default: 01089 _PMRHS = new PVT[ _opRHS.size() ]; break; 01090 } 01091 01092 delete[] _pJAC; 01093 _pJAC = 0; 01094 _opJAC.clear(); 01095 01096 return true; 01097 } 01098 01112 template <typename T, typename PMT, typename PVT> 01113 inline typename ODEBND_GSL<T,PMT,PVT>::STATUS 01114 ODEBND_GSL<T,PMT,PVT>::bounds 01115 ( const unsigned int ns, const double*tk, const T*Ip, T**Ixk, std::ostream&os ) 01116 { 01117 // Initialize trajectory integration with GSL 01118 _GSL_init( Ip ); 01119 01120 try{ 01121 // Bounds on initial conditions 01122 if( !_vIC.size() ) 01123 { _GSL_term(); return FATAL; } 01124 _pIC = _vIC.at(0); 01125 _opIC = _pDAG->subgraph( _nx, _pIC ); 01126 _init( Ixk[0] ); 01127 if( options.DISPLAY >= 1 ) _print_interm( tk[0], Ixk[0], "x", os ); 01128 // Record initial results 01129 if( options.RESRECORD ) 01130 _results.push_back( Results( tk[0], _nx, Ixk[0] ) ); 01131 01132 // Integrate ODEs through each stage using GSL 01133 _t = tk[0]; 01134 _h = options.H0; 01135 pODEBND_GSL = this; 01136 01137 for( _istg=0; _istg<ns; _istg++ ){ 01138 if( _istg && _vIC.size()>1 ) throw Exceptions( Exceptions::REINIT ); 01139 01140 // update list of operations in RHS and JAC 01141 const unsigned int iRHS = ( _vRHS.size()<2? 0: _istg ); 01142 if( (!_istg || iRHS) && !_set_RHS_dineqI( iRHS ) ) 01143 { _GSL_term(); return FATAL; } 01144 01145 while( _t < tk[_istg+1] ){ 01146 if( gsl_odeiv2_evolve_apply( _driver_dineqI->e, _driver_dineqI->c, _driver_dineqI->s, 01147 &_sys_dineqI, &_t, tk[_istg+1], &_h, _vec_state ) != GSL_SUCCESS 01148 || _h < options.HMIN 01149 || (options.NMAX && stats_traj.numSteps > options.NMAX) ) 01150 throw Exceptions( Exceptions::UNDEF ); 01151 stats_traj.numSteps++; 01152 if( options.HMAX > 0 && _h > options.HMAX ) _h = options.HMAX; 01153 } 01154 01155 switch( options.WRAPMIT){ 01156 case Options::NONE: 01157 case Options::DINEQ: 01158 _vec2I( _vec_state, Ixk[_istg+1] ); break; 01159 case Options::ELLIPS: 01160 default: 01161 _vec2E( _vec_state, Ixk[_istg+1] ); break; 01162 } 01163 if( options.DISPLAY >= 1 ) _print_interm( tk[_istg+1], Ixk[_istg+1], "x", os ); 01164 // Record intermediate results 01165 if( options.RESRECORD ) 01166 _results.push_back( Results( tk[_istg+1], _nx, Ixk[_istg+1] ) ); 01167 } 01168 } 01169 catch(...){ 01170 _GSL_term(); 01171 if( options.DISPLAY >= 1 ) _print_stats( stats_traj, os ); 01172 return FAILURE; 01173 } 01174 01175 _GSL_term(); 01176 if( options.DISPLAY >= 1 ) _print_stats( stats_traj, os ); 01177 return NORMAL; 01178 } 01179 01195 template <typename T, typename PMT, typename PVT> inline typename ODEBND_GSL<T,PMT,PVT>::STATUS 01196 ODEBND_GSL<T,PMT,PVT>::hausdorff 01197 ( const unsigned int ns, const double*tk, const T*Ip, double**Hxk, 01198 const unsigned int nsamp, std::ostream&os ) 01199 { 01200 int DISPLAY_ODEBND = options.DISPLAY; 01201 int DISPLAY_ODESLV = options.ODESLVOPT.DISPLAY; 01202 options.DISPLAY = 0; 01203 options.ODESLVOPT.DISPLAY = 0; 01204 _ODESLV_GSL->set( *this ); // in base class BASE_ODE 01205 _ODESLV_GSL->options = options.ODESLVOPT; 01206 _ODESLV_GSL->options.RESRECORD = false; 01207 01208 // Compute exact bounds 01209 T** Ixk0 = new T*[ns+1]; 01210 for( unsigned int is=0; is<ns+1; is++ ) Ixk0[is] = new T[_nx]; 01211 if( _ODESLV_GSL->bounds( ns, tk, Ip, Ixk0, 0, nsamp, os ) != NORMAL ){ 01212 for( unsigned int is=0; is<ns+1; is++ ) delete[] Ixk0[is]; 01213 delete[] Ixk0; 01214 return FAILURE; 01215 } 01216 01217 // Compute approximate bounds 01218 T** Ixk = new T*[ns+1]; 01219 for( unsigned int is=0; is<ns+1; is++ ) Ixk[is] = new T[_nx]; 01220 try{ bounds( ns, tk, Ip, Ixk, os ); } 01221 catch(...){;} 01222 unsigned int nsf = _istg; 01223 for( unsigned int is=nsf; is<ns; is++ ) 01224 for( unsigned int ix=0; ix<_nx; ix++ ) 01225 Ixk[_istg+1][ix] = T( -1e20, 1e20 ); 01226 01227 // Compute Hausdorff metric at each time step 01228 struct loc{ static double hausdorff 01229 ( const T&Ix, const T&Ix0 ) 01230 { return std::max( std::fabs(Op<T>::l(Ix)-Op<T>::l(Ix0)), 01231 std::fabs(Op<T>::u(Ix)-Op<T>::u(Ix0)) ); } 01232 }; 01233 01234 options.DISPLAY = DISPLAY_ODEBND; 01235 options.ODESLVOPT.DISPLAY = DISPLAY_ODESLV; 01236 for( unsigned int is=0; is<ns+1; is++ ){ 01237 for( unsigned int ix=0; ix<_nx; ix++ ) 01238 Hxk[is][ix] = loc::hausdorff( Ixk[is][ix], Ixk0[is][ix] ); 01239 if( options.DISPLAY >= 1 ) _print_interm( tk[is], Hxk[is], "dH", os ); 01240 } 01241 01242 for( unsigned int is=0; is<ns+1; is++ ) delete[] Ixk0[is]; 01243 delete[] Ixk0; 01244 for( unsigned int is=0; is<ns+1; is++ ) delete[] Ixk[is]; 01245 delete[] Ixk; 01246 01247 return NORMAL; 01248 } 01249 01250 template <typename T, typename PMT, typename PVT> template<typename U> inline void 01251 ODEBND_GSL<T,PMT,PVT>::_d2x 01252 ( const U*d, U*x, const bool reinit ) const 01253 { 01254 for( unsigned int ix=0; ix<_nx; ix++ ){ 01255 if( reinit ) x[ix] = 0.; 01256 for( unsigned int jx=0; jx<_nx; jx++ ) 01257 x[ix] += d[jx] * _A[jx*_nx+ix]; 01258 } 01259 return; 01260 } 01261 01262 template <typename T, typename PMT, typename PVT> template<typename U> inline void 01263 ODEBND_GSL<T,PMT,PVT>::_e2x 01264 ( const U*d, U*x, const bool reinit ) const 01265 { 01266 for( unsigned int ix=0; ix<_nx; ix++ ){ 01267 if( reinit ) x[ix] = 0.; 01268 x[ix] += d[ix]; 01269 } 01270 return; 01271 } 01272 01273 template <typename T, typename PMT, typename PVT> inline void 01274 ODEBND_GSL<T,PMT,PVT>::_e2x 01275 ( const double*Q, E&Ed, T*Id ) const 01276 { 01277 Ed.set( _nx, _Q ); 01278 #ifdef MC__ODEBND_GSL_LINTR_DEBUG 01279 std::cout << "Ed =" << Ed << std::endl; 01280 #endif 01281 01282 for( unsigned int ix=0; ix<_nx; ix++ ) 01283 Id[ix] = T( Ed.l(ix), Ed.u(ix) ); 01284 01285 #ifdef MC__ODEBND_GSL_LINTR_DEBUG 01286 for( unsigned int ix=0; ix<_nx; ix++ ) 01287 std::cout << "Id[" << ix << "] = " << Id[ix] << std::endl; 01288 { int dum; std::cin >> dum; } 01289 #endif 01290 return; 01291 } 01292 01293 template <typename T, typename PMT, typename PVT> inline void 01294 ODEBND_GSL<T,PMT,PVT>::_vec2PMI 01295 ( const double*vec, PVT*PMx ) 01296 { 01297 unsigned int ivec=0; 01298 for( unsigned int ix=0; ix<_nx; ix++ ){ 01299 PMx[ix].set( _PMenv ); 01300 PMx[ix].set( vec+ivec ); 01301 ivec+=_PMenv->nmon(); 01302 PMx[ix].set( T( vec[ivec], vec[ivec+1] ) ); 01303 ivec+=2; 01304 } 01305 return; 01306 } 01307 01308 template <typename T, typename PMT, typename PVT> inline void 01309 ODEBND_GSL<T,PMT,PVT>::_vec2PME 01310 ( const double*vec, PVT*PMx ) 01311 { 01312 unsigned int ivec=0; 01313 for( unsigned int ix=0; ix<_nx; ix++ ){ 01314 PMx[ix].set( _PMenv ); 01315 PMx[ix].set( vec+ivec ); 01316 ivec+=_PMenv->nmon(); 01317 } 01318 for( unsigned int iQ=0; iQ<_nx*(_nx+1)/2; iQ++ ) 01319 _Q[iQ] = vec[ivec++]; 01320 _e2x( _Q, _Ed, _Id ); 01321 for( unsigned int ix=0; ix<_nx; ix++ ) 01322 PMx[ix].set( _Id[ix] ); 01323 return; 01324 } 01325 01326 template <typename T, typename PMT, typename PVT> inline void 01327 ODEBND_GSL<T,PMT,PVT>::_PMI2vec 01328 ( const PVT*PM, double*vec ) 01329 { 01330 unsigned int ivec=0; 01331 for( unsigned int ix=0; ix<_nx; ix++ ){ 01332 std::pair<unsigned int, const double*> PMcoef = PM[ix].coefmon(); 01333 unsigned int imon = 0; 01334 for( ; imon<PMcoef.first; imon++ ) 01335 vec[ivec++] = PMcoef.second[imon]; 01336 for( ; imon<_PMenv->nmon(); imon++ ) 01337 vec[ivec++] = 0.; 01338 vec[ivec++] = Op<T>::l( PM[ix].remainder() ); 01339 vec[ivec++] = Op<T>::u( PM[ix].remainder() ); 01340 } 01341 return; 01342 } 01343 01344 template <typename T, typename PMT, typename PVT> inline void 01345 ODEBND_GSL<T,PMT,PVT>::_PMI2vec 01346 ( const PVT*PM, const double*RxL, const double*RxU, double*vec ) 01347 { 01348 unsigned int ivec=0; 01349 for( unsigned int ix=0; ix<_nx; ix++ ){ 01350 std::pair<unsigned int, const double*> PMcoef = PM[ix].coefmon(); 01351 unsigned int imon = 0; 01352 for( ; imon<PMcoef.first; imon++ ) 01353 vec[ivec++] = PMcoef.second[imon]; 01354 for( ; imon<_PMenv->nmon(); imon++ ) 01355 vec[ivec++] = 0.; 01356 vec[ivec++] = RxL[ix]; 01357 vec[ivec++] = RxU[ix]; 01358 } 01359 return; 01360 } 01361 01362 template <typename T, typename PMT, typename PVT> inline void 01363 ODEBND_GSL<T,PMT,PVT>::_PMI2vec 01364 ( const PVT*PM, const T*Rx, double*vec ) 01365 { 01366 unsigned int ivec=0; 01367 for( unsigned int ix=0; ix<_nx; ix++ ){ 01368 std::pair<unsigned int, const double*> PMcoef = PM[ix].coefmon(); 01369 unsigned int imon = 0; 01370 for( ; imon<PMcoef.first; imon++ ) 01371 vec[ivec++] = PMcoef.second[imon]; 01372 for( ; imon<_PMenv->nmon(); imon++ ) 01373 vec[ivec++] = 0.; 01374 vec[ivec++] = Op<T>::l( Rx[ix] ); 01375 vec[ivec++] = Op<T>::u( Rx[ix] ); 01376 } 01377 return; 01378 } 01379 01380 template <typename T, typename PMT, typename PVT> inline void 01381 ODEBND_GSL<T,PMT,PVT>::_PME2vec 01382 ( const PVT*PM, const double*QRx, double*vec ) 01383 { 01384 unsigned int ivec=0; 01385 for( unsigned int ix=0; ix<_nx; ix++ ){ 01386 std::pair<unsigned int, const double*> PMcoef = PM[ix].coefmon(); 01387 unsigned int imon = 0; 01388 for( ; imon<PMcoef.first; imon++ ) 01389 vec[ivec++] = PMcoef.second[imon]; 01390 for( ; imon<_PMenv->nmon(); imon++ ) 01391 vec[ivec++] = 0.; 01392 } 01393 for( unsigned int iQ=0; iQ<_nx*(_nx+1)/2; iQ++ ) 01394 vec[ivec++] = QRx[iQ]; 01395 return; 01396 } 01397 01398 template <typename T, typename PMT, typename PVT> inline void 01399 ODEBND_GSL<T,PMT,PVT>::_init 01400 ( PVT*PMx0 ) 01401 { 01402 switch( options.WRAPMIT){ 01403 01404 case Options::NONE: 01405 case Options::DINEQ: 01406 _pDAG->eval( _opIC, _nx, _pIC, PMx0, _np, _pVAR+_nx, _PMp ); 01407 return _PMI2vec( PMx0, _vec_state ); 01408 01409 case Options::ELLIPS: 01410 default:{ 01411 _pDAG->eval( _opIC, _nx, _pIC, PMx0, _np, _pVAR+_nx, _PMp ); 01412 for( unsigned int ip=0; ip<_np; ip++ ) 01413 _pref[ip] = Op<T>::mid( _PMp[ip].B() ); 01414 double trR2 = 0.; 01415 for( unsigned int ix=0, iQ=0; ix<_nx; ix++ ){ 01416 trR2 += sqr( Op<T>::diam( PMx0[ix].remainder() ) / 2. ); 01417 _Q[iQ++] = Op<T>::diam( PMx0[ix].remainder() ) / 2.; 01418 for( unsigned int jx=ix+1; jx<_nx; jx++ ) _Q[iQ++] = 0.; 01419 _Id[ix] = PMx0[ix].remainder(); 01420 } 01421 for( unsigned int ix=0, iQ=0; ix<_nx; ix++, iQ+=_nx-ix ) 01422 _Q[iQ] *= std::sqrt( trR2 ); 01423 _Ed.set( _nx, _Q ); 01424 #ifdef MC__ODEBND_GSL_LINTR_DEBUG 01425 std::cout << "ERx0 =" << _Ed << std::endl; 01426 #endif 01427 return _PME2vec( PMx0, _Q, _vec_state ); } 01428 } 01429 } 01430 01431 template <typename T, typename PMT, typename PVT> inline int 01432 ODEBND_GSL<T,PMT,PVT>::MC_GSLRHSPM__ 01433 ( double t, const double* x, double* xdot, void* user_data ) 01434 { 01435 ODEBND_GSL<T,PMT,PVT> *pODEBND_GSL = ODEBND_GSL<T,PMT,PVT>::pODEBND_GSL; 01436 int flag = pODEBND_GSL->_ODEBND_GSL_RHSPM( t, x, xdot, user_data ); 01437 ODEBND_GSL<T,PMT,PVT>::pODEBND_GSL = pODEBND_GSL; 01438 return flag; 01439 } 01440 01441 template <typename T, typename PMT, typename PVT> inline int 01442 ODEBND_GSL<T,PMT,PVT>::_ODEBND_GSL_RHSPM 01443 ( double t, const double* x, double* xdot, void* user_data ) 01444 { 01445 if( !_pRHS ) return GSL_EBADFUNC; 01446 stats_traj.numRHS++; 01447 01448 switch( options.WRAPMIT){ 01449 case Options::NONE: 01450 _vec2PMI( x, _PMx ); // set current state polynomial model 01451 #ifdef MC__ODEBND_GSL_PM_DEBUG 01452 std::cerr << "PMx Intermediate" << std::endl; 01453 _print_interm( t, _PMx, "x", std::cerr ); 01454 #endif 01455 _PMVAR[_nx+_np] = t; // set current time 01456 _pDAG->eval( _opRHS, _PMRHS, _nx, _pRHS, _PMxdot, _nVAR, _pVAR, _PMVAR ); 01457 _PMI2vec( _PMxdot, xdot ); 01458 #ifdef MC__ODEBND_GSL_PM_DEBUG 01459 std::cerr << "PMxdot Intermediate" << std::endl; 01460 _print_interm( t, _PMxdot, "x", std::cerr ); 01461 {int dum; std::cin >> dum;} 01462 #endif 01463 return GSL_SUCCESS; 01464 01465 case Options::DINEQ: 01466 _vec2PMI( x, _PMx ); // set current state polynomial model 01467 for( unsigned int ix=0; ix<_nx; ix++ ) _PMx[ix].center(); 01468 #ifdef MC__ODEBND_GSL_PM_DEBUG 01469 std::cerr << "PMx Intermediate" << std::endl; 01470 _print_interm( t, _PMx, "x", std::cerr ); 01471 #endif 01472 _PMVAR[_nx+_np] = t; // set current time 01473 for( unsigned int ix=0; ix<_nx; ix++ ){ 01474 T Rxi = _PMx[ix].remainder(); 01475 _PMx[ix].set( Op<T>::l( Rxi ) ); 01476 _pDAG->eval( _opRHSi[ix], _PMRHS, 1, _pRHS+ix, _PMxdot+ix, _nVAR, _pVAR, _PMVAR ); 01477 _RxLdot[ix] = Op<T>::l( _PMxdot[ix].remainder() ); 01478 _PMx[ix].set( Op<T>::u( Rxi ) ); 01479 _pDAG->eval( _opRHSi[ix], _PMRHS, 1, _pRHS+ix, _PMxdot+ix, _nVAR, _pVAR, _PMVAR ); 01480 _RxUdot[ix] = Op<T>::u( _PMxdot[ix].remainder() ); 01481 _PMx[ix].set( Rxi ); 01482 } 01483 _PMI2vec( _PMxdot, _RxLdot, _RxUdot, xdot ); 01484 #ifdef MC__ODEBND_GSL_PM_DEBUG 01485 std::cerr << "PMxdot Intermediate" << std::endl; 01486 _print_interm( t, _PMxdot, "x", std::cerr ); 01487 {int dum; std::cin >> dum;} 01488 #endif 01489 return GSL_SUCCESS; 01490 01491 case Options::ELLIPS:{ 01492 default: 01493 _vec2PME( x, _PMx ); // set current state polynomial model 01494 _PMVAR[_nx+_np] = t; // set current time 01495 #ifdef MC__ODEBND_GSL_PM_DEBUG 01496 std::cout << "@t=" << t << std::endl; 01497 for( unsigned int ix=0; ix<_nx; ix++ ) 01498 std::cout << "PMx[ " << ix << "] = " << _PMx[ix] << std::endl; 01499 std::cout << "Ed = " << _Ed << std::endl; 01500 for( unsigned int ix=0; ix<_nx; ix++ ) 01501 std::cout << "Id[" << ix << "] = " << _Id[ix] 01502 << " : " << Op<T>::mid(_Id[ix]) << std::endl; 01503 #endif 01504 01505 // In this variant a bound on the Jacobian matrix is computed and the 01506 // linear part is taken as the mid-point of this matrix 01507 if( !options.ORDMIT ) 01508 _PROP_PM_ELL0( t ); 01509 01510 // In this variant a polynomial model of the Jacobian matrix is computed and the 01511 // linear part is taken as the mid-point of this matrix 01512 else if( _PMenv->nord() > _MVXPenv->nord() ) 01513 _PROP_PM_ELL1( t ); 01514 01515 // In this variant a polynomial model in the joint state-parameter and 01516 // of the same order as the parameter polynomial model is computed 01517 else 01518 _PROP_PM_ELL2( t ); 01519 01520 // Set dynamics of shape matrix 01521 double trQ = 0., sumkappa = 0.; 01522 for( unsigned int ix=0; ix<_nx; ix++ ) 01523 trQ += ( _Q[_ndxLT(ix,ix)]>0? _Q[_ndxLT(ix,ix)]: machprec() ); 01524 const double srqt_trQ = (trQ>0? std::sqrt( trQ ): 0.) + options.QTOL; 01525 for( unsigned int ix=0; ix<_nx; ix++ ){ 01526 #ifdef MC__ODEBND_GSL_PM_DEBUG 01527 std::cout << "kappa[" << ix << "] = " 01528 << Op<T>::diam( _Iddot[ix] ) / ( 2. * srqt_trQ ) << std::endl; 01529 #endif 01530 sumkappa += Op<T>::diam( _Iddot[ix] ) / ( 2. * srqt_trQ ); 01531 } 01532 01533 for( unsigned int jx=0; jx<_nx; jx++ ){ 01534 for( unsigned int ix=jx; ix<_nx; ix++ ){ 01535 _Qdot[_ndxLT(ix,jx)] = sumkappa * _Q[_ndxLT(ix,jx)]; 01536 for( unsigned int kx=0; kx<_nx; kx++ ) 01537 _Qdot[_ndxLT(ix,jx)] += _Q[_ndxLT(ix,kx)] * _A[jx+kx*_nx] 01538 + _A[ix+kx*_nx] * _Q[_ndxLT(kx,jx)]; 01539 } 01540 _Qdot[_ndxLT(jx,jx)] += Op<T>::diam( _Iddot[jx] ) / 2. * srqt_trQ; 01541 } 01542 01543 #ifdef MC__ODEBND_GSL_PM_DEBUG 01544 for( unsigned int ix=0; ix<_nx; ix++ ) 01545 std::cout << "PMxdot[" << ix << "] =" << _PMxdot[ix] << std::endl; 01546 for( unsigned int ix=0; ix<_nx; ix++ ) 01547 std::cout << "Iddot[" << ix << "] =" << _Iddot[ix] << std::endl; 01548 E ERxdot( _nx, _Qdot ); 01549 std::cout << "ERxdot =" << ERxdot << std::endl; 01550 { int dum; std::cin >> dum; } 01551 #endif 01552 01553 // Copy time derivatives in GSL array 01554 _PME2vec( _PMxdot, _Qdot, xdot ); 01555 01556 return GSL_SUCCESS; 01557 } 01558 } 01559 } 01560 01561 template <typename T, typename PMT, typename PVT> inline void 01562 ODEBND_GSL<T,PMT,PVT>::_PROP_PM_ELL0 01563 ( const double t ) 01564 { 01565 // Compute polynomial approximant and ellipsoidal remainder of RHS 01566 for( unsigned int ix=0; ix<_nx; ix++ ){ 01567 _IVAR[ix] = _PMx[ix].bound(); // set current state bounds 01568 ( _PMx[ix].center() ).set( T(0.) ); // cancel remainder term 01569 } 01570 _IVAR[_nx+_np] = t; // set current time 01571 01572 _pDAG->eval( _opRHS, _PMRHS, _nx, _pRHS, _PMxdot, _nVAR, _pVAR, _PMVAR ); 01573 _pDAG->eval( _opJAC, _IJAC, _nx*_nx, _pJAC, _Idfdx, _nVAR, _pVAR, _IVAR ); 01574 01575 for( unsigned int ix=0; ix<_nx; ix++ ){ 01576 for( unsigned int jx=0; jx<_nx; jx++ ) 01577 _A[ix+jx*_nx] = Op<T>::mid( _Idfdx[ix*_nx+jx] ); 01578 _Iddot[ix] = _PMxdot[ix].remainder(); 01579 for( unsigned int jx=0; jx<_nx; jx++ ) 01580 _Iddot[ix] += ( _Idfdx[ix*_nx+jx] - _A[ix+jx*_nx] ) * _Id[jx]; 01581 #ifdef MC__ODEBND_GSL_PM_DEBUG 01582 std::cout << "Iddot[" << ix << "] = " << _Iddot[ix] 01583 << " : " << Op<T>::mid(_Iddot[ix]) << std::endl; 01584 #endif 01585 } 01586 } 01587 01588 template <typename T, typename PMT, typename PVT> inline void 01589 ODEBND_GSL<T,PMT,PVT>::_PROP_PM_ELL1 01590 ( const double t ) 01591 { 01592 // Compute polynomial approximant and ellipsoidal remainder of RHS 01593 for( unsigned int jx=0; jx<_nx; jx++ ){ 01594 _MVXPd[jx].set( _MVXPenv, _np+jx, _Id[jx] ); 01595 _MVXPx[jx].set( _MVXPenv ).set( _PMx[jx].center().set( T(0.) ), true ); 01596 } 01597 _e2x( _MVXPd, _MVXPx, false ); 01598 #ifdef MC__ODEBND_GSL_PM_DEBUG 01599 for( unsigned int ix=0; ix<_nx; ix++ ) 01600 std::cout << "MVXPx[ " << ix << "] = " << _MVXPx[ix] << std::endl; 01601 //{ int dum; std::cin >> dum; } 01602 #endif 01603 _MVXPVAR[_nx+_np] = t; // set current time 01604 01605 _pDAG->eval( _opRHS, _PMRHS, _nx, _pRHS, _PMxdot, _nVAR, _pVAR, _PMVAR ); 01606 _pDAG->eval( _opJAC, _PMJAC, _nx*_nx, _pJAC, _MVXPdfdx, _nVAR, _pVAR, _MVXPVAR ); 01607 01608 for( unsigned int ix=0; ix<_nx; ix++ ){ 01609 #ifdef MC__ODEBND_GSL_PM_DEBUG 01610 for( unsigned int jx=0; jx<_nx; jx++ ) 01611 std::cout << "PMdfdx[" << ix << "," << jx << "] = " << _MVXPdfdx[ix*_nx+jx] << std::endl; 01612 #endif 01613 // Extract constant coefficients and set to 0 01614 for( unsigned int jx=0; jx<_nx; jx++ ) 01615 _A[ix+jx*_nx] = ( _MVXPdfdx[ix*_nx+jx].center() ).constant( true ); 01616 #ifdef MC__ODEBND_GSL_PM_DEBUG 01617 std::cout << "A[" << ix << ",#] = "; 01618 for( unsigned int jx=0; jx<_nx; jx++ ) 01619 std::cout << _A[ix+jx*_nx] << " "; 01620 std::cout << std::endl; 01621 for( unsigned int jx=0; jx<_nx; jx++ ) 01622 std::cout << "PMdfdx[" << ix << "," << jx << "] = " << _MVXPdfdx[ix*_nx+jx] << std::endl; 01623 #endif 01624 // Bound remaining terms 01625 _Iddot[ix] = _PMxdot[ix].remainder(); 01626 for( unsigned int jx=0; jx<_nx; jx++ ) 01627 _Iddot[ix] += _MVXPdfdx[ix*_nx+jx].bound() * _Id[jx]; 01628 #ifdef MC__ODEBND_GSL_PM_DEBUG 01629 std::cout << "Iddot[" << ix << "] = " << _Iddot[ix] 01630 << " : " << Op<T>::mid(_Iddot[ix]) << std::endl; 01631 #endif 01632 } 01633 } 01634 01635 template <typename T, typename PMT, typename PVT> inline void 01636 ODEBND_GSL<T,PMT,PVT>::_PROP_PM_ELL2 01637 ( const double t ) 01638 { 01639 // Compute polynomial approximant and ellipsoidal remainder of RHS 01640 for( unsigned int jx=0; jx<_nx; jx++ ){ 01641 _MVXPd[jx].set( _MVXPenv, _np+jx, _Id[jx] ); 01642 _MVXPx[jx].set( _MVXPenv ).set( _PMx[jx].center().set( T(0.) ), true ); 01643 } 01644 _e2x( _MVXPd, _MVXPx, false ); 01645 #ifdef MC__ODEBND_GSL_PM_DEBUG 01646 for( unsigned int ix=0; ix<_nx; ix++ ) 01647 std::cout << "MVXPx[ " << ix << "] = " << _MVXPx[ix] << std::endl; 01648 //{ int dum; std::cin >> dum; } 01649 #endif 01650 _MVXPVAR[_nx+_np] = t; // set current time 01651 01652 _pDAG->eval( _opRHS, _PMRHS, _nx, _pRHS, _MVXPf, _nVAR, _pVAR, _MVXPVAR ); 01653 01654 for( unsigned int ix=0; ix<_nx; ix++ ){ 01655 #ifdef MC__ODEBND_GSL_PM_DEBUG 01656 std::cout << "MVXPf[" << ix << "] = " << _MVXPf[ix] << std::endl; 01657 #endif 01658 // Extract polynomial model in P and set to 0 01659 _MVXPf[ix].get( _PMxdot[ix].set(_PMenv), true ); 01660 #ifdef MC__ODEBND_GSL_PM_DEBUG 01661 std::cout << "PMxdot[" << ix << "] =" << _PMxdot[ix] << std::endl; 01662 std::cout << "MVXPf[" << ix << "] = " << _MVXPf[ix] << std::endl; 01663 { int dum; std::cin >> dum; } 01664 #endif 01665 // Extract linear part in X and set to 0 01666 for( unsigned int jx=0; jx<_nx; jx++ ) 01667 _A[ix+jx*_nx] = _MVXPf[ix].linear( _np+jx, true ); 01668 #ifdef MC__ODEBND_GSL_PM_DEBUG 01669 std::cout << "A[" << ix << ",#] = "; 01670 for( unsigned int jx=0; jx<_nx; jx++ ) 01671 std::cout << _A[ix+jx*_nx] << " "; 01672 std::cout << std::endl; 01673 std::cout << "MVXPf[" << ix << "] = " << _MVXPf[ix] << std::endl; 01674 #endif 01675 // Bound remaining terms 01676 _Iddot[ix] = _MVXPf[ix].bound(); 01677 #ifdef MC__ODEBND_GSL_PM_DEBUG 01678 std::cout << "Iddot[" << ix << "] = " << _Iddot[ix] 01679 << " : " << Op<T>::mid(_Iddot[ix]) << std::endl; 01680 #endif 01681 } 01682 } 01683 /* 01684 template <typename T, typename PMT, typename PVT> inline void 01685 ODEBND_GSL<T,PMT,PVT>::_INV_PM_ELL0() 01686 { 01687 // Compute Taylor model polynomial part and ellipsoidal remainder of RHS 01688 E Exdot.set( _Qdot ); 01689 for( unsigned int ix=0; ix<_nx; ix++ ){ 01690 _PMVAR[ix] = _PMxdot[ix].set( T(0.) ); // polynomial model of state derivatives 01691 _Iddot[ix] = T( Exdot.l(ix), Exdot.u(ix) ); 01692 _IVAR[ix] = _PMxdot[ix].bound() + _Iddot[ix]; // bound of state derivatives 01693 } 01694 01695 _pDAG->eval( _opINV, _ni, _pINV, _PMinv, _nVAR, _pVAR, _PMVAR ); 01696 _pDAG->eval( _opDINV, _ni*_nx, _pDINV, _Idinvdx, _nVAR, _pVAR, _IVAR ); 01697 01698 for( unsigned int ii=0; ii<_ni; ii++ ){ 01699 _Rinv[ii] = _PMinv[ii].remainder(); 01700 for( unsigned int jx=0; jx<_nx; jx++ ){ 01701 _Ainv[ii+jx*_ni] = Op<T>::mid( _Idinvdx[ii*_nx+jx] ); 01702 _Rinv[ii] += ( _Idinvdx[ii*_nx+jx] - _Ainv[ii+jx*_ni] ) * _Iddot[jx]; 01703 } 01704 #ifdef MC__ODEBND_GSL_PM_DEBUG 01705 std::cout << "Rinv[" << ii << "] =" << _Rinv[ii] 01706 << " diam(Rinv[" << ii << "]) =" << Op<T>::diam(_Rinv[ii]) 01707 << " midp(Rinv[" << ii << "]) =" << Op<T>::mid(_Rinv[ii]) 01708 << std::endl; 01709 std::cout << "Ainv[" << ii << ",#] = "; 01710 for( unsigned int jx=0; jx<_nx; jx++ ) 01711 std::cout << _Ainv[ii+jx*_ni] << " "; 01712 std::cout << std::endl; 01713 #endif 01714 } 01715 } 01716 */ 01717 template <typename T, typename PMT, typename PVT> inline int 01718 ODEBND_GSL<T,PMT,PVT>::MC_GSLJACPM__ 01719 ( double t, const double* x, double* jac, double* xdot, void* user_data ) 01720 { 01721 ODEBND_GSL<T,PMT,PVT> *pODEBND_GSL = ODEBND_GSL<T,PMT,PVT>::pODEBND_GSL; 01722 int flag = pODEBND_GSL->_ODEBND_GSL_JACPM( t, x, jac, xdot, user_data ); 01723 ODEBND_GSL<T,PMT,PVT>::pODEBND_GSL = pODEBND_GSL; 01724 return flag; 01725 } 01726 01727 template <typename T, typename PMT, typename PVT> inline int 01728 ODEBND_GSL<T,PMT,PVT>::_ODEBND_GSL_JACPM 01729 ( double t, const double* x, double* jac, double* xdot, void* user_data ) 01730 { 01731 stats_traj.numJAC++; 01732 return GSL_EBADFUNC; 01733 } 01734 01735 template <typename T, typename PMT, typename PVT> inline bool 01736 ODEBND_GSL<T,PMT,PVT>::_GSL_init 01737 ( const PVT* PMp ) 01738 { 01739 // Check polynomial model compatibility and size 01740 unsigned int kp=_np; 01741 for( unsigned int ip=0; ip<_np && kp==_np; ip++ ) 01742 if( PMp[ip].env() ) kp = ip; 01743 if( kp==_np || PMp[kp].env()->nvar()!=_np ) return false; 01744 _PMenv = PMp[kp].env(); 01745 01746 // Define ODE system in GSL format 01747 _sys_dineqPM.function = MC_GSLRHSPM__; 01748 _sys_dineqPM.jacobian = MC_GSLJACPM__; 01749 _sys_dineqPM.params = 0; 01750 _sys_dineqPM.dimension = _PMenv->nmon()*_nx; 01751 switch( options.WRAPMIT){ 01752 case Options::NONE: 01753 case Options::DINEQ: 01754 _sys_dineqPM.dimension += 2*_nx; 01755 break; 01756 case Options::ELLIPS: 01757 default: 01758 _sys_dineqPM.dimension += _nx*(_nx+1)/2; 01759 break; 01760 } 01761 _GSL_init( _sys_dineqPM, _driver_dineqPM ); 01762 01763 // Size and set DAG evaluation arrays 01764 _nVAR = _nx+_np+1; 01765 delete[] _pVAR; _pVAR = new FFVar[_nVAR]; 01766 delete[] _IVAR; _IVAR = new T[_nVAR]; 01767 delete[] _PMVAR; _PMVAR = new PVT[_nVAR]; 01768 for( unsigned ix=0; ix<_nx; ix++ ) _pVAR[ix] = _pX[ix]; 01769 for( unsigned ip=0; ip<_np; ip++ ) _pVAR[_nx+ip] = _pP[ip]; 01770 _pVAR[_nx+_np] = (_pT? *_pT: 0. ); 01771 for( unsigned ip=0; ip<_np; ip++ ) _IVAR[_nx+ip] = PMp[ip].bound(); 01772 _Ix = _Ip = 0; // not used 01773 for( unsigned ip=0; ip<_np; ip++ ) _PMVAR[_nx+ip] = PMp[ip]; 01774 _PMx = _PMVAR; 01775 _PMp = _PMVAR + _nx; 01776 01777 // Reset _MVXPVenv and related variables 01778 unsigned int MVXPsize = ( options.ORDMIT<_PMenv->nord()? options.ORDMIT: _PMenv->nord() ); 01779 if( _MVXPenv && ( _MVXPenv->nord() != MVXPsize || _MVXPenv->nvar() != _nx+_np ) ){ 01780 delete[] _MVXPf; _MVXPf = 0; 01781 delete[] _MVXPdfdx; _MVXPdfdx = 0; 01782 delete[] _MVXPd; _MVXPd = 0; 01783 delete[] _MVXPVAR; _MVXPVAR = _MVXPx = _MVXPp = 0; 01784 delete _MVXPenv; _MVXPenv = 0; 01785 } 01786 01787 // Size state/parameter arrays 01788 if( !_PMx ) _PMx = new PVT[_nx]; 01789 if( !_PMxdot ) _PMxdot = new PVT[_nx]; 01790 01791 switch( options.WRAPMIT){ 01792 case Options::NONE: 01793 break; 01794 01795 case Options::DINEQ: 01796 if( !_RxLdot ) _RxLdot = new double[_nx]; 01797 if( !_RxUdot ) _RxUdot = new double[_nx]; 01798 break; 01799 01800 case Options::ELLIPS: 01801 if( !_pref ) _pref = new double[_np]; 01802 if( !_xref ) _xref = new double[_nx]; 01803 if( !_A ) _A = new double[_nx*_nx]; 01804 if( !_Q ) _Q = new double[_nx*(_nx+1)/2]; 01805 if( !_Id ) _Id = new T[_nx]; 01806 if( !_Qdot ) _Qdot = new double[_nx*(_nx+1)/2]; 01807 if( !_Iddot ) _Iddot = new T[_nx]; 01808 if( !_Idfdx ) _Idfdx = new T[_nx*_nx]; 01809 if( !_MVXPenv ) _MVXPenv = new PMT( _nx+_np, MVXPsize ); 01810 _MVXPenv->options = _PMenv->options; 01811 if( !_MVXPd ) _MVXPd = new PVT[_nx]; 01812 if( !_MVXPf ) _MVXPf = new PVT[_nx]; 01813 if( !_MVXPdfdx ) _MVXPdfdx = new PVT[_nx*_nx]; 01814 if( !_MVXPVAR ) _MVXPVAR = new PVT[_nVAR]; 01815 _MVXPx = _MVXPVAR; 01816 _MVXPp = _MVXPVAR + _nx; 01817 for( unsigned int ip=0; ip<_np; ip++ ) 01818 _MVXPp[ip].set( _MVXPenv, ip, _PMp[ip].B() ); 01819 break; 01820 } 01821 01822 // Reset result record and statistics 01823 _results.clear(); 01824 _init_stats( stats_traj ); 01825 01826 return true; 01827 } 01828 01829 template <typename T, typename PMT, typename PVT> inline bool 01830 ODEBND_GSL<T,PMT,PVT>::_set_RHS_dineqPM 01831 ( const unsigned int iRHS ) 01832 { 01833 if( _vRHS.size() <= iRHS ) return false; 01834 01835 _pRHS = _vRHS.at( iRHS ); 01836 _opRHS = _pDAG->subgraph( _nx, _pRHS ); 01837 01838 delete[] _IRHS; _IRHS = 0; 01839 delete[] _PMRHS; _PMRHS = 0; 01840 delete[] _opRHSi; _opRHSi = 0; 01841 delete[] _IJAC; _IJAC = 0; 01842 delete[] _PMJAC; _PMJAC = 0; 01843 delete[] _pJAC; _pJAC = 0; _opJAC.clear(); 01844 switch( options.WRAPMIT){ 01845 case Options::NONE: 01846 _PMRHS = new PVT[ _opRHS.size() ]; break; 01847 case Options::DINEQ: 01848 _opRHSi = new std::list<const FFOp*>[_nx]; 01849 for( unsigned ix=0; ix<_nx; ix++ ) 01850 _opRHSi[ix] = _pDAG->subgraph( 1, _pRHS+ix ); 01851 _PMRHS = new PVT[ _opRHS.size() ]; break; 01852 case Options::ELLIPS: default: 01853 _PMRHS = new PVT[ _opRHS.size() ]; 01854 _pJAC = _pDAG->FAD( _nx, _pRHS, _nx, _pVAR ); 01855 _opJAC = _pDAG->subgraph( _nx*_nx, _pJAC ); 01856 if( !options.ORDMIT ) 01857 _IJAC = new T[ _opJAC.size() ]; 01858 else if( _PMenv->nord() > _MVXPenv->nord() ) 01859 _PMJAC = new PVT[ _opJAC.size() ]; 01860 break; 01861 } 01862 01863 return true; 01864 } 01865 01880 template <typename T, typename PMT, typename PVT> 01881 inline typename ODEBND_GSL<T,PMT,PVT>::STATUS 01882 ODEBND_GSL<T,PMT,PVT>::bounds 01883 ( const unsigned int ns, const double*tk, const PVT*PMp, PVT**PMxk, E*Exk, 01884 std::ostream&os ) 01885 { 01886 // Initialize trajectory integration with GSL 01887 if( !_GSL_init( PMp ) ) return FATAL; 01888 01889 try{ 01890 // Bounds on initial conditions 01891 if( !_vIC.size() ) 01892 { _GSL_term(); return FATAL; } 01893 _pIC = _vIC.at(0); 01894 _opIC = _pDAG->subgraph( _nx, _pIC ); 01895 _init( PMxk[0] ); 01896 if( Exk && options.WRAPMIT == Options::ELLIPS ) Exk[0] = _Ed; 01897 else if( Exk ) Exk[0].reset(); 01898 if( options.DISPLAY >= 1 ) 01899 switch( options.WRAPMIT ){ 01900 case Options::NONE: 01901 case Options::DINEQ: 01902 _print_interm( tk[0], PMxk[0], "x", os ); break; 01903 case Options::ELLIPS: 01904 _print_interm( tk[0], PMxk[0], _Ed, "x", os ); break; 01905 } 01906 // Record initial results 01907 if( options.RESRECORD ) 01908 _results.push_back( Results( tk[0], _nx, PMxk[0] ) ); 01909 01910 // Integrate ODEs through each stage using GSL 01911 _t = tk[0]; 01912 _h = options.H0; 01913 pODEBND_GSL = this; 01914 01915 for( _istg=0; _istg<ns; _istg++ ){ 01916 if( _istg && _vIC.size()>1 ) throw Exceptions( Exceptions::REINIT ); 01917 01918 // update list of operations in RHS and JAC 01919 const unsigned int iRHS = ( _vRHS.size()<2? 0: _istg ); 01920 if( (!_istg || iRHS) && !_set_RHS_dineqPM( iRHS ) ) 01921 { _GSL_term(); return FATAL; } 01922 01923 while( _t < tk[_istg+1] ){ 01924 if( gsl_odeiv2_evolve_apply( _driver_dineqPM->e, _driver_dineqPM->c, _driver_dineqPM->s, 01925 &_sys_dineqPM, &_t, tk[_istg+1], &_h, _vec_state ) != GSL_SUCCESS 01926 || _h < options.HMIN 01927 || (options.NMAX && stats_traj.numSteps > options.NMAX) ) 01928 throw Exceptions( Exceptions::UNDEF ); 01929 stats_traj.numSteps++; 01930 if( options.HMAX > 0 && _h > options.HMAX ) _h = options.HMAX; 01931 } 01932 01933 switch( options.WRAPMIT){ 01934 case Options::NONE: 01935 case Options::DINEQ: 01936 _vec2PMI( _vec_state, PMxk[_istg+1] ); break; 01937 if( Exk ) Exk[_istg+1].reset(); 01938 case Options::ELLIPS: 01939 default: 01940 _vec2PME( _vec_state, PMxk[_istg+1] ); break; 01941 if( Exk ) Exk[_istg+1] = _Ed; 01942 } 01943 if( options.DISPLAY >= 1 ) 01944 switch( options.WRAPMIT ){ 01945 case Options::NONE: 01946 case Options::DINEQ: 01947 _print_interm( tk[_istg+1], PMxk[_istg+1], "x", os ); break; 01948 case Options::ELLIPS: 01949 _print_interm( tk[_istg+1], PMxk[_istg+1], _Ed, "x", os ); break; 01950 } 01951 // Record intermediate results 01952 if( options.RESRECORD ) 01953 _results.push_back( Results( tk[_istg+1], _nx, PMxk[_istg+1] ) ); 01954 } 01955 } 01956 catch(...){ 01957 _GSL_term(); 01958 if( options.DISPLAY >= 1 ) _print_stats( stats_traj, os ); 01959 return FAILURE; 01960 } 01961 01962 _GSL_term(); 01963 if( options.DISPLAY >= 1 ) _print_stats( stats_traj, os ); 01964 return NORMAL; 01965 } 01966 01967 template <typename T, typename PMT, typename PVT> inline typename ODEBND_GSL<T,PMT,PVT>::STATUS 01968 ODEBND_GSL<T,PMT,PVT>::_remainders 01969 ( const unsigned int ns, const double*tk, const T*Ip, const PVT*const*PMxk, 01970 T**Rxk, const unsigned int nsamp, std::ostream&os ) 01971 { 01972 STATUS flag = NORMAL; 01973 01974 // Initialization of sampled bounds at parameter lower bound 01975 double *p = new double[_np]; 01976 for( unsigned int ip=0; ip<_np; ip++ ) 01977 p[ip] = Op<T>::l(Ip[ip]); 01978 double **xk = new double*[ns+1]; 01979 for( unsigned int is=0; is<=ns; is++ ) 01980 xk[is] = new double[_nx]; 01981 flag = _ODESLV_GSL->states( ns, tk, p, xk, 0, os ); 01982 if( flag != NORMAL || nsamp <= 1 ){ 01983 delete[] p; 01984 for( unsigned int is=0; is<=ns; is++ ) delete[] xk[is]; delete[] xk; 01985 return flag; 01986 } 01987 for( unsigned int is=0; is<=ns; is++ ) 01988 for( unsigned int ix=0; ix<_nx; ix++ ) 01989 Rxk[is][ix] = xk[is][ix] - PMxk[is][ix].polynomial( p ); 01990 01991 // Start sampling process 01992 unsigned int* vsamp = new unsigned int[_np]; 01993 flag = _remainders( ns, tk, Ip, PMxk, Rxk, nsamp, vsamp, 0, p, xk, os ); 01994 01995 // Clean-up 01996 delete[] p; 01997 for( unsigned int is=0; is<=ns; is++ ) delete[] xk[is]; delete[] xk; 01998 delete[] vsamp; 01999 02000 return flag; 02001 } 02002 02003 template <typename T, typename PMT, typename PVT> inline typename ODEBND_GSL<T,PMT,PVT>::STATUS 02004 ODEBND_GSL<T,PMT,PVT>::_remainders 02005 ( const unsigned int ns, const double*tk, const T*Ip, const PVT*const*PMxk, 02006 T**Rxk, const unsigned int nsamp, unsigned int* vsamp, const unsigned int ip, 02007 double*p, double**xk, std::ostream&os ) 02008 { 02009 STATUS flag = NORMAL; 02010 02011 // Update bounds for all sampling points 02012 for( unsigned int isamp=0; isamp<nsamp; isamp++ ){ 02013 vsamp[ip] = isamp; 02014 02015 // Continue recursive call 02016 if( ip+1 < _np ){ 02017 flag = _remainders( ns, tk, Ip, PMxk, Rxk, nsamp, vsamp, ip+1, p, xk, os ); 02018 if( flag != NORMAL ) return flag; 02019 continue; 02020 } 02021 02022 // Update bounds for current point 02023 #ifdef MC__ODEBND_GSL_SAMPLE_DEBUG 02024 std::cout << "Sample: "; 02025 #endif 02026 for( unsigned int ip=0; ip<_np; ip++ ){ 02027 p[ip] = Op<T>::l( Ip[ip] ) + vsamp[ip]/(nsamp-1.) * Op<T>::diam( Ip[ip] ); 02028 #ifdef MC__ODEBND_GSL_SAMPLE_DEBUG 02029 std::cout << p[ip] << " "; 02030 #endif 02031 } 02032 #ifdef MC__ODEBND_GSL_SAMPLE_DEBUG 02033 std::cout << std::endl; 02034 #endif 02035 flag = _ODESLV_GSL->states( ns, tk, p, xk, 0, os ); 02036 if( flag != NORMAL ) return flag; 02037 for( unsigned int is=0; is<=ns; is++ ) 02038 for( unsigned int ix=0; ix<_nx; ix++ ) 02039 Rxk[is][ix] = Op<T>::hull( xk[is][ix]-PMxk[is][ix].polynomial(p), 02040 Rxk[is][ix] ); 02041 } 02042 02043 return flag; 02044 } 02045 02062 02063 template <typename T, typename PMT, typename PVT> inline typename ODEBND_GSL<T,PMT,PVT>::STATUS 02064 ODEBND_GSL<T,PMT,PVT>::hausdorff 02065 ( const unsigned int ns, const double*tk, const PVT*PMp, double**Hxk, 02066 const unsigned int nsamp, std::ostream&os ) 02067 { 02068 int DISPLAY_ODEBND = options.DISPLAY; 02069 int DISPLAY_ODESLV = options.ODESLVOPT.DISPLAY; 02070 options.DISPLAY = 0; 02071 options.ODESLVOPT.DISPLAY = 0; 02072 _ODESLV_GSL->set( *this ); // in base class BASE_ODE 02073 _ODESLV_GSL->options = options.ODESLVOPT; 02074 _ODESLV_GSL->options.RESRECORD = false; 02075 02076 // Compute approximate bounds 02077 PVT** PMxk = new PVT*[ns+1]; 02078 for( unsigned int is=0; is<ns+1; is++ ) PMxk[is] = new PVT[_nx]; 02079 try{ bounds( ns, tk, PMp, PMxk, 0, os ); } 02080 catch(...){;} 02081 unsigned int nsf = _istg; 02082 for( unsigned int is=nsf; is<ns; is++ ) 02083 for( unsigned int ix=0; ix<_nx; ix++ ) 02084 PMxk[is+1][ix] = T( -1e20, 1e20 ); 02085 02086 // Compute remainder bounds 02087 T* Ip = new T[_np]; 02088 for( unsigned int ip=0; ip<_np; ip++ ) Ip[ip] = PMp[ip].B(); 02089 T** Rxk = new T*[ns+1]; 02090 for( unsigned int is=0; is<ns+1; is++ ) Rxk[is] = new T[_nx]; 02091 _remainders( nsf, tk, Ip, PMxk, Rxk, nsamp, os ); 02092 for( unsigned int is=nsf; is<ns; is++ ) 02093 for( unsigned int ix=0; ix<_nx; ix++ ) 02094 Rxk[is+1][ix] = T( 0. ); 02095 02096 // Compute Hausdorff metric at each time step 02097 struct loc{ static double hausdorff 02098 ( const T&Ix, const T&Ix0 ) 02099 { return std::max( std::fabs(Op<T>::l(Ix)-Op<T>::l(Ix0)), 02100 std::fabs(Op<T>::u(Ix)-Op<T>::u(Ix0)) ); } 02101 }; 02102 02103 options.DISPLAY = DISPLAY_ODEBND; 02104 options.ODESLVOPT.DISPLAY = DISPLAY_ODESLV; 02105 for( unsigned int is=0; is<ns+1; is++ ){ 02106 for( unsigned int ix=0; ix<_nx; ix++ ) 02107 Hxk[is][ix] = loc::hausdorff( PMxk[is][ix].R(), Rxk[is][ix] ); 02108 if( options.DISPLAY >= 1 ){ 02109 _print_interm( tk[is], Hxk[is], "dH", os ); 02110 } 02111 } 02112 02113 for( unsigned int is=0; is<ns+1; is++ ) delete[] Rxk[is]; 02114 delete[] Rxk; 02115 for( unsigned int is=0; is<ns+1; is++ ) delete[] PMxk[is]; 02116 delete[] PMxk; 02117 delete[] Ip; 02118 02119 return NORMAL; 02120 } 02121 02122 template <typename T, typename PMT, typename PVT> 02123 template <typename U> inline void 02124 ODEBND_GSL<T,PMT,PVT>::_print_interm 02125 ( const double t, const U*x, const std::string&var, std::ostream&os ) const 02126 { 02127 os << " @t = " << std::scientific << std::setprecision(4) 02128 << std::left << t << " :" << std::endl; 02129 for( unsigned int ix=0; ix<_nx; ix++ ) 02130 os << " " << var.c_str() << "[" << ix << "] = " << x[ix] << std::endl; 02131 return; 02132 } 02133 02134 template <typename T, typename PMT, typename PVT> 02135 template <typename U, typename V> inline void 02136 ODEBND_GSL<T,PMT,PVT>::_print_interm 02137 ( const double t, const U*x, const V&r, const std::string&var, std::ostream&os ) const 02138 { 02139 os << " @t = " << std::scientific << std::setprecision(4) 02140 << std::left << t << " :" << std::endl; 02141 for( unsigned int ix=0; ix<_nx; ix++ ) 02142 os << " " << var.c_str() << "[" << ix << "] = " << x[ix] << std::endl; 02143 os << " " << "R" << var.c_str() << " =" << r << std::endl; 02144 return; 02145 } 02146 02147 template <typename T, typename PMT, typename PVT> inline void 02148 ODEBND_GSL<T,PMT,PVT>::record 02149 ( std::ofstream&bndrec, const unsigned int iprec ) const 02150 { 02151 if( !bndrec ) return; 02152 02153 // Specify format 02154 bndrec << std::right << std::scientific << std::setprecision(iprec); 02155 02156 // Record computed interval bounds at stage times 02157 typename std::vector< Results >::const_iterator it = _results.begin(); 02158 for( ; it != _results.end(); ++it ){ 02159 bndrec << std::setw(iprec+9) << (*it).t; 02160 for( unsigned int ix=0; ix<_nx; ix++ ) 02161 bndrec << std::setw(iprec+9) << mc::Op<T>::l( (*it).X[ix] ) 02162 << std::setw(iprec+9) << mc::Op<T>::u( (*it).X[ix] ); 02163 bndrec << std::endl; 02164 } 02165 } 02166 02167 } // end namescape mc 02168 02169 #endif 02170