AIRS Code Collection
retrieval.c
Go to the documentation of this file.
1/*
2 This file is part of the AIRS Code Collection.
3
4 the AIRS Code Collections is free software: you can redistribute it
5 and/or modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation, either version 3 of
7 the License, or (at your option) any later version.
8
9 The AIRS Code Collection is distributed in the hope that it will be
10 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
11 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with the AIRS Code Collection. If not, see
16 <http://www.gnu.org/licenses/>.
17
18 Copyright (C) 2019-2025 Forschungszentrum Juelich GmbH
19*/
20
26#include <mpi.h>
27#include <omp.h>
28#include <netcdf.h>
29#include "jurassic.h"
30
31/* ------------------------------------------------------------
32 Macros...
33 ------------------------------------------------------------ */
34
36#define NC(cmd) { \
37 int nc_result=(cmd); \
38 if(nc_result!=NC_NOERR) \
39 ERRMSG("%s", nc_strerror(nc_result)); \
40}
41
42/* ------------------------------------------------------------
43 Dimensions...
44 ------------------------------------------------------------ */
45
47#define L1_NCHAN 34
48
50#define L1_NTRACK 135
51
53#define L1_NXTRACK 90
54
56#define L2_NLAY 27
57
59#define L2_NTRACK 45
60
62#define L2_NXTRACK 30
63
64/* ------------------------------------------------------------
65 Structs...
66 ------------------------------------------------------------ */
67
69typedef struct {
70
72 int ncid;
73
75 int np;
76
78 double l1_time[L1_NTRACK][L1_NXTRACK];
79
81 double l1_lon[L1_NTRACK][L1_NXTRACK];
82
84 double l1_lat[L1_NTRACK][L1_NXTRACK];
85
87 double l1_sat_z[L1_NTRACK];
88
90 double l1_sat_lon[L1_NTRACK];
91
93 double l1_sat_lat[L1_NTRACK];
94
96 double l1_nu[L1_NCHAN];
97
99 float l1_rad[L1_NTRACK][L1_NXTRACK][L1_NCHAN];
100
102 double l2_z[L2_NTRACK][L2_NXTRACK][L2_NLAY];
103
105 double l2_p[L2_NLAY];
106
108 double l2_t[L2_NTRACK][L2_NXTRACK][L2_NLAY];
109
111 float ret_z[NP];
112
114 float ret_p[L1_NTRACK * L1_NXTRACK];
115
117 float ret_t[L1_NTRACK * L1_NXTRACK * NP];
118
119} ncd_t;
120
122typedef struct {
123
125 int kernel_recomp;
126
128 int conv_itmax;
129
131 double conv_dmin;
132
134 double err_formod[ND];
135
137 double err_noise[ND];
138
140 double err_press;
141
143 double err_press_cz;
144
146 double err_press_ch;
147
149 double err_temp;
150
152 double err_temp_cz;
153
155 double err_temp_ch;
156
158 double err_q[NG];
159
161 double err_q_cz[NG];
162
164 double err_q_ch[NG];
165
167 double err_k[NW];
168
170 double err_k_cz[NW];
171
173 double err_k_ch[NW];
174
175} ret_t;
176
177/* ------------------------------------------------------------
178 Functions...
179 ------------------------------------------------------------ */
180
182void add_var(
183 int ncid,
184 const char *varname,
185 const char *unit,
186 const char *longname,
187 int type,
188 int dimid[],
189 int *varid,
190 int ndims);
191
193void buffer_nc(
194 atm_t * atm,
195 double chisq,
196 ncd_t * ncd,
197 int track,
198 int xtrack,
199 int np0,
200 int np1);
201
203double cost_function(
204 gsl_vector * dx,
205 gsl_vector * dy,
206 gsl_matrix * s_a_inv,
207 gsl_vector * sig_eps_inv);
208
210void fill_gaps(
211 double x[L2_NTRACK][L2_NXTRACK][L2_NLAY],
212 double cx,
213 double cy);
214
216void init_l2(
217 ncd_t * ncd,
218 int track,
219 int xtrack,
220 ctl_t * ctl,
221 atm_t * atm);
222
224void matrix_invert(
225 gsl_matrix * a);
226
228void matrix_product(
229 gsl_matrix * a,
230 gsl_vector * b,
231 int transpose,
232 gsl_matrix * c);
233
236 ret_t * ret,
237 ctl_t * ctl,
238 obs_t * obs_meas,
239 obs_t * obs_i,
240 atm_t * atm_apr,
241 atm_t * atm_i,
242 double *chisq);
243
245void read_nc(
246 char *filename,
247 ncd_t * ncd);
248
250void read_ret_ctl(
251 int argc,
252 char *argv[],
253 ctl_t * ctl,
254 ret_t * ret);
255
257void set_cov_apr(
258 ret_t * ret,
259 ctl_t * ctl,
260 atm_t * atm,
261 int *iqa,
262 int *ipa,
263 gsl_matrix * s_a);
264
266void set_cov_meas(
267 ret_t * ret,
268 ctl_t * ctl,
269 obs_t * obs,
270 gsl_vector * sig_noise,
271 gsl_vector * sig_formod,
272 gsl_vector * sig_eps_inv);
273
275void write_nc(
276 char *filename,
277 ncd_t * ncd);
278
279/* ------------------------------------------------------------
280 Main...
281 ------------------------------------------------------------ */
282
284 int argc,
285 char *argv[]) {
286
287 static ctl_t ctl;
288 static atm_t atm_apr, atm_clim, atm_i;
289 static obs_t obs_i, obs_meas;
290 static ncd_t ncd;
291 static ret_t ret;
292
293 FILE *in;
294
295 char filename[LEN];
296
297 double chisq, chisq_min, chisq_max, chisq_mean, z[NP];
298
299 int channel[ND], m, ntask = -1, rank, size;
300
301 /* ------------------------------------------------------------
302 Init...
303 ------------------------------------------------------------ */
304
305 /* MPI... */
306 MPI_Init(&argc, &argv);
307 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
308 MPI_Comm_size(MPI_COMM_WORLD, &size);
309
310 /* Measure CPU time... */
311 TIMER("total", 1);
312
313 /* Check arguments... */
314 if (argc < 3)
315 ERRMSG("Give parameters: <ctl> <filelist>");
316
317 /* Read control parameters... */
318 read_ctl(argc, argv, &ctl);
319 read_ret_ctl(argc, argv, &ctl, &ret);
320
321 /* Read retrieval grid... */
322 const int nz = (int) scan_ctl(argc, argv, "NZ", -1, "", NULL);
323 if (nz > NP)
324 ERRMSG("Too many altitudes!");
325 for (int iz = 0; iz < nz; iz++)
326 z[iz] = scan_ctl(argc, argv, "Z", iz, "", NULL);
327
328 /* Read track range... */
329 const int track0 = (int) scan_ctl(argc, argv, "TRACK_MIN", -1, "0", NULL);
330 const int track1 = (int) scan_ctl(argc, argv, "TRACK_MAX", -1, "134", NULL);
331
332 /* Read xtrack range... */
333 const int xtrack0 = (int) scan_ctl(argc, argv, "XTRACK_MIN", -1, "0", NULL);
334 const int xtrack1 =
335 (int) scan_ctl(argc, argv, "XTRACK_MAX", -1, "89", NULL);
336
337 /* Read height range... */
338 int np0 = (int) scan_ctl(argc, argv, "NP_MIN", -1, "0", NULL);
339 int np1 = (int) scan_ctl(argc, argv, "NP_MAX", -1, "100", NULL);
340 np1 = GSL_MIN(np1, nz - 1);
341
342 /* Background smoothing... */
343 const double sx = scan_ctl(argc, argv, "SX", -1, "8", NULL);
344 const double sy = scan_ctl(argc, argv, "SY", -1, "2", NULL);
345
346 /* SZA threshold... */
347 const double sza_thresh = scan_ctl(argc, argv, "SZA", -1, "96", NULL);
348
349 /* ------------------------------------------------------------
350 Distribute granules...
351 ------------------------------------------------------------ */
352
353 /* Open filelist... */
354 printf("Read filelist: %s\n", argv[2]);
355 if (!(in = fopen(argv[2], "r")))
356 ERRMSG("Cannot open filelist!");
357
358 /* Loop over netCDF files... */
359 while (fscanf(in, "%s", filename) != EOF) {
360
361 /* Distribute files with MPI... */
362 if ((++ntask) % size != rank)
363 continue;
364
365 /* Write info... */
366 printf("Retrieve file %s on rank %d of %d (with %d threads)...\n",
367 filename, rank + 1, size, omp_get_max_threads());
368
369 /* ------------------------------------------------------------
370 Initialize retrieval...
371 ------------------------------------------------------------ */
372
373 /* Read netCDF file... */
374 read_nc(filename, &ncd);
375
376 /* Identify radiance channels... */
377 for (int id = 0; id < ctl.nd; id++) {
378 channel[id] = -999;
379 for (int i = 0; i < L1_NCHAN; i++)
380 if (fabs(ctl.nu[id] - ncd.l1_nu[i]) < 0.1)
381 channel[id] = i;
382 if (channel[id] < 0)
383 ERRMSG("Cannot identify radiance channel!");
384 }
385
386 /* Fill data gaps... */
387 fill_gaps(ncd.l2_t, sx, sy);
388 fill_gaps(ncd.l2_z, sx, sy);
389
390 /* Set climatological data for center of granule... */
391 atm_clim.np = nz;
392 for (int iz = 0; iz < nz; iz++)
393 atm_clim.z[iz] = z[iz];
394 climatology(&ctl, &atm_clim);
395
396 /* ------------------------------------------------------------
397 Retrieval...
398 ------------------------------------------------------------ */
399
400 /* Get chi^2 statistics... */
401 chisq_min = 1e100;
402 chisq_max = -1e100;
403 chisq_mean = 0;
404 m = 0;
405
406 /* Loop over swaths... */
407 for (int track = track0; track <= track1; track++) {
408
409 /* Measure CPU time... */
410 TIMER("retrieval", 1);
411
412 /* Loop over scan... */
413 for (int xtrack = xtrack0; xtrack <= xtrack1; xtrack++) {
414
415 /* Store observation data... */
416 obs_meas.nr = 1;
417 obs_meas.time[0] = ncd.l1_time[track][xtrack];
418 obs_meas.obsz[0] = ncd.l1_sat_z[track];
419 obs_meas.obslon[0] = ncd.l1_sat_lon[track];
420 obs_meas.obslat[0] = ncd.l1_sat_lat[track];
421 obs_meas.vplon[0] = ncd.l1_lon[track][xtrack];
422 obs_meas.vplat[0] = ncd.l1_lat[track][xtrack];
423 for (int id = 0; id < ctl.nd; id++)
424 obs_meas.rad[id][0] = ncd.l1_rad[track][xtrack][channel[id]];
425
426 /* Flag out 4 micron channels for daytime measurements... */
427 if (sza(obs_meas.time[0], obs_meas.obslon[0], obs_meas.obslat[0])
428 < sza_thresh)
429 for (int id = 0; id < ctl.nd; id++)
430 if (ctl.nu[id] >= 2000)
431 obs_meas.rad[id][0] = GSL_NAN;
432
433 /* Prepare atmospheric data... */
434 copy_atm(&ctl, &atm_apr, &atm_clim, 0);
435 for (int ip = 0; ip < atm_apr.np; ip++) {
436 atm_apr.time[ip] = obs_meas.time[0];
437 atm_apr.lon[ip] = obs_meas.vplon[0];
438 atm_apr.lat[ip] = obs_meas.vplat[0];
439 }
440
441 /* Merge Level-2 data... */
442 init_l2(&ncd, track, xtrack, &ctl, &atm_apr);
443
444 /* Retrieval... */
445 optimal_estimation(&ret, &ctl, &obs_meas, &obs_i,
446 &atm_apr, &atm_i, &chisq);
447
448 /* Get chi^2 statistics... */
449 if (gsl_finite(chisq)) {
450 chisq_min = GSL_MIN(chisq_min, chisq);
451 chisq_max = GSL_MAX(chisq_max, chisq);
452 chisq_mean += chisq;
453 m++;
454 }
455
456 /* Buffer results... */
457 buffer_nc(&atm_i, chisq, &ncd, track, xtrack, np0, np1);
458 }
459
460 /* Measure CPU time... */
461 TIMER("retrieval", 3);
462 }
463
464 /* ------------------------------------------------------------
465 Finalize...
466 ------------------------------------------------------------ */
467
468 /* Write netCDF file... */
469 write_nc(filename, &ncd);
470
471 /* Write info... */
472 printf("chi^2: min= %g / mean= %g / max= %g / m= %d\n",
473 chisq_min, chisq_mean / m, chisq_max, m);
474 printf("Retrieval finished on rank %d of %d!\n", rank, size);
475 }
476
477 /* Close file list... */
478 fclose(in);
479
480 /* Measure CPU time... */
481 TIMER("total", 3);
482
483 /* Report memory usage... */
484 printf("MEMORY_ATM = %g MByte\n", 4. * sizeof(atm_t) / 1024. / 1024.);
485 printf("MEMORY_CTL = %g MByte\n", 1. * sizeof(ctl_t) / 1024. / 1024.);
486 printf("MEMORY_NCD = %g MByte\n", 1. * sizeof(ncd_t) / 1024. / 1024.);
487 printf("MEMORY_OBS = %g MByte\n", 3. * sizeof(atm_t) / 1024. / 1024.);
488 printf("MEMORY_RET = %g MByte\n", 1. * sizeof(ret_t) / 1024. / 1024.);
489 printf("MEMORY_TBL = %g MByte\n", 1. * sizeof(tbl_t) / 1024. / 1024.);
490
491 /* Report problem size... */
492 printf("SIZE_TASKS = %d\n", size);
493 printf("SIZE_THREADS = %d\n", omp_get_max_threads());
494
495 /* MPI... */
496 MPI_Finalize();
497
498 return EXIT_SUCCESS;
499}
500
501/*****************************************************************************/
502
504 int ncid,
505 const char *varname,
506 const char *unit,
507 const char *longname,
508 int type,
509 int dimid[],
510 int *varid,
511 int ndims) {
512
513 /* Check if variable exists... */
514 if (nc_inq_varid(ncid, varname, varid) != NC_NOERR) {
515
516 /* Define variable... */
517 NC(nc_def_var(ncid, varname, type, ndims, dimid, varid));
518
519 /* Set long name... */
520 NC(nc_put_att_text
521 (ncid, *varid, "long_name", strlen(longname), longname));
522
523 /* Set units... */
524 NC(nc_put_att_text(ncid, *varid, "units", strlen(unit), unit));
525 }
526}
527
528/*****************************************************************************/
529
531 atm_t *atm,
532 double chisq,
533 ncd_t *ncd,
534 int track,
535 int xtrack,
536 int np0,
537 int np1) {
538
539 /* Set number of data points... */
540 ncd->np = np1 - np0 + 1;
541
542 /* Save retrieval data... */
543 for (int ip = np0; ip <= np1; ip++) {
544 ncd->ret_z[ip - np0] = (float) atm->z[ip];
545 ncd->ret_p[track * L1_NXTRACK + xtrack] = (float) atm->p[np0];
546 ncd->ret_t[(track * L1_NXTRACK + xtrack) * ncd->np + ip - np0] =
547 (gsl_finite(chisq) ? (float) atm->t[ip] : GSL_NAN);
548 }
549}
550
551/*****************************************************************************/
552
554 gsl_vector *dx,
555 gsl_vector *dy,
556 gsl_matrix *s_a_inv,
557 gsl_vector *sig_eps_inv) {
558
559 double chisq_a, chisq_m = 0;
560
561 /* Get sizes... */
562 const size_t m = dy->size;
563 const size_t n = dx->size;
564
565 /* Allocate... */
566 gsl_vector *x_aux = gsl_vector_alloc(n);
567 gsl_vector *y_aux = gsl_vector_alloc(m);
568
569 /* Determine normalized cost function...
570 (chi^2 = 1/m * [dy^T * S_eps^{-1} * dy + dx^T * S_a^{-1} * dx]) */
571 for (size_t i = 0; i < m; i++)
572 chisq_m +=
573 gsl_pow_2(gsl_vector_get(dy, i) * gsl_vector_get(sig_eps_inv, i));
574 gsl_blas_dgemv(CblasNoTrans, 1.0, s_a_inv, dx, 0.0, x_aux);
575 gsl_blas_ddot(dx, x_aux, &chisq_a);
576
577 /* Free... */
578 gsl_vector_free(x_aux);
579 gsl_vector_free(y_aux);
580
581 /* Return cost function value... */
582 return (chisq_m + chisq_a) / (double) m;
583}
584
585/************************************************************************/
586
588 double x[L2_NTRACK][L2_NXTRACK][L2_NLAY],
589 double cx,
590 double cy) {
591
592 double help[L2_NTRACK][L2_NXTRACK];
593
594 /* Loop over layers... */
595 for (int lay = 0; lay < L2_NLAY; lay++) {
596
597 /* Loop over grid points... */
598 for (int track = 0; track < L2_NTRACK; track++)
599 for (int xtrack = 0; xtrack < L2_NXTRACK; xtrack++) {
600
601 /* Init... */
602 help[track][xtrack] = 0;
603 double wsum = 0;
604
605 /* Averrage data points... */
606 for (int track2 = 0; track2 < L2_NTRACK; track2++)
607 for (int xtrack2 = 0; xtrack2 < L2_NXTRACK; xtrack2++)
608 if (gsl_finite(x[track2][xtrack2][lay])
609 && x[track2][xtrack2][lay] > 0) {
610 const double w = exp(-gsl_pow_2((xtrack - xtrack2) / cx)
611 - gsl_pow_2((track - track2) / cy));
612 help[track][xtrack] += w * x[track2][xtrack2][lay];
613 wsum += w;
614 }
615
616 /* Normalize... */
617 if (wsum > 0)
618 help[track][xtrack] /= wsum;
619 else
620 help[track][xtrack] = GSL_NAN;
621 }
622
623 /* Copy grid points... */
624 for (int track = 0; track < L2_NTRACK; track++)
625 for (int xtrack = 0; xtrack < L2_NXTRACK; xtrack++)
626 x[track][xtrack][lay] = help[track][xtrack];
627 }
628}
629
630/************************************************************************/
631
633 ncd_t *ncd,
634 int track,
635 int xtrack,
636 ctl_t *ctl,
637 atm_t *atm) {
638
639 static atm_t atm_airs;
640
641 double k[NW], p, q[NG], t, zmax = 0, zmin = 1000;
642
643 /* Reset track- and xtrack-index to match Level-2 data... */
644 track /= 3;
645 xtrack /= 3;
646
647 /* Store AIRS data in atmospheric data struct... */
648 atm_airs.np = 0;
649 for (int lay = 0; lay < L2_NLAY; lay++)
650 if (gsl_finite(ncd->l2_z[track][xtrack][lay])) {
651 atm_airs.z[atm_airs.np] = ncd->l2_z[track][xtrack][lay];
652 atm_airs.p[atm_airs.np] = ncd->l2_p[lay];
653 atm_airs.t[atm_airs.np] = ncd->l2_t[track][xtrack][lay];
654 if ((++atm_airs.np) > NP)
655 ERRMSG("Too many layers!");
656 }
657
658 /* Check number of levels... */
659 if (atm_airs.np <= 0)
660 return;
661
662 /* Get height range of AIRS data... */
663 for (int ip = 0; ip < atm_airs.np; ip++) {
664 zmax = GSL_MAX(zmax, atm_airs.z[ip]);
665 zmin = GSL_MIN(zmin, atm_airs.z[ip]);
666 }
667
668 /* Merge AIRS data... */
669 for (int ip = 0; ip < atm->np; ip++) {
670
671 /* Interpolate AIRS data... */
672 intpol_atm(ctl, &atm_airs, atm->z[ip], &p, &t, q, k);
673
674 /* Weighting factor... */
675 double w = 1;
676 if (atm->z[ip] > zmax)
677 w = GSL_MAX(1 - (atm->z[ip] - zmax) / 50, 0);
678 if (atm->z[ip] < zmin)
679 w = GSL_MAX(1 - (zmin - atm->z[ip]) / 50, 0);
680
681 /* Merge... */
682 atm->t[ip] = w * t + (1 - w) * atm->t[ip];
683 atm->p[ip] = w * p + (1 - w) * atm->p[ip];
684 }
685}
686
687/*****************************************************************************/
688
690 gsl_matrix *a) {
691
692 size_t diag = 1;
693
694 /* Get size... */
695 const size_t n = a->size1;
696
697 /* Check if matrix is diagonal... */
698 for (size_t i = 0; i < n && diag; i++)
699 for (size_t j = i + 1; j < n; j++)
700 if (gsl_matrix_get(a, i, j) != 0) {
701 diag = 0;
702 break;
703 }
704
705 /* Quick inversion of diagonal matrix... */
706 if (diag)
707 for (size_t i = 0; i < n; i++)
708 gsl_matrix_set(a, i, i, 1 / gsl_matrix_get(a, i, i));
709
710 /* Matrix inversion by means of Cholesky decomposition... */
711 else {
712 gsl_linalg_cholesky_decomp(a);
713 gsl_linalg_cholesky_invert(a);
714 }
715}
716
717/*****************************************************************************/
718
720 gsl_matrix *a,
721 gsl_vector *b,
722 int transpose,
723 gsl_matrix *c) {
724
725 /* Set sizes... */
726 const size_t m = a->size1;
727 const size_t n = a->size2;
728
729 /* Allocate... */
730 gsl_matrix *aux = gsl_matrix_alloc(m, n);
731
732 /* Compute A^T B A... */
733 if (transpose == 1) {
734
735 /* Compute B^1/2 A... */
736 for (size_t i = 0; i < m; i++)
737 for (size_t j = 0; j < n; j++)
738 gsl_matrix_set(aux, i, j,
739 gsl_vector_get(b, i) * gsl_matrix_get(a, i, j));
740
741 /* Compute A^T B A = (B^1/2 A)^T (B^1/2 A)... */
742 gsl_blas_dgemm(CblasTrans, CblasNoTrans, 1.0, aux, aux, 0.0, c);
743 }
744
745 /* Compute A B A^T... */
746 else if (transpose == 2) {
747
748 /* Compute A B^1/2... */
749 for (size_t i = 0; i < m; i++)
750 for (size_t j = 0; j < n; j++)
751 gsl_matrix_set(aux, i, j,
752 gsl_matrix_get(a, i, j) * gsl_vector_get(b, j));
753
754 /* Compute A B A^T = (A B^1/2) (A B^1/2)^T... */
755 gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1.0, aux, aux, 0.0, c);
756 }
757
758 /* Free... */
759 gsl_matrix_free(aux);
760}
761
762/*****************************************************************************/
763
765 ret_t *ret,
766 ctl_t *ctl,
767 obs_t *obs_meas,
768 obs_t *obs_i,
769 atm_t *atm_apr,
770 atm_t *atm_i,
771 double *chisq) {
772
773 static int ipa[N], iqa[N];
774
775 double disq = 0, lmpar = 0.001;
776
777 /* ------------------------------------------------------------
778 Initialize...
779 ------------------------------------------------------------ */
780
781 /* Get sizes... */
782 const size_t m = obs2y(ctl, obs_meas, NULL, NULL, NULL);
783 const size_t n = atm2x(ctl, atm_apr, NULL, iqa, ipa);
784 if (m == 0 || n == 0) {
785 *chisq = GSL_NAN;
786 return;
787 }
788
789 /* Allocate... */
790 gsl_matrix *a = gsl_matrix_alloc(n, n);
791 gsl_matrix *cov = gsl_matrix_alloc(n, n);
792 gsl_matrix *k_i = gsl_matrix_alloc(m, n);
793 gsl_matrix *s_a_inv = gsl_matrix_alloc(n, n);
794
795 gsl_vector *b = gsl_vector_alloc(n);
796 gsl_vector *dx = gsl_vector_alloc(n);
797 gsl_vector *dy = gsl_vector_alloc(m);
798 gsl_vector *sig_eps_inv = gsl_vector_alloc(m);
799 gsl_vector *sig_formod = gsl_vector_alloc(m);
800 gsl_vector *sig_noise = gsl_vector_alloc(m);
801 gsl_vector *x_a = gsl_vector_alloc(n);
802 gsl_vector *x_i = gsl_vector_alloc(n);
803 gsl_vector *x_step = gsl_vector_alloc(n);
804 gsl_vector *y_aux = gsl_vector_alloc(m);
805 gsl_vector *y_i = gsl_vector_alloc(m);
806 gsl_vector *y_m = gsl_vector_alloc(m);
807
808 /* Set initial state... */
809 copy_atm(ctl, atm_i, atm_apr, 0);
810 copy_obs(ctl, obs_i, obs_meas, 0);
811 formod(ctl, atm_i, obs_i);
812
813 /* Set state vectors and observation vectors... */
814 atm2x(ctl, atm_apr, x_a, NULL, NULL);
815 atm2x(ctl, atm_i, x_i, NULL, NULL);
816 obs2y(ctl, obs_meas, y_m, NULL, NULL);
817 obs2y(ctl, obs_i, y_i, NULL, NULL);
818
819 /* Set inverse a priori covariance S_a^-1... */
820 set_cov_apr(ret, ctl, atm_apr, iqa, ipa, s_a_inv);
821 matrix_invert(s_a_inv);
822
823 /* Get measurement errors... */
824 set_cov_meas(ret, ctl, obs_meas, sig_noise, sig_formod, sig_eps_inv);
825
826 /* Determine dx = x_i - x_a and dy = y - F(x_i) ... */
827 gsl_vector_memcpy(dx, x_i);
828 gsl_vector_sub(dx, x_a);
829 gsl_vector_memcpy(dy, y_m);
830 gsl_vector_sub(dy, y_i);
831
832 /* Compute cost function... */
833 *chisq = cost_function(dx, dy, s_a_inv, sig_eps_inv);
834
835 /* Compute initial kernel... */
836 kernel(ctl, atm_i, obs_i, k_i);
837
838 /* ------------------------------------------------------------
839 Levenberg-Marquardt minimization...
840 ------------------------------------------------------------ */
841
842 /* Outer loop... */
843 for (int it = 1; it <= ret->conv_itmax; it++) {
844
845 /* Store current cost function value... */
846 double chisq_old = *chisq;
847
848 /* Compute kernel matrix K_i... */
849 if (it > 1 && it % ret->kernel_recomp == 0)
850 kernel(ctl, atm_i, obs_i, k_i);
851
852 /* Compute K_i^T * S_eps^{-1} * K_i ... */
853 if (it == 1 || it % ret->kernel_recomp == 0)
854 matrix_product(k_i, sig_eps_inv, 1, cov);
855
856 /* Determine b = K_i^T * S_eps^{-1} * dy - S_a^{-1} * dx ... */
857 for (size_t i = 0; i < m; i++)
858 gsl_vector_set(y_aux, i, gsl_vector_get(dy, i)
859 * gsl_pow_2(gsl_vector_get(sig_eps_inv, i)));
860 gsl_blas_dgemv(CblasTrans, 1.0, k_i, y_aux, 0.0, b);
861 gsl_blas_dgemv(CblasNoTrans, -1.0, s_a_inv, dx, 1.0, b);
862
863 /* Inner loop... */
864 for (int it2 = 0; it2 < 20; it2++) {
865
866 /* Compute A = (1 + lmpar) * S_a^{-1} + K_i^T * S_eps^{-1} * K_i ... */
867 gsl_matrix_memcpy(a, s_a_inv);
868 gsl_matrix_scale(a, 1 + lmpar);
869 gsl_matrix_add(a, cov);
870
871 /* Solve A * x_step = b by means of Cholesky decomposition... */
872 gsl_linalg_cholesky_decomp(a);
873 gsl_linalg_cholesky_solve(a, b, x_step);
874
875 /* Update atmospheric state... */
876 gsl_vector_add(x_i, x_step);
877 copy_atm(ctl, atm_i, atm_apr, 0);
878 copy_obs(ctl, obs_i, obs_meas, 0);
879 x2atm(ctl, x_i, atm_i);
880
881 /* Check atmospheric state... */
882 for (int ip = 0; ip < atm_i->np; ip++) {
883 atm_i->p[ip] = GSL_MIN(GSL_MAX(atm_i->p[ip], 5e-7), 5e4);
884 atm_i->t[ip] = GSL_MIN(GSL_MAX(atm_i->t[ip], 100), 400);
885 for (int ig = 0; ig < ctl->ng; ig++)
886 atm_i->q[ig][ip] = GSL_MIN(GSL_MAX(atm_i->q[ig][ip], 0), 1);
887 for (int iw = 0; iw < ctl->nw; iw++)
888 atm_i->k[iw][ip] = GSL_MAX(atm_i->k[iw][ip], 0);
889 }
890
891 /* Forward calculation... */
892 formod(ctl, atm_i, obs_i);
893 obs2y(ctl, obs_i, y_i, NULL, NULL);
894
895 /* Determine dx = x_i - x_a and dy = y - F(x_i) ... */
896 gsl_vector_memcpy(dx, x_i);
897 gsl_vector_sub(dx, x_a);
898 gsl_vector_memcpy(dy, y_m);
899 gsl_vector_sub(dy, y_i);
900
901 /* Compute cost function... */
902 *chisq = cost_function(dx, dy, s_a_inv, sig_eps_inv);
903
904 /* Modify Levenberg-Marquardt parameter... */
905 if (*chisq > chisq_old) {
906 lmpar *= 10;
907 gsl_vector_sub(x_i, x_step);
908 } else {
909 lmpar /= 10;
910 break;
911 }
912 }
913
914 /* Get normalized step size in state space... */
915 gsl_blas_ddot(x_step, b, &disq);
916 disq /= (double) n;
917
918 /* Convergence test... */
919 if ((it == 1 || it % ret->kernel_recomp == 0) && disq < ret->conv_dmin)
920 break;
921 }
922
923 /* ------------------------------------------------------------
924 Finalize...
925 ------------------------------------------------------------ */
926
927 gsl_matrix_free(a);
928 gsl_matrix_free(cov);
929 gsl_matrix_free(k_i);
930 gsl_matrix_free(s_a_inv);
931
932 gsl_vector_free(b);
933 gsl_vector_free(dx);
934 gsl_vector_free(dy);
935 gsl_vector_free(sig_eps_inv);
936 gsl_vector_free(sig_formod);
937 gsl_vector_free(sig_noise);
938 gsl_vector_free(x_a);
939 gsl_vector_free(x_i);
940 gsl_vector_free(x_step);
941 gsl_vector_free(y_aux);
942 gsl_vector_free(y_i);
943 gsl_vector_free(y_m);
944}
945
946/*****************************************************************************/
947
949 char *filename,
950 ncd_t *ncd) {
951
952 int varid;
953
954 /* Open netCDF file... */
955 printf("Read netCDF file: %s\n", filename);
956 NC(nc_open(filename, NC_WRITE, &ncd->ncid));
957
958 /* Read Level-1 data... */
959 NC(nc_inq_varid(ncd->ncid, "l1_time", &varid));
960 NC(nc_get_var_double(ncd->ncid, varid, ncd->l1_time[0]));
961 NC(nc_inq_varid(ncd->ncid, "l1_lon", &varid));
962 NC(nc_get_var_double(ncd->ncid, varid, ncd->l1_lon[0]));
963 NC(nc_inq_varid(ncd->ncid, "l1_lat", &varid));
964 NC(nc_get_var_double(ncd->ncid, varid, ncd->l1_lat[0]));
965 NC(nc_inq_varid(ncd->ncid, "l1_sat_z", &varid));
966 NC(nc_get_var_double(ncd->ncid, varid, ncd->l1_sat_z));
967 NC(nc_inq_varid(ncd->ncid, "l1_sat_lon", &varid));
968 NC(nc_get_var_double(ncd->ncid, varid, ncd->l1_sat_lon));
969 NC(nc_inq_varid(ncd->ncid, "l1_sat_lat", &varid));
970 NC(nc_get_var_double(ncd->ncid, varid, ncd->l1_sat_lat));
971 NC(nc_inq_varid(ncd->ncid, "l1_nu", &varid));
972 NC(nc_get_var_double(ncd->ncid, varid, ncd->l1_nu));
973 NC(nc_inq_varid(ncd->ncid, "l1_rad", &varid));
974 NC(nc_get_var_float(ncd->ncid, varid, ncd->l1_rad[0][0]));
975
976 /* Read Level-2 data... */
977 NC(nc_inq_varid(ncd->ncid, "l2_z", &varid));
978 NC(nc_get_var_double(ncd->ncid, varid, ncd->l2_z[0][0]));
979 NC(nc_inq_varid(ncd->ncid, "l2_press", &varid));
980 NC(nc_get_var_double(ncd->ncid, varid, ncd->l2_p));
981 NC(nc_inq_varid(ncd->ncid, "l2_temp", &varid));
982 NC(nc_get_var_double(ncd->ncid, varid, ncd->l2_t[0][0]));
983}
984
985/*****************************************************************************/
986
988 int argc,
989 char *argv[],
990 ctl_t *ctl,
991 ret_t *ret) {
992
993 /* Iteration control... */
994 ret->kernel_recomp =
995 (int) scan_ctl(argc, argv, "KERNEL_RECOMP", -1, "3", NULL);
996 ret->conv_itmax = (int) scan_ctl(argc, argv, "CONV_ITMAX", -1, "30", NULL);
997 ret->conv_dmin = scan_ctl(argc, argv, "CONV_DMIN", -1, "0.1", NULL);
998
999 for (int id = 0; id < ctl->nd; id++)
1000 ret->err_formod[id] = scan_ctl(argc, argv, "ERR_FORMOD", id, "0", NULL);
1001
1002 for (int id = 0; id < ctl->nd; id++)
1003 ret->err_noise[id] = scan_ctl(argc, argv, "ERR_NOISE", id, "0", NULL);
1004
1005 ret->err_press = scan_ctl(argc, argv, "ERR_PRESS", -1, "0", NULL);
1006 ret->err_press_cz = scan_ctl(argc, argv, "ERR_PRESS_CZ", -1, "-999", NULL);
1007 ret->err_press_ch = scan_ctl(argc, argv, "ERR_PRESS_CH", -1, "-999", NULL);
1008
1009 ret->err_temp = scan_ctl(argc, argv, "ERR_TEMP", -1, "0", NULL);
1010 ret->err_temp_cz = scan_ctl(argc, argv, "ERR_TEMP_CZ", -1, "-999", NULL);
1011 ret->err_temp_ch = scan_ctl(argc, argv, "ERR_TEMP_CH", -1, "-999", NULL);
1012
1013 for (int ig = 0; ig < ctl->ng; ig++) {
1014 ret->err_q[ig] = scan_ctl(argc, argv, "ERR_Q", ig, "0", NULL);
1015 ret->err_q_cz[ig] = scan_ctl(argc, argv, "ERR_Q_CZ", ig, "-999", NULL);
1016 ret->err_q_ch[ig] = scan_ctl(argc, argv, "ERR_Q_CH", ig, "-999", NULL);
1017 }
1018
1019 for (int iw = 0; iw < ctl->nw; iw++) {
1020 ret->err_k[iw] = scan_ctl(argc, argv, "ERR_K", iw, "0", NULL);
1021 ret->err_k_cz[iw] = scan_ctl(argc, argv, "ERR_K_CZ", iw, "-999", NULL);
1022 ret->err_k_ch[iw] = scan_ctl(argc, argv, "ERR_K_CH", iw, "-999", NULL);
1023 }
1024}
1025
1026/*****************************************************************************/
1027
1029 ret_t *ret,
1030 ctl_t *ctl,
1031 atm_t *atm,
1032 int *iqa,
1033 int *ipa,
1034 gsl_matrix *s_a) {
1035
1036 /* Get sizes... */
1037 const size_t n = s_a->size1;
1038
1039 /* Allocate... */
1040 gsl_vector *x_a = gsl_vector_alloc(n);
1041
1042 /* Get sigma vector... */
1043 atm2x(ctl, atm, x_a, NULL, NULL);
1044 for (size_t i = 0; i < n; i++) {
1045 if (iqa[i] == IDXP)
1046 gsl_vector_set(x_a, i, ret->err_press / 100 * gsl_vector_get(x_a, i));
1047 if (iqa[i] == IDXT)
1048 gsl_vector_set(x_a, i, ret->err_temp);
1049 for (int ig = 0; ig < ctl->ng; ig++)
1050 if (iqa[i] == IDXQ(ig))
1051 gsl_vector_set(x_a, i, ret->err_q[ig] / 100 * gsl_vector_get(x_a, i));
1052 for (int iw = 0; iw < ctl->nw; iw++)
1053 if (iqa[i] == IDXK(iw))
1054 gsl_vector_set(x_a, i, ret->err_k[iw]);
1055 }
1056
1057 /* Check standard deviations... */
1058 for (size_t i = 0; i < n; i++)
1059 if (gsl_pow_2(gsl_vector_get(x_a, i)) <= 0)
1060 ERRMSG("Check a priori data (zero standard deviation)!");
1061
1062 /* Initialize diagonal covariance... */
1063 gsl_matrix_set_zero(s_a);
1064 for (size_t i = 0; i < n; i++)
1065 gsl_matrix_set(s_a, i, i, gsl_pow_2(gsl_vector_get(x_a, i)));
1066
1067 /* Loop over matrix elements... */
1068 for (size_t i = 0; i < n; i++)
1069 for (size_t j = 0; j < n; j++)
1070 if (i != j && iqa[i] == iqa[j]) {
1071
1072 /* Initialize... */
1073 double cz = 0;
1074 double ch = 0;
1075
1076 /* Set correlation lengths for pressure... */
1077 if (iqa[i] == IDXP) {
1078 cz = ret->err_press_cz;
1079 ch = ret->err_press_ch;
1080 }
1081
1082 /* Set correlation lengths for temperature... */
1083 if (iqa[i] == IDXT) {
1084 cz = ret->err_temp_cz;
1085 ch = ret->err_temp_ch;
1086 }
1087
1088 /* Set correlation lengths for volume mixing ratios... */
1089 for (int ig = 0; ig < ctl->ng; ig++)
1090 if (iqa[i] == IDXQ(ig)) {
1091 cz = ret->err_q_cz[ig];
1092 ch = ret->err_q_ch[ig];
1093 }
1094
1095 /* Set correlation lengths for extinction... */
1096 for (int iw = 0; iw < ctl->nw; iw++)
1097 if (iqa[i] == IDXK(iw)) {
1098 cz = ret->err_k_cz[iw];
1099 ch = ret->err_k_ch[iw];
1100 }
1101
1102 /* Compute correlations... */
1103 if (cz > 0 && ch > 0) {
1104
1105 /* Get Cartesian coordinates... */
1106 double x0[3], x1[3];
1107 geo2cart(0, atm->lon[ipa[i]], atm->lat[ipa[i]], x0);
1108 geo2cart(0, atm->lon[ipa[j]], atm->lat[ipa[j]], x1);
1109
1110 /* Compute correlations... */
1111 const double rho =
1112 exp(-DIST(x0, x1) / ch -
1113 fabs(atm->z[ipa[i]] - atm->z[ipa[j]]) / cz);
1114
1115 /* Set covariance... */
1116 gsl_matrix_set(s_a, i, j, gsl_vector_get(x_a, i)
1117 * gsl_vector_get(x_a, j) * rho);
1118 }
1119 }
1120
1121 /* Free... */
1122 gsl_vector_free(x_a);
1123}
1124
1125/*****************************************************************************/
1126
1128 ret_t *ret,
1129 ctl_t *ctl,
1130 obs_t *obs,
1131 gsl_vector *sig_noise,
1132 gsl_vector *sig_formod,
1133 gsl_vector *sig_eps_inv) {
1134
1135 static obs_t obs_err;
1136
1137 /* Get size... */
1138 const size_t m = sig_eps_inv->size;
1139
1140 /* Noise error (always considered in retrieval fit)... */
1141 copy_obs(ctl, &obs_err, obs, 1);
1142 for (int ir = 0; ir < obs_err.nr; ir++)
1143 for (int id = 0; id < ctl->nd; id++)
1144 obs_err.rad[id][ir]
1145 = (gsl_finite(obs->rad[id][ir]) ? ret->err_noise[id] : GSL_NAN);
1146 obs2y(ctl, &obs_err, sig_noise, NULL, NULL);
1147
1148 /* Forward model error (always considered in retrieval fit)... */
1149 copy_obs(ctl, &obs_err, obs, 1);
1150 for (int ir = 0; ir < obs_err.nr; ir++)
1151 for (int id = 0; id < ctl->nd; id++)
1152 obs_err.rad[id][ir]
1153 = fabs(ret->err_formod[id] / 100 * obs->rad[id][ir]);
1154 obs2y(ctl, &obs_err, sig_formod, NULL, NULL);
1155
1156 /* Total error... */
1157 for (size_t i = 0; i < m; i++)
1158 gsl_vector_set(sig_eps_inv, i,
1159 1 / sqrt(gsl_pow_2(gsl_vector_get(sig_noise, i))
1160 + gsl_pow_2(gsl_vector_get(sig_formod, i))));
1161
1162 /* Check standard deviations... */
1163 for (size_t i = 0; i < m; i++)
1164 if (gsl_vector_get(sig_eps_inv, i) <= 0)
1165 ERRMSG("Check measurement errors (zero standard deviation)!");
1166}
1167
1168/*****************************************************************************/
1169
1171 char *filename,
1172 ncd_t *ncd) {
1173
1174 int dimid[10], p_id, t_id, z_id;
1175
1176 /* Create netCDF file... */
1177 printf("Write netCDF file: %s\n", filename);
1178
1179 /* Read existing dimensions... */
1180 NC(nc_inq_dimid(ncd->ncid, "L1_NTRACK", &dimid[0]));
1181 NC(nc_inq_dimid(ncd->ncid, "L1_NXTRACK", &dimid[1]));
1182
1183 /* Set define mode... */
1184 NC(nc_redef(ncd->ncid));
1185
1186 /* Set new dimensions... */
1187 if (nc_inq_dimid(ncd->ncid, "RET_NP", &dimid[2]) != NC_NOERR)
1188 NC(nc_def_dim(ncd->ncid, "RET_NP", (size_t) ncd->np, &dimid[2]));
1189
1190 /* Set new variables... */
1191 add_var(ncd->ncid, "ret_z", "km", "altitude", NC_FLOAT, &dimid[2], &z_id,
1192 1);
1193 add_var(ncd->ncid, "ret_press", "hPa", "pressure", NC_FLOAT, dimid, &p_id,
1194 2);
1195 add_var(ncd->ncid, "ret_temp", "K", "temperature", NC_FLOAT, dimid, &t_id,
1196 3);
1197
1198 /* Leave define mode... */
1199 NC(nc_enddef(ncd->ncid));
1200
1201 /* Write data... */
1202 NC(nc_put_var_float(ncd->ncid, z_id, ncd->ret_z));
1203 NC(nc_put_var_float(ncd->ncid, p_id, ncd->ret_p));
1204 NC(nc_put_var_float(ncd->ncid, t_id, ncd->ret_t));
1205
1206 /* Close netCDF file... */
1207 NC(nc_close(ncd->ncid));
1208}
void read_ctl(int argc, char *argv[], ctl_t *ctl)
Read forward model control parameters.
Definition: jurassic.c:4547
void x2atm(const ctl_t *ctl, const gsl_vector *x, atm_t *atm)
Decompose parameter vector or state vector.
Definition: jurassic.c:5896
void intpol_atm(const ctl_t *ctl, const atm_t *atm, const double z, double *p, double *t, double *q, double *k)
Interpolate atmospheric data.
Definition: jurassic.c:3685
double sza(const double sec, const double lon, const double lat)
Calculate solar zenith angle.
Definition: jurassic.c:5183
void formod(const ctl_t *ctl, atm_t *atm, obs_t *obs)
Determine ray paths and compute radiative transfer.
Definition: jurassic.c:3026
void copy_obs(const ctl_t *ctl, obs_t *obs_dest, const obs_t *obs_src, const int init)
Copy and initialize observation data.
Definition: jurassic.c:2975
double scan_ctl(int argc, char *argv[], const char *varname, int arridx, const char *defvalue, char *value)
Search control parameter file for variable entry.
Definition: jurassic.c:5114
void copy_atm(const ctl_t *ctl, atm_t *atm_dest, const atm_t *atm_src, const int init)
Copy and initialize atmospheric data.
Definition: jurassic.c:2921
size_t obs2y(const ctl_t *ctl, const obs_t *obs, gsl_vector *y, int *ida, int *ira)
Compose measurement vector.
Definition: jurassic.c:4174
size_t atm2x(const ctl_t *ctl, const atm_t *atm, gsl_vector *x, int *iqa, int *ipa)
Compose state vector or parameter vector.
Definition: jurassic.c:29
void climatology(const ctl_t *ctl, atm_t *atm)
Interpolate climatological data.
Definition: jurassic.c:123
void geo2cart(const double z, const double lon, const double lat, double *x)
Convert geolocation to Cartesian coordinates.
Definition: jurassic.c:3500
void kernel(ctl_t *ctl, atm_t *atm, obs_t *obs, gsl_matrix *k)
Compute Jacobians.
Definition: jurassic.c:4004
JURASSIC library declarations.
#define N
Maximum size of state vector.
Definition: jurassic.h:393
#define LEN
Maximum length of ASCII data lines.
Definition: jurassic.h:383
#define ERRMSG(...)
Print error message and quit program.
Definition: jurassic.h:237
#define IDXK(iw)
Indices for extinction.
Definition: jurassic.h:460
#define ND
Maximum number of radiance channels.
Definition: jurassic.h:353
#define TIMER(name, mode)
Start or stop a timer.
Definition: jurassic.h:201
#define IDXP
Index for pressure.
Definition: jurassic.h:451
#define NP
Maximum number of atmospheric data points.
Definition: jurassic.h:363
#define NG
Maximum number of emitters.
Definition: jurassic.h:358
#define DIST(a, b)
Compute Cartesian distance between two vectors.
Definition: jurassic.h:134
#define IDXQ(ig)
Indices for volume mixing ratios.
Definition: jurassic.h:457
#define NW
Maximum number of spectral windows.
Definition: jurassic.h:378
#define IDXT
Index for temperature.
Definition: jurassic.h:454
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:719
int main(int argc, char *argv[])
Definition: retrieval.c:283
#define NC(cmd)
Execute netCDF library command and check result.
Definition: retrieval.c:36
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:1028
void optimal_estimation(ret_t *ret, ctl_t *ctl, 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:764
void fill_gaps(double x[L2_NTRACK][L2_NXTRACK][L2_NLAY], double cx, double cy)
Fill data gaps in L2 data.
Definition: retrieval.c:587
#define L1_NXTRACK
Across-track size of AIRS radiance granule (don't change).
Definition: retrieval.c:53
#define L1_NTRACK
Along-track size of AIRS radiance granule (don't change).
Definition: retrieval.c:50
#define L2_NXTRACK
Across-track size of AIRS retrieval granule (don't change).
Definition: retrieval.c:62
void write_nc(char *filename, ncd_t *ncd)
Write to netCDF file...
Definition: retrieval.c:1170
void read_nc(char *filename, ncd_t *ncd)
Read netCDF file.
Definition: retrieval.c:948
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:503
#define L2_NLAY
Number of AIRS pressure layers (don't change).
Definition: retrieval.c:56
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:530
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:1127
void read_ret_ctl(int argc, char *argv[], ctl_t *ctl, ret_t *ret)
Read retrieval control parameters.
Definition: retrieval.c:987
void matrix_invert(gsl_matrix *a)
Invert symmetric matrix.
Definition: retrieval.c:689
#define L1_NCHAN
Number of AIRS radiance channels (don't change).
Definition: retrieval.c:47
#define L2_NTRACK
Along-track size of AIRS retrieval granule (don't change).
Definition: retrieval.c:59
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:553
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:632
Atmospheric data.
Definition: jurassic.h:488
double time[NP]
Time (seconds since 2000-01-01T00:00Z).
Definition: jurassic.h:494
double k[NW][NP]
Extinction [km^-1].
Definition: jurassic.h:515
double lat[NP]
Latitude [deg].
Definition: jurassic.h:503
double lon[NP]
Longitude [deg].
Definition: jurassic.h:500
double t[NP]
Temperature [K].
Definition: jurassic.h:509
int np
Number of data points.
Definition: jurassic.h:491
double z[NP]
Altitude [km].
Definition: jurassic.h:497
double q[NG][NP]
Volume mixing ratio [ppv].
Definition: jurassic.h:512
double p[NP]
Pressure [hPa].
Definition: jurassic.h:506
Forward model control parameters.
Definition: jurassic.h:541
int nw
Number of spectral windows.
Definition: jurassic.h:556
double nu[ND]
Centroid wavenumber of each channel [cm^-1].
Definition: jurassic.h:553
int ng
Number of emitters.
Definition: jurassic.h:544
int nd
Number of radiance channels.
Definition: jurassic.h:550
Buffer for netCDF data.
Definition: diff_apr.c:68
double l1_lat[L1_NTRACK][L1_NXTRACK]
Footprint latitude [deg].
Definition: diff_apr.c:83
float ret_p[L1_NTRACK *L1_NXTRACK]
Pressure [hPa].
Definition: diff_apr.c:113
double l1_lon[L1_NTRACK][L1_NXTRACK]
Footprint longitude [deg].
Definition: diff_apr.c:80
double l2_z[L2_NTRACK][L2_NXTRACK][L2_NLAY]
Altitude [km].
Definition: diff_apr.c:101
double l1_sat_lat[L1_NTRACK]
Satellite latitude [deg].
Definition: diff_apr.c:92
int ncid
NetCDF file ID.
Definition: diff_apr.c:71
int np
Number of retrieval altitudes.
Definition: diff_apr.c:74
double l1_sat_lon[L1_NTRACK]
Satellite longitude [deg].
Definition: diff_apr.c:89
float ret_z[NP]
Altitude [km].
Definition: diff_apr.c:110
double l2_p[L2_NLAY]
Pressure [hPa].
Definition: diff_apr.c:104
float ret_t[L1_NTRACK *L1_NXTRACK *NP]
Temperature [K].
Definition: diff_apr.c:116
double l2_t[L2_NTRACK][L2_NXTRACK][L2_NLAY]
Temperature [K].
Definition: diff_apr.c:107
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
Observation geometry and radiance data.
Definition: jurassic.h:734
double rad[ND][NR]
Radiance [W/(m^2 sr cm^-1)].
Definition: jurassic.h:773
double vplat[NR]
View point latitude [deg].
Definition: jurassic.h:758
double obslon[NR]
Observer longitude [deg].
Definition: jurassic.h:746
double obslat[NR]
Observer latitude [deg].
Definition: jurassic.h:749
double obsz[NR]
Observer altitude [km].
Definition: jurassic.h:743
double vplon[NR]
View point longitude [deg].
Definition: jurassic.h:755
double time[NR]
Time (seconds since 2000-01-01T00:00Z).
Definition: jurassic.h:740
int nr
Number of ray paths.
Definition: jurassic.h:737
Retrieval results.
Definition: libairs.h:237
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 conv_dmin
Minimum normalized step size in state space.
Definition: nlte.c:131
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
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
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
Emissivity look-up tables.
Definition: jurassic.h:778