@@ -909,6 +909,136 @@ void SpaceCharge<DataT, Nz, Nr, Nphi>::calcLocalDistortionCorrectionVector(const
909909 mIsLocalVecDistSet [side] = true ;
910910}
911911
912+ template <typename DataT, size_t Nz, size_t Nr, size_t Nphi>
913+ template <typename ElectricFields>
914+ void SpaceCharge<DataT, Nz, Nr, Nphi>::calcLocalDistortionsCorrectionsRK4(const SpaceCharge<DataT, Nz, Nr, Nphi>::Type type, const Side side)
915+ {
916+ // see: https://en.wikipedia.org/wiki/Runge%E2%80%93Kutta_methods
917+ // calculate local distortions/corrections for each vertex in the tpc using Runge Kutta 4 method
918+ #pragma omp parallel for num_threads(sNThreads)
919+ for (size_t iPhi = 0 ; iPhi < Nphi; ++iPhi) {
920+ const DataT phi = getPhiVertex (iPhi, side);
921+ for (size_t iR = 0 ; iR < Nr; ++iR) {
922+ const DataT radius = getRVertex (iR, side);
923+ for (size_t iZ = 0 ; iZ < Nz - 1 ; ++iZ) {
924+ // set z coordinate depending on distortions or correction calculation
925+ const size_t iZ0 = type == Type::Corrections ? iZ + 1 : iZ;
926+ const size_t iZ1 = type == Type::Corrections ? iZ : iZ + 1 ;
927+
928+ const DataT z0 = getZVertex (iZ0, side);
929+ const DataT z1 = getZVertex (iZ1, side);
930+
931+ const DataT stepSize = z1 - z0; // h in the RK4 method
932+ const DataT absstepSize = std::abs (stepSize);
933+
934+ const DataT stepSizeHalf = 0.5 * stepSize; // half z bin for RK4
935+ const DataT absstepSizeHalf = std::abs (stepSizeHalf);
936+
937+ // starting position for RK4
938+ const DataT zk1 = z0;
939+ const DataT rk1 = radius;
940+ const DataT phik1 = phi;
941+
942+ DataT k1dR = 0 ; // derivative in r direction
943+ DataT k1dZ = 0 ; // derivative in z direction
944+ DataT k1dRPhi = 0 ; // derivative in rphi direction
945+
946+ // get derivative on current vertex
947+ switch (type) {
948+ case Type::Corrections:
949+ k1dR = getLocalVecCorrR (iZ0, iR, iPhi, side);
950+ k1dZ = getLocalVecCorrZ (iZ0, iR, iPhi, side);
951+ k1dRPhi = getLocalVecCorrRPhi (iZ0, iR, iPhi, side);
952+ break ;
953+
954+ case Type::Distortions:
955+ k1dR = getLocalVecDistR (iZ0, iR, iPhi, side);
956+ k1dZ = getLocalVecDistZ (iZ0, iR, iPhi, side);
957+ k1dRPhi = getLocalVecDistRPhi (iZ0, iR, iPhi, side);
958+ break ;
959+ }
960+
961+ // approximate position after half stepSize
962+ const DataT zk2 = zk1 + stepSizeHalf + absstepSizeHalf * k1dZ;
963+ const DataT rk2 = rk1 + absstepSizeHalf * k1dR;
964+ const DataT k1dPhi = k1dRPhi / rk1;
965+ const DataT phik2 = phik1 + absstepSizeHalf * k1dPhi;
966+
967+ // get derivative for new position
968+ DataT k2dR = 0 ;
969+ DataT k2dZ = 0 ;
970+ DataT k2dRPhi = 0 ;
971+ type == Type::Corrections ? getLocalCorrectionVectorCyl (zk2, rk2, phik2, side, k2dZ, k2dR, k2dRPhi) : getLocalDistortionVectorCyl (zk2, rk2, phik2, side, k2dZ, k2dR, k2dRPhi);
972+
973+ // approximate new position
974+ const DataT zk3 = zk1 + stepSizeHalf + absstepSizeHalf * k2dZ;
975+ const DataT rk3 = rk1 + absstepSizeHalf * k2dR;
976+ const DataT k2dPhi = k2dRPhi / rk2;
977+ const DataT phik3 = phik1 + absstepSizeHalf * k2dPhi;
978+
979+ DataT k3dR = 0 ;
980+ DataT k3dZ = 0 ;
981+ DataT k3dRPhi = 0 ;
982+ type == Type::Corrections ? getLocalCorrectionVectorCyl (zk3, rk3, phik3, side, k3dZ, k3dR, k3dRPhi) : getLocalDistortionVectorCyl (zk3, rk3, phik3, side, k3dZ, k3dR, k3dRPhi);
983+
984+ const DataT zk4 = zk1 + stepSize + absstepSize * k3dZ;
985+ const DataT rk4 = rk1 + absstepSize * k3dR;
986+ const DataT k3dPhi = k3dRPhi / rk3;
987+ const DataT phik4 = phik1 + absstepSize * k3dPhi;
988+
989+ DataT k4dR = 0 ;
990+ DataT k4dZ = 0 ;
991+ DataT k4dRPhi = 0 ;
992+ type == Type::Corrections ? getLocalCorrectionVectorCyl (zk4, rk4, phik4, side, k4dZ, k4dR, k4dRPhi) : getLocalDistortionVectorCyl (zk4, rk4, phik4, side, k4dZ, k4dR, k4dRPhi);
993+ const DataT k4dPhi = k4dRPhi / rk4;
994+
995+ // RK4 formula. See wikipedia: u = h * 1/6 * (k1 + 2*k2 + 2*k3 + k4)
996+ const DataT stepsizeSixth = absstepSize / 6 ;
997+ const DataT drRK = stepsizeSixth * (k1dR + 2 * k2dR + 2 * k3dR + k4dR);
998+ const DataT dzRK = stepsizeSixth * (k1dZ + 2 * k2dZ + 2 * k3dZ + k4dZ);
999+ const DataT dphiRK = stepsizeSixth * (k1dPhi + 2 * k2dPhi + 2 * k3dPhi + k4dPhi);
1000+
1001+ // store local distortions/corrections
1002+ switch (type) {
1003+ case Type::Corrections:
1004+ mLocalCorrdR [side](iZ + 1 , iR, iPhi) = drRK;
1005+ mLocalCorrdRPhi [side](iZ + 1 , iR, iPhi) = dphiRK * radius;
1006+ mLocalCorrdZ [side](iZ + 1 , iR, iPhi) = dzRK;
1007+ break ;
1008+
1009+ case Type::Distortions:
1010+ mLocalDistdR [side](iZ, iR, iPhi) = drRK;
1011+ mLocalDistdRPhi [side](iZ, iR, iPhi) = dphiRK * radius;
1012+ mLocalDistdZ [side](iZ, iR, iPhi) = dzRK;
1013+ break ;
1014+ }
1015+ }
1016+ // extrapolate local distortion/correction to last/first bin using legendre polynoms with x0=0, x1=1, x2=2 and x=-1. This has to be done to ensure correct interpolation in the last,second last/first,second bin!
1017+ switch (type) {
1018+ case Type::Corrections:
1019+ mLocalCorrdR [side](0 , iR, iPhi) = 3 * (mLocalCorrdR [side](1 , iR, iPhi) - mLocalCorrdR [side](2 , iR, iPhi)) + mLocalCorrdR [side](3 , iR, iPhi);
1020+ mLocalCorrdRPhi [side](0 , iR, iPhi) = 3 * (mLocalCorrdRPhi [side](1 , iR, iPhi) - mLocalCorrdRPhi [side](2 , iR, iPhi)) + mLocalCorrdRPhi [side](3 , iR, iPhi);
1021+ mLocalCorrdZ [side](0 , iR, iPhi) = 3 * (mLocalCorrdZ [side](1 , iR, iPhi) - mLocalCorrdZ [side](2 , iR, iPhi)) + mLocalCorrdZ [side](3 , iR, iPhi);
1022+ break ;
1023+
1024+ case Type::Distortions:
1025+ mLocalDistdR [side](Nz - 1 , iR, iPhi) = 3 * (mLocalDistdR [side](Nz - 2 , iR, iPhi) - mLocalDistdR [side](Nz - 3 , iR, iPhi)) + mLocalDistdR [side](Nz - 4 , iR, iPhi);
1026+ mLocalDistdRPhi [side](Nz - 1 , iR, iPhi) = 3 * (mLocalDistdRPhi [side](Nz - 2 , iR, iPhi) - mLocalDistdRPhi [side](Nz - 3 , iR, iPhi)) + mLocalDistdRPhi [side](Nz - 4 , iR, iPhi);
1027+ mLocalDistdZ [side](Nz - 1 , iR, iPhi) = 3 * (mLocalDistdZ [side](Nz - 2 , iR, iPhi) - mLocalDistdZ [side](Nz - 3 , iR, iPhi)) + mLocalDistdZ [side](Nz - 4 , iR, iPhi);
1028+ break ;
1029+ }
1030+ }
1031+ }
1032+ switch (type) {
1033+ case Type::Corrections:
1034+ mIsLocalCorrSet [side] = true ;
1035+ break ;
1036+ case Type::Distortions:
1037+ mIsLocalDistSet [side] = true ;
1038+ break ;
1039+ }
1040+ }
1041+
9121042template <typename DataT, size_t Nz, size_t Nr, size_t Nphi>
9131043template <typename Fields>
9141044void SpaceCharge<DataT, Nz, Nr, Nphi>::calcGlobalDistortions(const Fields& formulaStruct)
@@ -1150,6 +1280,22 @@ void SpaceCharge<DataT, Nz, Nr, Nphi>::getLocalDistortionsCyl(const DataT z, con
11501280 ldistRPhi = mInterpolatorLocalDist [side].evaldRPhi (z, r, phi);
11511281}
11521282
1283+ template <typename DataT, size_t Nz, size_t Nr, size_t Nphi>
1284+ void SpaceCharge<DataT, Nz, Nr, Nphi>::getLocalDistortionVectorCyl(const DataT z, const DataT r, const DataT phi, const Side side, DataT& lvecdistZ, DataT& lvecdistR, DataT& lvecdistRPhi) const
1285+ {
1286+ lvecdistZ = mInterpolatorLocalVecDist [side].evaldZ (z, r, phi);
1287+ lvecdistR = mInterpolatorLocalVecDist [side].evaldR (z, r, phi);
1288+ lvecdistRPhi = mInterpolatorLocalVecDist [side].evaldRPhi (z, r, phi);
1289+ }
1290+
1291+ template <typename DataT, size_t Nz, size_t Nr, size_t Nphi>
1292+ void SpaceCharge<DataT, Nz, Nr, Nphi>::getLocalCorrectionVectorCyl(const DataT z, const DataT r, const DataT phi, const Side side, DataT& lveccorrZ, DataT& lveccorrR, DataT& lveccorrRPhi) const
1293+ {
1294+ lveccorrZ = -mInterpolatorLocalVecDist [side].evaldZ (z, r, phi);
1295+ lveccorrR = -mInterpolatorLocalVecDist [side].evaldR (z, r, phi);
1296+ lveccorrRPhi = -mInterpolatorLocalVecDist [side].evaldRPhi (z, r, phi);
1297+ }
1298+
11531299template <typename DataT, size_t Nz, size_t Nr, size_t Nphi>
11541300void SpaceCharge<DataT, Nz, Nr, Nphi>::getDistortionsCyl(const DataT z, const DataT r, const DataT phi, const Side side, DataT& distZ, DataT& distR, DataT& distRPhi) const
11551301{
@@ -1233,6 +1379,7 @@ template void O2TPCSpaceCharge3DCalc129D::calcLocalDistortionsCorrections(const
12331379template void O2TPCSpaceCharge3DCalc129D::calcLocalDistortionsCorrections (const O2TPCSpaceCharge3DCalc129D::Type, const AnaFields129D&);
12341380template void O2TPCSpaceCharge3DCalc129D::calcLocalDistortionCorrectionVector (const NumFields129D&);
12351381template void O2TPCSpaceCharge3DCalc129D::calcLocalDistortionCorrectionVector (const AnaFields129D&);
1382+ template void O2TPCSpaceCharge3DCalc129D::calcLocalDistortionsCorrectionsRK4 (const O2TPCSpaceCharge3DCalc129D::Type, o2::tpc::Side);
12361383template void O2TPCSpaceCharge3DCalc129D::calcGlobalCorrections (const NumFields129D&);
12371384template void O2TPCSpaceCharge3DCalc129D::calcGlobalCorrections (const AnaFields129D&);
12381385template void O2TPCSpaceCharge3DCalc129D::calcGlobalCorrections (const DistCorrInterp129D&);
@@ -1251,6 +1398,7 @@ template void O2TPCSpaceCharge3DCalc33D::calcLocalDistortionsCorrections(const O
12511398template void O2TPCSpaceCharge3DCalc33D::calcLocalDistortionsCorrections (const O2TPCSpaceCharge3DCalc33D::Type, const AnaFields33D&);
12521399template void O2TPCSpaceCharge3DCalc33D::calcLocalDistortionCorrectionVector (const NumFields33D&);
12531400template void O2TPCSpaceCharge3DCalc33D::calcLocalDistortionCorrectionVector (const AnaFields33D&);
1401+ template void O2TPCSpaceCharge3DCalc33D::calcLocalDistortionsCorrectionsRK4 (const O2TPCSpaceCharge3DCalc33D::Type, o2::tpc::Side);
12541402template void O2TPCSpaceCharge3DCalc33D::calcGlobalCorrections (const NumFields33D&);
12551403template void O2TPCSpaceCharge3DCalc33D::calcGlobalCorrections (const AnaFields33D&);
12561404template void O2TPCSpaceCharge3DCalc33D::calcGlobalCorrections (const DistCorrInterp33D&);
@@ -1269,6 +1417,7 @@ template void O2TPCSpaceCharge3DCalc65D::calcLocalDistortionsCorrections(const O
12691417template void O2TPCSpaceCharge3DCalc65D::calcLocalDistortionsCorrections (const O2TPCSpaceCharge3DCalc65D::Type, const AnaFields65D&);
12701418template void O2TPCSpaceCharge3DCalc65D::calcLocalDistortionCorrectionVector (const NumFields65D&);
12711419template void O2TPCSpaceCharge3DCalc65D::calcLocalDistortionCorrectionVector (const AnaFields65D&);
1420+ template void O2TPCSpaceCharge3DCalc65D::calcLocalDistortionsCorrectionsRK4 (const O2TPCSpaceCharge3DCalc65D::Type, o2::tpc::Side);
12721421template void O2TPCSpaceCharge3DCalc65D::calcGlobalCorrections (const NumFields65D&);
12731422template void O2TPCSpaceCharge3DCalc65D::calcGlobalCorrections (const AnaFields65D&);
12741423template void O2TPCSpaceCharge3DCalc65D::calcGlobalCorrections (const DistCorrInterp65D&);
@@ -1287,6 +1436,7 @@ template void O2TPCSpaceCharge3DCalc17D::calcLocalDistortionsCorrections(const O
12871436template void O2TPCSpaceCharge3DCalc17D::calcLocalDistortionsCorrections (const O2TPCSpaceCharge3DCalc17D::Type, const AnaFields17D&);
12881437template void O2TPCSpaceCharge3DCalc17D::calcLocalDistortionCorrectionVector (const NumFields17D&);
12891438template void O2TPCSpaceCharge3DCalc17D::calcLocalDistortionCorrectionVector (const AnaFields17D&);
1439+ template void O2TPCSpaceCharge3DCalc17D::calcLocalDistortionsCorrectionsRK4 (const O2TPCSpaceCharge3DCalc17D::Type, o2::tpc::Side);
12901440template void O2TPCSpaceCharge3DCalc17D::calcGlobalCorrections (const NumFields17D&);
12911441template void O2TPCSpaceCharge3DCalc17D::calcGlobalCorrections (const AnaFields17D&);
12921442template void O2TPCSpaceCharge3DCalc17D::calcGlobalCorrections (const DistCorrInterp17D&);
@@ -1305,6 +1455,7 @@ template void O2TPCSpaceCharge3DCalc257D::calcLocalDistortionsCorrections(const
13051455template void O2TPCSpaceCharge3DCalc257D::calcLocalDistortionsCorrections (const O2TPCSpaceCharge3DCalc257D::Type, const AnaFields257D&);
13061456template void O2TPCSpaceCharge3DCalc257D::calcLocalDistortionCorrectionVector (const NumFields257D&);
13071457template void O2TPCSpaceCharge3DCalc257D::calcLocalDistortionCorrectionVector (const AnaFields257D&);
1458+ template void O2TPCSpaceCharge3DCalc257D::calcLocalDistortionsCorrectionsRK4 (const O2TPCSpaceCharge3DCalc257D::Type, o2::tpc::Side);
13081459template void O2TPCSpaceCharge3DCalc257D::calcGlobalCorrections (const NumFields257D&);
13091460template void O2TPCSpaceCharge3DCalc257D::calcGlobalCorrections (const AnaFields257D&);
13101461template void O2TPCSpaceCharge3DCalc257D::calcGlobalCorrections (const DistCorrInterp257D&);
@@ -1323,6 +1474,7 @@ template void O2TPCSpaceCharge3DCalc257360D::calcLocalDistortionsCorrections(con
13231474template void O2TPCSpaceCharge3DCalc257360D::calcLocalDistortionsCorrections (const O2TPCSpaceCharge3DCalc257360D::Type, const AnaFields257360D&);
13241475template void O2TPCSpaceCharge3DCalc257360D::calcLocalDistortionCorrectionVector (const NumFields257360D&);
13251476template void O2TPCSpaceCharge3DCalc257360D::calcLocalDistortionCorrectionVector (const AnaFields257360D&);
1477+ template void O2TPCSpaceCharge3DCalc257360D::calcLocalDistortionsCorrectionsRK4 (const O2TPCSpaceCharge3DCalc257360D::Type, o2::tpc::Side);
13261478template void O2TPCSpaceCharge3DCalc257360D::calcGlobalCorrections (const NumFields257360D&);
13271479template void O2TPCSpaceCharge3DCalc257360D::calcGlobalCorrections (const AnaFields257360D&);
13281480template void O2TPCSpaceCharge3DCalc257360D::calcGlobalCorrections (const DistCorrInterp257360D&);
0 commit comments