3
#include "atmosmodel.h"
4
#include "aerosolconcentration.h"
6
/* Update the atmospheric profile (P(z),T(z),H2O(z),O3(z)) in case the target
10
Given the altitude of the target in kilometers as input, we transform the
11
original atmospheric profile (Pressure, Temperature, Water Vapor, Ozone)
12
so that first level of the new profile is the one at the target altitude.
13
We also compute the new integrated content in water vapor and ozone, that
14
are used as outputs or in computations when the user chooses to enter a
15
specific amount of Ozone and Water Vapor.
17
void Altitude::pressure(AtmosModel& atms, float& uw, float& uo3)
19
/* log linear interpolation */
20
if(xps >= 100) xps = 99.99f;
23
for(i = 0; atms.z[i] <= xps; i++);
28
float xa = (float)((atms.z[isup] - atms.z[iinf]) / log(atms.p[isup] / atms.p[iinf]));
29
float xb = (float)(atms.z[isup] - xa * log(atms.p[isup]));
30
float ps = (float)exp((xps - xb) / xa);
32
/* interpolating temperature wator vapor and ozone profile versus altitude */
34
float xtemp = (atms.t[isup] - atms.t[iinf]) / (atms.z[isup] - atms.z[iinf]);
35
xtemp = xtemp * (xalt - atms.z[iinf]) + atms.t[iinf];
36
float xwo = (atms.wo[isup] - atms.wo[iinf]) / (atms.z[isup] - atms.z[iinf]);
37
xwo = xwo * (xalt - atms.z[iinf]) + atms.wo[iinf];
38
float xwh = (atms.wh[isup] - atms.wh[iinf]) / (atms.z[isup] - atms.z[iinf]);
39
xwh = xwh * (xalt - atms.z[iinf]) + atms.wh[iinf];
41
/* updating atmospheric profile
42
1rst level: target , complete to 34
43
with interpolated layers */
50
for (i = 1; i < 33 - iinf; ++i)
52
atms.z[i] = atms.z[i + iinf];
53
atms.p[i] = atms.p[i + iinf];
54
atms.t[i] = atms.t[i + iinf];
55
atms.wh[i] = atms.wh[i + iinf];
56
atms.wo[i] = atms.wo[i + iinf];
58
int l = 33 - iinf - 1;
59
for (i = l; i < 34; ++i)
61
atms.z[i] = (atms.z[33] - atms.z[l]) * (i - l) / (33 - l) + atms.z[l];
62
atms.p[i] = (atms.p[33] - atms.p[l]) * (i - l) / (33 - l) + atms.p[l];
63
atms.t[i] = (atms.t[33] - atms.t[l]) * (i - l) / (33 - l) + atms.t[l];
64
atms.wh[i] = (atms.wh[33] - atms.wh[l]) * (i - l) / (33 - l) + atms.wh[l];
65
atms.wo[i] = (atms.wo[33] - atms.wo[l]) * (i - l) / (33 - l) + atms.wo[l];
68
/* compute modified h2o and o3 integrated content */
71
const float g = 98.1f;
72
const float air = 0.028964f/0.0224f;
73
const float ro3 = 0.048f/0.0224f;
78
for (k = 0; k < 33; ++k)
80
float roair = air * 273.16f * atms.p[k] / (atms.t[k] * 1013.25f);
81
rmwh[k] = atms.wh[k] / (roair * 1e3f);
82
rmo3[k] = atms.wo[k] / (roair * 1e3f);
85
for (k = 1; k < 33; ++k)
87
float ds = (atms.p[k - 1] - atms.p[k]) / atms.p[0];
88
uw += (rmwh[k] + rmwh[k - 1]) * ds / 2.f;
89
uo3 += (rmo3[k] + rmo3[k - 1]) * ds / 2.f;
91
uw = uw * atms.p[0] * 100.f / g;
92
uo3 = uo3 * atms.p[0] * 100.f / g;
93
uo3 = uo3 * 1e3f / ro3;
97
Function: Update the atmospheric profile (P(z),T(z),H2O(z),O3(z)) in case the observer is on
100
Description: Given the altitude or pressure at aircraft level as input, the first task is to
101
compute the altitude (in case the pressure has been entered) or the pressure (in case the altitude has
102
been entered) at plane level. Then, a new atmospheric profile is created (Pp,Tp,H2Op,O3p) for which
103
the last level is located at the plane altitude. This profile is used in the gaseous absorption
104
computation (ABSTRA.f) for the path from target to sensor (upward transmission). The ozone and
105
water vapor integrated content of the "plane" atmospheric profile are also an output of this
106
subroutine. The last output is the proportion of molecules below plane level which is useful in
107
scattering computations (OS.f,ISO.f).
109
void Altitude::presplane(AtmosModel& atms)
111
/* log linear interpolation */
113
if(xpp >= 100) xpp = 1000;
116
for(i = 0; atms.z[i] <= xpp; i++);
121
float xa = (float)((atms.z[isup] - atms.z[iinf]) / log(atms.p[isup] / atms.p[iinf]));
122
float xb = (float)(atms.z[isup] - xa * log(atms.p[isup]));
123
float ps = (float)(exp((xpp - xb) / xa));
125
/* interpolating temperature wator vapor and ozone profile versus altitud */
127
float xtemp = (atms.t[isup] - atms.t[iinf])/ (atms.z[isup] - atms.z[iinf]);
128
xtemp = xtemp * (xalt - atms.z[iinf]) + atms.t[iinf];
129
float xwo = (atms.wo[isup] - atms.wo[iinf]) / (atms.z[isup] - atms.z[iinf]);
130
xwo = xwo * (xalt - atms.z[iinf]) + atms.wo[iinf];
131
float xwh = (atms.wh[isup] - atms.wh[iinf]) / (atms.z[isup] - atms.z[iinf]);
132
xwh = xwh * (xalt - atms.z[iinf]) + atms.wh[iinf];
134
/* updating atmospheric profile
135
last level: plane , complete to 34
136
with interpolated layers */
137
for(i = 0; i <= iinf; i++)
139
plane_sim.zpl[i] = atms.z[i];
140
plane_sim.ppl[i] = atms.p[i];
141
plane_sim.tpl[i] = atms.t[i];
142
plane_sim.whpl[i] = atms.wh[i];
143
plane_sim.wopl[i] = atms.wo[i];
146
for(i = iinf+1; i < 34; i++)
148
plane_sim.zpl[i] = xalt;
149
plane_sim.ppl[i] = ps;
150
plane_sim.tpl[i] = xtemp;
151
plane_sim.whpl[i] = xwh;
152
plane_sim.wopl[i] = xwo;
155
/* compute modified h2o and o3 integrated content
156
compute conversion factor for rayleigh optical thickness computation
160
const float g = 98.1f;
161
const float air = 0.028964f/0.0224f;
162
const float ro3 = 0.048f/0.0224f;
169
for(k = 0; k < 33; k++)
171
float roair = (float)(air * 273.16 * plane_sim.ppl[k] / (1013.25 * plane_sim.tpl[k]));
172
rmwh[k] = atms.wh[k] / (roair * 1000);
173
rmo3[k] = atms.wo[k] / (roair * 1000);
174
rt += (atms.p[k+1] / atms.t[k+1] + atms.p[k] / atms.p[k]) * (atms.z[k+1] - atms.z[k]);
175
rp += (plane_sim.ppl[k+1] / plane_sim.tpl[k+1] + plane_sim.ppl[k] / plane_sim.tpl[k])
176
* (plane_sim.zpl[k+1] - plane_sim.zpl[k]);
180
for(k = 1; k < 33; k++)
182
float ds = (plane_sim.ppl[k-1] - plane_sim.ppl[k]) / plane_sim.ppl[0];
183
atms.uw += (rmwh[k] + rmwh[k-1])*ds/2;
184
atms.uo3+= (rmo3[k] + rmo3[k-1])*ds/2;
187
atms.uw *= plane_sim.ppl[0] * 100 / g;
188
atms.uo3*= plane_sim.ppl[0] * 100 / g;
189
atms.uo3*= 1000 / ro3;
192
void Altitude::init(AtmosModel &atms, const AerosolConcentration &aerocon)
205
else if(atms.idatm != 8) pressure(atms, atms.uw, atms.uo3);
206
else pressure(atms, uwus, uo3us);
210
/* ground measurement option */
214
original_taer55p = taer55p = 0;
219
/* satellite case of equivalent */
222
original_taer55p = taer55p = aerocon.taer55;
229
/* "real" plane case */
231
cin >> original_puo3;
232
cin.ignore(numeric_limits < int >::max(), '\n'); /* ignore comments */
235
puo3 = original_puo3;
245
puw *= atms.uw / uwus;
246
puo3 *= atms.uo3 / uo3us;
256
palt = plane_sim.zpl[33] - atms.z[0];
257
pps = plane_sim.ppl[33];
258
cin >> original_taer55p;
259
taer55p = original_taer55p;
261
if ((taer55p > 0) || ((aerocon.taer55 - taer55p) < 1e-03))
263
/* a scale heigh of 2km is assumed in case no value is given for taer55p */
264
taer55p = (float)(aerocon.taer55 * (1 - exp(-palt / 2)));
268
/* compute effective scale heigh */
269
double sham = exp(-palt / 4);
270
double sha = 1 - (taer55p / aerocon.taer55);
272
if( sha >= sham) taer55p = (float)(aerocon.taer55 * (1 - exp(-palt / 4)));
274
sha = -palt/log(sha);
275
taer55p = (float)(aerocon.taer55 * (1 - exp(-palt/sha)));
281
void Altitude::update_hv(AtmosModel & atms, const AerosolConcentration & aerocon)
294
else if (atms.idatm != 8)
295
pressure(atms, atms.uw, atms.uo3);
297
pressure(atms, uwus, uo3us);
300
/* ground measurement option */
307
else if (xpp >= 100) {
308
/* satellite case of equivalent */
311
taer55p = aerocon.taer55;
317
/* "real" plane case */
320
puo3 = original_puo3;
326
if (atms.idatm == 8) {
329
puw *= atms.uw / uwus;
330
puo3 *= atms.uo3 / uo3us;
339
palt = plane_sim.zpl[33] - atms.z[0];
340
pps = plane_sim.ppl[33];
341
taer55p = original_taer55p;
343
if ((taer55p > 0) || ((aerocon.taer55 - taer55p) < 1e-03)) {
344
/* a scale heigh of 2km is assumed in case no value is given for taer55p */
345
taer55p = (float)(aerocon.taer55 * (1 - exp(-palt / 2)));
348
/* compute effective scale heigh */
349
double sham = exp(-palt / 4);
350
double sha = 1 - (taer55p / aerocon.taer55);
353
taer55p = (float)(aerocon.taer55 * (1 - exp(-palt / 4)));
355
sha = -palt / log(sha);
356
taer55p = (float)(aerocon.taer55 * (1 - exp(-palt / sha)));
362
void Altitude::parse()
365
cin.ignore(numeric_limits<int>::max(),'\n'); /* ignore comments */
366
original_xps = -original_xps;
369
cin.ignore(numeric_limits<int>::max(),'\n'); /* ignore comments */
370
original_xpp = -original_xpp;
373
/* --- plane simulation output if selected ---- */
374
void Altitude::print()
379
Output::WriteLn(22," plane simulation description ");
380
Output::WriteLn(22," ---------------------------- ");
383
s1.setf(ios::fixed, ios::floatfield);
385
s1 << " plane pressure [mb] " << setw(9) << pps << ends;
386
Output::WriteLn(10,s1.str());
389
s2.setf(ios::fixed, ios::floatfield);
391
s2 << " plane altitude absolute [km] " << setw(9) << plane_sim.zpl[33] << ends;
392
Output::WriteLn(10,s2.str());
395
Output::WriteLn(15," atmosphere under plane description: ");
398
s3.setf(ios::fixed, ios::floatfield);
400
s3 << " ozone content " << setw(9) << puo3 << ends;
401
Output::WriteLn(15,s3.str());
405
s4.setf(ios::fixed, ios::floatfield);
407
s4 << " h2o content " << setw(9) << puw << ends;
408
Output::WriteLn(15,s4.str());
411
s5.setf(ios::fixed, ios::floatfield);
413
s5 << "aerosol opt. thick. 550nm " << setw(9) << taer55p << ends;
414
Output::WriteLn(15,s5.str());
418
Altitude Altitude::Parse()