AIRS Code Collection
Data Structures | Macros | Functions
retrieval.c File Reference

Retrieval processor for AIRS. More...

#include <mpi.h>
#include <omp.h>
#include <netcdf.h>
#include "jurassic.h"

Go to the source code of this file.

Data Structures

struct  ncd_t
 Buffer for netCDF data. More...
 
struct  ret_t
 Retrieval results. More...
 

Macros

#define NC(cmd)
 Execute netCDF library command and check result. More...
 
#define L1_NCHAN   34
 Number of AIRS radiance channels (don't change). More...
 
#define L1_NTRACK   135
 Along-track size of AIRS radiance granule (don't change). More...
 
#define L1_NXTRACK   90
 Across-track size of AIRS radiance granule (don't change). More...
 
#define L2_NLAY   27
 Number of AIRS pressure layers (don't change). More...
 
#define L2_NTRACK   45
 Along-track size of AIRS retrieval granule (don't change). More...
 
#define L2_NXTRACK   30
 Across-track size of AIRS retrieval granule (don't change). More...
 

Functions

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. More...
 
void buffer_nc (atm_t *atm, double chisq, ncd_t *ncd, int track, int xtrack, int np0, int np1)
 Buffer netCDF data. More...
 
double cost_function (gsl_vector *dx, gsl_vector *dy, gsl_matrix *s_a_inv, gsl_vector *sig_eps_inv)
 Compute cost function. More...
 
void fill_gaps (double x[L2_NTRACK][L2_NXTRACK][L2_NLAY], double cx, double cy)
 Fill data gaps in L2 data. More...
 
void init_l2 (ncd_t *ncd, int track, int xtrack, ctl_t *ctl, atm_t *atm)
 Initialize with AIRS Level-2 data. More...
 
void matrix_invert (gsl_matrix *a)
 Invert symmetric matrix. More...
 
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. More...
 
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. More...
 
void read_nc (char *filename, ncd_t *ncd)
 Read netCDF file. More...
 
void read_ret_ctl (int argc, char *argv[], ctl_t *ctl, ret_t *ret)
 Read retrieval control parameters. More...
 
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. More...
 
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. More...
 
void write_nc (char *filename, ncd_t *ncd)
 Write to netCDF file... More...
 
int main (int argc, char *argv[])
 

Detailed Description

Retrieval processor for AIRS.

Definition in file retrieval.c.

Macro Definition Documentation

◆ NC

#define NC (   cmd)
Value:
{ \
int nc_result=(cmd); \
if(nc_result!=NC_NOERR) \
ERRMSG("%s", nc_strerror(nc_result)); \
}

Execute netCDF library command and check result.

Definition at line 36 of file retrieval.c.

◆ L1_NCHAN

#define L1_NCHAN   34

Number of AIRS radiance channels (don't change).

Definition at line 47 of file retrieval.c.

◆ L1_NTRACK

#define L1_NTRACK   135

Along-track size of AIRS radiance granule (don't change).

Definition at line 50 of file retrieval.c.

◆ L1_NXTRACK

#define L1_NXTRACK   90

Across-track size of AIRS radiance granule (don't change).

Definition at line 53 of file retrieval.c.

◆ L2_NLAY

#define L2_NLAY   27

Number of AIRS pressure layers (don't change).

Definition at line 56 of file retrieval.c.

◆ L2_NTRACK

#define L2_NTRACK   45

Along-track size of AIRS retrieval granule (don't change).

Definition at line 59 of file retrieval.c.

◆ L2_NXTRACK

#define L2_NXTRACK   30

Across-track size of AIRS retrieval granule (don't change).

Definition at line 62 of file retrieval.c.

Function Documentation

◆ add_var()

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.

Add variable to netCDF file.

Definition at line 507 of file retrieval.c.

515 {
516
517 /* Check if variable exists... */
518 if (nc_inq_varid(ncid, varname, varid) != NC_NOERR) {
519
520 /* Define variable... */
521 NC(nc_def_var(ncid, varname, type, ndims, dimid, varid));
522
523 /* Set long name... */
524 NC(nc_put_att_text
525 (ncid, *varid, "long_name", strlen(longname), longname));
526
527 /* Set units... */
528 NC(nc_put_att_text(ncid, *varid, "units", strlen(unit), unit));
529 }
530}
#define NC(cmd)
Execute netCDF library command and check result.
Definition: retrieval.c:36

◆ buffer_nc()

void buffer_nc ( atm_t *  atm,
double  chisq,
ncd_t ncd,
int  track,
int  xtrack,
int  np0,
int  np1 
)

Buffer netCDF data.

Definition at line 534 of file retrieval.c.

541 {
542
543 /* Set number of data points... */
544 ncd->np = np1 - np0 + 1;
545
546 /* Save retrieval data... */
547 for (int ip = np0; ip <= np1; ip++) {
548 ncd->ret_z[ip - np0] = (float) atm->z[ip];
549 ncd->ret_p[track * L1_NXTRACK + xtrack] = (float) atm->p[np0];
550 ncd->ret_t[(track * L1_NXTRACK + xtrack) * ncd->np + ip - np0] =
551 (gsl_finite(chisq) ? (float) atm->t[ip] : GSL_NAN);
552 }
553}
#define L1_NXTRACK
Across-track size of AIRS radiance granule (don't change).
Definition: retrieval.c:53
float ret_p[L1_NTRACK *L1_NXTRACK]
Pressure [hPa].
Definition: diff_apr.c:113
int np
Number of retrieval altitudes.
Definition: diff_apr.c:74
float ret_z[NP]
Altitude [km].
Definition: diff_apr.c:110
float ret_t[L1_NTRACK *L1_NXTRACK *NP]
Temperature [K].
Definition: diff_apr.c:116

◆ cost_function()

double cost_function ( gsl_vector *  dx,
gsl_vector *  dy,
gsl_matrix *  s_a_inv,
gsl_vector *  sig_eps_inv 
)

Compute cost function.

Definition at line 557 of file retrieval.c.

561 {
562
563 double chisq_a, chisq_m = 0;
564
565 /* Get sizes... */
566 const size_t m = dy->size;
567 const size_t n = dx->size;
568
569 /* Allocate... */
570 gsl_vector *x_aux = gsl_vector_alloc(n);
571 gsl_vector *y_aux = gsl_vector_alloc(m);
572
573 /* Determine normalized cost function...
574 (chi^2 = 1/m * [dy^T * S_eps^{-1} * dy + dx^T * S_a^{-1} * dx]) */
575 for (size_t i = 0; i < m; i++)
576 chisq_m +=
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);
580
581 /* Free... */
582 gsl_vector_free(x_aux);
583 gsl_vector_free(y_aux);
584
585 /* Return cost function value... */
586 return (chisq_m + chisq_a) / (double) m;
587}

◆ fill_gaps()

void fill_gaps ( double  x[L2_NTRACK][L2_NXTRACK][L2_NLAY],
double  cx,
double  cy 
)

Fill data gaps in L2 data.

Definition at line 591 of file retrieval.c.

594 {
595
596 double help[L2_NTRACK][L2_NXTRACK];
597
598 /* Loop over layers... */
599 for (int lay = 0; lay < L2_NLAY; lay++) {
600
601 /* Loop over grid points... */
602 for (int track = 0; track < L2_NTRACK; track++)
603 for (int xtrack = 0; xtrack < L2_NXTRACK; xtrack++) {
604
605 /* Init... */
606 help[track][xtrack] = 0;
607 double wsum = 0;
608
609 /* Averrage data points... */
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];
617 wsum += w;
618 }
619
620 /* Normalize... */
621 if (wsum > 0)
622 help[track][xtrack] /= wsum;
623 else
624 help[track][xtrack] = GSL_NAN;
625 }
626
627 /* Copy grid points... */
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];
631 }
632}
#define L2_NXTRACK
Across-track size of AIRS retrieval granule (don't change).
Definition: retrieval.c:62
#define L2_NLAY
Number of AIRS pressure layers (don't change).
Definition: retrieval.c:56
#define L2_NTRACK
Along-track size of AIRS retrieval granule (don't change).
Definition: retrieval.c:59

◆ init_l2()

void init_l2 ( ncd_t ncd,
int  track,
int  xtrack,
ctl_t *  ctl,
atm_t *  atm 
)

Initialize with AIRS Level-2 data.

Definition at line 636 of file retrieval.c.

641 {
642
643 static atm_t atm_airs;
644
645 double k[NW], p, q[NG], t, zmax = 0, zmin = 1000;
646
647 /* Reset track- and xtrack-index to match Level-2 data... */
648 track /= 3;
649 xtrack /= 3;
650
651 /* Store AIRS data in atmospheric data struct... */
652 atm_airs.np = 0;
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!");
660 }
661
662 /* Check number of levels... */
663 if (atm_airs.np <= 0)
664 return;
665
666 /* Get height range of AIRS data... */
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]);
670 }
671
672 /* Merge AIRS data... */
673 for (int ip = 0; ip < atm->np; ip++) {
674
675 /* Interpolate AIRS data... */
676 intpol_atm(ctl, &atm_airs, atm->z[ip], &p, &t, q, k);
677
678 /* Weighting factor... */
679 double w = 1;
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);
684
685 /* Merge... */
686 atm->t[ip] = w * t + (1 - w) * atm->t[ip];
687 atm->p[ip] = w * p + (1 - w) * atm->p[ip];
688 }
689}
double l2_z[L2_NTRACK][L2_NXTRACK][L2_NLAY]
Altitude [km].
Definition: diff_apr.c:101
double l2_p[L2_NLAY]
Pressure [hPa].
Definition: diff_apr.c:104
double l2_t[L2_NTRACK][L2_NXTRACK][L2_NLAY]
Temperature [K].
Definition: diff_apr.c:107

◆ matrix_invert()

void matrix_invert ( gsl_matrix *  a)

Invert symmetric matrix.

Definition at line 693 of file retrieval.c.

694 {
695
696 size_t diag = 1;
697
698 /* Get size... */
699 const size_t n = a->size1;
700
701 /* Check if matrix is diagonal... */
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) {
705 diag = 0;
706 break;
707 }
708
709 /* Quick inversion of diagonal matrix... */
710 if (diag)
711 for (size_t i = 0; i < n; i++)
712 gsl_matrix_set(a, i, i, 1 / gsl_matrix_get(a, i, i));
713
714 /* Matrix inversion by means of Cholesky decomposition... */
715 else {
716 gsl_linalg_cholesky_decomp(a);
717 gsl_linalg_cholesky_invert(a);
718 }
719}

◆ matrix_product()

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.

Definition at line 723 of file retrieval.c.

727 {
728
729 /* Set sizes... */
730 const size_t m = a->size1;
731 const size_t n = a->size2;
732
733 /* Allocate... */
734 gsl_matrix *aux = gsl_matrix_alloc(m, n);
735
736 /* Compute A^T B A... */
737 if (transpose == 1) {
738
739 /* Compute B^1/2 A... */
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));
744
745 /* Compute A^T B A = (B^1/2 A)^T (B^1/2 A)... */
746 gsl_blas_dgemm(CblasTrans, CblasNoTrans, 1.0, aux, aux, 0.0, c);
747 }
748
749 /* Compute A B A^T... */
750 else if (transpose == 2) {
751
752 /* Compute A B^1/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));
757
758 /* Compute A B A^T = (A B^1/2) (A B^1/2)^T... */
759 gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1.0, aux, aux, 0.0, c);
760 }
761
762 /* Free... */
763 gsl_matrix_free(aux);
764}

◆ optimal_estimation()

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.

Definition at line 768 of file retrieval.c.

776 {
777
778 static int ipa[N], iqa[N];
779
780 double disq = 0, lmpar = 0.001;
781
782 /* ------------------------------------------------------------
783 Initialize...
784 ------------------------------------------------------------ */
785
786 /* Get sizes... */
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) {
790 *chisq = GSL_NAN;
791 return;
792 }
793
794 /* Allocate... */
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);
799
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);
812
813 /* Set initial state... */
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);
817
818 /* Set state vectors and observation vectors... */
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);
823
824 /* Set inverse a priori covariance S_a^-1... */
825 set_cov_apr(ret, ctl, atm_apr, iqa, ipa, s_a_inv);
826 matrix_invert(s_a_inv);
827
828 /* Get measurement errors... */
829 set_cov_meas(ret, ctl, obs_meas, sig_noise, sig_formod, sig_eps_inv);
830
831 /* Determine dx = x_i - x_a and dy = y - F(x_i) ... */
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);
836
837 /* Compute cost function... */
838 *chisq = cost_function(dx, dy, s_a_inv, sig_eps_inv);
839
840 /* Compute initial kernel... */
841 kernel(ctl, tbl, atm_i, obs_i, k_i);
842
843 /* ------------------------------------------------------------
844 Levenberg-Marquardt minimization...
845 ------------------------------------------------------------ */
846
847 /* Outer loop... */
848 for (int it = 1; it <= ret->conv_itmax; it++) {
849
850 /* Store current cost function value... */
851 double chisq_old = *chisq;
852
853 /* Compute kernel matrix K_i... */
854 if (it > 1 && it % ret->kernel_recomp == 0)
855 kernel(ctl, tbl, atm_i, obs_i, k_i);
856
857 /* Compute K_i^T * S_eps^{-1} * K_i ... */
858 if (it == 1 || it % ret->kernel_recomp == 0)
859 matrix_product(k_i, sig_eps_inv, 1, cov);
860
861 /* Determine b = K_i^T * S_eps^{-1} * dy - S_a^{-1} * dx ... */
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);
867
868 /* Inner loop... */
869 for (int it2 = 0; it2 < 20; it2++) {
870
871 /* Compute A = (1 + lmpar) * S_a^{-1} + K_i^T * S_eps^{-1} * K_i ... */
872 gsl_matrix_memcpy(a, s_a_inv);
873 gsl_matrix_scale(a, 1 + lmpar);
874 gsl_matrix_add(a, cov);
875
876 /* Solve A * x_step = b by means of Cholesky decomposition... */
877 gsl_linalg_cholesky_decomp(a);
878 gsl_linalg_cholesky_solve(a, b, x_step);
879
880 /* Update atmospheric state... */
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);
885
886 /* Check atmospheric state... */
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);
894 }
895
896 /* Forward calculation... */
897 formod(ctl, tbl, atm_i, obs_i);
898 obs2y(ctl, obs_i, y_i, NULL, NULL);
899
900 /* Determine dx = x_i - x_a and dy = y - F(x_i) ... */
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);
905
906 /* Compute cost function... */
907 *chisq = cost_function(dx, dy, s_a_inv, sig_eps_inv);
908
909 /* Modify Levenberg-Marquardt parameter... */
910 if (*chisq > chisq_old) {
911 lmpar *= 10;
912 gsl_vector_sub(x_i, x_step);
913 } else {
914 lmpar /= 10;
915 break;
916 }
917 }
918
919 /* Get normalized step size in state space... */
920 gsl_blas_ddot(x_step, b, &disq);
921 disq /= (double) n;
922
923 /* Convergence test... */
924 if ((it == 1 || it % ret->kernel_recomp == 0) && disq < ret->conv_dmin)
925 break;
926 }
927
928 /* ------------------------------------------------------------
929 Finalize...
930 ------------------------------------------------------------ */
931
932 gsl_matrix_free(a);
933 gsl_matrix_free(cov);
934 gsl_matrix_free(k_i);
935 gsl_matrix_free(s_a_inv);
936
937 gsl_vector_free(b);
938 gsl_vector_free(dx);
939 gsl_vector_free(dy);
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);
949}
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.
Definition: retrieval.c:723
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.
Definition: retrieval.c:1033
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.
Definition: retrieval.c:1132
void matrix_invert(gsl_matrix *a)
Invert symmetric matrix.
Definition: retrieval.c:693
double cost_function(gsl_vector *dx, gsl_vector *dy, gsl_matrix *s_a_inv, gsl_vector *sig_eps_inv)
Compute cost function.
Definition: retrieval.c:557
double conv_dmin
Minimum normalized step size in state space.
Definition: nlte.c:131
int kernel_recomp
Recomputation of kernel matrix (number of iterations).
Definition: nlte.c:125
int conv_itmax
Maximum number of iterations.
Definition: nlte.c:128
Here is the call graph for this function:

◆ read_nc()

void read_nc ( char *  filename,
ncd_t ncd 
)

Read netCDF file.

Definition at line 953 of file retrieval.c.

955 {
956
957 int varid;
958
959 /* Open netCDF file... */
960 printf("Read netCDF file: %s\n", filename);
961 NC(nc_open(filename, NC_WRITE, &ncd->ncid));
962
963 /* Read Level-1 data... */
964 NC(nc_inq_varid(ncd->ncid, "l1_time", &varid));
965 NC(nc_get_var_double(ncd->ncid, varid, ncd->l1_time[0]));
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));
971 NC(nc_get_var_double(ncd->ncid, varid, ncd->l1_sat_z));
972 NC(nc_inq_varid(ncd->ncid, "l1_sat_lon", &varid));
973 NC(nc_get_var_double(ncd->ncid, varid, ncd->l1_sat_lon));
974 NC(nc_inq_varid(ncd->ncid, "l1_sat_lat", &varid));
975 NC(nc_get_var_double(ncd->ncid, varid, ncd->l1_sat_lat));
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]));
980
981 /* Read Level-2 data... */
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]));
988}
double l1_lat[L1_NTRACK][L1_NXTRACK]
Footprint latitude [deg].
Definition: diff_apr.c:83
double l1_lon[L1_NTRACK][L1_NXTRACK]
Footprint longitude [deg].
Definition: diff_apr.c:80
double l1_sat_lat[L1_NTRACK]
Satellite latitude [deg].
Definition: diff_apr.c:92
int ncid
NetCDF file ID.
Definition: diff_apr.c:71
double l1_sat_lon[L1_NTRACK]
Satellite longitude [deg].
Definition: diff_apr.c:89
double l1_nu[L1_NCHAN]
Channel frequencies [cm^-1].
Definition: diff_apr.c:95
double l1_sat_z[L1_NTRACK]
Satellite altitude [km].
Definition: diff_apr.c:86
float l1_rad[L1_NTRACK][L1_NXTRACK][L1_NCHAN]
Radiance [W/(m^2 sr cm^-1)].
Definition: diff_apr.c:98
double l1_time[L1_NTRACK][L1_NXTRACK]
Time (seconds since 2000-01-01T00:00Z).
Definition: diff_apr.c:77

◆ read_ret_ctl()

void read_ret_ctl ( int  argc,
char *  argv[],
ctl_t *  ctl,
ret_t ret 
)

Read retrieval control parameters.

Definition at line 992 of file retrieval.c.

996 {
997
998 /* Iteration control... */
999 ret->kernel_recomp =
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);
1003
1004 for (int id = 0; id < ctl->nd; id++)
1005 ret->err_formod[id] = scan_ctl(argc, argv, "ERR_FORMOD", id, "0", NULL);
1006
1007 for (int id = 0; id < ctl->nd; id++)
1008 ret->err_noise[id] = scan_ctl(argc, argv, "ERR_NOISE", id, "0", NULL);
1009
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);
1013
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);
1017
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);
1022 }
1023
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);
1028 }
1029}
double err_k_ch[NW]
Horizontal correlation length for extinction error [km].
Definition: nlte.c:173
double err_press_cz
Vertical correlation length for pressure error [km].
Definition: nlte.c:143
double err_k_cz[NW]
Vertical correlation length for extinction error [km].
Definition: nlte.c:170
double err_press
Pressure error [%].
Definition: nlte.c:140
double err_q_ch[NG]
Horizontal correlation length for volume mixing ratio error [km].
Definition: nlte.c:164
double err_noise[ND]
Noise error [W/(m^2 sr cm^-1)].
Definition: nlte.c:137
double err_formod[ND]
Forward model error [%].
Definition: nlte.c:134
double err_q_cz[NG]
Vertical correlation length for volume mixing ratio error [km].
Definition: nlte.c:161
double err_temp_cz
Vertical correlation length for temperature error [km].
Definition: nlte.c:152
double err_temp
Temperature error [K].
Definition: nlte.c:149
double err_temp_ch
Horizontal correlation length for temperature error [km].
Definition: nlte.c:155
double err_press_ch
Horizontal correlation length for pressure error [km].
Definition: nlte.c:146
double err_q[NG]
Volume mixing ratio error [%].
Definition: nlte.c:158
double err_k[NW]
Extinction error [1/km].
Definition: nlte.c:167

◆ set_cov_apr()

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.

Definition at line 1033 of file retrieval.c.

1039 {
1040
1041 /* Get sizes... */
1042 const size_t n = s_a->size1;
1043
1044 /* Allocate... */
1045 gsl_vector *x_a = gsl_vector_alloc(n);
1046
1047 /* Get sigma vector... */
1048 atm2x(ctl, atm, x_a, NULL, NULL);
1049 for (size_t i = 0; i < n; i++) {
1050 if (iqa[i] == IDXP)
1051 gsl_vector_set(x_a, i, ret->err_press / 100 * gsl_vector_get(x_a, i));
1052 if (iqa[i] == IDXT)
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]);
1060 }
1061
1062 /* Check standard deviations... */
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)!");
1066
1067 /* Initialize diagonal covariance... */
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)));
1071
1072 /* Loop over matrix elements... */
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]) {
1076
1077 /* Initialize... */
1078 double cz = 0;
1079 double ch = 0;
1080
1081 /* Set correlation lengths for pressure... */
1082 if (iqa[i] == IDXP) {
1083 cz = ret->err_press_cz;
1084 ch = ret->err_press_ch;
1085 }
1086
1087 /* Set correlation lengths for temperature... */
1088 if (iqa[i] == IDXT) {
1089 cz = ret->err_temp_cz;
1090 ch = ret->err_temp_ch;
1091 }
1092
1093 /* Set correlation lengths for volume mixing ratios... */
1094 for (int ig = 0; ig < ctl->ng; ig++)
1095 if (iqa[i] == IDXQ(ig)) {
1096 cz = ret->err_q_cz[ig];
1097 ch = ret->err_q_ch[ig];
1098 }
1099
1100 /* Set correlation lengths for extinction... */
1101 for (int iw = 0; iw < ctl->nw; iw++)
1102 if (iqa[i] == IDXK(iw)) {
1103 cz = ret->err_k_cz[iw];
1104 ch = ret->err_k_ch[iw];
1105 }
1106
1107 /* Compute correlations... */
1108 if (cz > 0 && ch > 0) {
1109
1110 /* Get Cartesian coordinates... */
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);
1114
1115 /* Compute correlations... */
1116 const double rho =
1117 exp(-DIST(x0, x1) / ch -
1118 fabs(atm->z[ipa[i]] - atm->z[ipa[j]]) / cz);
1119
1120 /* Set covariance... */
1121 gsl_matrix_set(s_a, i, j, gsl_vector_get(x_a, i)
1122 * gsl_vector_get(x_a, j) * rho);
1123 }
1124 }
1125
1126 /* Free... */
1127 gsl_vector_free(x_a);
1128}

◆ set_cov_meas()

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.

Definition at line 1132 of file retrieval.c.

1138 {
1139
1140 static obs_t obs_err;
1141
1142 /* Get size... */
1143 const size_t m = sig_eps_inv->size;
1144
1145 /* Noise error (always considered in retrieval fit)... */
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++)
1149 obs_err.rad[id][ir]
1150 = (gsl_finite(obs->rad[id][ir]) ? ret->err_noise[id] : GSL_NAN);
1151 obs2y(ctl, &obs_err, sig_noise, NULL, NULL);
1152
1153 /* Forward model error (always considered in retrieval fit)... */
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++)
1157 obs_err.rad[id][ir]
1158 = fabs(ret->err_formod[id] / 100 * obs->rad[id][ir]);
1159 obs2y(ctl, &obs_err, sig_formod, NULL, NULL);
1160
1161 /* Total error... */
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))));
1166
1167 /* Check standard deviations... */
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)!");
1171}

◆ write_nc()

void write_nc ( char *  filename,
ncd_t ncd 
)

Write to netCDF file...

Definition at line 1175 of file retrieval.c.

1177 {
1178
1179 int dimid[10], p_id, t_id, z_id;
1180
1181 /* Create netCDF file... */
1182 printf("Write netCDF file: %s\n", filename);
1183
1184 /* Read existing dimensions... */
1185 NC(nc_inq_dimid(ncd->ncid, "L1_NTRACK", &dimid[0]));
1186 NC(nc_inq_dimid(ncd->ncid, "L1_NXTRACK", &dimid[1]));
1187
1188 /* Set define mode... */
1189 NC(nc_redef(ncd->ncid));
1190
1191 /* Set new dimensions... */
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]));
1194
1195 /* Set new variables... */
1196 add_var(ncd->ncid, "ret_z", "km", "altitude", NC_FLOAT, &dimid[2], &z_id,
1197 1);
1198 add_var(ncd->ncid, "ret_press", "hPa", "pressure", NC_FLOAT, dimid, &p_id,
1199 2);
1200 add_var(ncd->ncid, "ret_temp", "K", "temperature", NC_FLOAT, dimid, &t_id,
1201 3);
1202
1203 /* Leave define mode... */
1204 NC(nc_enddef(ncd->ncid));
1205
1206 /* Write data... */
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));
1210
1211 /* Close netCDF file... */
1212 NC(nc_close(ncd->ncid));
1213}
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.
Definition: retrieval.c:507
Here is the call graph for this function:

◆ main()

int main ( int  argc,
char *  argv[] 
)

Definition at line 284 of file retrieval.c.

286 {
287
288 static ctl_t ctl;
289 static atm_t atm_apr, atm_clim, atm_i;
290 static obs_t obs_i, obs_meas;
291 static ncd_t ncd;
292 static ret_t ret;
293
294 FILE *in;
295
296 char filename[LEN];
297
298 double chisq, chisq_min, chisq_max, chisq_mean, z[NP];
299
300 int channel[ND], m, ntask = -1, rank, size;
301
302 /* ------------------------------------------------------------
303 Init...
304 ------------------------------------------------------------ */
305
306 /* MPI... */
307 MPI_Init(&argc, &argv);
308 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
309 MPI_Comm_size(MPI_COMM_WORLD, &size);
310
311 /* Measure CPU time... */
312 TIMER("total", 1);
313
314 /* Check arguments... */
315 if (argc < 3)
316 ERRMSG("Give parameters: <ctl> <filelist>");
317
318 /* Read control parameters... */
319 read_ctl(argc, argv, &ctl);
320 read_ret_ctl(argc, argv, &ctl, &ret);
321
322 /* Initialize look-up tables... */
323 tbl_t *tbl = read_tbl(&ctl);
324
325 /* Read retrieval grid... */
326 const int nz = (int) scan_ctl(argc, argv, "NZ", -1, "", NULL);
327 if (nz > NP)
328 ERRMSG("Too many altitudes!");
329 for (int iz = 0; iz < nz; iz++)
330 z[iz] = scan_ctl(argc, argv, "Z", iz, "", NULL);
331
332 /* Read track range... */
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);
335
336 /* Read xtrack range... */
337 const int xtrack0 = (int) scan_ctl(argc, argv, "XTRACK_MIN", -1, "0", NULL);
338 const int xtrack1 =
339 (int) scan_ctl(argc, argv, "XTRACK_MAX", -1, "89", NULL);
340
341 /* Read height range... */
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);
345
346 /* Background smoothing... */
347 const double sx = scan_ctl(argc, argv, "SX", -1, "8", NULL);
348 const double sy = scan_ctl(argc, argv, "SY", -1, "2", NULL);
349
350 /* SZA threshold... */
351 const double sza_thresh = scan_ctl(argc, argv, "SZA", -1, "96", NULL);
352
353 /* ------------------------------------------------------------
354 Distribute granules...
355 ------------------------------------------------------------ */
356
357 /* Open filelist... */
358 printf("Read filelist: %s\n", argv[2]);
359 if (!(in = fopen(argv[2], "r")))
360 ERRMSG("Cannot open filelist!");
361
362 /* Loop over netCDF files... */
363 while (fscanf(in, "%s", filename) != EOF) {
364
365 /* Distribute files with MPI... */
366 if ((++ntask) % size != rank)
367 continue;
368
369 /* Write info... */
370 printf("Retrieve file %s on rank %d of %d (with %d threads)...\n",
371 filename, rank + 1, size, omp_get_max_threads());
372
373 /* ------------------------------------------------------------
374 Initialize retrieval...
375 ------------------------------------------------------------ */
376
377 /* Read netCDF file... */
378 read_nc(filename, &ncd);
379
380 /* Identify radiance channels... */
381 for (int id = 0; id < ctl.nd; id++) {
382 channel[id] = -999;
383 for (int i = 0; i < L1_NCHAN; i++)
384 if (fabs(ctl.nu[id] - ncd.l1_nu[i]) < 0.1)
385 channel[id] = i;
386 if (channel[id] < 0)
387 ERRMSG("Cannot identify radiance channel!");
388 }
389
390 /* Fill data gaps... */
391 fill_gaps(ncd.l2_t, sx, sy);
392 fill_gaps(ncd.l2_z, sx, sy);
393
394 /* Set climatological data for center of granule... */
395 atm_clim.np = nz;
396 for (int iz = 0; iz < nz; iz++)
397 atm_clim.z[iz] = z[iz];
398 climatology(&ctl, &atm_clim);
399
400 /* ------------------------------------------------------------
401 Retrieval...
402 ------------------------------------------------------------ */
403
404 /* Get chi^2 statistics... */
405 chisq_min = 1e100;
406 chisq_max = -1e100;
407 chisq_mean = 0;
408 m = 0;
409
410 /* Loop over swaths... */
411 for (int track = track0; track <= track1; track++) {
412
413 /* Measure CPU time... */
414 TIMER("retrieval", 1);
415
416 /* Loop over scan... */
417 for (int xtrack = xtrack0; xtrack <= xtrack1; xtrack++) {
418
419 /* Store observation data... */
420 obs_meas.nr = 1;
421 obs_meas.time[0] = ncd.l1_time[track][xtrack];
422 obs_meas.obsz[0] = ncd.l1_sat_z[track];
423 obs_meas.obslon[0] = ncd.l1_sat_lon[track];
424 obs_meas.obslat[0] = ncd.l1_sat_lat[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]];
429
430 /* Flag out 4 micron channels for daytime measurements... */
431 if (sza(obs_meas.time[0], obs_meas.obslon[0], obs_meas.obslat[0])
432 < sza_thresh)
433 for (int id = 0; id < ctl.nd; id++)
434 if (ctl.nu[id] >= 2000)
435 obs_meas.rad[id][0] = GSL_NAN;
436
437 /* Prepare atmospheric data... */
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];
443 }
444
445 /* Merge Level-2 data... */
446 init_l2(&ncd, track, xtrack, &ctl, &atm_apr);
447
448 /* Retrieval... */
449 optimal_estimation(&ret, &ctl, tbl, &obs_meas, &obs_i,
450 &atm_apr, &atm_i, &chisq);
451
452 /* Get chi^2 statistics... */
453 if (gsl_finite(chisq)) {
454 chisq_min = GSL_MIN(chisq_min, chisq);
455 chisq_max = GSL_MAX(chisq_max, chisq);
456 chisq_mean += chisq;
457 m++;
458 }
459
460 /* Buffer results... */
461 buffer_nc(&atm_i, chisq, &ncd, track, xtrack, np0, np1);
462 }
463
464 /* Measure CPU time... */
465 TIMER("retrieval", 3);
466 }
467
468 /* ------------------------------------------------------------
469 Finalize...
470 ------------------------------------------------------------ */
471
472 /* Write netCDF file... */
473 write_nc(filename, &ncd);
474
475 /* Write info... */
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);
479 }
480
481 /* Close file list... */
482 fclose(in);
483
484 /* Measure CPU time... */
485 TIMER("total", 3);
486
487 /* Report memory usage... */
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.);
494
495 /* Report problem size... */
496 printf("SIZE_TASKS = %d\n", size);
497 printf("SIZE_THREADS = %d\n", omp_get_max_threads());
498
499 /* MPI... */
500 MPI_Finalize();
501
502 return EXIT_SUCCESS;
503}
void fill_gaps(double x[L2_NTRACK][L2_NXTRACK][L2_NLAY], double cx, double cy)
Fill data gaps in L2 data.
Definition: retrieval.c:591
void write_nc(char *filename, ncd_t *ncd)
Write to netCDF file...
Definition: retrieval.c:1175
void read_nc(char *filename, ncd_t *ncd)
Read netCDF file.
Definition: retrieval.c:953
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.
Definition: retrieval.c:768
void buffer_nc(atm_t *atm, double chisq, ncd_t *ncd, int track, int xtrack, int np0, int np1)
Buffer netCDF data.
Definition: retrieval.c:534
void read_ret_ctl(int argc, char *argv[], ctl_t *ctl, ret_t *ret)
Read retrieval control parameters.
Definition: retrieval.c:992
#define L1_NCHAN
Number of AIRS radiance channels (don't change).
Definition: retrieval.c:47
void init_l2(ncd_t *ncd, int track, int xtrack, ctl_t *ctl, atm_t *atm)
Initialize with AIRS Level-2 data.
Definition: retrieval.c:636
Buffer for netCDF data.
Definition: diff_apr.c:68
Retrieval results.
Definition: libairs.h:237
Here is the call graph for this function: