CLHEP VERSION Reference Documentation
   
CLHEP Home Page     CLHEP Documentation     CLHEP Bug Reports

RKIntegrator.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 // $Id: 
00003 #include "CLHEP/GenericFunctions/RKIntegrator.hh"
00004 #include "CLHEP/GenericFunctions/AdaptiveRKStepper.hh"
00005 #include "CLHEP/GenericFunctions/Variable.hh"
00006 #include <climits>
00007 #include <stdexcept>
00008 namespace Genfun {
00009 FUNCTION_OBJECT_IMP(RKIntegrator::RKFunction)
00010 
00011 RKIntegrator::RKFunction::RKFunction(RKData *data, unsigned int index)
00012   :_data(data),
00013    _index(index)
00014 {
00015   _data->ref();
00016 }
00017 
00018 RKIntegrator::RKFunction::~RKFunction() 
00019 {
00020   _data->unref();
00021 }
00022 
00023 RKIntegrator::RKFunction::RKFunction(const RKIntegrator::RKFunction & right)
00024   :AbsFunction(right),
00025    _data(right._data),
00026    _index(right._index)
00027 {
00028   _data->ref();
00029 }
00030 
00031 
00032 double RKIntegrator::RKFunction::operator() (double t) const {
00033   if (t<0) return 0;
00034   if (!_data->_locked) _data->lock();
00035 
00036   // Do this first, thereafter, just read the cache
00037   _data->recache();
00038   
00039 
00040   // If the cache is empty, make an entry for t=0;
00041   size_t nvar = _data->_startingValParameter.size();
00042   if (_data->_fx.empty()) {
00043     RKData::Data d(nvar);
00044     d.time=0;
00045     Argument arg(nvar);
00046     for (size_t f=0;f<nvar;f++) {
00047       d.variable[f]=_data->_startingValParameterCache[f];
00048       arg[f]=d.variable[f];
00049     }
00050     _data->_fx.insert(d);
00051   }
00052 
00053   if (t==0) return (*_data->_fx.begin()).variable[_index];
00054 
00055   RKData::Data dt(nvar);
00056   dt.time=t;
00057   std::set<RKData::Data>::iterator l =_data->_fx.lower_bound(dt);
00058 
00059   // We did find an exact value (measure 0), just return it. 
00060   if (l!=_data->_fx.end() && (*l).time==t) {
00061     return (*l).variable[_index];
00062   }
00063 
00064   else {
00065     std::set<RKData::Data>::iterator u =_data->_fx.upper_bound(dt);
00066     
00067     while (u==_data->_fx.end()) {
00068       u--;
00069       RKData::Data newData(nvar);;
00070       _data->_stepper->step(_data,*u, newData, 0);
00071       _data->_fx.insert(l,newData);
00072       if (newData.time==t) return newData.variable[_index];
00073       u = _data->_fx.upper_bound(dt);
00074     }
00075     u--;
00076     _data->_stepper->step(_data,*u, dt, t);
00077     return dt.variable[_index];
00078   }
00079 }
00080 
00081 
00082 RKIntegrator::RKData::RKData():_locked(false) {
00083 }
00084 
00085 RKIntegrator::RKData::~RKData() {
00086   for (size_t i=0;i<_startingValParameter.size();i++) delete _startingValParameter[i];
00087   for (size_t i=0;i<_controlParameter.size();i++)     delete _controlParameter[i];
00088   for (size_t i=0;i<_diffEqn.size();  i++)            delete _diffEqn[i];
00089   delete _stepper;
00090 }
00091 
00092 RKIntegrator::RKIntegrator(const RKIntegrator::RKStepper *stepper) :
00093   _data(new RKData())
00094 {
00095   if (stepper) _data->_stepper=stepper->clone();
00096   else _data->_stepper= new AdaptiveRKStepper();
00097   _data->ref();
00098 }
00099 
00100 RKIntegrator::~RKIntegrator() {
00101   _data->unref();
00102   for (size_t i=0;i<_fcn.size();i++) delete _fcn[i];
00103 }
00104 
00105 Parameter * RKIntegrator::addDiffEquation(const AbsFunction * diffEquation,
00106                                           const std::string &variableName,
00107                                           double defStartingValue,
00108                                           double defValueMin,
00109                                           double defValueMax) {
00110   Parameter *par = new Parameter(variableName, defStartingValue, defValueMin, defValueMax);
00111   _data->_startingValParameter.push_back(par);
00112   _data->_diffEqn.push_back(diffEquation->clone());
00113   _data->_startingValParameterCache.push_back(defStartingValue);
00114   _fcn.push_back(new RKFunction(_data,_fcn.size()));
00115   return par;
00116 }
00117 
00118 
00119 
00120 
00121 
00122 Parameter * RKIntegrator::createControlParameter (const std::string & variableName,
00123                                                   double defStartingValue,
00124                                                   double startingValueMin,
00125                                                   double startingValueMax) {
00126 
00127   Parameter *par = new Parameter(variableName, defStartingValue, startingValueMin, startingValueMax);
00128   _data->_controlParameter.push_back(par);
00129   _data->_controlParameterCache.push_back(defStartingValue);
00130   return par;
00131 
00132 }
00133 
00134 
00135 
00136 const RKIntegrator::RKFunction * RKIntegrator::getFunction(unsigned int i) const {
00137   return _fcn[i];
00138 }
00139 
00140 
00141 
00142 void RKIntegrator::RKData::lock() {
00143   if (!_locked) {
00144     unsigned int size = _diffEqn.size();
00145     for (size_t i=0;i<size;i++) {
00146       if (!(_diffEqn[i]->dimensionality()==size)) throw std::runtime_error("Runtime error in RKIntegrator");
00147     }
00148     _locked=true;
00149   }
00150 }
00151 
00152 
00153 
00154 void RKIntegrator::RKData::recache() {
00155 
00156   bool stale=false;
00157   if (!stale) {
00158     for (size_t p=0;p<_startingValParameter.size();p++) {
00159       if (_startingValParameter[p]->getValue()!=_startingValParameterCache[p]) {
00160         _startingValParameterCache[p]=_startingValParameter[p]->getValue();
00161         stale=true;
00162         break;
00163       }
00164     }
00165   }
00166 
00167   if (!stale) {
00168     for (size_t p=0;p<_controlParameter.size();p++) {
00169       if (_controlParameter[p]->getValue()!=_controlParameterCache[p]) {
00170         _controlParameterCache[p]=_controlParameter[p]->getValue();
00171         stale=true;
00172         break;
00173       }
00174     }
00175   }
00176   
00177   if (stale) {
00178     _fx.erase(_fx.begin(),_fx.end());
00179   }
00180   
00181 }
00182 
00183 
00184 
00185 RKIntegrator::RKStepper::~RKStepper(){}
00186 
00187 
00188 } // namespace Genfun

Generated on 15 Nov 2012 for CLHEP by  doxygen 1.4.7