CorsikaShowerFileGeometryProducer.cc
Go to the documentation of this file.
1 #include <io/CorsikaShowerFileGeometryProducer.h>
2 
3 #include <io/RawCorsikaFile.h>
4 #include <io/CorsikaBlock.h>
5 #include <io/CorsikaIOException.h>
6 #include <io/CorsikaUtilities.h>
7 
8 #include <utl/ErrorLogger.h>
9 #include <utl/AugerUnits.h>
10 #include <utl/CoordinateSystem.h>
11 #include <utl/CoordinateSystemPtr.h>
12 #include <utl/ReferenceEllipsoid.h>
13 #include <utl/UTMPoint.h>
14 #include <utl/Point.h>
15 #include <utl/Math.h>
16 #include <utl/Vector.h>
17 #include <utl/GeometryUtilities.h>
18 
19 #include <det/Detector.h>
20 
21 #include <fwk/LocalCoordinateSystem.h>
22 #include <fwk/MagneticFieldModel.h>
23 
24 #include <vector>
25 #include <sstream>
26 
27 using namespace io;
28 using namespace utl;
29 using namespace std;
30 
31 
33 CorsikaShowerFileGeometryProducer(const double corsikaZenith,
34  const double corsikaAzimuth,
35  const double obsLevelHeight,
36  const bool multiCore,
37  const utl::CoordinateSystemPtr refCS,
38  const double corsikaRotation,
39  const bool correctForRealisticMagneticFieldDeclination) :
40  fCORSIKAZenith(corsikaZenith),
41  fCORSIKAAzimuth(corsikaAzimuth),
42  fObsLevelHeight(obsLevelHeight),
43  fHasMultiCore(multiCore),
44  fRefCS(refCS),
45  fCoordinateRotation(corsikaRotation),
46  fCorrectForRealisticMagneticFieldDeclination(correctForRealisticMagneticFieldDeclination)
47 { }
48 
49 
50 /*
51  This crazy function returns the coordinate system corresponding to
52  the surface where CORSIKA saved particles coordinates. CORSIKA can
53  save flat, as well as curved surfaces. The "shower core" in CORSIKA
54  is always at 0,0 and this is the center of the CS.
55 
56  Warning: if you use an option in CORSIKA like CSCAT, TELESCOPE,
57  AUGERHIT, etc. that makes assumptions on the location of specific
58  "detectors", "volumes" or "positions", this must be 100% reflected
59  here. The consquence can be that CS z-axis does not strictly point
60  upwards, but is deflected to some extend, etc. Be careful. Don't
61  make any implicit assumptions! Use points, vectors and CSs
62  consitently and you will be fine.
63 */
64 
67 {
68  /* There are several options that have to be considered.
69 
70  1) Normal case: CORSIKA observation level height must correspond
71  to Offline altitude. CS origin is shifted to height altitude.
72 
73  2) Case where it is important to retain the alignment of CORSIKA
74  output with other external positions (TELESCOPS, AUGERHIT,
75  Radio-Antennas, COREAS...), which are given in a particular _fixed_
76  reference frame within CORSIKA. This requires to put the CS
77  into this particular CORSIKA reference frame. For example if
78  site-CS is used for "TELESCOPES" then CS must be on altitute
79  where the z-coordinate in "site-CS" corresponds to the CORSIKA
80  observation level. (this is tested for flat CORSIKA. need to confirm
81  for curved and curved-output, too). External(core)-CS will
82  then have a z-axis parallel to site-CS, not strictly pointing
83  upward. Zenith, azimuth are relative to this particular CS,
84  too!
85 
86  PROBLEM TO SOLVE: Which reference frame should we select for
87  Auger in CORSIKA as a convention ??? Need to decide !!!
88  */
89 
90  static bool showThisMessageOnlyOnce = true;
91  const bool useAugerCS = !fHasMultiCore;
92 
93  const utl::CoordinateSystemPtr cs = fwk::LocalCoordinateSystem::Create(anyPointOnShowerAxis);
95 
96  double north = 0;
98  // magnetic field declination
99  north = det::Detector::GetInstance().GetGeoMagneticField().GetDeclination(anyPointOnShowerAxis);
100  ostringstream info;
101  info << "Magnetic field declination: " << north/utl::degree << " deg";
102  INFO(info);
103  }
104 
105  if (useAugerCS) {
106 
107  // Option 1
108  // second: move CORSIKA CS along shower axis so that Auger altitude
109  // is identical to CORSIKA observation level height create vector
110 
111  // pointing along the momvement of the shower in CORSIKA frame (see
112  // Fig 1 of CORSIKA_GUIDE7.5600.pdf). This is different from normal
113  // Auger convention!
114 
115  const double sinZenith = sin(fCORSIKAZenith);
116  const double cosZenith = cos(fCORSIKAZenith);
117 
118  // This is for Auger azimuth, corsika phi always relative to magnetic north
119  // CORSIKA direction is direction of motion of CR, not direction from where CR is coming
120  const double augerAzimuth = Corsika::CorsikaAzimuthToAuger(fCORSIKAAzimuth + kPi, north);
121  const Vector direction(-cos(augerAzimuth)*sinZenith,
122  -sin(augerAzimuth)*sinZenith,
123  -cosZenith, cs);
124 
125  const vector<Point> intersections =
126  utl::Intersection(ReferenceEllipsoid::Get(ReferenceEllipsoid::eWGS84),
128  Line(anyPointOnShowerAxis, direction));
129 
130  {
131  const UTMPoint theUTMPoint(anyPointOnShowerAxis, ReferenceEllipsoid::eWGS84);
132  const double altitude = theUTMPoint.GetHeight();
133  ostringstream inf;
134  inf << "Observation level height: " << fObsLevelHeight/m << " m, Offline core height: " << altitude/m << " m";
135  INFO(inf);
136  }
137 
138  if (intersections.empty()) {
139  WARNING("Shower does not intersect observation level.");
140  }
141 
142  // pick closest point (there are typically two solutions)
143  Vector toPlane;
144  double closest = 0;
145  bool first = true;
146 
147  for (const auto& inter : intersections) {
148  const Vector coreToPoint = inter - anyPointOnShowerAxis;
149  const double dist = coreToPoint.GetMag();
150  if (first) {
151  closest = dist;
152  toPlane = coreToPoint;
153  first = false;
154  } else if (dist < closest) {
155  closest = dist;
156  toPlane = coreToPoint;
157  }
158  }
159 
160  if (showThisMessageOnlyOnce) {
161  ostringstream inf;
162  inf << "CORSIKA particle ground plane is displaced by " << (toPlane*direction)/m << "m "
163  "along shower axis with respect to Offline ground level.";
164  INFO(inf);
165  showThisMessageOnlyOnce = false;
166  }
167 
168  coreCS = fwk::LocalCoordinateSystem::Create(Point(0, 0, 0, CoordinateSystem::Translation(toPlane, cs)));
169 
170  // *******************************************************************
171  } else { // CS is not an AugerCoordinateSystem
172 
173  // Option 2
174 
175  // corsika z-axis might not be pointing straight up !
176 
177  const Vector shift = anyPointOnShowerAxis - Point(0, 0, 0, fRefCS);
178 
179  // now move refCS origin to core
180  coreCS = CoordinateSystem::Translation(shift, fRefCS);
181 
182  if (showThisMessageOnlyOnce) {
183  ostringstream inf;
184  inf << "CORSIKA particle ground plane is rotated by "
185  << Angle(Vector(0, 0, 1, coreCS), Vector(0, 0, 1, cs))/deg << " deg "
186  "in zenith with respect to Offline ground level.";
187  INFO(inf);
188  showThisMessageOnlyOnce = false;
189  }
190  }
191 
192  /*
193  Final step:
194 
195  rotate Auger CS into CORSIKA CS
196 
197  in CORSIKA x axis points to magnetic north. In Offline x-axis points to geographic east.
198  */
199  const double angle = Corsika::CorsikaAzimuthToAuger(fCoordinateRotation, north);
200  ostringstream inf;
201  inf << "Rotation (around z axis) between Auger CS and Corsika CS: " << angle / deg << " deg.";
202  INFO(inf);
203  const CoordinateSystemPtr particlePlaneCS = CoordinateSystem::RotationZ(angle, coreCS);
204  return particlePlaneCS;
205 }
Point object.
Definition: Point.h:32
double Angle(const double theta1, const double phi1, const double theta2, const double phi2)
Class to hold and convert a point in geodetic coordinates.
Definition: UTMPoint.h:40
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
double GetMag() const
Definition: Vector.h:58
Line Intersection(const Plane &p1, const Plane &p2)
constexpr double deg
Definition: AugerUnits.h:140
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
double GetHeight() const
Get the height.
Definition: UTMPoint.h:212
constexpr double kPi
Definition: MathConstants.h:24
constexpr double degree
double CorsikaAzimuthToAuger(const double corsikaAzimuth, const double magneticFieldDeclination)
Returns the azimuth rotated from Corisika&#39;s system to Auger standard.
#define WARNING(message)
Macro for logging warning messages.
Definition: ErrorLogger.h:163
Vector object.
Definition: Vector.h:30
virtual utl::CoordinateSystemPtr MakeGroundParticleCoordinateSystem(const utl::Point &anyPointOnShowerAxis)
utl::CoordinateSystemPtr Get(const std::string &id)
Get a well-known Coordinate System.
static Policy::type Create(const utl::Point &theOrigin)
Create the standard local coordinate system for a Point.
constexpr double m
Definition: AugerUnits.h:121
Definition: Line.h:17

, generated on Tue Sep 26 2023.