JURASSIC
formod.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-2021 Forschungszentrum Juelich GmbH
18*/
19
25#include "jurassic.h"
26#ifdef UNIFIED
27#include "jurassic_unified_library.h"
28#endif
29
30/* ------------------------------------------------------------
31 Functions...
32 ------------------------------------------------------------ */
33
35void call_formod(
36 ctl_t * ctl,
37 const char *wrkdir,
38 const char *obsfile,
39 const char *atmfile,
40 const char *radfile,
41 const char *task);
42
43/* ------------------------------------------------------------
44 Main...
45 ------------------------------------------------------------ */
46
47int main(
48 int argc,
49 char *argv[]) {
50
51 static ctl_t ctl;
52
53 /* Check arguments... */
54 if (argc < 5)
55 ERRMSG("Give parameters: <ctl> <obs> <atm> <rad>");
56
57 /* Read control parameters... */
58 read_ctl(argc, argv, &ctl);
59
60#ifdef UNIFIED
61
62 static atm_t atm;
63 static obs_t obs;
64
65 /* Read observation geometry... */
66 read_obs(NULL, argv[2], &ctl, &obs);
67
68 /* Read atmospheric data... */
69 read_atm(NULL, argv[3], &ctl, &atm);
70
71 /* Call forward model... */
72 jur_unified_init(argc, argv);
73 jur_unified_formod_multiple_packages(&atm, &obs, 1, NULL);
74
75 /* Save radiance data... */
76 write_obs(NULL, argv[4], &ctl, &obs);
77
78#else
79
80 char dirlist[LEN], task[LEN];
81
82 /* Get task... */
83 scan_ctl(argc, argv, "TASK", -1, "-", task);
84
85 /* Get dirlist... */
86 scan_ctl(argc, argv, "DIRLIST", -1, "-", dirlist);
87
88 /* Single forward calculation... */
89 if (dirlist[0] == '-')
90 call_formod(&ctl, NULL, argv[2], argv[3], argv[4], task);
91
92 /* Work on directory list... */
93 else {
94
95 /* Open directory list... */
96 FILE *in;
97 if (!(in = fopen(dirlist, "r")))
98 ERRMSG("Cannot open directory list!");
99
100 /* Loop over directories... */
101 char wrkdir[LEN];
102 while (fscanf(in, "%s", wrkdir) != EOF) {
103
104 /* Write info... */
105 LOG(1, "\nWorking directory: %s", wrkdir);
106
107 /* Call forward model... */
108 call_formod(&ctl, wrkdir, argv[2], argv[3], argv[4], task);
109 }
110
111 /* Close dirlist... */
112 fclose(in);
113 }
114
115#endif
116
117 return EXIT_SUCCESS;
118}
119
120/*****************************************************************************/
121
123 ctl_t * ctl,
124 const char *wrkdir,
125 const char *obsfile,
126 const char *atmfile,
127 const char *radfile,
128 const char *task) {
129
130 static atm_t atm, atm2;
131 static obs_t obs, obs2;
132
133 /* Read observation geometry... */
134 read_obs(wrkdir, obsfile, ctl, &obs);
135
136 /* Read atmospheric data... */
137 read_atm(wrkdir, atmfile, ctl, &atm);
138
139 /* Compute multiple profiles... */
140 if (task[0] == 'p' || task[0] == 'P') {
141
142 /* Loop over ray paths... */
143 for (int ir = 0; ir < obs.nr; ir++) {
144
145 /* Get atmospheric data... */
146 atm2.np = 0;
147 for (int ip = 0; ip < atm.np; ip++)
148 if (atm.time[ip] == obs.time[ir]) {
149 atm2.time[atm2.np] = atm.time[ip];
150 atm2.z[atm2.np] = atm.z[ip];
151 atm2.lon[atm2.np] = atm.lon[ip];
152 atm2.lat[atm2.np] = atm.lat[ip];
153 atm2.p[atm2.np] = atm.p[ip];
154 atm2.t[atm2.np] = atm.t[ip];
155 for (int ig = 0; ig < ctl->ng; ig++)
156 atm2.q[ig][atm2.np] = atm.q[ig][ip];
157 for (int iw = 0; iw < ctl->nw; iw++)
158 atm2.k[iw][atm2.np] = atm.k[iw][ip];
159 atm2.np++;
160 }
161
162 /* Get observation data... */
163 obs2.nr = 1;
164 obs2.time[0] = obs.time[ir];
165 obs2.vpz[0] = obs.vpz[ir];
166 obs2.vplon[0] = obs.vplon[ir];
167 obs2.vplat[0] = obs.vplat[ir];
168 obs2.obsz[0] = obs.obsz[ir];
169 obs2.obslon[0] = obs.obslon[ir];
170 obs2.obslat[0] = obs.obslat[ir];
171
172 /* Check number of data points... */
173 if (atm2.np > 0) {
174
175 /* Call forward model... */
176 formod(ctl, &atm2, &obs2);
177
178 /* Save radiance data... */
179 for (int id = 0; id < ctl->nd; id++) {
180 obs.rad[id][ir] = obs2.rad[id][0];
181 obs.tau[id][ir] = obs2.tau[id][0];
182 }
183 }
184 }
185
186 /* Write radiance data... */
187 write_obs(wrkdir, radfile, ctl, &obs);
188 }
189
190 /* Compute single profile... */
191 else {
192
193 /* Call forward model... */
194 formod(ctl, &atm, &obs);
195
196 /* Save radiance data... */
197 write_obs(wrkdir, radfile, ctl, &obs);
198
199 /* Compute contributions... */
200 if (task[0] == 'c' || task[0] == 'C') {
201
202 char filename[LEN];
203
204 /* Switch off continua... */
205 ctl->ctm_co2 = 0;
206 ctl->ctm_h2o = 0;
207 ctl->ctm_n2 = 0;
208 ctl->ctm_o2 = 0;
209
210 /* Loop over emitters... */
211 for (int ig = 0; ig < ctl->ng; ig++) {
212
213 /* Copy atmospheric data... */
214 copy_atm(ctl, &atm2, &atm, 0);
215
216 /* Set extinction to zero... */
217 for (int iw = 0; iw < ctl->nw; iw++)
218 for (int ip = 0; ip < atm2.np; ip++)
219 atm2.k[iw][ip] = 0;
220
221 /* Set volume mixing ratios to zero... */
222 for (int ig2 = 0; ig2 < ctl->ng; ig2++)
223 if (ig2 != ig)
224 for (int ip = 0; ip < atm2.np; ip++)
225 atm2.q[ig2][ip] = 0;
226
227 /* Call forward model... */
228 formod(ctl, &atm2, &obs);
229
230 /* Save radiance data... */
231 sprintf(filename, "%s.%s", radfile, ctl->emitter[ig]);
232 write_obs(wrkdir, filename, ctl, &obs);
233 }
234
235 /* Copy atmospheric data... */
236 copy_atm(ctl, &atm2, &atm, 0);
237
238 /* Set volume mixing ratios to zero... */
239 for (int ig = 0; ig < ctl->ng; ig++)
240 for (int ip = 0; ip < atm2.np; ip++)
241 atm2.q[ig][ip] = 0;
242
243 /* Call forward model... */
244 formod(ctl, &atm2, &obs);
245
246 /* Save radiance data... */
247 sprintf(filename, "%s.EXTINCT", radfile);
248 write_obs(wrkdir, filename, ctl, &obs);
249 }
250
251 /* Measure CPU-time... */
252 if (task[0] == 't' || task[0] == 'T') {
253
254 /* Init... */
255 double t_min, t_max, t_mean = 0, t_sigma = 0;
256 int n = 0;
257
258 /* Initialize random number generator... */
259 gsl_rng_env_setup();
260 gsl_rng *rng = gsl_rng_alloc(gsl_rng_default);
261
262 /* Loop over profiles... */
263 do {
264
265 /* Create random atmosphere... */
266 copy_atm(ctl, &atm2, &atm, 0);
267 double dtemp = 40. * (gsl_rng_uniform(rng) - 0.5);
268 double dpress = 1. - 0.1 * gsl_rng_uniform(rng);
269 double dq[NG];
270 for (int ig = 0; ig < ctl->ng; ig++)
271 dq[ig] = 0.8 + 0.4 * gsl_rng_uniform(rng);
272 for (int ip = 0; ip < atm2.np; ip++) {
273 atm.t[ip] += dtemp;
274 atm.p[ip] *= dpress;
275 for (int ig = 0; ig < ctl->ng; ig++)
276 atm.q[ig][ip] *= dq[ig];
277 }
278
279 /* Measure runtime... */
280 double t0 = omp_get_wtime();
281 formod(ctl, &atm2, &obs);
282 double dt = omp_get_wtime() - t0;
283
284 /* Get runtime statistics... */
285 t_mean += (dt);
286 t_sigma += POW2(dt);
287 if (n == 0 || dt < t_min)
288 t_min = dt;
289 if (n == 0 || dt > t_max)
290 t_max = dt;
291 n++;
292
293 } while (t_mean < 10.0);
294
295 /* Write results... */
296 t_mean /= (double) n;
297 t_sigma = sqrt(t_sigma / (double) n - POW2(t_mean));
298 printf("RUNTIME_MEAN = %g s\n", t_mean);
299 printf("RUNTIME_SIGMA = %g s\n", t_sigma);
300 printf("RUNTIME_MIN = %g s\n", t_min);
301 printf("RUNTIME_MAX = %g s\n", t_max);
302 printf("RAYS_PER_SECOND = %g", (double) obs.nr / t_mean);
303 }
304
305 /* Analyze effect of step size... */
306 if (task[0] == 's' || task[0] == 'S') {
307
308 /* Reference run... */
309 ctl->rayds = 0.1;
310 ctl->raydz = 0.01;
311 formod(ctl, &atm, &obs);
312 copy_obs(ctl, &obs2, &obs, 0);
313
314 /* Loop over step size... */
315 for (double dz = 0.01; dz <= 2; dz *= 1.1) {
316 printf("STEPSIZE: \n");
317 for (double ds = 0.1; ds <= 50; ds *= 1.1) {
318
319 /* Set step size... */
320 ctl->rayds = ds;
321 ctl->raydz = dz;
322
323 /* Measure runtime... */
324 double t0 = omp_get_wtime();
325 formod(ctl, &atm, &obs);
326 double dt = omp_get_wtime() - t0;
327
328 /* Get differences... */
329 double mean[ND], sigma[ND];
330 for (int id = 0; id < ctl->nd; id++) {
331 mean[id] = sigma[id] = 0;
332 int n = 0;
333 for (int ir = 0; ir < obs.nr; ir++) {
334 double err = 200. * (obs.rad[id][ir] - obs2.rad[id][ir])
335 / (obs.rad[id][ir] + obs2.rad[id][ir]);
336 mean[id] += err;
337 sigma[id] += POW2(err);
338 n++;
339 }
340 mean[id] /= n;
341 sigma[id] = sqrt(sigma[id] / n - POW2(mean[id]));
342 }
343
344 /* Write results... */
345 printf("STEPSIZE: %g %g %g", ds, dz, dt);
346 for (int id = 0; id < ctl->nd; id++)
347 printf(" %g %g", mean[id], sigma[id]);
348 printf("\n");
349 }
350 }
351 }
352 }
353}
int main(int argc, char *argv[])
Definition: formod.c:47
void call_formod(ctl_t *ctl, const char *wrkdir, const char *obsfile, const char *atmfile, const char *radfile, const char *task)
Perform forward model calculations in a single directory.
Definition: formod.c:122
void read_ctl(int argc, char *argv[], ctl_t *ctl)
Read forward model control parameters.
Definition: jurassic.c:4550
void formod(const ctl_t *ctl, atm_t *atm, obs_t *obs)
Determine ray paths and compute radiative transfer.
Definition: jurassic.c:3026
void read_atm(const char *dirname, const char *filename, const ctl_t *ctl, atm_t *atm)
Read atmospheric data.
Definition: jurassic.c:4445
void copy_obs(const ctl_t *ctl, obs_t *obs_dest, const obs_t *obs_src, const int init)
Copy and initialize observation data.
Definition: jurassic.c:2975
void read_obs(const char *dirname, const char *filename, const ctl_t *ctl, obs_t *obs)
Read observation data.
Definition: jurassic.c:4700
void write_obs(const char *dirname, const char *filename, const ctl_t *ctl, const obs_t *obs)
Write observation data.
Definition: jurassic.c:5673
double scan_ctl(int argc, char *argv[], const char *varname, int arridx, const char *defvalue, char *value)
Search control parameter file for variable entry.
Definition: jurassic.c:5117
void copy_atm(const ctl_t *ctl, atm_t *atm_dest, const atm_t *atm_src, const int init)
Copy and initialize atmospheric data.
Definition: jurassic.c:2921
JURASSIC library declarations.
#define LEN
Maximum length of ASCII data lines.
Definition: jurassic.h:383
#define POW2(x)
Compute x^2.
Definition: jurassic.h:187
#define ERRMSG(...)
Print error message and quit program.
Definition: jurassic.h:237
#define ND
Maximum number of radiance channels.
Definition: jurassic.h:353
#define NG
Maximum number of emitters.
Definition: jurassic.h:358
#define LOG(level,...)
Print log message.
Definition: jurassic.h:221
Atmospheric data.
Definition: jurassic.h:488
double time[NP]
Time (seconds since 2000-01-01T00:00Z).
Definition: jurassic.h:494
double k[NW][NP]
Extinction [km^-1].
Definition: jurassic.h:515
double lat[NP]
Latitude [deg].
Definition: jurassic.h:503
double lon[NP]
Longitude [deg].
Definition: jurassic.h:500
double t[NP]
Temperature [K].
Definition: jurassic.h:509
int np
Number of data points.
Definition: jurassic.h:491
double z[NP]
Altitude [km].
Definition: jurassic.h:497
double q[NG][NP]
Volume mixing ratio [ppv].
Definition: jurassic.h:512
double p[NP]
Pressure [hPa].
Definition: jurassic.h:506
Forward model control parameters.
Definition: jurassic.h:541
int nw
Number of spectral windows.
Definition: jurassic.h:556
int ctm_co2
Compute CO2 continuum (0=no, 1=yes).
Definition: jurassic.h:589
int ctm_n2
Compute N2 continuum (0=no, 1=yes).
Definition: jurassic.h:595
int ctm_h2o
Compute H2O continuum (0=no, 1=yes).
Definition: jurassic.h:592
int ng
Number of emitters.
Definition: jurassic.h:544
int nd
Number of radiance channels.
Definition: jurassic.h:550
int ctm_o2
Compute O2 continuum (0=no, 1=yes).
Definition: jurassic.h:598
char emitter[NG][LEN]
Name of each emitter.
Definition: jurassic.h:547
double rayds
Maximum step length for raytracing [km].
Definition: jurassic.h:604
double raydz
Vertical step length for raytracing [km].
Definition: jurassic.h:607
Observation geometry and radiance data.
Definition: jurassic.h:734
double tau[ND][NR]
Transmittance of ray path.
Definition: jurassic.h:770
double rad[ND][NR]
Radiance [W/(m^2 sr cm^-1)].
Definition: jurassic.h:773
double vpz[NR]
View point altitude [km].
Definition: jurassic.h:752
double vplat[NR]
View point latitude [deg].
Definition: jurassic.h:758
double obslon[NR]
Observer longitude [deg].
Definition: jurassic.h:746
double obslat[NR]
Observer latitude [deg].
Definition: jurassic.h:749
double obsz[NR]
Observer altitude [km].
Definition: jurassic.h:743
double vplon[NR]
View point longitude [deg].
Definition: jurassic.h:755
double time[NR]
Time (seconds since 2000-01-01T00:00Z).
Definition: jurassic.h:740
int nr
Number of ray paths.
Definition: jurassic.h:737