14 #include <utl/Reader.h>
15 #include <utl/ErrorLogger.h>
16 #include <utl/AugerUnits.h>
17 #include <utl/MathConstants.h>
18 #include <utl/PhysicalConstants.h>
19 #include <utl/PhysicalFunctions.h>
20 #include <utl/TabulatedFunction.h>
21 #include <utl/TabulatedFunctionErrors.h>
22 #include <utl/Trace.h>
23 #include <utl/TraceAlgorithm.h>
24 #include <utl/Particle.h>
25 #include <utl/UTMPoint.h>
26 #include <utl/Point.h>
27 #include <utl/ReferenceEllipsoid.h>
28 #include <utl/RandomEngine.h>
29 #include <utl/config.h>
31 #include <fwk/CentralConfig.h>
32 #include <fwk/RandomEngineRegistry.h>
34 #include <evt/Event.h>
35 #include <evt/ShowerSimData.h>
36 #include <evt/VGaisserHillasParameter.h>
37 #include <evt/GaisserHillas4Parameter.h>
38 #include <evt/DefaultShowerGeometryProducer.h>
40 #include <det/Detector.h>
42 #include <fdet/FDetector.h>
43 #include <fdet/FDetector.h>
45 #include <atm/ProfileResult.h>
49 #include <CLHEP/Random/Randomize.h>
51 using namespace ProfileSimulatorOG;
60 using CLHEP::RandGauss;
61 using CLHEP::RandFlat;
62 using CLHEP::RandExponential;
80 cout <<
"ProfileSimulator::Init()" << endl;
87 ERROR(
"Could not find branch type");
94 ERROR(
"Could not find branch energyCutoff");
99 if (fProfileType == eFromEnergy) {
101 fRandomEngine = &RandomEngineRegistry::GetInstance().Get(RandomEngineRegistry::eDetector);
104 if (!generateEnergyB) {
105 ERROR(
"Could not find branch generateEnergy");
108 generateEnergyB.
GetData(fGenerateEnergy);
112 ERROR(
"Could not find branch constantX0");
122 ERROR(
"Could not find branch x0");
126 fGH.SetShapeParameter(
gh::eX0, x0, error);
131 ERROR(
"Could not find branch energyMin");
138 ERROR(
"Could not find branch energyMax");
144 if (!alphaSpectrumB) {
145 ERROR(
"Could not find branch alphaSpectrum");
148 alphaSpectrumB.
GetData(fAlphaSpectrum);
152 ERROR(
"Could not find branch xMaxSig");
161 if (fProfileType == eFromFixParameters) {
167 ERROR(
"Could not find branch x0");
171 fGH.SetShapeParameter(
gh::eX0, x0, error);
176 ERROR(
"Could not find branch xMax");
180 fGH.SetXMax(xmax, error);
185 ERROR(
"Could not find branch nMax");
189 fGH.SetNMax(nmax, error);
194 ERROR(
"This Profile Type is not available.");
206 ERROR(
"Shower sim data already exists. Cannot produce new Profile event.");
211 Detector& theDetector = Detector::GetInstance();
214 double height = 1200*
m;
220 double depthG = dvh.
Y(height);
223 if (fProfileType == eFromEnergy) {
234 double energy = DicePowerLaw(fMinEnergy, fMaxEnergy, -fAlphaSpectrum);
240 xone = RandomXOne(fPrimary, energy);
245 double xzero = RandomXZero(fPrimary, energy);
246 fGH.SetShapeParameter(
gh::eX0, xzero + xone, 0);
251 double xm = RandomXMax(fPrimary, energy);
252 fGH.SetXMax(xm + xone, 0);
259 double nm = RandomNMax(fPrimary, energy);
260 fGH.SetNMax(
pow(10, nm), 0);
268 std::vector<double> depth;
269 std::vector<double> nParticles;
271 const double depthTop = (fGH.GetShapeParameter(
gh::eX0) > 0*
g/
cm2) ?
274 const int steps = 200;
275 double deltaD = (depthG/
abs(cos(fTheta)) - depthTop) / steps;
276 double depthI = depthTop;
280 for (
int i = 0; i < steps; ++i) {
281 const double particles =
289 double deposit = dEdX*particles;
295 INFO (
"Longitudinal profile filled");
298 INFO (
"Shower dEdX profile filled");
330 if (min > 0 && max > 0) {
331 double randNo = RandFlat::shoot(&fRandomEngine->GetEngine(), 0, 1);
333 x =
pow(
pow(min, index + 1) + randNo * (
pow(max, index + 1) -
pow(min, index + 1)),
336 x = min*
pow(max/min, randNo);
339 INFO(
"Impossible to dice!");
354 const double enExp = log10(energy);
355 const double eEx[] = { 17.5, 18, 18.5, 19, 19.5, 20, 20.5, 21 };
358 if (eEx[1] <= enExp && enExp < eEx[2])
360 else if (eEx[2] <= enExp && enExp < eEx[3])
362 else if (eEx[3] <= enExp && enExp < eEx[4])
364 else if (eEx[4] <= enExp && enExp < eEx[5])
366 else if (eEx[5] <= enExp && enExp < eEx[6])
368 else if (eEx[6] <= enExp)
372 const double c[] = { 49.701, 50.099, 46.640, 47.805, 43.782, 41.703, 40.328, 39.397 };
373 const double rXOne = (c[i]*eEx[i+1] - c[i+1]*eEx[i] + (c[i+1] - c[i])*enExp) / (eEx[i+1] - eEx[i]);
374 return RandExponential::shoot(&fRandomEngine->GetEngine(), rXOne) *
g/
cm2;
377 const double c[] = { 11.490, 11.738, 11.576, 11.834, 10.894, 11.376, 10.374, 10.473 };
378 const double rXOne = (c[i]*eEx[i+1] - c[i+1]*eEx[i] + (c[i+1] - c[i])*enExp) / (eEx[i+1] - eEx[i]);
379 return RandExponential::shoot(&fRandomEngine->GetEngine(), rXOne) *
g/
cm2;
391 const double enExp = log10(energy);
392 const double eEx[] = { 17.5, 18, 18.5, 19, 19.5, 20, 20.5, 21 };
395 if (eEx[1] <= enExp && enExp < eEx[2])
397 else if (eEx[2] <= enExp && enExp < eEx[3])
399 else if (eEx[3] <= enExp && enExp < eEx[4])
401 else if (eEx[4] <= enExp && enExp < eEx[5])
403 else if (eEx[5] <= enExp && enExp < eEx[6])
405 else if (eEx[6] <= enExp)
409 const double c[] = { -165.721, -180.741, -202.48, -213.481, -219.733, -221.584, -219.707, -211.232 };
410 const double c_s[] = { 74.837, 64.832, 65.819, 63.105, 61.768, 53.593, 53.542, 51.322 };
411 const double rX0 = (c[i]*eEx[i+1] - c[i+1]*eEx[i] + (c[i+1] - c[i])*enExp) / (eEx[i+1] - eEx[i]);
412 const double x0Sig = (c_s[i]*eEx[i+1] - c_s[i+1]*eEx[i] + (c_s[i+1] - c_s[i])*enExp) / (eEx[i+1] - eEx[i]);
413 return RandGauss::shoot(rX0, x0Sig) *
g/
cm2;
416 const double c[] = { -98.287, -117.574, -133.692, -152.395, -171.399, -188.069, -203.030, -212.375 };
417 const double c_s[] = { 39.532, 43.111, 41.771, 39.977, 36.580, 32.515, 28.729, 25.103 };
418 const double rX0 = (c[i]*eEx[i+1] - c[i+1]*eEx[i] + (c[i+1] - c[i])*enExp) / (eEx[i+1] - eEx[i]);
419 const double x0Sig = (c_s[i]*eEx[i+1] - c_s[i+1]*eEx[i] + (c_s[i+1] - c_s[i])*enExp) / (eEx[i+1] - eEx[i]);
420 return RandGauss::shoot(rX0, x0Sig) *
g/
cm2;
433 double enExp = log10(energy);
434 double rXMax, randomXMax;
436 const double eEx[] = { 17.5, 18, 18.5, 19, 19.5, 20, 20.5, 21 };
439 if (enExp >= eEx[1] && enExp < eEx[2]) i = 1;
440 if(enExp >= eEx[2] && enExp < eEx[3]) i = 2;
441 if(enExp >= eEx[3] && enExp < eEx[4]) i = 3;
442 if(enExp >= eEx[4] && enExp < eEx[5]) i = 4;
443 if(enExp >= eEx[5] && enExp < eEx[6]) i = 5;
444 if(enExp >= eEx[6]) i = 6;
448 double c[8] ={ 643.683, 671.343, 698.360, 727.941, 752.808, 775.352,
450 double c_s[8] = { 49.153, 42.425, 39.745, 42.068, 44.504, 40.818,
453 rXMax = (c[i]*eEx[i+1] - c[i+1]*eEx[i] + (c[i+1] - c[i])*enExp)
454 / (eEx[i+1] - eEx[i]);
455 xMaxSig = (c_s[i]*eEx[i+1] - c_s[i+1]*eEx[i] + (c_s[i+1] - c_s[i])*enExp)
456 / (eEx[i+1] - eEx[i]);
457 randomXMax = RandGauss::shoot(rXMax, xMaxSig);
461 double c[8] = { 586.590, 619.281, 648.269, 679.845, 709.612,
462 739.855, 770.108, 797.705 };
463 double c_s[8] ={ 21.540, 20.686, 17.408, 17.671, 17.301, 16.968,
466 rXMax = (c[i]*eEx[i+1] - c[i+1]*eEx[i] + (c[i+1] - c[i])*enExp)
467 / (eEx[i+1] - eEx[i]);
468 xMaxSig = (c_s[i]*eEx[i+1] - c_s[i+1]*eEx[i] + (c_s[i+1] - c_s[i])*enExp)
469 / (eEx[i+1] - eEx[i]);
470 randomXMax = RandGauss::shoot(rXMax, xMaxSig);
473 return randomXMax*(
g/
cm/
cm);
483 double energy)
const {
484 double lambdaSig =0.;
485 double enExp = log10(energy);
487 double rlambda, randomlambda;
489 double eEx[8] = {17.5, 18.0, 18.5, 19.0, 19.5, 20.0, 20.5, 21.0};
492 if(enExp >= eEx[1] && enExp < eEx[2]) i = 1;
493 if(enExp >= eEx[2] && enExp < eEx[3]) i = 2;
494 if(enExp >= eEx[3] && enExp < eEx[4]) i = 3;
495 if(enExp >= eEx[4] && enExp < eEx[5]) i = 4;
496 if(enExp >= eEx[5] && enExp < eEx[6]) i = 5;
497 if(enExp >= eEx[6]) i = 6;
501 double c[8] = { 58.473, 57.178, 56.578, 57.302, 58.475, 60.919,
503 double c_s[8] = { 12.256, 6.428, 6.268, 5.825, 6.026, 7.297,
506 rlambda = (c[i]*eEx[i+1] - c[i+1]*eEx[i] + (c[i+1] - c[i])*enExp)
507 / (eEx[i+1] - eEx[i]);
508 lambdaSig = (c_s[i]*eEx[i+1] - c_s[i+1]*eEx[i] + (c_s[i+1] - c_s[i])*enExp)
509 / (eEx[i+1] - eEx[i]);
510 randomlambda = RandGauss::shoot(rlambda, lambdaSig);
515 double c[8] = { 65.921, 63.033, 61.048, 59.358, 58.569, 57.887,
517 double c_s[8] = { 4.093, 3.555, 2.989, 2.435, 2.445, 2.016,
520 rlambda = (c[i]*eEx[i+1] - c[i+1]*eEx[i] + (c[i+1] - c[i])*enExp)
521 / (eEx[i+1] - eEx[i]);
522 lambdaSig = (c_s[i]*eEx[i+1] - c_s[i+1]*eEx[i] + (c_s[i+1] - c_s[i])*enExp)
523 / (eEx[i+1] - eEx[i]);
524 randomlambda = RandGauss::shoot(rlambda, lambdaSig);
527 return randomlambda*(
g/
cm/
cm);
536 double energy)
const {
539 double enExp = log10(energy);
540 double rNMax, randomNMax;
542 double eEx[8] = { 17.5, 18.0, 18.5, 19.0, 19.5, 20.0, 20.5, 21.0 };
545 if(enExp >= eEx[1] && enExp < eEx[2]) i = 1;
546 if(enExp >= eEx[2] && enExp < eEx[3]) i = 2;
547 if(enExp >= eEx[3] && enExp < eEx[4]) i = 3;
548 if(enExp >= eEx[4] && enExp < eEx[5]) i = 4;
549 if(enExp >= eEx[5] && enExp < eEx[6]) i = 5;
550 if(enExp >= eEx[6]) i = 6;
554 double c[8] = {8.31744, 8.81478, 9.31236, 9.80634, 10.3005,
555 10.7908, 11.282, 11.7698};
556 double c_s[8] = {0.02134, 0.01762, 0.01344, 0.01284, 0.01262,
557 0.01728, 0.01972, 0.02892};
559 rNMax = (c[i]*eEx[i+1] - c[i+1]*eEx[i] + ( c[i+1] - c[i] )*enExp)
560 / (eEx[i+1] - eEx[i]);
561 NMaxSig = (c_s[i]*eEx[i+1] - c_s[i+1]*eEx[i] + (c_s[i+1] - c_s[i])*enExp)
562 / (eEx[i+1] - eEx[i]);
563 randomNMax = RandGauss::shoot(rNMax, NMaxSig);
568 double c[8] = { 8.28851, 8.79259, 9.29535, 9.79570, 10.29420,
569 10.79200, 11.28860, 11.78570 };
570 double c_s[8] = { 0.01048, 0.01050, 0.00949, 0.00892, 0.00892,
571 0.008912, 0.00849, 0.00725 };
573 rNMax = (c[i]*eEx[i+1] - c[i+1]*eEx[i] + (c[i+1] - c[i])*enExp)
574 / (eEx[i+1] - eEx[i]);
575 NMaxSig = (c_s[i]*eEx[i+1] - c_s[i+1]*eEx[i] + (c_s[i+1] - c_s[i])*enExp)
576 / (eEx[i+1] - eEx[i]);
578 randomNMax = RandGauss::shoot(rNMax, NMaxSig);
591 double xMax,
double energy)
const {
593 const double kDepthMax = 4000.0*(
g/
cm/
cm);
594 const double kExpMax = 1.0e20;
596 double gaisserHillas = -kExpMax;
597 double auxXMax = xMax - xZero;
599 if(depth <= 0 || depth > kDepthMax)
600 return(gaisserHillas);
602 gaisserHillas = (auxXMax*(log(depth/auxXMax) + 1) - depth)/
utl::kLambdaGH
603 + log(
pow(10.0, (log10(energy) - 9.215)));
608 if (gaisserHillas < -kExpMax) {
609 gaisserHillas = -kExpMax;
611 else if (gaisserHillas > kExpMax) {
612 gaisserHillas = kExpMax;
614 return (exp(gaisserHillas));
631 const double kParamAge[21] =
632 { 0.0, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1.00,
633 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00};
636 const double kParamdEdX1[21] =
637 { 0.0, 2.9679, 2.7096, 2.5285, 2.3801, 2.2935, 2.2213, 2.1586, 2.1023,
638 2.0506, 2.0022, 1.9563, 1.9123, 1.8696, 1.8278, 1.7867, 1.7459,
639 1.7052, 1.6643, 1.6229, 1.5806 };
642 const double kParamRho1[21] =
643 { 0.0, 0.119E-04, 0.119E-04, 0.119E-04, 0.119E-04, 0.119E-04, 0.119E-04,
644 0.119E-04, 0.119E-04, 0.119E-04, 0.119E-04, 0.119E-04, 0.119E-04,
645 0.119E-04, 0.119E-04, 0.119E-04, 0.119E-04, 0.119E-04, 0.119E-04,
646 0.119E-04, 0.119E-04 };
649 const double kParamdEdX2[21] =
650 { 0.0, 2.7043, 2.5086, 2.3723, 2.2588, 2.1914, 2.1339, 2.0828, 2.0361,
651 1.9923, 1.9508, 1.9108, 1.8719, 1.8338, 1.7963, 1.7589, 1.7216,
652 1.6841, 1.6461, 1.6074, 1.5676 };
655 const double kParamRho2[21] =
656 { 0.0, 0.119E-02, 0.119E-02, 0.119E-02, 0.119E-02, 0.119E-02, 0.119E-02,
657 0.119E-02, 0.119E-02, 0.119E-02, 0.119E-02, 0.119E-02, 0.119E-02,
658 0.119E-02, 0.119E-02, 0.119E-02, 0.119E-02, 0.119E-02, 0.119E-02,
659 0.119E-02, 0.119E-02 };
663 double rho = density;
684 double dEdXTmp1 = (kParamdEdX1[i1]
685 + (kParamdEdX1[i2] - kParamdEdX1[i1])
686 *(age - kParamAge[i1])/(kParamAge[i2] - kParamAge[i1]))
688 double dEdXTmp2 = (kParamdEdX2[i1]
689 + (kParamdEdX2[i2] - kParamdEdX2[i1])
690 *(age - kParamAge[i1])/(kParamAge[i2] - kParamAge[i1]))
693 double dEdX = dEdXTmp1 + (dEdXTmp2 - dEdXTmp1)
694 *log(rho/(kParamRho1[i1]*(
g/
cm/
cm/
cm)))
695 /log(kParamRho2[i1]/kParamRho1[i1]);
utl::CoordinateSystemPtr GetLocalCoordinateSystem() const
Get the Auger coordinate system associated to the shower core position.
int GetPrimaryParticle() const
Get the type of the shower primary particle.
const evt::VGaisserHillasParameter & GetGHParameters() const
Get the Gaisser-Hillas parameters of the shower.
double RandomXOne(int primary, double energy) const
Class to hold collection (x,y) points and provide interpolation between them.
void SetEnergyCutoff(const double energy, const ProfileType type=eElectron)
Set the enegy cutoff for which the profile of charged particles was calculated.
bool HasSimShower() const
#define INFO(message)
Macro for logging informational messages.
void MakeGHParameters(const evt::VGaisserHillasParameter &ghPar)
Make the Gaisser-Hillas parameters of the shower.
Base class for exceptions trying to access non-existing components.
void PushBack(const double x, const double y)
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
double RandomLambda(int primary, double energy) const
double pow(const double x, const unsigned int i)
void MakedEdX(const utl::TabulatedFunction &dEdX)
Make the energy deposit of the shower.
double Y(const double x) const
Get the Y value (coordinate) for given X (ordinate)
double CalculatedEdX(double age, double density) const
This function is obsolete Calculation of the mean energy deposition in the atmosphere.
Interface class to access Shower Simulated parameters.
const atm::Atmosphere & GetAtmosphere() const
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
Class representing a document branch.
void MakeLongitudinalProfile(const utl::TabulatedFunction &lp, const ProfileType type=eCharged)
Make the longitudinal charge profile of the shower.
const utl::Vector & GetDirection() const
Get the direction of the shower axis. This is the true direction of shower movement.
double RandomXZero(int primary, double energy) const
double RandomNMax(int primary, double energy) const
Class describing the Atmospheric profile.
double abs(const SVector< n, T > &v)
fwk::VModule::ResultFlag Init()
Initialize: invoked at beginning of run (NOT beginning of event)
Top of the hierarchy of the detector description interface.
const atm::ProfileResult & EvaluateDepthVsHeight() const
Tabulated function giving Y=depth as a function of X=height.
void SetEnergy(const double theEnergy)
Set the energy of the shower primary particle.
fwk::VModule::ResultFlag Finish()
Finish: invoked at end of the run (NOT end of the event)
void GetData(bool &b) const
Overloads of the GetData member template function.
double CalculateNMax(double depth, double xZero, double xMax, double energy) const
double RandomXMax(int primary, double energy) const
double GaisserHillas(const double x, const double x0, const double xMax, const double nMax, const double lambda)
Calculate the Gaisser-Hillas function.
double DicePowerLaw(double min, double max, double index) const
ResultFlag
Flag returned by module methods to the RunController.
constexpr double kLambdaGH
double EnergyDeposit(const double age, const double enCut)
Parametrization for the average energy deposit per particle.
fwk::VModule::ResultFlag Run(evt::Event &theEvent)
Run: invoked once per event.
Main configuration utility.
#define ERROR(message)
Macro for logging error messages.
virtual ~ProfileSimulator()
utl::Branch GetTopBranch(const std::string &id)
Get top branch for moduleConfigLink with given id (XML files)