@@ -757,15 +757,6 @@ void SpaceCharge<DataT>::calcGlobalDistCorrIterative(const DistCorrInterpolator<
757757 const DataT radius = getRVertex (iR, side);
758758 for (unsigned int iZ = 1 ; iZ < mParamGrid .NZVertices ; ++iZ) {
759759 const DataT z = getZVertex (iZ, side);
760-
761- unsigned int nearestiZ = iZ;
762- unsigned int nearestiR = iR;
763- unsigned int nearestiPhi = iPhi;
764-
765- DataT nearestZ = getZVertex (nearestiZ, side);
766- DataT nearestR = getRVertex (nearestiR, side);
767- DataT nearestPhi = getPhiVertex (nearestiPhi, side);
768-
769760 //
770761 // ==========================================================================================
771762 // ==== start algorithm: use tricubic upsampling to numerically approach the query point ====
@@ -774,9 +765,9 @@ void SpaceCharge<DataT>::calcGlobalDistCorrIterative(const DistCorrInterpolator<
774765 // 1. calculate difference from nearest point to query point with stepwidth factor x
775766 // and approach the new point
776767 //
777- DataT stepR = (radius - nearestR) * approachR ;
778- DataT stepZ = (z - nearestZ) * approachZ ;
779- DataT stepPhi = (phi - nearestPhi) * approachPhi ;
768+ DataT stepR = 0 ;
769+ DataT stepZ = 0 ;
770+ DataT stepPhi = 0 ;
780771
781772 // needed to check for convergence
782773 DataT lastCorrdR = std::numeric_limits<DataT>::max ();
@@ -790,9 +781,9 @@ void SpaceCharge<DataT>::calcGlobalDistCorrIterative(const DistCorrInterpolator<
790781
791782 for (int iter = 0 ; iter < maxIter; ++iter) {
792783 // 2. get new point coordinates
793- const DataT rCurrPos = getRVertex (nearestiR, side) + stepR;
794- const DataT zCurrPos = getZVertex (nearestiZ, side) + stepZ;
795- const DataT phiCurrPos = getPhiVertex (nearestiPhi, side) + stepPhi;
784+ const DataT rCurrPos = radius + stepR;
785+ const DataT zCurrPos = z + stepZ;
786+ const DataT phiCurrPos = phi + stepPhi;
796787
797788 // abort calculation of drift path if electron reached inner/outer field cage or central electrode
798789 if (rCurrPos <= getRMinSim (side) || rCurrPos >= getRMaxSim (side) || getSide (zCurrPos) != side) {
@@ -867,6 +858,177 @@ void SpaceCharge<DataT>::calcGlobalDistCorrIterative(const DistCorrInterpolator<
867858 }
868859}
869860
861+ template <typename DataT>
862+ void SpaceCharge<DataT>::calcGlobalDistWithGlobalCorrIterativeLinearCartesian(const Side side, const SpaceCharge<DataT>* scSCale, float scale, const int maxIter, const DataT approachX, const DataT approachY, const DataT approachZ, const DataT diffCorr)
863+ {
864+ calcGlobalDistCorrIterativeLinearCartesian (getGlobalCorrInterpolator (side), maxIter, approachX, approachY, approachZ, diffCorr, scSCale, scale, Type::Distortions);
865+ }
866+
867+ template <typename DataT>
868+ void SpaceCharge<DataT>::calcGlobalDistWithGlobalCorrIterativeLinearCartesian(const SpaceCharge<DataT>* scSCale, float scale, const int maxIter, const DataT approachX, const DataT approachY, const DataT approachZ, const DataT diffCorr)
869+ {
870+ #pragma omp parallel for num_threads(sNThreads)
871+ for (int iside = 0 ; iside < FNSIDES; ++iside) {
872+ const o2::tpc::Side side = (iside == 0 ) ? Side::A : Side::C;
873+ calcGlobalDistWithGlobalCorrIterativeLinearCartesian (side, scSCale, scale, maxIter, approachX, approachY, approachZ, diffCorr);
874+ }
875+ }
876+
877+ template <typename DataT>
878+ void SpaceCharge<DataT>::calcGlobalCorrWithGlobalDistIterativeLinearCartesian(const Side side, const SpaceCharge<DataT>* scSCale, float scale, const int maxIter, const DataT approachX, const DataT approachY, const DataT approachZ, const DataT diffCorr)
879+ {
880+ calcGlobalDistCorrIterativeLinearCartesian (getGlobalDistInterpolator (side), maxIter, approachX, approachY, approachZ, diffCorr, scSCale, scale, Type::Corrections);
881+ }
882+
883+ template <typename DataT>
884+ void SpaceCharge<DataT>::calcGlobalCorrWithGlobalDistIterativeLinearCartesian(const SpaceCharge<DataT>* scSCale, float scale, const int maxIter, const DataT approachX, const DataT approachY, const DataT approachZ, const DataT diffCorr)
885+ {
886+ #pragma omp parallel for num_threads(sNThreads)
887+ for (int iside = 0 ; iside < FNSIDES; ++iside) {
888+ const o2::tpc::Side side = (iside == 0 ) ? Side::A : Side::C;
889+ calcGlobalCorrWithGlobalDistIterativeLinearCartesian (side, scSCale, scale, maxIter, approachX, approachY, approachZ, diffCorr);
890+ }
891+ }
892+
893+ template <typename DataT>
894+ void SpaceCharge<DataT>::calcGlobalDistCorrIterativeLinearCartesian(const DistCorrInterpolator<DataT>& globCorr, const int maxIter, const DataT approachX, const DataT approachY, const DataT approachZ, const DataT diffCorr, const SpaceCharge<DataT>* scSCale, float scale, const Type type)
895+ {
896+ const Side side = globCorr.getSide ();
897+ if (type == Type::Distortions) {
898+ initContainer (mGlobalDistdR [side], true );
899+ initContainer (mGlobalDistdZ [side], true );
900+ initContainer (mGlobalDistdRPhi [side], true );
901+ } else {
902+ initContainer (mGlobalCorrdR [side], true );
903+ initContainer (mGlobalCorrdZ [side], true );
904+ initContainer (mGlobalCorrdRPhi [side], true );
905+ }
906+
907+ const auto & scSCaleInterpolator = (type == Type::Distortions) ? scSCale->mInterpolatorGlobalCorr [side] : scSCale->mInterpolatorGlobalDist [side];
908+
909+ #pragma omp parallel for num_threads(sNThreads)
910+ for (unsigned int iPhi = 0 ; iPhi < mParamGrid .NPhiVertices ; ++iPhi) {
911+ const DataT phi = getPhiVertex (iPhi, side);
912+ for (unsigned int iR = 0 ; iR < mParamGrid .NRVertices ; ++iR) {
913+ const DataT radius = getRVertex (iR, side);
914+ const DataT x = getXFromPolar (radius, phi);
915+ const DataT y = getYFromPolar (radius, phi);
916+
917+ for (unsigned int iZ = 1 ; iZ < mParamGrid .NZVertices ; ++iZ) {
918+ const DataT z = getZVertex (iZ, side);
919+
920+ DataT stepX = 0 ;
921+ DataT stepY = 0 ;
922+ DataT stepZ = 0 ;
923+
924+ // needed to check for convergence
925+ DataT lastCorrX = std::numeric_limits<DataT>::max ();
926+ DataT lastCorrY = std::numeric_limits<DataT>::max ();
927+ DataT lastCorrZ = std::numeric_limits<DataT>::max ();
928+ DataT lastX = std::numeric_limits<DataT>::max ();
929+ DataT lastY = std::numeric_limits<DataT>::max ();
930+ DataT lastZ = std::numeric_limits<DataT>::max ();
931+
932+ for (int iter = 0 ; iter < maxIter; ++iter) {
933+ const DataT xCurrPos = x + stepX;
934+ const DataT yCurrPos = y + stepY;
935+ const DataT zCurrPos = z + stepZ;
936+
937+ // abort calculation of drift path if electron reached inner/outer field cage or central electrode
938+ const DataT rCurrPos = getRadiusFromCartesian (xCurrPos, yCurrPos);
939+ if (rCurrPos <= getRMinSim (side) || rCurrPos >= getRMaxSim (side) || getSide (zCurrPos) != side) {
940+ break ;
941+ }
942+
943+ // interpolate global correction at new point and calculate position of global correction
944+ DataT corrX = 0 ;
945+ DataT corrY = 0 ;
946+ DataT corrZ = 0 ;
947+ (type == Type::Distortions) ? getCorrections (xCurrPos, yCurrPos, zCurrPos, side, corrX, corrY, corrZ) : getDistortions (xCurrPos, yCurrPos, zCurrPos, side, corrX, corrY, corrZ);
948+
949+ if (scSCale && scale != 0 ) {
950+ DataT corrXScale = 0 ;
951+ DataT corrYScale = 0 ;
952+ DataT corrZScale = 0 ;
953+ (type == Type::Distortions) ? scSCale->getCorrections (xCurrPos, yCurrPos, zCurrPos, side, corrXScale, corrYScale, corrZScale) : getDistortions (xCurrPos, yCurrPos, zCurrPos, side, corrX, corrY, corrZ);
954+ corrX += scale * corrXScale;
955+ corrY += scale * corrYScale;
956+ corrZ += scale * corrZScale;
957+ }
958+
959+ // check for convergence
960+ const DataT diffCorrX = std::abs (corrX - lastCorrX);
961+ const DataT diffCorrY = std::abs (corrY - lastCorrY);
962+ const DataT diffCorrZ = std::abs (corrZ - lastCorrZ);
963+
964+ lastCorrX = corrX;
965+ lastCorrY = corrY;
966+ lastCorrZ = corrZ;
967+ lastX = xCurrPos;
968+ lastY = yCurrPos;
969+ lastZ = zCurrPos;
970+
971+ // stop algorithm if converged
972+ if ((diffCorrX < diffCorr) && (diffCorrY < diffCorr) && (diffCorrZ < diffCorr)) {
973+ break ;
974+ }
975+
976+ const DataT xNewPos = xCurrPos + corrX;
977+ const DataT yNewPos = yCurrPos + corrY;
978+ const DataT zNewPos = zCurrPos + corrZ;
979+
980+ // approach desired coordinate
981+ stepX += (x - xNewPos) * approachX;
982+ stepY += (y - yNewPos) * approachY;
983+ stepZ += (z - zNewPos) * approachZ;
984+ }
985+
986+ const DataT xNew = lastX + lastCorrX;
987+ const DataT yNew = lastY + lastCorrY;
988+ const DataT radiusNew = getRadiusFromCartesian (xNew, yNew);
989+ const DataT corrdR = -(radiusNew - getRadiusFromCartesian (lastX, lastY));
990+
991+ float phiNew = getPhiFromCartesian (xNew, yNew);
992+ o2::math_utils::bringTo02PiGen (phiNew);
993+
994+ float phiLast = getPhiFromCartesian (lastX, lastY);
995+ o2::math_utils::bringTo02PiGen (phiLast);
996+
997+ DataT deltaPhi = (phiNew - phiLast);
998+ // handle edge cases
999+ if (deltaPhi > PI) {
1000+ deltaPhi -= 2 * PI;
1001+ } else if (deltaPhi < -PI) {
1002+ deltaPhi += 2 * PI;
1003+ }
1004+ const DataT corrdRPhi = -deltaPhi * radiusNew;
1005+
1006+ // set global distortions if algorithm converged or iterations exceed max numbers of iterations
1007+ if (type == Type::Distortions) {
1008+ mGlobalDistdR [side](iZ, iR, iPhi) = corrdR;
1009+ mGlobalDistdRPhi [side](iZ, iR, iPhi) = corrdRPhi;
1010+ mGlobalDistdZ [side](iZ, iR, iPhi) = -lastCorrZ;
1011+ } else {
1012+ mGlobalCorrdR [side](iZ, iR, iPhi) = corrdR;
1013+ mGlobalCorrdRPhi [side](iZ, iR, iPhi) = corrdRPhi;
1014+ mGlobalCorrdZ [side](iZ, iR, iPhi) = -lastCorrZ;
1015+ }
1016+ }
1017+ }
1018+ for (unsigned int iR = 0 ; iR < mParamGrid .NRVertices ; ++iR) {
1019+ if (type == Type::Distortions) {
1020+ mGlobalDistdR [side](0 , iR, iPhi) = 3 * (mGlobalDistdR [side](1 , iR, iPhi) - mGlobalDistdR [side](2 , iR, iPhi)) + mGlobalDistdR [side](3 , iR, iPhi);
1021+ mGlobalDistdRPhi [side](0 , iR, iPhi) = 3 * (mGlobalDistdRPhi [side](1 , iR, iPhi) - mGlobalDistdRPhi [side](2 , iR, iPhi)) + mGlobalDistdRPhi [side](3 , iR, iPhi);
1022+ mGlobalDistdZ [side](0 , iR, iPhi) = 3 * (mGlobalDistdZ [side](1 , iR, iPhi) - mGlobalDistdZ [side](2 , iR, iPhi)) + mGlobalDistdZ [side](3 , iR, iPhi);
1023+ } else {
1024+ mGlobalCorrdR [side](0 , iR, iPhi) = 3 * (mGlobalCorrdR [side](1 , iR, iPhi) - mGlobalCorrdR [side](2 , iR, iPhi)) + mGlobalCorrdR [side](3 , iR, iPhi);
1025+ mGlobalCorrdRPhi [side](0 , iR, iPhi) = 3 * (mGlobalCorrdRPhi [side](1 , iR, iPhi) - mGlobalCorrdRPhi [side](2 , iR, iPhi)) + mGlobalCorrdRPhi [side](3 , iR, iPhi);
1026+ mGlobalCorrdZ [side](0 , iR, iPhi) = 3 * (mGlobalCorrdZ [side](1 , iR, iPhi) - mGlobalCorrdZ [side](2 , iR, iPhi)) + mGlobalCorrdZ [side](3 , iR, iPhi);
1027+ }
1028+ }
1029+ }
1030+ }
1031+
8701032template <typename DataT>
8711033NumericalFields<DataT> SpaceCharge<DataT>::getElectricFieldsInterpolator(const Side side) const
8721034{
0 commit comments