37 int nc_result=(cmd); \
38 if(nc_result!=NC_NOERR) \
39 ERRMSG("%s", nc_strerror(nc_result)); \
134 double err_formod[ND];
137 double err_noise[ND];
186 const char *longname,
206 gsl_matrix * s_a_inv,
207 gsl_vector * sig_eps_inv);
271 gsl_vector * sig_noise,
272 gsl_vector * sig_formod,
273 gsl_vector * sig_eps_inv);
289 static atm_t atm_apr, atm_clim, atm_i;
290 static obs_t obs_i, obs_meas;
298 double chisq, chisq_min, chisq_max, chisq_mean, z[NP];
300 int channel[ND], m, ntask = -1, rank, size;
307 MPI_Init(&argc, &argv);
308 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
309 MPI_Comm_size(MPI_COMM_WORLD, &size);
316 ERRMSG(
"Give parameters: <ctl> <filelist>");
319 read_ctl(argc, argv, &ctl);
323 tbl_t *tbl = read_tbl(&ctl);
326 const int nz = (int) scan_ctl(argc, argv,
"NZ", -1,
"", NULL);
328 ERRMSG(
"Too many altitudes!");
329 for (
int iz = 0; iz < nz; iz++)
330 z[iz] = scan_ctl(argc, argv,
"Z", iz,
"", NULL);
333 const int track0 = (int) scan_ctl(argc, argv,
"TRACK_MIN", -1,
"0", NULL);
334 const int track1 = (int) scan_ctl(argc, argv,
"TRACK_MAX", -1,
"134", NULL);
337 const int xtrack0 = (int) scan_ctl(argc, argv,
"XTRACK_MIN", -1,
"0", NULL);
339 (int) scan_ctl(argc, argv,
"XTRACK_MAX", -1,
"89", NULL);
342 int np0 = (int) scan_ctl(argc, argv,
"NP_MIN", -1,
"0", NULL);
343 int np1 = (int) scan_ctl(argc, argv,
"NP_MAX", -1,
"100", NULL);
344 np1 = GSL_MIN(np1, nz - 1);
347 const double sx = scan_ctl(argc, argv,
"SX", -1,
"8", NULL);
348 const double sy = scan_ctl(argc, argv,
"SY", -1,
"2", NULL);
351 const double sza_thresh = scan_ctl(argc, argv,
"SZA", -1,
"96", NULL);
358 printf(
"Read filelist: %s\n", argv[2]);
359 if (!(in = fopen(argv[2],
"r")))
360 ERRMSG(
"Cannot open filelist!");
363 while (fscanf(in,
"%s", filename) != EOF) {
366 if ((++ntask) % size != rank)
370 printf(
"Retrieve file %s on rank %d of %d (with %d threads)...\n",
371 filename, rank + 1, size, omp_get_max_threads());
381 for (
int id = 0;
id < ctl.nd;
id++) {
384 if (fabs(ctl.nu[
id] - ncd.
l1_nu[i]) < 0.1)
387 ERRMSG(
"Cannot identify radiance channel!");
396 for (
int iz = 0; iz < nz; iz++)
397 atm_clim.z[iz] = z[iz];
398 climatology(&ctl, &atm_clim);
411 for (
int track = track0; track <= track1; track++) {
414 TIMER(
"retrieval", 1);
417 for (
int xtrack = xtrack0; xtrack <= xtrack1; xtrack++) {
421 obs_meas.time[0] = ncd.
l1_time[track][xtrack];
422 obs_meas.obsz[0] = ncd.
l1_sat_z[track];
425 obs_meas.vplon[0] = ncd.
l1_lon[track][xtrack];
426 obs_meas.vplat[0] = ncd.
l1_lat[track][xtrack];
427 for (
int id = 0;
id < ctl.nd;
id++)
428 obs_meas.rad[
id][0] = ncd.
l1_rad[track][xtrack][channel[
id]];
431 if (sza(obs_meas.time[0], obs_meas.obslon[0], obs_meas.obslat[0])
433 for (
int id = 0;
id < ctl.nd;
id++)
434 if (ctl.nu[
id] >= 2000)
435 obs_meas.rad[id][0] = GSL_NAN;
438 copy_atm(&ctl, &atm_apr, &atm_clim, 0);
439 for (
int ip = 0; ip < atm_apr.np; ip++) {
440 atm_apr.time[ip] = obs_meas.time[0];
441 atm_apr.lon[ip] = obs_meas.vplon[0];
442 atm_apr.lat[ip] = obs_meas.vplat[0];
446 init_l2(&ncd, track, xtrack, &ctl, &atm_apr);
450 &atm_apr, &atm_i, &chisq);
453 if (gsl_finite(chisq)) {
454 chisq_min = GSL_MIN(chisq_min, chisq);
455 chisq_max = GSL_MAX(chisq_max, chisq);
461 buffer_nc(&atm_i, chisq, &ncd, track, xtrack, np0, np1);
465 TIMER(
"retrieval", 3);
476 printf(
"chi^2: min= %g / mean= %g / max= %g / m= %d\n",
477 chisq_min, chisq_mean / m, chisq_max, m);
478 printf(
"Retrieval finished on rank %d of %d!\n", rank, size);
488 printf(
"MEMORY_ATM = %g MByte\n", 4. *
sizeof(atm_t) / 1024. / 1024.);
489 printf(
"MEMORY_CTL = %g MByte\n", 1. *
sizeof(ctl_t) / 1024. / 1024.);
490 printf(
"MEMORY_NCD = %g MByte\n", 1. *
sizeof(
ncd_t) / 1024. / 1024.);
491 printf(
"MEMORY_OBS = %g MByte\n", 3. *
sizeof(atm_t) / 1024. / 1024.);
492 printf(
"MEMORY_RET = %g MByte\n", 1. *
sizeof(
ret_t) / 1024. / 1024.);
493 printf(
"MEMORY_TBL = %g MByte\n", 1. *
sizeof(tbl_t) / 1024. / 1024.);
496 printf(
"SIZE_TASKS = %d\n", size);
497 printf(
"SIZE_THREADS = %d\n", omp_get_max_threads());
511 const char *longname,
518 if (nc_inq_varid(ncid, varname, varid) != NC_NOERR) {
521 NC(nc_def_var(ncid, varname, type, ndims, dimid, varid));
525 (ncid, *varid,
"long_name", strlen(longname), longname));
528 NC(nc_put_att_text(ncid, *varid,
"units", strlen(unit), unit));
544 ncd->
np = np1 - np0 + 1;
547 for (
int ip = np0; ip <= np1; ip++) {
548 ncd->
ret_z[ip - np0] = (float) atm->z[ip];
551 (gsl_finite(chisq) ? (float) atm->t[ip] : GSL_NAN);
561 gsl_vector *sig_eps_inv) {
563 double chisq_a, chisq_m = 0;
566 const size_t m = dy->size;
567 const size_t n = dx->size;
570 gsl_vector *x_aux = gsl_vector_alloc(n);
571 gsl_vector *y_aux = gsl_vector_alloc(m);
575 for (
size_t i = 0; i < m; i++)
577 gsl_pow_2(gsl_vector_get(dy, i) * gsl_vector_get(sig_eps_inv, i));
578 gsl_blas_dgemv(CblasNoTrans, 1.0, s_a_inv, dx, 0.0, x_aux);
579 gsl_blas_ddot(dx, x_aux, &chisq_a);
582 gsl_vector_free(x_aux);
583 gsl_vector_free(y_aux);
586 return (chisq_m + chisq_a) / (double) m;
599 for (
int lay = 0; lay <
L2_NLAY; lay++) {
602 for (
int track = 0; track <
L2_NTRACK; track++)
603 for (
int xtrack = 0; xtrack <
L2_NXTRACK; xtrack++) {
606 help[track][xtrack] = 0;
610 for (
int track2 = 0; track2 <
L2_NTRACK; track2++)
611 for (
int xtrack2 = 0; xtrack2 <
L2_NXTRACK; xtrack2++)
612 if (gsl_finite(x[track2][xtrack2][lay])
613 && x[track2][xtrack2][lay] > 0) {
614 const double w = exp(-gsl_pow_2((xtrack - xtrack2) / cx)
615 - gsl_pow_2((track - track2) / cy));
616 help[track][xtrack] += w * x[track2][xtrack2][lay];
622 help[track][xtrack] /= wsum;
624 help[track][xtrack] = GSL_NAN;
628 for (
int track = 0; track <
L2_NTRACK; track++)
629 for (
int xtrack = 0; xtrack <
L2_NXTRACK; xtrack++)
630 x[track][xtrack][lay] = help[track][xtrack];
643 static atm_t atm_airs;
645 double k[NW], p, q[NG], t, zmax = 0, zmin = 1000;
653 for (
int lay = 0; lay <
L2_NLAY; lay++)
654 if (gsl_finite(ncd->
l2_z[track][xtrack][lay])) {
655 atm_airs.z[atm_airs.np] = ncd->
l2_z[track][xtrack][lay];
656 atm_airs.p[atm_airs.np] = ncd->
l2_p[lay];
657 atm_airs.t[atm_airs.np] = ncd->
l2_t[track][xtrack][lay];
658 if ((++atm_airs.np) > NP)
659 ERRMSG(
"Too many layers!");
663 if (atm_airs.np <= 0)
667 for (
int ip = 0; ip < atm_airs.np; ip++) {
668 zmax = GSL_MAX(zmax, atm_airs.z[ip]);
669 zmin = GSL_MIN(zmin, atm_airs.z[ip]);
673 for (
int ip = 0; ip < atm->np; ip++) {
676 intpol_atm(ctl, &atm_airs, atm->z[ip], &p, &t, q, k);
680 if (atm->z[ip] > zmax)
681 w = GSL_MAX(1 - (atm->z[ip] - zmax) / 50, 0);
682 if (atm->z[ip] < zmin)
683 w = GSL_MAX(1 - (zmin - atm->z[ip]) / 50, 0);
686 atm->t[ip] = w * t + (1 - w) * atm->t[ip];
687 atm->p[ip] = w * p + (1 - w) * atm->p[ip];
699 const size_t n = a->size1;
702 for (
size_t i = 0; i < n && diag; i++)
703 for (
size_t j = i + 1; j < n; j++)
704 if (gsl_matrix_get(a, i, j) != 0) {
711 for (
size_t i = 0; i < n; i++)
712 gsl_matrix_set(a, i, i, 1 / gsl_matrix_get(a, i, i));
716 gsl_linalg_cholesky_decomp(a);
717 gsl_linalg_cholesky_invert(a);
730 const size_t m = a->size1;
731 const size_t n = a->size2;
734 gsl_matrix *aux = gsl_matrix_alloc(m, n);
737 if (transpose == 1) {
740 for (
size_t i = 0; i < m; i++)
741 for (
size_t j = 0; j < n; j++)
742 gsl_matrix_set(aux, i, j,
743 gsl_vector_get(b, i) * gsl_matrix_get(a, i, j));
746 gsl_blas_dgemm(CblasTrans, CblasNoTrans, 1.0, aux, aux, 0.0, c);
750 else if (transpose == 2) {
753 for (
size_t i = 0; i < m; i++)
754 for (
size_t j = 0; j < n; j++)
755 gsl_matrix_set(aux, i, j,
756 gsl_matrix_get(a, i, j) * gsl_vector_get(b, j));
759 gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1.0, aux, aux, 0.0, c);
763 gsl_matrix_free(aux);
778 static int ipa[N], iqa[N];
780 double disq = 0, lmpar = 0.001;
787 const size_t m = obs2y(ctl, obs_meas, NULL, NULL, NULL);
788 const size_t n = atm2x(ctl, atm_apr, NULL, iqa, ipa);
789 if (m == 0 || n == 0) {
795 gsl_matrix *a = gsl_matrix_alloc(n, n);
796 gsl_matrix *cov = gsl_matrix_alloc(n, n);
797 gsl_matrix *k_i = gsl_matrix_alloc(m, n);
798 gsl_matrix *s_a_inv = gsl_matrix_alloc(n, n);
800 gsl_vector *b = gsl_vector_alloc(n);
801 gsl_vector *dx = gsl_vector_alloc(n);
802 gsl_vector *dy = gsl_vector_alloc(m);
803 gsl_vector *sig_eps_inv = gsl_vector_alloc(m);
804 gsl_vector *sig_formod = gsl_vector_alloc(m);
805 gsl_vector *sig_noise = gsl_vector_alloc(m);
806 gsl_vector *x_a = gsl_vector_alloc(n);
807 gsl_vector *x_i = gsl_vector_alloc(n);
808 gsl_vector *x_step = gsl_vector_alloc(n);
809 gsl_vector *y_aux = gsl_vector_alloc(m);
810 gsl_vector *y_i = gsl_vector_alloc(m);
811 gsl_vector *y_m = gsl_vector_alloc(m);
814 copy_atm(ctl, atm_i, atm_apr, 0);
815 copy_obs(ctl, obs_i, obs_meas, 0);
816 formod(ctl, tbl, atm_i, obs_i);
819 atm2x(ctl, atm_apr, x_a, NULL, NULL);
820 atm2x(ctl, atm_i, x_i, NULL, NULL);
821 obs2y(ctl, obs_meas, y_m, NULL, NULL);
822 obs2y(ctl, obs_i, y_i, NULL, NULL);
829 set_cov_meas(ret, ctl, obs_meas, sig_noise, sig_formod, sig_eps_inv);
832 gsl_vector_memcpy(dx, x_i);
833 gsl_vector_sub(dx, x_a);
834 gsl_vector_memcpy(dy, y_m);
835 gsl_vector_sub(dy, y_i);
841 kernel(ctl, tbl, atm_i, obs_i, k_i);
848 for (
int it = 1; it <= ret->
conv_itmax; it++) {
851 double chisq_old = *chisq;
855 kernel(ctl, tbl, atm_i, obs_i, k_i);
862 for (
size_t i = 0; i < m; i++)
863 gsl_vector_set(y_aux, i, gsl_vector_get(dy, i)
864 * gsl_pow_2(gsl_vector_get(sig_eps_inv, i)));
865 gsl_blas_dgemv(CblasTrans, 1.0, k_i, y_aux, 0.0, b);
866 gsl_blas_dgemv(CblasNoTrans, -1.0, s_a_inv, dx, 1.0, b);
869 for (
int it2 = 0; it2 < 20; it2++) {
872 gsl_matrix_memcpy(a, s_a_inv);
873 gsl_matrix_scale(a, 1 + lmpar);
874 gsl_matrix_add(a, cov);
877 gsl_linalg_cholesky_decomp(a);
878 gsl_linalg_cholesky_solve(a, b, x_step);
881 gsl_vector_add(x_i, x_step);
882 copy_atm(ctl, atm_i, atm_apr, 0);
883 copy_obs(ctl, obs_i, obs_meas, 0);
884 x2atm(ctl, x_i, atm_i);
887 for (
int ip = 0; ip < atm_i->np; ip++) {
888 atm_i->p[ip] = GSL_MIN(GSL_MAX(atm_i->p[ip], 5e-7), 5e4);
889 atm_i->t[ip] = GSL_MIN(GSL_MAX(atm_i->t[ip], 100), 400);
890 for (
int ig = 0; ig < ctl->ng; ig++)
891 atm_i->q[ig][ip] = GSL_MIN(GSL_MAX(atm_i->q[ig][ip], 0), 1);
892 for (
int iw = 0; iw < ctl->nw; iw++)
893 atm_i->k[iw][ip] = GSL_MAX(atm_i->k[iw][ip], 0);
897 formod(ctl, tbl, atm_i, obs_i);
898 obs2y(ctl, obs_i, y_i, NULL, NULL);
901 gsl_vector_memcpy(dx, x_i);
902 gsl_vector_sub(dx, x_a);
903 gsl_vector_memcpy(dy, y_m);
904 gsl_vector_sub(dy, y_i);
910 if (*chisq > chisq_old) {
912 gsl_vector_sub(x_i, x_step);
920 gsl_blas_ddot(x_step, b, &disq);
933 gsl_matrix_free(cov);
934 gsl_matrix_free(k_i);
935 gsl_matrix_free(s_a_inv);
940 gsl_vector_free(sig_eps_inv);
941 gsl_vector_free(sig_formod);
942 gsl_vector_free(sig_noise);
943 gsl_vector_free(x_a);
944 gsl_vector_free(x_i);
945 gsl_vector_free(x_step);
946 gsl_vector_free(y_aux);
947 gsl_vector_free(y_i);
948 gsl_vector_free(y_m);
960 printf(
"Read netCDF file: %s\n", filename);
961 NC(nc_open(filename, NC_WRITE, &ncd->
ncid));
964 NC(nc_inq_varid(ncd->
ncid,
"l1_time", &varid));
966 NC(nc_inq_varid(ncd->
ncid,
"l1_lon", &varid));
967 NC(nc_get_var_double(ncd->
ncid, varid, ncd->
l1_lon[0]));
968 NC(nc_inq_varid(ncd->
ncid,
"l1_lat", &varid));
969 NC(nc_get_var_double(ncd->
ncid, varid, ncd->
l1_lat[0]));
970 NC(nc_inq_varid(ncd->
ncid,
"l1_sat_z", &varid));
972 NC(nc_inq_varid(ncd->
ncid,
"l1_sat_lon", &varid));
974 NC(nc_inq_varid(ncd->
ncid,
"l1_sat_lat", &varid));
976 NC(nc_inq_varid(ncd->
ncid,
"l1_nu", &varid));
977 NC(nc_get_var_double(ncd->
ncid, varid, ncd->
l1_nu));
978 NC(nc_inq_varid(ncd->
ncid,
"l1_rad", &varid));
979 NC(nc_get_var_float(ncd->
ncid, varid, ncd->
l1_rad[0][0]));
982 NC(nc_inq_varid(ncd->
ncid,
"l2_z", &varid));
983 NC(nc_get_var_double(ncd->
ncid, varid, ncd->
l2_z[0][0]));
984 NC(nc_inq_varid(ncd->
ncid,
"l2_press", &varid));
985 NC(nc_get_var_double(ncd->
ncid, varid, ncd->
l2_p));
986 NC(nc_inq_varid(ncd->
ncid,
"l2_temp", &varid));
987 NC(nc_get_var_double(ncd->
ncid, varid, ncd->
l2_t[0][0]));
1000 (int) scan_ctl(argc, argv,
"KERNEL_RECOMP", -1,
"3", NULL);
1001 ret->
conv_itmax = (int) scan_ctl(argc, argv,
"CONV_ITMAX", -1,
"30", NULL);
1002 ret->
conv_dmin = scan_ctl(argc, argv,
"CONV_DMIN", -1,
"0.1", NULL);
1004 for (
int id = 0;
id < ctl->nd;
id++)
1005 ret->
err_formod[
id] = scan_ctl(argc, argv,
"ERR_FORMOD",
id,
"0", NULL);
1007 for (
int id = 0;
id < ctl->nd;
id++)
1008 ret->
err_noise[
id] = scan_ctl(argc, argv,
"ERR_NOISE",
id,
"0", NULL);
1010 ret->
err_press = scan_ctl(argc, argv,
"ERR_PRESS", -1,
"0", NULL);
1011 ret->
err_press_cz = scan_ctl(argc, argv,
"ERR_PRESS_CZ", -1,
"-999", NULL);
1012 ret->
err_press_ch = scan_ctl(argc, argv,
"ERR_PRESS_CH", -1,
"-999", NULL);
1014 ret->
err_temp = scan_ctl(argc, argv,
"ERR_TEMP", -1,
"0", NULL);
1015 ret->
err_temp_cz = scan_ctl(argc, argv,
"ERR_TEMP_CZ", -1,
"-999", NULL);
1016 ret->
err_temp_ch = scan_ctl(argc, argv,
"ERR_TEMP_CH", -1,
"-999", NULL);
1018 for (
int ig = 0; ig < ctl->ng; ig++) {
1019 ret->
err_q[ig] = scan_ctl(argc, argv,
"ERR_Q", ig,
"0", NULL);
1020 ret->
err_q_cz[ig] = scan_ctl(argc, argv,
"ERR_Q_CZ", ig,
"-999", NULL);
1021 ret->
err_q_ch[ig] = scan_ctl(argc, argv,
"ERR_Q_CH", ig,
"-999", NULL);
1024 for (
int iw = 0; iw < ctl->nw; iw++) {
1025 ret->
err_k[iw] = scan_ctl(argc, argv,
"ERR_K", iw,
"0", NULL);
1026 ret->
err_k_cz[iw] = scan_ctl(argc, argv,
"ERR_K_CZ", iw,
"-999", NULL);
1027 ret->
err_k_ch[iw] = scan_ctl(argc, argv,
"ERR_K_CH", iw,
"-999", NULL);
1042 const size_t n = s_a->size1;
1045 gsl_vector *x_a = gsl_vector_alloc(n);
1048 atm2x(ctl, atm, x_a, NULL, NULL);
1049 for (
size_t i = 0; i < n; i++) {
1051 gsl_vector_set(x_a, i, ret->
err_press / 100 * gsl_vector_get(x_a, i));
1053 gsl_vector_set(x_a, i, ret->
err_temp);
1054 for (
int ig = 0; ig < ctl->ng; ig++)
1055 if (iqa[i] == IDXQ(ig))
1056 gsl_vector_set(x_a, i, ret->
err_q[ig] / 100 * gsl_vector_get(x_a, i));
1057 for (
int iw = 0; iw < ctl->nw; iw++)
1058 if (iqa[i] == IDXK(iw))
1059 gsl_vector_set(x_a, i, ret->
err_k[iw]);
1063 for (
size_t i = 0; i < n; i++)
1064 if (gsl_pow_2(gsl_vector_get(x_a, i)) <= 0)
1065 ERRMSG(
"Check a priori data (zero standard deviation)!");
1068 gsl_matrix_set_zero(s_a);
1069 for (
size_t i = 0; i < n; i++)
1070 gsl_matrix_set(s_a, i, i, gsl_pow_2(gsl_vector_get(x_a, i)));
1073 for (
size_t i = 0; i < n; i++)
1074 for (
size_t j = 0; j < n; j++)
1075 if (i != j && iqa[i] == iqa[j]) {
1082 if (iqa[i] == IDXP) {
1088 if (iqa[i] == IDXT) {
1094 for (
int ig = 0; ig < ctl->ng; ig++)
1095 if (iqa[i] == IDXQ(ig)) {
1101 for (
int iw = 0; iw < ctl->nw; iw++)
1102 if (iqa[i] == IDXK(iw)) {
1108 if (cz > 0 && ch > 0) {
1111 double x0[3], x1[3];
1112 geo2cart(0, atm->lon[ipa[i]], atm->lat[ipa[i]], x0);
1113 geo2cart(0, atm->lon[ipa[j]], atm->lat[ipa[j]], x1);
1117 exp(-DIST(x0, x1) / ch -
1118 fabs(atm->z[ipa[i]] - atm->z[ipa[j]]) / cz);
1121 gsl_matrix_set(s_a, i, j, gsl_vector_get(x_a, i)
1122 * gsl_vector_get(x_a, j) * rho);
1127 gsl_vector_free(x_a);
1136 gsl_vector *sig_noise,
1137 gsl_vector *sig_formod,
1138 gsl_vector *sig_eps_inv) {
1140 static obs_t obs_err;
1143 const size_t m = sig_eps_inv->size;
1146 copy_obs(ctl, &obs_err, obs, 1);
1147 for (
int ir = 0; ir < obs_err.nr; ir++)
1148 for (
int id = 0;
id < ctl->nd;
id++)
1150 = (gsl_finite(obs->rad[
id][ir]) ? ret->
err_noise[
id] : GSL_NAN);
1151 obs2y(ctl, &obs_err, sig_noise, NULL, NULL);
1154 copy_obs(ctl, &obs_err, obs, 1);
1155 for (
int ir = 0; ir < obs_err.nr; ir++)
1156 for (
int id = 0;
id < ctl->nd;
id++)
1158 = fabs(ret->
err_formod[
id] / 100 * obs->rad[
id][ir]);
1159 obs2y(ctl, &obs_err, sig_formod, NULL, NULL);
1162 for (
size_t i = 0; i < m; i++)
1163 gsl_vector_set(sig_eps_inv, i,
1164 1 / sqrt(gsl_pow_2(gsl_vector_get(sig_noise, i))
1165 + gsl_pow_2(gsl_vector_get(sig_formod, i))));
1168 for (
size_t i = 0; i < m; i++)
1169 if (gsl_vector_get(sig_eps_inv, i) <= 0)
1170 ERRMSG(
"Check measurement errors (zero standard deviation)!");
1179 int dimid[10], p_id, t_id, z_id;
1182 printf(
"Write netCDF file: %s\n", filename);
1185 NC(nc_inq_dimid(ncd->
ncid,
"L1_NTRACK", &dimid[0]));
1186 NC(nc_inq_dimid(ncd->
ncid,
"L1_NXTRACK", &dimid[1]));
1192 if (nc_inq_dimid(ncd->
ncid,
"RET_NP", &dimid[2]) != NC_NOERR)
1193 NC(nc_def_dim(ncd->
ncid,
"RET_NP", (
size_t) ncd->
np, &dimid[2]));
1196 add_var(ncd->
ncid,
"ret_z",
"km",
"altitude", NC_FLOAT, &dimid[2], &z_id,
1198 add_var(ncd->
ncid,
"ret_press",
"hPa",
"pressure", NC_FLOAT, dimid, &p_id,
1200 add_var(ncd->
ncid,
"ret_temp",
"K",
"temperature", NC_FLOAT, dimid, &t_id,
1204 NC(nc_enddef(ncd->
ncid));
1207 NC(nc_put_var_float(ncd->
ncid, z_id, ncd->
ret_z));
1208 NC(nc_put_var_float(ncd->
ncid, p_id, ncd->
ret_p));
1209 NC(nc_put_var_float(ncd->
ncid, t_id, ncd->
ret_t));
void matrix_product(gsl_matrix *a, gsl_vector *b, int transpose, gsl_matrix *c)
Compute matrix product A^TBA or ABA^T for diagonal matrix B.
int main(int argc, char *argv[])
#define NC(cmd)
Execute netCDF library command and check result.
void set_cov_apr(ret_t *ret, ctl_t *ctl, atm_t *atm, int *iqa, int *ipa, gsl_matrix *s_a)
Set a priori covariance.
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 write_nc(char *filename, ncd_t *ncd)
Write to netCDF file...
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).
void optimal_estimation(ret_t *ret, ctl_t *ctl, tbl_t *tbl, obs_t *obs_meas, obs_t *obs_i, atm_t *atm_apr, atm_t *atm_i, double *chisq)
Carry out optimal estimation retrieval.
void buffer_nc(atm_t *atm, double chisq, ncd_t *ncd, int track, int xtrack, int np0, int np1)
Buffer netCDF data.
void set_cov_meas(ret_t *ret, ctl_t *ctl, obs_t *obs, gsl_vector *sig_noise, gsl_vector *sig_formod, gsl_vector *sig_eps_inv)
Set measurement errors.
void read_ret_ctl(int argc, char *argv[], ctl_t *ctl, ret_t *ret)
Read retrieval control parameters.
void matrix_invert(gsl_matrix *a)
Invert symmetric matrix.
#define L1_NCHAN
Number of AIRS radiance channels (don't change).
#define L2_NTRACK
Along-track size of AIRS retrieval granule (don't change).
double cost_function(gsl_vector *dx, gsl_vector *dy, gsl_matrix *s_a_inv, gsl_vector *sig_eps_inv)
Compute cost function.
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].
float ret_p[L1_NTRACK *L1_NXTRACK]
Pressure [hPa].
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].
int np
Number of retrieval altitudes.
double l1_sat_lon[L1_NTRACK]
Satellite longitude [deg].
float ret_z[NP]
Altitude [km].
double l2_p[L2_NLAY]
Pressure [hPa].
float ret_t[L1_NTRACK *L1_NXTRACK *NP]
Temperature [K].
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).
double err_k_ch[NW]
Horizontal correlation length for extinction error [km].
double err_press_cz
Vertical correlation length for pressure error [km].
double err_k_cz[NW]
Vertical correlation length for extinction error [km].
double err_press
Pressure error [%].
double err_q_ch[NG]
Horizontal correlation length for volume mixing ratio error [km].
double err_noise[ND]
Noise error [W/(m^2 sr cm^-1)].
double err_formod[ND]
Forward model error [%].
double err_q_cz[NG]
Vertical correlation length for volume mixing ratio error [km].
double err_temp_cz
Vertical correlation length for temperature error [km].
double conv_dmin
Minimum normalized step size in state space.
double err_temp
Temperature error [K].
double err_temp_ch
Horizontal correlation length for temperature error [km].
int kernel_recomp
Recomputation of kernel matrix (number of iterations).
int conv_itmax
Maximum number of iterations.
double err_press_ch
Horizontal correlation length for pressure error [km].
double err_q[NG]
Volume mixing ratio error [%].
double err_k[NW]
Extinction error [1/km].