#include "PndTpcRungeKutta.h" #include #include #include "TVector3.h" #include "PndTpcEFieldCyl.h" #include "PndMultiField.h" #include "PndFieldMap.h" PndTpcRungeKutta::PndTpcRungeKutta(const double timeStep, const double maxRelError, const double maxRelToSpeedError, const double maxAbsoluteError, const double specificCharge, PndTpcEFieldCyl* eField, PndMultiField* bField, const double friction) { _dt =timeStep; _epsilon = maxRelError; _epsilonDeriv = maxRelToSpeedError; _epsilonAbs = maxAbsoluteError; _sc = specificCharge; _eField = eField; _bField = bField; _bFieldCyl = NULL; _friction = friction; _constE_flag = false; _constB_flag = false; init(); } PndTpcRungeKutta::PndTpcRungeKutta(const double timeStep, const double maxRelError, const double maxRelToSpeedError, const double maxAbsoluteError, const double specificCharge, const char* eFieldFile, const char* bFieldFile, const double friction) { _dt =timeStep; _epsilon = maxRelError; _epsilonDeriv = maxRelToSpeedError; _epsilonAbs = maxAbsoluteError; _sc = specificCharge; _eField = new PndTpcEFieldCyl(eFieldFile); _bFieldCyl = new PndTpcEFieldCyl(bFieldFile); _bField=NULL; _friction = friction; _constE_flag = false; _constB_flag = false; init(); } PndTpcRungeKutta::~PndTpcRungeKutta() { delete _eField; if(_bField!=NULL) delete _bField; if(_bFieldCyl!=NULL) delete _bFieldCyl; } bool PndTpcRungeKutta::stepForwards(double* aP) { double aPcopy[6]; for (int j=0; j<6; j++) { aPcopy[j]=aP[j]; } //steping forwards by _dt double error[6]; getNextPoint(aP,error); //defining the maximal allowed error double allowedError[6]; double deriv[6]; derivates(aPcopy, deriv); for (int j=0; j<6; j++) { allowedError[j] = _epsilon*std::fabs(aPcopy[j])+ _epsilonDeriv*_dt* std::fabs(deriv[j]) + _epsilonAbs; } //is the estimated error to big? double worstDim =-1; for (int j=0; j<6; j++) { //avoid division through 0 if (error[j] <= allowedError[j]/8. ) continue; else if (worstDim > allowedError[j]/error[j] || worstDim == -1) worstDim = allowedError[j]/error[j]; } if (worstDim == -1) //error was always small enough worstDim = 8; else if (worstDim <= 0) //allowedError was one time 0 (every error is to big) { worstDim = 1;// the step will be done because repeating is useless std::cout<<"Allowed Error was 0. Could not decrease step size appropriate!"<= 1) { //never make the stepsize to big if (worstDim > 7.6) _dt = 0.95*_dt*1.5; else _dt = 0.95*_dt*std::pow((worstDim),0.2); return(true);//the step was succesfull } //case the error was to big else { _dt=0.95*_dt*std::pow(worstDim,0.25); //reset the old values for (int j=0; j<6; j++) { aP[j] = aPcopy[j]; } } return(false); //the stepping failed } void PndTpcRungeKutta::getNextPoint(double* aP, double* errorEstimate) { double k[6][6]; TVector3 bFieldValue; double bFieldX, bFieldY, bFieldZ; if(!_constB_flag){ if(_bField!=0) { //use PndMultiField double pos_temp[3]; double field_val[3]; for(int i=0; i<3; i++) pos_temp[i] = aP[i+3]*100.; _bField->GetFieldValue(pos_temp, field_val); bFieldX = field_val[0]*0.1; bFieldY = field_val[1]*0.1; bFieldZ = field_val[2]*0.1; /*FairFieldMap takes coordinates in [cm] and returns B in [kGauss] -> *0.1 ! */ // bFieldX = _bField->GetBx(aP[3]*100., aP[4]*100., aP[5]*100.)*0.1; // bFieldY = _bField->GetBy(aP[3]*100., aP[4]*100., aP[5]*100.)*0.1; // bFieldZ = _bField->GetBz(aP[3]*100., aP[4]*100., aP[5]*100.)*0.1; } if(_bFieldCyl!=NULL) { //use PndTpcEFieldCyl for B field representation bFieldValue = _bFieldCyl->value(TVector3(aP[3]*100., aP[4]*100., aP[5]*100.)); bFieldX = bFieldValue.X(); bFieldY = bFieldValue.Y(); bFieldZ = bFieldValue.Z(); } } else { bFieldValue = _constB; bFieldX = bFieldValue.X(); bFieldY = bFieldValue.Y(); bFieldZ = bFieldValue.Z(); } _dglmat[0][1] = bFieldZ * _sc; _dglmat[0][2] = -bFieldY * _sc; _dglmat[1][0] = -bFieldZ * _sc; _dglmat[1][2] = bFieldX * _sc; _dglmat[2][0] = bFieldY * _sc; _dglmat[2][3] = -bFieldX * _sc; // read in E field ------------------------------------------------ TVector3 fieldValue; if(! _constE_flag) { // //_efield at the right point [V/m] fieldValue = _eField->value(TVector3(aP[3]*100.,aP[4]*100.,aP[5]*100.))*100.; } else fieldValue = _constE; _dgladd[0] = fieldValue.X() *_sc; _dgladd[1] = fieldValue.Y() *_sc; _dgladd[2] = fieldValue.Z() *_sc; //fifth order Runge Kutta for (int i=0; i<6; i++) { double midP[6]; for (int j=0; j<6; j++) { double bdotk =0; for (int l=0; l