ODEBND
odebnd_gsl.hpp
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