INSTINCT Code Coverage Report


Directory: src/
File: Navigation/Atmosphere/Troposphere/Models/GPT.cpp
Date: 2025-02-07 16:54:41
Exec Total Coverage
Lines: 299 309 96.8%
Functions: 4 5 80.0%
Branches: 293 568 51.6%

Line Branch Exec Source
1 // This file is part of INSTINCT, the INS Toolkit for Integrated
2 // Navigation Concepts and Training by the Institute of Navigation of
3 // the University of Stuttgart, Germany.
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
9 #include "GPT.hpp"
10
11 #include <array>
12 #include <cmath>
13
14 #include "internal/GPT2Coeffs.hpp"
15 #include "internal/GPT3Coeffs.hpp"
16
17 #include "Navigation/Constants.hpp"
18 #include "Navigation/Math/Math.hpp"
19
20 namespace NAV
21 {
22 725 GPT2output GPT2_param(const double& mjd, const Eigen::Vector3d& lla_pos)
23 {
24 using internal::GPT2_grid;
25
26 725 GPT2output gpt2outputs;
27
28 // change the reference epoch to January 1 2000
29 725 double mjd1 = mjd - 51544.5;
30 // GPT2 with time variation
31 725 double cosfy = cos(mjd1 / 365.25 * 2.0 * M_PI);
32 725 double coshy = cos(mjd1 / 365.25 * 4.0 * M_PI);
33 725 double sinfy = sin(mjd1 / 365.25 * 2.0 * M_PI);
34 725 double sinhy = sin(mjd1 / 365.25 * 4.0 * M_PI);
35
36
1/2
✓ Branch 1 taken 725 times.
✗ Branch 2 not taken.
725 double dlat = lla_pos(0);
37
1/2
✓ Branch 1 taken 725 times.
✗ Branch 2 not taken.
725 double dlon = lla_pos(1);
38
1/2
✓ Branch 1 taken 725 times.
✗ Branch 2 not taken.
725 double hell = lla_pos(2);
39
40 // only positive longitude in degrees
41
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 725 times.
725 double plon = dlon < 0.0 ? (dlon + 2.0 * M_PI) * 180.0 / M_PI : dlon * 180.0 / M_PI;
42
43 // transform to polar distance in degrees
44 725 double ppod = (-dlat + M_PI / 2.0) * 180.0 / M_PI;
45
46 // find the index (line in the grid file) of the nearest point
47 725 auto ipod = static_cast<int>(floor(ppod + 1.0));
48 725 auto ilon = static_cast<int>(floor(plon + 1.0));
49
50 // normalized (to one) differences, can be positive or negative
51 725 double diffpod = ppod - (ipod - 0.5);
52 725 double difflon = plon - (ilon - 0.5);
53
54 // added by HCY
55
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 689 times.
725 if (ipod == 181) { ipod = 180; }
56 // added by GP
57
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 725 times.
725 if (ilon == 361) { ilon = 1; }
58
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 725 times.
725 if (ilon == 0) { ilon = 360; }
59
60 725 constexpr size_t N = 4;
61 725 std::array<size_t, N> indx{};
62 // get the number of the corresponding line
63 725 indx[0] = static_cast<size_t>((ipod - 1) * 360 + ilon) - 1;
64
65 // near the poles: nearest neighbour interpolation
66 // otherwise: bilinear, with the 1 degree grid the limits are lower and upper (GP)
67
4/4
✓ Branch 0 taken 689 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 653 times.
725 if (ppod <= 0.5 || ppod >= 179.5) // case of nearest neighborhood
68 {
69 72 auto ix = indx[0];
70 // transforming ellipsoidal height to orthometric height
71
1/2
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
72 gpt2outputs.undu = GPT2_grid.at(ix).undulation; // undu: geoid undulation in m
72 72 double hgt = hell - gpt2outputs.undu;
73
74 // pressure, temperature at the height of the grid
75
5/10
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 72 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 72 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 72 times.
✗ Branch 14 not taken.
72 double T0 = GPT2_grid.at(ix).T_A0 + GPT2_grid.at(ix).T_A1 * cosfy + GPT2_grid.at(ix).T_B1 * sinfy + GPT2_grid.at(ix).T_A2 * coshy + GPT2_grid.at(ix).T_B2 * sinhy;
76
5/10
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 72 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 72 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 72 times.
✗ Branch 14 not taken.
72 double p0 = GPT2_grid.at(ix).p_A0 + GPT2_grid.at(ix).p_A1 * cosfy + GPT2_grid.at(ix).p_B1 * sinfy + GPT2_grid.at(ix).p_A2 * coshy + GPT2_grid.at(ix).p_B2 * sinhy;
77
78 // specific humidity
79
5/10
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 72 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 72 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 72 times.
✗ Branch 14 not taken.
72 double Q = (GPT2_grid.at(ix).Q_A0 + GPT2_grid.at(ix).Q_A1 * cosfy + GPT2_grid.at(ix).Q_B1 * sinfy + GPT2_grid.at(ix).Q_A2 * coshy + GPT2_grid.at(ix).Q_B2 * sinhy)
80 72 / 1e3;
81
82 // lapse rate of the temperature
83
5/10
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 72 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 72 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 72 times.
✗ Branch 14 not taken.
72 gpt2outputs.dT = (GPT2_grid.at(ix).dT_A0 + GPT2_grid.at(ix).dT_A1 * cosfy + GPT2_grid.at(ix).dT_B1 * sinfy + GPT2_grid.at(ix).dT_A2 * coshy + GPT2_grid.at(ix).dT_B2 * sinhy)
84 72 / 1e3;
85
86 // station height - grid height
87
1/2
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
72 double redh = hgt - GPT2_grid.at(ix).Hs; // Hs: orthometric grid height in m
88
89 // temperature at station height in Celsius
90 72 gpt2outputs.T = T0 + gpt2outputs.dT * redh - 273.150;
91
92 // temperature lapse rate in degrees / km
93 72 gpt2outputs.dT = gpt2outputs.dT * 1e3;
94
95 // virtual temperature in Kelvin
96 72 double Tv = T0 * (1 + 0.6077 * Q);
97
98 72 double c = InsConst::G_NORM * InsConst::dMtr / (InsConst::Rg * Tv);
99
100 // pressure in hPa
101 72 gpt2outputs.p = (p0 * exp(-c * redh)) / 100.0;
102
103 // hydrostatic coefficient ah
104
5/10
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 72 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 72 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 72 times.
✗ Branch 14 not taken.
72 gpt2outputs.ah = (GPT2_grid.at(ix).h_A0 + GPT2_grid.at(ix).h_A1 * cosfy + GPT2_grid.at(ix).h_B1 * sinfy + GPT2_grid.at(ix).h_A2 * coshy + GPT2_grid.at(ix).h_B2 * sinhy)
105 72 / 1e3;
106
107 // wet coefficient aw
108
5/10
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 72 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 72 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 72 times.
✗ Branch 14 not taken.
72 gpt2outputs.aw = (GPT2_grid.at(ix).w_A0 + GPT2_grid.at(ix).w_A1 * cosfy + GPT2_grid.at(ix).w_B1 * sinfy + GPT2_grid.at(ix).w_A2 * coshy + GPT2_grid.at(ix).w_B2 * sinhy)
109 72 / 1e3;
110
111 // water vapour decrease factor la - added by GP
112
5/10
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 72 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 72 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 72 times.
✗ Branch 14 not taken.
72 gpt2outputs.la = GPT2_grid.at(ix).la_A0 + GPT2_grid.at(ix).la_A1 * cosfy + GPT2_grid.at(ix).la_B1 * sinfy + GPT2_grid.at(ix).la_A2 * coshy + GPT2_grid.at(ix).la_B2 * sinhy;
113
114 // mean temperature of the water vapor Tm - added by GP
115
5/10
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 72 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 72 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 72 times.
✗ Branch 14 not taken.
72 gpt2outputs.Tm = GPT2_grid.at(ix).Tm_A0 + GPT2_grid.at(ix).Tm_A1 * cosfy + GPT2_grid.at(ix).Tm_B1 * sinfy + GPT2_grid.at(ix).Tm_A2 * coshy + GPT2_grid.at(ix).Tm_B2 * sinhy;
116
117 // water vapor pressure in hPa - changed by GP
118 72 double e0 = Q * p0 / (0.622 + 0.378 * Q) / 100.0; // on the grid
119
120 72 gpt2outputs.e = e0 * pow((100.0 * gpt2outputs.p / p0), (gpt2outputs.la + 1)); // on the station height - (14) Askne and Nordius, 1987
121 72 }
122 else // bilinear interpolation
123 {
124 653 double ipod1 = ipod + int(math::sign(1.0, diffpod));
125 653 double ilon1 = ilon + int(math::sign(1.0, difflon));
126
127 // changed for the 1 degree grid (GP)
128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 653 times.
653 if (ilon1 == 361) { ilon1 = 1; }
129
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 636 times.
653 if (ilon1 == 0) { ilon1 = 360; }
130 // get the number of the line
131 653 indx[1] = static_cast<size_t>((ipod1 - 1) * 360 + ilon) - 1; // along same longitude
132 653 indx[2] = static_cast<size_t>((ipod - 1) * 360 + ilon1) - 1; // along same polar distance
133 653 indx[3] = static_cast<size_t>((ipod1 - 1) * 360 + ilon1) - 1; // diagonal
134
135 653 std::array<double, N> undul{};
136 653 std::array<double, N> Ql{};
137 653 std::array<double, N> dTl{};
138 653 std::array<double, N> Tl{};
139 653 std::array<double, N> pl{};
140 653 std::array<double, N> ahl{};
141 653 std::array<double, N> awl{};
142 653 std::array<double, N> lal{};
143 653 std::array<double, N> Tml{};
144 653 std::array<double, N> el{};
145
146
2/2
✓ Branch 0 taken 2612 times.
✓ Branch 1 taken 653 times.
3265 for (size_t l = 0; l < N; l++)
147 {
148 // transforming ellipsoidal height to orthometric height:
149 // Hortho = -N + Hell
150
1/2
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
2612 auto ix = indx.at(l);
151
152
2/4
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
2612 undul.at(l) = GPT2_grid.at(ix).undulation; // undu: geoid undulation in m
153
1/2
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
2612 double hgt = hell - undul.at(l);
154
155 // pressure, temperature at the height of the grid
156
5/10
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2612 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2612 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2612 times.
✗ Branch 14 not taken.
2612 double T0 = GPT2_grid.at(ix).T_A0 + GPT2_grid.at(ix).T_A1 * cosfy + GPT2_grid.at(ix).T_B1 * sinfy + GPT2_grid.at(ix).T_A2 * coshy + GPT2_grid.at(ix).T_B2 * sinhy;
157
5/10
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2612 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2612 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2612 times.
✗ Branch 14 not taken.
2612 double p0 = GPT2_grid.at(ix).p_A0 + GPT2_grid.at(ix).p_A1 * cosfy + GPT2_grid.at(ix).p_B1 * sinfy + GPT2_grid.at(ix).p_A2 * coshy + GPT2_grid.at(ix).p_B2 * sinhy;
158
159 // humidity
160
5/10
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2612 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2612 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2612 times.
✗ Branch 14 not taken.
2612 Ql.at(l) = (GPT2_grid.at(ix).Q_A0 + GPT2_grid.at(ix).Q_A1 * cosfy + GPT2_grid.at(ix).Q_B1 * sinfy + GPT2_grid.at(ix).Q_A2 * coshy + GPT2_grid.at(ix).Q_B2 * sinhy)
161
1/2
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
2612 / 1e3;
162
163 // reduction = stationheight - gridheight
164
1/2
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
2612 double redh = hgt - GPT2_grid.at(ix).Hs; // Hs: orthometric grid height in m
165
166 // lapse rate of the temperature in degree / m
167
5/10
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2612 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2612 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2612 times.
✗ Branch 14 not taken.
2612 dTl.at(l) = (GPT2_grid.at(ix).dT_A0 + GPT2_grid.at(ix).dT_A1 * cosfy + GPT2_grid.at(ix).dT_B1 * sinfy + GPT2_grid.at(ix).dT_A2 * coshy + GPT2_grid.at(ix).dT_B2 * sinhy)
168
1/2
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
2612 / 1e3;
169
170 // temperature reduction to station height
171
2/4
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
2612 Tl.at(l) = T0 + dTl.at(l) * redh - 273.150;
172
173 // virtual temperature
174
1/2
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
2612 double Tv = T0 * (1 + 0.6077 * Ql.at(l));
175 2612 double c = InsConst::G_NORM * InsConst::dMtr / (InsConst::Rg * Tv);
176
177 // pressure in hPa
178
1/2
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
2612 pl.at(l) = (p0 * exp(-c * redh)) / 100.0;
179
180 // hydrostatic coefficient ah
181
5/10
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2612 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2612 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2612 times.
✗ Branch 14 not taken.
2612 ahl.at(l) = (GPT2_grid.at(ix).h_A0 + GPT2_grid.at(ix).h_A1 * cosfy + GPT2_grid.at(ix).h_B1 * sinfy + GPT2_grid.at(ix).h_A2 * coshy + GPT2_grid.at(ix).h_B2 * sinhy)
182
1/2
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
2612 / 1e3;
183
184 // wet coefficient aw
185
5/10
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2612 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2612 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2612 times.
✗ Branch 14 not taken.
2612 awl.at(l) = (GPT2_grid.at(ix).w_A0 + GPT2_grid.at(ix).w_A1 * cosfy + GPT2_grid.at(ix).w_B1 * sinfy + GPT2_grid.at(ix).w_A2 * coshy + GPT2_grid.at(ix).w_B2 * sinhy)
186
1/2
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
2612 / 1e3;
187
188 // water vapor decrease factor la - added by GP
189
6/12
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2612 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2612 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2612 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 2612 times.
✗ Branch 17 not taken.
2612 lal.at(l) = GPT2_grid.at(ix).la_A0 + GPT2_grid.at(ix).la_A1 * cosfy + GPT2_grid.at(ix).la_B1 * sinfy + GPT2_grid.at(ix).la_A2 * coshy + GPT2_grid.at(ix).la_B2 * sinhy;
190
191 // mean temperature of the water vapor Tm - added by GP
192
6/12
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2612 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2612 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2612 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 2612 times.
✗ Branch 17 not taken.
2612 Tml.at(l) = GPT2_grid.at(ix).Tm_A0 + GPT2_grid.at(ix).Tm_A1 * cosfy + GPT2_grid.at(ix).Tm_B1 * sinfy + GPT2_grid.at(ix).Tm_A2 * coshy + GPT2_grid.at(ix).Tm_B2 * sinhy;
193
194 // water vapor pressure in hPa - changed by GP
195
2/4
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
2612 double e0 = Ql.at(l) * p0 / (0.622 + 0.378 * Ql.at(l)) / 100.0; // on the grid
196
197
3/6
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2612 times.
✗ Branch 8 not taken.
2612 el.at(l) = e0 * pow((100.0 * pl.at(l) / p0), (lal.at(l) + 1.0)); // on the station height (14) Askne and Nordius, 1987
198 }
199
200 653 double dnpod1 = fabs(diffpod); // distance nearer point
201 653 double dnpod2 = 1.0 - dnpod1; // distance to distant point
202 653 double dnlon1 = fabs(difflon);
203 653 double dnlon2 = 1.0 - dnlon1;
204
205 // pressure
206 653 double R1 = dnpod2 * pl[0] + dnpod1 * pl[1];
207 653 double R2 = dnpod2 * pl[2] + dnpod1 * pl[3];
208 653 gpt2outputs.p = dnlon2 * R1 + dnlon1 * R2;
209
210 // temperature
211 653 R1 = dnpod2 * Tl[0] + dnpod1 * Tl[1];
212 653 R2 = dnpod2 * Tl[2] + dnpod1 * Tl[3];
213 653 gpt2outputs.T = dnlon2 * R1 + dnlon1 * R2;
214
215 // temperature in degree per km
216 653 R1 = dnpod2 * dTl[0] + dnpod1 * dTl[1];
217 653 R2 = dnpod2 * dTl[2] + dnpod1 * dTl[3];
218 653 gpt2outputs.dT = (dnlon2 * R1 + dnlon1 * R2) * 1e3;
219
220 // water vapor pressure in hPa - changed by GP
221 653 R1 = dnpod2 * el[0] + dnpod1 * el[1];
222 653 R2 = dnpod2 * el[2] + dnpod1 * el[3];
223 653 gpt2outputs.e = dnlon2 * R1 + dnlon1 * R2;
224
225 // hydrostatic
226 653 R1 = dnpod2 * ahl[0] + dnpod1 * ahl[1];
227 653 R2 = dnpod2 * ahl[2] + dnpod1 * ahl[3];
228 653 gpt2outputs.ah = dnlon2 * R1 + dnlon1 * R2;
229
230 // wet
231 653 R1 = dnpod2 * awl[0] + dnpod1 * awl[1];
232 653 R2 = dnpod2 * awl[2] + dnpod1 * awl[3];
233 653 gpt2outputs.aw = dnlon2 * R1 + dnlon1 * R2;
234
235 // undulation
236 653 R1 = dnpod2 * undul[0] + dnpod1 * undul[1];
237 653 R2 = dnpod2 * undul[2] + dnpod1 * undul[3];
238 653 gpt2outputs.undu = dnlon2 * R1 + dnlon1 * R2;
239
240 // water vapor decrease factor la - added by GP
241 653 R1 = dnpod2 * lal[0] + dnpod1 * lal[1];
242 653 R2 = dnpod2 * lal[2] + dnpod1 * lal[3];
243 653 gpt2outputs.la = dnlon2 * R1 + dnlon1 * R2;
244
245 // mean temperature of the water vapor - added by GP
246 653 R1 = dnpod2 * Tml[0] + dnpod1 * Tml[1];
247 653 R2 = dnpod2 * Tml[2] + dnpod1 * Tml[3];
248 653 gpt2outputs.Tm = dnlon2 * R1 + dnlon1 * R2;
249 }
250
251 1450 return gpt2outputs;
252 }
253
254 725 GPT3output GPT3_param(const double& mjd, const Eigen::Vector3d& lla_pos)
255 {
256 using internal::GPT3_grid;
257
258 725 GPT3output gpt3outputs;
259
260 // convert mjd to doy
261
1/2
✓ Branch 1 taken 725 times.
✗ Branch 2 not taken.
725 double doy = mjd2doy(mjd);
262 // factors for amplitudes
263 725 double cosfy = cos(doy / 365.25 * 2.0 * M_PI);
264 725 double coshy = cos(doy / 365.25 * 4.0 * M_PI);
265 725 double sinfy = sin(doy / 365.25 * 2.0 * M_PI);
266 725 double sinhy = sin(doy / 365.25 * 4.0 * M_PI);
267
268
1/2
✓ Branch 1 taken 725 times.
✗ Branch 2 not taken.
725 double dlat = lla_pos(0);
269
1/2
✓ Branch 1 taken 725 times.
✗ Branch 2 not taken.
725 double dlon = lla_pos(1);
270
1/2
✓ Branch 1 taken 725 times.
✗ Branch 2 not taken.
725 double hell = lla_pos(2);
271
272 // only positive longitude in degrees
273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 725 times.
725 double plon = dlon < 0.0 ? (dlon + 2.0 * M_PI) * 180.0 / M_PI : dlon * 180.0 / M_PI;
274
275 // transform to polar distance in degrees
276 725 double ppod = (-dlat + M_PI / 2.0) * 180.0 / M_PI;
277
278 // find the index (line in the grid file) of the nearest point
279 725 auto ipod = static_cast<int>(floor(ppod + 1.0));
280 725 auto ilon = static_cast<int>(floor(plon + 1.0));
281
282 // normalized (to one) differences, can be positive or negative
283 725 double diffpod = ppod - (ipod - 0.5);
284 725 double difflon = plon - (ilon - 0.5);
285
286 // added by HCY
287
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 689 times.
725 if (ipod == 181) { ipod = 180; }
288 // added by GP
289
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 725 times.
725 if (ilon == 361) { ilon = 1; }
290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 725 times.
725 if (ilon == 0) { ilon = 360; }
291
292 725 constexpr size_t N = 4;
293 725 std::array<size_t, N> indx{};
294 // get the number of the corresponding line
295 725 indx[0] = static_cast<size_t>((ipod - 1) * 360 + ilon) - 1;
296
297 // near the poles: nearest neighbour interpolation
298 // otherwise: bilinear, with the 1 degree grid the limits are lower and upper (GP)
299
4/4
✓ Branch 0 taken 689 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 653 times.
725 if (ppod <= 0.5 || ppod >= 179.5) // case of nearest neighborhood
300 {
301 72 auto ix = indx[0];
302 // transforming ellipsoidal height to orthometric height
303
1/2
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
72 gpt3outputs.undu = GPT3_grid.at(ix).undulation; // undu: geoid undulation in m
304 72 double hgt = hell - gpt3outputs.undu;
305
306 // pressure, temperature at the height of the grid
307
5/10
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 72 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 72 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 72 times.
✗ Branch 14 not taken.
72 double T0 = GPT3_grid.at(ix).T_A0 + GPT3_grid.at(ix).T_A1 * cosfy + GPT3_grid.at(ix).T_B1 * sinfy + GPT3_grid.at(ix).T_A2 * coshy + GPT3_grid.at(ix).T_B2 * sinhy;
308
5/10
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 72 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 72 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 72 times.
✗ Branch 14 not taken.
72 double p0 = GPT3_grid.at(ix).p_A0 + GPT3_grid.at(ix).p_A1 * cosfy + GPT3_grid.at(ix).p_B1 * sinfy + GPT3_grid.at(ix).p_A2 * coshy + GPT3_grid.at(ix).p_B2 * sinhy;
309
310 // specific humidity
311
5/10
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 72 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 72 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 72 times.
✗ Branch 14 not taken.
72 double Q = (GPT3_grid.at(ix).Q_A0 + GPT3_grid.at(ix).Q_A1 * cosfy + GPT3_grid.at(ix).Q_B1 * sinfy + GPT3_grid.at(ix).Q_A2 * coshy + GPT3_grid.at(ix).Q_B2 * sinhy)
312 72 / 1e3;
313
314 // lapse rate of the temperature
315
5/10
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 72 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 72 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 72 times.
✗ Branch 14 not taken.
72 gpt3outputs.dT = (GPT3_grid.at(ix).dT_A0 + GPT3_grid.at(ix).dT_A1 * cosfy + GPT3_grid.at(ix).dT_B1 * sinfy + GPT3_grid.at(ix).dT_A2 * coshy + GPT3_grid.at(ix).dT_B2 * sinhy)
316 72 / 1e3;
317
318 // station height - grid height
319
1/2
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
72 double redh = hgt - GPT3_grid.at(ix).Hs; // Hs: orthometric grid height in m
320
321 // temperature at station height in Celsius
322 72 gpt3outputs.T = T0 + gpt3outputs.dT * redh - 273.150;
323
324 // temperature lapse rate in degrees / km
325 72 gpt3outputs.dT = gpt3outputs.dT * 1e3;
326
327 // virtual temperature in Kelvin
328 72 double Tv = T0 * (1 + 0.6077 * Q);
329
330 72 double c = InsConst::G_NORM * InsConst::dMtr / (InsConst::Rg * Tv);
331
332 // pressure in hPa
333 72 gpt3outputs.p = (p0 * exp(-c * redh)) / 100.0;
334
335 // hydrostatic coefficient ah
336
5/10
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 72 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 72 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 72 times.
✗ Branch 14 not taken.
72 gpt3outputs.ah = (GPT3_grid.at(ix).h_A0 + GPT3_grid.at(ix).h_A1 * cosfy + GPT3_grid.at(ix).h_B1 * sinfy + GPT3_grid.at(ix).h_A2 * coshy + GPT3_grid.at(ix).h_B2 * sinhy)
337 72 / 1e3;
338
339 // wet coefficient aw
340
5/10
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 72 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 72 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 72 times.
✗ Branch 14 not taken.
72 gpt3outputs.aw = (GPT3_grid.at(ix).w_A0 + GPT3_grid.at(ix).w_A1 * cosfy + GPT3_grid.at(ix).w_B1 * sinfy + GPT3_grid.at(ix).w_A2 * coshy + GPT3_grid.at(ix).w_B2 * sinhy)
341 72 / 1e3;
342
343 // water vapour decrease factor la - added by GP
344
5/10
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 72 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 72 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 72 times.
✗ Branch 14 not taken.
72 gpt3outputs.la = GPT3_grid.at(ix).la_A0 + GPT3_grid.at(ix).la_A1 * cosfy + GPT3_grid.at(ix).la_B1 * sinfy + GPT3_grid.at(ix).la_A2 * coshy + GPT3_grid.at(ix).la_B2 * sinhy;
345
346 // mean temperature of the water vapor Tm - added by GP
347
5/10
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 72 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 72 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 72 times.
✗ Branch 14 not taken.
72 gpt3outputs.Tm = GPT3_grid.at(ix).Tm_A0 + GPT3_grid.at(ix).Tm_A1 * cosfy + GPT3_grid.at(ix).Tm_B1 * sinfy + GPT3_grid.at(ix).Tm_A2 * coshy + GPT3_grid.at(ix).Tm_B2 * sinhy;
348
349 // water vapor pressure in hPa - changed by GP
350 72 double e0 = Q * p0 / (0.622 + 0.378 * Q) / 100.0; // on the grid
351
352 72 gpt3outputs.e = e0 * pow((100.0 * gpt3outputs.p / p0), (gpt3outputs.la + 1)); // on the station height - (14) Askne and Nordius, 1987
353
354 // north and east gradients (total, hydrostatic and wet)
355
5/10
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 72 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 72 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 72 times.
✗ Branch 14 not taken.
72 gpt3outputs.Gn_h = (GPT3_grid.at(ix).Gnh_A0 + GPT3_grid.at(ix).Gnh_A1 * cosfy + GPT3_grid.at(ix).Gnh_B1 * sinfy + GPT3_grid.at(ix).Gnh_A2 * coshy + GPT3_grid.at(ix).Gnh_B2 * sinhy)
356 72 / 1e5;
357
5/10
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 72 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 72 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 72 times.
✗ Branch 14 not taken.
72 gpt3outputs.Ge_h = (GPT3_grid.at(ix).Geh_A0 + GPT3_grid.at(ix).Geh_A1 * cosfy + GPT3_grid.at(ix).Geh_B1 * sinfy + GPT3_grid.at(ix).Geh_A2 * coshy + GPT3_grid.at(ix).Geh_B2 * sinhy)
358 72 / 1e5;
359
5/10
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 72 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 72 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 72 times.
✗ Branch 14 not taken.
72 gpt3outputs.Gn_w = (GPT3_grid.at(ix).Gnw_A0 + GPT3_grid.at(ix).Gnw_A1 * cosfy + GPT3_grid.at(ix).Gnw_B1 * sinfy + GPT3_grid.at(ix).Gnw_A2 * coshy + GPT3_grid.at(ix).Gnw_B2 * sinhy)
360 72 / 1e5;
361
5/10
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 72 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 72 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 72 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 72 times.
✗ Branch 14 not taken.
72 gpt3outputs.Ge_w = (GPT3_grid.at(ix).Gew_A0 + GPT3_grid.at(ix).Gew_A1 * cosfy + GPT3_grid.at(ix).Gew_B1 * sinfy + GPT3_grid.at(ix).Gew_A2 * coshy + GPT3_grid.at(ix).Gew_B2 * sinhy)
362 72 / 1e5;
363 72 }
364 else // bilinear interpolation
365 {
366 653 double ipod1 = ipod + int(math::sign(1.0, diffpod));
367 653 double ilon1 = ilon + int(math::sign(1.0, difflon));
368
369 // changed for the 1 degree grid (GP)
370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 653 times.
653 if (ilon1 == 361) { ilon1 = 1; }
371
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 636 times.
653 if (ilon1 == 0) { ilon1 = 360; }
372 // get the number of the line
373 653 indx[1] = static_cast<size_t>((ipod1 - 1) * 360 + ilon) - 1; // along same longitude
374 653 indx[2] = static_cast<size_t>((ipod - 1) * 360 + ilon1) - 1; // along same polar distance
375 653 indx[3] = static_cast<size_t>((ipod1 - 1) * 360 + ilon1) - 1; // diagonal
376
377 653 std::array<double, N> undul{};
378 653 std::array<double, N> Ql{};
379 653 std::array<double, N> dTl{};
380 653 std::array<double, N> Tl{};
381 653 std::array<double, N> pl{};
382 653 std::array<double, N> ahl{};
383 653 std::array<double, N> awl{};
384 653 std::array<double, N> lal{};
385 653 std::array<double, N> Tml{};
386 653 std::array<double, N> el{};
387 653 std::array<double, N> Gn_hl{};
388 653 std::array<double, N> Ge_hl{};
389 653 std::array<double, N> Gn_wl{};
390 653 std::array<double, N> Ge_wl{};
391
392
2/2
✓ Branch 0 taken 2612 times.
✓ Branch 1 taken 653 times.
3265 for (size_t l = 0; l < N; l++)
393 {
394 // transforming ellipsoidal height to orthometric height:
395 // Hortho = -N + Hell
396
1/2
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
2612 auto ix = indx.at(l);
397
398
2/4
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
2612 undul.at(l) = GPT3_grid.at(ix).undulation; // undu: geoid undulation in m
399
1/2
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
2612 double hgt = hell - undul.at(l);
400
401 // pressure, temperature at the height of the grid
402
5/10
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2612 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2612 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2612 times.
✗ Branch 14 not taken.
2612 double T0 = GPT3_grid.at(ix).T_A0 + GPT3_grid.at(ix).T_A1 * cosfy + GPT3_grid.at(ix).T_B1 * sinfy + GPT3_grid.at(ix).T_A2 * coshy + GPT3_grid.at(ix).T_B2 * sinhy;
403
5/10
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2612 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2612 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2612 times.
✗ Branch 14 not taken.
2612 double p0 = GPT3_grid.at(ix).p_A0 + GPT3_grid.at(ix).p_A1 * cosfy + GPT3_grid.at(ix).p_B1 * sinfy + GPT3_grid.at(ix).p_A2 * coshy + GPT3_grid.at(ix).p_B2 * sinhy;
404
405 // humidity
406
5/10
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2612 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2612 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2612 times.
✗ Branch 14 not taken.
2612 Ql.at(l) = (GPT3_grid.at(ix).Q_A0 + GPT3_grid.at(ix).Q_A1 * cosfy + GPT3_grid.at(ix).Q_B1 * sinfy + GPT3_grid.at(ix).Q_A2 * coshy + GPT3_grid.at(ix).Q_B2 * sinhy)
407
1/2
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
2612 / 1e3;
408
409 // reduction = stationheight - gridheight
410
1/2
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
2612 double redh = hgt - GPT3_grid.at(ix).Hs; // Hs: orthometric grid height in m
411
412 // lapse rate of the temperature in degree / m
413
5/10
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2612 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2612 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2612 times.
✗ Branch 14 not taken.
2612 dTl.at(l) = (GPT3_grid.at(ix).dT_A0 + GPT3_grid.at(ix).dT_A1 * cosfy + GPT3_grid.at(ix).dT_B1 * sinfy + GPT3_grid.at(ix).dT_A2 * coshy + GPT3_grid.at(ix).dT_B2 * sinhy)
414
1/2
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
2612 / 1e3;
415
416 // temperature reduction to station height
417
2/4
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
2612 Tl.at(l) = T0 + dTl.at(l) * redh - 273.150;
418
419 // virtual temperature
420
1/2
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
2612 double Tv = T0 * (1 + 0.6077 * Ql.at(l));
421 2612 double c = InsConst::G_NORM * InsConst::dMtr / (InsConst::Rg * Tv);
422
423 // pressure in hPa
424
1/2
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
2612 pl.at(l) = (p0 * exp(-c * redh)) / 100.0;
425
426 // hydrostatic coefficient ah
427
5/10
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2612 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2612 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2612 times.
✗ Branch 14 not taken.
2612 ahl.at(l) = (GPT3_grid.at(ix).h_A0 + GPT3_grid.at(ix).h_A1 * cosfy + GPT3_grid.at(ix).h_B1 * sinfy + GPT3_grid.at(ix).h_A2 * coshy + GPT3_grid.at(ix).h_B2 * sinhy)
428
1/2
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
2612 / 1e3;
429
430 // wet coefficient aw
431
5/10
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2612 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2612 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2612 times.
✗ Branch 14 not taken.
2612 awl.at(l) = (GPT3_grid.at(ix).w_A0 + GPT3_grid.at(ix).w_A1 * cosfy + GPT3_grid.at(ix).w_B1 * sinfy + GPT3_grid.at(ix).w_A2 * coshy + GPT3_grid.at(ix).w_B2 * sinhy)
432
1/2
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
2612 / 1e3;
433
434 // water vapor decrease factor la - added by GP
435
6/12
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2612 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2612 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2612 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 2612 times.
✗ Branch 17 not taken.
2612 lal.at(l) = GPT3_grid.at(ix).la_A0 + GPT3_grid.at(ix).la_A1 * cosfy + GPT3_grid.at(ix).la_B1 * sinfy + GPT3_grid.at(ix).la_A2 * coshy + GPT3_grid.at(ix).la_B2 * sinhy;
436
437 // mean temperature of the water vapor Tm - added by GP
438
6/12
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2612 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2612 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2612 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 2612 times.
✗ Branch 17 not taken.
2612 Tml.at(l) = GPT3_grid.at(ix).Tm_A0 + GPT3_grid.at(ix).Tm_A1 * cosfy + GPT3_grid.at(ix).Tm_B1 * sinfy + GPT3_grid.at(ix).Tm_A2 * coshy + GPT3_grid.at(ix).Tm_B2 * sinhy;
439
440 // water vapor pressure in hPa - changed by GP
441
2/4
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
2612 double e0 = Ql.at(l) * p0 / (0.622 + 0.378 * Ql.at(l)) / 100.0; // on the grid
442
443
3/6
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2612 times.
✗ Branch 8 not taken.
2612 el.at(l) = e0 * pow((100.0 * pl.at(l) / p0), (lal.at(l) + 1.0)); // on the station height (14) Askne and Nordius, 1987
444
445 // north and east gradients (total, hydrostatic and wet)
446
5/10
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2612 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2612 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2612 times.
✗ Branch 14 not taken.
2612 Gn_hl.at(l) = (GPT3_grid.at(ix).Gnh_A0 + GPT3_grid.at(ix).Gnh_A1 * cosfy + GPT3_grid.at(ix).Gnh_B1 * sinfy + GPT3_grid.at(ix).Gnh_A2 * coshy + GPT3_grid.at(ix).Gnh_B2 * sinhy)
447
1/2
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
2612 / 1e5;
448
5/10
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2612 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2612 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2612 times.
✗ Branch 14 not taken.
2612 Ge_hl.at(l) = (GPT3_grid.at(ix).Geh_A0 + GPT3_grid.at(ix).Geh_A1 * cosfy + GPT3_grid.at(ix).Geh_B1 * sinfy + GPT3_grid.at(ix).Geh_A2 * coshy + GPT3_grid.at(ix).Geh_B2 * sinhy)
449
1/2
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
2612 / 1e5;
450
5/10
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2612 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2612 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2612 times.
✗ Branch 14 not taken.
2612 Gn_wl.at(l) = (GPT3_grid.at(ix).Gnw_A0 + GPT3_grid.at(ix).Gnw_A1 * cosfy + GPT3_grid.at(ix).Gnw_B1 * sinfy + GPT3_grid.at(ix).Gnw_A2 * coshy + GPT3_grid.at(ix).Gnw_B2 * sinhy)
451
1/2
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
2612 / 1e5;
452
5/10
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2612 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2612 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2612 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2612 times.
✗ Branch 14 not taken.
5224 Ge_wl.at(l) = (GPT3_grid.at(ix).Gew_A0 + GPT3_grid.at(ix).Gew_A1 * cosfy + GPT3_grid.at(ix).Gew_B1 * sinfy + GPT3_grid.at(ix).Gew_A2 * coshy + GPT3_grid.at(ix).Gew_B2 * sinhy)
453
1/2
✓ Branch 1 taken 2612 times.
✗ Branch 2 not taken.
2612 / 1e5;
454 }
455
456 653 double dnpod1 = fabs(diffpod); // distance nearer point
457 653 double dnpod2 = 1.0 - dnpod1; // distance to distant point
458 653 double dnlon1 = fabs(difflon);
459 653 double dnlon2 = 1.0 - dnlon1;
460
461 // pressure
462 653 double R1 = dnpod2 * pl[0] + dnpod1 * pl[1];
463 653 double R2 = dnpod2 * pl[2] + dnpod1 * pl[3];
464 653 gpt3outputs.p = dnlon2 * R1 + dnlon1 * R2;
465
466 // temperature
467 653 R1 = dnpod2 * Tl[0] + dnpod1 * Tl[1];
468 653 R2 = dnpod2 * Tl[2] + dnpod1 * Tl[3];
469 653 gpt3outputs.T = dnlon2 * R1 + dnlon1 * R2;
470
471 // temperature in degree per km
472 653 R1 = dnpod2 * dTl[0] + dnpod1 * dTl[1];
473 653 R2 = dnpod2 * dTl[2] + dnpod1 * dTl[3];
474 653 gpt3outputs.dT = (dnlon2 * R1 + dnlon1 * R2) * 1e3;
475
476 // water vapor pressure in hPa - changed by GP
477 653 R1 = dnpod2 * el[0] + dnpod1 * el[1];
478 653 R2 = dnpod2 * el[2] + dnpod1 * el[3];
479 653 gpt3outputs.e = dnlon2 * R1 + dnlon1 * R2;
480
481 // hydrostatic
482 653 R1 = dnpod2 * ahl[0] + dnpod1 * ahl[1];
483 653 R2 = dnpod2 * ahl[2] + dnpod1 * ahl[3];
484 653 gpt3outputs.ah = dnlon2 * R1 + dnlon1 * R2;
485
486 // wet
487 653 R1 = dnpod2 * awl[0] + dnpod1 * awl[1];
488 653 R2 = dnpod2 * awl[2] + dnpod1 * awl[3];
489 653 gpt3outputs.aw = dnlon2 * R1 + dnlon1 * R2;
490
491 // undulation
492 653 R1 = dnpod2 * undul[0] + dnpod1 * undul[1];
493 653 R2 = dnpod2 * undul[2] + dnpod1 * undul[3];
494 653 gpt3outputs.undu = dnlon2 * R1 + dnlon1 * R2;
495
496 // water vapor decrease factor la - added by GP
497 653 R1 = dnpod2 * lal[0] + dnpod1 * lal[1];
498 653 R2 = dnpod2 * lal[2] + dnpod1 * lal[3];
499 653 gpt3outputs.la = dnlon2 * R1 + dnlon1 * R2;
500
501 // mean temperature of the water vapor - added by GP
502 653 R1 = dnpod2 * Tml[0] + dnpod1 * Tml[1];
503 653 R2 = dnpod2 * Tml[2] + dnpod1 * Tml[3];
504 653 gpt3outputs.Tm = dnlon2 * R1 + dnlon1 * R2;
505
506 // gradients
507 653 R1 = dnpod2 * Gn_hl[0] + dnpod1 * Gn_hl[1];
508 653 R2 = dnpod2 * Gn_hl[2] + dnpod1 * Gn_hl[3];
509 653 gpt3outputs.Gn_h = dnlon2 * R1 + dnlon1 * R2;
510
511 653 R1 = dnpod2 * Ge_hl[0] + dnpod1 * Ge_hl[1];
512 653 R2 = dnpod2 * Ge_hl[2] + dnpod1 * Ge_hl[3];
513 653 gpt3outputs.Ge_h = dnlon2 * R1 + dnlon1 * R2;
514
515 653 R1 = dnpod2 * Gn_wl[0] + dnpod1 * Gn_wl[1];
516 653 R2 = dnpod2 * Gn_wl[2] + dnpod1 * Gn_wl[3];
517 653 gpt3outputs.Gn_w = dnlon2 * R1 + dnlon1 * R2;
518
519 653 R1 = dnpod2 * Ge_wl[0] + dnpod1 * Ge_wl[1];
520 653 R2 = dnpod2 * Ge_wl[2] + dnpod1 * Ge_wl[3];
521 653 gpt3outputs.Ge_w = dnlon2 * R1 + dnlon1 * R2;
522 }
523
524 1450 return gpt3outputs;
525 }
526
527 725 double mjd2doy(const double& mjd)
528 {
529 // convert mjd to doy
530 725 double hour = floor((mjd - floor(mjd)) * 24); // get hours
531 725 double minu = floor((((mjd - floor(mjd)) * 24) - hour) * 60); // get minutes
532 725 double sec = (((((mjd - floor(mjd)) * 24) - hour) * 60) - minu) * 60; // get seconds
533
534 // change secs, min hour whose sec==60 and days, whose hour==24
535
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 725 times.
725 if (sec == 60.0) { minu = minu + 1; }
536
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 725 times.
725 if (minu == 60.0) { hour = hour + 1; }
537
538 // calc jd (yet wrong for hour==24)
539 725 double jd = mjd + 2400000.5;
540
541 // if hour==24, correct jd and set hour==0
542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 725 times.
725 if (hour == 24.0) { jd = jd + 1; }
543
544 // integer Julian date
545 725 double jd_int = floor(jd + 0.5);
546
547 725 double aa = jd_int + 32044;
548 725 double bb = floor((4 * aa + 3) / 146097);
549 725 double cc = aa - floor((bb * 146097) / 4);
550 725 double dd = floor((4 * cc + 3) / 1461);
551 725 double ee = cc - floor((1461 * dd) / 4);
552 725 double mm = floor((5 * ee + 2) / 153);
553
554 725 auto day = static_cast<int>(ee - floor((153 * mm + 2) / 5) + 1);
555 725 auto month = static_cast<int>(mm + 3 - 12 * floor(mm / 10));
556 725 auto year = static_cast<int>(bb * 100 + dd - 4800 + floor(mm / 10));
557
558 // first check if the specified year is leap year or not (logical output)
559 725 double leapYear = 0.0;
560
2/6
✓ Branch 0 taken 725 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 725 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
725 if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
561 {
562 725 leapYear = 1.0;
563 }
564 else
565 {
566 leapYear = 0.0;
567 }
568
2/4
✓ Branch 1 taken 725 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 725 times.
✗ Branch 7 not taken.
2900 auto days = [inits = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }] { return std::vector<int>{ std::begin(inits), std::end(inits) }; }();
569 725 int sum = 0;
570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 725 times.
725 for (size_t i = 0; i < static_cast<size_t>(month) - 1; i++)
571 {
572 sum = sum + days[i];
573 }
574 725 double doy = sum + day;
575
576
2/4
✓ Branch 0 taken 725 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 725 times.
725 if (leapYear == 1 && month > 2)
577 {
578 doy = doy + 1;
579 }
580
581 // Add decimal places
582 725 doy = doy + mjd - floor(mjd);
583
584 725 return doy;
585 725 }
586
587 double asknewet(const double& e, const double& Tm, const double& la)
588 {
589 // coefficients
590 double k1 = 77.604; // K/hPa
591 double k2 = 64.79; // K/hPa
592 double k2p = k2 - k1 * 18.0152 / 28.9644; // K/hPa
593 double k3 = 377600.0; // KK/hPa
594
595 // specific gas constant for dry consituents
596 constexpr double Rd = InsConst::Rg / InsConst::dMtr;
597
598 return 1.0e-6 * (k2p + k3 / Tm) * Rd / (la + 1.0) / InsConst::G_NORM * e;
599 }
600
601 } // namespace NAV
602