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 xo[3], xs[3], xm[3], hyam[
NZ], hybm[
NZ], kz[NSHAPE],
114 kw[NSHAPE], wsum;
115
116 static float *help;
117
118 static int init, ncid, dimid, varid, track0, track1, nk;
119
120 static size_t rs;
121
122 atm_t *atm;
123
124 obs_t *obs;
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
142 read_ctl(argc, argv, &ctl);
143 scan_ctl(argc, argv, "PERTNAME", -1, "4mu", pertname);
144 scan_ctl(argc, argv, "KERNEL", -1, "-", kernel);
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
150 ctl.write_bbt = 1;
151
152
153
154
155
156
158 ALLOC(help, float,
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
436 ALLOC(atm, atm_t, 1);
437 ALLOC(obs, obs_t, 1);
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
480 obs->nr = 1;
481 obs->obsz[0] = 705;
482 obs->obslon[0] = pert->
lon[itrack][44];
483 obs->obslat[0] = pert->
lat[itrack][44];
484 obs->vpz[0] = 0;
485 obs->vplon[0] = pert->
lon[itrack][ixtrack];
486 obs->vplat[0] = pert->
lat[itrack][ixtrack];
487
488
489 geo2cart(obs->obsz[0], obs->obslon[0], obs->obslat[0], xo);
490 geo2cart(obs->vpz[0], obs->vplon[0], obs->vplat[0], xs);
491
492
493 if (slant) {
494 atm->np = 0;
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];
499 cart2geo(xm, &atm->z[atm->np], &atm->lon[atm->np],
500 &atm->lat[atm->np]);
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 ray path data points!");
508 }
509 } else {
510 atm->np = 0;
511 for (double f = 10.0; f <= 90.0; f += 0.2) {
512 atm->time[atm->np] = pert->
time[itrack][ixtrack];
513 atm->z[atm->np] = f;
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 ray path data points!");
518 }
519 }
520
521
522 climatology(&ctl, atm);
523
524
525 for (int ip = 0; ip < atm->np; ip++)
526 intpol(model, atm->z[ip], atm->lon[ip], atm->lat[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
539 if (kernel[0] != '-') {
540
541
542 if (!init) {
543 init = 1;
544 read_shape(kernel, kz, kw, &nk);
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]) {
553 const int iz = locate_irr(kz, nk, atm->z[ip]);
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
566 formod(&ctl, atm, obs);
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 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].