LArSoft  v10_04_05
Liquid Argon Software toolkit - https://larsoft.org/
OpFastScintillation.hh
Go to the documentation of this file.
1 // Class adapted for LArSoft by Ben Jones, MIT 10/10/12
2 //
3 // This class is a physics process based on the standard Geant4 scintillation process.
4 //
5 // It has been stripped down and adapted to form the backbone of the LArG4 fast optical
6 // simulation. Photons, instead of being produced and added to the geant4 particle stack,
7 // are logged and used to predict the visibility of this step to each PMT in the detector.
8 //
9 // The photonvisibilityservice looks up the visibility of the relevant xyz point, and if a
10 // photon is detected at a given PMT, one OnePhoton object is logged in the
11 // OpDetPhotonTable
12 //
13 // At the end of the event, the OpDetPhotonTable is read out by LArG4, and detected
14 // photons are stored in the event.
15 //
16 // This process can be used alongside the standard Cerenkov process, which does step
17 // geant4 opticalphotons. Both the fast scintillation table and the geant4 sensitive
18 // detectors are read out by LArG4 to produce a combined SimPhoton collection.
19 
20 #ifndef OpFastScintillation_h
21 #define OpFastScintillation_h 1
22 
25 #include "larcoreobj/SimpleTypesAndConstants/geo_vectors.h" // geo::Point_t
26 #include "larsim/PhotonPropagation/PhotonVisibilityTypes.h" // phot::MappedT0s_t
27 
28 #include "Geant4/G4ForceCondition.hh"
29 #include "Geant4/G4ParticleDefinition.hh"
30 #include "Geant4/G4PhysicsOrderedFreeVector.hh"
31 #include "Geant4/G4PhysicsTable.hh"
32 #include "Geant4/G4ProcessType.hh"
33 #include "Geant4/G4String.hh"
34 #include "Geant4/G4ThreeVector.hh"
35 #include "Geant4/G4Types.hh"
36 #include "Geant4/G4VRestDiscreteProcess.hh"
37 
38 #include "TF1.h"
39 #include "TVector3.h"
40 
41 #include <memory> // std::unique_ptr
42 
43 class G4EmSaturation;
44 class G4Step;
45 class G4Track;
46 class G4VParticleChange;
47 namespace CLHEP {
48  class RandGeneral;
49 }
50 namespace phot {
51  class PhotonVisibilityService;
52 }
53 
54 namespace larg4 {
55 
56  class OpFastScintillation : public G4VRestDiscreteProcess {
57  public:
58  OpFastScintillation(const G4String& processName = "Scintillation",
59  G4ProcessType type = fElectromagnetic);
60 
62 
63  // OpFastScintillation Process has both PostStepDoIt (for energy deposition of
64  // particles in flight) and AtRestDoIt (for energy given to the medium by particles at
65  // rest)
66 
67  virtual G4bool IsApplicable(const G4ParticleDefinition& aParticleType);
68  // Returns true -> 'is applicable', for any particle type except for an
69  // 'opticalphoton' and for short-lived particles
70 
71  G4double GetMeanFreePath(const G4Track& aTrack, G4double, G4ForceCondition*);
72  // Returns infinity; i. e. the process does not limit the step, but sets the
73  // 'StronglyForced' condition for the DoIt to be invoked at every step.
74 
75  G4double GetMeanLifeTime(const G4Track& aTrack, G4ForceCondition*);
76  // Returns infinity; i. e. the process does not limit the time, but sets the
77  // 'StronglyForced' condition for the DoIt to be invoked at every step.
78 
79  virtual G4VParticleChange* PostStepDoIt(const G4Track& aTrack, const G4Step& aStep);
80  virtual G4VParticleChange* AtRestDoIt(const G4Track& aTrack, const G4Step& aStep);
81 
82  // These are the methods implementing the scintillation process.
83 
84  void SetTrackSecondariesFirst(const G4bool state);
85  // If set, the primary particle tracking is interrupted and any produced scintillation
86  // photons are tracked next. When all have been tracked, the tracking of the primary
87  // resumes.
88 
89  void SetFiniteRiseTime(const G4bool state);
90  // If set, the OpFastScintillation process expects the user to have set the constant
91  // material property FAST/SLOWSCINTILLATIONRISETIME.
92 
93  G4bool GetTrackSecondariesFirst() const;
94  // Returns the boolean flag for tracking secondaries first.
95 
96  G4bool GetFiniteRiseTime() const;
97  // Returns the boolean flag for a finite scintillation rise time.
98 
99  void SetScintillationYieldFactor(const G4double yieldfactor);
100  // Called to set the scintillation photon yield factor, needed when the yield is
101  // different for different types of particles. This scales the yield obtained from the
102  // G4MaterialPropertiesTable.
103 
104  G4double GetScintillationYieldFactor() const;
105  // Returns the photon yield factor.
106 
107  void SetScintillationExcitationRatio(const G4double excitationratio);
108  // Called to set the scintillation exciation ratio, needed when the scintillation
109  // level excitation is different for different types of particles. This overwrites the
110  // YieldRatio obtained from the G4MaterialPropertiesTable.
111 
112  G4double GetScintillationExcitationRatio() const;
113  // Returns the scintillation level excitation ratio.
114 
115  G4PhysicsTable* GetFastIntegralTable() const;
116  // Returns the address of the fast scintillation integral table.
117 
118  G4PhysicsTable* GetSlowIntegralTable() const;
119  // Returns the address of the slow scintillation integral table.
120 
121  void AddSaturation(G4EmSaturation* sat) { emSaturation = sat; }
122  // Adds Birks Saturation to the process.
123 
124  void RemoveSaturation() { emSaturation = NULL; }
125  // Removes the Birks Saturation from the process.
126 
127  G4EmSaturation* GetSaturation() const { return emSaturation; }
128  // Returns the Birks Saturation.
129 
130  void SetScintillationByParticleType(const G4bool);
131  // Called by the user to set the scintillation yield as a function of energy deposited
132  // by particle type
133 
134  G4bool GetScintillationByParticleType() const { return scintillationByParticleType; }
135  // Return the boolean that determines the method of scintillation production
136 
137  void DumpPhysicsTable() const;
138  // Prints the fast and slow scintillation integral tables.
139 
140  void getVUVTimes(std::vector<double>& arrivalTimes,
141  const double distance_in_cm,
142  const size_t angle_bin);
143  void generateParam(const size_t index, const size_t angle_bin);
144  // Functions for vuv component Landau + Exponential timing parameterisation, updated
145  // method
146 
147  void getVISTimes(std::vector<double>& arrivalTimes,
148  const TVector3& ScintPoint,
149  const TVector3& OpDetPoint);
150  // Visible component timing parameterisation
151 
152  void detectedDirectHits(std::map<size_t, int>& DetectedNum,
153  const double Num,
154  geo::Point_t const& ScintPoint) const;
155  void detectedReflecHits(std::map<size_t, int>& ReflDetectedNum,
156  const double Num,
157  geo::Point_t const& ScintPoint) const;
158 
159  protected:
160  void BuildThePhysicsTable();
161  // It builds either the fast or slow scintillation integral table; or both.
162 
163  bool RecordPhotonsProduced(const G4Step& aStep, double N);
164  // Note the production of N photons in at point xyz. pass on to generate detector
165  // response, etc.
166 
167  std::unique_ptr<G4PhysicsTable> theSlowIntegralTable;
168  std::unique_ptr<G4PhysicsTable> theFastIntegralTable;
169 
172 
173  G4double YieldFactor;
174 
175  G4double ExcitationRatio;
176 
178 
179  private:
181  double h; // height
182  double w; // width
184  int type;
185  };
186 
188  bool usesSemiAnalyticModel() const;
189 
190  int VUVHits(const double Nphotons_created,
191  geo::Point_t const& ScintPoint,
192  OpticalDetector const& opDet) const;
193  // Calculates semi-analytic model number of hits for vuv component
194 
195  int VISHits(geo::Point_t const& ScintPoint,
196  OpticalDetector const& opDet,
197  const double cathode_hits_rec,
198  const std::array<double, 3> hotspot) const;
199  // Calculates semi-analytic model number of hits for visible component
200 
201  G4double single_exp(const G4double t, const G4double tau2) const;
202  G4double bi_exp(const G4double t, const G4double tau1, const G4double tau2) const;
203 
204  G4double scint_time(const G4Step& aStep,
205  G4double ScintillationTime,
206  G4double ScintillationRiseTime) const;
207  void propagationTime(std::vector<double>& arrival_time_dist,
208  G4ThreeVector x0,
209  const size_t OpChannel,
210  bool Reflected = false); //const;
211 
212  // emission time distribution when there is a finite rise time
213  G4double sample_time(const G4double tau1, const G4double tau2) const;
214 
215  // Facility for TPB emission energies
216  double reemission_energy() const;
217  std::map<double, double> tpbemission;
218  std::unique_ptr<CLHEP::RandGeneral> fTPBEm;
219 
220  void average_position(G4Step const& aStep, double* xzyPos) const;
221 
222  G4EmSaturation* emSaturation;
223  // functions and parameters for the propagation time parametrization
226 
227  //For new VUV time parametrization
228  double fstep_size, fmin_d, fmax_d, fvuv_vgroup_mean, fvuv_vgroup_max, finflexion_point_distance,
229  fangle_bin_timing_vuv;
230  std::vector<std::vector<double>> fparameters[7];
231  // vector containing generated VUV timing parameterisations
232  std::vector<std::vector<TF1>> VUV_timing;
233  // vector containing min and max range VUV timing parameterisations are sampled to
234  std::vector<std::vector<double>> VUV_max;
235  std::vector<std::vector<double>> VUV_min;
236 
237  // For new VIS time parameterisation
238  double fvis_vmean, fangle_bin_timing_vis;
239  std::vector<double> fdistances_refl;
240  std::vector<double> fradial_distances_refl;
241  std::vector<std::vector<std::vector<double>>> fcut_off_pars;
242  std::vector<std::vector<std::vector<double>>> ftau_pars;
243 
244  struct Dims {
245  double h, w; // height, width
246  };
247 
248  // solid angle of rectangular aperture calculation functions
249  double Rectangle_SolidAngle(const double a, const double b, const double d) const;
250  double Rectangle_SolidAngle(Dims const& o, const std::array<double, 3> v) const;
251  // solid angle of circular aperture calculation functions
252  double Disk_SolidAngle(const double d, const double h, const double b) const;
253  // solid angle of a dome aperture calculation functions
254  double Omega_Dome_Model(const double distance, const double theta) const;
255 
256  // For VUV semi-analytic hits
257  // Gaisser-Hillas correction parameters for VUV Nhits estimation
258  G4double Gaisser_Hillas(const double x, const double* par) const;
260  // flat PDs
262  std::vector<std::vector<double>> fGHvuvpars_flat;
263  std::vector<double> fborder_corr_angulo_flat;
264  std::vector<std::vector<double>> fborder_corr_flat;
265  // dome PDs
267  std::vector<std::vector<double>> fGHvuvpars_dome;
268  std::vector<double> fborder_corr_angulo_dome;
269  std::vector<std::vector<double>> fborder_corr_dome;
270 
271  // For VIS semi-analytic hits
273  // correction parameters for VIS Nhits estimation
275  // flat PDs
276  std::vector<double> fvis_distances_x_flat;
277  std::vector<double> fvis_distances_r_flat;
278  std::vector<std::vector<std::vector<double>>> fvispars_flat;
279  // dome PDs
280  std::vector<double> fvis_distances_x_dome;
281  std::vector<double> fvis_distances_r_dome;
282  std::vector<std::vector<std::vector<double>>> fvispars_dome;
283 
284  // geometry properties
285  double fplane_depth, fcathode_zdimension, fcathode_ydimension;
287  std::vector<geo::BoxBoundedGeo> const fActiveVolumes;
288 
289  // Optical detector properties for semi-analytic hits
290  double fradius;
293  std::vector<geo::Point_t> fOpDetCenter;
294  std::vector<int> fOpDetType;
295  std::vector<double> fOpDetLength;
296  std::vector<double> fOpDetHeight;
297  //double fGlobalTimeOffset;
298 
299  void ProcessStep(const G4Step& step);
300 
301  bool const bPropagate;
302 
305 
307  bool const fUseNhitsModel = false;
309  bool const fOnlyActiveVolume = false;
312  bool const fOnlyOneCryostat = false;
314  bool const fOpaqueCathode = false;
315 
316  bool isOpDetInSameTPC(geo::Point_t const& ScintPoint, geo::Point_t const& OpDetPoint) const;
317  bool isScintInActiveVolume(geo::Point_t const& ScintPoint);
318  double interpolate(const std::vector<double>& xData,
319  const std::vector<double>& yData,
320  double x,
321  bool extrapolate,
322  size_t i = 0) const;
323  void interpolate3(std::array<double, 3>& inter,
324  const std::vector<double>& xData,
325  const std::vector<double>& yData1,
326  const std::vector<double>& yData2,
327  const std::vector<double>& yData3,
328  double x,
329  bool extrapolate) const;
330 
331  static std::vector<geo::BoxBoundedGeo> extractActiveVolumes(geo::GeometryCore const& geom);
332 
333  }; // class OpFastScintillation
334 
335  inline G4bool OpFastScintillation::IsApplicable(const G4ParticleDefinition& aParticleType)
336  {
337  if (aParticleType.GetParticleName() == "opticalphoton") return false;
338  if (aParticleType.IsShortLived()) return false;
339 
340  return true;
341  }
342 
343  inline void OpFastScintillation::SetTrackSecondariesFirst(const G4bool state)
344  {
345  fTrackSecondariesFirst = state;
346  }
347 
348  inline void OpFastScintillation::SetFiniteRiseTime(const G4bool state)
349  {
350  fFiniteRiseTime = state;
351  }
352 
353  inline G4bool OpFastScintillation::GetTrackSecondariesFirst() const
354  {
355  return fTrackSecondariesFirst;
356  }
357 
358  inline G4bool OpFastScintillation::GetFiniteRiseTime() const
359  {
360  return fFiniteRiseTime;
361  }
362 
363  inline void OpFastScintillation::SetScintillationYieldFactor(const G4double yieldfactor)
364  {
365  YieldFactor = yieldfactor;
366  }
367 
368  inline G4double OpFastScintillation::GetScintillationYieldFactor() const
369  {
370  return YieldFactor;
371  }
372 
373  inline void OpFastScintillation::SetScintillationExcitationRatio(const G4double excitationratio)
374  {
375  ExcitationRatio = excitationratio;
376  }
377 
378  inline G4double OpFastScintillation::GetScintillationExcitationRatio() const
379  {
380  return ExcitationRatio;
381  }
382 
383  inline G4PhysicsTable* OpFastScintillation::GetSlowIntegralTable() const
384  {
385  return theSlowIntegralTable.get();
386  }
387 
388  inline G4PhysicsTable* OpFastScintillation::GetFastIntegralTable() const
389  {
390  return theFastIntegralTable.get();
391  }
392 
393  inline void OpFastScintillation::DumpPhysicsTable() const
394  {
395  if (theFastIntegralTable) {
396  G4int PhysicsTableSize = theFastIntegralTable->entries();
397  G4PhysicsOrderedFreeVector* v;
398  for (G4int i = 0; i < PhysicsTableSize; i++) {
399  v = (G4PhysicsOrderedFreeVector*)(*theFastIntegralTable)[i];
400  v->DumpValues();
401  }
402  }
403  if (theSlowIntegralTable) {
404  G4int PhysicsTableSize = theSlowIntegralTable->entries();
405  G4PhysicsOrderedFreeVector* v;
406  for (G4int i = 0; i < PhysicsTableSize; i++) {
407  v = (G4PhysicsOrderedFreeVector*)(*theSlowIntegralTable)[i];
408  v->DumpValues();
409  }
410  }
411  }
412 
413  template <typename TReal>
414  inline double dist(const TReal* x, const TReal* y, const unsigned int dimension)
415  {
416  double d = 0.;
417  for (unsigned int p = 0; p < dimension; ++p) {
418  d += (*(x + p) - *(y + p)) * (*(x + p) - *(y + p));
419  }
420  return std::sqrt(d);
421  }
422 
423  template <typename TVector3>
424  inline double dist(const std::array<double, 3> x,
425  const TVector3 y,
426  const unsigned int dimension,
427  const unsigned int start)
428  {
429  double d = 0.;
430  for (unsigned int p = start; p < dimension; ++p) {
431  d += (x[p] - y[p]) * (x[p] - y[p]);
432  }
433  return std::sqrt(d);
434  }
435 
436  // implements relative method - do not use for comparing with zero
437  // use this most of the time, tolerance needs to be meaningful in your context
438  template <typename TReal>
439  inline constexpr static bool
440  isApproximatelyEqual(TReal a, TReal b, TReal tolerance = std::numeric_limits<TReal>::epsilon())
441  {
442  TReal diff = std::fabs(a - b);
443  if (diff <= tolerance) return true;
444  if (diff < std::fmax(std::fabs(a), std::fabs(b)) * tolerance) return true;
445  return false;
446  }
447 
448  // supply tolerance that is meaningful in your context
449  // for example, default tolerance may not work if you are comparing double with float
450  template <typename TReal>
451  inline constexpr static bool isApproximatelyZero(
452  TReal a,
453  TReal tolerance = std::numeric_limits<TReal>::epsilon())
454  {
455  if (std::fabs(a) <= tolerance) return true;
456  return false;
457  }
458 
459  // use this when you want to be on safe side
460  // for example, don't start rover unless signal is above 1
461  template <typename TReal>
462  inline constexpr static bool
463  isDefinitelyLessThan(TReal a, TReal b, TReal tolerance = std::numeric_limits<TReal>::epsilon())
464  {
465  TReal diff = a - b;
466  if (diff < tolerance) return true;
467  if (diff < std::fmax(std::fabs(a), std::fabs(b)) * tolerance) return true;
468  return false;
469  }
470 
471  template <typename TReal>
472  inline constexpr static bool
473  isDefinitelyGreaterThan(TReal a, TReal b, TReal tolerance = std::numeric_limits<TReal>::epsilon())
474  {
475  TReal diff = a - b;
476  if (diff > tolerance) return true;
477  if (diff > std::fmax(std::fabs(a), std::fabs(b)) * tolerance) return true;
478  return false;
479  }
480 
481  // template<typename Function, typename... Args>
482  // auto OpFastScintillation::invoke_memoized(Function function, Args... args)
483  // {
484  // using key_type = std::tuple<Args...>;
485  // using value_type = std::invoke_result_t<Function, Args...>;
486  // static_assert(! std::is_same_v<Function, std::function<value_type(Args...)>>,
487  // "cannot memoize on std::function (use a lambda instead)");
488  // static_assert(! std::is_same_v<Function, value_type(*)(Args...)>,
489  // "cannot memoize on function pointer (use a lambda instead)");
490  // static std::mutex mutex;
491  // static std::map<key_type, value_type> cache;
492  // auto key = std::tuple(args...);
493  // auto lock = std::lock_guard<std::mutex>(mutex);
494  // if (cache.count(key)){
495  // return cache[key];
496  // }
497  // return cache[key] = std::apply(function, key);
498  // }
499 
500 } // namespace larg4
501 
502 #endif /* OpFastScintillation_h */
Float_t x
Definition: compare.C:6
std::vector< std::vector< std::vector< double > > > fvispars_dome
G4EmSaturation * GetSaturation() const
std::vector< geo::Point_t > fOpDetCenter
void interpolate3(std::array< double, 3 > &inter, const std::vector< double > &xData, const std::vector< double > &yData1, const std::vector< double > &yData2, const std::vector< double > &yData3, const double x, const bool extrapolate)
std::vector< double > fOpDetHeight
Float_t y
Definition: compare.C:6
std::map< double, double > tpbemission
std::vector< std::vector< std::vector< double > > > fvispars_flat
Geant4 interface.
std::vector< double > fvis_distances_r_flat
std::vector< double > fdistances_refl
std::unique_ptr< G4PhysicsTable > theSlowIntegralTable
std::vector< std::vector< TF1 > > VUV_timing
std::vector< std::vector< double > > fGHvuvpars_flat
std::vector< std::vector< double > > VUV_min
std::vector< std::vector< double > > fGHvuvpars_dome
std::vector< double > fborder_corr_angulo_dome
constexpr unsigned int dimension()
bool const bPropagate
Whether propagation of photons is enabled.
std::vector< std::vector< double > > fborder_corr_dome
std::vector< std::vector< double > > fborder_corr_flat
std::vector< double > fvis_distances_x_flat
std::vector< double > fborder_corr_angulo_flat
std::vector< double > fOpDetLength
Definitions of geometry vector data types.
std::unique_ptr< CLHEP::RandGeneral > fTPBEm
std::vector< geo::BoxBoundedGeo > const fActiveVolumes
std::vector< std::vector< std::vector< double > > > ftau_pars
Float_t d
Definition: plot.C:235
double dist(const std::array< double, 3 > x, const TVector3 y, const unsigned int dimension, const unsigned int start)
G4bool GetScintillationByParticleType() const
Description of the physical geometry of one entire detector.
Definition: GeometryCore.h:91
static constexpr bool isDefinitelyGreaterThan(TReal a, TReal b, TReal tolerance=std::numeric_limits< TReal >::epsilon())
Provides a base class aware of world box coordinates.
std::vector< double > fradial_distances_refl
std::vector< double > fvis_distances_r_dome
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:180
General LArSoft Utilities.
std::vector< std::vector< std::vector< double > > > fcut_off_pars
A container for photon visibility mapping data.
static constexpr bool isApproximatelyEqual(TReal a, TReal b, TReal tolerance=std::numeric_limits< TReal >::epsilon())
std::vector< double > fvis_distances_x_dome
Declaration of types related to photon visibility.
phot::PhotonVisibilityService const *const fPVS
Photon visibility service instance.
std::vector< std::vector< double > > VUV_max
void AddSaturation(G4EmSaturation *sat)
static constexpr bool isDefinitelyLessThan(TReal a, TReal b, TReal tolerance=std::numeric_limits< TReal >::epsilon())
phot::MappedFunctions_t ParPropTimeTF1
double interpolate(const std::vector< double > &xData, const std::vector< double > &yData, const double x, const bool extrapolate, size_t i)
static constexpr bool isApproximatelyZero(TReal a, TReal tolerance=std::numeric_limits< TReal >::epsilon())
std::unique_ptr< G4PhysicsTable > theFastIntegralTable