105 {
106
108
110
111 const double var_dh = 100.;
112
113 static double xo[3], xs[3], xm[3], hyam[
NZ], hybm[
NZ], kz[
NSHAPE],
115
116 static float *help;
117
118 static int init, ncid, dimid, varid, track0, track1, nk;
119
120 static size_t rs;
121
123
125
127
129
131
132
133
134
135
136
137 if (argc < 8)
138 ERRMSG(
"Give parameters: <ctl> <model> <model.nc> <pert.nc>"
139 " <wave_airs.tab> <wave_model.tab> <wave_airs.nc> <wave_model.nc>");
140
141
143 scan_ctl(argc, argv,
"PERTNAME", -1,
"4mu", pertname);
145 const int extpol = (int)
scan_ctl(argc, argv,
"EXTPOL", -1,
"0", NULL);
146 const int slant = (int)
scan_ctl(argc, argv,
"SLANT", -1,
"1", NULL);
147 const double t_ovp =
scan_ctl(argc, argv,
"T_OVP", -1,
"", NULL);
148
149
151
152
153
154
155
156
160
161
162 printf("Read %s data: %s\n", argv[2], argv[3]);
163 NC(nc_open(argv[3], NC_NOWRITE, &ncid));
164
165
166 LOG(2,
"Check time...");
167 if (nc_inq_dimid(ncid, "time", &dimid) != NC_NOERR)
168 NC(nc_inq_dimid(ncid,
"time", &dimid));
169 NC(nc_inq_dimlen(ncid, dimid, &rs));
170 if (rs != 1)
171 ERRMSG(
"Only one time step is allowed!");
172
173
174 LOG(2,
"Read latitudes...");
175 if (nc_inq_dimid(ncid, "lat", &dimid) != NC_NOERR)
176 NC(nc_inq_dimid(ncid,
"latitude", &dimid));
177 NC(nc_inq_dimlen(ncid, dimid, &rs));
178 model->
nlat = (int) rs;
180 ERRMSG(
"Too many latitudes!");
181 if (nc_inq_varid(ncid, "lat", &varid) != NC_NOERR)
182 NC(nc_inq_varid(ncid,
"latitude", &varid));
183 NC(nc_get_var_double(ncid, varid, model->
lat));
184
185
186 LOG(2,
"Read longitudes...");
187 if (nc_inq_dimid(ncid, "lon", &dimid) != NC_NOERR)
188 NC(nc_inq_dimid(ncid,
"longitude", &dimid));
189 NC(nc_inq_dimlen(ncid, dimid, &rs));
190 model->
nlon = (int) rs;
192 ERRMSG(
"Too many longitudes!");
193 if (nc_inq_varid(ncid, "lon", &varid))
194 NC(nc_inq_varid(ncid,
"longitude", &varid));
195 NC(nc_get_var_double(ncid, varid, model->
lon));
196
197
198 if (strcasecmp(argv[2], "icon") == 0) {
199
200
201 LOG(2,
"Read levels...");
202 NC(nc_inq_dimid(ncid,
"height", &dimid));
203 NC(nc_inq_dimlen(ncid, dimid, &rs));
204 model->
nz = (int) rs;
206 ERRMSG(
"Too many altitudes!");
207
208
209 LOG(2,
"Read height...");
210 NC(nc_inq_varid(ncid,
"z_mc", &varid));
211 NC(nc_get_var_float(ncid, varid, help));
212 for (
int ilon = 0; ilon < model->
nlon; ilon++)
213 for (
int ilat = 0; ilat < model->
nlat; ilat++)
214 for (
int iz = 0; iz < model->
nz; iz++)
215 model->
z[ilon][ilat][iz] =
216 (
float) (help[(iz * model->
nlat + ilat) * model->
nlon + ilon] /
217 1e3);
218
219
220 LOG(2,
"Read temperature...");
221 NC(nc_inq_varid(ncid,
"temp", &varid));
222 NC(nc_get_var_float(ncid, varid, help));
223 for (
int ilon = 0; ilon < model->
nlon; ilon++)
224 for (
int ilat = 0; ilat < model->
nlat; ilat++)
225 for (
int iz = 0; iz < model->
nz; iz++)
226 model->
t[ilon][ilat][iz] =
227 help[(iz * model->
nlat + ilat) * model->
nlon + ilon];
228
229
230 LOG(2,
"Read pressure...");
231 NC(nc_inq_varid(ncid,
"pres", &varid));
232 NC(nc_get_var_float(ncid, varid, help));
233 for (
int ilon = 0; ilon < model->
nlon; ilon++)
234 for (
int ilat = 0; ilat < model->
nlat; ilat++)
235 for (
int iz = 0; iz < model->
nz; iz++)
236 model->
p[ilon][ilat][iz] =
237 (
float) (help[(iz * model->
nlat + ilat) * model->
nlon + ilon] /
238 1e2);
239 }
240
241
242 else if (strcasecmp(argv[2], "ifs") == 0) {
243
244
245 LOG(2,
"Read levels...");
246 NC(nc_inq_dimid(ncid,
"lev_2", &dimid));
247 NC(nc_inq_dimlen(ncid, dimid, &rs));
248 model->
nz = (int) rs;
250 ERRMSG(
"Too many altitudes!");
251
252
253 LOG(2,
"Read height...");
254 NC(nc_inq_varid(ncid,
"gh", &varid));
255 NC(nc_get_var_float(ncid, varid, help));
256 for (
int ilon = 0; ilon < model->
nlon; ilon++)
257 for (
int ilat = 0; ilat < model->
nlat; ilat++)
258 for (
int iz = 0; iz < model->
nz; iz++)
259 model->
z[ilon][ilat][iz] =
260 (
float) (help[(iz * model->
nlat + ilat) * model->
nlon + ilon] /
261 1e3);
262
263
264 LOG(2,
"Read temperature...");
265 NC(nc_inq_varid(ncid,
"t", &varid));
266 NC(nc_get_var_float(ncid, varid, help));
267 for (
int ilon = 0; ilon < model->
nlon; ilon++)
268 for (
int ilat = 0; ilat < model->
nlat; ilat++)
269 for (
int iz = 0; iz < model->
nz; iz++)
270 model->
t[ilon][ilat][iz] =
271 help[(iz * model->
nlat + ilat) * model->
nlon + ilon];
272
273
274 LOG(2,
"Read surface pressure...");
275 NC(nc_inq_varid(ncid,
"lnsp", &varid));
276 NC(nc_get_var_float(ncid, varid, help));
277 for (
int ilon = 0; ilon < model->
nlon; ilon++)
278 for (
int ilat = 0; ilat < model->
nlat; ilat++)
279 model->
ps[ilon][ilat] = (
float) exp(help[ilat * model->
nlon + ilon]);
280
281
282 LOG(2,
"Read grid coefficients...");
283 NC(nc_inq_varid(ncid,
"hyam", &varid));
284 NC(nc_get_var_double(ncid, varid, hyam));
285 NC(nc_inq_varid(ncid,
"hybm", &varid));
286 NC(nc_get_var_double(ncid, varid, hybm));
287
288
289 LOG(2,
"Calculate pressure...");
290 for (
int ilon = 0; ilon < model->
nlon; ilon++)
291 for (
int ilat = 0; ilat < model->
nlat; ilat++)
292 for (
int iz = 0; iz < model->
nz; iz++)
293 model->
p[ilon][ilat][iz]
294 = (
float) ((hyam[iz] + hybm[iz] * model->
ps[ilon][ilat]) / 100.);
295 }
296
297
298 else if (strcasecmp(argv[2], "um") == 0) {
299
300
301 LOG(2,
"Read levels...");
302 if (nc_inq_dimid(ncid, "RHO_TOP_eta_rho", &dimid) != NC_NOERR)
303 NC(nc_inq_dimid(ncid,
"RHO_eta_rho", &dimid));
304 NC(nc_inq_dimlen(ncid, dimid, &rs));
305 model->
nz = (int) rs;
307 ERRMSG(
"Too many altitudes!");
308
309
310 LOG(2,
"Read height...");
311 if (nc_inq_varid(ncid, "STASH_m01s15i102_2", &varid) != NC_NOERR)
312 NC(nc_inq_varid(ncid,
"STASH_m01s15i102", &varid));
313 NC(nc_get_var_float(ncid, varid, help));
314 for (
int ilon = 0; ilon < model->
nlon; ilon++)
315 for (
int ilat = 0; ilat < model->
nlat; ilat++)
316 for (
int iz = 0; iz < model->
nz; iz++)
317 model->
z[ilon][ilat][iz] =
318 (
float) (help[(iz * model->
nlat + ilat) * model->
nlon + ilon] /
319 1e3);
320
321
322 LOG(2,
"Read temperature...");
323 NC(nc_inq_varid(ncid,
"STASH_m01s30i004", &varid));
324 NC(nc_get_var_float(ncid, varid, help));
325 for (
int ilon = 0; ilon < model->
nlon; ilon++)
326 for (
int ilat = 0; ilat < model->
nlat; ilat++)
327 for (
int iz = 0; iz < model->
nz; iz++)
328 model->
t[ilon][ilat][iz] =
329 help[(iz * model->
nlat + ilat) * model->
nlon + ilon];
330
331
332 LOG(2,
"Read pressure...");
333 NC(nc_inq_varid(ncid,
"STASH_m01s00i407", &varid));
334 NC(nc_get_var_float(ncid, varid, help));
335 for (
int ilon = 0; ilon < model->
nlon; ilon++)
336 for (
int ilat = 0; ilat < model->
nlat; ilat++)
337 for (
int iz = 0; iz < model->
nz; iz++)
338 model->
p[ilon][ilat][iz] =
339 0.01f * help[(iz * model->
nlat + ilat) * model->
nlon + ilon];
340 }
341
342
343 else if (strcasecmp(argv[2], "wrf") == 0) {
344
345
346 LOG(2,
"Read levels...");
347 NC(nc_inq_dimid(ncid,
"bottom_top", &dimid));
348 NC(nc_inq_dimlen(ncid, dimid, &rs));
349 model->
nz = (int) rs;
351 ERRMSG(
"Too many altitudes!");
352
353
354 LOG(2,
"Read height...");
355 NC(nc_inq_varid(ncid,
"z", &varid));
356 NC(nc_get_var_float(ncid, varid, help));
357 for (
int ilon = 0; ilon < model->
nlon; ilon++)
358 for (
int ilat = 0; ilat < model->
nlat; ilat++)
359 for (
int iz = 0; iz < model->
nz; iz++)
360 model->
z[ilon][ilat][iz] =
361 (
float) (help[(iz * model->
nlat + ilat) * model->
nlon + ilon] /
362 1e3);
363
364
365 LOG(2,
"Read temperature...");
366 NC(nc_inq_varid(ncid,
"tk", &varid));
367 NC(nc_get_var_float(ncid, varid, help));
368 for (
int ilon = 0; ilon < model->
nlon; ilon++)
369 for (
int ilat = 0; ilat < model->
nlat; ilat++)
370 for (
int iz = 0; iz < model->
nz; iz++)
371 model->
t[ilon][ilat][iz] =
372 help[(iz * model->
nlat + ilat) * model->
nlon + ilon];
373
374
375 LOG(2,
"Read pressure...");
376 NC(nc_inq_varid(ncid,
"p", &varid));
377 NC(nc_get_var_float(ncid, varid, help));
378 for (
int ilon = 0; ilon < model->
nlon; ilon++)
379 for (
int ilat = 0; ilat < model->
nlat; ilat++)
380 for (
int iz = 0; iz < model->
nz; iz++)
381 model->
p[ilon][ilat][iz] =
382 (
float) (help[(iz * model->
nlat + ilat) * model->
nlon + ilon] /
383 1e2);
384 }
385
386 else
387 ERRMSG(
"Model type not supported!");
388
389
391
392
393 free(help);
394
395
396 LOG(2,
"Checking...");
397 for (
int ilon = 0; ilon < model->
nlon; ilon++)
398 for (
int ilat = 0; ilat < model->
nlat; ilat++)
399 for (
int iz = 0; iz < model->
nz; iz++)
400 if (model->
t[ilon][ilat][iz] <= 100
401 || model->
t[ilon][ilat][iz] >= 400) {
402 model->
p[ilon][ilat][iz] = GSL_NAN;
403 model->
t[ilon][ilat][iz] = GSL_NAN;
404 model->
z[ilon][ilat][iz] = GSL_NAN;
405 }
406
407
408 LOG(2,
"Smoothing...");
410
411
412 for (
int iz = 0; iz < model->
nz; iz++)
413 printf("section_height: %d %g %g %g %g %g\n", iz,
414 model->
z[model->
nlon / 2][model->
nlat / 2][iz],
416 model->
p[model->
nlon / 2][model->
nlat / 2][iz],
417 model->
t[model->
nlon / 2][model->
nlat / 2][iz]);
418 for (
int ilon = 0; ilon < model->
nlon; ilon++)
419 printf("section_west_east: %d %g %g %g %g %g\n", ilon,
420 model->
z[ilon][model->
nlat / 2][model->
nz / 2],
421 model->
lon[ilon], model->
lat[model->
nlat / 2],
422 model->
p[ilon][model->
nlat / 2][model->
nz / 2],
423 model->
t[ilon][model->
nlat / 2][model->
nz / 2]);
424 for (
int ilat = 0; ilat < model->
nlat; ilat++)
425 printf("section_north_south: %d %g %g %g %g %g\n", ilat,
426 model->
z[model->
nlon / 2][ilat][model->
nz / 2],
427 model->
lon[model->
nlon / 2], model->
lat[ilat],
428 model->
p[model->
nlon / 2][ilat][model->
nz / 2],
429 model->
t[model->
nlon / 2][ilat][model->
nz / 2]);
430
431
432
433
434
435
440
441
443
444
445 for (
int itrack = 0; itrack < pert->
ntrack; itrack++) {
446 if (pert->
time[itrack][44] < t_ovp - 720 || itrack == 0)
447 track0 = itrack;
448 track1 = itrack;
449 if (pert->
time[itrack][44] > t_ovp + 720)
450 break;
451 }
452
453
455
456
458
459
461
462
465
466
467
468
469
470
471 for (int itrack = track0; itrack <= track1; itrack++)
472 for (
int ixtrack = 0; ixtrack < pert->
nxtrack; ixtrack++) {
473
474
475 if (ixtrack == 0)
476 printf("Compute track %d / %d ...\n", itrack - track0 + 1,
477 track1 - track0 + 1);
478
479
485 obs->
vplon[0] = pert->
lon[itrack][ixtrack];
486 obs->
vplat[0] = pert->
lat[itrack][ixtrack];
487
488
491
492
493 if (slant) {
495 for (double f = 0.0; f <= 1.0; f += 0.0002) {
496 xm[0] = f * xo[0] + (1 - f) * xs[0];
497 xm[1] = f * xo[1] + (1 - f) * xs[1];
498 xm[2] = f * xo[2] + (1 - f) * xs[2];
501 atm->
time[atm->
np] = pert->
time[itrack][ixtrack];
502 if (atm->
z[atm->
np] < 10)
503 continue;
504 else if (atm->
z[atm->
np] > 90)
505 break;
506 else if ((++atm->
np) >=
NP)
507 ERRMSG(
"Too many altitudes!");
508 }
509 } else {
511 for (double f = 10.0; f <= 90.0; f += 0.2) {
512 atm->
time[atm->
np] = pert->
time[itrack][ixtrack];
514 atm->
lon[atm->
np] = pert->
lon[itrack][ixtrack];
515 atm->
lat[atm->
np] = pert->
lat[itrack][ixtrack];
516 if ((++atm->
np) >=
NP)
517 ERRMSG(
"Too many altitudes!");
518 }
519 }
520
521
523
524
525 for (
int ip = 0; ip < atm->
np; ip++)
527 &atm->
p[ip], &atm->
t[ip]);
528
529
530 int okay = 1;
531 for (
int ip = 0; ip < atm->
np; ip++)
532 if (!gsl_finite(atm->
p[ip]) || !gsl_finite(atm->
t[ip]))
533 okay = 0;
534 if (!okay)
535 pert->
bt[itrack][ixtrack] = GSL_NAN;
536 else {
537
538
540
541
542 if (!init) {
543 init = 1;
545 if (kz[0] > kz[1])
546 ERRMSG(
"Kernel function must be ascending!");
547 }
548
549
550 pert->
bt[itrack][ixtrack] = wsum = 0;
551 for (
int ip = 0; ip < atm->
np; ip++)
552 if (atm->
z[ip] >= kz[0] && atm->
z[ip] <= kz[nk - 1]) {
554 const double w =
555 LIN(kz[iz], kw[iz], kz[iz + 1], kw[iz + 1], atm->
z[ip]);
556 pert->
bt[itrack][ixtrack] += w * atm->
t[ip];
557 wsum += w;
558 }
559 pert->
bt[itrack][ixtrack] /= wsum;
560 }
561
562
563 else {
564
565
567
568
569 pert->
bt[itrack][ixtrack] = 0;
570 for (
int id = 0;
id < ctl.
nd;
id++)
571 pert->
bt[itrack][ixtrack] += obs->
rad[
id][0] / ctl.
nd;
572 }
573 }
574 }
575
576
577 if (extpol)
578 for (int itrack = track0; itrack <= track1; itrack++) {
579 for (
int ixtrack = 1; ixtrack < pert->
nxtrack; ixtrack++)
580 if (!gsl_finite(pert->
bt[itrack][ixtrack]))
581 pert->
bt[itrack][ixtrack] = pert->
bt[itrack][ixtrack - 1];
582 for (
int ixtrack = pert->
nxtrack - 2; ixtrack >= 0; ixtrack--)
583 if (!gsl_finite(pert->
bt[itrack][ixtrack]))
584 pert->
bt[itrack][ixtrack] = pert->
bt[itrack][ixtrack + 1];
585 }
586
587
588
589
590
591
593
594
596
597
599
600
603
604
605 free(atm);
606 free(obs);
607 free(pert);
608 free(wave);
609
610 return EXIT_SUCCESS;
611}
void intpol(model_t *model, double z, double lon, double lat, double *p, double *t)
Interpolation of model data.
void write_nc(char *filename, wave_t *wave)
Write wave struct to netCDF file.
void smooth(model_t *model)
Smoothing of model data.
void read_ctl(int argc, char *argv[], ctl_t *ctl)
Read forward model control parameters.
void formod(const ctl_t *ctl, atm_t *atm, obs_t *obs)
Determine ray paths and compute radiative transfer.
void cart2geo(const double *x, double *z, double *lon, double *lat)
Convert Cartesian coordinates to geolocation.
double scan_ctl(int argc, char *argv[], const char *varname, int arridx, const char *defvalue, char *value)
Search control parameter file for variable entry.
void read_shape(const char *filename, double *x, double *y, int *n)
Read shape function.
void climatology(const ctl_t *ctl, atm_t *atm)
Interpolate climatological data.
void geo2cart(const double z, const double lon, const double lat, double *x)
Convert geolocation to Cartesian coordinates.
void kernel(ctl_t *ctl, atm_t *atm, obs_t *obs, gsl_matrix *k)
Compute Jacobians.
#define LEN
Maximum length of ASCII data lines.
#define ERRMSG(...)
Print error message and quit program.
#define NSHAPE
Maximum number of shape function grid points.
#define ALLOC(ptr, type, n)
Allocate memory.
#define NP
Maximum number of atmospheric data points.
#define LOG(level,...)
Print log message.
void background_poly(wave_t *wave, int dim_x, int dim_y)
Get background based on polynomial fits.
void variance(wave_t *wave, double dh)
Compute local variance.
void pert2wave(pert_t *pert, wave_t *wave, int track0, int track1, int xtrack0, int xtrack1)
Convert radiance perturbation data to wave analysis struct.
void read_pert(char *filename, char *pertname, pert_t *pert)
Read radiance perturbation data.
void write_wave(char *filename, wave_t *wave)
Write wave analysis data.
double time[NP]
Time (seconds since 2000-01-01T00:00Z).
double lat[NP]
Latitude [deg].
double lon[NP]
Longitude [deg].
double t[NP]
Temperature [K].
int np
Number of data points.
double z[NP]
Altitude [km].
double p[NP]
Pressure [hPa].
Forward model control parameters.
int nd
Number of radiance channels.
int write_bbt
Use brightness temperature instead of radiance (0=no, 1=yes).
float ps[NLON][NLAT]
Surface pressure [hPa].
Observation geometry and radiance data.
double rad[ND][NR]
Radiance [W/(m^2 sr cm^-1)].
double vpz[NR]
View point altitude [km].
double vplat[NR]
View point latitude [deg].
double obslon[NR]
Observer longitude [deg].
double obslat[NR]
Observer latitude [deg].
double obsz[NR]
Observer altitude [km].
double vplon[NR]
View point longitude [deg].
int nr
Number of ray paths.
double time[PERT_NTRACK][PERT_NXTRACK]
Time (seconds since 2000-01-01T00:00Z).
int ntrack
Number of along-track values.
int nxtrack
Number of across-track values.
double lon[PERT_NTRACK][PERT_NXTRACK]
Longitude [deg].
double bt[PERT_NTRACK][PERT_NXTRACK]
Brightness temperature (4 or 15 micron) [K].
double lat[PERT_NTRACK][PERT_NXTRACK]
Latitude [deg].