JURASSIC
Functions
formod.c File Reference

JURASSIC forward model. More...

#include "jurassic.h"

Go to the source code of this file.

Functions

void call_formod (ctl_t *ctl, const tbl_t *tbl, const char *wrkdir, const char *obsfile, const char *atmfile, const char *radfile, const char *task, const char *obsref)
 Perform forward model calculations in a single directory. More...
 
void compute_rel_errors (const ctl_t *ctl, const obs_t *obs_test, const obs_t *obs_ref, double *mre, double *sdre, double *minre, double *maxre)
 Calculate relative errors. More...
 
void usage (void)
 Print command-line help. More...
 
int main (int argc, char *argv[])
 

Detailed Description

JURASSIC forward model.

Definition in file formod.c.

Function Documentation

◆ call_formod()

void call_formod ( ctl_t ctl,
const tbl_t tbl,
const char *  wrkdir,
const char *  obsfile,
const char *  atmfile,
const char *  radfile,
const char *  task,
const char *  obsref 
)

Perform forward model calculations in a single directory.

Definition at line 226 of file formod.c.

234 {
235
236 static atm_t atm, atm2;
237 static obs_t obs, obs2;
238
239 /* Read atmospheric data... */
240 SELECT_TIMER("READ_ATM", "INPUT");
241 read_atm(wrkdir, atmfile, ctl, &atm, 0);
242
243 /* Read observation geometry... */
244 SELECT_TIMER("READ_OBS", "INPUT");
245 read_obs(wrkdir, obsfile, ctl, &obs, 0);
246
247 /* Compute multiple profiles... */
248 if (task[0] == 'p' || task[0] == 'P') {
249
250 SELECT_TIMER("FORMOD_PROFILE_LOOP", "FORWARD");
251
252 /* Loop over ray paths... */
253 for (int ir = 0; ir < obs.nr; ir++) {
254
255 /* Get atmospheric data... */
256 atm2.np = 0;
257 for (int ip = 0; ip < atm.np; ip++)
258 if (atm.time[ip] == obs.time[ir]) {
259 atm2.time[atm2.np] = atm.time[ip];
260 atm2.z[atm2.np] = atm.z[ip];
261 atm2.lon[atm2.np] = atm.lon[ip];
262 atm2.lat[atm2.np] = atm.lat[ip];
263 atm2.p[atm2.np] = atm.p[ip];
264 atm2.t[atm2.np] = atm.t[ip];
265 for (int ig = 0; ig < ctl->ng; ig++)
266 atm2.q[ig][atm2.np] = atm.q[ig][ip];
267 for (int iw = 0; iw < ctl->nw; iw++)
268 atm2.k[iw][atm2.np] = atm.k[iw][ip];
269 atm2.np++;
270 }
271
272 /* Get observation data... */
273 obs2.nr = 1;
274 obs2.time[0] = obs.time[ir];
275 obs2.vpz[0] = obs.vpz[ir];
276 obs2.vplon[0] = obs.vplon[ir];
277 obs2.vplat[0] = obs.vplat[ir];
278 obs2.obsz[0] = obs.obsz[ir];
279 obs2.obslon[0] = obs.obslon[ir];
280 obs2.obslat[0] = obs.obslat[ir];
281
282 /* Check number of data points... */
283 if (atm2.np > 0) {
284
285 /* Call forward model... */
286 formod(ctl, tbl, &atm2, &obs2);
287
288 /* Save radiance data... */
289 for (int id = 0; id < ctl->nd; id++) {
290 obs.rad[id][ir] = obs2.rad[id][0];
291 obs.tau[id][ir] = obs2.tau[id][0];
292 }
293 }
294 }
295
296 /* Write radiance data... */
297 SELECT_TIMER("WRITE_OBS", "OUTPUT");
298 write_obs(wrkdir, radfile, ctl, &obs, 0);
299 }
300
301 /* Compute single profile... */
302 else {
303
304 /* Call forward model... */
305 SELECT_TIMER("FORMOD", "FORWARD");
306 formod(ctl, tbl, &atm, &obs);
307
308 /* Save radiance data... */
309 SELECT_TIMER("WRITE_OBS", "OUTPUT");
310 write_obs(wrkdir, radfile, ctl, &obs, 0);
311
312 /* Evaluate results... */
313 if (obsref[0] != '-') {
314
315 SELECT_TIMER("EVAL", "OUTPUT");
316
317 /* Read reference data... */
318 read_obs(wrkdir, obsref, ctl, &obs2, 0);
319
320 /* Calculate relative errors... */
321 double mre[ND], sdre[ND], minre[ND], maxre[ND];
322 compute_rel_errors(ctl, &obs, &obs2, mre, sdre, minre, maxre);
323
324 /* Write results... */
325 for (int id = 0; id < ctl->nd; id++)
326 printf
327 ("EVAL: nu= %.4f cm^-1 | MRE= %g %% | SDRE= %g %% | MinRE= %g %% | MaxRE= %g %%\n",
328 ctl->nu[id], mre[id], sdre[id], minre[id], maxre[id]);
329 }
330
331 /* Compute contributions of emitters... */
332 if (task[0] == 'c' || task[0] == 'C') {
333
334 SELECT_TIMER("CONTRIBUTIONS", "FORWARD");
335
336 char filename[LEN];
337
338 /* Switch off continua... */
339 ctl->ctm_co2 = 0;
340 ctl->ctm_h2o = 0;
341 ctl->ctm_n2 = 0;
342 ctl->ctm_o2 = 0;
343
344 /* Loop over emitters... */
345 for (int ig = 0; ig < ctl->ng; ig++) {
346
347 /* Copy atmospheric data... */
348 copy_atm(ctl, &atm2, &atm, 0);
349
350 /* Set extinction to zero... */
351 for (int iw = 0; iw < ctl->nw; iw++)
352 for (int ip = 0; ip < atm2.np; ip++)
353 atm2.k[iw][ip] = 0;
354
355 /* Select emitter... */
356 for (int ig2 = 0; ig2 < ctl->ng; ig2++)
357 if (ig2 != ig)
358 for (int ip = 0; ip < atm2.np; ip++)
359 atm2.q[ig2][ip] = 0;
360
361 /* Call forward model... */
362 formod(ctl, tbl, &atm2, &obs);
363
364 /* Save radiance data... */
365 sprintf(filename, "%s.%s", radfile, ctl->emitter[ig]);
366 write_obs(wrkdir, filename, ctl, &obs, 0);
367 }
368
369 /* Copy atmospheric data... */
370 copy_atm(ctl, &atm2, &atm, 0);
371
372 /* Set volume mixing ratios to zero, keep extinction... */
373 for (int ig = 0; ig < ctl->ng; ig++)
374 for (int ip = 0; ip < atm2.np; ip++)
375 atm2.q[ig][ip] = 0;
376
377 /* Call forward model... */
378 formod(ctl, tbl, &atm2, &obs);
379
380 /* Save radiance data... */
381 sprintf(filename, "%s.EXTINCT", radfile);
382 write_obs(wrkdir, filename, ctl, &obs, 0);
383 }
384
385 /* Measure CPU-time... */
386 if (task[0] == 't' || task[0] == 'T') {
387
388 /* Init... */
389 double t_min = 0, t_max = 0, t_mean = 0, t_sd = 0;
390 int n = 0;
391
392 /* Initialize random number generator... */
393 gsl_rng_env_setup();
394 gsl_rng *rng = gsl_rng_alloc(gsl_rng_default);
395
396 /* Loop over profiles... */
397 do {
398
399 /* Create random atmosphere... */
400 copy_atm(ctl, &atm2, &atm, 0);
401 double dtemp = 40. * (gsl_rng_uniform(rng) - 0.5);
402 double dpress = 1. - 0.1 * gsl_rng_uniform(rng);
403 double dq[NG];
404 for (int ig = 0; ig < ctl->ng; ig++)
405 dq[ig] = 0.8 + 0.4 * gsl_rng_uniform(rng);
406 for (int ip = 0; ip < atm2.np; ip++) {
407 atm2.t[ip] += dtemp;
408 atm2.p[ip] *= dpress;
409 for (int ig = 0; ig < ctl->ng; ig++)
410 atm2.q[ig][ip] *= dq[ig];
411 }
412
413 /* Measure runtime... */
414 SELECT_TIMER("BENCHMARK_SAMPLE", "ANALYSIS");
415 double t0 = omp_get_wtime();
416 formod(ctl, tbl, &atm2, &obs);
417 double dt = omp_get_wtime() - t0;
418
419 /* Get runtime statistics... */
420 t_mean += dt;
421 t_sd += POW2(dt);
422 if (n == 0 || dt < t_min)
423 t_min = dt;
424 if (n == 0 || dt > t_max)
425 t_max = dt;
426 n++;
427
428 } while (t_mean < 10.0);
429
430 /* Keep the legacy benchmark line and the new timer-style overlap metric. */
431 t_mean /= (double) n;
432 t_sd = sqrt(t_sd / (double) n - POW2(t_mean));
433 printf("RUNTIME: mean= %g s | stddev= %g s | min= %g s | max= %g s\n",
434 t_mean, t_sd, t_min, t_max);
435
436 /* Free... */
437 gsl_rng_free(rng);
438 }
439
440 /* Analyze impact of step size... */
441 if (task[0] == 's' || task[0] == 'S') {
442
443 SELECT_TIMER("STEP_ANALYSIS", "ANALYSIS");
444
445 /* Reference run... */
446 ctl->rayds = 0.1;
447 ctl->raydz = 0.01;
448 formod(ctl, tbl, &atm, &obs);
449 copy_obs(ctl, &obs2, &obs, 0);
450
451 /* Loop over step size... */
452 for (double dz = 0.01; dz <= 2; dz *= 1.1)
453 for (double ds = 0.1; ds <= 50; ds *= 1.1) {
454
455 /* Set step size... */
456 ctl->rayds = ds;
457 ctl->raydz = dz;
458
459 /* Measure runtime... */
460 double t0 = omp_get_wtime();
461 formod(ctl, tbl, &atm, &obs);
462 double dt = omp_get_wtime() - t0;
463
464 /* Calculate relative errors... */
465 double mre[ND], sdre[ND], minre[ND], maxre[ND];
466 compute_rel_errors(ctl, &obs, &obs2, mre, sdre, minre, maxre);
467
468 /* Write results... */
469 for (int id = 0; id < ctl->nd; id++)
470 printf
471 ("STEPSIZE: ds= %.4f km | dz= %g km | t= %g s | nu= %.4f cm^-1"
472 " | MRE= %g %% | SDRE= %g %% | MinRE= %g %% | MaxRE= %g %%\n",
473 ds, dz, dt, ctl->nu[id], mre[id], sdre[id], minre[id],
474 maxre[id]);
475 }
476 }
477 }
478}
void compute_rel_errors(const ctl_t *ctl, const obs_t *obs_test, const obs_t *obs_ref, double *mre, double *sdre, double *minre, double *maxre)
Calculate relative errors.
Definition: formod.c:482
void read_obs(const char *dirname, const char *filename, const ctl_t *ctl, obs_t *obs, int profile)
Read observation data from an input file.
Definition: jurassic.c:5810
void write_obs(const char *dirname, const char *filename, const ctl_t *ctl, const obs_t *obs, int profile)
Write observation data to an output file in ASCII or binary format.
Definition: jurassic.c:8275
void read_atm(const char *dirname, const char *filename, const ctl_t *ctl, atm_t *atm, int profile)
Read atmospheric input data from a file.
Definition: jurassic.c:5193
void copy_obs(const ctl_t *ctl, obs_t *obs_dest, const obs_t *obs_src, const int init)
Copy or initialize observation geometry and radiance data.
Definition: jurassic.c:3320
void formod(const ctl_t *ctl, const tbl_t *tbl, atm_t *atm, obs_t *obs)
Execute the selected forward model.
Definition: jurassic.c:3421
void copy_atm(const ctl_t *ctl, atm_t *atm_dest, const atm_t *atm_src, const int init)
Copy or initialize atmospheric profile data.
Definition: jurassic.c:3270
#define LEN
Maximum length of ASCII data lines.
Definition: jurassic.h:268
#define POW2(x)
Compute the square of a value.
Definition: jurassic.h:1018
#define SELECT_TIMER(id, group)
Switch to a named aggregated timer.
Definition: jurassic.h:1158
#define ND
Maximum number of radiance channels.
Definition: jurassic.h:288
#define NG
Maximum number of emitters.
Definition: jurassic.h:298
Atmospheric profile data.
Definition: jurassic.h:1375
double time[NP]
Time (seconds since 2000-01-01T00:00Z).
Definition: jurassic.h:1381
double k[NW][NP]
Extinction [km^-1].
Definition: jurassic.h:1402
double lat[NP]
Latitude [deg].
Definition: jurassic.h:1390
double lon[NP]
Longitude [deg].
Definition: jurassic.h:1387
double t[NP]
Temperature [K].
Definition: jurassic.h:1396
int np
Number of data points.
Definition: jurassic.h:1378
double z[NP]
Altitude [km].
Definition: jurassic.h:1384
double q[NG][NP]
Volume mixing ratio [ppv].
Definition: jurassic.h:1399
double p[NP]
Pressure [hPa].
Definition: jurassic.h:1393
int nw
Number of spectral windows.
Definition: jurassic.h:1455
double nu[ND]
Centroid wavenumber of each channel [cm^-1].
Definition: jurassic.h:1452
int ctm_co2
Compute CO2 continuum (0=no, 1=yes).
Definition: jurassic.h:1497
int ctm_n2
Compute N2 continuum (0=no, 1=yes).
Definition: jurassic.h:1503
int ctm_h2o
Compute H2O continuum (0=no, 1=yes).
Definition: jurassic.h:1500
int ng
Number of emitters.
Definition: jurassic.h:1431
int nd
Number of radiance channels.
Definition: jurassic.h:1449
int ctm_o2
Compute O2 continuum (0=no, 1=yes).
Definition: jurassic.h:1506
char emitter[NG][LEN]
Name of each emitter.
Definition: jurassic.h:1434
double rayds
Maximum step length for raytracing [km].
Definition: jurassic.h:1512
double raydz
Vertical step length for raytracing [km].
Definition: jurassic.h:1515
Observation geometry and radiance data.
Definition: jurassic.h:1657
double tau[ND][NR]
Transmittance of ray path.
Definition: jurassic.h:1693
double rad[ND][NR]
Radiance [W/(m^2 sr cm^-1)].
Definition: jurassic.h:1696
double vpz[NR]
View point altitude [km].
Definition: jurassic.h:1675
double vplat[NR]
View point latitude [deg].
Definition: jurassic.h:1681
double obslon[NR]
Observer longitude [deg].
Definition: jurassic.h:1669
double obslat[NR]
Observer latitude [deg].
Definition: jurassic.h:1672
double obsz[NR]
Observer altitude [km].
Definition: jurassic.h:1666
double vplon[NR]
View point longitude [deg].
Definition: jurassic.h:1678
double time[NR]
Time (seconds since 2000-01-01T00:00Z).
Definition: jurassic.h:1663
int nr
Number of ray paths.
Definition: jurassic.h:1660
Here is the call graph for this function:

◆ compute_rel_errors()

void compute_rel_errors ( const ctl_t ctl,
const obs_t obs_test,
const obs_t obs_ref,
double *  mre,
double *  sdre,
double *  minre,
double *  maxre 
)

Calculate relative errors.

Definition at line 482 of file formod.c.

489 {
490
491 /* Loop over channels... */
492 for (int id = 0; id < ctl->nd; id++) {
493
494 double sum = 0, sum2 = 0;
495 minre[id] = +1e9;
496 maxre[id] = -1e9;
497 int n = 0;
498
499 /* Loop over ray paths... */
500 for (int ir = 0; ir < obs_test->nr; ir++) {
501
502 /* Check for zero... */
503 if (obs_ref->rad[id][ir] == 0)
504 continue;
505
506 /* Calculate relative error... */
507 double err = 100.0 * (obs_test->rad[id][ir] - obs_ref->rad[id][ir])
508 / obs_ref->rad[id][ir];
509
510 /* Get statistics... */
511 sum += err;
512 sum2 += err * err;
513 if (err > maxre[id])
514 maxre[id] = err;
515 if (err < minre[id])
516 minre[id] = err;
517 n++;
518 }
519
520 /* Get mean and standard deviaton... */
521 mre[id] = sum / n;
522 sdre[id] = sqrt(sum2 / n - mre[id] * mre[id]);
523 }
524}

◆ usage()

static void usage ( void  )

Print command-line help.

Definition at line 163 of file formod.c.

164 {
165
166 printf("\nJURASSIC forward model.\n\n");
167 printf
168 ("Compute simulated radiances or transmittances for the configured\n");
169 printf
170 ("channels from observation geometry, atmospheric state, and control\n");
171 printf("settings.\n\n");
172 printf("Usage:\n");
173 printf(" formod <ctl> <obs> <atm> <rad> [KEY VALUE ...]\n\n");
174 printf("Arguments:\n");
175 printf(" <ctl> Control file.\n");
176 printf(" <obs> Observation geometry input file.\n");
177 printf(" <atm> Atmospheric state input file.\n");
178 printf(" <rad> Output file for simulated radiances or transmittances.\n");
179 printf(" [KEY VALUE] Optional control parameters.\n\n");
180 printf("Tool-specific control parameters:\n");
181 printf(" TASK <name> Select the operation mode.\n");
182 printf
183 (" - or omitted: regular forward-model simulation.\n");
184 printf
185 (" c: write separate outputs for individual emitter and\n");
186 printf(" extinction contributions.\n");
187 printf
188 (" p: process observation profiles one ray at a time,\n");
189 printf(" matching atmospheric profiles by time.\n");
190 printf
191 (" s: analyze sensitivity to ray-tracing step sizes.\n");
192 printf
193 (" t: run the built-in runtime benchmark using randomly\n");
194 printf
195 (" perturbed versions of the input atmosphere.\n");
196 printf
197 (" DIRLIST <file> Read working directories from <file> and run one case\n");
198 printf
199 (" per directory using the same <obs>, <atm>, and <rad>\n");
200 printf(" filenames relative to each listed directory.\n");
201 printf
202 (" OBSREF <file> Read reference observations from <file> and print\n");
203 printf
204 (" relative-error diagnostics against the simulated output.\n");
205 printf("\n");
206 printf("Common control parameters:\n");
207 printf
208 (" TBLBASE, TBLFMT Lookup-table base name and format.\n");
209 printf
210 (" ATMFMT, OBSFMT Atmospheric and observation file formats.\n");
211 printf(" NG, EMITTER[i] Active emitters.\n");
212 printf(" ND, NU[i], NW, WINDOW[i] Spectral channels and windows.\n");
213 printf
214 (" NCL, CLNU[i], NSF, SFNU[i] Cloud and surface spectral grids.\n");
215 printf
216 (" WRITE_BBT, FORMOD Output units and forward-model selection.\n");
217 printf(" CTM_*, REFRAC Continua and refractivity.\n");
218 printf
219 (" RAYDS, RAYDZ, FOV Ray tracing and field of view.\n\n");
220 printf("Further information:\n");
221 printf(" Manual: https://slcs-jsc.github.io/jurassic/\n");
222}

◆ main()

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

Definition at line 63 of file formod.c.

65 {
66
67 static ctl_t ctl;
68
69 /* Print usage information... */
70 USAGE;
71
72 /* Check arguments... */
73 if (argc < 5)
74 ERRMSG("Missing or invalid command-line arguments.\n\n"
75 "Usage: formod <ctl> <obs> <atm> <rad> [KEY VALUE ...]\n\n"
76 "Use -h for full help.");
77
78 /* Read control parameters... */
79 SELECT_TIMER("READ_CTL", "INPUT");
80 read_ctl(argc, argv, &ctl);
81
82#ifdef UNIFIED
83
84 static atm_t atm;
85 static obs_t obs;
86
87 /* Read observation geometry... */
88 SELECT_TIMER("READ_OBS", "INPUT");
89 read_obs(NULL, argv[2], &ctl, &obs, 0);
90
91 /* Read atmospheric data... */
92 SELECT_TIMER("READ_ATM", "INPUT");
93 read_atm(NULL, argv[3], &ctl, &atm, 0);
94
95 /* Call forward model... */
96 SELECT_TIMER("FORMOD_UNIFIED", "FORWARD");
97 jur_unified_init(argc, argv);
98 jur_unified_formod_multiple_packages(&atm, &obs, 1, NULL);
99
100 /* Save radiance data... */
101 SELECT_TIMER("WRITE_OBS", "OUTPUT");
102 write_obs(NULL, argv[4], &ctl, &obs, 0);
103
104#else
105
106 char dirlist[LEN], obsref[LEN], task[LEN];
107
108 /* Initialize look-up tables... */
109 SELECT_TIMER("READ_TBL", "INPUT");
110 tbl_t *tbl = read_tbl(&ctl);
111
112 /* Get task... */
113 SELECT_TIMER("READ_TASK", "INPUT");
114 scan_ctl(argc, argv, "TASK", -1, "-", task);
115
116 /* Get dirlist... */
117 SELECT_TIMER("READ_DIRLIST", "INPUT");
118 scan_ctl(argc, argv, "DIRLIST", -1, "-", dirlist);
119
120 /* Get reference data... */
121 SELECT_TIMER("READ_OBSREF", "INPUT");
122 scan_ctl(argc, argv, "OBSREF", -1, "-", obsref);
123
124 /* Single forward calculation... */
125 if (dirlist[0] == '-')
126 call_formod(&ctl, tbl, NULL, argv[2], argv[3], argv[4], task, obsref);
127
128 /* Work on directory list... */
129 else {
130
131 /* Open directory list... */
132 FILE *in;
133 if (!(in = fopen(dirlist, "r")))
134 ERRMSG("Cannot open directory list!");
135
136 /* Loop over directories... */
137 char wrkdir[LEN];
138 while (fscanf(in, "%4999s", wrkdir) != EOF) {
139
140 /* Write info... */
141 LOG(1, "\nWorking directory: %s", wrkdir);
142
143 /* Call forward model... */
144 call_formod(&ctl, tbl, wrkdir, argv[2], argv[3], argv[4], task, obsref);
145 }
146
147 /* Close dirlist... */
148 fclose(in);
149 }
150
151#endif
152
153 /* Free... */
154 SELECT_TIMER("FINALIZE", "OVERHEAD");
155 tbl_free(&ctl, tbl);
157
158 return EXIT_SUCCESS;
159}
void call_formod(ctl_t *ctl, const tbl_t *tbl, const char *wrkdir, const char *obsfile, const char *atmfile, const char *radfile, const char *task, const char *obsref)
Perform forward model calculations in a single directory.
Definition: formod.c:226
void tbl_free(const ctl_t *ctl, tbl_t *tbl)
Free lookup table and all internally allocated memory.
Definition: jurassic.c:7002
void read_ctl(int argc, char *argv[], ctl_t *ctl)
Read model control parameters from command-line and configuration input.
Definition: jurassic.c:5516
double scan_ctl(int argc, char *argv[], const char *varname, const int arridx, const char *defvalue, char *value)
Scan control file or command-line arguments for a configuration variable.
Definition: jurassic.c:6612
tbl_t * read_tbl(const ctl_t *ctl)
Read emissivity lookup tables from disk.
Definition: jurassic.c:6332
#define ERRMSG(...)
Print an error message with contextual information and terminate the program.
Definition: jurassic.h:1325
#define USAGE
Print usage information on -h or --help.
Definition: jurassic.h:1206
#define PRINT_TIMERS
Print aggregated timer statistics.
Definition: jurassic.h:1168
#define LOG(level,...)
Print a log message with a specified logging level.
Definition: jurassic.h:1255
Control parameters.
Definition: jurassic.h:1428
Emissivity look-up tables.
Definition: jurassic.h:1842
Here is the call graph for this function: