105 {
106
107 static ctl_t ctl;
108
109 static char kernel[LEN], pertname[LEN];
110
111 const double var_dh = 100.;
112
113 static double hyam[
NZ], hybm[
NZ], kz[NSHAPE], kw[NSHAPE];
114
115 static float *help;
116
117 static int init, ncid, dimid, varid, track0, track1, nk;
118
119 static size_t rs;
120
121 atm_t *atm;
122
123 obs_t *obs;
124
126
128
130
131
132
133
134
135
136 if (argc < 8)
137 ERRMSG("Give parameters: <ctl> <model> <model.nc> <pert.nc>"
138 " <wave_airs.tab> <wave_model.tab> <wave_airs.nc> <wave_model.nc>");
139
140
141 read_ctl(argc, argv, &ctl);
142 scan_ctl(argc, argv, "PERTNAME", -1, "4mu", pertname);
143 scan_ctl(argc, argv, "KERNEL", -1, "-", kernel);
144 const int extpol = (int) scan_ctl(argc, argv, "EXTPOL", -1, "0", NULL);
145 const int slant = (int) scan_ctl(argc, argv, "SLANT", -1, "1", NULL);
146 const double t_ovp = scan_ctl(argc, argv, "T_OVP", -1, "", NULL);
147
148
149 ctl.write_bbt = 1;
150
151
152 tbl_t *tbl = read_tbl(&ctl);
153
154
155
156
157
158
160 ALLOC(help, float,
162
163
164 printf("Read %s data: %s\n", argv[2], argv[3]);
165 NC(nc_open(argv[3], NC_NOWRITE, &ncid));
166
167
168 LOG(2, "Check time...");
169 if (nc_inq_dimid(ncid, "time", &dimid) != NC_NOERR)
170 NC(nc_inq_dimid(ncid,
"time", &dimid));
171 NC(nc_inq_dimlen(ncid, dimid, &rs));
172 if (rs != 1)
173 ERRMSG("Only one time step is allowed!");
174
175
176 LOG(2, "Read latitudes...");
177 if (nc_inq_dimid(ncid, "lat", &dimid) != NC_NOERR)
178 NC(nc_inq_dimid(ncid,
"latitude", &dimid));
179 NC(nc_inq_dimlen(ncid, dimid, &rs));
180 model->
nlat = (int) rs;
182 ERRMSG("Too many latitudes!");
183 if (nc_inq_varid(ncid, "lat", &varid) != NC_NOERR)
184 NC(nc_inq_varid(ncid,
"latitude", &varid));
185 NC(nc_get_var_double(ncid, varid, model->
lat));
186
187
188 LOG(2, "Read longitudes...");
189 if (nc_inq_dimid(ncid, "lon", &dimid) != NC_NOERR)
190 NC(nc_inq_dimid(ncid,
"longitude", &dimid));
191 NC(nc_inq_dimlen(ncid, dimid, &rs));
192 model->
nlon = (int) rs;
194 ERRMSG("Too many longitudes!");
195 if (nc_inq_varid(ncid, "lon", &varid))
196 NC(nc_inq_varid(ncid,
"longitude", &varid));
197 NC(nc_get_var_double(ncid, varid, model->
lon));
198
199
200 if (strcasecmp(argv[2], "icon") == 0) {
201
202
203 LOG(2, "Read levels...");
204 NC(nc_inq_dimid(ncid,
"height", &dimid));
205 NC(nc_inq_dimlen(ncid, dimid, &rs));
206 model->
nz = (int) rs;
208 ERRMSG("Too many altitudes!");
209
210
211 LOG(2, "Read height...");
212 NC(nc_inq_varid(ncid,
"z_mc", &varid));
213 NC(nc_get_var_float(ncid, varid, help));
214 for (
int ilon = 0; ilon < model->
nlon; ilon++)
215 for (
int ilat = 0; ilat < model->
nlat; ilat++)
216 for (
int iz = 0; iz < model->
nz; iz++)
217 model->
z[ilon][ilat][iz] =
218 (
float) (help[(iz * model->
nlat + ilat) * model->
nlon + ilon] /
219 1e3);
220
221
222 LOG(2, "Read temperature...");
223 NC(nc_inq_varid(ncid,
"temp", &varid));
224 NC(nc_get_var_float(ncid, varid, help));
225 for (
int ilon = 0; ilon < model->
nlon; ilon++)
226 for (
int ilat = 0; ilat < model->
nlat; ilat++)
227 for (
int iz = 0; iz < model->
nz; iz++)
228 model->
t[ilon][ilat][iz] =
229 help[(iz * model->
nlat + ilat) * model->
nlon + ilon];
230
231
232 LOG(2, "Read pressure...");
233 NC(nc_inq_varid(ncid,
"pres", &varid));
234 NC(nc_get_var_float(ncid, varid, help));
235 for (
int ilon = 0; ilon < model->
nlon; ilon++)
236 for (
int ilat = 0; ilat < model->
nlat; ilat++)
237 for (
int iz = 0; iz < model->
nz; iz++)
238 model->
p[ilon][ilat][iz] =
239 (
float) (help[(iz * model->
nlat + ilat) * model->
nlon + ilon] /
240 1e2);
241 }
242
243
244 else if (strcasecmp(argv[2], "ifs") == 0) {
245
246
247 LOG(2, "Read levels...");
248 NC(nc_inq_dimid(ncid,
"lev_2", &dimid));
249 NC(nc_inq_dimlen(ncid, dimid, &rs));
250 model->
nz = (int) rs;
252 ERRMSG("Too many altitudes!");
253
254
255 LOG(2, "Read height...");
256 NC(nc_inq_varid(ncid,
"gh", &varid));
257 NC(nc_get_var_float(ncid, varid, help));
258 for (
int ilon = 0; ilon < model->
nlon; ilon++)
259 for (
int ilat = 0; ilat < model->
nlat; ilat++)
260 for (
int iz = 0; iz < model->
nz; iz++)
261 model->
z[ilon][ilat][iz] =
262 (
float) (help[(iz * model->
nlat + ilat) * model->
nlon + ilon] /
263 1e3);
264
265
266 LOG(2, "Read temperature...");
267 NC(nc_inq_varid(ncid,
"t", &varid));
268 NC(nc_get_var_float(ncid, varid, help));
269 for (
int ilon = 0; ilon < model->
nlon; ilon++)
270 for (
int ilat = 0; ilat < model->
nlat; ilat++)
271 for (
int iz = 0; iz < model->
nz; iz++)
272 model->
t[ilon][ilat][iz] =
273 help[(iz * model->
nlat + ilat) * model->
nlon + ilon];
274
275
276 LOG(2, "Read surface pressure...");
277 NC(nc_inq_varid(ncid,
"lnsp", &varid));
278 NC(nc_get_var_float(ncid, varid, help));
279 for (
int ilon = 0; ilon < model->
nlon; ilon++)
280 for (
int ilat = 0; ilat < model->
nlat; ilat++)
281 model->
ps[ilon][ilat] = (
float) exp(help[ilat * model->
nlon + ilon]);
282
283
284 LOG(2, "Read grid coefficients...");
285 NC(nc_inq_varid(ncid,
"hyam", &varid));
286 NC(nc_get_var_double(ncid, varid, hyam));
287 NC(nc_inq_varid(ncid,
"hybm", &varid));
288 NC(nc_get_var_double(ncid, varid, hybm));
289
290
291 LOG(2, "Calculate pressure...");
292 for (
int ilon = 0; ilon < model->
nlon; ilon++)
293 for (
int ilat = 0; ilat < model->
nlat; ilat++)
294 for (
int iz = 0; iz < model->
nz; iz++)
295 model->
p[ilon][ilat][iz]
296 = (
float) ((hyam[iz] + hybm[iz] * model->
ps[ilon][ilat]) / 100.);
297 }
298
299
300 else if (strcasecmp(argv[2], "um") == 0) {
301
302
303 LOG(2, "Read levels...");
304 if (nc_inq_dimid(ncid, "RHO_TOP_eta_rho", &dimid) != NC_NOERR)
305 NC(nc_inq_dimid(ncid,
"RHO_eta_rho", &dimid));
306 NC(nc_inq_dimlen(ncid, dimid, &rs));
307 model->
nz = (int) rs;
309 ERRMSG("Too many altitudes!");
310
311
312 LOG(2, "Read height...");
313 if (nc_inq_varid(ncid, "STASH_m01s15i102_2", &varid) != NC_NOERR)
314 NC(nc_inq_varid(ncid,
"STASH_m01s15i102", &varid));
315 NC(nc_get_var_float(ncid, varid, help));
316 for (
int ilon = 0; ilon < model->
nlon; ilon++)
317 for (
int ilat = 0; ilat < model->
nlat; ilat++)
318 for (
int iz = 0; iz < model->
nz; iz++)
319 model->
z[ilon][ilat][iz] =
320 (
float) (help[(iz * model->
nlat + ilat) * model->
nlon + ilon] /
321 1e3);
322
323
324 LOG(2, "Read temperature...");
325 NC(nc_inq_varid(ncid,
"STASH_m01s30i004", &varid));
326 NC(nc_get_var_float(ncid, varid, help));
327 for (
int ilon = 0; ilon < model->
nlon; ilon++)
328 for (
int ilat = 0; ilat < model->
nlat; ilat++)
329 for (
int iz = 0; iz < model->
nz; iz++)
330 model->
t[ilon][ilat][iz] =
331 help[(iz * model->
nlat + ilat) * model->
nlon + ilon];
332
333
334 LOG(2, "Read pressure...");
335 NC(nc_inq_varid(ncid,
"STASH_m01s00i407", &varid));
336 NC(nc_get_var_float(ncid, varid, help));
337 for (
int ilon = 0; ilon < model->
nlon; ilon++)
338 for (
int ilat = 0; ilat < model->
nlat; ilat++)
339 for (
int iz = 0; iz < model->
nz; iz++)
340 model->
p[ilon][ilat][iz] =
341 0.01f * help[(iz * model->
nlat + ilat) * model->
nlon + ilon];
342 }
343
344
345 else if (strcasecmp(argv[2], "wrf") == 0) {
346
347
348 LOG(2, "Read levels...");
349 NC(nc_inq_dimid(ncid,
"bottom_top", &dimid));
350 NC(nc_inq_dimlen(ncid, dimid, &rs));
351 model->
nz = (int) rs;
353 ERRMSG("Too many altitudes!");
354
355
356 LOG(2, "Read height...");
357 NC(nc_inq_varid(ncid,
"z", &varid));
358 NC(nc_get_var_float(ncid, varid, help));
359 for (
int ilon = 0; ilon < model->
nlon; ilon++)
360 for (
int ilat = 0; ilat < model->
nlat; ilat++)
361 for (
int iz = 0; iz < model->
nz; iz++)
362 model->
z[ilon][ilat][iz] =
363 (
float) (help[(iz * model->
nlat + ilat) * model->
nlon + ilon] /
364 1e3);
365
366
367 LOG(2, "Read temperature...");
368 NC(nc_inq_varid(ncid,
"tk", &varid));
369 NC(nc_get_var_float(ncid, varid, help));
370 for (
int ilon = 0; ilon < model->
nlon; ilon++)
371 for (
int ilat = 0; ilat < model->
nlat; ilat++)
372 for (
int iz = 0; iz < model->
nz; iz++)
373 model->
t[ilon][ilat][iz] =
374 help[(iz * model->
nlat + ilat) * model->
nlon + ilon];
375
376
377 LOG(2, "Read pressure...");
378 NC(nc_inq_varid(ncid,
"p", &varid));
379 NC(nc_get_var_float(ncid, varid, help));
380 for (
int ilon = 0; ilon < model->
nlon; ilon++)
381 for (
int ilat = 0; ilat < model->
nlat; ilat++)
382 for (
int iz = 0; iz < model->
nz; iz++)
383 model->
p[ilon][ilat][iz] =
384 (
float) (help[(iz * model->
nlat + ilat) * model->
nlon + ilon] /
385 1e2);
386 }
387
388 else
389 ERRMSG("Model type not supported!");
390
391
393
394
395 free(help);
396
397
398 LOG(2, "Checking...");
399 for (
int ilon = 0; ilon < model->
nlon; ilon++)
400 for (
int ilat = 0; ilat < model->
nlat; ilat++)
401 for (
int iz = 0; iz < model->
nz; iz++)
402 if (model->
t[ilon][ilat][iz] <= 100
403 || model->
t[ilon][ilat][iz] >= 400) {
404 model->
p[ilon][ilat][iz] = GSL_NAN;
405 model->
t[ilon][ilat][iz] = GSL_NAN;
406 model->
z[ilon][ilat][iz] = GSL_NAN;
407 }
408
409
410 LOG(2, "Smoothing...");
412
413
414 for (
int iz = 0; iz < model->
nz; iz++)
415 printf("section_height: %d %g %g %g %g %g\n", iz,
416 model->
z[model->
nlon / 2][model->
nlat / 2][iz],
418 model->
p[model->
nlon / 2][model->
nlat / 2][iz],
419 model->
t[model->
nlon / 2][model->
nlat / 2][iz]);
420 for (
int ilon = 0; ilon < model->
nlon; ilon++)
421 printf("section_west_east: %d %g %g %g %g %g\n", ilon,
422 model->
z[ilon][model->
nlat / 2][model->
nz / 2],
423 model->
lon[ilon], model->
lat[model->
nlat / 2],
424 model->
p[ilon][model->
nlat / 2][model->
nz / 2],
425 model->
t[ilon][model->
nlat / 2][model->
nz / 2]);
426 for (
int ilat = 0; ilat < model->
nlat; ilat++)
427 printf("section_north_south: %d %g %g %g %g %g\n", ilat,
428 model->
z[model->
nlon / 2][ilat][model->
nz / 2],
429 model->
lon[model->
nlon / 2], model->
lat[ilat],
430 model->
p[model->
nlon / 2][ilat][model->
nz / 2],
431 model->
t[model->
nlon / 2][ilat][model->
nz / 2]);
432
433
434
435
436
437
438 ALLOC(atm, atm_t, 1);
439 ALLOC(obs, obs_t, 1);
442
443
445
446
447 for (
int itrack = 0; itrack < pert->
ntrack; itrack++) {
448 if (pert->
time[itrack][44] < t_ovp - 720 || itrack == 0)
449 track0 = itrack;
450 track1 = itrack;
451 if (pert->
time[itrack][44] > t_ovp + 720)
452 break;
453 }
454
455
457
458
460
461
463
464
467
468
469
470
471
472
473 for (int itrack = track0; itrack <= track1; itrack++)
474 for (
int ixtrack = 0; ixtrack < pert->
nxtrack; ixtrack++) {
475
476
477 if (ixtrack == 0)
478 printf("Compute track %d / %d ...\n", itrack - track0 + 1,
479 track1 - track0 + 1);
480
481
482 obs->nr = 1;
483 obs->obsz[0] = 705;
484 obs->obslon[0] = pert->
lon[itrack][44];
485 obs->obslat[0] = pert->
lat[itrack][44];
486 obs->vpz[0] = 0;
487 obs->vplon[0] = pert->
lon[itrack][ixtrack];
488 obs->vplat[0] = pert->
lat[itrack][ixtrack];
489
490
491 double xm[3], xo[3], xs[3];
492 geo2cart(obs->obsz[0], obs->obslon[0], obs->obslat[0], xo);
493 geo2cart(obs->vpz[0], obs->vplon[0], obs->vplat[0], xs);
494
495
496 if (slant) {
497 atm->np = 0;
498 for (double f = 0.0; f <= 1.0; f += 0.0002) {
499 xm[0] = f * xo[0] + (1 - f) * xs[0];
500 xm[1] = f * xo[1] + (1 - f) * xs[1];
501 xm[2] = f * xo[2] + (1 - f) * xs[2];
502 cart2geo(xm, &atm->z[atm->np], &atm->lon[atm->np],
503 &atm->lat[atm->np]);
504 atm->time[atm->np] = pert->
time[itrack][ixtrack];
505 if (atm->z[atm->np] < 10)
506 continue;
507 else if (atm->z[atm->np] > 90)
508 break;
509 else if ((++atm->np) >= NP)
510 ERRMSG("Too many ray path data points!");
511 }
512 } else {
513 atm->np = 0;
514 for (double f = 10.0; f <= 90.0; f += 0.2) {
515 atm->time[atm->np] = pert->
time[itrack][ixtrack];
516 atm->z[atm->np] = f;
517 atm->lon[atm->np] = pert->
lon[itrack][ixtrack];
518 atm->lat[atm->np] = pert->
lat[itrack][ixtrack];
519 if ((++atm->np) >= NP)
520 ERRMSG("Too many ray path data points!");
521 }
522 }
523
524
525 climatology(&ctl, atm);
526
527
528 for (int ip = 0; ip < atm->np; ip++)
529 intpol(model, atm->z[ip], atm->lon[ip], atm->lat[ip],
530 &atm->p[ip], &atm->t[ip]);
531
532
533 int okay = 1;
534 for (int ip = 0; ip < atm->np; ip++)
535 if (!gsl_finite(atm->p[ip]) || !gsl_finite(atm->t[ip]))
536 okay = 0;
537 if (!okay)
538 pert->
bt[itrack][ixtrack] = GSL_NAN;
539 else {
540
541
542 if (kernel[0] != '-') {
543
544
545 if (!init) {
546 init = 1;
547 read_shape(kernel, kz, kw, &nk);
548 if (kz[0] > kz[1])
549 ERRMSG("Kernel function must be ascending!");
550 }
551
552
553 double wsum = 0;
554 pert->
bt[itrack][ixtrack] = 0;
555 for (int ip = 0; ip < atm->np; ip++)
556 if (atm->z[ip] >= kz[0] && atm->z[ip] <= kz[nk - 1]) {
557 const int iz = locate_irr(kz, nk, atm->z[ip]);
558 const double w =
559 LIN(kz[iz], kw[iz], kz[iz + 1], kw[iz + 1], atm->z[ip]);
560 pert->
bt[itrack][ixtrack] += w * atm->t[ip];
561 wsum += w;
562 }
563 pert->
bt[itrack][ixtrack] /= wsum;
564 }
565
566
567 else {
568
569
570 formod(&ctl, tbl, atm, obs);
571
572
573 pert->
bt[itrack][ixtrack] = 0;
574 for (int id = 0; id < ctl.nd; id++)
575 pert->
bt[itrack][ixtrack] += obs->rad[
id][0] / ctl.nd;
576 }
577 }
578 }
579
580
581 if (extpol)
582 for (int itrack = track0; itrack <= track1; itrack++) {
583 for (
int ixtrack = 1; ixtrack < pert->
nxtrack; ixtrack++)
584 if (!gsl_finite(pert->
bt[itrack][ixtrack]))
585 pert->
bt[itrack][ixtrack] = pert->
bt[itrack][ixtrack - 1];
586 for (
int ixtrack = pert->
nxtrack - 2; ixtrack >= 0; ixtrack--)
587 if (!gsl_finite(pert->
bt[itrack][ixtrack]))
588 pert->
bt[itrack][ixtrack] = pert->
bt[itrack][ixtrack + 1];
589 }
590
591
592
593
594
595
597
598
600
601
603
604
607
608
609 free(atm);
610 free(obs);
611 free(pert);
612 free(wave);
613 free(tbl);
614
615 return EXIT_SUCCESS;
616}
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 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.
float ps[NLON][NLAT]
Surface pressure [hPa].
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].