JURASSIC
retrieval.c
Go to the documentation of this file.
1/*
2 This file is part of JURASSIC.
3
4 JURASSIC is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 JURASSIC is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with JURASSIC. If not, see <http://www.gnu.org/licenses/>.
16
17 Copyright (C) 2003-2025 Forschungszentrum Juelich GmbH
18*/
19
25#include "jurassic.h"
26
27/* ------------------------------------------------------------
28 Structs...
29 ------------------------------------------------------------ */
30
32typedef struct {
33
35 char dir[LEN];
36
39
42
44 double conv_dmin;
45
48
50 double err_formod[ND];
51
53 double err_noise[ND];
54
56 double err_press;
57
60
63
65 double err_temp;
66
69
72
74 double err_q[NG];
75
77 double err_q_cz[NG];
78
80 double err_q_ch[NG];
81
83 double err_k[NW];
84
86 double err_k_cz[NW];
87
89 double err_k_ch[NW];
90
92 double err_clz;
93
95 double err_cldz;
96
98 double err_clk[NCL];
99
101 double err_sft;
102
104 double err_sfeps[NSF];
105
106} ret_t;
107
108/* ------------------------------------------------------------
109 Functions...
110 ------------------------------------------------------------ */
111
113void analyze_avk(
114 ret_t * ret,
115 ctl_t * ctl,
116 atm_t * atm,
117 int *iqa,
118 int *ipa,
119 gsl_matrix * avk);
120
123 gsl_matrix * avk,
124 int iq,
125 int *ipa,
126 size_t *n0,
127 size_t *n1,
128 double *cont,
129 double *res);
130
132double cost_function(
133 gsl_vector * dx,
134 gsl_vector * dy,
135 gsl_matrix * s_a_inv,
136 gsl_vector * sig_eps_inv);
137
139void matrix_invert(
140 gsl_matrix * a);
141
143void matrix_product(
144 gsl_matrix * a,
145 gsl_vector * b,
146 int transpose,
147 gsl_matrix * c);
148
151 ret_t * ret,
152 ctl_t * ctl,
153 tbl_t * tbl,
154 obs_t * obs_meas,
155 obs_t * obs_i,
156 atm_t * atm_apr,
157 atm_t * atm_i);
158
160void read_ret(
161 int argc,
162 char *argv[],
163 ctl_t * ctl,
164 ret_t * ret);
165
167void set_cov_apr(
168 ret_t * ret,
169 ctl_t * ctl,
170 atm_t * atm,
171 int *iqa,
172 int *ipa,
173 gsl_matrix * s_a);
174
176void set_cov_meas(
177 ret_t * ret,
178 ctl_t * ctl,
179 obs_t * obs,
180 gsl_vector * sig_noise,
181 gsl_vector * sig_formod,
182 gsl_vector * sig_eps_inv);
183
185void write_stddev(
186 const char *quantity,
187 ret_t * ret,
188 ctl_t * ctl,
189 atm_t * atm,
190 gsl_matrix * s);
191
192/* ------------------------------------------------------------
193 Main...
194 ------------------------------------------------------------ */
195
197 int argc,
198 char *argv[]) {
199
200 static atm_t atm_i, atm_apr;
201 static ctl_t ctl;
202 static obs_t obs_i, obs_meas;
203 static ret_t ret;
204
205 FILE *dirlist;
206
207 /* Check arguments... */
208 if (argc < 3)
209 ERRMSG("Give parameters: <ctl> <dirlist>");
210
211 /* Measure CPU-time... */
212 TIMER("total", 1);
213
214 /* Read control parameters... */
215 read_ctl(argc, argv, &ctl);
216 read_ret(argc, argv, &ctl, &ret);
217
218 /* Initialize look-up tables... */
219 tbl_t *tbl = read_tbl(&ctl);
220
221 /* Open directory list... */
222 if (!(dirlist = fopen(argv[2], "r")))
223 ERRMSG("Cannot open directory list!");
224
225 /* Loop over directories... */
226 while (fscanf(dirlist, "%4999s", ret.dir) != EOF) {
227
228 /* Write info... */
229 LOG(1, "\nRetrieve in directory %s...\n", ret.dir);
230
231 /* Read atmospheric data... */
232 read_atm(ret.dir, "atm_apr.tab", &ctl, &atm_apr);
233
234 /* Read observation data... */
235 read_obs(ret.dir, "obs_meas.tab", &ctl, &obs_meas);
236
237 /* Run retrieval... */
238 optimal_estimation(&ret, &ctl, tbl, &obs_meas, &obs_i, &atm_apr, &atm_i);
239
240 /* Measure CPU-time... */
241 TIMER("total", 2);
242 }
243
244 /* Write info... */
245 LOG(1, "\nRetrieval done...");
246
247 /* Measure CPU-time... */
248 TIMER("total", 3);
249
250 /* Free... */
251 free(tbl);
252
253 return EXIT_SUCCESS;
254}
255
256/*****************************************************************************/
257
259 ret_t *ret,
260 ctl_t *ctl,
261 atm_t *atm,
262 int *iqa,
263 int *ipa,
264 gsl_matrix *avk) {
265
266 static atm_t atm_cont, atm_res;
267
268 size_t i, n0[NQ], n1[NQ];
269
270 /* Get sizes... */
271 const size_t n = avk->size1;
272
273 /* Find sub-matrices for different quantities... */
274 for (int iq = 0; iq < NQ; iq++) {
275 n0[iq] = N;
276 for (i = 0; i < n; i++) {
277 if (iqa[i] == iq && n0[iq] == N)
278 n0[iq] = i;
279 if (iqa[i] == iq)
280 n1[iq] = i - n0[iq] + 1;
281 }
282 }
283
284 /* Initialize... */
285 copy_atm(ctl, &atm_cont, atm, 1);
286 copy_atm(ctl, &atm_res, atm, 1);
287
288 /* Analyze quantities... */
289 analyze_avk_quantity(avk, IDXP, ipa, n0, n1, atm_cont.p, atm_res.p);
290 analyze_avk_quantity(avk, IDXT, ipa, n0, n1, atm_cont.t, atm_res.t);
291 for (int ig = 0; ig < ctl->ng; ig++)
292 analyze_avk_quantity(avk, IDXQ(ig), ipa, n0, n1,
293 atm_cont.q[ig], atm_res.q[ig]);
294 for (int iw = 0; iw < ctl->nw; iw++)
295 analyze_avk_quantity(avk, IDXK(iw), ipa, n0, n1,
296 atm_cont.k[iw], atm_res.k[iw]);
297 analyze_avk_quantity(avk, IDXCLZ, ipa, n0, n1, &atm_cont.clz, &atm_res.clz);
298 analyze_avk_quantity(avk, IDXCLDZ, ipa, n0, n1, &atm_cont.cldz,
299 &atm_res.cldz);
300 for (int icl = 0; icl < ctl->ncl; icl++)
301 analyze_avk_quantity(avk, IDXCLK(icl), ipa, n0, n1,
302 &atm_cont.clk[icl], &atm_res.clk[icl]);
303 analyze_avk_quantity(avk, IDXSFT, ipa, n0, n1, &atm_cont.sft, &atm_res.sft);
304 for (int isf = 0; isf < ctl->nsf; isf++)
305 analyze_avk_quantity(avk, IDXSFEPS(isf), ipa, n0, n1,
306 &atm_cont.sfeps[isf], &atm_res.sfeps[isf]);
307
308 /* Write results to disk... */
309 write_atm(ret->dir, "atm_cont.tab", ctl, &atm_cont);
310 write_atm(ret->dir, "atm_res.tab", ctl, &atm_res);
311}
312
313/*****************************************************************************/
314
316 gsl_matrix *avk,
317 int iq,
318 int *ipa,
319 size_t *n0,
320 size_t *n1,
321 double *cont,
322 double *res) {
323
324 /* Loop over state vector elements... */
325 if (n0[iq] < N)
326 for (size_t i = 0; i < n1[iq]; i++) {
327
328 /* Get area of averaging kernel... */
329 for (size_t j = 0; j < n1[iq]; j++)
330 cont[ipa[n0[iq] + i]] += gsl_matrix_get(avk, n0[iq] + i, n0[iq] + j);
331
332 /* Get information density... */
333 res[ipa[n0[iq] + i]] = 1 / gsl_matrix_get(avk, n0[iq] + i, n0[iq] + i);
334 }
335}
336
337/*****************************************************************************/
338
340 gsl_vector *dx,
341 gsl_vector *dy,
342 gsl_matrix *s_a_inv,
343 gsl_vector *sig_eps_inv) {
344
345 double chisq_a, chisq_m = 0;
346
347 /* Get sizes... */
348 const size_t m = dy->size;
349 const size_t n = dx->size;
350
351 /* Allocate... */
352 gsl_vector *x_aux = gsl_vector_alloc(n);
353 gsl_vector *y_aux = gsl_vector_alloc(m);
354
355 /* Determine normalized cost function...
356 (chi^2 = 1/m * [dy^T * S_eps^{-1} * dy + dx^T * S_a^{-1} * dx]) */
357 for (size_t i = 0; i < m; i++)
358 chisq_m += POW2(gsl_vector_get(dy, i) * gsl_vector_get(sig_eps_inv, i));
359 gsl_blas_dgemv(CblasNoTrans, 1.0, s_a_inv, dx, 0.0, x_aux);
360 gsl_blas_ddot(dx, x_aux, &chisq_a);
361
362 /* Free... */
363 gsl_vector_free(x_aux);
364 gsl_vector_free(y_aux);
365
366 /* Return cost function value... */
367 return (chisq_m + chisq_a) / (double) m;
368}
369
370/*****************************************************************************/
371
373 gsl_matrix *a) {
374
375 size_t diag = 1;
376
377 /* Get size... */
378 const size_t n = a->size1;
379
380 /* Check if matrix is diagonal... */
381 for (size_t i = 0; i < n && diag; i++)
382 for (size_t j = i + 1; j < n; j++)
383 if (gsl_matrix_get(a, i, j) != 0) {
384 diag = 0;
385 break;
386 }
387
388 /* Quick inversion of diagonal matrix... */
389 if (diag)
390 for (size_t i = 0; i < n; i++)
391 gsl_matrix_set(a, i, i, 1 / gsl_matrix_get(a, i, i));
392
393 /* Matrix inversion by means of Cholesky decomposition... */
394 else {
395 gsl_linalg_cholesky_decomp(a);
396 gsl_linalg_cholesky_invert(a);
397 }
398}
399
400/*****************************************************************************/
401
403 gsl_matrix *a,
404 gsl_vector *b,
405 int transpose,
406 gsl_matrix *c) {
407
408 /* Set sizes... */
409 const size_t m = a->size1;
410 const size_t n = a->size2;
411
412 /* Allocate... */
413 gsl_matrix *aux = gsl_matrix_alloc(m, n);
414
415 /* Compute A^T B A... */
416 if (transpose == 1) {
417
418 /* Compute B^1/2 A... */
419 for (size_t i = 0; i < m; i++)
420 for (size_t j = 0; j < n; j++)
421 gsl_matrix_set(aux, i, j,
422 gsl_vector_get(b, i) * gsl_matrix_get(a, i, j));
423
424 /* Compute A^T B A = (B^1/2 A)^T (B^1/2 A)... */
425 gsl_blas_dgemm(CblasTrans, CblasNoTrans, 1.0, aux, aux, 0.0, c);
426 }
427
428 /* Compute A B A^T... */
429 else if (transpose == 2) {
430
431 /* Compute A B^1/2... */
432 for (size_t i = 0; i < m; i++)
433 for (size_t j = 0; j < n; j++)
434 gsl_matrix_set(aux, i, j,
435 gsl_matrix_get(a, i, j) * gsl_vector_get(b, j));
436
437 /* Compute A B A^T = (A B^1/2) (A B^1/2)^T... */
438 gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1.0, aux, aux, 0.0, c);
439 }
440
441 /* Free... */
442 gsl_matrix_free(aux);
443}
444
445/*****************************************************************************/
446
448 ret_t *ret,
449 ctl_t *ctl,
450 tbl_t *tbl,
451 obs_t *obs_meas,
452 obs_t *obs_i,
453 atm_t *atm_apr,
454 atm_t *atm_i) {
455
456 static int ipa[N], iqa[N];
457
458 FILE *out;
459
460 char filename[2 * LEN];
461
462 double chisq, disq = 0, lmpar = 0.001;
463
464 int it = 0;
465
466 /* ------------------------------------------------------------
467 Initialize...
468 ------------------------------------------------------------ */
469
470 /* Get sizes... */
471 const size_t m = obs2y(ctl, obs_meas, NULL, NULL, NULL);
472 const size_t n = atm2x(ctl, atm_apr, NULL, iqa, ipa);
473 if (m == 0 || n == 0)
474 ERRMSG("Check problem definition!");
475
476 /* Write info... */
477 LOG(1, "Problem size: m= %d / n= %d "
478 "(alloc= %.4g MB / stat= %.4g MB)",
479 (int) m, (int) n,
480 (double) (3 * m * n + 4 * n * n + 8 * m +
481 8 * n) * sizeof(double) / 1024. / 1024.,
482 (double) (5 * sizeof(atm_t) + 3 * sizeof(obs_t)
483 + 2 * N * sizeof(int)) / 1024. / 1024.);
484
485 /* Allocate... */
486 gsl_matrix *a = gsl_matrix_alloc(n, n);
487 gsl_matrix *cov = gsl_matrix_alloc(n, n);
488 gsl_matrix *k_i = gsl_matrix_alloc(m, n);
489 gsl_matrix *s_a_inv = gsl_matrix_alloc(n, n);
490
491 gsl_vector *b = gsl_vector_alloc(n);
492 gsl_vector *dx = gsl_vector_alloc(n);
493 gsl_vector *dy = gsl_vector_alloc(m);
494 gsl_vector *sig_eps_inv = gsl_vector_alloc(m);
495 gsl_vector *sig_formod = gsl_vector_alloc(m);
496 gsl_vector *sig_noise = gsl_vector_alloc(m);
497 gsl_vector *x_a = gsl_vector_alloc(n);
498 gsl_vector *x_i = gsl_vector_alloc(n);
499 gsl_vector *x_step = gsl_vector_alloc(n);
500 gsl_vector *y_aux = gsl_vector_alloc(m);
501 gsl_vector *y_i = gsl_vector_alloc(m);
502 gsl_vector *y_m = gsl_vector_alloc(m);
503
504 /* Set initial state... */
505 copy_atm(ctl, atm_i, atm_apr, 0);
506 copy_obs(ctl, obs_i, obs_meas, 0);
507 formod(ctl, tbl, atm_i, obs_i);
508
509 /* Set state vectors and observation vectors... */
510 atm2x(ctl, atm_apr, x_a, NULL, NULL);
511 atm2x(ctl, atm_i, x_i, NULL, NULL);
512 obs2y(ctl, obs_meas, y_m, NULL, NULL);
513 obs2y(ctl, obs_i, y_i, NULL, NULL);
514
515 /* Set inverse a priori covariance S_a^-1... */
516 set_cov_apr(ret, ctl, atm_apr, iqa, ipa, s_a_inv);
517 write_matrix(ret->dir, "matrix_cov_apr.tab", ctl, s_a_inv,
518 atm_i, obs_i, "x", "x", "r");
519 matrix_invert(s_a_inv);
520
521 /* Get measurement errors... */
522 set_cov_meas(ret, ctl, obs_meas, sig_noise, sig_formod, sig_eps_inv);
523
524 /* Create cost function file... */
525 sprintf(filename, "%s/costs.tab", ret->dir);
526 if (!(out = fopen(filename, "w")))
527 ERRMSG("Cannot create cost function file!");
528
529 /* Write header... */
530 fprintf(out,
531 "# $1 = iteration number\n"
532 "# $2 = normalized cost function\n"
533 "# $3 = number of measurements\n"
534 "# $4 = number of state vector elements\n\n");
535
536 /* Determine dx = x_i - x_a and dy = y - F(x_i) ... */
537 gsl_vector_memcpy(dx, x_i);
538 gsl_vector_sub(dx, x_a);
539 gsl_vector_memcpy(dy, y_m);
540 gsl_vector_sub(dy, y_i);
541
542 /* Compute cost function... */
543 chisq = cost_function(dx, dy, s_a_inv, sig_eps_inv);
544
545 /* Write info... */
546 LOG(1, "it= %d / chi^2/m= %g", it, chisq);
547
548 /* Write to cost function file... */
549 fprintf(out, "%d %g %d %d\n", it, chisq, (int) m, (int) n);
550
551 /* Compute initial kernel... */
552 kernel(ctl, tbl, atm_i, obs_i, k_i);
553
554 /* ------------------------------------------------------------
555 Levenberg-Marquardt minimization...
556 ------------------------------------------------------------ */
557
558 /* Outer loop... */
559 for (it = 1; it <= ret->conv_itmax; it++) {
560
561 /* Store current cost function value... */
562 double chisq_old = chisq;
563
564 /* Compute kernel matrix K_i... */
565 if (it > 1 && it % ret->kernel_recomp == 0)
566 kernel(ctl, tbl, atm_i, obs_i, k_i);
567
568 /* Compute K_i^T * S_eps^{-1} * K_i ... */
569 if (it == 1 || it % ret->kernel_recomp == 0)
570 matrix_product(k_i, sig_eps_inv, 1, cov);
571
572 /* Determine b = K_i^T * S_eps^{-1} * dy - S_a^{-1} * dx ... */
573 for (size_t i = 0; i < m; i++)
574 gsl_vector_set(y_aux, i, gsl_vector_get(dy, i)
575 * POW2(gsl_vector_get(sig_eps_inv, i)));
576 gsl_blas_dgemv(CblasTrans, 1.0, k_i, y_aux, 0.0, b);
577 gsl_blas_dgemv(CblasNoTrans, -1.0, s_a_inv, dx, 1.0, b);
578
579 /* Inner loop... */
580 for (int it2 = 0; it2 < 20; it2++) {
581
582 /* Compute A = (1 + lmpar) * S_a^{-1} + K_i^T * S_eps^{-1} * K_i ... */
583 gsl_matrix_memcpy(a, s_a_inv);
584 gsl_matrix_scale(a, 1 + lmpar);
585 gsl_matrix_add(a, cov);
586
587 /* Solve A * x_step = b by means of Cholesky decomposition... */
588 gsl_linalg_cholesky_decomp(a);
589 gsl_linalg_cholesky_solve(a, b, x_step);
590
591 /* Update atmospheric state... */
592 gsl_vector_add(x_i, x_step);
593 copy_atm(ctl, atm_i, atm_apr, 0);
594 copy_obs(ctl, obs_i, obs_meas, 0);
595 x2atm(ctl, x_i, atm_i);
596
597 /* Check atmospheric state... */
598 for (int ip = 0; ip < atm_i->np; ip++) {
599 atm_i->p[ip] = MIN(MAX(atm_i->p[ip], 5e-7), 5e4);
600 atm_i->t[ip] = MIN(MAX(atm_i->t[ip], 100), 400);
601 for (int ig = 0; ig < ctl->ng; ig++)
602 atm_i->q[ig][ip] = MIN(MAX(atm_i->q[ig][ip], 0), 1);
603 for (int iw = 0; iw < ctl->nw; iw++)
604 atm_i->k[iw][ip] = MAX(atm_i->k[iw][ip], 0);
605 }
606 atm_i->clz = MAX(atm_i->clz, 0);
607 atm_i->cldz = MAX(atm_i->cldz, 0.1);
608 for (int icl = 0; icl < ctl->ncl; icl++)
609 atm_i->clk[icl] = MAX(atm_i->clk[icl], 0);
610 atm_i->sft = MIN(MAX(atm_i->sft, 100), 400);
611 for (int isf = 0; isf < ctl->nsf; isf++)
612 atm_i->sfeps[isf] = MIN(MAX(atm_i->sfeps[isf], 0), 1);
613
614 /* Forward calculation... */
615 formod(ctl, tbl, atm_i, obs_i);
616 obs2y(ctl, obs_i, y_i, NULL, NULL);
617
618 /* Determine dx = x_i - x_a and dy = y - F(x_i) ... */
619 gsl_vector_memcpy(dx, x_i);
620 gsl_vector_sub(dx, x_a);
621 gsl_vector_memcpy(dy, y_m);
622 gsl_vector_sub(dy, y_i);
623
624 /* Compute cost function... */
625 chisq = cost_function(dx, dy, s_a_inv, sig_eps_inv);
626
627 /* Modify Levenberg-Marquardt parameter... */
628 if (chisq > chisq_old) {
629 lmpar *= 10;
630 gsl_vector_sub(x_i, x_step);
631 } else {
632 lmpar /= 10;
633 break;
634 }
635 }
636
637 /* Write info... */
638 LOG(1, "it= %d / chi^2/m= %g", it, chisq);
639
640 /* Write to cost function file... */
641 fprintf(out, "%d %g %d %d\n", it, chisq, (int) m, (int) n);
642
643 /* Get normalized step size in state space... */
644 gsl_blas_ddot(x_step, b, &disq);
645 disq /= (double) n;
646
647 /* Convergence test... */
648 if ((it == 1 || it % ret->kernel_recomp == 0) && disq < ret->conv_dmin)
649 break;
650 }
651
652 /* Close cost function file... */
653 fclose(out);
654
655 /* Store results... */
656 write_atm(ret->dir, "atm_final.tab", ctl, atm_i);
657 write_obs(ret->dir, "obs_final.tab", ctl, obs_i);
658 write_matrix(ret->dir, "matrix_kernel.tab", ctl, k_i,
659 atm_i, obs_i, "y", "x", "r");
660
661 /* ------------------------------------------------------------
662 Analysis of retrieval results...
663 ------------------------------------------------------------ */
664
665 /* Check if error analysis is requested... */
666 if (ret->err_ana) {
667
668 /* Allocate... */
669 gsl_matrix *auxnm = gsl_matrix_alloc(n, m);
670 gsl_matrix *corr = gsl_matrix_alloc(n, n);
671 gsl_matrix *gain = gsl_matrix_alloc(n, m);
672
673 /* Compute inverse retrieval covariance...
674 cov^{-1} = S_a^{-1} + K_i^T * S_eps^{-1} * K_i */
675 matrix_product(k_i, sig_eps_inv, 1, cov);
676 gsl_matrix_add(cov, s_a_inv);
677
678 /* Compute retrieval covariance... */
679 matrix_invert(cov);
680 write_matrix(ret->dir, "matrix_cov_ret.tab", ctl, cov,
681 atm_i, obs_i, "x", "x", "r");
682 write_stddev("total", ret, ctl, atm_i, cov);
683
684 /* Compute correlation matrix... */
685 for (size_t i = 0; i < n; i++)
686 for (size_t j = 0; j < n; j++)
687 gsl_matrix_set(corr, i, j, gsl_matrix_get(cov, i, j)
688 / sqrt(gsl_matrix_get(cov, i, i))
689 / sqrt(gsl_matrix_get(cov, j, j)));
690 write_matrix(ret->dir, "matrix_corr.tab", ctl, corr,
691 atm_i, obs_i, "x", "x", "r");
692
693 /* Compute gain matrix...
694 G = cov * K^T * S_eps^{-1} */
695 for (size_t i = 0; i < n; i++)
696 for (size_t j = 0; j < m; j++)
697 gsl_matrix_set(auxnm, i, j, gsl_matrix_get(k_i, j, i)
698 * POW2(gsl_vector_get(sig_eps_inv, j)));
699 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, cov, auxnm, 0.0, gain);
700 write_matrix(ret->dir, "matrix_gain.tab", ctl, gain,
701 atm_i, obs_i, "x", "y", "c");
702
703 /* Compute retrieval error due to noise... */
704 matrix_product(gain, sig_noise, 2, a);
705 write_stddev("noise", ret, ctl, atm_i, a);
706
707 /* Compute retrieval error due to forward model errors... */
708 matrix_product(gain, sig_formod, 2, a);
709 write_stddev("formod", ret, ctl, atm_i, a);
710
711 /* Compute averaging kernel matrix
712 A = G * K ... */
713 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, gain, k_i, 0.0, a);
714 write_matrix(ret->dir, "matrix_avk.tab", ctl, a,
715 atm_i, obs_i, "x", "x", "r");
716
717 /* Analyze averaging kernel matrix... */
718 analyze_avk(ret, ctl, atm_i, iqa, ipa, a);
719
720 /* Free... */
721 gsl_matrix_free(auxnm);
722 gsl_matrix_free(corr);
723 gsl_matrix_free(gain);
724 }
725
726 /* ------------------------------------------------------------
727 Finalize...
728 ------------------------------------------------------------ */
729
730 gsl_matrix_free(a);
731 gsl_matrix_free(cov);
732 gsl_matrix_free(k_i);
733 gsl_matrix_free(s_a_inv);
734
735 gsl_vector_free(b);
736 gsl_vector_free(dx);
737 gsl_vector_free(dy);
738 gsl_vector_free(sig_eps_inv);
739 gsl_vector_free(sig_formod);
740 gsl_vector_free(sig_noise);
741 gsl_vector_free(x_a);
742 gsl_vector_free(x_i);
743 gsl_vector_free(x_step);
744 gsl_vector_free(y_aux);
745 gsl_vector_free(y_i);
746 gsl_vector_free(y_m);
747}
748
749/*****************************************************************************/
750
752 int argc,
753 char *argv[],
754 ctl_t *ctl,
755 ret_t *ret) {
756
757 /* Iteration control... */
758 ret->kernel_recomp =
759 (int) scan_ctl(argc, argv, "KERNEL_RECOMP", -1, "3", NULL);
760 ret->conv_itmax = (int) scan_ctl(argc, argv, "CONV_ITMAX", -1, "30", NULL);
761 ret->conv_dmin = scan_ctl(argc, argv, "CONV_DMIN", -1, "0.1", NULL);
762
763 /* Error analysis... */
764 ret->err_ana = (int) scan_ctl(argc, argv, "ERR_ANA", -1, "1", NULL);
765
766 for (int id = 0; id < ctl->nd; id++)
767 ret->err_formod[id] = scan_ctl(argc, argv, "ERR_FORMOD", id, "0", NULL);
768
769 for (int id = 0; id < ctl->nd; id++)
770 ret->err_noise[id] = scan_ctl(argc, argv, "ERR_NOISE", id, "0", NULL);
771
772 ret->err_press = scan_ctl(argc, argv, "ERR_PRESS", -1, "0", NULL);
773 ret->err_press_cz = scan_ctl(argc, argv, "ERR_PRESS_CZ", -1, "-999", NULL);
774 ret->err_press_ch = scan_ctl(argc, argv, "ERR_PRESS_CH", -1, "-999", NULL);
775
776 ret->err_temp = scan_ctl(argc, argv, "ERR_TEMP", -1, "0", NULL);
777 ret->err_temp_cz = scan_ctl(argc, argv, "ERR_TEMP_CZ", -1, "-999", NULL);
778 ret->err_temp_ch = scan_ctl(argc, argv, "ERR_TEMP_CH", -1, "-999", NULL);
779
780 for (int ig = 0; ig < ctl->ng; ig++) {
781 ret->err_q[ig] = scan_ctl(argc, argv, "ERR_Q", ig, "0", NULL);
782 ret->err_q_cz[ig] = scan_ctl(argc, argv, "ERR_Q_CZ", ig, "-999", NULL);
783 ret->err_q_ch[ig] = scan_ctl(argc, argv, "ERR_Q_CH", ig, "-999", NULL);
784 }
785
786 for (int iw = 0; iw < ctl->nw; iw++) {
787 ret->err_k[iw] = scan_ctl(argc, argv, "ERR_K", iw, "0", NULL);
788 ret->err_k_cz[iw] = scan_ctl(argc, argv, "ERR_K_CZ", iw, "-999", NULL);
789 ret->err_k_ch[iw] = scan_ctl(argc, argv, "ERR_K_CH", iw, "-999", NULL);
790 }
791
792 ret->err_clz = scan_ctl(argc, argv, "ERR_CLZ", -1, "0", NULL);
793 ret->err_cldz = scan_ctl(argc, argv, "ERR_CLDZ", -1, "0", NULL);
794 for (int icl = 0; icl < ctl->ncl; icl++)
795 ret->err_clk[icl] = scan_ctl(argc, argv, "ERR_CLK", icl, "0", NULL);
796
797 ret->err_sft = scan_ctl(argc, argv, "ERR_SFT", -1, "0", NULL);
798 for (int isf = 0; isf < ctl->nsf; isf++)
799 ret->err_sfeps[isf] = scan_ctl(argc, argv, "ERR_SFEPS", isf, "0", NULL);
800}
801
802/*****************************************************************************/
803
805 ret_t *ret,
806 ctl_t *ctl,
807 atm_t *atm,
808 int *iqa,
809 int *ipa,
810 gsl_matrix *s_a) {
811
812 double x0[3], x1[3];
813
814 /* Get sizes... */
815 const size_t n = s_a->size1;
816
817 /* Allocate... */
818 gsl_vector *x_a = gsl_vector_alloc(n);
819
820 /* Get sigma vector... */
821 atm2x(ctl, atm, x_a, NULL, NULL);
822 for (size_t i = 0; i < n; i++) {
823 if (iqa[i] == IDXP)
824 gsl_vector_set(x_a, i, ret->err_press / 100 * gsl_vector_get(x_a, i));
825 if (iqa[i] == IDXT)
826 gsl_vector_set(x_a, i, ret->err_temp);
827 for (int ig = 0; ig < ctl->ng; ig++)
828 if (iqa[i] == IDXQ(ig))
829 gsl_vector_set(x_a, i, ret->err_q[ig] / 100 * gsl_vector_get(x_a, i));
830 for (int iw = 0; iw < ctl->nw; iw++)
831 if (iqa[i] == IDXK(iw))
832 gsl_vector_set(x_a, i, ret->err_k[iw]);
833 if (iqa[i] == IDXCLZ)
834 gsl_vector_set(x_a, i, ret->err_clz);
835 if (iqa[i] == IDXCLDZ)
836 gsl_vector_set(x_a, i, ret->err_cldz);
837 for (int icl = 0; icl < ctl->ncl; icl++)
838 if (iqa[i] == IDXCLK(icl))
839 gsl_vector_set(x_a, i, ret->err_clk[icl]);
840 if (iqa[i] == IDXSFT)
841 gsl_vector_set(x_a, i, ret->err_sft);
842 for (int isf = 0; isf < ctl->nsf; isf++)
843 if (iqa[i] == IDXSFEPS(isf))
844 gsl_vector_set(x_a, i, ret->err_sfeps[isf]);
845 }
846
847 /* Check standard deviations... */
848 for (size_t i = 0; i < n; i++)
849 if (POW2(gsl_vector_get(x_a, i)) <= 0)
850 ERRMSG("Check a priori data (zero standard deviation)!");
851
852 /* Initialize diagonal covariance... */
853 gsl_matrix_set_zero(s_a);
854 for (size_t i = 0; i < n; i++)
855 gsl_matrix_set(s_a, i, i, POW2(gsl_vector_get(x_a, i)));
856
857 /* Loop over matrix elements... */
858 for (size_t i = 0; i < n; i++)
859 for (size_t j = 0; j < n; j++)
860 if (i != j && iqa[i] == iqa[j]) {
861
862 /* Initialize... */
863 double cz = 0;
864 double ch = 0;
865
866 /* Set correlation lengths for pressure... */
867 if (iqa[i] == IDXP) {
868 cz = ret->err_press_cz;
869 ch = ret->err_press_ch;
870 }
871
872 /* Set correlation lengths for temperature... */
873 if (iqa[i] == IDXT) {
874 cz = ret->err_temp_cz;
875 ch = ret->err_temp_ch;
876 }
877
878 /* Set correlation lengths for volume mixing ratios... */
879 for (int ig = 0; ig < ctl->ng; ig++)
880 if (iqa[i] == IDXQ(ig)) {
881 cz = ret->err_q_cz[ig];
882 ch = ret->err_q_ch[ig];
883 }
884
885 /* Set correlation lengths for extinction... */
886 for (int iw = 0; iw < ctl->nw; iw++)
887 if (iqa[i] == IDXK(iw)) {
888 cz = ret->err_k_cz[iw];
889 ch = ret->err_k_ch[iw];
890 }
891
892 /* Compute correlations... */
893 if (cz > 0 && ch > 0) {
894
895 /* Get Cartesian coordinates... */
896 geo2cart(0, atm->lon[ipa[i]], atm->lat[ipa[i]], x0);
897 geo2cart(0, atm->lon[ipa[j]], atm->lat[ipa[j]], x1);
898
899 /* Compute correlations... */
900 double rho =
901 exp(-DIST(x0, x1) / ch -
902 fabs(atm->z[ipa[i]] - atm->z[ipa[j]]) / cz);
903
904 /* Set covariance... */
905 gsl_matrix_set(s_a, i, j, gsl_vector_get(x_a, i)
906 * gsl_vector_get(x_a, j) * rho);
907 }
908 }
909
910 /* Free... */
911 gsl_vector_free(x_a);
912}
913
914/*****************************************************************************/
915
917 ret_t *ret,
918 ctl_t *ctl,
919 obs_t *obs,
920 gsl_vector *sig_noise,
921 gsl_vector *sig_formod,
922 gsl_vector *sig_eps_inv) {
923
924 static obs_t obs_err;
925
926 /* Get size... */
927 const size_t m = sig_eps_inv->size;
928
929 /* Noise error (always considered in retrieval fit)... */
930 copy_obs(ctl, &obs_err, obs, 1);
931 for (int ir = 0; ir < obs_err.nr; ir++)
932 for (int id = 0; id < ctl->nd; id++)
933 obs_err.rad[id][ir]
934 = (isfinite(obs->rad[id][ir]) ? ret->err_noise[id] : NAN);
935 obs2y(ctl, &obs_err, sig_noise, NULL, NULL);
936
937 /* Forward model error (always considered in retrieval fit)... */
938 copy_obs(ctl, &obs_err, obs, 1);
939 for (int ir = 0; ir < obs_err.nr; ir++)
940 for (int id = 0; id < ctl->nd; id++)
941 obs_err.rad[id][ir]
942 = fabs(ret->err_formod[id] / 100 * obs->rad[id][ir]);
943 obs2y(ctl, &obs_err, sig_formod, NULL, NULL);
944
945 /* Total error... */
946 for (size_t i = 0; i < m; i++)
947 gsl_vector_set(sig_eps_inv, i, 1 / sqrt(POW2(gsl_vector_get(sig_noise, i))
948 +
949 POW2(gsl_vector_get
950 (sig_formod, i))));
951
952 /* Check standard deviations... */
953 for (size_t i = 0; i < m; i++)
954 if (gsl_vector_get(sig_eps_inv, i) <= 0)
955 ERRMSG("Check measurement errors (zero standard deviation)!");
956}
957
958/*****************************************************************************/
959
961 const char *quantity,
962 ret_t *ret,
963 ctl_t *ctl,
964 atm_t *atm,
965 gsl_matrix *s) {
966
967 static atm_t atm_aux;
968
969 char filename[LEN];
970
971 /* Get sizes... */
972 const size_t n = s->size1;
973
974 /* Allocate... */
975 gsl_vector *x_aux = gsl_vector_alloc(n);
976
977 /* Compute standard deviation... */
978 for (size_t i = 0; i < n; i++)
979 gsl_vector_set(x_aux, i, sqrt(gsl_matrix_get(s, i, i)));
980
981 /* Write to disk... */
982 copy_atm(ctl, &atm_aux, atm, 1);
983 x2atm(ctl, x_aux, &atm_aux);
984 sprintf(filename, "atm_err_%s.tab", quantity);
985 write_atm(ret->dir, filename, ctl, &atm_aux);
986
987 /* Free... */
988 gsl_vector_free(x_aux);
989}
void write_atm(const char *dirname, const char *filename, const ctl_t *ctl, const atm_t *atm)
Write atmospheric data.
Definition: jurassic.c:5470
void read_ctl(int argc, char *argv[], ctl_t *ctl)
Read forward model control parameters.
Definition: jurassic.c:4658
void x2atm(const ctl_t *ctl, const gsl_vector *x, atm_t *atm)
Decompose parameter vector or state vector.
Definition: jurassic.c:6029
void read_atm(const char *dirname, const char *filename, const ctl_t *ctl, atm_t *atm)
Read atmospheric data.
Definition: jurassic.c:4556
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:3153
void read_obs(const char *dirname, const char *filename, const ctl_t *ctl, obs_t *obs)
Read observation data.
Definition: jurassic.c:4812
void write_obs(const char *dirname, const char *filename, const ctl_t *ctl, const obs_t *obs)
Write observation data.
Definition: jurassic.c:5803
void kernel(const ctl_t *ctl, const tbl_t *tbl, atm_t *atm, obs_t *obs, gsl_matrix *k)
Compute Jacobians.
Definition: jurassic.c:4128
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.
Definition: jurassic.c:5248
void formod(const ctl_t *ctl, const tbl_t *tbl, atm_t *atm, obs_t *obs)
Determine ray paths and compute radiative transfer.
Definition: jurassic.c:3204
tbl_t * read_tbl(const ctl_t *ctl)
Read look-up table data.
Definition: jurassic.c:5074
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:3103
size_t obs2y(const ctl_t *ctl, const obs_t *obs, gsl_vector *y, int *ida, int *ira)
Compose measurement vector.
Definition: jurassic.c:4294
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 geo2cart(const double z, const double lon, const double lat, double *x)
Convert geolocation to Cartesian coordinates.
Definition: jurassic.c:3648
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.
Definition: jurassic.c:5625
JURASSIC library declarations.
#define N
Maximum size of state vector.
Definition: jurassic.h:404
#define IDXCLZ
Index for cloud layer height.
Definition: jurassic.h:469
#define LEN
Maximum length of ASCII data lines.
Definition: jurassic.h:394
#define POW2(x)
Compute x^2.
Definition: jurassic.h:188
#define MIN(a, b)
Macro to determine the minimum of two values.
Definition: jurassic.h:161
#define IDXCLDZ
Index for cloud layer depth.
Definition: jurassic.h:472
#define ERRMSG(...)
Print error message and quit program.
Definition: jurassic.h:238
#define IDXK(iw)
Indices for extinction.
Definition: jurassic.h:466
#define NQ
Maximum number of quantities.
Definition: jurassic.h:409
#define ND
Maximum number of radiance channels.
Definition: jurassic.h:364
#define IDXSFT
Index for surface layer temperature.
Definition: jurassic.h:484
#define IDXSFEPS(isf)
Indices for surface layer emissivity.
Definition: jurassic.h:487
#define IDXCLK(icl)
Indices for cloud layer extinction.
Definition: jurassic.h:475
#define TIMER(name, mode)
Start or stop a timer.
Definition: jurassic.h:202
#define IDXP
Index for pressure.
Definition: jurassic.h:457
#define NG
Maximum number of emitters.
Definition: jurassic.h:369
#define LOG(level,...)
Print log message.
Definition: jurassic.h:222
#define NSF
Maximum number of surface layer spectral grid points.
Definition: jurassic.h:384
#define NCL
Maximum number of cloud layer spectral grid points.
Definition: jurassic.h:359
#define DIST(a, b)
Compute Cartesian distance between two vectors.
Definition: jurassic.h:135
#define IDXQ(ig)
Indices for volume mixing ratios.
Definition: jurassic.h:463
#define NW
Maximum number of spectral windows.
Definition: jurassic.h:389
#define MAX(a, b)
Macro to determine the maximum of two values.
Definition: jurassic.h:157
#define IDXT
Index for temperature.
Definition: jurassic.h:460
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:402
int main(int argc, char *argv[])
Definition: retrieval.c:196
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:804
void analyze_avk(ret_t *ret, ctl_t *ctl, atm_t *atm, int *iqa, int *ipa, gsl_matrix *avk)
Compute information content and resolution.
Definition: retrieval.c:258
void read_ret(int argc, char *argv[], ctl_t *ctl, ret_t *ret)
Read retrieval control parameters.
Definition: retrieval.c:751
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:916
void write_stddev(const char *quantity, ret_t *ret, ctl_t *ctl, atm_t *atm, gsl_matrix *s)
Write retrieval error to file.
Definition: retrieval.c:960
void matrix_invert(gsl_matrix *a)
Invert symmetric matrix.
Definition: retrieval.c:372
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)
Carry out optimal estimation retrieval.
Definition: retrieval.c:447
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:339
void analyze_avk_quantity(gsl_matrix *avk, int iq, int *ipa, size_t *n0, size_t *n1, double *cont, double *res)
Analyze averaging kernels for individual retrieval target.
Definition: retrieval.c:315
Atmospheric data.
Definition: jurassic.h:494
double sfeps[NSF]
Surface emissivity.
Definition: jurassic.h:542
double k[NW][NP]
Extinction [km^-1].
Definition: jurassic.h:521
double lat[NP]
Latitude [deg].
Definition: jurassic.h:509
double lon[NP]
Longitude [deg].
Definition: jurassic.h:506
double t[NP]
Temperature [K].
Definition: jurassic.h:515
double clz
Cloud layer height [km].
Definition: jurassic.h:524
int np
Number of data points.
Definition: jurassic.h:497
double cldz
Cloud layer depth [km].
Definition: jurassic.h:527
double sft
Surface temperature [K].
Definition: jurassic.h:539
double z[NP]
Altitude [km].
Definition: jurassic.h:503
double clk[NCL]
Cloud layer extinction [km^-1].
Definition: jurassic.h:530
double q[NG][NP]
Volume mixing ratio [ppv].
Definition: jurassic.h:518
double p[NP]
Pressure [hPa].
Definition: jurassic.h:512
Forward model control parameters.
Definition: jurassic.h:547
int nw
Number of spectral windows.
Definition: jurassic.h:574
int ng
Number of emitters.
Definition: jurassic.h:550
int nd
Number of radiance channels.
Definition: jurassic.h:568
int ncl
Number of cloud layer spectral grid points.
Definition: jurassic.h:580
int nsf
Number of surface layer spectral grid points.
Definition: jurassic.h:586
Observation geometry and radiance data.
Definition: jurassic.h:761
double rad[ND][NR]
Radiance [W/(m^2 sr cm^-1)].
Definition: jurassic.h:800
int nr
Number of ray paths.
Definition: jurassic.h:764
Retrieval control parameters.
Definition: retrieval.c:32
double err_press_cz
Vertical correlation length for pressure error [km].
Definition: retrieval.c:59
double err_press
Pressure error [%].
Definition: retrieval.c:56
double err_k_cz[NW]
Vertical correlation length for extinction error [km].
Definition: retrieval.c:86
int err_ana
Carry out error analysis (0=no, 1=yes).
Definition: retrieval.c:47
double err_k_ch[NW]
Horizontal correlation length for extinction error [km].
Definition: retrieval.c:89
double err_temp_cz
Vertical correlation length for temperature error [km].
Definition: retrieval.c:68
double err_formod[ND]
Forward model error [%].
Definition: retrieval.c:50
double conv_dmin
Minimum normalized step size in state space.
Definition: retrieval.c:44
double err_temp
Temperature error [K].
Definition: retrieval.c:65
double err_q_cz[NG]
Vertical correlation length for volume mixing ratio error [km].
Definition: retrieval.c:77
double err_noise[ND]
Noise error [W/(m^2 sr cm^-1)].
Definition: retrieval.c:53
double err_clz
Cloud height error [km].
Definition: retrieval.c:92
double err_sft
Surface temperature error [K].
Definition: retrieval.c:101
double err_clk[NCL]
Cloud extinction error [km^-1].
Definition: retrieval.c:98
double err_temp_ch
Horizontal correlation length for temperature error [km].
Definition: retrieval.c:71
int kernel_recomp
Re-computation of kernel matrix (number of iterations).
Definition: retrieval.c:38
int conv_itmax
Maximum number of iterations.
Definition: retrieval.c:41
double err_cldz
Cloud depth error [km].
Definition: retrieval.c:95
double err_press_ch
Horizontal correlation length for pressure error [km].
Definition: retrieval.c:62
double err_q_ch[NG]
Horizontal correlation length for volume mixing ratio error [km].
Definition: retrieval.c:80
double err_q[NG]
Volume mixing ratio error [%].
Definition: retrieval.c:74
char dir[LEN]
Working directory.
Definition: retrieval.c:35
double err_sfeps[NSF]
Surface emissivity error.
Definition: retrieval.c:104
double err_k[NW]
Extinction error [km^-1].
Definition: retrieval.c:83
Emissivity look-up tables.
Definition: jurassic.h:805