44                {
   45 
   47 
   48  static atm_t atm, atm2;
 
   49 
   51 
   52  static FILE *in, *out;
   53 
   54  static char line[
LEN];
 
   55 
   57    obs_sim, scl = 1.0, scl_err, c0, c1, cov00, cov01, cov11, sumsq,
   60 
   63 
   64  static int i, ig, n, nl, ndata[
NMAX], nprof;
 
   65 
   66  
   67  if (argc < 6)
   68    ERRMSG(
"Give parameters: <ctl> <prof> <inv> <atm> <kernel>");
 
   69 
   70  
   72  const double dt = 
scan_ctl(argc, argv, 
"INVERT_DT", -1, 
"86400", NULL);
 
   73  const double obs_err =
   74    scan_ctl(argc, argv, 
"INVERT_OBS_ERR", -1, 
"1.0", NULL);
 
   75  const int data = (int) 
scan_ctl(argc, argv, 
"INVERT_DATA", -1, 
"2", NULL);
 
   76  const int fit = (int) 
scan_ctl(argc, argv, 
"INVERT_FIT", -1, 
"3", NULL);
 
   77  const int itmax =
   78    (int) 
scan_ctl(argc, argv, 
"INVERT_ITMAX", -1, 
"10", NULL);
 
   79  const double tol = 
scan_ctl(argc, argv, 
"INVERT_TOL", -1, 
"1e-4", NULL);
 
   80 
   81  
   84  if (strcmp(ctl.
emitter[0], 
"SO2") != 0)
 
   85    ERRMSG(
"Set EMITTER[0] = SO2!");
 
   86  if (strcmp(ctl.
emitter[1], 
"H2O") != 0)
 
   87    ERRMSG(
"Set EMITTER[1] = H2O!");
 
   88  if (strcmp(ctl.
emitter[2], 
"O3") != 0)
 
   89    ERRMSG(
"Set EMITTER[2] = O3!");
 
   90  if (strcmp(ctl.
emitter[3], 
"CO2") != 0)
 
   91    ERRMSG(
"Set EMITTER[3] = CO2!");
 
   94 
   95  
   98 
   99  
  102 
  103  
  105 
  106  
  107
  108
  109 
  110  
  111  LOG(1, 
"Read profile data: %s", argv[2]);
 
  112 
  113  
  114  if (!(in = fopen(argv[2], "r")))
  115    ERRMSG(
"Cannot open file!");
 
  116 
  117  
  118  while (fgets(line, 
LEN, in)) {
 
  119 
  120    
  121    if (sscanf(line, "%lg %lg %lg %lg %g %g %g %g %g %g", &rtime[nl],
  122               &rz[nl], &rlon[nl], &rlat[nl], &rp[nl], &rt[nl], &rso2[nl],
  123               &rh2o[nl], &ro3[nl], &robs[nl]) != 10)
  124      continue;
  126      ERRMSG(
"Too many profile data points!");
 
  127  }
  128 
  129  
  130  fclose(in);
  131 
  132  
  133
  134
  135 
  136  
  137  for (int it = 0; it < itmax; it++) {
  138 
  139    
  141    for (i = 0; i < 
NMAX; i++) {
 
  142      ndata[i] = 0;
  143      x[i] = y[i] = NAN;
  144    }
  145 
  146    
  147    for (int il = 0; il < nl; il++) {
  148 
  149      
  150      if ((rtime[il] != atm.
time[0]
 
  151           || rlon[il] != atm.
lon[0]
 
  152           || rlat[il] != atm.
lat[0])
 
  154 
  155        
  156        formod(&ctl, tbl, &atm, &obs);
 
  157        obs_sim = obs.
rad[0][0] - obs.
rad[1][0];
 
  158 
  159        
  160        i = (int) ((atm.
time[0] - rtime[0]) / dt);
 
  161        if (i < 0 && i >= 
NMAX)
 
  162          ERRMSG(
"Time index out of range!");
 
  163 
  164        
  165        if (data == 1) {
  166          x[i] = (isfinite(x[i]) ? 
MAX(x[i], obs_sim) : obs_sim);
 
  167          y[i] = (isfinite(y[i]) ? 
MAX(y[i], obs_meas) : obs_meas);
 
  168          y_err[i] = obs_err;
  169          if (isfinite(x[i]) && isfinite(y[i]))
  170            ndata[i] = 1;
  171        }
  172 
  173        
  174        else if (data == 2) {
  175          if (ndata[i] == 0) {
  176            x[i] = obs_sim;
  177            y[i] = obs_meas;
  178            y_err[i] = 
POW2(obs_meas);
 
  179          } else {
  180            x[i] += obs_sim;
  181            y[i] += obs_meas;
  182            y_err[i] += 
POW2(obs_meas);
 
  183          }
  184          ndata[i]++;
  185        }
  186 
  187        
  188        nprof++;
  190        for (
int ip = 0; ip < atm.
np; ip++) {
 
  192          atm2.
z[ip] += atm.
z[ip];
 
  193          atm2.
lon[ip] += atm.
lon[ip];
 
  194          atm2.
lat[ip] += atm.
lat[ip];
 
  195          atm2.
p[ip] += atm.
p[ip];
 
  196          atm2.
t[ip] += atm.
t[ip];
 
  197          for (ig = 1; ig < ctl.
ng; ig++)
 
  198            atm2.
q[ig][ip] += atm.
q[ig][ip];
 
  199        }
  200 
  201        
  203      }
  204 
  205      
  206      obs_meas = robs[il];
  207      atm.
time[atm.
np] = rtime[il];
 
  208      atm.
z[atm.
np] = rz[il];
 
  209      atm.
lon[atm.
np] = rlon[il];
 
  210      atm.
lat[atm.
np] = rlat[il];
 
  211      atm.
p[atm.
np] = rp[il];
 
  212      atm.
t[atm.
np] = rt[il];
 
  213      atm.
q[0][atm.
np] = rso2[il] * scl;
 
  214      atm.
q[1][atm.
np] = rh2o[il];
 
  215      atm.
q[2][atm.
np] = ro3[il];
 
  216      atm.
q[3][atm.
np] = 371.789948e-6 + 2.026214e-6
 
  217        * (atm.
time[atm.
np] - 63158400.) / 31557600.;
 
  219        ERRMSG(
"Too many data points!");
 
  220    }
  221 
  222    
  223    if (data == 2)
  224      for (i = 0; i < 
NMAX; i++)
 
  225        if (ndata[i] > 0) {
  226          x[i] /= ndata[i];
  227          y[i] /= ndata[i];
  228          y_err[i] = sqrt(
MAX(y_err[i] / ndata[i] - 
POW2(y[i]), 0.0))
 
  229            / sqrt(ndata[i]);   
  230        }
  231 
  232    
  233    n = 0;
  234    for (i = 0; i < 
NMAX; i++)
 
  235      if (ndata[i] > 0 && isfinite(x[i]) && isfinite(y[i])
  236          && isfinite(y_err[i])) {
  237        x2[n] = x[i];
  238        y2[n] = y[i];
  239        y2_err[n] = y_err[i];
  240        w2[n] = 1. / 
POW2(y_err[i]);
 
  241        n++;
  242      }
  243 
  244    
  245    if (fit == 1)
  246      gsl_fit_mul(x2, 1, y2, 1, (size_t) n, &c1, &cov11, &sumsq);
  247    else if (fit == 2)
  248      gsl_fit_wmul(x2, 1, w2, 1, y2, 1, (size_t) n, &c1, &cov11, &sumsq);
  249    else if (fit == 3)
  250      gsl_fit_linear(x2, 1, y2, 1, (size_t) n, &c0, &c1, &cov00, &cov01,
  251                     &cov11, &sumsq);
  252    else if (fit == 4)
  253      gsl_fit_wlinear(x2, 1, w2, 1, y2, 1, (size_t) n, &c0, &c1, &cov00,
  254                      &cov01, &cov11, &sumsq);
  255    else
  256      ERRMSG(
"Check INVERT_FIT!");
 
  257 
  258    
  259    double scl_old = scl;
  260    scl_err = scl * sqrt(cov11);
  261    scl *= c1;
  262 
  263    
  264    LOG(1, 
"  it= %d | scl= %g +/- %g | RMSE= %g",
 
  265        it, scl, scl_err, sqrt(sumsq / n));
  266 
  267    
  268    if (fabs(2.0 * (scl - scl_old) / (scl + scl_old)) < tol)
  269      break;
  270  }
  271 
  272  
  273
  274
  275 
  276  
  277  LOG(1, 
"Write inversion data: %s", argv[3]);
 
  278 
  279  
  280  if (!(out = fopen(argv[3], "w")))
  281    ERRMSG(
"Cannot create file!");
 
  282 
  283  
  284  fprintf(out,
  285          "# $1 = time (seconds since 2000-01-01T00:00Z)\n"
  286          "# $2 = simulated SO2 index [K]\n"
  287          "# $3 = scaled simulated SO2 index [K]\n"
  288          "# $4 = error of scaled simulated SO2 index [K]\n"
  289          "# $5 = observed SO2 index [K]\n"
  290          "# $6 = error of observed SO2 index [K]\n\n");
  291 
  292  
  293  for (i = 0; i < n; i++) {
  294 
  295    
  296    if (fit == 1 || fit == 2)
  297      gsl_fit_mul_est(x2[i], c1, cov11, &y2_sim[i], &y2_sim_err[i]);
  298    else if (fit == 3 || fit == 4)
  299      gsl_fit_linear_est(x2[i], c0, c1, cov00, cov01, cov11, &y2_sim[i],
  300                         &y2_sim_err[i]);
  301 
  302    
  303    fprintf(out, "%.2f %g %g %g %g %g\n", rtime[0] + (i + 0.5) * dt,
  304            x2[i], y2_sim[i], y2_sim_err[i], y2[i], y2_err[i]);
  305  }
  306 
  307  
  308  fprintf(out, "\n");
  309  fprintf(out, "#    scl= %g +/- %g\n", scl, scl_err);
  310  fprintf(out, "#     c1= %g +/- %g\n", c1, sqrt(cov11));
  311  if (fit == 3 || fit == 4) {
  312    fprintf(out, "#     c0= %g +/- %g\n", c0, sqrt(cov00));
  313    fprintf(out, "#   corr= %g\n", cov01 / (sqrt(cov00) * sqrt(cov11)));
  314  }
  315  fprintf(out, "#   RMSE= %g\n", sqrt(sumsq / n));
  316  fprintf(out, "#      n= %d\n", n);
  317 
  318  
  319  fclose(out);
  320 
  321  
  322
  323
  324 
  325  
  326  for (
int ip = 0; ip < atm2.
np; ip++) {
 
  327    atm2.
time[ip] /= nprof;
 
  329    atm2.
lon[ip] /= nprof;
 
  330    atm2.
lat[ip] /= nprof;
 
  333    for (ig = 0; ig < ctl.
ng; ig++)
 
  334      atm2.
q[ig][ip] /= nprof;
 
  335  }
  336 
  337  
  338  const size_t nk = 
atm2x(&ctl, &atm2, NULL, NULL, NULL);
 
  339  const size_t mk = 
obs2y(&ctl, &obs, NULL, NULL, NULL);
 
  340 
  341  
  342  gsl_matrix *k = gsl_matrix_alloc(mk, nk);
  343 
  344  
  345  kernel(&ctl, tbl, &atm2, &obs, k);
 
  346 
  347  
  349 
  350  
  351  write_matrix(NULL, argv[5], &ctl, k, &atm2, &obs, 
"y", 
"x", 
"r");
 
  352 
  353  
  354  gsl_matrix_free(k);
  355  free(tbl);
  356 
  357  return EXIT_SUCCESS;
  358}
#define NMAX
Maximum number of data points...
 
#define NLMAX
Maximum number of data lines...
 
void write_atm(const char *dirname, const char *filename, const ctl_t *ctl, const atm_t *atm)
Write atmospheric data.
 
void read_ctl(int argc, char *argv[], ctl_t *ctl)
Read forward model control parameters.
 
void kernel(const ctl_t *ctl, const tbl_t *tbl, atm_t *atm, obs_t *obs, gsl_matrix *k)
Compute Jacobians.
 
double scan_ctl(int argc, char *argv[], const char *varname, const int arridx, const char *defvalue, char *value)
Search control parameter file for variable entry.
 
void formod(const ctl_t *ctl, const tbl_t *tbl, atm_t *atm, obs_t *obs)
Determine ray paths and compute radiative transfer.
 
tbl_t * read_tbl(const ctl_t *ctl)
Read look-up table data.
 
size_t obs2y(const ctl_t *ctl, const obs_t *obs, gsl_vector *y, int *ida, int *ira)
Compose measurement vector.
 
size_t atm2x(const ctl_t *ctl, const atm_t *atm, gsl_vector *x, int *iqa, int *ipa)
Compose state vector or parameter vector.
 
void write_matrix(const char *dirname, const char *filename, const ctl_t *ctl, const gsl_matrix *matrix, const atm_t *atm, const obs_t *obs, const char *rowspace, const char *colspace, const char *sort)
Write matrix.
 
#define LEN
Maximum length of ASCII data lines.
 
#define POW2(x)
Compute x^2.
 
#define ERRMSG(...)
Print error message and quit program.
 
#define NP
Maximum number of atmospheric data points.
 
#define LOG(level,...)
Print log message.
 
#define MAX(a, b)
Macro to determine the maximum of two values.
 
double time[NP]
Time (seconds since 2000-01-01T00:00Z).
 
double lat[NP]
Latitude [deg].
 
double lon[NP]
Longitude [deg].
 
double t[NP]
Temperature [K].
 
int np
Number of data points.
 
double z[NP]
Altitude [km].
 
double q[NG][NP]
Volume mixing ratio [ppv].
 
double p[NP]
Pressure [hPa].
 
Forward model control parameters.
 
int write_matrix
Write matrix file (0=no, 1=yes).
 
int ng
Number of emitters.
 
int nd
Number of radiance channels.
 
char emitter[NG][LEN]
Name of each emitter.
 
int write_bbt
Use brightness temperature instead of radiance (0=no, 1=yes).
 
Observation geometry and radiance data.
 
double rad[ND][NR]
Radiance [W/(m^2 sr cm^-1)].
 
double obsz[NR]
Observer altitude [km].
 
int nr
Number of ray paths.
 
Emissivity look-up tables.