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_VAL_HPP 00006 #define MC__ODEBND_VAL_HPP 00007 00008 #undef MC__ODEBND_VAL_DEBUG 00009 #undef MC__ODEBND_VAL_DEBUG_INVARIANT 00010 #undef MC__ODEBND_VAL_STEPSIZE_HSTAB 00011 00012 #include <stdexcept> 00013 #include <cassert> 00014 #include <cmath> 00015 #include <fstream> 00016 #include <vector> 00017 #include <sys/time.h> 00018 00019 #include "ellipsoid.hpp" 00020 #include "tmodel.hpp" 00021 #include "cmodel.hpp" 00022 00023 #include "odeslv_gsl.hpp" 00024 00025 namespace mc 00026 { 00038 template <typename T, typename PMT=mc::TModel<T>, typename PVT=mc::TVar<T> > 00039 class ODEBND_VAL: public BASE_ODE 00040 { 00041 private: 00042 00043 typedef Ellipsoid E; 00044 00046 unsigned int _nVAR; 00047 00049 FFVar* _pVAR; 00050 00052 T *_IVAR; 00053 00055 PMT *_PMenv; 00056 00058 PVT *_PMVAR; 00059 00061 PMT *_MVenv; 00062 00064 PVT *_MVVAR; 00065 00066 00068 T *_Ix; 00069 00071 PVT *_PMx; 00072 00074 E _Ex; 00075 00077 E _Ex_TE; 00078 00080 T *_Rx; 00081 00083 T *_Rx_TE; 00084 00086 CPPL::dgematrix _Ax; 00087 00089 T *_Rinv; 00090 00092 T *_Ninv; 00093 00095 CPPL::dgematrix _Ainv; 00096 00097 00099 T* _IDAG; 00100 00102 PVT* _PMDAG; 00103 00104 00106 std::list<const FFOp*> _opTRHS; 00107 00109 const FFVar* _pTRHS; 00110 00112 PVT *_PMTRHS; 00113 00114 00116 std::list<const FFOp*> _opFTRHS; 00117 00119 const FFVar* _pFTRHS; 00120 00122 T *_IFTRHS; 00123 00125 PVT *_PMFTRHS; 00126 00127 00129 std::list<const FFOp*> _opTRHSval; 00130 00132 T *_ITRHSval; 00133 00135 PVT *_PMTRHSval; 00136 00137 00139 std::list<const FFOp*> _opIC; 00140 00142 const FFVar* _pIC; 00143 00144 00146 std::list<const FFOp*> _opINV; 00147 00149 const FFVar* _pINV; 00150 00152 PVT *_PMINV; 00153 00154 00156 std::list<const FFOp*> _opFINV; 00157 00159 const FFVar* _pFINV; 00160 00162 T *_IFINV; 00163 00165 PVT *_PMFINV; 00166 00167 00169 double _h; 00170 00172 double _hmax; 00173 00175 double _tmax; 00176 00178 double _tval; 00179 00181 ODESLV_GSL<T>* _ODESLV_GSL; 00182 00183 public: 00187 00188 ODEBND_VAL(); 00189 00191 virtual ~ODEBND_VAL(); 00192 00194 struct Results 00195 { 00197 Results 00198 ( const double tk, const unsigned int nxk, const T*Ixk ): 00199 t( tk ), nx( nxk ) 00200 { X = new T[nx]; 00201 for( unsigned int ix=0; ix<nx; ix++ ) X[ix] = Ixk[ix]; } 00202 Results 00203 ( const double tk, const unsigned int nxk, const PVT*PMxk ): 00204 t( tk ), nx( nxk ) 00205 { X = new T[nx]; 00206 for( unsigned int ix=0; ix<nx; ix++ ) X[ix] = PMxk[ix].B(); } 00207 Results 00208 ( const Results&res ): 00209 t( res.t ), nx( res.nx ) 00210 { X = new T[nx]; 00211 for( unsigned int ix=0; ix<nx; ix++ ) X[ix] = res.X[ix]; } 00213 ~Results() 00214 { delete[] X; } 00216 double t; 00218 unsigned int nx; 00220 T* X; 00221 }; 00222 00224 struct Options: 00225 { 00227 Options(): 00228 TSORDER(7), WRAPMIT(ELLIPS), ORDMIT(1), DMAX(1e20), HMIN(1e-8), HMAX(1e8), 00229 HREDUC(0.8), HSTAB(true), TOL(1e-7), SCALING(true), ATOL(1e-10), 00230 QTOL(machprec()), TSTOP(true), PMVALID(false), USEINV(true), 00231 ODESLVOPT(typename ODESLV_GSL<T>::Options()), DISPLAY(1), RESRECORD(false) 00232 {} 00234 enum WRAPPING_STRATEGY{ 00235 NONE=0, 00236 ELLIPS 00237 }; 00239 unsigned int TSORDER; 00241 WRAPPING_STRATEGY WRAPMIT; 00243 unsigned int ORDMIT; 00245 double DMAX; 00247 double HMIN; 00249 double HMAX; 00251 double HREDUC; 00253 double HSTAB; 00255 double TOL; 00257 bool SCALING; 00259 double ATOL; 00261 double QTOL; 00263 bool TSTOP; 00265 bool PMVALID; 00267 bool USEINV; 00269 typename ODESLV_GSL<T>::Options ODESLVOPT; 00271 int DISPLAY; 00273 bool RESRECORD; 00274 } options; 00275 00277 struct Stats 00278 { 00280 Stats(): 00281 cputime(0.), numSteps(0), numTRHS_I(0), numFTRHS_I(0), numTRHS_PM(0), numFTRHS_PM(0) 00282 {} 00284 void reset() 00285 { cputime = 0.; 00286 numSteps = numTRHS_I = numFTRHS_I = numTRHS_PM = numFTRHS_PM = 0; } 00287 00289 double cputime; 00291 unsigned long numSteps; 00293 unsigned long numTRHS_I; 00295 unsigned long numFTRHS_I; 00297 unsigned long numTRHS_PM; 00299 unsigned long numFTRHS_PM; 00300 }; 00301 00303 Stats stats_traj; 00304 00306 class Exceptions 00307 { 00308 public: 00310 enum TYPE{ 00311 REINIT=1, 00312 HREDUC, 00313 UNDEF=-33 00314 }; 00316 Exceptions( TYPE ierr ) : _ierr( ierr ){} 00318 int ierr(){ return _ierr; } 00320 std::string what(){ 00321 switch( _ierr ){ 00322 case REINIT: 00323 return "ODEBND_VAL::Exceptions State reinitialization at intermediate stage not allowed"; 00324 case HREDUC: 00325 return "ODEBND_VAL::Exceptions Invalid stepsize reduction parameter"; 00326 case UNDEF: default: 00327 return "ODEBND_VAL::Exceptions Calling a feature not yet implemented"; 00328 } 00329 } 00330 private: 00331 TYPE _ierr; 00332 }; 00333 00335 STATUS bounds 00336 ( const unsigned int ns, const double*tk, const PVT*PMp, PVT**PMxk, 00337 E*ERxk=0, std::ostream&os=std::cout ); 00338 00340 STATUS hausdorff 00341 ( const unsigned int ns, const double*tk, const PVT*PMp, double**Hxk, 00342 const unsigned int nsamp, std::ostream&os=std::cout ); 00343 00345 void record 00346 ( std::ofstream&bndrec, const unsigned int iprec=5 ) const; 00347 00349 double final_time() const 00350 { return _t; }; 00353 private: 00355 static void _init_stats 00356 ( Stats&stats ); 00357 00359 static void _final_stats 00360 ( Stats&stats ); 00361 00363 static void _print_stats 00364 ( const Stats&stats, std::ostream&os=std::cout ); 00365 00367 std::vector< Results > _results; 00368 00370 template <typename U> double _scale 00371 ( U&R, const T&X ) const; 00372 00374 template <typename U> double _smaxnorm 00375 ( U*R, const T*X ) const; 00376 00378 template <typename U> double _snorm 00379 ( U*R, const T*X ) const; 00380 00382 template <typename U> double _diam 00383 ( U*X ) const; 00384 00386 template <typename U> double _stepsize 00387 ( const unsigned q, U*UTRHS, const T*X, const bool hdep ) const; 00388 00390 double _validation 00391 ( const unsigned q, PVT*PMTRHS, const T*X ); 00392 00394 template <typename U, typename V> static U _predictor 00395 ( const V&h, const unsigned q, const unsigned n, const U*U_TE, 00396 const unsigned i ); 00397 00399 template <typename U, typename V> static U _predictor 00400 ( const V&h, const unsigned q, const unsigned n, const U*U_FTE, 00401 const unsigned i, const unsigned j ); 00402 00404 bool _prepare 00405 ( const PVT*PMp ); 00406 00408 bool _init 00409 ( const unsigned k, const double tk, PVT*PMxk, E*Exk ); 00410 00412 bool _resize 00413 ( const unsigned q, const unsigned int iRHS ); 00414 00416 STATUS _propagate 00417 ( const double tnext, std::ostream&os ); 00418 00420 STATUS _propagate_INT 00421 ( const double tnext, std::ostream&os ); 00422 00424 STATUS _propagate_ELL 00425 ( const double tnext, std::ostream&os ); 00426 00428 STATUS _propagate_ELL0 00429 ( const unsigned q, const double tnext, std::ostream&os ); 00430 00432 STATUS _propagate_ELL1 00433 ( const unsigned q, const double tnext, std::ostream&os ); 00434 00436 STATUS _propagate_ELL2 00437 ( const unsigned q, const double tnext, std::ostream&os ); 00438 00440 STATUS _invariant_ELL 00441 ( std::ostream&os ); 00442 00444 STATUS _invariant_ELL0 00445 ( const PVT*Px, const T*Rx, std::ostream&os ); 00446 00448 STATUS _invariant_ELL1 00449 ( const PVT*Px, const T*Rx, std::ostream&os ); 00450 00452 STATUS _invariant_ELL2 00453 ( const PVT*Px, const T*Rx, std::ostream&os ); 00454 00456 STATUS _update_ELL 00457 ( std::ostream&os ); 00458 00460 STATUS _remainders 00461 ( const unsigned int ns, const double*tk, const T*Ip, const PVT*const*PMxk, 00462 T**Rxk, const unsigned int nsamp, std::ostream&os=std::cout ); 00463 00465 STATUS _remainders 00466 ( const unsigned int ns, const double*tk, const T*Ip, const PVT*const*PMxk, 00467 T**Rxk, const unsigned int nsamp, unsigned int* vsamp, 00468 const unsigned int ip, double*p, double**xk, std::ostream&os ); 00469 00471 template<typename U> void _print_interm 00472 ( const double t, const U*x, const std::string&var, std::ostream&os=std::cout ) const; 00473 00475 template<typename U, typename V> void _print_interm 00476 ( const double t, const U*x, const V&r, const std::string&var, std::ostream&os=std::cout ) const; 00477 00479 static double _factorial 00480 ( const unsigned int n ) 00481 { 00482 return( n==1? 1: n*_factorial(n-1) ); 00483 } 00484 00486 ODEBND_VAL(const ODEBND_VAL&); 00487 ODEBND_VAL& operator=(const ODEBND_VAL&); 00488 }; 00489 00490 template <typename T, typename PMT, typename PVT> 00491 inline 00492 ODEBND_VAL<T,PMT,PVT>::ODEBND_VAL 00493 () : BASE_ODE() 00494 { 00495 // Initalize DAG computation 00496 _nVAR = 0; 00497 _pVAR = 0; 00498 _PMVAR = _MVVAR = _PMDAG = 0; 00499 _IVAR = _IDAG = 0; 00500 00501 // Initalize dynamic system computation 00502 _pTRHS = _pFTRHS = _pIC = _pINV = _pFINV = 0; 00503 _PMenv = _MVenv = 0; 00504 _Ix = _Rx = _Rx_TE = _Rinv = _Ninv = 0; 00505 _PMx = 0; 00506 _IFTRHS = _ITRHSval = _IFINV = 0; 00507 _PMTRHS = _PMFTRHS = _PMTRHSval = _PMINV = _PMFINV = 0; 00508 00509 // Initialize ellipsoidal calculus 00510 #ifdef MC__ODEBND_VAL_DEBUG 00511 E::options.PSDCHK = true; 00512 #else 00513 E::options.PSDCHK = false; 00514 #endif 00515 00516 // Initalize GSL 00517 _ODESLV_GSL = new ODESLV_GSL<T>(); 00518 } 00519 00520 template <typename T, typename PMT, typename PVT> 00521 inline 00522 ODEBND_VAL<T,PMT,PVT>::~ODEBND_VAL 00523 () 00524 { 00525 delete[] _pVAR; 00526 delete[] _IVAR; 00527 delete[] _PMVAR; 00528 delete[] _MVVAR; 00529 delete[] _IDAG; 00530 delete[] _PMDAG; 00531 00532 // Do *NOT* free _PMenv 00533 delete _MVenv; 00534 delete[] _PMx; 00535 delete[] _Ix; 00536 delete[] _Rx; 00537 delete[] _Rx_TE; 00538 delete[] _Rinv; 00539 delete[] _Ninv; 00540 00541 delete[] _pTRHS; 00542 delete[] _PMTRHS; 00543 delete[] _pFTRHS; 00544 delete[] _PMFTRHS; 00545 delete[] _IFTRHS; 00546 delete[] _PMTRHSval; 00547 delete[] _ITRHSval; 00548 // Do *NOT* free _pIC; 00549 // Do *NOT* free _pINV; 00550 delete[] _PMINV; 00551 delete[] _pFINV; 00552 delete[] _PMFINV; 00553 delete[] _IFINV; 00554 00555 delete _ODESLV_GSL; 00556 } 00557 00558 template <typename T, typename PMT, typename PVT> 00559 template <typename U> inline double 00560 ODEBND_VAL<T,PMT,PVT>::_scale 00561 ( U&R, const T&X ) const 00562 { 00563 return( options.SCALING? 00564 Op<U>::abs(R)/(2.*options.TOL*Op<T>::abs(X)+options.ATOL): 00565 Op<U>::abs(R)/options.TOL ); 00566 } 00567 00568 template <typename T, typename PMT, typename PVT> 00569 template <typename U> inline double 00570 ODEBND_VAL<T,PMT,PVT>::_smaxnorm 00571 ( U*R, const T*X ) const 00572 { 00573 double maxnorm = 0.; 00574 for( unsigned int ix=0; ix<_nx; ix++ ) 00575 maxnorm = std::max( maxnorm, _scale(R[ix],X[ix]) ); 00576 return maxnorm; 00577 } 00578 00579 template <typename T, typename PMT, typename PVT> 00580 template <typename U> inline double 00581 ODEBND_VAL<T,PMT,PVT>::_snorm 00582 ( U*R, const T*X ) const 00583 { 00584 double snorm = 0.; 00585 for( unsigned int ix=0; ix<_nx; ix++ ) 00586 snorm += _scale(R[ix],X[ix]); 00587 return snorm/(double)_nx; 00588 } 00589 00590 template <typename T, typename PMT, typename PVT> 00591 template <typename U> inline double 00592 ODEBND_VAL<T,PMT,PVT>::_diam 00593 ( U*X ) const 00594 { 00595 double diam = 0.; 00596 for( unsigned int ix=0; ix<_nx; ix++ ) 00597 diam = std::max( diam, Op<U>::diam(X[ix]) ); 00598 return diam; 00599 } 00600 00601 template <typename T, typename PMT, typename PVT> 00602 template <typename U, typename V> inline U 00603 ODEBND_VAL<T,PMT,PVT>::_predictor 00604 ( const V&h, const unsigned q, const unsigned n, const U*U_TE, 00605 const unsigned i ) 00606 { 00607 #ifdef MC__ODEBND_VAL_DEBUG 00608 for( unsigned k=0; k<q; q++ ) 00609 std::cout << "ODEBND_VAL::_predictor *** f[" << q << "](" << i << ") = " 00610 << U_TE[q*n+i] << std::endl; 00611 #endif 00612 // Compute predictor of xi(_t+h) 00613 unsigned pTEi = q*n+i; 00614 U Xi( U_TE[pTEi] ); 00615 pTEi -= n; 00616 for( unsigned k=0; k<q; k++, pTEi-=n ) 00617 { Xi *= h; Xi += U_TE[pTEi]; } 00618 return Xi; 00619 00620 } 00621 00622 template <typename T, typename PMT, typename PVT> 00623 template <typename U, typename V> inline U 00624 ODEBND_VAL<T,PMT,PVT>::_predictor 00625 ( const V&h, const unsigned q, const unsigned n, const U*U_FTE, 00626 const unsigned i, const unsigned j ) 00627 { 00628 // Compute predictor of dxi(_t+h)/dx 00629 unsigned pFTEij = q*n*n+i*n+j; 00630 U DjXi( U_FTE[pFTEij] ); 00631 pFTEij -= n*n; 00632 for( unsigned k=0; k<q; k++, pFTEij-=n*n ) 00633 { DjXi *= h; DjXi += U_FTE[pFTEij]; }; 00634 return DjXi; 00635 } 00636 00637 template <typename T, typename PMT, typename PVT> 00638 template <typename U> inline double 00639 ODEBND_VAL<T,PMT,PVT>::_stepsize 00640 ( const unsigned q, U*UTRHS, const T*X, const bool hdep ) const 00641 { 00642 #ifdef MC__ODEBND_VAL_DEBUG_STEPSIZE 00643 std::cout << "UTRHS[q+1]:"; 00644 for( unsigned int ix=0; ix<_nx; ix++ ) 00645 std::cout << " " << UTRHS[ix]; 00646 std::cout << std::endl << "factorial: " << _factorial(q+1) << std::endl; 00647 #endif 00648 return hdep? std::pow( _smaxnorm(UTRHS,X)*_factorial(q+1) + machprec(), -1./q ) 00649 : std::pow( _smaxnorm(UTRHS,X)*_factorial(q+1) + machprec(), -1./(q+1) ); 00650 } 00651 00652 template <typename T, typename PMT, typename PVT> 00653 inline double 00654 ODEBND_VAL<T,PMT,PVT>::_validation 00655 ( const unsigned q, PVT*PMTRHS, const T*X ) 00656 { 00657 if( options.HREDUC >= 1. || options.HREDUC <=0. ) throw Exceptions( Exceptions::HREDUC ); 00658 00659 // Stepsize validatinon 00660 #ifdef MC__ODEBND_VAL_DEBUG_STEPSIZE 00661 for( unsigned k=1; k<=q; k++ ){ 00662 double h0 = _stepsize( k, PMTRHS+k*_nx, X, options.HSTAB ); 00663 std::cout << k << " " << h0 << std::endl; 00664 } 00665 { int dum; std::cin >> dum; } 00666 #endif 00667 double h = _stepsize( q, PMTRHS+q*_nx, X, options.HSTAB ) * options.HREDUC, hval; 00668 for( ; true; h *= options.HREDUC ){ 00669 00670 // Check minimum stepsize criterion 00671 if( h < options.HMIN ) return h; 00672 00673 // Check predictor validity on full step [0,h] 00674 if( options.PMVALID ){ // polynomial model-based validation 00675 for( unsigned ix=0; ix<_nx; ix++ ){ 00676 _PMVAR[ix] = _predictor( T(0,1)*h, q, _nx, PMTRHS, ix ).center(); 00677 _PMVAR[ix] += options.HSTAB? h*options.TOL*T(-1,1): options.TOL*T(-1,1); 00678 } 00679 _PMVAR[_nx+_np] = _t; // Keep time when stepsize was computed 00680 _pDAG->eval( _opTRHSval, _PMDAG, _nx, _pTRHS+(q+1)*_nx, _PMTRHSval, _nVAR, _pVAR, _PMVAR ); 00681 ++stats_traj.numTRHS_PM; 00682 hval = _stepsize(q, _PMTRHSval, X, options.HSTAB ); 00683 } 00684 else{ // Interval-based validation 00685 for( unsigned ix=0; ix<_nx; ix++ ){ 00686 _IVAR[ix] = _predictor( T(0,1)*h, q, _nx, PMTRHS, ix ).bound(); 00687 _IVAR[ix] += options.HSTAB? h*options.TOL*T(-1,1): options.TOL*T(-1,1); 00688 } 00689 _IVAR[_nx+_np] = _t; // Keep time when stepsize was computed 00690 _pDAG->eval( _opTRHSval, _IDAG, _nx, _pTRHS+(q+1)*_nx, _ITRHSval, _nVAR, _pVAR, _IVAR ); 00691 ++stats_traj.numTRHS_I; 00692 hval = _stepsize( q, _ITRHSval, X, options.HSTAB ); 00693 } 00694 #ifdef MC__ODEBND_VAL_DEBUG_STEPSIZE 00695 std::cout << "current step: h=" << h << " <=? " << hval << std::endl; 00696 #endif 00697 if( h < hval ) return h; 00698 } 00699 } 00700 00701 template <typename T, typename PMT, typename PVT> 00702 inline typename ODEBND_VAL<T,PMT,PVT>::STATUS 00703 ODEBND_VAL<T,PMT,PVT>::_propagate_INT 00704 ( const double tnext, std::ostream&os ) 00705 { 00706 const unsigned q = options.TSORDER; 00707 00708 // Taylor series expansion in PVT arithmetic up to order TSORDER+1 00709 for( unsigned ix=0; ix<_nx; ix++ ) _PMVAR[ix] = _PMx[ix]; 00710 _PMVAR[_nx+_np] = _t; 00711 _pDAG->eval( _opTRHS, _PMDAG, (q+2)*_nx, _pTRHS, _PMTRHS, _nVAR, _pVAR, _PMVAR ); 00712 ++stats_traj.numTRHS_PM; 00713 00714 // Stepsize selection and validation 00715 _h = _validation( q, _PMTRHS, _Ix ); 00716 if( _h < options.HMIN ) return FAILURE; 00717 if( _h > options.HMAX ) _h = options.HMAX; 00718 // Modify stepsize if stage time is exceeded 00719 if( _t+_h > tnext ) _h = tnext-_t; 00720 ++stats_traj.numSteps; 00721 00722 // Enclosure propagation 00723 for( unsigned int ix=0; ix<_nx; ix++ ){ 00724 _PMx[ix] = _predictor( _h, q, _nx, _PMTRHS, ix ); 00725 // Truncation error 00726 #ifdef MC__ODEBND_VAL_STEPSIZE_HSTAB 00727 _PMx[ix] += _h*options.TOL*T(-1.,1.); 00728 #else 00729 _PMx[ix] += options.TOL*T(-1.,1.); 00730 #endif 00731 #ifdef MC__ODEBND_VAL_DEBUG 00732 std::cout << "PMx(@" << _t+_h << ")[" << ix << "] = " << _PMx[ix] << std::endl; 00733 #endif 00734 _Ix[ix] = _PMx[ix].bound(); 00735 } 00736 _Ex.set(); 00737 00738 // Check enclosure diameter before returning 00739 return( _diam(_Ix) < options.DMAX? NORMAL: FAILURE ); 00740 } 00741 00742 template <typename T, typename PMT, typename PVT> 00743 inline typename ODEBND_VAL<T,PMT,PVT>::STATUS 00744 ODEBND_VAL<T,PMT,PVT>::_propagate_ELL0 00745 ( const unsigned q, const double tnext, std::ostream&os ) 00746 { 00747 // Stepsize validation 00748 if( options.TSTOP || isequal( _t, _tmax ) ){ 00749 00750 _Ex_TE = _Ex; // Copy of _Ex at expansion point for updates later on 00751 for( unsigned int ix=0; ix<_nx; ix++ ){ 00752 _Rx_TE[ix] = _PMx[ix].remainder(); // Copy of polynomial model remainder at expansion time for updates later on 00753 _PMx[ix].center().set( T(0.) ); // Keep centered polynomial part 00754 } 00755 00756 // Taylor series expansion in PVT arithmetic up to order TSORDER+1 00757 for( unsigned ix=0; ix<_nx; ix++ ) _PMVAR[ix] = _PMx[ix]; 00758 _PMVAR[_nx+_np] = _t; // Keep time when stepsize was computed 00759 _pDAG->eval( _opTRHS, _PMDAG, (q+2)*_nx, _pTRHS, _PMTRHS, _nVAR, _pVAR, _PMVAR ); 00760 ++stats_traj.numTRHS_PM; 00761 00762 // Taylor series expansion and differentiation in T arithmetic up to order TSORDER 00763 for( unsigned ix=0; ix<_nx; ix++ ) _IVAR[ix] = _Ix[ix]; 00764 _IVAR[_nx+_np] = _t; 00765 _pDAG->eval( _opFTRHS, _IDAG, (q+1)*_nx*_nx, _pFTRHS, _IFTRHS, _nVAR, _pVAR, _IVAR ); 00766 ++stats_traj.numFTRHS_I; 00767 00768 // Stepsize selection and validation 00769 _hmax = _h = _validation( q, _PMTRHS, _Ix ); 00770 if( _hmax < options.HMIN ) return FAILURE; 00771 if( _hmax > options.HMAX ) _hmax = _h = options.HMAX; 00772 // Modify stepsize if stage time is exceeded 00773 _tmax = _t+_hmax; 00774 // Keep time when stepsize was computed 00775 _tval = _t; 00776 ++stats_traj.numSteps; 00777 #ifdef MC__ODEBND_VAL_DEBUG 00778 std::cout << "\nCurrent step: hmax=" << _hmax << " tmax=" << _tmax << std::endl; 00779 { int dum; std::cin >> dum; } 00780 #endif 00781 } 00782 00783 // By-pass stepsize validation if previous integration step can be 00784 // carried out further and ODE RHS is continuous 00785 else{ 00786 _h = _hmax; 00787 } 00788 00789 // Limit stepsize so as to stop at stage time tnext 00790 if( _tmax > tnext ) _h = tnext-_tval; // Do not use _t directly as it may be different from the validation time 00791 #ifdef MC__ODEBND_VAL_DEBUG 00792 std::cout << "\nCurrent step: t=" << _t << " h=" << _h << " tnext=" << tnext 00793 << " hmax=" << _hmax << " tmax=" << _tmax << std::endl; 00794 #endif 00795 00796 // Enclosure propagation 00797 for( unsigned int ix=0; ix<_nx; ix++ ){ 00798 _PMx[ix] = _predictor( _h, q, _nx, _PMTRHS, ix ).center(); 00799 #ifdef MC__ODEBND_VAL_DEBUG 00800 std::cout << "_PMx[" << ix << "] =" << _PMx[ix]; 00801 #endif 00802 // Remainder of polynomial model propagation of state polynomial approximant 00803 _Rx[ix] = _PMx[ix].remainder(); 00804 // Linear part for ellipsoidal remainder update 00805 for( unsigned int jx=0; jx<_nx; jx++ ){ 00806 T IAx = _predictor( _h, q, _nx, _IFTRHS, ix, jx ); 00807 _Ax(ix,jx) = Op<T>::mid( IAx ); 00808 _Rx[ix] += ( IAx - _Ax(ix,jx) ) * _Rx_TE[jx]; 00809 } 00810 // Truncation error 00811 #ifdef MC__ODEBND_VAL_STEPSIZE_HSTAB 00812 _Rx[ix] += _h*options.TOL*T(-1.,1.); 00813 #else 00814 _Rx[ix] += options.TOL*T(-1.,1.); 00815 #endif 00816 #ifdef MC__ODEBND_VAL_DEBUG 00817 std::cout << "_Rx[" << ix << "] =" << _Rx[ix] 00818 << " diam(_Rx[" << ix << "]) =" << Op<T>::diam(_Rx[ix]) 00819 << " midp(_Rx[" << ix << "]) =" << Op<T>::mid(_Rx[ix]) 00820 << std::endl; 00821 #endif 00822 } 00823 #ifdef MC__ODEBND_VAL_DEBUG 00824 std::cout << "_Ax(@" << _tval << ") =\n" << _Ax << std::endl; 00825 std::cout << "_Ex(@" << _tval << ") =" << _Ex_TE << std::endl; 00826 #endif 00827 00828 // Correct stepsize in case stepsize selection/validation was by-passed 00829 _h -= (_t-_tval); 00830 #ifdef MC__ODEBND_VAL_DEBUG 00831 std::cout << "\nAdjusted step: h=" << _h << " tval=" << _tval << std::endl; 00832 #endif 00833 00834 return NORMAL; 00835 } 00836 00837 template <typename T, typename PMT, typename PVT> 00838 inline typename ODEBND_VAL<T,PMT,PVT>::STATUS 00839 ODEBND_VAL<T,PMT,PVT>::_propagate_ELL1 00840 ( const unsigned q, const double tnext, std::ostream&os ) 00841 { 00842 // Stepsize validation 00843 if( options.TSTOP || isequal( _t, _tmax ) ){ 00844 00845 _Ex_TE = _Ex; // Copy of _Ex at expansion point for updates later on 00846 for( unsigned int ix=0; ix<_nx; ix++ ){ 00847 _Rx_TE[ix] = _PMx[ix].remainder(); // Copy of polynomial model remainder at expansion time for updates later on 00848 _PMx[ix].center().set( T(0.) ); // get centered polynomial part 00849 } 00850 00851 // Taylor series expansion in PVT arithmetic up to order TSORDER+1 00852 for( unsigned ix=0; ix<_nx; ix++ ) _PMVAR[ix] = _PMx[ix]; 00853 _PMVAR[_nx+_np] = _t; // Keep time when stepsize was computed 00854 _pDAG->eval( _opTRHS, _PMDAG, (q+2)*_nx, _pTRHS, _PMTRHS, _nVAR, _pVAR, _PMVAR ); 00855 ++stats_traj.numTRHS_PM; 00856 00857 // Taylor series expansion and differentiation in PVT arithmetic up to order TSORDER 00858 for( unsigned ix=0; ix<_nx; ix++ ){ 00859 PVT MVri( _MVenv, _np+ix, _Rx_TE[ix] ); 00860 _MVVAR[ix].set( _MVenv ).set( _PMx[ix], true ); 00861 _MVVAR[ix] += MVri; 00862 } 00863 _MVVAR[_nx+_np] = _t; 00864 _pDAG->eval( _opFTRHS, _PMDAG, (q+1)*_nx*_nx, _pFTRHS, _PMFTRHS, _nVAR, _pVAR, _MVVAR ); 00865 ++stats_traj.numFTRHS_PM; 00866 00867 // Stepsize selection and validation 00868 _hmax = _h = _validation( q, _PMTRHS, _Ix ); 00869 if( _hmax < options.HMIN ) return FAILURE; 00870 if( _hmax > options.HMAX ) _hmax = _h = options.HMAX; 00871 // Modify stepsize if stage time is exceeded 00872 _tmax = _t+_hmax; 00873 // Keep time when stepsize was computed 00874 _tval = _t; 00875 ++stats_traj.numSteps; 00876 #ifdef MC__ODEBND_VAL_DEBUG 00877 std::cout << "\nCurrent step: hmax=" << _hmax << " tmax=" << _tmax << std::endl; 00878 //{ int dum; std::cin >> dum; } 00879 #endif 00880 } 00881 00882 // By-pass stepsize validation if previous integration step can be 00883 // carried out further and ODE RHS is continuous 00884 else{ 00885 _h = _hmax; 00886 } 00887 00888 // Limit stepsize so as to stop at stage time tnext 00889 // Do not use _t since might be different from Taylor expansion time 00890 if( _tmax > tnext ) _h = tnext-_tval; 00891 #ifdef MC__ODEBND_VAL_DEBUG 00892 std::cout << "\nCurrent step: t=" << _t << " h=" << _h << " tnext=" << tnext 00893 << " hmax=" << _hmax << " tmax=" << _tmax << std::endl; 00894 #endif 00895 00896 // Enclosure propagation 00897 for( unsigned int ix=0; ix<_nx; ix++ ){ 00898 _PMx[ix] = _predictor( _h, q, _nx, _PMTRHS, ix ).center(); 00899 #ifdef MC__ODEBND_VAL_DEBUG 00900 std::cout << "_PMx[" << ix << "] =" << _PMx[ix]; 00901 #endif 00902 // Remainder of polynomial model propagation of state polynomial approximant 00903 _Rx[ix] = _PMx[ix].remainder(); 00904 // Linear part for ellipsoidal remainder update 00905 for( unsigned int jx=0; jx<_nx; jx++ ){ 00906 PVT MVfx = _predictor( _h, q, _nx, _PMFTRHS, ix, jx ).center(); 00907 _Ax(ix,jx) = MVfx.constant(); 00908 _Rx[ix] += ( MVfx.bound() - _Ax(ix,jx) ) * _Rx_TE[jx]; 00909 } 00910 // Truncation error 00911 #ifdef MC__ODEBND_VAL_STEPSIZE_HSTAB 00912 _Rx[ix] += _h*options.TOL*T(-1.,1.); 00913 #else 00914 _Rx[ix] += options.TOL*T(-1.,1.); 00915 #endif 00916 #ifdef MC__ODEBND_VAL_DEBUG 00917 std::cout << "_Rx[" << ix << "] =" << _Rx[ix] 00918 << " diam(_Rx[" << ix << "]) =" << Op<T>::diam(_Rx[ix]) 00919 << " midp(_Rx[" << ix << "]) =" << Op<T>::mid(_Rx[ix]) 00920 << std::endl; 00921 #endif 00922 } 00923 #ifdef MC__ODEBND_VAL_DEBUG 00924 std::cout << "_Ax(@" << _tval << ") =\n" << _Ax << std::endl; 00925 std::cout << "_Ex(@" << _tval << ") =" << _Ex_TE << std::endl; 00926 #endif 00927 00928 // Correct stepsize in case stepsize selection/validation was by-passed 00929 _h -= (_t-_tval); 00930 #ifdef MC__ODEBND_VAL_DEBUG 00931 std::cout << "\nAdjusted step: h=" << _h << " tval=" << _tval << std::endl; 00932 #endif 00933 00934 return NORMAL; 00935 } 00936 template <typename T, typename PMT, typename PVT> 00937 inline typename ODEBND_VAL<T,PMT,PVT>::STATUS 00938 ODEBND_VAL<T,PMT,PVT>::_propagate_ELL2 00939 ( const unsigned q, const double tnext, std::ostream&os ) 00940 { 00941 // Stepsize validation 00942 if( options.TSTOP || isequal( _t, _tmax ) ){ 00943 00944 _Ex_TE = _Ex; // Copy of _Ex at expansion point for updates later on 00945 for( unsigned int ix=0; ix<_nx; ix++ ){ 00946 _Rx[ix] = _PMx[ix].center().remainder(); // get centered remainder 00947 _PMx[ix].set( T(0.) ); // cancel remainder term to get polynomial part 00948 #ifdef MC__ODEBND_VAL_DEBUG 00949 std::cout << "_PMx[" << ix << "] =" << _PMx[ix]; 00950 std::cout << "_Rx[" << ix << "] =" << _Rx[ix] << std::endl; 00951 #endif 00952 } 00953 00954 // Taylor series expansion in PVT arithmetic (joint parameter-state) up to order TSORDER+1 00955 for( unsigned ix=0; ix<_nx; ix++ ){ 00956 PVT MVri( _MVenv, _np+ix, _Rx[ix] ); 00957 _MVVAR[ix].set( _MVenv ).set( _PMx[ix], true ); 00958 _MVVAR[ix] += MVri; 00959 } 00960 _MVVAR[_nx+_np] = _t; 00961 _pDAG->eval( _opTRHS, _PMDAG, (q+2)*_nx, _pTRHS, _PMTRHS, _nVAR, _pVAR, _MVVAR ); 00962 ++stats_traj.numTRHS_PM; 00963 00964 // Stepsize selection and validation 00965 _hmax = _h = _validation( q, _PMTRHS, _Ix ); 00966 if( _hmax < options.HMIN ) return FAILURE; 00967 if( _hmax > options.HMAX ) _hmax = _h = options.HMAX; 00968 // Modify stepsize if stage time is exceeded 00969 _tmax = _t+_hmax; 00970 // Keep time when stepsize was computed 00971 _tval = _t; 00972 ++stats_traj.numSteps; 00973 } 00974 00975 // By-pass stepsize validation if previous integration step can be 00976 // carried out further and ODE RHS is continuous 00977 else{ 00978 #ifdef MC__ODEBND_VAL_DEBUG 00979 std::cout << "Expansion by-passed: t=" << _t << " tmax=" << _tmax << " hmax=" << _hmax << std::endl; 00980 #endif 00981 _h = _hmax; 00982 } 00983 00984 // Limit stepsize so as to stop at stage time tnext 00985 // Do not use _t since might be different from Taylor expansion time 00986 if( _tmax > tnext ) _h = tnext-_tval; 00987 #ifdef MC__ODEBND_VAL_DEBUG 00988 std::cout << "\nCurrent step: t=" << _t << " h=" << _h << " tnext=" << tnext 00989 << " hmax=" << _hmax << " tmax=" << _tmax << std::endl; 00990 #endif 00991 00992 // Enclosure propagation 00993 for( unsigned int ix=0; ix<_nx; ix++ ){ 00994 PVT MVXh = _predictor( _h, q, _nx, _PMTRHS, ix ).center(); 00995 #ifdef MC__ODEBND_VAL_DEBUG 00996 std::cout << "MVXh[" << ix << "] =" << MVXh; 00997 #endif 00998 // Extract state polynomial approximant in p and set to 0 00999 MVXh.get( _PMx[ix].set(_PMenv), true ); 01000 #ifdef MC__ODEBND_VAL_DEBUG 01001 std::cout << "_PMx[" << ix << "] =" << _PMx[ix]; 01002 std::cout << "MVXh[" << ix << "] =" << MVXh; 01003 #endif 01004 // Extract first-order terms and set to 0 01005 for( unsigned int jx=0; jx<_nx; jx++ ) 01006 _Ax(ix,jx) = MVXh.linear(_np+jx,true); 01007 // Remainder is higher-order terms *plus* truncation error 01008 #ifdef MC__ODEBND_VAL_STEPSIZE_HSTAB 01009 _Rx[ix] = MVXh.bound() + _h*options.TOL*T(-1.,1.); 01010 #else 01011 _Rx[ix] = MVXh.bound() + options.TOL*T(-1.,1.); 01012 #endif 01013 #ifdef MC__ODEBND_VAL_DEBUG 01014 std::cout << "_Rx[" << ix << "] =" << _Rx[ix] 01015 << " diam(_Rx[" << ix << "]) =" << Op<T>::diam(_Rx[ix]) 01016 << " midp(_Rx[" << ix << "]) =" << Op<T>::mid(_Rx[ix]) 01017 << std::endl; 01018 #endif 01019 } 01020 #ifdef MC__ODEBND_VAL_DEBUG 01021 std::cout << "_Ax(@" << _tval << ") =\n" << _Ax << std::endl; 01022 std::cout << "_Ex(@" << _tval << ") =" << _Ex_TE << std::endl; 01023 #endif 01024 01025 // Correct stepsize in case stepsize selection/validation was by-passed 01026 _h -= (_t-_tval); 01027 #ifdef MC__ODEBND_VAL_DEBUG 01028 std::cout << "\nAdjusted step: h=" << _h << " tval=" << _tval << std::endl; 01029 #endif 01030 01031 return NORMAL; 01032 } 01033 01034 template <typename T, typename PMT, typename PVT> 01035 inline typename ODEBND_VAL<T,PMT,PVT>::STATUS 01036 ODEBND_VAL<T,PMT,PVT>::_invariant_ELL0 01037 ( const PVT*Px, const T*Rx, std::ostream&os ) 01038 { 01039 // Compute invariants in PVT arithmetic 01040 for( unsigned i=0; i<_nx; i++ ) _PMVAR[i] = Px[i]; 01041 _PMVAR[_nx+_np] = _t; 01042 _pDAG->eval( _opINV, _PMDAG, _ni, _pINV, _PMINV, _nVAR, _pVAR, _PMVAR ); 01043 01044 // Compute invariant derivatives in T arithmetic 01045 for( unsigned i=0; i<_nx; i++ ) _IVAR[i] = _PMx[i].bound() + _Rx[i]; 01046 _IVAR[_nx+_np] = _t; 01047 _pDAG->eval( _opFINV, _IDAG, _ni*_nx, _pFINV, _IFINV, _nVAR, _pVAR, _IVAR ); 01048 01049 // Compute invariant directions and remainders 01050 for( unsigned i=0, ij=0; i<_ni; i++ ){ 01051 _Rinv[i] = _PMINV[i].remainder(); 01052 for( unsigned j=0; j<_nx; j++, ij++ ){ 01053 _Ainv(i,j) = Op<T>::mid(_IFINV[ij]); // row-wise storage in IFINV 01054 _Rinv[i] += ( _IFINV[ij] - _Ainv(i,j) ) * Rx[j]; 01055 } 01056 #ifdef MC__ODEBND_VAL_DEBUG 01057 std::cout << "_Rinv[" << i << "] =" << _Rinv[i] 01058 << " diam(_Rinv[" << i << "]) =" << Op<T>::diam(_Rinv[i]) 01059 << " midp(_Rinv[" << i << "]) =" << Op<T>::mid(_Rinv[i]) 01060 << std::endl; 01061 #endif 01062 } 01063 #ifdef MC__ODEBND_VAL_DEBUG 01064 std::cout << "_Ainv(@" << _t << ") =\n" << _Ainv << std::endl; 01065 { int dum; std::cin >> dum; } 01066 #endif 01067 01068 return NORMAL; 01069 } 01070 01071 template <typename T, typename PMT, typename PVT> 01072 inline typename ODEBND_VAL<T,PMT,PVT>::STATUS 01073 ODEBND_VAL<T,PMT,PVT>::_invariant_ELL1 01074 ( const PVT*Px, const T*Rx, std::ostream&os ) 01075 { 01076 // Compute invariants in PVT arithmetic 01077 for( unsigned i=0; i<_nx; i++ ) _PMVAR[i] = Px[i]; 01078 _PMVAR[_nx+_np] = _t; 01079 _pDAG->eval( _opINV, _PMDAG, _ni, _pINV, _PMINV, _nVAR, _pVAR, _PMVAR ); 01080 01081 // Compute invariant derivatives in PVT arithmetic 01082 for( unsigned i=0; i<_nx; i++ ){ 01083 PVT MVri( _MVenv, _np+i, Rx[i] ); 01084 _MVVAR[i].set( _MVenv ).set( Px[i], true ); 01085 _MVVAR[i] += MVri; 01086 #ifdef MC__ODEBND_VAL_DEBUG 01087 std::cout << "Px[" << i << "] = " << Px[i] << std::endl; 01088 std::cout << "_MVx[" << i << "] = " << _MVVAR[i] << std::endl; 01089 #endif 01090 } 01091 _MVVAR[_nx+_np] = _t; 01092 _pDAG->eval( _opFINV, _PMDAG, _ni*_nx, _pFINV, _PMFINV, _nVAR, _pVAR, _MVVAR ); 01093 01094 for( unsigned i=0, ij=0; i<_ni; i++ ){ 01095 _Rinv[i] = _PMINV[i].remainder(); 01096 for( unsigned j=0; j<_nx; j++, ij++ ){ 01097 #ifdef MC__ODEBND_VAL_DEBUG 01098 std::cout << "_PMFINV[" << i << "," << j << "] =" << _PMFINV[ij] 01099 << std::endl; 01100 #endif 01101 _Ainv(i,j) = _PMFINV[ij].center().constant(); 01102 _Rinv[i] += ( _PMFINV[ij].bound() - _Ainv(i,j) ) * Rx[j]; 01103 } 01104 #ifdef MC__ODEBND_VAL_DEBUG 01105 std::cout << "_Rinv[" << i << "] =" << _Rinv[i] 01106 << " diam(_Rinv[" << i << "]) =" << Op<T>::diam(_Rinv[i]) 01107 << " midp(_Rinv[" << i << "]) =" << Op<T>::mid(_Rinv[i]) 01108 << std::endl; 01109 #endif 01110 } 01111 #ifdef MC__ODEBND_VAL_DEBUG 01112 std::cout << "_Ainv(@" << _t << ") =\n" << _Ainv << std::endl; 01113 { int dum; std::cin >> dum; } 01114 #endif 01115 01116 return NORMAL; 01117 } 01118 01119 template <typename T, typename PMT, typename PVT> 01120 inline typename ODEBND_VAL<T,PMT,PVT>::STATUS 01121 ODEBND_VAL<T,PMT,PVT>::_invariant_ELL2 01122 ( const PVT*Px, const T*Rx, std::ostream&os ) 01123 { 01124 // Compute invariants in PVT arithmetic (joint X,P expansion) 01125 for( unsigned i=0; i<_nx; i++ ){ 01126 PVT MVri( _MVenv, _np+i, Rx[i] ); 01127 _MVVAR[i].set( _MVenv ).set( Px[i], true ); 01128 _MVVAR[i] += MVri; 01129 #ifdef MC__ODEBND_VAL_DEBUG 01130 std::cout << "Px[" << i << "] = " << Px[i] << std::endl; 01131 std::cout << "_MVx[" << i << "] = " << _MVVAR[i] << std::endl; 01132 #endif 01133 } 01134 _MVVAR[_nx+_np] = _t; 01135 _pDAG->eval( _opINV, _PMDAG, _ni, _pINV, _PMINV, _nVAR, _pVAR, _MVVAR ); 01136 01137 for( unsigned int i=0; i<_ni; i++ ){ 01138 // Extract state polynomial approximant in p and set to 0 01139 PVT Pinv; _PMINV[i].get( Pinv.set(_PMenv), true ); //THIS SHOULD NORMALLY BE ZERO!!! 01140 // Extract first-order terms and set to 0 01141 for( unsigned int j=0; j<_nx; j++ ) 01142 _Ainv(i,j) = _PMINV[i].linear( _np+j, true ); 01143 _Rinv[i] = _PMINV[i].bound(); 01144 #ifdef MC__ODEBND_VAL_DEBUG 01145 std::cout << "_Rinv[" << i << "] =" << _Rinv[i] 01146 << " diam(_Rinv[" << i << "]) =" << Op<T>::diam(_Rinv[i]) 01147 << " midp(_Rinv[" << i << "]) =" << Op<T>::mid(_Rinv[i]) 01148 << std::endl; 01149 #endif 01150 } 01151 #ifdef MC__ODEBND_VAL_DEBUG 01152 std::cout << "_Ainv(@" << _t << ") =\n" << _Ainv << std::endl; 01153 { int dum; std::cin >> dum; } 01154 #endif 01155 01156 return NORMAL; 01157 } 01158 01159 template <typename T, typename PMT, typename PVT> 01160 inline typename ODEBND_VAL<T,PMT,PVT>::STATUS 01161 ODEBND_VAL<T,PMT,PVT>::_invariant_ELL 01162 ( std::ostream&os ) 01163 { 01164 if( !options.USEINV || !_ni ) return NORMAL; 01165 01166 // Update polynomial model and derived bounds 01167 for( unsigned int ix=0; ix<_nx; ix++ ){ 01168 _PMx[ix].set( T(0.) ); // polynomial part 01169 _Rx[ix] = T( _Ex.l(ix), _Ex.u(ix) ); // centered remainder 01170 } 01171 01172 // In this variant a bound on the Jacobian matrix of the invariant is computed 01173 // and the linear part is taken as the mid-point of this matrix 01174 if( !options.ORDMIT ){ 01175 if( _invariant_ELL0( _PMx, _Rx, os ) != NORMAL ) return FAILURE; 01176 } 01177 01178 // In this variant a polynomial model of the Jacobian matrix of the invariant is 01179 // computed and the linear part is taken as the mid-point of this matrix 01180 else if( options.ORDMIT < _PMenv->nord() ){ 01181 if( _invariant_ELL1( _PMx, _Rx, os ) != NORMAL ) return FAILURE; 01182 } 01183 01184 // In this variant a polynomial model of the invariant in the joint state-parameter 01185 // and of the same order as the parameter polynomial model is computed 01186 else{ 01187 if( _invariant_ELL2( _PMx, _Rx, os ) != NORMAL ) return FAILURE; 01188 } 01189 01190 // Contract ellipsoidal remainder 01191 for( unsigned int ii=0; ii<_ni; ii++ ){ 01192 // Try exact intersection with hyperplane 01193 E Ex_red; 01194 try{ 01195 Ex_red = hpintersection( _Ex, std::make_pair( t(_Ainv.row(ii)), 0. ) ); 01196 #ifdef MC__ODEBND_VAL_DEBUG_INVARIANT 01197 std::cout << "_Ex (intersection) =\n" << Ex_red << std::endl; 01198 #endif 01199 // Nonlinear invariant case <-- NOT YET TESTED EXTENSIVELY--> 01200 if( Op<T>::diam(_Rinv[ii]) > machprec() ){ 01201 for( unsigned int jx=0; jx<_nx; jx++ ) 01202 _Ninv[jx] = _Ainv(ii,jx)/(_Ainv.row(ii)%_Ainv.row(ii))*_Rinv[ii]; 01203 Ex_red = minksum_ea( Ex_red, _Ninv, options.QTOL ); 01204 #ifdef MC__ODEBND_VAL_DEBUG_INVARIANT 01205 std::cout << "_Ex (minkowski sum) =\n" << Ex_red << std::endl; 01206 #endif 01207 } 01208 #ifdef MC__ODEBND_VAL_DEBUG_INVARIANT 01209 int dum; std::cin >> dum; 01210 #endif 01211 } 01212 catch( E::Exceptions &eObj){ 01213 continue; 01214 } 01215 if( Ex_red.trQ() < _Ex.trQ() ){ 01216 #ifdef MC__ODEBND_VAL_DEBUG_INVARIANT 01217 std::cout << "_Ex (initial) =\n" << _Ex << std::endl; 01218 std::cout << "_Ex (updated) =\n" << Ex_red << std::endl; 01219 int dum; std::cin >> dum; 01220 #endif 01221 _Ex = Ex_red; 01222 } 01223 } 01224 01225 return NORMAL; 01226 } 01227 01228 template <typename T, typename PMT, typename PVT> 01229 inline typename ODEBND_VAL<T,PMT,PVT>::STATUS 01230 ODEBND_VAL<T,PMT,PVT>::_update_ELL 01231 ( std::ostream&os ) 01232 { 01233 try{ 01234 //_Ex = mtimes(_Ex_TE,_Ax); 01235 _Ex = minksum_ea( mtimes(_Ex_TE,_Ax), _Rx, options.QTOL ); 01236 for( unsigned int ix=0; ix<_nx; ix++ ) _PMx[ix] += _Ex_TE.c(ix); 01237 _Ex = _Ex.O(); 01238 #ifdef MC__ODEBND_VAL_DEBUG 01239 std::cout << "_Ex(" << _t+_h << ") =" << _Ex << std::endl; 01240 {int dum; std::cin >> dum;} 01241 #endif 01242 } 01243 catch( E::Exceptions &eObj){ 01244 return FAILURE; 01245 } 01246 #ifdef MC__ODEBND_VAL_DEBUG 01247 for( unsigned int ix=0; ix<_nx; ix++ ) 01248 std::cout << "_Rx[" << ix << " =\n" << T( _Ex.l(ix), _Ex.u(ix) ) << std::endl; 01249 #endif 01250 01251 // Contract ellipsoidal remainder using ODE invariants 01252 if( _invariant_ELL( os ) != NORMAL ) return FAILURE; 01253 01254 // Update polynomial model and derived bounds 01255 for( unsigned int ix=0; ix<_nx; ix++ ){ 01256 _PMx[ix].set( T( _Ex.l(ix), _Ex.u(ix) ) ); 01257 _Ix[ix] =_PMx[ix].bound(); 01258 #ifdef MC__ODEBND_VAL_DEBUG 01259 std::cout << "_Rx[" << ix << " =\n" << T( _Ex.l(ix), _Ex.u(ix) ) << std::endl; 01260 std::cout << "_Ix[" << ix << " (bef.) = " << _Ix[ix] << std::endl; 01261 #endif 01262 } 01263 01264 return NORMAL; 01265 } 01266 01267 template <typename T, typename PMT, typename PVT> 01268 inline typename ODEBND_VAL<T,PMT,PVT>::STATUS 01269 ODEBND_VAL<T,PMT,PVT>::_propagate_ELL 01270 ( const double tnext, std::ostream&os ) 01271 { 01272 // In this variant a bound on the Jacobian matrix is computed and the 01273 // linear part is taken as the mid-point of this matrix 01274 if( !options.ORDMIT ){ 01275 if( _propagate_ELL0( options.TSORDER, tnext, os ) != NORMAL ) return FAILURE; 01276 } 01277 // In this variant a polynomial model of the Jacobian matrix is computed and the 01278 // linear part is taken as the mid-point of this matrix 01279 else if( options.ORDMIT < _PMenv->nord() ){ 01280 if( _propagate_ELL1( options.TSORDER, tnext, os ) != NORMAL ) return FAILURE; 01281 } 01282 // In this variant a polynomial model in the joint state-parameter and 01283 // of the same order as the parameter polynomial model is computed 01284 else{ 01285 if( _propagate_ELL2( options.TSORDER, tnext, os ) != NORMAL ) return FAILURE; 01286 } 01287 01288 // Compute ellispoidal remainder 01289 if( _update_ELL( os ) != NORMAL ) return FAILURE; 01290 01291 // Check enclosure diameter before returning 01292 return( _diam(_Ix) < options.DMAX? NORMAL: FAILURE ); 01293 } 01294 01295 template <typename T, typename PMT, typename PVT> 01296 inline typename ODEBND_VAL<T,PMT,PVT>::STATUS 01297 ODEBND_VAL<T,PMT,PVT>::_propagate 01298 ( const double tnext, std::ostream&os ) 01299 { 01300 // Propagate validated enclosure until tnext 01301 STATUS flag = NORMAL; 01302 for( _h = 0; flag == NORMAL && tnext > _t; _t += _h ){ 01303 switch( options.WRAPMIT){ 01304 case Options::NONE: 01305 flag = _propagate_INT( tnext, os ); break; 01306 01307 case Options::ELLIPS: 01308 default: 01309 flag = _propagate_ELL( tnext, os ); break; 01310 } 01311 } 01312 return flag; 01313 } 01314 01315 template <typename T, typename PMT, typename PVT> inline bool 01316 ODEBND_VAL<T,PMT,PVT>::_resize 01317 ( const unsigned q, const unsigned iRHS ) 01318 { 01319 if( _vRHS.size() <= iRHS ) return false; 01320 01321 delete[] _pTRHS; _pTRHS = _pDAG->TAD( q+1, _nx, _vRHS[iRHS], _nx, _pVAR, _pT ); 01322 _opTRHS = _pDAG->subgraph( (q+2)*_nx, _pTRHS ); 01323 delete[] _PMTRHS; _PMTRHS = new PVT[(q+2)*_nx]; 01324 unsigned nPMDAG = _opTRHS.size(); 01325 01326 _opTRHSval = _pDAG->subgraph( _nx, _pTRHS+(q+1)*_nx ); 01327 delete[] _PMTRHSval; _PMTRHSval = options.PMVALID? new PVT[_nx]: 0; 01328 delete[] _ITRHSval; _ITRHSval = options.PMVALID? 0: new T[_nx]; 01329 unsigned nIDAG = options.PMVALID? 0: _opTRHSval.size(); 01330 01331 delete[] _pFTRHS; _pFTRHS = 0; 01332 _opFTRHS.clear(); 01333 delete[] _PMFTRHS; _PMFTRHS = 0; 01334 delete[] _IFTRHS; _IFTRHS = 0; 01335 01336 _pINV = 0; 01337 _opINV.clear(); 01338 delete[] _PMINV; _PMINV = 0; 01339 01340 delete[] _pFINV; _pFINV = 0; 01341 _opFINV.clear(); 01342 delete[] _PMFINV; _PMFINV = 0; 01343 delete[] _IFINV; _IFINV = 0; 01344 01345 switch( options.WRAPMIT){ 01346 case Options::NONE: 01347 break; 01348 01349 case Options::ELLIPS: default: 01350 if( options.USEINV && _vINV.size() && _ni ){ // INV 01351 _pINV = _vINV[iRHS]; 01352 _opINV = _pDAG->subgraph( _ni, _pINV ); 01353 _PMINV = new PVT[_ni]; 01354 if( nPMDAG < _opINV.size() ) nPMDAG = _opINV.size(); 01355 } 01356 if( !options.ORDMIT ){ // ELL0 01357 _pFTRHS = _pDAG->FAD( (q+1)*_nx, _pTRHS, _nx, _pVAR ); 01358 _opFTRHS = _pDAG->subgraph( (q+1)*_nx*_nx, _pFTRHS ); 01359 _IFTRHS = new T[(q+1)*_nx*_nx]; 01360 if( nIDAG < _opFTRHS.size() ) nIDAG = _opFTRHS.size(); 01361 if( options.USEINV && _vINV.size() && _ni ){ 01362 _pFINV = _pDAG->FAD( _ni, _pINV, _nx, _pVAR ); 01363 _opFINV = _pDAG->subgraph( _ni*_nx, _pFINV ); 01364 _IFINV = new T[_ni*_nx]; 01365 if( nIDAG < _opFINV.size() ) nIDAG = _opFINV.size(); 01366 } 01367 } 01368 else if( _PMenv->nord() > _MVenv->nord() ){ // ELL1 01369 _pFTRHS = _pDAG->FAD( (q+1)*_nx, _pTRHS, _nx, _pVAR ); 01370 _opFTRHS = _pDAG->subgraph( (q+1)*_nx*_nx, _pFTRHS ); 01371 _PMFTRHS = new PVT[(q+1)*_nx*_nx]; 01372 if( nPMDAG < _opFTRHS.size() ) nPMDAG = _opFTRHS.size(); 01373 if( options.USEINV && _vINV.size() && _ni ){ 01374 _pFINV = _pDAG->FAD( _ni, _pINV, _nx, _pVAR ); 01375 _opFINV = _pDAG->subgraph( _ni*_nx, _pFINV ); 01376 _PMFINV = new PVT[_ni*_nx]; 01377 if( nPMDAG < _opFINV.size() ) nPMDAG = _opFINV.size(); 01378 } 01379 } 01380 // ELL2 01381 break; 01382 } 01383 01384 delete[] _PMDAG; _PMDAG = new PVT[nPMDAG]; 01385 delete[] _IDAG; _IDAG = new T[nIDAG]; 01386 01387 return true; 01388 } 01389 01390 template <typename T, typename PMT, typename PVT> 01391 inline bool 01392 ODEBND_VAL<T,PMT,PVT>::_prepare 01393 ( const PVT* PMp ) 01394 { 01395 // Check polynomial model compatibility and size 01396 unsigned int kp=_np; 01397 for( unsigned int ip=0; ip<_np && kp==_np; ip++ ) 01398 if( PMp[ip].env() ) kp = ip; 01399 if( kp==_np || PMp[kp].env()->nvar()!=_np ) return false; 01400 _PMenv = PMp[kp].env(); 01401 01402 // Internal polynomial model environment reset 01403 unsigned int MVord = ( options.ORDMIT<_PMenv->nord()? options.ORDMIT: _PMenv->nord() ); 01404 if( !_MVenv || _MVenv->nord() != MVord || _MVenv->nvar() != _nx+_np ){ 01405 delete _MVenv; _MVenv = new PMT( _nx+_np, MVord ); 01406 _MVenv->options = _PMenv->options; 01407 } 01408 01409 // Size and set DAG evaluation arrays 01410 if( _nVAR != _nx+_np+1 ){ 01411 _nVAR = _nx+_np+1; 01412 delete[] _pVAR; _pVAR = new FFVar[_nVAR]; 01413 delete[] _IVAR; _IVAR = new T[_nVAR]; 01414 delete[] _PMVAR; _PMVAR = new PVT[_nVAR]; 01415 delete[] _MVVAR; _MVVAR = new PVT[_nVAR]; 01416 } 01417 for( unsigned ix=0; ix<_nx; ix++ ) 01418 _pVAR[ix] = _pX[ix]; 01419 for( unsigned ip=0; ip<_np; ip++ ){ 01420 _pVAR[_nx+ip] = _pP[ip]; 01421 _IVAR[_nx+ip] = PMp[ip].bound(); 01422 _PMVAR[_nx+ip] = PMp[ip]; 01423 _MVVAR[_nx+ip].set( _MVenv, ip, _IVAR[_nx+ip] ); 01424 } 01425 _pVAR[_nx+_np] = (_pT? *_pT: 0. ); 01426 01427 // State bounds 01428 if( !_Ix ) _Ix = new T[_nx]; 01429 if( !_PMx ) _PMx = new PVT[_nx]; 01430 01431 // Size environments and arrays 01432 switch( options.WRAPMIT){ 01433 case Options::NONE: 01434 break; 01435 01436 case Options::ELLIPS: 01437 default: 01438 if( _Ax.n != _nx ){ 01439 _Ax.resize(_nx,_nx); 01440 delete[] _Rx; _Rx = new T[_nx]; 01441 delete[] _Rx_TE; _Rx_TE = new T[_nx]; 01442 } 01443 if( options.USEINV && _ni && ( _Ainv.n != _nx || _Ainv.m != _ni ) ){ 01444 _Ainv.resize(_ni,_nx); 01445 delete[] _Rinv; _Rinv = new T[_ni]; 01446 delete[] _Ninv; _Ninv = new T[_ni]; 01447 } 01448 break; 01449 } 01450 01451 return true; 01452 } 01453 01454 template <typename T, typename PMT, typename PVT> 01455 inline bool 01456 ODEBND_VAL<T,PMT,PVT>::_init 01457 ( const unsigned k, const double tk, PVT*PMxk, E*Exk ) 01458 { 01459 if( !_vIC.size() ) return false; 01460 if( k && _vIC.size()>1 ) throw Exceptions( Exceptions::REINIT ); 01461 if( k ) return true; 01462 01463 _t = _tmax = tk; 01464 _pIC = _vIC.at(0); 01465 _opIC = _pDAG->subgraph( _nx, _pIC ); 01466 01467 switch( options.WRAPMIT){ 01468 01469 case Options::NONE: 01470 _pDAG->eval( _opIC, _nx, _pIC, _PMx, _np, _pVAR+_nx, _PMVAR+_nx ); 01471 for( unsigned int ix=0; ix<_nx; ix++ ) 01472 _Ix[ix] = _PMx[ix].center().bound(); 01473 _Ex.set(); 01474 break; 01475 01476 case Options::ELLIPS: 01477 default: 01478 _pDAG->eval( _opIC, _nx, _pIC, _PMx, _np, _pVAR+_nx, _PMVAR+_nx ); 01479 for( unsigned int ix=0; ix<_nx; ix++ ){ 01480 _PMx[ix].center(); 01481 _Rx[ix] = _PMx[ix].remainder(); 01482 _Ix[ix] = _PMx[ix].bound(); 01483 #ifdef MC__ODEBND_VAL_DEBUG 01484 std::cout << "PMx0[" << ix << "] =" << _PMx[ix] << std::endl; 01485 #endif 01486 } 01487 _Ex.set( _nx, _Rx ); 01488 #ifdef MC__ODEBND_VAL_DEBUG 01489 std::cout << "Ex0 =" << _Ex << std::endl; 01490 #endif 01491 // THERE MIGHT BE A BETTER WAY OF INITIALIZING IF AN ELLIPSOIDAL 01492 // REMAINDER BOUND IS KNOWN FOR THE PARAMETERS 01493 break; 01494 } 01495 01496 // Copy internal variables back into arguments 01497 for( unsigned ix=0; ix<_nx; ix++ ) PMxk[ix] = _PMx[ix]; 01498 if( Exk ) *Exk = _Ex; 01499 return true; 01500 } 01501 01516 template <typename T, typename PMT, typename PVT> 01517 inline typename ODEBND_VAL<T,PMT,PVT>::STATUS 01518 ODEBND_VAL<T,PMT,PVT>::bounds 01519 ( const unsigned int ntk, const double*tk, const PVT*PMp, PVT**PMxk, 01520 E*Exk, std::ostream&os ) 01521 { 01522 01523 // Initialize validated ODE bounding 01524 if( !_prepare( PMp ) ) return FATAL; 01525 _results.clear(); 01526 _init_stats( stats_traj ); 01527 01528 try{ 01529 // Initial state bounds 01530 if( !_init( 0, tk[0], PMxk[0], Exk ) ) return FATAL; 01531 if( options.DISPLAY >= 1 ) 01532 switch( options.WRAPMIT ){ 01533 case Options::NONE: _print_interm( tk[0], _PMx, "x", os ); break; 01534 case Options::ELLIPS: _print_interm( tk[0], _PMx, _Ex, "x", os ); break; 01535 } 01536 // Record initial results 01537 if( options.RESRECORD ) 01538 _results.push_back( Results( tk[0], _nx, _PMx ) ); 01539 01540 // Integrate ODEs through each stage 01541 for( _istg=0; _istg<ntk; _istg++ ){ 01542 01543 // update list of operations in RHS and INV 01544 const unsigned int iRHS = ( _vRHS.size()<2? 0: _istg ); 01545 if( (!_istg || iRHS) && !_resize( options.TSORDER, iRHS ) ) return FATAL; 01546 01547 if( _istg && !_init( _istg, tk[_istg], PMxk[_istg], Exk+_istg ) ) return FATAL; 01548 if( _propagate( tk[_istg+1], os ) != NORMAL ){ 01549 _final_stats( stats_traj ); 01550 if( options.DISPLAY >= 1 ) _print_stats( stats_traj, os ); 01551 return FAILURE; 01552 } 01553 for( unsigned int ix=0; ix<_nx; ix++ ) PMxk[_istg+1][ix] = _PMx[ix]; 01554 if( Exk ) Exk[_istg+1] = _Ex; 01555 if( options.DISPLAY >= 1 ) 01556 switch( options.WRAPMIT ){ 01557 case Options::NONE: _print_interm( tk[_istg+1], _PMx, "x", os ); break; 01558 case Options::ELLIPS: _print_interm( tk[_istg+1], _PMx, _Ex, "x", os ); break; 01559 } 01560 // Record intermediate results 01561 if( options.RESRECORD ) _results.push_back( Results( tk[_istg+1], _nx, _PMx ) ); 01562 } 01563 } 01564 catch(...){ 01565 _final_stats( stats_traj ); 01566 if( options.DISPLAY >= 1 ) _print_stats( stats_traj, os ); 01567 return FAILURE; 01568 } 01569 01570 _final_stats( stats_traj ); 01571 if( options.DISPLAY >= 1 ) _print_stats( stats_traj, os ); 01572 return NORMAL; 01573 } 01574 01575 template <typename T, typename PMT, typename PVT> inline typename ODEBND_VAL<T,PMT,PVT>::STATUS 01576 ODEBND_VAL<T,PMT,PVT>::_remainders 01577 ( const unsigned int ns, const double*tk, const T*Ip, const PVT*const*PMxk, 01578 T**Rxk, const unsigned int nsamp, std::ostream&os ) 01579 { 01580 STATUS flag = NORMAL; 01581 01582 // Initialization of sampled bounds at parameter lower bound 01583 double *p = new double[_np]; 01584 for( unsigned int ip=0; ip<_np; ip++ ) 01585 p[ip] = Op<T>::l(Ip[ip]); 01586 double **xk = new double*[ns+1]; 01587 for( unsigned int is=0; is<=ns; is++ ) 01588 xk[is] = new double[_nx]; 01589 flag = _ODESLV_GSL->states( ns, tk, p, xk, 0, os ); 01590 if( flag != NORMAL || nsamp <= 1 ){ 01591 delete[] p; 01592 for( unsigned int is=0; is<=ns; is++ ) delete[] xk[is]; delete[] xk; 01593 return flag; 01594 } 01595 for( unsigned int is=0; is<=ns; is++ ) 01596 for( unsigned int ix=0; ix<_nx; ix++ ) 01597 Rxk[is][ix] = xk[is][ix] - PMxk[is][ix].polynomial( p ); 01598 01599 // Start sampling process 01600 unsigned int* vsamp = new unsigned int[_np]; 01601 flag = _remainders( ns, tk, Ip, PMxk, Rxk, nsamp, vsamp, 0, p, xk, os ); 01602 01603 // Clean-up 01604 delete[] p; 01605 for( unsigned int is=0; is<=ns; is++ ) delete[] xk[is]; delete[] xk; 01606 delete[] vsamp; 01607 01608 return flag; 01609 } 01610 01611 template <typename T, typename PMT, typename PVT> inline typename ODEBND_VAL<T,PMT,PVT>::STATUS 01612 ODEBND_VAL<T,PMT,PVT>::_remainders 01613 ( const unsigned int ns, const double*tk, const T*Ip, const PVT*const*PMxk, 01614 T**Rxk, const unsigned int nsamp, unsigned int* vsamp, const unsigned int ip, 01615 double*p, double**xk, std::ostream&os ) 01616 { 01617 STATUS flag = NORMAL; 01618 01619 // Update bounds for all sampling points 01620 for( unsigned int isamp=0; isamp<nsamp; isamp++ ){ 01621 vsamp[ip] = isamp; 01622 01623 // Continue recursive call 01624 if( ip+1 < _np ){ 01625 flag = _remainders( ns, tk, Ip, PMxk, Rxk, nsamp, vsamp, ip+1, p, xk, os ); 01626 if( flag != NORMAL ) return flag; 01627 continue; 01628 } 01629 01630 // Update bounds for current point 01631 #ifdef MC__ODEBND_GSL_SAMPLE_DEBUG 01632 std::cout << "Sample: "; 01633 #endif 01634 for( unsigned int ip=0; ip<_np; ip++ ){ 01635 p[ip] = Op<T>::l( Ip[ip] ) + vsamp[ip]/(nsamp-1.) * Op<T>::diam( Ip[ip] ); 01636 #ifdef MC__ODEBND_GSL_SAMPLE_DEBUG 01637 std::cout << p[ip] << " "; 01638 #endif 01639 } 01640 #ifdef MC__ODEBND_GSL_SAMPLE_DEBUG 01641 std::cout << std::endl; 01642 #endif 01643 flag = _ODESLV_GSL->states( ns, tk, p, xk, 0, os ); 01644 if( flag != NORMAL ) return flag; 01645 for( unsigned int is=0; is<=ns; is++ ) 01646 for( unsigned int ix=0; ix<_nx; ix++ ) 01647 Rxk[is][ix] = Op<T>::hull( xk[is][ix]-PMxk[is][ix].polynomial(p), 01648 Rxk[is][ix] ); 01649 } 01650 01651 return flag; 01652 } 01653 01670 01671 template <typename T, typename PMT, typename PVT> inline typename ODEBND_VAL<T,PMT,PVT>::STATUS 01672 ODEBND_VAL<T,PMT,PVT>::hausdorff 01673 ( const unsigned int ns, const double*tk, const PVT*PMp, double**Hxk, 01674 const unsigned int nsamp, std::ostream&os ) 01675 { 01676 int DISPLAY_ODEBND = options.DISPLAY; 01677 int DISPLAY_ODESLV = options.ODESLVOPT.DISPLAY; 01678 options.DISPLAY = 0; 01679 options.ODESLVOPT.DISPLAY = 0; 01680 _ODESLV_GSL->set( *this ); // in base class BASE_ODE 01681 _ODESLV_GSL->options = options.ODESLVOPT; 01682 _ODESLV_GSL->options.RESRECORD = false; 01683 01684 // Compute approximate bounds 01685 PVT** PMxk = new PVT*[ns+1]; 01686 for( unsigned int is=0; is<ns+1; is++ ) PMxk[is] = new PVT[_nx]; 01687 try{ bounds( ns, tk, PMp, PMxk, 0, os ); } 01688 catch(...){;} 01689 unsigned int nsf = _istg; 01690 for( unsigned int is=nsf; is<ns; is++ ) 01691 for( unsigned int ix=0; ix<_nx; ix++ ) 01692 PMxk[is+1][ix] = T( -1e20, 1e20 ); 01693 01694 // Compute remainder bounds 01695 T* Ip = new T[_np]; 01696 for( unsigned int ip=0; ip<_np; ip++ ) Ip[ip] = PMp[ip].B(); 01697 T** Rxk = new T*[ns+1]; 01698 for( unsigned int is=0; is<ns+1; is++ ) Rxk[is] = new T[_nx]; 01699 _remainders( nsf, tk, Ip, PMxk, Rxk, nsamp, os ); 01700 for( unsigned int is=nsf; is<ns; is++ ) 01701 for( unsigned int ix=0; ix<_nx; ix++ ) 01702 Rxk[is+1][ix] = T( 0. ); 01703 01704 // Compute Hausdorff metric at each time step 01705 struct loc{ static double hausdorff 01706 ( const T&Ix, const T&Ix0 ) 01707 { return std::max( std::fabs(Op<T>::l(Ix)-Op<T>::l(Ix0)), 01708 std::fabs(Op<T>::u(Ix)-Op<T>::u(Ix0)) ); } 01709 }; 01710 01711 options.DISPLAY = DISPLAY_ODEBND; 01712 options.ODESLVOPT.DISPLAY = DISPLAY_ODESLV; 01713 for( unsigned int is=0; is<ns+1; is++ ){ 01714 for( unsigned int ix=0; ix<_nx; ix++ ) 01715 Hxk[is][ix] = loc::hausdorff( PMxk[is][ix].R(), Rxk[is][ix] ); 01716 if( options.DISPLAY >= 1 ){ 01717 _print_interm( tk[is], Hxk[is], "dH", os ); 01718 } 01719 } 01720 01721 for( unsigned int is=0; is<ns+1; is++ ) delete[] Rxk[is]; 01722 delete[] Rxk; 01723 for( unsigned int is=0; is<ns+1; is++ ) delete[] PMxk[is]; 01724 delete[] PMxk; 01725 delete[] Ip; 01726 01727 return NORMAL; 01728 } 01729 01730 template <typename T, typename PMT, typename PVT> 01731 template <typename U> inline void 01732 ODEBND_VAL<T,PMT,PVT>::_print_interm 01733 ( const double t, const U*x, const std::string&var, std::ostream&os ) const 01734 { 01735 os << " @t = " << std::scientific << std::setprecision(4) 01736 << std::left << t << " :" << std::endl; 01737 for( unsigned int ix=0; ix<_nx; ix++ ) 01738 os << " " << var.c_str() << "[" << ix << "] = " << x[ix] << std::endl; 01739 return; 01740 } 01741 01742 template <typename T, typename PMT, typename PVT> 01743 template <typename U, typename V> inline void 01744 ODEBND_VAL<T,PMT,PVT>::_print_interm 01745 ( const double t, const U*x, const V&r, const std::string&var, std::ostream&os ) const 01746 { 01747 os << " @t = " << std::scientific << std::setprecision(4) 01748 << std::left << t << " :" << std::endl; 01749 for( unsigned int ix=0; ix<_nx; ix++ ) 01750 os << " " << var.c_str() << "[" << ix << "] = " << x[ix] << std::endl; 01751 os << " " << "R" << var.c_str() << " =" << r << std::endl; 01752 return; 01753 } 01754 01755 template <typename T, typename PMT, typename PVT> 01756 inline void 01757 ODEBND_VAL<T,PMT,PVT>::record 01758 ( std::ofstream&bndrec, const unsigned int iprec ) const 01759 { 01760 if( !bndrec ) return; 01761 01762 // Specify format 01763 bndrec << std::right << std::scientific << std::setprecision(iprec); 01764 01765 // Record computed interval bounds at stage times 01766 typename std::vector< Results >::const_iterator it = _results.begin(); 01767 for( ; it != _results.end(); ++it ){ 01768 bndrec << std::setw(iprec+9) << (*it).t; 01769 for( unsigned int ix=0; ix<_nx; ix++ ) 01770 bndrec << std::setw(iprec+9) << mc::Op<T>::l( (*it).X[ix] ) 01771 << std::setw(iprec+9) << mc::Op<T>::u( (*it).X[ix] ); 01772 bndrec << std::endl; 01773 } 01774 } 01775 01776 template <typename T, typename PMT, typename PVT> 01777 inline void 01778 ODEBND_VAL<T,PMT,PVT>::_init_stats 01779 ( Stats&stats ) 01780 { 01781 // Initialize statistics 01782 stats.reset(); 01783 timeval time; 01784 gettimeofday(&time, 0) ; 01785 stats.cputime = - time.tv_sec - time.tv_usec*1e-6; 01786 } 01787 01788 template <typename T, typename PMT, typename PVT> 01789 inline void 01790 ODEBND_VAL<T,PMT,PVT>::_final_stats 01791 ( Stats&stats ) 01792 { 01793 // Get final CPU time 01794 timeval time; 01795 gettimeofday(&time, 0); 01796 stats.cputime += time.tv_sec + time.tv_usec*1e-6; 01797 } 01798 01799 template <typename T, typename PMT, typename PVT> 01800 inline void 01801 ODEBND_VAL<T,PMT,PVT>::_print_stats 01802 ( const Stats&stats, std::ostream&os ) 01803 { 01804 // Statistics 01805 os << " No STEPS " << stats.numSteps 01806 << std::endl 01807 << " No EVALATIONS" 01808 << " TRHS: " << stats.numTRHS_I << " (IA) " << stats.numTRHS_PM << " (PM)" 01809 << " FTRHS: " << stats.numFTRHS_I << " (IA) " << stats.numFTRHS_PM << " (PM)" 01810 << std::endl 01811 << " CPU TIME (SEC) " << std::fixed << std::left 01812 << std::setprecision(5) << stats.cputime << std::endl; 01813 return; 01814 } 01815 01816 } // end namescape mc 01817 #endif