HumidAirRayleighModel.cc
Go to the documentation of this file.
1 
9 #include <det/Detector.h>
10 
11 #include <atm/HumidAirRayleighModel.h>
12 #include <atm/InclinedAtmosphericProfile.h>
13 #include <atm/ScatteringResult.h>
14 #include <atm/AttenuationResult.h>
15 #include <atm/ProfileResult.h>
16 
17 #include <fwk/CentralConfig.h>
18 #include <fwk/CoordinateSystemRegistry.h>
19 
20 #include <utl/Point.h>
21 #include <utl/Vector.h>
22 #include <utl/AugerUnits.h>
23 #include <utl/Reader.h>
24 #include <utl/ErrorLogger.h>
25 #include <utl/MathConstants.h>
26 #include <utl/PhysicalConstants.h>
27 #include <utl/ReferenceEllipsoid.h>
28 #include <utl/TabulatedFunctionErrors.h>
29 
30 #include <iostream>
31 #include <string>
32 #include <sstream>
33 #include <vector>
34 
35 using namespace det;
36 using namespace atm;
37 using namespace utl;
38 using namespace std;
39 using namespace fwk;
40 
41 
42 HumidAirRayleighModel::HumidAirRayleighModel() :
43  fIntegrationStepWidth(0)
44 {
45 }
46 
47 
48 void
50 {
51  Branch topB =
52  CentralConfig::GetInstance()->GetTopBranch("HumidAirRayleighModel");
53 
54  topB.GetChild("IntegrationStepWidth").GetData(fIntegrationStepWidth);
55 }
56 
57 
70  const Point& xB,
71  const double angle,
72  const double distance,
73  const std::vector<double>& wLength)
74  const
75 {
76  AttenuationResult raylAtt = EvaluateRayleighAttenuation(xA, xB, wLength);
77  return EvaluateRayleighScattering(xA, xB, angle, distance, raylAtt);
78 }
79 
80 
83  const Point& xB,
84  const double angle,
85  const double distance,
86  const AttenuationResult& raylAtt)
87  const
88 {
89  const double fractionError = 0;
90  const double wError = 0;
92  const TabulatedFunctionErrors& attenuation = raylAtt.GetTransmissionFactor();
93 
94  const unsigned int nWl = attenuation.GetNPoints();
95  for (unsigned int iWl = 0; iWl < nWl; ++iWl) {
96  const double wl = attenuation.GetX(iWl);
97  // Errors to be implemented
98  const double sct = EvaluateRayleighScattering(xA, xB, angle, distance, wl, attenuation.GetY(iWl));
99  frac.PushBack(wl, wError, sct, fractionError);
100  }
101 
102  return ScatteringResult(frac, angle);
103 }
104 
105 
106 double
108  const Point& xB,
109  const double angle,
110  const double distance,
111  const double wLength)
112  const
113 {
114  const double raylAtt = EvaluateRayleighAttenuation(xA, xB, wLength);
115  return EvaluateRayleighScattering(xA, xB, angle, distance, wLength, raylAtt);
116 }
117 
118 
119 double
121  const Point& /*xB*/,
122  const double angle,
123  const double distance,
124  const double wLength,
125  const double raylAtt)
126  const
127 {
128  return (1. - raylAtt)
129  * EvaluateScatteringAngle(xA, angle, wLength)
130  / (distance * distance);
131 }
132 
133 
134 
141  const Point& xFinal,
142  const vector<double>& wLength)
143  const
144 {
145  TabulatedFunctionErrors attenuation;
146  const double transAttError = 0;
147  const double wError = 0;
148 
149  for (std::vector<double>::const_iterator it = wLength.begin();
150  it != wLength.end(); ++it) {
151  const double transAtt = EvaluateRayleighAttenuation(xInit, xFinal, *it);
152  attenuation.PushBack(*it, wError, transAtt, transAttError);
153  }
154 
155  return AttenuationResult(attenuation);
156 }
157 
158 
164 double
166  const Point& xFinal,
167  double wLength)
168  const
169 {
170  const Atmosphere& atmos = Detector::GetInstance().GetAtmosphere();
171 
172  const ProfileResult& prVsH = atmos.EvaluatePressureVsHeight();
173  const ProfileResult& pvVsH = atmos.EvaluateVaporPressureVsHeight();
174  const ProfileResult& tempVsH = atmos.EvaluateTemperatureVsHeight();
175  const ProfileResult& riVsH = atmos.EvaluateRefractionIndexVsHeight(wLength);
176 
177  const ReferenceEllipsoid& wgs84 = ReferenceEllipsoid::Get(ReferenceEllipsoid::eWGS84);
178 
179  Vector dir = xFinal - xInit;
180  const double length = dir.GetMag();
181  dir.Normalize();
182 
183  double distance = 0;
184  double transmittance = 1;
185 
186  while (distance < length) {
187  const double delta =
188  (distance + fIntegrationStepWidth < length) ?
189  fIntegrationStepWidth : (length - distance);
190 
191  if (delta < 1*m)
192  break;
193 
194  const Point p1 = xInit + distance * dir;
195  distance += delta;
196  const Point p2 = xInit + distance * dir;
197 
198  const double hP1 = wgs84.PointToLatitudeLongitudeHeight(p1).get<2>();
199  const double hP2 = wgs84.PointToLatitudeLongitudeHeight(p2).get<2>();
200  const double height = 0.5 * (hP1 + hP2);
201 
202  const double pr = prVsH.Y(height);
203  const double pv = pvVsH.Y(height);
204  const double temp = tempVsH.Y(height);
205  const double ri = riVsH.Y(height);
206 
207  const double Nair = pr / (kBoltzmann * temp);
208  const double sigmaR = RayleighCrossSection(wLength, ri, temp, pr, pv);
209 
210  // Combine the optical depth + Beer-Lambert-Bouguer law:
211  // tau_m(0,r; lambda) = \int_0^r N(r') sigmaR(r', lambda) dr',
212  // T(0,r; lambda) = exp{-tau(0,r; lambda)}
213  transmittance *= exp(-Nair * sigmaR * delta);
214  }
215 
216  return transmittance;
217 }
218 
219 
220 double
222  const double wLength)
223  const
224 {
225  const Atmosphere& atmos = Detector::GetInstance().GetAtmosphere();
226 
227  const ReferenceEllipsoid& wgs84 =
228  ReferenceEllipsoid::Get(ReferenceEllipsoid::eWGS84);
229  const double height = wgs84.PointToLatitudeLongitudeHeight(p).get<2>();
230 
231  const double ri = atmos.EvaluateRefractionIndexVsHeight(wLength).Y(height);
232  const double pr = atmos.EvaluatePressureVsHeight().Y(height);
233  const double pv = atmos.EvaluateVaporPressureVsHeight().Y(height);
234  const double temp = atmos.EvaluateTemperatureVsHeight().Y(height);
235 
236  const double Nair = pr / (kBoltzmann * temp);
237  const double sigmaR = RayleighCrossSection(wLength, ri, temp, pr, pv);
238 
239  // Attenuation length = inverse of volume scattering coefficient
240  return 1 / (Nair * sigmaR);
241 }
242 
243 
244 double
246  const double angle,
247  const double wLength)
248  const
249 {
250  const Atmosphere& atmos = Detector::GetInstance().GetAtmosphere();
251  const ReferenceEllipsoid& wgs84 =
252  ReferenceEllipsoid::Get(ReferenceEllipsoid::eWGS84);
253 
254  const double height = wgs84.PointToLatitudeLongitudeHeight(p).get<2>();
255  const double pr = atmos.EvaluatePressureVsHeight().Y(height);
256  const double pv = atmos.EvaluateVaporPressureVsHeight().Y(height);
257 
258  // Depolarization: use dispersion of the King factor in a humid atmosphere
259  const double Fk = KingFactor(wLength, pr, pv);
260  const double rhoN = (6. * Fk - 6.) / (7. * Fk + 3.);
261  const double costh = cos(angle);
262 
263  // Phase function
264  return 3 / (8*kPi * (2 + rhoN)) * ((1 + rhoN) + (1 - rhoN) * costh*costh);
265 }
266 
267 
268 double
269 HumidAirRayleighModel::KingFactor(const double wl, const double pressure,
270  const double vaporPressure)
271  const
272 {
273  const double invWl2 = pow(wl / micrometer, -2.);
274 
275  // King factors for primary constituents of air.
276  // See C. Tomasi et al,. Appl. Opt. 44 (2005) 3320, eqs. 20-22
277  const double FkN2 = 1.034 + 3.17e-4 * invWl2;
278  const double FkO2 = 1.096 + invWl2 * (1.385e-3 + 1.448e-4 * invWl2);
279  const double FkAr = 1.;
280  const double FkCO2 = 1.15;
281  const double FkH2O = 1.001;
282 
283  const double H2OAirFraction = vaporPressure / pressure;
284 
285  // Total King factor is a weighted sum of the constituents of air
286  return (FkN2 * kN2AirFraction + FkO2 * kO2AirFraction +
287  FkAr * kArAirFraction + FkCO2 * kCO2AirFraction +
288  FkH2O * H2OAirFraction) /
291  H2OAirFraction);
292 }
293 
294 
295 double
297  const double refIndex,
298  const double temperature,
299  const double pressure,
300  const double vaporPressure)
301  const
302 {
303  const double N_air = pressure / (kBoltzmann * temperature);
304  const double refIndex2 = refIndex * refIndex;
305  const double factorKing = KingFactor(wl, pressure, vaporPressure);
306 
307  return 24* pow(kPi, 3)
308  * pow(((refIndex2 - 1) / (refIndex2 + 2)), 2)
309  * pow(wl, -4) / (N_air * N_air) * factorKing;
310 }
Branch GetTopBranch() const
Definition: Branch.cc:63
unsigned int GetNPoints() const
Top of the interface to Atmosphere information.
void Normalize()
Definition: Vector.h:64
Point object.
Definition: Point.h:32
const utl::TabulatedFunctionErrors & GetTransmissionFactor() const
Transmission factor.
const atm::ProfileResult & EvaluatePressureVsHeight() const
Tabulated function giving Y=air pressure as a function of X=height.
double GetAttenuationLength(const utl::Point &p, const double wLength) const
Attenuation in units of length [1/scattering coefficient].
double EvaluateScatteringAngle(const utl::Point &p, const double angle, const double wLength) const
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
Definition: Branch.cc:211
constexpr double kN2AirFraction
double pow(const double x, const unsigned int i)
double GetMag() const
Definition: Vector.h:58
double Y(const double x) const
Get the Y value (coordinate) for given X (ordinate)
Class holding the output of the ScatteringResult function.
constexpr double micrometer
Definition: AugerUnits.h:101
Class representing a document branch.
Definition: Branch.h:107
Reference ellipsoids for UTM transformations.
Class describing the Atmospheric profile.
Definition: ProfileResult.h:25
constexpr double kPi
Definition: MathConstants.h:24
atm::AttenuationResult EvaluateRayleighAttenuation(const utl::Point &xInit, const utl::Point &xFinal, const std::vector< double > &wLength) const
Calculate the Rayleigh attenuation between two points for a vector of wavelengths.
Triple PointToLatitudeLongitudeHeight(const Point &thePoint) const
Convert Point to Lat/Long/Height.
void PushBack(const double x, const double xErr, const double y, const double yErr)
void GetData(bool &b) const
Overloads of the GetData member template function.
Definition: Branch.cc:644
const double & GetY(const unsigned int idx) const
double RayleighCrossSection(const double wl, const double refIndex, const double temperature, const double pressure, const double vaporPressure) const
constexpr double kBoltzmann
constexpr double kO2AirFraction
Vector object.
Definition: Vector.h:30
const double & GetX(const unsigned int idx) const
atm::ScatteringResult EvaluateRayleighScattering(const utl::Point &xA, const utl::Point &xB, const double angle, const double distance, const std::vector< double > &wLength) const
Calculate the fraction of Rayleigh scattering photons in the beam.
double KingFactor(const double wl, const double pressure, const double vaporPressure) const
utl::CoordinateSystemPtr Get(const std::string &id)
Get a well-known Coordinate System.
const atm::ProfileResult & EvaluateRefractionIndexVsHeight() const
Tabulated function giving Y=refraction index as a function of X=height.
constexpr double kCO2AirFraction
constexpr double kArAirFraction
constexpr double m
Definition: AugerUnits.h:121
const atm::ProfileResult & EvaluateVaporPressureVsHeight() const
Tabulated function giving Y=H20 vapor pressure as a function of X=height.
const atm::ProfileResult & EvaluateTemperatureVsHeight() const
Tabulated function giving Y=temperature as a function of X=height.
Class describing the Atmospheric attenuation.

, generated on Tue Sep 26 2023.