CLHEP VERSION Reference Documentation
CLHEP Home Page CLHEP Documentation CLHEP Bug Reports |
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