37 int nc_result=(cmd); \
38 if(nc_result!=NC_NOERR) \
39 ERRMSG("%s", nc_strerror(nc_result)); \
130 const char *longname,
164 static atm_t atm_apr, atm_clim, atm_i;
165 static obs_t obs_i, obs_meas;
169 static FILE *in, *out;
171 static char filename[LEN], filename2[2 * LEN];
176 static int channel[ND], n, ntask = -1, rank, size;
183 MPI_Init(&argc, &argv);
184 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
185 MPI_Comm_size(MPI_COMM_WORLD, &size);
192 ERRMSG(
"Give parameters: <ctl> <filelist>");
195 read_ctl(argc, argv, &ctl);
196 read_ret(argc, argv, &ctl, &ret);
199 tbl_t *tbl = read_tbl(&ctl);
202 const int nz = (int) scan_ctl(argc, argv,
"NZ", -1,
"", NULL);
204 ERRMSG(
"Too many altitudes!");
205 for (
int iz = 0; iz < nz; iz++)
206 z[iz] = scan_ctl(argc, argv,
"Z", iz,
"", NULL);
209 const int track0 = (int) scan_ctl(argc, argv,
"TRACK_MIN", -1,
"0", NULL);
210 const int track1 = (int) scan_ctl(argc, argv,
"TRACK_MAX", -1,
"134", NULL);
213 const int xtrack0 = (int) scan_ctl(argc, argv,
"XTRACK_MIN", -1,
"0", NULL);
215 (int) scan_ctl(argc, argv,
"XTRACK_MAX", -1,
"89", NULL);
218 const double sx = scan_ctl(argc, argv,
"SX", -1,
"8", NULL);
219 const double sy = scan_ctl(argc, argv,
"SY", -1,
"2", NULL);
226 printf(
"Read filelist: %s\n", argv[2]);
227 if (!(in = fopen(argv[2],
"r")))
228 ERRMSG(
"Cannot open filelist!");
231 while (fscanf(in,
"%s", filename) != EOF) {
234 if ((++ntask) % size != rank)
238 printf(
"Retrieve file %s on rank %d of %d (with %d threads)...\n",
239 filename, rank + 1, size, omp_get_max_threads());
249 for (
int id = 0;
id < ctl.nd;
id++) {
252 if (fabs(ctl.nu[
id] - ncd.
l1_nu[i]) < 0.1)
255 ERRMSG(
"Cannot identify radiance channel!");
264 for (
int iz = 0; iz < nz; iz++)
265 atm_clim.z[iz] = z[iz];
266 climatology(&ctl, &atm_clim);
273 for (
int track = track0; track <= track1; track++) {
276 TIMER(
"retrieval", 1);
279 for (
int xtrack = xtrack0; xtrack <= xtrack1; xtrack++) {
283 obs_meas.time[0] = ncd.
l1_time[track][xtrack];
284 obs_meas.obsz[0] = ncd.
l1_sat_z[track];
287 obs_meas.vplon[0] = ncd.
l1_lon[track][xtrack];
288 obs_meas.vplat[0] = ncd.
l1_lat[track][xtrack];
289 for (
int id = 0;
id < ctl.nd;
id++)
290 obs_meas.rad[
id][0] = ncd.
l1_rad[track][xtrack][channel[
id]];
293 for (
int id = 0;
id < ctl.nd;
id++)
294 if (ctl.nu[
id] >= 2000)
295 obs_meas.rad[id][0] = GSL_NAN;
298 copy_atm(&ctl, &atm_apr, &atm_clim, 0);
299 for (
int ip = 0; ip < atm_apr.np; ip++) {
300 atm_apr.time[ip] = obs_meas.time[0];
301 atm_apr.lon[ip] = obs_meas.vplon[0];
302 atm_apr.lat[ip] = obs_meas.vplat[0];
306 init_l2(&ncd, track, xtrack, &ctl, &atm_apr);
309 optimal_estimation(&ret, &ctl, tbl, &obs_meas, &obs_i,
310 &atm_apr, &atm_i, &chisq[track][xtrack]);
313 for (
int id = 0;
id < ctl.nd;
id++)
314 obs_meas.rad[
id][0] = obs_i.rad[
id][0]
315 = ncd.
l1_rad[track][xtrack][channel[
id]];
316 formod(&ctl, tbl, &atm_i, &obs_i);
320 ni[track][xtrack] = 0;
321 for (
int id = 0;
id < ctl.nd;
id++)
322 if (ctl.nu[
id] >= 2000 && gsl_finite(obs_meas.rad[
id][0])) {
324 (BRIGHT(obs_meas.rad[
id][0], ncd.
l1_nu[channel[
id]])
325 - BRIGHT(obs_i.rad[
id][0], ncd.
l1_nu[channel[
id]]));
328 ni[track][xtrack] /= n;
332 TIMER(
"retrieval", 3);
340 sprintf(filename2,
"%s.nlte.tab", filename);
343 printf(
"Write non-LTE data: %s\n", filename2);
344 if (!(out = fopen(filename2,
"w")))
345 ERRMSG(
"Cannot create file!");
349 "# $1 = time (seconds since 2000-01-01, 00:00 UTC)\n"
350 "# $2 = longitude [deg]\n"
351 "# $3 = latitude [deg]\n"
352 "# $4 = solar zenith angle [deg]\n"
353 "# $5 = non-LTE index [K]\n" "# $6 = chi^2 of retrieval fit\n");
356 for (
int track = track0; track <= track1; track++) {
358 for (
int xtrack = xtrack0; xtrack <= xtrack1; xtrack++)
359 fprintf(out,
"%.2f %g %g %g %g %g\n",ncd.
l1_time[track][xtrack],
361 RAD2DEG(acos(cos_sza(ncd.
l1_time[track][xtrack],
362 ncd.
l1_lon[track][xtrack],
363 ncd.
l1_lat[track][xtrack]))),
364 ni[track][xtrack], chisq[track][xtrack]);
371 printf(
"Retrieval finished on rank %d of %d!\n", rank, size);
384 printf(
"MEMORY_ATM = %g MByte\n", 4. *
sizeof(atm_t) / 1024. / 1024.);
385 printf(
"MEMORY_CTL = %g MByte\n", 1. *
sizeof(ctl_t) / 1024. / 1024.);
386 printf(
"MEMORY_NCD = %g MByte\n", 1. *
sizeof(
ncd_t) / 1024. / 1024.);
387 printf(
"MEMORY_OBS = %g MByte\n", 3. *
sizeof(atm_t) / 1024. / 1024.);
388 printf(
"MEMORY_RET = %g MByte\n", 1. *
sizeof(ret_t) / 1024. / 1024.);
389 printf(
"MEMORY_TBL = %g MByte\n", 1. *
sizeof(tbl_t) / 1024. / 1024.);
392 printf(
"SIZE_TASKS = %d\n", size);
393 printf(
"SIZE_THREADS = %d\n", omp_get_max_threads());
407 const char *longname,
414 if (nc_inq_varid(ncid, varname, varid) != NC_NOERR) {
417 NC(nc_def_var(ncid, varname, type, ndims, dimid, varid));
421 (ncid, *varid,
"long_name", strlen(longname), longname));
424 NC(nc_put_att_text(ncid, *varid,
"units", strlen(unit), unit));
438 for (
int lay = 0; lay <
L2_NLAY; lay++) {
441 for (
int track = 0; track <
L2_NTRACK; track++)
442 for (
int xtrack = 0; xtrack <
L2_NXTRACK; xtrack++) {
445 help[track][xtrack] = 0;
449 for (
int track2 = 0; track2 <
L2_NTRACK; track2++)
450 for (
int xtrack2 = 0; xtrack2 <
L2_NXTRACK; xtrack2++)
451 if (gsl_finite(x[track2][xtrack2][lay])
452 && x[track2][xtrack2][lay] > 0) {
453 const double w = exp(-gsl_pow_2((xtrack - xtrack2) / cx)
454 - gsl_pow_2((track - track2) / cy));
455 help[track][xtrack] += w * x[track2][xtrack2][lay];
461 help[track][xtrack] /= wsum;
463 help[track][xtrack] = GSL_NAN;
467 for (
int track = 0; track <
L2_NTRACK; track++)
468 for (
int xtrack = 0; xtrack <
L2_NXTRACK; xtrack++)
469 x[track][xtrack][lay] = help[track][xtrack];
482 static atm_t atm_airs;
484 double k[NW], p, q[NG], t, zmax = 0, zmin = 1000;
492 for (
int lay = 0; lay <
L2_NLAY; lay++)
493 if (gsl_finite(ncd->
l2_z[track][xtrack][lay])) {
494 atm_airs.z[atm_airs.np] = ncd->
l2_z[track][xtrack][lay];
495 atm_airs.p[atm_airs.np] = ncd->
l2_p[lay];
496 atm_airs.t[atm_airs.np] = ncd->
l2_t[track][xtrack][lay];
497 if ((++atm_airs.np) > NP)
498 ERRMSG(
"Too many layers!");
502 if (atm_airs.np <= 0)
506 for (
int ip = 0; ip < atm_airs.np; ip++) {
507 zmax = GSL_MAX(zmax, atm_airs.z[ip]);
508 zmin = GSL_MIN(zmin, atm_airs.z[ip]);
512 for (
int ip = 0; ip < atm->np; ip++) {
515 intpol_atm(ctl, &atm_airs, atm->z[ip], &p, &t, q, k);
519 if (atm->z[ip] > zmax)
520 w = GSL_MAX(1 - (atm->z[ip] - zmax) / 50, 0);
521 if (atm->z[ip] < zmin)
522 w = GSL_MAX(1 - (zmin - atm->z[ip]) / 50, 0);
525 atm->t[ip] = w * t + (1 - w) * atm->t[ip];
526 atm->p[ip] = w * p + (1 - w) * atm->p[ip];
539 printf(
"Read netCDF file: %s\n", filename);
540 NC(nc_open(filename, NC_WRITE, &ncd->
ncid));
543 NC(nc_inq_varid(ncd->
ncid,
"l1_time", &varid));
545 NC(nc_inq_varid(ncd->
ncid,
"l1_lon", &varid));
546 NC(nc_get_var_double(ncd->
ncid, varid, ncd->
l1_lon[0]));
547 NC(nc_inq_varid(ncd->
ncid,
"l1_lat", &varid));
548 NC(nc_get_var_double(ncd->
ncid, varid, ncd->
l1_lat[0]));
549 NC(nc_inq_varid(ncd->
ncid,
"l1_sat_z", &varid));
551 NC(nc_inq_varid(ncd->
ncid,
"l1_sat_lon", &varid));
553 NC(nc_inq_varid(ncd->
ncid,
"l1_sat_lat", &varid));
555 NC(nc_inq_varid(ncd->
ncid,
"l1_nu", &varid));
556 NC(nc_get_var_double(ncd->
ncid, varid, ncd->
l1_nu));
557 NC(nc_inq_varid(ncd->
ncid,
"l1_rad", &varid));
558 NC(nc_get_var_float(ncd->
ncid, varid, ncd->
l1_rad[0][0]));
561 NC(nc_inq_varid(ncd->
ncid,
"l2_z", &varid));
562 NC(nc_get_var_double(ncd->
ncid, varid, ncd->
l2_z[0][0]));
563 NC(nc_inq_varid(ncd->
ncid,
"l2_press", &varid));
564 NC(nc_get_var_double(ncd->
ncid, varid, ncd->
l2_p));
565 NC(nc_inq_varid(ncd->
ncid,
"l2_temp", &varid));
566 NC(nc_get_var_double(ncd->
ncid, varid, ncd->
l2_t[0][0]));
int main(int argc, char *argv[])
#define NC(cmd)
Execute netCDF library command and check result.
void fill_gaps(double x[L2_NTRACK][L2_NXTRACK][L2_NLAY], double cx, double cy)
Fill data gaps in L2 data.
#define L1_NXTRACK
Across-track size of AIRS radiance granule (don't change).
#define L1_NTRACK
Along-track size of AIRS radiance granule (don't change).
#define L2_NXTRACK
Across-track size of AIRS retrieval granule (don't change).
void read_nc(char *filename, ncd_t *ncd)
Read netCDF file.
void add_var(int ncid, const char *varname, const char *unit, const char *longname, int type, int dimid[], int *varid, int ndims)
Create variable in netCDF file.
#define L2_NLAY
Number of AIRS pressure layers (don't change).
#define L1_NCHAN
Number of AIRS radiance channels (don't change).
#define L2_NTRACK
Along-track size of AIRS retrieval granule (don't change).
void init_l2(ncd_t *ncd, int track, int xtrack, ctl_t *ctl, atm_t *atm)
Initialize with AIRS Level-2 data.
double l1_lat[L1_NTRACK][L1_NXTRACK]
Footprint latitude [deg].
double l1_lon[L1_NTRACK][L1_NXTRACK]
Footprint longitude [deg].
double l2_z[L2_NTRACK][L2_NXTRACK][L2_NLAY]
Altitude [km].
double l1_sat_lat[L1_NTRACK]
Satellite latitude [deg].
double l1_sat_lon[L1_NTRACK]
Satellite longitude [deg].
double l2_p[L2_NLAY]
Pressure [hPa].
double l2_t[L2_NTRACK][L2_NXTRACK][L2_NLAY]
Temperature [K].
double l1_nu[L1_NCHAN]
Channel frequencies [cm^-1].
double l1_sat_z[L1_NTRACK]
Satellite altitude [km].
float l1_rad[L1_NTRACK][L1_NXTRACK][L1_NCHAN]
Radiance [W/(m^2 sr cm^-1)].
double l1_time[L1_NTRACK][L1_NXTRACK]
Time (seconds since 2000-01-01T00:00Z).