1 #include <atm/InclinedAtmosphericProfile.h>
2 #include <atm/ProfileResult.h>
3 #include <atm/Atmosphere.h>
5 #include <fwk/LocalCoordinateSystem.h>
6 #include <fwk/CoordinateSystemRegistry.h>
7 #include <utl/CoordinateSystemPtr.h>
9 #include <utl/ErrorLogger.h>
10 #include <utl/AugerUnits.h>
11 #include <utl/AugerException.h>
12 #include <utl/PhysicalConstants.h>
13 #include <utl/TabulatedFunction.h>
14 #include <utl/TabulatedFunctionErrors.h>
15 #include <utl/UTMPoint.h>
16 #include <utl/Point.h>
17 #include <utl/Vector.h>
18 #include <utl/ReferenceEllipsoid.h>
19 #include <utl/GeometryUtilities.h>
21 #include <det/Detector.h>
35 InclinedAtmosphericProfile::InclinedAtmosphericProfile(
const Point& core,
40 bool upward = (axis.
GetZ(LocalCoordinateSystem::Create(core)) < 0);
42 const Vector dirInverse = axis;
45 INFO(
string(
"Running ") + (upward ?
"upward" :
"downward") +
" mode!");
49 bool skimming =
false;
53 auto& detector = det::Detector::GetInstance();
56 const auto& atmDepthVsHeight =
atmosphere.EvaluateDepthVsHeight();
57 const auto& atmHeightVsDepth =
atmosphere.EvaluateHeightVsDepth();
58 const auto& atmDensityVsHeight =
atmosphere.EvaluateDensityVsHeight();
61 const double atmSafetyMargin = 1*
mm;
62 const double earthSafetyMargin = 1*
m;
72 const double atmHeightMax = atmDepthVsHeight.MaxX() - atmSafetyMargin;
73 const double atmHeightMin = atmDepthVsHeight.MinX() + earthSafetyMargin;
74 const double atmHeightMin_density = atmDensityVsHeight.MinX() + earthSafetyMargin;
75 const double minAtm =
max(atmHeightMin, atmHeightMin_density);
76 const double maxVerticalDepth = atmDepthVsHeight.Y(atmHeightMin);
77 const double minVerticalDepth = atmDepthVsHeight.Y(atmHeightMax);
81 const vector<Point> pAtm =
86 if (pAtm.size() < 2) {
88 err <<
"This shower geometry does not intersect the atmosphere!!!" << endl;
95 const vector<Point> pEarth =
101 switch (pEarth.size()) {
104 firstPoint = pEarth[0];
107 firstPoint = pAtm[1];
108 lastPoint = pEarth[1];
113 firstPoint = pAtm[1];
119 cout <<
"Scraper!\n";
126 cout <<
"Core\t" << core.GetCoordinates(csECEF) <<
"\n"
127 "Destination\t" << lastPoint.GetCoordinates(csECEF) <<
"\n"
128 "First\t" << firstPoint.GetCoordinates(csECEF) << endl;
138 Point iPoint = firstPoint;
142 cosTheta = dirInverse.
GetCosTheta(LocalCoordinateSystem::Create(
UTMPoint(firstPoint, wgs84)));
145 err <<
"InclinedAtmosphericProfile: un-physical local point ";
151 double verticalDeltaX = 0;
153 double tmpDepth = atmDepthVsHeight.Y(tmpHeight);
154 vector<Point> tmpPoints;
157 double tmpSlantDepth = upward ? cosTheta*(tmpDepth - atmDepthVsHeight.Y(0)) : tmpDepth;
160 vector<double> verticalHeight;
161 vector<double> slantDepth;
162 vector<double> distanceToImpactPoint;
165 verticalHeight.push_back(atmHeightVsDepth.Y(tmpDepth));
166 slantDepth.push_back(log(tmpSlantDepth));
167 distanceToImpactPoint.push_back(0 - (firstPoint - core).GetMag());
178 err <<
"InclinedAtmosphericProfile: un-physical local point ";
183 verticalDeltaX = deltaX * cosTheta;
184 tmpDepth += verticalDeltaX;
187 if (maxVerticalDepth <= tmpDepth || tmpDepth <= minVerticalDepth) {
189 verticalDeltaX = atmDepthVsHeight.Y(tmpHeight) - (tmpDepth - verticalDeltaX);
190 tmpSlantDepth += verticalDeltaX / cosTheta;
193 verticalHeight.push_back(tmpHeight);
195 slantDepth.push_back(log(tmpSlantDepth));
197 distanceToImpactPoint.push_back((lastPoint - core).GetMag());
201 tmpSlantDepth += deltaX;
202 tmpHeight = atmHeightVsDepth.Y(tmpDepth);
207 if (tmpPoints.size() < 2) {
210 tmpDepth -= verticalDeltaX;
211 tmpSlantDepth -= deltaX;
212 tmpHeight = atmHeightVsDepth.Y(tmpDepth);
214 tmpSlantDepth += atmDensityVsHeight.Y(tmpHeight) * (tmpPoints[0] - tmpPoints[1]).GetMag();
218 INFO(
"Reached space!");
224 nextPoint = skimming ? (upward ? tmpPoints[1] : tmpPoints[0]) : (upward ? tmpPoints[0] : tmpPoints[1]);
227 verticalHeight.push_back(tmpHeight);
229 slantDepth.push_back(log(tmpSlantDepth));
231 distanceToImpactPoint.push_back((nextPoint - firstPoint).GetMag() - (core - firstPoint).GetMag());
239 if (slantDepth.size() <= 1) {
241 err <<
"No points calculated. Table is empty. " << endl;
247 const double testCosTheta = dirirection.GetCosTheta(LocalCoordinateSystem::Create(
UTMPoint(core, wgs84)));
248 cout <<
"CosTheta\tSlantDepth\tverticalHeight\tDistance\n";
249 for (
unsigned int i = 0; i < verticalHeight.size(); ++i) {
250 cout << -testCosTheta <<
'\t'
251 << exp(slantDepth[i])/
g*
cm2 <<
'\t'
252 << verticalHeight[i]/
m <<
'\t'
253 << distanceToImpactPoint[i]/
m << endl;
258 vector<double> verticalHeightErrors(slantDepth.size());
259 vector<double> slantDepthErrors(slantDepth.size());
260 vector<double> distanceErrors(slantDepth.size());
263 vector<double> slantDepthReverse(slantDepth.size());
264 vector<double> verticalHeightReverse(slantDepth.size());
266 reverse_copy(slantDepth.begin(), slantDepth.end(), slantDepthReverse.begin());
267 reverse_copy(verticalHeight.begin(), verticalHeight.end(), verticalHeightReverse.begin());
270 slantDepth, slantDepthErrors);
272 fSlantDepthVsDistance =
273 new ProfileResult(tabSlantDist, ProfileResult::eLinear, ProfileResult::eLog);
276 distanceToImpactPoint, distanceErrors);
278 fDistanceVsSlantDepth =
279 new ProfileResult(tabDistSlant, ProfileResult::eLog, ProfileResult::eLinear);
282 verticalHeightReverse, verticalHeightErrors);
284 fHeightVsSlantDepth =
285 new ProfileResult(tabHeightSlant, ProfileResult::eLog, ProfileResult::eLinear);
288 verticalHeight, verticalHeightErrors);
291 new ProfileResult(tabHeightDistance, ProfileResult::eLinear, ProfileResult::eLinear);
295 InclinedAtmosphericProfile::~InclinedAtmosphericProfile()
297 delete fSlantDepthVsDistance;
298 delete fDistanceVsSlantDepth;
299 delete fHeightVsSlantDepth;
300 delete fHeightVsDistance;
306 InclinedAtmosphericProfile::EvaluateSlantDepthVsDistance()
309 if (fSlantDepthVsDistance)
310 return *fSlantDepthVsDistance;
318 InclinedAtmosphericProfile::EvaluateDistanceVsSlantDepth()
321 if (fDistanceVsSlantDepth)
322 return *fDistanceVsSlantDepth;
330 InclinedAtmosphericProfile::EvaluateHeightVsSlantDepth()
333 if (fHeightVsSlantDepth)
334 return *fHeightVsSlantDepth;
342 InclinedAtmosphericProfile::EvaluateHeightVsDistance()
345 if (fHeightVsDistance)
346 return *fHeightVsDistance;
355 InclinedAtmosphericProfile::IntegratedGrammage(
const utl::Point& pStart,
361 auto& detector = det::Detector::GetInstance();
365 const double atmHeightMin = atmDepthVsHeight.
MinX();
366 const double atmHeightMax = atmDepthVsHeight.
MaxX();
368 Vector dir(pStop - pStart);
369 const double length = dir.
GetMag();
375 while (distance < length) {
377 const double delta_now = (length - distance < delta ? length - distance : delta);
378 const Point p1 = pStart + distance * dir;
379 distance += delta_now;
380 const Point p2 = pStart + distance * dir;
382 double cosLocalTheta = 0;
385 cosLocalTheta = dir.GetCosTheta(LocalCoordinateSystem::Create(utm));
390 const double heightP1 = wgs84.PointToLatitudeLongitudeHeight(p1).get<2>();
391 const double heightP2 = wgs84.PointToLatitudeLongitudeHeight(p2).get<2>();
393 if (heightP1 <= atmHeightMin || heightP1 >= atmHeightMax ||
394 heightP2 <= atmHeightMin || heightP2 >= atmHeightMax) {
399 const double depthP1 = atmDepthVsHeight.
Y(heightP1);
400 const double depthP2 = atmDepthVsHeight.
Y(heightP2);
402 depth += (depthP1 - depthP2) / cosLocalTheta;
constexpr double atmosphere
Class to hold and convert a point in geodetic coordinates.
double GetCosTheta(const CoordinateSystemPtr &coordinateSystem) const
cos of zenith (theta) angle
#define INFO(message)
Macro for logging informational messages.
static const ReferenceEllipsoid & Get(const EllipsoidID theID)
Get known ellipsoid by registered ID.
double Y(const double x) const
Get the Y value (coordinate) for given X (ordinate)
Line Intersection(const Plane &p1, const Plane &p2)
double GetHeight() const
Get the height.
Class describing the Atmospheric profile.
double MinX() const
Return the minimum value for X (ordinate) stored in the profile.
Report problems in UTM handling.
execption handling for calculation/access for inclined atmosphere model
utl::CoordinateSystemPtr Get(const std::string &id)
Get a well-known Coordinate System.
double GetZ(const CoordinateSystemPtr &coordinateSystem) const
#define ERROR(message)
Macro for logging error messages.
double MaxX() const
Return the maximum value for X (ordinate) stored in the profile.