NBTropModel.cpp
Go to the documentation of this file.
1 //==============================================================================
2 //
3 // This file is part of GNSSTk, the ARL:UT GNSS Toolkit.
4 //
5 // The GNSSTk is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published
7 // by the Free Software Foundation; either version 3.0 of the License, or
8 // any later version.
9 //
10 // The GNSSTk is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with GNSSTk; if not, write to the Free Software Foundation,
17 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
18 //
19 // This software was developed by Applied Research Laboratories at the
20 // University of Texas at Austin.
21 // Copyright 2004-2022, The Board of Regents of The University of Texas System
22 //
23 //==============================================================================
24 
25 //==============================================================================
26 //
27 // This software was developed by Applied Research Laboratories at the
28 // University of Texas at Austin, under contract to an agency or agencies
29 // within the U.S. Department of Defense. The U.S. Government retains all
30 // rights to use, duplicate, distribute, disclose, or release this software.
31 //
32 // Pursuant to DoD Directive 523024
33 //
34 // DISTRIBUTION STATEMENT A: This software has been approved for public
35 // release, distribution is unlimited.
36 //
37 //==============================================================================
38 
39 #include "YDSTime.hpp"
40 #include "NBTropModel.hpp"
41 
42 #define THROW_IF_INVALID_DETAILED() {if (!valid) { \
43  InvalidTropModel e; \
44  if(!validWeather) e.addText("Invalid trop model: weather"); \
45  if(!validRxLatitude) e.addText("Invalid trop model: validRxLatitude"); \
46  if(!validRxHeight) e.addText("Invalid trop model: validRxHeight"); \
47  if(!validDOY) e.addText("Invalid trop model: day of year"); \
48  GNSSTK_THROW(e);}}
49 
50 namespace gnsstk
51 {
52  static const double NBRd=287.054; // J/kg/K = m*m*K/s*s
53  static const double NBg=9.80665; // m/s*s
54  static const double NBk1=77.604; // K/mbar
55  static const double NBk3p=382000; // K*K/mbar
56 
57  static const double NBLat[5]={ 15.0, 30.0, 45.0, 60.0, 75.0};
58 
59  // zenith delays, averages
60  static const double NBZP0[5]={1013.25,1017.25,1015.75,1011.75,1013.00};
61  static const double NBZT0[5]={ 299.65, 294.15, 283.15, 272.15, 263.65};
62  static const double NBZW0[5]={ 26.31, 21.79, 11.66, 6.78, 4.11};
63  static const double NBZB0[5]={6.30e-3,6.05e-3,5.58e-3,5.39e-3,4.53e-3};
64  static const double NBZL0[5]={ 2.77, 3.15, 2.57, 1.81, 1.55};
65 
66  // zenith delays, amplitudes
67  static const double NBZPa[5]={ 0.0, -3.75, -2.25, -1.75, -0.50};
68  static const double NBZTa[5]={ 0.0, 7.0, 11.0, 15.0, 14.5};
69  static const double NBZWa[5]={ 0.0, 8.85, 7.24, 5.36, 3.39};
70  static const double NBZBa[5]={ 0.0,0.25e-3,0.32e-3,0.81e-3,0.62e-3};
71  static const double NBZLa[5]={ 0.0, 0.33, 0.46, 0.74, 0.30};
72 
73  // mapping function, dry, averages
74  static const double NBMad[5]={1.2769934e-3,1.2683230e-3,1.2465397e-3,1.2196049e-3,
75  1.2045996e-3};
76  static const double NBMbd[5]={2.9153695e-3,2.9152299e-3,2.9288445e-3,2.9022565e-3,
77  2.9024912e-3};
78  static const double NBMcd[5]={62.610505e-3,62.837393e-3,63.721774e-3,63.824265e-3,
79  64.258455e-3};
80 
81  // mapping function, dry, amplitudes
82  static const double NBMaa[5]={0.0,1.2709626e-5,2.6523662e-5,3.4000452e-5,
83  4.1202191e-5};
84  static const double NBMba[5]={0.0,2.1414979e-5,3.0160779e-5,7.2562722e-5,
85  11.723375e-5};
86  static const double NBMca[5]={0.0,9.0128400e-5,4.3497037e-5,84.795348e-5,
87  170.37206e-5};
88 
89  // mapping function, wet, averages (there are no amplitudes for wet)
90  static const double NBMaw[5]={5.8021897e-4,5.6794847e-4,5.8118019e-4,5.9727542e-4,
91  6.1641693e-4};
92  static const double NBMbw[5]={1.4275268e-3,1.5138625e-3,1.4572752e-3,1.5007428e-3,
93  1.7599082e-3};
94  static const double NBMcw[5]={4.3472961e-2,4.6729510e-2,4.3908931e-2,4.4626982e-2,
95  5.4736038e-2};
96 
97  // labels for use with the interpolation routine
98  enum TableEntry { ZP=1, ZT, ZW, ZB, ZL, Mad, Mbd, Mcd, Maw, Mbw, Mcw };
99 
100  // the interpolation routine
101  static double NB_Interpolate(double lat, int doy, TableEntry entry)
102  {
103  const double *pave = NULL, *pamp = NULL;
104  double ret, day=double(doy);
105 
106  // assign pointer to the right array
107  switch(entry) {
108  case ZP: pave=&NBZP0[0]; pamp=&NBZPa[0]; break;
109  case ZT: pave=&NBZT0[0]; pamp=&NBZTa[0]; break;
110  case ZW: pave=&NBZW0[0]; pamp=&NBZWa[0]; break;
111  case ZB: pave=&NBZB0[0]; pamp=&NBZBa[0]; break;
112  case ZL: pave=&NBZL0[0]; pamp=&NBZLa[0]; break;
113  case Mad: pave=&NBMad[0]; pamp=&NBMaa[0]; break;
114  case Mbd: pave=&NBMbd[0]; pamp=&NBMba[0]; break;
115  case Mcd: pave=&NBMcd[0]; pamp=&NBMca[0]; break;
116  case Maw: pave=&NBMaw[0]; break;
117  case Mbw: pave=&NBMbw[0]; break;
118  case Mcw: pave=&NBMcw[0]; break;
119  default:
120  {
121  InvalidRequest exc("NB_Interpolate called with unknown entry");
122  GNSSTK_THROW(exc);
123  }
124  }
125 
126  // find the index i such that NBLat[i] <= lat < NBLat[i+1]
127  int i = int(ABS(lat)/15.0)-1;
128 
129  if(i>=0 && i<=3) { // mid-latitude -> regular interpolation
130  double m=(ABS(lat)-NBLat[i])/(NBLat[i+1]-NBLat[i]);
131  ret = pave[i]+m*(pave[i+1]-pave[i]);
132  if(entry < Maw)
133  ret -= (pamp[i]+m*(pamp[i+1]-pamp[i]))
134  * std::cos(TWO_PI*(day-28.0)/365.25);
135  }
136  else { // < 15 or > 75 -> simpler interpolation
137  if(i<0) i=0; else i=4;
138  ret = pave[i];
139  if(entry < Maw)
140  ret -= pamp[i]*std::cos(TWO_PI*(day-28.0)/365.25);
141  }
142 
143  return ret;
144 
145  } // end double NB_Interpolate(lat,doy,entry)
146 
147 
149  validWeather(false), validRxLatitude(false),
150  validDOY(false), validRxHeight(false)
151  {}
152 
153 
154  NBTropModel::NBTropModel(const double& lat,
155  const int& day)
156  : validWeather(false), validRxLatitude(false), validDOY(false),
157  validRxHeight(false)
158  {
159  setReceiverLatitude(lat);
160  setDayOfYear(day);
161  setWeather();
162  }
163 
164 
165  NBTropModel::NBTropModel(const double& lat,
166  const int& day,
167  const WxObservation& wx)
168  : validWeather(false), validRxLatitude(false), validDOY(false),
169  validRxHeight(false)
170  {
171  setReceiverLatitude(lat);
172  setDayOfYear(day);
173  setWeather(wx);
174  }
175 
176 
177  NBTropModel::NBTropModel(const double& lat,
178  const int& day,
179  const double& T,
180  const double& P,
181  const double& H)
182  : validWeather(false), validRxLatitude(false), validDOY(false),
183  validRxHeight(false)
184  {
185  setReceiverLatitude(lat);
186  setDayOfYear(day);
187  setWeather(T,P,H);
188  }
189 
190 
191  NBTropModel::NBTropModel(const double& ht,
192  const double& lat,
193  const int& day)
194  : validWeather(false), validRxLatitude(false), validDOY(false),
195  validRxHeight(false)
196  {
197  setReceiverHeight(ht);
198  setReceiverLatitude(lat);
199  setDayOfYear(day);
200  setWeather();
201  }
202 
203 
204  // re-define this to get the throws
205  double NBTropModel::correction(double elevation) const
206  {
208 
209  if(elevation < 0.0) return 0.0;
210 
211  return (dry_zenith_delay() * dry_mapping_function(elevation)
212  + wet_zenith_delay() * wet_mapping_function(elevation));
213  }
214 
215 
217  const Position& SV,
218  const CommonTime& tt)
219  {
221 
222  // compute height and latitude from RX
225 
226  // compute day of year from tt
227  setDayOfYear(int((static_cast<YDSTime>(tt)).doy));
228 
229  return TropModel::correction(RX.elevation(SV));
230  }
231 
232 
233  double NBTropModel::correction(const Xvt& RX,
234  const Xvt& SV,
235  const CommonTime& tt)
236  {
237  Position R(RX),S(SV);
238  return NBTropModel::correction(R,S,tt);
239  }
240 
241 
243  {
245 
246  double beta = NB_Interpolate(latitude,doy,ZB);
247  double gm = 9.784*(1.0-2.66e-3*std::cos(2.0*latitude*DEG_TO_RAD)-2.8e-7*height);
248 
249  /* scale factors for height above mean sea level
250  * if weather is given, assume it's measured at ht -> kw=kd=1
251  */
252  double kd=1, base=std::log(1.0-beta*height/temp);
254  kd = std::exp(base*NBg/(NBRd*beta));
255 
256  // compute the zenith delay for dry component
257  return ((1.0e-6*NBk1*NBRd/gm) * kd * press);
258 
259  } // end NBTropModel::dry_zenith_delay()
260 
261 
263  {
265 
266  double beta = NB_Interpolate(latitude,doy,ZB);
267  double lam = NB_Interpolate(latitude,doy,ZL);
268  double gm = 9.784*(1.0-2.66e-3*std::cos(2.0*latitude*DEG_TO_RAD)-2.8e-7*height);
269 
270  /* scale factors for height above mean sea level
271  * if weather is given, assume it's measured at ht -> kw=kd=1
272  */
273  double kw=1, base=std::log(1.0-beta*height/temp);
275  kw = std::exp(base*(-1.0+(lam+1)*NBg/(NBRd*beta)));
276 
277  // compute the zenith delay for wet component
278  return ((1.0e-6*NBk3p*NBRd/(gm*(lam+1)-beta*NBRd)) * kw * humid/temp);
279 
280  } // end NBTropModel::wet_zenith_delay()
281 
282 
283  double NBTropModel::dry_mapping_function(double elevation) const
284  {
286 
287  if(elevation < 0.0) return 0.0;
288 
289  double a,b,c,se,map;
290  se = std::sin(elevation*DEG_TO_RAD);
291 
295  map = (1.0+a/(1.0+b/(1.0+c))) / (se+a/(se+b/(se+c)));
296 
297  a = 2.53e-5;
298  b = 5.49e-3;
299  c = 1.14e-3;
300  if(ABS(elevation)<=0.001) se=0.001;
301  map += ((1.0/se)-(1.0+a/(1.0+b/(1.0+c)))/(se+a/(se+b/(se+c))))*height/1000.0;
302 
303  return map;
304 
305  } // end NBTropModel::dry_mapping_function()
306 
307 
308  double NBTropModel::wet_mapping_function(double elevation) const
309  {
311 
312  if(elevation < 0.0) return 0.0;
313 
314  double a,b,c,se;
315  se = std::sin(elevation*DEG_TO_RAD);
319 
320  return ( (1.0+a/(1.0+b/(1.0+c))) / (se+a/(se+b/(se+c))) );
321 
322  } // end NBTropModel::wet_mapping_function()
323 
324 
325  void NBTropModel::setWeather(const double& T,
326  const double& P,
327  const double& H)
328  {
329  interpolateWeather=false;
331  // humid actually stores water vapor partial pressure
332  double th=300./temp;
333  humid = 2.409e9*H*th*th*th*th*std::exp(-22.64*th);
334  validWeather = true;
336 
337  } // end NBTropModel::setWeather()
338 
339 
341  {
342  interpolateWeather = false;
343  try
344  {
346  // humid actually stores vapor partial pressure
347  double th=300./temp;
348  humid = 2.409e9*humid*th*th*th*th*std::exp(-22.64*th);
349  validWeather = true;
351  }
352  catch(InvalidParameter& e)
353  {
354  valid = validWeather = false;
355  GNSSTK_RETHROW(e);
356  }
357  }
358 
359 
361  {
362  interpolateWeather = true;
363 
364  if(!validRxLatitude)
365  {
366  valid = validWeather = false;
367  InvalidTropModel e("NBTropModel must have Rx latitude before interpolating weather");
368  GNSSTK_THROW(e);
369  }
370  if(!validDOY)
371  {
372  valid = validWeather = false;
373  InvalidTropModel e("NBTropModel must have day of year before interpolating weather ");
374  GNSSTK_THROW(e);
375  }
379  validWeather = true;
381  }
382 
383 
384  void NBTropModel::setReceiverHeight(const double& ht)
385  {
386  height = ht;
387  validRxHeight = true;
390  setWeather();
391  }
392 
393 
394  void NBTropModel::setReceiverLatitude(const double& lat)
395  {
396  latitude = lat;
397  validRxLatitude = true;
400  setWeather();
401  }
402 
403 
404  void NBTropModel::setDayOfYear(const int& d)
405  {
406  doy = d;
407  if (doy > 0 && doy < 367) validDOY=true; else validDOY = false;
410  setWeather();
411  }
412 
413 }
gnsstk::TropModel::correction
virtual double correction(double elevation) const
Definition: TropModel.cpp:53
YDSTime.hpp
se
double se
obliquity cos, T*cos, sin coefficients
Definition: IERS2003NutationData.hpp:48
gnsstk::NBTropModel::dry_mapping_function
virtual double dry_mapping_function(double elevation) const
Definition: NBTropModel.cpp:283
gnsstk::NBTropModel::setReceiverLatitude
void setReceiverLatitude(const double &lat)
Definition: NBTropModel.cpp:394
gnsstk::NBk3p
static const double NBk3p
Definition: NBTropModel.cpp:55
gnsstk::NBTropModel::wet_mapping_function
virtual double wet_mapping_function(double elevation) const
Definition: NBTropModel.cpp:308
example6.day
day
Definition: example6.py:66
gnsstk::NBTropModel::interpolateWeather
bool interpolateWeather
Definition: NBTropModel.hpp:189
gnsstk::NBTropModel::height
double height
Definition: NBTropModel.hpp:190
gnsstk::YDSTime
Definition: YDSTime.hpp:58
gnsstk::NBTropModel::validRxHeight
bool validRxHeight
Definition: NBTropModel.hpp:195
gnsstk::NBMcd
static const double NBMcd[5]
Definition: NBTropModel.cpp:78
gnsstk::Mbw
@ Mbw
Definition: NBTropModel.cpp:98
gnsstk::NBZWa
static const double NBZWa[5]
Definition: NBTropModel.cpp:69
gnsstk::WxObservation
A Single Weather Observation.
Definition: WxObsMap.hpp:55
NULL
#define NULL
Definition: getopt1.c:64
gnsstk::TWO_PI
const double TWO_PI
GPS value of PI*2.
Definition: GNSSconstants.hpp:68
gnsstk::NBTropModel::setDayOfYear
void setDayOfYear(const int &d)
Definition: NBTropModel.cpp:404
gnsstk::NBZW0
static const double NBZW0[5]
Definition: NBTropModel.cpp:62
gnsstk::NBMad
static const double NBMad[5]
Definition: NBTropModel.cpp:74
gnsstk::NBTropModel::doy
int doy
Definition: NBTropModel.hpp:192
gnsstk
For Sinex::InputHistory.
Definition: BasicFramework.cpp:50
std::sin
double sin(gnsstk::Angle x)
Definition: Angle.hpp:144
gnsstk::ZL
@ ZL
Definition: NBTropModel.cpp:98
gnsstk::NBZBa
static const double NBZBa[5]
Definition: NBTropModel.cpp:70
gnsstk::TropModel::humid
double humid
latest value of relative humidity (percent)
Definition: TropModel.hpp:282
gnsstk::NBMaw
static const double NBMaw[5]
Definition: NBTropModel.cpp:90
gnsstk::NBg
static const double NBg
Definition: NBTropModel.cpp:53
gnsstk::Position::getHeight
double getHeight() const noexcept
return height above ellipsoid (meters)
Definition: Position.hpp:474
gnsstk::Mbd
@ Mbd
Definition: NBTropModel.cpp:98
gnsstk::NBMaa
static const double NBMaa[5]
Definition: NBTropModel.cpp:82
gnsstk::NBMba
static const double NBMba[5]
Definition: NBTropModel.cpp:84
gnsstk::NB_Interpolate
static double NB_Interpolate(double lat, int doy, TableEntry entry)
Definition: NBTropModel.cpp:101
gnsstk::ZB
@ ZB
Definition: NBTropModel.cpp:98
gnsstk::NBTropModel::validWeather
bool validWeather
Definition: NBTropModel.hpp:193
gnsstk::NBLat
static const double NBLat[5]
Definition: NBTropModel.cpp:57
gnsstk::NBZLa
static const double NBZLa[5]
Definition: NBTropModel.cpp:71
gnsstk::Position::getGeodeticLatitude
double getGeodeticLatitude() const noexcept
return geodetic latitude (deg N)
Definition: Position.hpp:454
gnsstk::NBk1
static const double NBk1
Definition: NBTropModel.cpp:54
gnsstk::CommonTime
Definition: CommonTime.hpp:84
log
#define log
Definition: DiscCorr.cpp:625
NBTropModel.hpp
gnsstk::Mcw
@ Mcw
Definition: NBTropModel.cpp:98
gnsstk::Xvt
Definition: Xvt.hpp:60
gnsstk::NBZP0
static const double NBZP0[5]
Definition: NBTropModel.cpp:60
gnsstk::TropModel::valid
bool valid
true only if current model parameters are valid
Definition: TropModel.hpp:279
THROW_IF_INVALID_DETAILED
#define THROW_IF_INVALID_DETAILED()
Definition: NBTropModel.cpp:42
std::cos
double cos(gnsstk::Angle x)
Definition: Angle.hpp:146
gnsstk::beta
double beta(double x, double y)
Definition: SpecialFuncs.cpp:204
gnsstk::TropModel::press
double press
latest value of pressure (millibars)
Definition: TropModel.hpp:281
GNSSTK_RETHROW
#define GNSSTK_RETHROW(exc)
Definition: Exception.hpp:369
gnsstk::NBTropModel::latitude
double latitude
Definition: NBTropModel.hpp:191
gnsstk::TableEntry
TableEntry
Definition: NBTropModel.cpp:98
gnsstk::NBZT0
static const double NBZT0[5]
Definition: NBTropModel.cpp:61
gnsstk::TrackingCode::P
@ P
Legacy GPS precise code.
gnsstk::ZP
@ ZP
Definition: NBTropModel.cpp:98
ABS
#define ABS(x)
Definition: MathBase.hpp:73
gnsstk::NBTropModel::correction
virtual double correction(double elevation) const
Definition: NBTropModel.cpp:205
gnsstk::NBTropModel::NBTropModel
NBTropModel()
Empty constructor.
Definition: NBTropModel.cpp:148
gnsstk::Mcd
@ Mcd
Definition: NBTropModel.cpp:98
gnsstk::NBTropModel::wet_zenith_delay
virtual double wet_zenith_delay() const
Definition: NBTropModel.cpp:262
gnsstk::NBMbw
static const double NBMbw[5]
Definition: NBTropModel.cpp:92
gnsstk::NBMca
static const double NBMca[5]
Definition: NBTropModel.cpp:86
gnsstk::TropModel::setWeather
virtual void setWeather(const double &T, const double &P, const double &H)
Definition: TropModel.cpp:85
gnsstk::NBZTa
static const double NBZTa[5]
Definition: NBTropModel.cpp:68
gnsstk::NBTropModel::validRxLatitude
bool validRxLatitude
Definition: NBTropModel.hpp:194
gnsstk::NBZL0
static const double NBZL0[5]
Definition: NBTropModel.cpp:64
gnsstk::Position
Definition: Position.hpp:136
gnsstk::NBTropModel::setWeather
void setWeather()
Definition: NBTropModel.cpp:360
GNSSTK_THROW
#define GNSSTK_THROW(exc)
Definition: Exception.hpp:366
gnsstk::NBRd
static const double NBRd
Definition: NBTropModel.cpp:52
gnsstk::TropModel::temp
double temp
latest value of temperature (kelvin or celsius)
Definition: TropModel.hpp:280
gnsstk::NBMbd
static const double NBMbd[5]
Definition: NBTropModel.cpp:76
gnsstk::Maw
@ Maw
Definition: NBTropModel.cpp:98
gnsstk::NBZPa
static const double NBZPa[5]
Definition: NBTropModel.cpp:67
gnsstk::ZW
@ ZW
Definition: NBTropModel.cpp:98
gnsstk::NBTropModel::dry_zenith_delay
virtual double dry_zenith_delay() const
Definition: NBTropModel.cpp:242
gnsstk::ZT
@ ZT
Definition: NBTropModel.cpp:98
gnsstk::NBTropModel::validDOY
bool validDOY
Definition: NBTropModel.hpp:196
gnsstk::NBZB0
static const double NBZB0[5]
Definition: NBTropModel.cpp:63
gnsstk::Position::elevation
double elevation(const Position &Target) const
Definition: Position.cpp:1308
gnsstk::NBTropModel::setReceiverHeight
void setReceiverHeight(const double &ht)
Definition: NBTropModel.cpp:384
gnsstk::NBMcw
static const double NBMcw[5]
Definition: NBTropModel.cpp:94
gnsstk::Mad
@ Mad
Definition: NBTropModel.cpp:98
gnsstk::DEG_TO_RAD
static const double DEG_TO_RAD
Conversion Factor from degrees to radians (units: degrees^-1)
Definition: GNSSconstants.hpp:76


gnsstk
Author(s):
autogenerated on Wed Oct 25 2023 02:40:40