00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef __DIFFERENTIALSTEPPER_HPP
00032 #define __DIFFERENTIALSTEPPER_HPP
00033
00034 #include "libecs.hpp"
00035 #include "Stepper.hpp"
00036
00037 #include "boost/multi_array.hpp"
00038
00039 namespace libecs
00040 {
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 typedef boost::multi_array<Real, 2> RealMatrix_;
00057 DECLARE_TYPE( RealMatrix_, RealMatrix );
00058
00059
00060 DECLARE_CLASS( DifferentialStepper );
00061
00062 LIBECS_DM_CLASS( DifferentialStepper, Stepper )
00063 {
00064
00065 public:
00066
00067 LIBECS_DM_OBJECT_ABSTRACT( DifferentialStepper )
00068 {
00069 INHERIT_PROPERTIES( Stepper );
00070
00071
00072 PROPERTYSLOT( Real, StepInterval,
00073 &DifferentialStepper::initializeStepInterval,
00074 &DifferentialStepper::getStepInterval );
00075
00076 PROPERTYSLOT_GET_NO_LOAD_SAVE( Real, NextStepInterval );
00077 PROPERTYSLOT_SET_GET_NO_LOAD_SAVE( Real, TolerableStepInterval );
00078 PROPERTYSLOT_GET_NO_LOAD_SAVE( Integer, Stage );
00079 PROPERTYSLOT_GET_NO_LOAD_SAVE( Integer, Order );
00080 }
00081
00082 class Interpolant
00083 :
00084 public libecs::Interpolant
00085 {
00086
00087 public:
00088
00089 Interpolant( DifferentialStepperRef aStepper,
00090 VariablePtr const aVariablePtr )
00091 :
00092 libecs::Interpolant( aVariablePtr ),
00093 theStepper( aStepper ),
00094 theIndex( theStepper.getVariableIndex( aVariablePtr ) )
00095 {
00096 ;
00097 }
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 virtual const Real getDifference( RealParam aTime,
00150 RealParam anInterval ) const
00151 {
00152 if ( !theStepper.theStateFlag )
00153 {
00154 return 0.0;
00155 }
00156
00157 const Real aTimeInterval1( aTime - theStepper.getCurrentTime() );
00158 const Real aTimeInterval2( aTimeInterval1 - anInterval );
00159
00160 const RealMatrixCref aTaylorSeries( theStepper.getTaylorSeries() );
00161 RealCptr aTaylorCoefficientPtr( aTaylorSeries.origin() + theIndex );
00162
00163
00164
00165
00166
00167 Real aValue1( *aTaylorCoefficientPtr * aTimeInterval1 );
00168 Real aValue2( *aTaylorCoefficientPtr * aTimeInterval2 );
00169
00170
00171
00172
00173 const RealMatrix::size_type aTaylorSize( theStepper.getOrder() );
00174 if( aTaylorSize >= 2)
00175 {
00176 const Real
00177 aStepIntervalInv( 1.0 / theStepper.getTolerableStepInterval() );
00178
00179 const RealMatrix::size_type aStride( aTaylorSeries.strides()[0] );
00180
00181 Real aFactorialInv1( aTimeInterval1 );
00182 Real aFactorialInv2( aTimeInterval2 );
00183
00184 RealMatrix::size_type s( aTaylorSize - 1 );
00185
00186 const Real theta1( aTimeInterval1 * aStepIntervalInv );
00187 const Real theta2( aTimeInterval2 * aStepIntervalInv );
00188
00189 do
00190 {
00191
00192
00193
00194 aTaylorCoefficientPtr += aStride;
00195 const Real aTaylorCoefficient( *aTaylorCoefficientPtr );
00196
00197 aFactorialInv1 *= theta1;
00198 aFactorialInv2 *= theta2;
00199
00200 aValue1 += aTaylorCoefficient * aFactorialInv1;
00201 aValue2 += aTaylorCoefficient * aFactorialInv2;
00202
00203
00204 --s;
00205 } while( s != 0 );
00206 }
00207
00208 return aValue1 - aValue2;
00209 }
00210
00211 virtual const Real getVelocity( RealParam aTime ) const
00212 {
00213 if ( !theStepper.theStateFlag )
00214 {
00215 return 0.0;
00216 }
00217
00218 const Real aTimeInterval( aTime - theStepper.getCurrentTime() );
00219
00220 const RealMatrixCref aTaylorSeries( theStepper.getTaylorSeries() );
00221 RealCptr aTaylorCoefficientPtr( aTaylorSeries.origin() + theIndex );
00222
00223
00224
00225
00226
00227 Real aValue( *aTaylorCoefficientPtr );
00228
00229
00230
00231
00232 const RealMatrix::size_type aTaylorSize( theStepper.getStage() );
00233 if( aTaylorSize >= 2 && aTimeInterval != 0.0 )
00234 {
00235 const RealMatrix::size_type aStride( aTaylorSeries.strides()[0] );
00236
00237 Real aFactorialInv( 1.0 );
00238
00239 RealMatrix::size_type s( 1 );
00240
00241 const Real theta( aTimeInterval
00242 / theStepper.getTolerableStepInterval() );
00243
00244 do
00245 {
00246
00247 ++s;
00248
00249 aTaylorCoefficientPtr += aStride;
00250 const Real aTaylorCoefficient( *aTaylorCoefficientPtr );
00251
00252 aFactorialInv *= theta * s;
00253
00254 aValue += aTaylorCoefficient * aFactorialInv;
00255
00256
00257 } while( s != aTaylorSize );
00258 }
00259
00260 return aValue;
00261 }
00262
00263 protected:
00264
00265 DifferentialStepperRef theStepper;
00266 VariableVector::size_type theIndex;
00267
00268 };
00269
00270 public:
00271
00272 DifferentialStepper();
00273 virtual ~DifferentialStepper();
00274
00275 SET_METHOD( Real, NextStepInterval )
00276 {
00277 theNextStepInterval = value;
00278 }
00279
00280 GET_METHOD( Real, NextStepInterval )
00281 {
00282 return theNextStepInterval;
00283 }
00284
00285 SET_METHOD( Real, TolerableStepInterval )
00286 {
00287 theTolerableStepInterval = value;
00288 }
00289
00290 GET_METHOD( Real, TolerableStepInterval )
00291 {
00292 return theTolerableStepInterval;
00293 }
00294
00295 void initializeStepInterval( RealParam aStepInterval )
00296 {
00297 setStepInterval( aStepInterval );
00298 setTolerableStepInterval( aStepInterval );
00299 setNextStepInterval( aStepInterval );
00300 }
00301
00302 void resetAll();
00303 void interIntegrate();
00304 void initializeVariableReferenceList();
00305 void setVariableVelocity( boost::detail::multi_array::sub_array<Real, 1> aVelocityBuffer );
00306
00307 virtual void initialize();
00308
00309 virtual void reset();
00310
00311 virtual void interrupt( TimeParam aTime );
00312
00313 virtual InterpolantPtr createInterpolant( VariablePtr aVariable )
00314 {
00315 return new DifferentialStepper::Interpolant( *this, aVariable );
00316 }
00317
00318 virtual GET_METHOD( Integer, Stage )
00319 {
00320 return 1;
00321 }
00322
00323 virtual GET_METHOD( Integer, Order )
00324 {
00325 return getStage();
00326 }
00327
00328 RealMatrixCref getTaylorSeries() const
00329 {
00330 return theTaylorSeries;
00331 }
00332
00333 protected:
00334
00335 const bool isExternalErrorTolerable() const;
00336
00337 RealMatrix theTaylorSeries;
00338
00339 std::vector< std::vector<Integer> > theVariableReferenceListVector;
00340
00341 bool theStateFlag;
00342
00343 private:
00344
00345 Real theNextStepInterval;
00346 Real theTolerableStepInterval;
00347 };
00348
00349
00350
00351
00352
00353
00354
00355
00356 DECLARE_CLASS( AdaptiveDifferentialStepper );
00357
00358 LIBECS_DM_CLASS( AdaptiveDifferentialStepper, DifferentialStepper )
00359 {
00360
00361 public:
00362
00363 LIBECS_DM_OBJECT_ABSTRACT( AdaptiveDifferentialStepper )
00364 {
00365 INHERIT_PROPERTIES( DifferentialStepper );
00366
00367 PROPERTYSLOT_SET_GET( Real, Tolerance );
00368 PROPERTYSLOT_SET_GET( Real, AbsoluteToleranceFactor );
00369 PROPERTYSLOT_SET_GET( Real, StateToleranceFactor );
00370 PROPERTYSLOT_SET_GET( Real, DerivativeToleranceFactor );
00371
00372 PROPERTYSLOT( Integer, IsEpsilonChecked,
00373 &AdaptiveDifferentialStepper::setEpsilonChecked,
00374 &AdaptiveDifferentialStepper::isEpsilonChecked );
00375 PROPERTYSLOT_SET_GET( Real, AbsoluteEpsilon );
00376 PROPERTYSLOT_SET_GET( Real, RelativeEpsilon );
00377
00378 PROPERTYSLOT_GET_NO_LOAD_SAVE( Real, MaxErrorRatio );
00379 }
00380
00381 public:
00382
00383 AdaptiveDifferentialStepper();
00384 virtual ~AdaptiveDifferentialStepper();
00385
00386
00387
00388
00389
00390
00391
00392 SET_METHOD( Real, Tolerance )
00393 {
00394 theTolerance = value;
00395 }
00396
00397 GET_METHOD( Real, Tolerance )
00398 {
00399 return theTolerance;
00400 }
00401
00402 SET_METHOD( Real, AbsoluteToleranceFactor )
00403 {
00404 theAbsoluteToleranceFactor = value;
00405 }
00406
00407 GET_METHOD( Real, AbsoluteToleranceFactor )
00408 {
00409 return theAbsoluteToleranceFactor;
00410 }
00411
00412 SET_METHOD( Real, StateToleranceFactor )
00413 {
00414 theStateToleranceFactor = value;
00415 }
00416
00417 GET_METHOD( Real, StateToleranceFactor )
00418 {
00419 return theStateToleranceFactor;
00420 }
00421
00422 SET_METHOD( Real, DerivativeToleranceFactor )
00423 {
00424 theDerivativeToleranceFactor = value;
00425 }
00426
00427 GET_METHOD( Real, DerivativeToleranceFactor )
00428 {
00429 return theDerivativeToleranceFactor;
00430 }
00431
00432 SET_METHOD( Real, MaxErrorRatio )
00433 {
00434 theMaxErrorRatio = value;
00435 }
00436
00437 GET_METHOD( Real, MaxErrorRatio )
00438 {
00439 return theMaxErrorRatio;
00440 }
00441
00442
00443
00444
00445
00446 SET_METHOD( Integer, EpsilonChecked )
00447 {
00448 if ( value > 0 ) {
00449 theEpsilonChecked = true;
00450 }
00451 else {
00452 theEpsilonChecked = false;
00453 }
00454 }
00455
00456 const Integer isEpsilonChecked() const
00457 {
00458 return theEpsilonChecked;
00459 }
00460
00461 SET_METHOD( Real, AbsoluteEpsilon )
00462 {
00463 theAbsoluteEpsilon = value;
00464 }
00465
00466 GET_METHOD( Real, AbsoluteEpsilon )
00467 {
00468 return theAbsoluteEpsilon;
00469 }
00470
00471 SET_METHOD( Real, RelativeEpsilon )
00472 {
00473 theRelativeEpsilon = value;
00474 }
00475
00476 GET_METHOD( Real, RelativeEpsilon )
00477 {
00478 return theRelativeEpsilon;
00479 }
00480
00481 virtual void initialize();
00482 virtual void step();
00483 virtual bool calculate() = 0;
00484
00485 virtual GET_METHOD( Integer, Stage )
00486 {
00487 return 2;
00488 }
00489
00490 private:
00491
00492 Real safety;
00493 Real theTolerance;
00494 Real theAbsoluteToleranceFactor;
00495 Real theStateToleranceFactor;
00496 Real theDerivativeToleranceFactor;
00497
00498 bool theEpsilonChecked;
00499 Real theAbsoluteEpsilon;
00500 Real theRelativeEpsilon;
00501
00502 Real theMaxErrorRatio;
00503 };
00504
00505
00506 }
00507
00508 #endif
00509
00510
00511
00512
00513
00514
00515
00516
00517