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