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 tbl_t *tbl = read_tbl(&ctl);
154
155
156
157
158
159
161 ALLOC(help, float,
163
164
165 printf("Read %s data: %s\n", argv[2], argv[3]);
166 NC(nc_open(argv[3], NC_NOWRITE, &ncid));
167
168
169 LOG(2, "Check time...");
170 if (nc_inq_dimid(ncid, "time", &dimid) != NC_NOERR)
171 NC(nc_inq_dimid(ncid,
"time", &dimid));
172 NC(nc_inq_dimlen(ncid, dimid, &rs));
173 if (rs != 1)
174 ERRMSG("Only one time step is allowed!");
175
176
177 LOG(2, "Read latitudes...");
178 if (nc_inq_dimid(ncid, "lat", &dimid) != NC_NOERR)
179 NC(nc_inq_dimid(ncid,
"latitude", &dimid));
180 NC(nc_inq_dimlen(ncid, dimid, &rs));
181 model->
nlat = (int) rs;
183 ERRMSG("Too many latitudes!");
184 if (nc_inq_varid(ncid, "lat", &varid) != NC_NOERR)
185 NC(nc_inq_varid(ncid,
"latitude", &varid));
186 NC(nc_get_var_double(ncid, varid, model->
lat));
187
188
189 LOG(2, "Read longitudes...");
190 if (nc_inq_dimid(ncid, "lon", &dimid) != NC_NOERR)
191 NC(nc_inq_dimid(ncid,
"longitude", &dimid));
192 NC(nc_inq_dimlen(ncid, dimid, &rs));
193 model->
nlon = (int) rs;
195 ERRMSG("Too many longitudes!");
196 if (nc_inq_varid(ncid, "lon", &varid))
197 NC(nc_inq_varid(ncid,
"longitude", &varid));
198 NC(nc_get_var_double(ncid, varid, model->
lon));
199
200
201 if (strcasecmp(argv[2], "icon") == 0) {
202
203
204 LOG(2, "Read levels...");
205 NC(nc_inq_dimid(ncid,
"height", &dimid));
206 NC(nc_inq_dimlen(ncid, dimid, &rs));
207 model->
nz = (int) rs;
209 ERRMSG("Too many altitudes!");
210
211
212 LOG(2, "Read height...");
213 NC(nc_inq_varid(ncid,
"z_mc", &varid));
214 NC(nc_get_var_float(ncid, varid, help));
215 for (
int ilon = 0; ilon < model->
nlon; ilon++)
216 for (
int ilat = 0; ilat < model->
nlat; ilat++)
217 for (
int iz = 0; iz < model->
nz; iz++)
218 model->
z[ilon][ilat][iz] =
219 (
float) (help[(iz * model->
nlat + ilat) * model->
nlon + ilon] /
220 1e3);
221
222
223 LOG(2, "Read temperature...");
224 NC(nc_inq_varid(ncid,
"temp", &varid));
225 NC(nc_get_var_float(ncid, varid, help));
226 for (
int ilon = 0; ilon < model->
nlon; ilon++)
227 for (
int ilat = 0; ilat < model->
nlat; ilat++)
228 for (
int iz = 0; iz < model->
nz; iz++)
229 model->
t[ilon][ilat][iz] =
230 help[(iz * model->
nlat + ilat) * model->
nlon + ilon];
231
232
233 LOG(2, "Read pressure...");
234 NC(nc_inq_varid(ncid,
"pres", &varid));
235 NC(nc_get_var_float(ncid, varid, help));
236 for (
int ilon = 0; ilon < model->
nlon; ilon++)
237 for (
int ilat = 0; ilat < model->
nlat; ilat++)
238 for (
int iz = 0; iz < model->
nz; iz++)
239 model->
p[ilon][ilat][iz] =
240 (
float) (help[(iz * model->
nlat + ilat) * model->
nlon + ilon] /
241 1e2);
242 }
243
244
245 else if (strcasecmp(argv[2], "ifs") == 0) {
246
247
248 LOG(2, "Read levels...");
249 NC(nc_inq_dimid(ncid,
"lev_2", &dimid));
250 NC(nc_inq_dimlen(ncid, dimid, &rs));
251 model->
nz = (int) rs;
253 ERRMSG("Too many altitudes!");
254
255
256 LOG(2, "Read height...");
257 NC(nc_inq_varid(ncid,
"gh", &varid));
258 NC(nc_get_var_float(ncid, varid, help));
259 for (
int ilon = 0; ilon < model->
nlon; ilon++)
260 for (
int ilat = 0; ilat < model->
nlat; ilat++)
261 for (
int iz = 0; iz < model->
nz; iz++)
262 model->
z[ilon][ilat][iz] =
263 (
float) (help[(iz * model->
nlat + ilat) * model->
nlon + ilon] /
264 1e3);
265
266
267 LOG(2, "Read temperature...");
268 NC(nc_inq_varid(ncid,
"t", &varid));
269 NC(nc_get_var_float(ncid, varid, help));
270 for (
int ilon = 0; ilon < model->
nlon; ilon++)
271 for (
int ilat = 0; ilat < model->
nlat; ilat++)
272 for (
int iz = 0; iz < model->
nz; iz++)
273 model->
t[ilon][ilat][iz] =
274 help[(iz * model->
nlat + ilat) * model->
nlon + ilon];
275
276
277 LOG(2, "Read surface pressure...");
278 NC(nc_inq_varid(ncid,
"lnsp", &varid));
279 NC(nc_get_var_float(ncid, varid, help));
280 for (
int ilon = 0; ilon < model->
nlon; ilon++)
281 for (
int ilat = 0; ilat < model->
nlat; ilat++)
282 model->
ps[ilon][ilat] = (
float) exp(help[ilat * model->
nlon + ilon]);
283
284
285 LOG(2, "Read grid coefficients...");
286 NC(nc_inq_varid(ncid,
"hyam", &varid));
287 NC(nc_get_var_double(ncid, varid, hyam));
288 NC(nc_inq_varid(ncid,
"hybm", &varid));
289 NC(nc_get_var_double(ncid, varid, hybm));
290
291
292 LOG(2, "Calculate pressure...");
293 for (
int ilon = 0; ilon < model->
nlon; ilon++)
294 for (
int ilat = 0; ilat < model->
nlat; ilat++)
295 for (
int iz = 0; iz < model->
nz; iz++)
296 model->
p[ilon][ilat][iz]
297 = (
float) ((hyam[iz] + hybm[iz] * model->
ps[ilon][ilat]) / 100.);
298 }
299
300
301 else if (strcasecmp(argv[2], "um") == 0) {
302
303
304 LOG(2, "Read levels...");
305 if (nc_inq_dimid(ncid, "RHO_TOP_eta_rho", &dimid) != NC_NOERR)
306 NC(nc_inq_dimid(ncid,
"RHO_eta_rho", &dimid));
307 NC(nc_inq_dimlen(ncid, dimid, &rs));
308 model->
nz = (int) rs;
310 ERRMSG("Too many altitudes!");
311
312
313 LOG(2, "Read height...");
314 if (nc_inq_varid(ncid, "STASH_m01s15i102_2", &varid) != NC_NOERR)
315 NC(nc_inq_varid(ncid,
"STASH_m01s15i102", &varid));
316 NC(nc_get_var_float(ncid, varid, help));
317 for (
int ilon = 0; ilon < model->
nlon; ilon++)
318 for (
int ilat = 0; ilat < model->
nlat; ilat++)
319 for (
int iz = 0; iz < model->
nz; iz++)
320 model->
z[ilon][ilat][iz] =
321 (
float) (help[(iz * model->
nlat + ilat) * model->
nlon + ilon] /
322 1e3);
323
324
325 LOG(2, "Read temperature...");
326 NC(nc_inq_varid(ncid,
"STASH_m01s30i004", &varid));
327 NC(nc_get_var_float(ncid, varid, help));
328 for (
int ilon = 0; ilon < model->
nlon; ilon++)
329 for (
int ilat = 0; ilat < model->
nlat; ilat++)
330 for (
int iz = 0; iz < model->
nz; iz++)
331 model->
t[ilon][ilat][iz] =
332 help[(iz * model->
nlat + ilat) * model->
nlon + ilon];
333
334
335 LOG(2, "Read pressure...");
336 NC(nc_inq_varid(ncid,
"STASH_m01s00i407", &varid));
337 NC(nc_get_var_float(ncid, varid, help));
338 for (
int ilon = 0; ilon < model->
nlon; ilon++)
339 for (
int ilat = 0; ilat < model->
nlat; ilat++)
340 for (
int iz = 0; iz < model->
nz; iz++)
341 model->
p[ilon][ilat][iz] =
342 0.01f * help[(iz * model->
nlat + ilat) * model->
nlon + ilon];
343 }
344
345
346 else if (strcasecmp(argv[2], "wrf") == 0) {
347
348
349 LOG(2, "Read levels...");
350 NC(nc_inq_dimid(ncid,
"bottom_top", &dimid));
351 NC(nc_inq_dimlen(ncid, dimid, &rs));
352 model->
nz = (int) rs;
354 ERRMSG("Too many altitudes!");
355
356
357 LOG(2, "Read height...");
358 NC(nc_inq_varid(ncid,
"z", &varid));
359 NC(nc_get_var_float(ncid, varid, help));
360 for (
int ilon = 0; ilon < model->
nlon; ilon++)
361 for (
int ilat = 0; ilat < model->
nlat; ilat++)
362 for (
int iz = 0; iz < model->
nz; iz++)
363 model->
z[ilon][ilat][iz] =
364 (
float) (help[(iz * model->
nlat + ilat) * model->
nlon + ilon] /
365 1e3);
366
367
368 LOG(2, "Read temperature...");
369 NC(nc_inq_varid(ncid,
"tk", &varid));
370 NC(nc_get_var_float(ncid, varid, help));
371 for (
int ilon = 0; ilon < model->
nlon; ilon++)
372 for (
int ilat = 0; ilat < model->
nlat; ilat++)
373 for (
int iz = 0; iz < model->
nz; iz++)
374 model->
t[ilon][ilat][iz] =
375 help[(iz * model->
nlat + ilat) * model->
nlon + ilon];
376
377
378 LOG(2, "Read pressure...");
379 NC(nc_inq_varid(ncid,
"p", &varid));
380 NC(nc_get_var_float(ncid, varid, help));
381 for (
int ilon = 0; ilon < model->
nlon; ilon++)
382 for (
int ilat = 0; ilat < model->
nlat; ilat++)
383 for (
int iz = 0; iz < model->
nz; iz++)
384 model->
p[ilon][ilat][iz] =
385 (
float) (help[(iz * model->
nlat + ilat) * model->
nlon + ilon] /
386 1e2);
387 }
388
389 else
390 ERRMSG("Model type not supported!");
391
392
394
395
396 free(help);
397
398
399 LOG(2, "Checking...");
400 for (
int ilon = 0; ilon < model->
nlon; ilon++)
401 for (
int ilat = 0; ilat < model->
nlat; ilat++)
402 for (
int iz = 0; iz < model->
nz; iz++)
403 if (model->
t[ilon][ilat][iz] <= 100
404 || model->
t[ilon][ilat][iz] >= 400) {
405 model->
p[ilon][ilat][iz] = GSL_NAN;
406 model->
t[ilon][ilat][iz] = GSL_NAN;
407 model->
z[ilon][ilat][iz] = GSL_NAN;
408 }
409
410
411 LOG(2, "Smoothing...");
413
414
415 for (
int iz = 0; iz < model->
nz; iz++)
416 printf("section_height: %d %g %g %g %g %g\n", iz,
417 model->
z[model->
nlon / 2][model->
nlat / 2][iz],
419 model->
p[model->
nlon / 2][model->
nlat / 2][iz],
420 model->
t[model->
nlon / 2][model->
nlat / 2][iz]);
421 for (
int ilon = 0; ilon < model->
nlon; ilon++)
422 printf("section_west_east: %d %g %g %g %g %g\n", ilon,
423 model->
z[ilon][model->
nlat / 2][model->
nz / 2],
424 model->
lon[ilon], model->
lat[model->
nlat / 2],
425 model->
p[ilon][model->
nlat / 2][model->
nz / 2],
426 model->
t[ilon][model->
nlat / 2][model->
nz / 2]);
427 for (
int ilat = 0; ilat < model->
nlat; ilat++)
428 printf("section_north_south: %d %g %g %g %g %g\n", ilat,
429 model->
z[model->
nlon / 2][ilat][model->
nz / 2],
430 model->
lon[model->
nlon / 2], model->
lat[ilat],
431 model->
p[model->
nlon / 2][ilat][model->
nz / 2],
432 model->
t[model->
nlon / 2][ilat][model->
nz / 2]);
433
434
435
436
437
438
439 ALLOC(atm, atm_t, 1);
440 ALLOC(obs, obs_t, 1);
443
444
446
447
448 for (
int itrack = 0; itrack < pert->
ntrack; itrack++) {
449 if (pert->
time[itrack][44] < t_ovp - 720 || itrack == 0)
450 track0 = itrack;
451 track1 = itrack;
452 if (pert->
time[itrack][44] > t_ovp + 720)
453 break;
454 }
455
456
458
459
461
462
464
465
468
469
470
471
472
473
474 for (int itrack = track0; itrack <= track1; itrack++)
475 for (
int ixtrack = 0; ixtrack < pert->
nxtrack; ixtrack++) {
476
477
478 if (ixtrack == 0)
479 printf("Compute track %d / %d ...\n", itrack - track0 + 1,
480 track1 - track0 + 1);
481
482
483 obs->nr = 1;
484 obs->obsz[0] = 705;
485 obs->obslon[0] = pert->
lon[itrack][44];
486 obs->obslat[0] = pert->
lat[itrack][44];
487 obs->vpz[0] = 0;
488 obs->vplon[0] = pert->
lon[itrack][ixtrack];
489 obs->vplat[0] = pert->
lat[itrack][ixtrack];
490
491
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 pert->
bt[itrack][ixtrack] = wsum = 0;
554 for (int ip = 0; ip < atm->np; ip++)
555 if (atm->z[ip] >= kz[0] && atm->z[ip] <= kz[nk - 1]) {
556 const int iz = locate_irr(kz, nk, atm->z[ip]);
557 const double w =
558 LIN(kz[iz], kw[iz], kz[iz + 1], kw[iz + 1], atm->z[ip]);
559 pert->
bt[itrack][ixtrack] += w * atm->t[ip];
560 wsum += w;
561 }
562 pert->
bt[itrack][ixtrack] /= wsum;
563 }
564
565
566 else {
567
568
569 formod(&ctl, tbl, atm, obs);
570
571
572 pert->
bt[itrack][ixtrack] = 0;
573 for (int id = 0; id < ctl.nd; id++)
574 pert->
bt[itrack][ixtrack] += obs->rad[
id][0] / ctl.nd;
575 }
576 }
577 }
578
579
580 if (extpol)
581 for (int itrack = track0; itrack <= track1; itrack++) {
582 for (
int ixtrack = 1; ixtrack < pert->
nxtrack; ixtrack++)
583 if (!gsl_finite(pert->
bt[itrack][ixtrack]))
584 pert->
bt[itrack][ixtrack] = pert->
bt[itrack][ixtrack - 1];
585 for (
int ixtrack = pert->
nxtrack - 2; ixtrack >= 0; ixtrack--)
586 if (!gsl_finite(pert->
bt[itrack][ixtrack]))
587 pert->
bt[itrack][ixtrack] = pert->
bt[itrack][ixtrack + 1];
588 }
589
590
591
592
593
594
596
597
599
600
602
603
606
607
608 free(atm);
609 free(obs);
610 free(pert);
611 free(wave);
612 free(tbl);
613
614 return EXIT_SUCCESS;
615}
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].