MonthlyAvgDBProfileModel.cc
Go to the documentation of this file.
1 
8 #include <iostream>
9 #include <string>
10 #include <sstream>
11 #include <vector>
12 #include <limits>
13 
14 #include <utl/Reader.h>
15 #include <utl/ErrorLogger.h>
16 #include <utl/AugerException.h>
17 #include <utl/AugerUnits.h>
18 #include <utl/MathConstants.h>
19 #include <utl/TabulatedFunction.h>
20 #include <utl/TimeStamp.h>
21 #include <utl/UTCDateTime.h>
22 #include <utl/PhysicalConstants.h>
23 #include <utl/PhysicalFunctions.h>
24 
25 #include <fwk/CentralConfig.h>
26 
27 #include <atm/MonthlyAvgDBProfileModel.h>
28 #include <atm/ProfileResult.h>
29 #include <atm/MolecularDB.h>
30 #include <atm/MolecularLayer.h>
31 #include <atm/MolecularZone.h>
32 #include <atm/ProfileResult.h>
33 #include <det/Detector.h>
34 
35 #include <utl/ErrorLogger.h>
36 
37 using namespace atm;
38 using namespace utl;
39 using namespace std;
40 using namespace fwk;
41 
42 
43 // For some reason, CLHEP SystemOfUnits.h
44 // #defines pascal to hep_pascal, putting it in
45 // the global namespace and screwing up our own
46 // definition of pascal from AugerUnits.h. It appears
47 // the CLHEP units are being pulled in via the geometry
48 // package. The following line undoes the CLHEP sabotage.
49 #undef pascal
50 
51 
52 const ProfileResult&
54  const
55 {
56  if (!CheckForUpdates())
57  throw NoDataForModelException("No monthly average data found for pressure.");
58  return *fTabLogPressureVsHeight;
59 }
60 
61 
62 const ProfileResult&
64  const
65 {
66  if (!CheckForUpdates())
67  throw NoDataForModelException("No monthly average data found for temperature.");
68  return *fTabTemperatureVsHeight;
69 }
70 
71 
72 const ProfileResult&
74  const
75 {
76  if (!CheckForUpdates())
77  throw NoDataForModelException("No monthly average data found for humidity.");
78  return *fTabLogVaporPressureVsHeight;
79 }
80 
81 
82 const ProfileResult&
84  const
85 {
86  if (!CheckForUpdates())
87  throw NoDataForModelException("No monthly average data found for density.");
88  return *fTabLogDensityVsHeight;
89 }
90 
91 
92 const ProfileResult&
94  const
95 {
96  if (!CheckForUpdates())
97  throw NoDataForModelException("No monthly average data found for depth.");
98  return *fTabLogDepthVsHeight;
99 }
100 
101 
102 const ProfileResult&
104  const
105 {
106  if (!CheckForUpdates())
107  throw NoDataForModelException("No monthly average data found for height vs depth.");
108  return *fTabHeightVsLogDepth;
109 }
110 
111 
112 const ProfileResult&
114  const
115 {
116  if (!CheckForUpdates())
117  throw NoDataForModelException("No monthly average data found for refraction index.");
118  return *fTabRIVsHeight;
119 }
120 
121 
122 bool
124  const
125 {
126  return CheckForUpdates();
127 }
128 
129 
130 bool
132  const
133 {
134  // Check if the detector has been updated to a new month,
135  // and fill verious lookup tables if so
136  if (fCurrentTime &&
137  UTCDateTime(fCurrentTime).GetMonth() ==
138  UTCDateTime(det::Detector::GetInstance().GetTime()).GetMonth())
139  return true;
140 
141  // Atmosphere state is changing: clean up calculated refraction profiles
142  CleanRIVsWavelength();
143 
144  fCurrentTime = det::Detector::GetInstance().GetTime();
145 
146  TabulatedFunctionErrors tabRIVsHeight;
147  TabulatedFunctionErrors tabLogPressureVsHeight;
148  TabulatedFunctionErrors tabLogVaporPressureVsHeight;
149  TabulatedFunctionErrors tabTemperatureVsHeight;
150  TabulatedFunctionErrors tabLogDepthVsHeight;
151  TabulatedFunctionErrors tabLogDensityVsHeight;
152  TabulatedFunctionErrors tabHeightVsLogDepth;
153 
154  // determine (seasonal average) profileType based on month
155  const unsigned int iMonth = UTCDateTime(fCurrentTime).GetMonth();
156 
158  switch (iMonth) {
159  case 1:
161  break;
162  case 2:
164  break;
165  case 3:
167  break;
168  case 4:
170  break;
171  case 5:
173  break;
174  case 6:
176  break;
177  case 7:
179  break;
180  case 8:
182  break;
183  case 9:
185  break;
186  case 10:
188  break;
189  case 11:
191  break;
192  case 12:
194  break;
195  default:
196  ostringstream msg;
197  msg << "Invalid month number : " << iMonth;
198  ERROR(msg);
199  }
200 
201  const MolecularDB& mDB =
202  det::Detector::GetInstance().GetAtmosphere().GetMolecularDB(profileId);
203 
204  // Fill tabulated functions. Perform conversions into Auger base units
205  int nZonesCheck = 0;
206  const double minLog = kLn10 * numeric_limits<double>::min_exponent10;
207 
208  for (MolecularDB::ZoneIterator zIt = mDB.ZonesBegin();
209  zIt != mDB.ZonesEnd(); ++zIt) {
210 
211  for (MolecularZone::LayerIterator lIt = zIt->LayersBegin();
212  lIt != zIt->LayersEnd(); ++lIt) {
213 
214  // TEMPORARY.. in case some entries in database are not ordered
215  // by ordinate, skip the unorder entries for now. This should be
216  // fixed automatically when TabulatedFunction is redesigned + reimplemented,
217  // at which time code up to 'END TEMPORARY' should be removed.
218  if (lIt != zIt->LayersBegin()) {
219  MolecularZone::LayerIterator newIt = lIt;
220  if (newIt->GetHeight() <= (--newIt)->GetHeight())
221  break;
222  }
223  // END TEMPORARY patch to compensate shitty TabulatedFunction class
224 
225  tabLogDepthVsHeight.PushBack(
226  lIt->GetHeight(), lIt->GetHeightError(),
227  log(lIt->GetDepth()), lIt->GetDepthError() / lIt->GetDepth()
228  );
229 
230  // Move calculation of refraction index to base class once
231  // TabulatedFunction is fixed
232  const double refracIndex = utl::RefractionIndex::LorentzLorentz(lIt->GetPressure() * kOverburdenSeaLevel / atmosphere);
233  tabRIVsHeight.PushBack(
234  lIt->GetHeight(), 0, // ERRORS need to be computed
235  refracIndex, 0
236  );
237 
238  tabLogPressureVsHeight.PushBack(
239  lIt->GetHeight(), lIt->GetHeightError(),
240  log(lIt->GetPressure()), lIt->GetPressureError() / lIt->GetPressure()
241  );
242 
243  // Convert relative humidity to vapor pressure
244  const double pSat = utl::SaturationVaporPressure(lIt->GetTemperature());
245  const double pVapor = lIt->GetHumidity() * pSat;
246  const double dpVapor = lIt->GetHumidityError() * pSat; // Ignore dT...
247 
248  tabLogVaporPressureVsHeight.PushBack(
249  lIt->GetHeight(), lIt->GetHeightError(),
250  (pVapor > 0) ? log(pVapor) : minLog, (pVapor > 0 && dpVapor > 0) ? pVapor / dpVapor : minLog
251  );
252 
253  tabTemperatureVsHeight.PushBack(
254  lIt->GetHeight(), lIt->GetHeightError(),
255  lIt->GetTemperature(), lIt->GetTemperatureError()
256  );
257 
258  tabLogDensityVsHeight.PushBack(
259  lIt->GetHeight(), lIt->GetHeightError(),
260  log(lIt->GetAirDensity()), lIt->GetAirDensityError() / lIt->GetAirDensity()
261  );
262  }
263 
264  // Fill the log depth vs height profile, starting from the top layer
265  MolecularZone::LayerIterator lIt = zIt->LayersEnd();
266  while (lIt != zIt->LayersBegin()) {
267  --lIt;
268 
269  // TEMPORARY.. in case some entries in database are not ordered
270  // by ordinate, skip the unorder entries for now. This should be
271  // fixed automatically when TabulatedFunction is redesigned + reimplemented,
272  // at which time code up to 'END TEMPORARY' should be removed.
273  if (lIt != --(zIt->LayersEnd())) {
274  MolecularZone::LayerIterator newIt = lIt;
275  if (newIt->GetHeight() >= (++newIt)->GetHeight())
276  break;
277  }
278  // END TEMPORARY patch to compensate shitty TabulatedFunction class
279 
280  tabHeightVsLogDepth.PushBack(
281  log(lIt->GetDepth()), lIt->GetDepthError() / lIt->GetDepth(),
282  lIt->GetHeight(), lIt->GetHeightError()
283  );
284 
285  }
286  ++nZonesCheck;
287  }
288 
289  if (!nZonesCheck) {
290  ostringstream msg;
291  msg << "Monthly average data requested from database, "
292  "but no data found for month "
293  << UTCDateTime(fCurrentTime).GetMonth();
294  DEBUGLOG(msg);
295  return false;
296  }
297 
298  if (nZonesCheck != 1) {
299  ERROR("some kind of error here");
300  }
301 
302  // Create profile results
303  *fTabLogPressureVsHeight =
304  ProfileResult(tabLogPressureVsHeight, ProfileResult::eLinear, ProfileResult::eLog);
305 
306  *fTabLogVaporPressureVsHeight =
307  ProfileResult(tabLogVaporPressureVsHeight, ProfileResult::eLinear, ProfileResult::eLog);
308 
309  *fTabTemperatureVsHeight =
311 
312  *fTabLogDensityVsHeight =
314 
315  *fTabLogDepthVsHeight =
317 
318  *fTabHeightVsLogDepth =
320 
321  *fTabRIVsHeight =
323 
324  // Extend all tables to a height of 100 km
325  ExtendProfilesTo100km();
326 
327  return true;
328 }
August Malargue model.
Definition: MolecularIds.h:29
const atm::ProfileResult & EvaluatePressureVsHeight() const override
Table of air pressure as a function of height.
June Malargue model.
Definition: MolecularIds.h:25
boost::transform_iterator< InternalZoneFunctor, InternalZoneIterator, const MolecularZone & > ZoneIterator
ZoneIterator returns a pointer to a MolecularZone.
Definition: MolecularDB.h:52
constexpr double atmosphere
Definition: AugerUnits.h:215
March Malargue model.
Definition: MolecularIds.h:19
const atm::ProfileResult & EvaluateDensityVsHeight() const override
Table of density as a function of height.
const ProfileResult & EvaluateVaporPressureVsHeight() const override
Table of H2O vapor pressure as a function of height.
May Malargue model.
Definition: MolecularIds.h:23
October Malargue model.
Definition: MolecularIds.h:33
constexpr double kOverburdenSeaLevel
ZoneIterator ZonesEnd() const
End of the collection of valid Zones.
Definition: MolecularDB.h:59
Detector description interface for data in the Atm_Molecular database.
Definition: MolecularDB.h:29
November Malargue model.
Definition: MolecularIds.h:35
July Malargue model.
Definition: MolecularIds.h:27
virtual bool HasData() const override
True if a data source is for the given model.
Exception to use in a atmosphere model cannot find data it needs.
const atm::ProfileResult & EvaluateTemperatureVsHeight() const override
Table of temperature as a function of height.
const atm::ProfileResult & EvaluateRefractionIndexVsHeight() const override
Tabl of refraction index as a function of height.
const atm::ProfileResult & EvaluateDepthVsHeight() const override
Table of depth as a function of height.
January Malargue model.
Definition: MolecularIds.h:15
const atm::ProfileResult & EvaluateHeightVsDepth() const override
Table of height as a function of depth.
Class describing the Atmospheric profile.
Definition: ProfileResult.h:25
ProfileId
Monitoring profiles:
Definition: MolecularIds.h:8
#define DEBUGLOG(message)
Macro for logging debugging messages.
Definition: ErrorLogger.h:157
double SaturationVaporPressure(const double temperature)
Evaluate the saturation vapor pressure over ice or water.
void PushBack(const double x, const double xErr, const double y, const double yErr)
constexpr double kLn10
Definition: MathConstants.h:29
ZoneIterator ZonesBegin() const
Beginning of the collection of valid Zones.
Definition: MolecularDB.h:55
double LorentzLorentz(const double verticalDepth)
Calculate the refraction index for a given depth.
int GetMonth() const
Definition: UTCDate.h:46
December Malargue model.
Definition: MolecularIds.h:37
September Malargue model.
Definition: MolecularIds.h:31
boost::indirect_iterator< InternalLayerIterator, const MolecularLayer & > LayerIterator
Layer iterator returns a pointer to the molecular data slice for this zone.
Definition: MolecularZone.h:43
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
February Malargue model.
Definition: MolecularIds.h:17
April Malargue model.
Definition: MolecularIds.h:21

, generated on Tue Sep 26 2023.