Skip to content

Commit cba7551

Browse files
Ernst Hellbarsawenzel
authored andcommitted
Adding first version of constant space-charge distortions to TPC simulation. New options to enable distortions in digitizer-workflow.
1 parent db62922 commit cba7551

File tree

11 files changed

+653
-15
lines changed

11 files changed

+653
-15
lines changed

Detectors/TPC/simulation/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ set(SRCS
2626
src/PadResponse.cxx
2727
src/Point.cxx
2828
src/SAMPAProcessing.cxx
29+
src/SpaceCharge.cxx
2930
)
3031

3132
set(HEADERS
@@ -42,6 +43,7 @@ set(HEADERS
4243
include/${MODULE_NAME}/PadResponse.h
4344
include/${MODULE_NAME}/Point.h
4445
include/${MODULE_NAME}/SAMPAProcessing.h
46+
include/${MODULE_NAME}/SpaceCharge.h
4547
)
4648
Set(LINKDEF src/TPCSimulationLinkDef.h)
4749
Set(LIBRARY_NAME ${MODULE_NAME})

Detectors/TPC/simulation/include/TPCSimulation/Digitizer.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "TPCSimulation/DigitContainer.h"
1919
#include "TPCSimulation/PadResponse.h"
2020
#include "TPCSimulation/Point.h"
21+
#include "TPCSimulation/SpaceCharge.h"
2122

2223
#include "TPCBase/Mapper.h"
2324
#include "Steer/HitProcessingManager.h"
@@ -27,6 +28,7 @@
2728
using std::vector;
2829

2930
class TTree;
31+
class TH3;
3032

3133
namespace o2
3234
{
@@ -92,16 +94,26 @@ class Digitizer
9294
/// \param isContinuous - false for triggered readout, true for continuous readout
9395
static void setContinuousReadout(bool isContinuous) { mIsContinuous = isContinuous; }
9496

97+
/// Enable the use of space-charge distortions
98+
/// \param distortionType select the type of space-charge distortions (constant or realistic)
99+
/// \param hisInitialSCDensity optional space-charge density histogram to use at the beginning of the simulation
100+
/// \param nZSlices number of grid points in z, must be (2**N)+1
101+
/// \param nPhiBins number of grid points in phi
102+
/// \param nRBins number of grid points in r, must be (2**N)+1
103+
void enableSCDistortions(SpaceCharge::SCDistortionType distortionType, TH3* hisInitialSCDensity, int nZSlices, int nPhiBins, int nRBins);
104+
95105
private:
96106
Digitizer(const Digitizer&);
97107
Digitizer& operator=(const Digitizer&);
98108

99-
DigitContainer* mDigitContainer; ///< Container for the Digits
100-
static bool mIsContinuous; ///< Switch for continuous readout
109+
DigitContainer* mDigitContainer; ///< Container for the Digits
110+
std::unique_ptr<SpaceCharge> mSpaceChargeHandler; ///< Handler of space-charge distortions
111+
static bool mIsContinuous; ///< Switch for continuous readout
112+
bool mUseSCDistortions; ///< Flag to switch on the use of space-charge distortions
101113

102114
ClassDefNV(Digitizer, 1);
103115
};
104-
}
105-
}
116+
} // namespace TPC
117+
} // namespace o2
106118

107119
#endif // ALICEO2_TPC_Digitizer_H_

Detectors/TPC/simulation/include/TPCSimulation/DigitizerTask.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@
2222
#include "SimulationDataFormat/MCTruthContainer.h"
2323
#include "TPCBase/Sector.h"
2424
#include "TPCSimulation/Digitizer.h"
25+
#include "TPCSimulation/SpaceCharge.h"
2526
#include "Steer/HitProcessingManager.h"
2627

28+
class TH3;
29+
2730
namespace o2
2831
{
2932
namespace TPC
@@ -60,6 +63,14 @@ class DigitizerTask : public FairTask
6063
/// \param isContinuous - false for triggered readout, true for continuous readout
6164
void setContinuousReadout(bool isContinuous);
6265

66+
/// Enable the use of space-charge distortions
67+
/// \param distortionType select the type of space-charge distortions (constant or realistic)
68+
/// \param hisInitialSCDensity optional space-charge density histogram to use at the beginning of the simulation
69+
/// \param nZSlices number of grid points in z, must be (2**N)+1; default size 129
70+
/// \param nPhiBins number of grid points in phi; default size 180
71+
/// \param nRBins number of grid points in r, must be (2**N)+1; default size 129
72+
void enableSCDistortions(SpaceCharge::SCDistortionType distortionType, TH3* hisInitialSCDensity = nullptr, int nZSlices = 65, int nPhiBins = 180, int nRBins = 65);
73+
6374
/// Set the maximal number of written out time bins
6475
/// \param nTimeBinsMax Maximal number of time bins to be written out
6576
void setMaximalTimeBinWriteOut(int i) { mTimeBinMax = i; }
@@ -173,7 +184,7 @@ inline void DigitizerTask::setupSector(int s)
173184
mDigitsDebugArray->clear();
174185
mHitSector = s;
175186
}
176-
}
177-
}
187+
} // namespace TPC
188+
} // namespace o2
178189

179190
#endif // ALICEO2_TPC_DigitizerTask_H_
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
// Copyright CERN and copyright holders of ALICE O2. This software is
2+
// distributed under the terms of the GNU General Public License v3 (GPL
3+
// Version 3), copied verbatim in the file "COPYING".
4+
//
5+
// See http://alice-o2.web.cern.ch/license for full licensing information.
6+
//
7+
// In applying this license CERN does not waive the privileges and immunities
8+
// granted to it by virtue of its status as an Intergovernmental Organization
9+
// or submit itself to any jurisdiction.
10+
11+
/// \file SpaceCharge.h
12+
/// \brief Definition of the handler for the ALICE TPC space-charge distortions calculations
13+
/// \author Ernst Hellbär, Goethe-Universität Frankfurt, ernst.hellbar@cern.ch
14+
15+
/*
16+
* TODO:
17+
* - fix constants (more precise values, export into TPCBase/Constants)
18+
* - pad granularity in r, rphi?
19+
* - accumulate and add next slice
20+
* - event based: propagate charge(ievent-1), add charge(ievent)
21+
* - time based: mTime0, mEffectiveTime
22+
* addIons(eventtime, drifttime, r, phi)
23+
* time in us, 50 kHz = <one event / 20 us>
24+
* if (ev.time+dr.time-mTime0 < mLengthTimebin) => add2NextSlice
25+
* if (mLengthTimebin < ev.time+dr.time-mTime0 < mLengthTimebin+100us) add2NextToNextSlice
26+
* - apply updated distortions to ions in NextToNextSlice when space charge is propagated; need to store exact positions (e.g. std::vector<std::vector<float>>)!
27+
* - ion transport along the E field -> Jacobi matrices?
28+
* - what about primary ionization?
29+
* - irregular bin sizes in r and rphi
30+
* - timebins or z bins?
31+
*/
32+
33+
#ifndef ALICEO2_TPC_SPACECHARGE_H
34+
#define ALICEO2_TPC_SPACECHARGE_H
35+
36+
#include <TMatrixT.h>
37+
38+
#include "AliTPCSpaceCharge3DCalc.h"
39+
#include "DataFormatsTPC/Defs.h"
40+
41+
class TH3;
42+
class TMatrixDfwd;
43+
44+
class AliTPCLookUpTable3DInterpolatorD;
45+
46+
namespace o2
47+
{
48+
namespace TPC
49+
{
50+
51+
class SpaceCharge
52+
{
53+
public:
54+
/// Enumerator for setting the space-charge distortion mode
55+
enum SCDistortionType {
56+
SCDistortionsConstant = 0, // space-charge distortions constant over time
57+
SCDistortionsRealistic = 1 // realistic evolution of space-charge distortions over time
58+
};
59+
60+
// Constructors
61+
/// Default constructor using a grid size of (129 z bins, 180 phi bins, 129 r bins)
62+
SpaceCharge();
63+
/// Constructor with grid size specified by user
64+
/// \param nZSlices number of grid points in z, must be (2**N)+1
65+
/// \param nPhiBins number of grid points in phi
66+
/// \param nRBins number of grid points in r, must be (2**N)+1
67+
SpaceCharge(int nZSlices, int nPhiBins, int nRBins);
68+
/// Constructor with grid size and interpolation order specified by user
69+
/// \param nZSlices number of grid points in z, must be (2**N)+1
70+
/// \param nPhiBins number of grid points in phi
71+
/// \param nRBins number of grid points in r, must be (2**N)+1
72+
/// \param interpolationOrder order used for interpolation of lookup tables
73+
SpaceCharge(int nZSlices, int nPhiBins, int nRBins, int interpolationOrder);
74+
75+
// Destructor
76+
~SpaceCharge() = default;
77+
78+
/// Allocate memory for data members
79+
void allocateMemory();
80+
81+
/// Calculate lookup tables if initial space-charge density is provided
82+
void init();
83+
84+
/// Calculate distortion and correction lookup tables using AliTPCSpaceChargeCalc class
85+
void calculateLookupTables();
86+
/// Update distortion and correction lookup tables by current space-charge density
87+
/// \param eventTime time of current event
88+
void updateLookupTables(float eventTime);
89+
90+
/// Set omega*tau and T1, T2 tensor terms in Langevin-equation solution
91+
/// \param omegaTau omega*tau
92+
/// \param t1 T1 tensor term
93+
/// \param t2 T2 tensor term
94+
void setOmegaTauT1T2(float omegaTau, float t1, float t2);
95+
/// Set an initial space-charge density
96+
/// \param hisSCDensity 3D space-charge density histogram, expected format (phi,r,z)
97+
void setInitialSpaceChargeDensity(TH3* hisSCDensity);
98+
/// Add ions to space-charge density
99+
/// \param zPos z position
100+
/// \param phiPos phi position
101+
/// \param rPos radial position
102+
/// \param nIons number of ions
103+
void fillSCDensity(float zPos, float phiPos, float rPos, int nIons);
104+
/// Propagate space-charge density along electric field by one time slice
105+
void propagateSpaceCharge();
106+
/// Drift ion along electric field by one time slice
107+
/// \param point 3D coordinates of the ion
108+
/// \return GlobalPosition3D with coordinates of drifted ion
109+
GlobalPosition3D driftIon(GlobalPosition3D& point);
110+
111+
/// Correct electron position using correction lookup tables
112+
/// \param point 3D coordinates of the electron
113+
void correctElectron(GlobalPosition3D& point);
114+
/// Distort electron position using distortion lookup tables
115+
/// \param point 3D coordinates of the electron
116+
void distortElectron(GlobalPosition3D& point);
117+
118+
/// Set the space-charge distortions model
119+
/// \param distortionType distortion type (constant or realistic)
120+
void setSCDistortionType(SCDistortionType distortionType) { mSCDistortionType = distortionType; }
121+
/// Get the space-charge distortions model
122+
SCDistortionType getSCDistortionType() const { return mSCDistortionType; }
123+
124+
private:
125+
/// Convert amount of ions into charge density C/m^3
126+
/// \param nIons number of ions
127+
/// \return space-charge density (C/m^3)
128+
float ions2Charge(int nIons);
129+
130+
static constexpr float DvDEoverv0 = 0.0025; //! v'(E) / v0 = K / (K*E0) for ions, used in dz calculation
131+
static const float sEzField; //! nominal drift field
132+
133+
static constexpr int MaxZSlices = 200; //! default number of z slices (1 ms slices)
134+
static constexpr int MaxPhiBins = 360; //! default number of phi bins
135+
static constexpr float DriftLength = 250.; //! drift length of the TPC in (cm)
136+
// ion mobility K = 3.0769231 cm^2/(Vs) in Ne-CO2 90-10 published by A. Deisting
137+
// v_drift = K * E = 3.0769231 cm^2/(Vs) * 400 V/cm = 1230.7692 cm/s
138+
// t_drift = 250 cm / v_drift = 203 ms
139+
static constexpr float IonDriftTime = 2.03e5; //! drift time of ions for one full drift (us)
140+
static constexpr float RadiusInner = 85.; //! inner radius of the TPC active area
141+
static constexpr float RadiusOuter = 245.; //! outer radius of the TPC active area
142+
143+
const int mInterpolationOrder; ///< order for interpolation of lookup tables: 2==quadratic, >2==cubic spline
144+
145+
const int mNZSlices; ///< number of z slices used in lookup tables
146+
const int mNPhiBins; ///< number of phi bins used in lookup tables
147+
const int mNRBins; ///< number of r bins used in lookup tables
148+
const float mLengthZSlice; ///< length of one z bin (cm)
149+
const float mLengthTimeSlice; ///< ion drift time for one z slice (us)
150+
const float mWidthPhiBin; ///< width of one phi bin (radians)
151+
const float mLengthRBin; ///< length of one r bin (cm)
152+
153+
std::vector<double> mCoordZ; ///< vector wiht coodinates of the z bins
154+
std::vector<double> mCoordPhi; ///< vector wiht coodinates of the phi bins
155+
std::vector<double> mCoordR; ///< vector wiht coodinates of the r bins
156+
157+
bool mUseInitialSCDensity; ///< Flag for the use of an initial space-charge density at the beginning of the simulation
158+
bool mInitLookUpTables; ///< Flag to indicate if lookup tables have been calculated
159+
float mTimeInit; ///< time of last update of lookup tables
160+
SCDistortionType mSCDistortionType; ///< Type of space-charge distortions
161+
162+
AliTPCSpaceCharge3DCalc mLookUpTableCalculator; ///< object to calculate and store correction and distortion lookup tables
163+
164+
/// TODO: check fastest way to order std::vectors
165+
std::vector<std::vector<float>> mSpaceChargeDensityA; ///< space-charge density on the A side, stored in C/m^3 (z)(phi*r), ordering: z=[0,250], ir+iphi*nRBins
166+
std::vector<std::vector<float>> mSpaceChargeDensityC; ///< space-charge density on the C side, stored in C/m^3 (z)(phi*r), ordering: z=[0,-250], ir+iphi*nRBins
167+
168+
/// TODO: Eliminate the need for these matrices as members, they will be owned by AliTPCLookUpTable3DInterpolatorD. AliTPCLookUpTable3DInterpolatorD needs getters for the matrices and the constructor has to be modified.
169+
TMatrixD** mMatrixLocalIonDriftDzA; ///< matrix to store local ion drift in z direction along E field on A side
170+
TMatrixD** mMatrixLocalIonDriftDzC; ///< matrix to store local ion drift in z direction along E field on A side
171+
TMatrixD** mMatrixLocalIonDriftDrphiA; ///< matrix to store local ion drift in rphi direction along E field on A side
172+
TMatrixD** mMatrixLocalIonDriftDrphiC; ///< matrix to store local ion drift in rphi direction along E field on A side
173+
TMatrixD** mMatrixLocalIonDriftDrA; ///< matrix to store local ion drift in radial direction along E field on A side
174+
TMatrixD** mMatrixLocalIonDriftDrC; ///< matrix to store local ion drift in radial direction along E field on C side
175+
std::unique_ptr<AliTPCLookUpTable3DInterpolatorD> mLookUpLocalIonDriftA; ///< lookup table for local ion drift along E field on A side
176+
std::unique_ptr<AliTPCLookUpTable3DInterpolatorD> mLookUpLocalIonDriftC; ///< lookup table for local ion drift along E field on C side
177+
};
178+
179+
} // namespace TPC
180+
} // namespace o2
181+
182+
#endif // ALICEO2_TPC_SPACECHARGE_H

Detectors/TPC/simulation/src/Digitizer.cxx

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
/// \brief Implementation of the ALICE TPC digitizer
1313
/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de
1414

15+
#include "TH3.h"
16+
1517
#include "TPCSimulation/Digitizer.h"
1618
#include "TPCBase/ParameterDetector.h"
1719
#include "TPCBase/ParameterElectronics.h"
@@ -32,11 +34,24 @@ ClassImp(o2::TPC::Digitizer)
3234

3335
bool o2::TPC::Digitizer::mIsContinuous = true;
3436

35-
Digitizer::Digitizer() : mDigitContainer(nullptr) {}
37+
Digitizer::Digitizer()
38+
: mDigitContainer(nullptr),
39+
mSpaceChargeHandler(nullptr),
40+
mUseSCDistortions(false)
41+
{
42+
}
3643

3744
Digitizer::~Digitizer() { delete mDigitContainer; }
3845

39-
void Digitizer::init() { mDigitContainer = new DigitContainer(); }
46+
void Digitizer::init()
47+
{
48+
mDigitContainer = new DigitContainer();
49+
50+
// Calculate distortion lookup tables if initial space-charge density is provided
51+
if (mUseSCDistortions) {
52+
mSpaceChargeHandler->init();
53+
}
54+
}
4055

4156
DigitContainer* Digitizer::Process(const Sector& sector, const std::vector<o2::TPC::HitGroup>& hits, int eventID,
4257
float eventTime)
@@ -45,6 +60,9 @@ DigitContainer* Digitizer::Process(const Sector& sector, const std::vector<o2::T
4560
eventTime = 0.f;
4661
}
4762

63+
/// TODO: if eventtime-lastUpdate>=one space-charge time slice
64+
/// 1) Propagate current space-charge density
65+
/// 2) recalculate distortion lookup tables with updated space-charge density
4866
for (auto& inputgroup : hits) {
4967
ProcessHitGroup(inputgroup, sector, eventTime, eventID);
5068
}
@@ -89,7 +107,12 @@ void Digitizer::ProcessHitGroup(const HitGroup& inputgroup, const Sector& sector
89107
for (size_t hitindex = 0; hitindex < inputgroup.getSize(); ++hitindex) {
90108
const auto& eh = inputgroup.getHit(hitindex);
91109

92-
const GlobalPosition3D posEle(eh.GetX(), eh.GetY(), eh.GetZ());
110+
GlobalPosition3D posEle(eh.GetX(), eh.GetY(), eh.GetZ());
111+
112+
// Distort the electron position in case space-charge distortions are used
113+
if (mUseSCDistortions) {
114+
mSpaceChargeHandler->distortElectron(posEle);
115+
}
93116

94117
/// Remove electrons that end up more than three sigma of the hit's average diffusion away from the current sector
95118
/// boundary
@@ -100,6 +123,8 @@ void Digitizer::ProcessHitGroup(const HitGroup& inputgroup, const Sector& sector
100123
/// The energy loss stored corresponds to nElectrons
101124
const int nPrimaryElectrons = static_cast<int>(eh.GetEnergyLoss());
102125

126+
/// TODO: add primary ions to space-charge density
127+
103128
/// Loop over electrons
104129
for (int iEle = 0; iEle < nPrimaryElectrons; ++iEle) {
105130

@@ -144,7 +169,21 @@ void Digitizer::ProcessHitGroup(const HitGroup& inputgroup, const Sector& sector
144169
mDigitContainer->addDigit(label, digiPadPos.getCRU(), sampaProcessing.getTimeBinFromTime(time), globalPad,
145170
signalArray[i]);
146171
}
172+
173+
/// TODO: add ion backflow to space-charge density
147174
}
148175
/// end of loop over electrons
149176
}
150177
}
178+
179+
void Digitizer::enableSCDistortions(SpaceCharge::SCDistortionType distortionType, TH3* hisInitialSCDensity, int nZSlices, int nPhiBins, int nRBins)
180+
{
181+
mUseSCDistortions = true;
182+
if (!mSpaceChargeHandler) {
183+
mSpaceChargeHandler = std::make_unique<SpaceCharge>(nZSlices, nPhiBins, nRBins);
184+
}
185+
mSpaceChargeHandler->setSCDistortionType(distortionType);
186+
if (hisInitialSCDensity) {
187+
mSpaceChargeHandler->setInitialSpaceChargeDensity(hisInitialSCDensity);
188+
}
189+
}

0 commit comments

Comments
 (0)