Skip to content

Commit f4e3199

Browse files
matthias-kleinerdavidrohr
authored andcommitted
SpaceCharge: adding Runge Kutta 4 method for local distortions/corrections
1 parent 7274677 commit f4e3199

2 files changed

Lines changed: 181 additions & 0 deletions

File tree

Detectors/TPC/spacecharge/include/TPCSpaceCharge/SpaceCharge.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,13 @@ class SpaceCharge
140140
template <typename ElectricFields = AnalyticalFields<DataT>>
141141
void calcLocalDistortionCorrectionVector(const ElectricFields& formulaStruct);
142142

143+
/// step 3b: calculate the local distortions and corrections with the local distortion/correction vectors using Runge Kutta 4.
144+
/// calcLocalDistortionCorrectionVector() has to be called before this function
145+
/// \param type calculate local corrections or local distortions: type = o2::tpc::SpaceCharge<>::Type::Distortions or o2::tpc::SpaceCharge<>::Type::Corrections
146+
/// \param side side of the TPC
147+
template <typename ElectricFields = AnalyticalFields<DataT>>
148+
void calcLocalDistortionsCorrectionsRK4(const Type type, const Side side);
149+
143150
/// step 4: calculate global corrections by using the electric field or the local corrections
144151
/// \param formulaStruct struct containing a method to evaluate the electric field Er, Ez, Ephi or the local corrections
145152
template <typename Fields = AnalyticalFields<DataT>>
@@ -218,6 +225,24 @@ class SpaceCharge
218225
/// \param ldistRPhi returns local distortion in rphi direction
219226
void getLocalDistortionsCyl(const DataT z, const DataT r, const DataT phi, const Side side, DataT& ldistZ, DataT& ldistR, DataT& ldistRPhi) const;
220227

228+
/// get the local distortion vector for given coordinate
229+
/// \param z global z coordinate
230+
/// \param r global r coordinate
231+
/// \param phi global phi coordinate
232+
/// \param lvecdistZ returns local distortion vector in z direction
233+
/// \param lvecdistR returns local distortion vector in r direction
234+
/// \param lvecdistRPhi returns local distortion vector in rphi direction
235+
void getLocalDistortionVectorCyl(const DataT z, const DataT r, const DataT phi, const Side side, DataT& lvecdistZ, DataT& lvecdistR, DataT& lvecdistRPhi) const;
236+
237+
/// get the local correction vector for given coordinate
238+
/// \param z global z coordinate
239+
/// \param r global r coordinate
240+
/// \param phi global phi coordinate
241+
/// \param ldistZ returns local correction vector in z direction
242+
/// \param ldistR returns local correction vector in r direction
243+
/// \param ldistRPhi returns local correction vector in rphi direction
244+
void getLocalCorrectionVectorCyl(const DataT z, const DataT r, const DataT phi, const Side side, DataT& lveccorrZ, DataT& lveccorrR, DataT& lveccorrRPhi) const;
245+
221246
/// get the global distortions for given coordinate
222247
/// \param z global z coordinate
223248
/// \param r global r coordinate
@@ -754,6 +779,10 @@ class SpaceCharge
754779
{mLocalDistdR[Side::A], mLocalDistdZ[Side::A], mLocalDistdRPhi[Side::A], mGrid3D[Side::A], Side::A},
755780
{mLocalDistdR[Side::C], mLocalDistdZ[Side::C], mLocalDistdRPhi[Side::C], mGrid3D[Side::C], Side::C}}; ///< interpolator for the local distortions
756781

782+
DistCorrInterpolator<DataT, Nz, Nr, Nphi> mInterpolatorLocalVecDist[FNSIDES]{
783+
{mLocalVecDistdR[Side::A], mLocalVecDistdZ[Side::A], mLocalVecDistdRPhi[Side::A], mGrid3D[Side::A], Side::A},
784+
{mLocalVecDistdR[Side::C], mLocalVecDistdZ[Side::C], mLocalVecDistdRPhi[Side::C], mGrid3D[Side::C], Side::C}}; ///< interpolator for the local distortion vectors
785+
757786
NumericalFields<DataT, Nz, Nr, Nphi> mInterpolatorEField[FNSIDES]{
758787
{mElectricFieldEr[Side::A], mElectricFieldEz[Side::A], mElectricFieldEphi[Side::A], mGrid3D[Side::A], Side::A},
759788
{mElectricFieldEr[Side::C], mElectricFieldEz[Side::C], mElectricFieldEphi[Side::C], mGrid3D[Side::C], Side::C}}; ///< interpolator for the electric fields

Detectors/TPC/spacecharge/src/SpaceCharge.cxx

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
9121042
template <typename DataT, size_t Nz, size_t Nr, size_t Nphi>
9131043
template <typename Fields>
9141044
void 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+
11531299
template <typename DataT, size_t Nz, size_t Nr, size_t Nphi>
11541300
void 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
12331379
template void O2TPCSpaceCharge3DCalc129D::calcLocalDistortionsCorrections(const O2TPCSpaceCharge3DCalc129D::Type, const AnaFields129D&);
12341380
template void O2TPCSpaceCharge3DCalc129D::calcLocalDistortionCorrectionVector(const NumFields129D&);
12351381
template void O2TPCSpaceCharge3DCalc129D::calcLocalDistortionCorrectionVector(const AnaFields129D&);
1382+
template void O2TPCSpaceCharge3DCalc129D::calcLocalDistortionsCorrectionsRK4(const O2TPCSpaceCharge3DCalc129D::Type, o2::tpc::Side);
12361383
template void O2TPCSpaceCharge3DCalc129D::calcGlobalCorrections(const NumFields129D&);
12371384
template void O2TPCSpaceCharge3DCalc129D::calcGlobalCorrections(const AnaFields129D&);
12381385
template void O2TPCSpaceCharge3DCalc129D::calcGlobalCorrections(const DistCorrInterp129D&);
@@ -1251,6 +1398,7 @@ template void O2TPCSpaceCharge3DCalc33D::calcLocalDistortionsCorrections(const O
12511398
template void O2TPCSpaceCharge3DCalc33D::calcLocalDistortionsCorrections(const O2TPCSpaceCharge3DCalc33D::Type, const AnaFields33D&);
12521399
template void O2TPCSpaceCharge3DCalc33D::calcLocalDistortionCorrectionVector(const NumFields33D&);
12531400
template void O2TPCSpaceCharge3DCalc33D::calcLocalDistortionCorrectionVector(const AnaFields33D&);
1401+
template void O2TPCSpaceCharge3DCalc33D::calcLocalDistortionsCorrectionsRK4(const O2TPCSpaceCharge3DCalc33D::Type, o2::tpc::Side);
12541402
template void O2TPCSpaceCharge3DCalc33D::calcGlobalCorrections(const NumFields33D&);
12551403
template void O2TPCSpaceCharge3DCalc33D::calcGlobalCorrections(const AnaFields33D&);
12561404
template void O2TPCSpaceCharge3DCalc33D::calcGlobalCorrections(const DistCorrInterp33D&);
@@ -1269,6 +1417,7 @@ template void O2TPCSpaceCharge3DCalc65D::calcLocalDistortionsCorrections(const O
12691417
template void O2TPCSpaceCharge3DCalc65D::calcLocalDistortionsCorrections(const O2TPCSpaceCharge3DCalc65D::Type, const AnaFields65D&);
12701418
template void O2TPCSpaceCharge3DCalc65D::calcLocalDistortionCorrectionVector(const NumFields65D&);
12711419
template void O2TPCSpaceCharge3DCalc65D::calcLocalDistortionCorrectionVector(const AnaFields65D&);
1420+
template void O2TPCSpaceCharge3DCalc65D::calcLocalDistortionsCorrectionsRK4(const O2TPCSpaceCharge3DCalc65D::Type, o2::tpc::Side);
12721421
template void O2TPCSpaceCharge3DCalc65D::calcGlobalCorrections(const NumFields65D&);
12731422
template void O2TPCSpaceCharge3DCalc65D::calcGlobalCorrections(const AnaFields65D&);
12741423
template void O2TPCSpaceCharge3DCalc65D::calcGlobalCorrections(const DistCorrInterp65D&);
@@ -1287,6 +1436,7 @@ template void O2TPCSpaceCharge3DCalc17D::calcLocalDistortionsCorrections(const O
12871436
template void O2TPCSpaceCharge3DCalc17D::calcLocalDistortionsCorrections(const O2TPCSpaceCharge3DCalc17D::Type, const AnaFields17D&);
12881437
template void O2TPCSpaceCharge3DCalc17D::calcLocalDistortionCorrectionVector(const NumFields17D&);
12891438
template void O2TPCSpaceCharge3DCalc17D::calcLocalDistortionCorrectionVector(const AnaFields17D&);
1439+
template void O2TPCSpaceCharge3DCalc17D::calcLocalDistortionsCorrectionsRK4(const O2TPCSpaceCharge3DCalc17D::Type, o2::tpc::Side);
12901440
template void O2TPCSpaceCharge3DCalc17D::calcGlobalCorrections(const NumFields17D&);
12911441
template void O2TPCSpaceCharge3DCalc17D::calcGlobalCorrections(const AnaFields17D&);
12921442
template void O2TPCSpaceCharge3DCalc17D::calcGlobalCorrections(const DistCorrInterp17D&);
@@ -1305,6 +1455,7 @@ template void O2TPCSpaceCharge3DCalc257D::calcLocalDistortionsCorrections(const
13051455
template void O2TPCSpaceCharge3DCalc257D::calcLocalDistortionsCorrections(const O2TPCSpaceCharge3DCalc257D::Type, const AnaFields257D&);
13061456
template void O2TPCSpaceCharge3DCalc257D::calcLocalDistortionCorrectionVector(const NumFields257D&);
13071457
template void O2TPCSpaceCharge3DCalc257D::calcLocalDistortionCorrectionVector(const AnaFields257D&);
1458+
template void O2TPCSpaceCharge3DCalc257D::calcLocalDistortionsCorrectionsRK4(const O2TPCSpaceCharge3DCalc257D::Type, o2::tpc::Side);
13081459
template void O2TPCSpaceCharge3DCalc257D::calcGlobalCorrections(const NumFields257D&);
13091460
template void O2TPCSpaceCharge3DCalc257D::calcGlobalCorrections(const AnaFields257D&);
13101461
template void O2TPCSpaceCharge3DCalc257D::calcGlobalCorrections(const DistCorrInterp257D&);
@@ -1323,6 +1474,7 @@ template void O2TPCSpaceCharge3DCalc257360D::calcLocalDistortionsCorrections(con
13231474
template void O2TPCSpaceCharge3DCalc257360D::calcLocalDistortionsCorrections(const O2TPCSpaceCharge3DCalc257360D::Type, const AnaFields257360D&);
13241475
template void O2TPCSpaceCharge3DCalc257360D::calcLocalDistortionCorrectionVector(const NumFields257360D&);
13251476
template void O2TPCSpaceCharge3DCalc257360D::calcLocalDistortionCorrectionVector(const AnaFields257360D&);
1477+
template void O2TPCSpaceCharge3DCalc257360D::calcLocalDistortionsCorrectionsRK4(const O2TPCSpaceCharge3DCalc257360D::Type, o2::tpc::Side);
13261478
template void O2TPCSpaceCharge3DCalc257360D::calcGlobalCorrections(const NumFields257360D&);
13271479
template void O2TPCSpaceCharge3DCalc257360D::calcGlobalCorrections(const AnaFields257360D&);
13281480
template void O2TPCSpaceCharge3DCalc257360D::calcGlobalCorrections(const DistCorrInterp257360D&);

0 commit comments

Comments
 (0)