#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) { fdt =timeStep; fepsilon = maxRelError; fepsilonDeriv = maxRelToSpeedError; fepsilonAbs = maxAbsoluteError; fsc = specificCharge; feField = eField; fbField = bField; fbFieldCyl = NULL; ffriction = friction; fconstE_flag = false; fconstB_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) { fdt =timeStep; fepsilon = maxRelError; fepsilonDeriv = maxRelToSpeedError; fepsilonAbs = maxAbsoluteError; fsc = specificCharge; feField = new PndTpcEFieldCyl(eFieldFile); fbFieldCyl = new PndTpcEFieldCyl(bFieldFile); fbField=NULL; ffriction = friction; fconstE_flag = false; fconstB_flag = false; init(); } PndTpcRungeKutta::~PndTpcRungeKutta() { delete feField; if(fbField!=NULL) delete fbField; if(fbFieldCyl!=NULL) delete fbFieldCyl; } bool PndTpcRungeKutta::stepForwards(double* aP) { double aPcopy[6]; for (int j=0; j<6; j++) { aPcopy[j]=aP[j]; } //steping forwards by fdt 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] = fepsilon*std::fabs(aPcopy[j])+ fepsilonDeriv*fdt* std::fabs(deriv[j]) + fepsilonAbs; } //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) fdt = 0.95*fdt*1.5; else fdt = 0.95*fdt*std::pow((worstDim),0.2); return(true);//the step was succesfull } //case the error was to big else { fdt=0.95*fdt*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(!fconstB_flag){ if(fbField!=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.; fbField->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 = fbField->GetBx(aP[3]*100., aP[4]*100., aP[5]*100.)*0.1; // bFieldY = fbField->GetBy(aP[3]*100., aP[4]*100., aP[5]*100.)*0.1; // bFieldZ = fbField->GetBz(aP[3]*100., aP[4]*100., aP[5]*100.)*0.1; } if(fbFieldCyl!=NULL) { //use PndTpcEFieldCyl for B field representation bFieldValue = fbFieldCyl->value(TVector3(aP[3]*100., aP[4]*100., aP[5]*100.)); bFieldX = bFieldValue.X(); bFieldY = bFieldValue.Y(); bFieldZ = bFieldValue.Z(); } } else { bFieldValue = fconstB; bFieldX = bFieldValue.X(); bFieldY = bFieldValue.Y(); bFieldZ = bFieldValue.Z(); } fdglmat[0][1] = bFieldZ * fsc; fdglmat[0][2] = -bFieldY * fsc; fdglmat[1][0] = -bFieldZ * fsc; fdglmat[1][2] = bFieldX * fsc; fdglmat[2][0] = bFieldY * fsc; fdglmat[2][3] = -bFieldX * fsc; // read in E field ------------------------------------------------ TVector3 fieldValue; if(! fconstE_flag) { // //fefield at the right point [V/m] fieldValue = feField->value(TVector3(aP[3]*100.,aP[4]*100.,aP[5]*100.))*100.; } else fieldValue = fconstE; fdgladd[0] = fieldValue.X() *fsc; fdgladd[1] = fieldValue.Y() *fsc; fdgladd[2] = fieldValue.Z() *fsc; //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