35static uint64_t rng_ctr;
39static curandGenerator_t rng_curand;
49#define CHUNK_SIZE 2147483647
52 MPI_Bcast(&N, 1, MPI_UINT64_T, 0, MPI_COMM_WORLD);
55 const size_t num_chunks = (N + CHUNK_SIZE - 1) / CHUNK_SIZE;
58 for (
size_t i = 0; i < num_chunks; i++) {
61 const size_t start = i * CHUNK_SIZE;
62 const size_t end = (start + CHUNK_SIZE > N) ? N : start + CHUNK_SIZE;
63 const size_t chunk_size = end - start;
66 MPI_Bcast((
char *) data + start, (
int) chunk_size, MPI_BYTE, 0,
80 const double radius = sqrt(
DOTP(x, x));
82 *lat =
RAD2DEG(asin(x[2] / radius));
83 *lon =
RAD2DEG(atan2(x[1], x[0]));
98 const double sza_thresh =
DEG2RAD(85.), csza_thresh = cos(sza_thresh);
101 const double oh =
clim_zm(&clim->
oh, t, lat, p);
108 const double csza =
cos_sza(t, lon, lat);
109 const double denom = (csza >= csza_thresh) ? csza : csza_thresh;
120 const double sza_thresh =
DEG2RAD(85.), csza_thresh = cos(sza_thresh);
123 for (
int it = 0; it < clim->
oh.
ntime; it++)
124 for (
int iz = 0; iz < clim->
oh.
np; iz++)
125 for (
int iy = 0; iy < clim->
oh.
nlat; iy++) {
132 for (
double lon = -180; lon < 180; lon += 1.0) {
135 const double denom = (csza >= csza_thresh) ? csza : csza_thresh;
141 clim->
oh.
vmr[it][iz][iy] /= (sum / (double) n);
156 if (p < photo->p[photo->
np - 1])
157 p_help = photo->
p[photo->
np - 1];
158 else if (p > photo->
p[0])
159 p_help = photo->
p[0];
162 double sza_help = sza;
163 if (sza < photo->sza[0])
164 sza_help = photo->
sza[0];
165 else if (sza > photo->
sza[photo->
nsza - 1])
166 sza_help = photo->
sza[photo->
nsza - 1];
169 double o3c_help = o3c;
170 if (o3c < photo->o3c[0])
171 o3c_help = photo->
o3c[0];
172 else if (o3c > photo->
o3c[photo->
no3c - 1])
173 o3c_help = photo->
o3c[photo->
no3c - 1];
181 const double aux00 =
LIN(photo->
p[ip], rate[ip][isza][io3c],
182 photo->
p[ip + 1], rate[ip + 1][isza][io3c],
184 const double aux01 =
LIN(photo->
p[ip], rate[ip][isza][io3c + 1],
185 photo->
p[ip + 1], rate[ip + 1][isza][io3c + 1],
187 const double aux10 =
LIN(photo->
p[ip], rate[ip][isza + 1][io3c],
188 photo->
p[ip + 1], rate[ip + 1][isza + 1][io3c],
190 const double aux11 =
LIN(photo->
p[ip], rate[ip][isza + 1][io3c + 1],
191 photo->
p[ip + 1], rate[ip + 1][isza + 1][io3c + 1],
194 LIN(photo->
o3c[io3c], aux00, photo->
o3c[io3c + 1], aux01, o3c_help);
196 LIN(photo->
o3c[io3c], aux10, photo->
o3c[io3c + 1], aux11, o3c_help);
198 LIN(photo->
sza[isza], aux0, photo->
sza[isza + 1], aux1, sza_help);
199 return MAX(aux, 0.0);
210 double sec =
FMOD(t, 365.25 * 86400.);
212 sec += 365.25 * 86400.;
220 clim->
tropo[isec][ilat],
222 clim->
tropo[isec][ilat + 1], lat);
224 clim->
tropo[isec + 1][ilat],
226 clim->
tropo[isec + 1][ilat + 1], lat);
236 LOG(1,
"Initialize tropopause data...");
240 double tropo_time[12] = {
241 1209600.00, 3888000.00, 6393600.00,
242 9072000.00, 11664000.00, 14342400.00,
243 16934400.00, 19612800.00, 22291200.00,
244 24883200.00, 27561600.00, 30153600.00
250 const double tropo_lat[73] = {
251 -90, -87.5, -85, -82.5, -80, -77.5, -75, -72.5, -70, -67.5,
252 -65, -62.5, -60, -57.5, -55, -52.5, -50, -47.5, -45, -42.5,
253 -40, -37.5, -35, -32.5, -30, -27.5, -25, -22.5, -20, -17.5,
254 -15, -12.5, -10, -7.5, -5, -2.5, 0, 2.5, 5, 7.5, 10, 12.5,
255 15, 17.5, 20, 22.5, 25, 27.5, 30, 32.5, 35, 37.5, 40, 42.5,
256 45, 47.5, 50, 52.5, 55, 57.5, 60, 62.5, 65, 67.5, 70, 72.5,
257 75, 77.5, 80, 82.5, 85, 87.5, 90
262 const double tropo[12][73] = {
263 {324.1, 325.6, 325, 324.3, 322.5, 319.7, 314, 307.2, 301.8, 299.6,
264 297.1, 292.2, 285.6, 276.1, 264, 248.9, 231.9, 213.5, 194.4,
265 175.3, 157, 140.4, 126.7, 116.3, 109.5, 105.4, 103, 101.4, 100.4,
266 99.69, 99.19, 98.84, 98.56, 98.39, 98.39, 98.42, 98.44, 98.54,
267 98.68, 98.81, 98.89, 98.96, 99.12, 99.65, 101.4, 105.4, 113.5, 128,
268 152.1, 184.7, 214, 234.1, 247.3, 255.8, 262.6, 267.7, 271.7, 275,
269 277.2, 279, 280.1, 280.4, 280.6, 280.1, 279.3, 278.3, 276.8, 275.8,
270 275.3, 275.6, 275.4, 274.1, 273.5},
271 {337.3, 338.7, 337.8, 336.4, 333, 328.8, 321.1, 312.6, 306.6, 303.7,
272 300.2, 293.8, 285.4, 273.8, 259.6, 242.7, 224.4, 205.2, 186, 167.5,
273 150.3, 135, 122.8, 113.9, 108.2, 104.7, 102.5, 101.1, 100.2, 99.42,
274 98.88, 98.52, 98.25, 98.09, 98.07, 98.1, 98.12, 98.2, 98.25, 98.27,
275 98.26, 98.27, 98.36, 98.79, 100.2, 104.2, 113.7, 131.2, 159.5, 193,
276 220.4, 238.1, 250.2, 258.1, 264.7, 269.7, 273.7, 277.3, 280.2, 282.8,
277 284.9, 286.5, 288.1, 288.8, 289, 288.5, 287.2, 286.3, 286.1, 287.2,
278 287.5, 286.2, 285.8},
279 {335, 336, 335.7, 335.1, 332.3, 328.1, 320.6, 311.8, 305.1, 301.9,
280 297.6, 290, 280.4, 268.3, 254.6, 239.6, 223.9, 207.9, 192.2, 176.9,
281 161.7, 146.4, 132.2, 120.6, 112.3, 107.2, 104.3, 102.4, 101.3,
282 100.4, 99.86, 99.47, 99.16, 98.97, 98.94, 98.97, 99, 99.09, 99.2,
283 99.31, 99.35, 99.41, 99.51, 99.86, 101.1, 104.9, 114.3, 131, 156.8,
284 186.3, 209.3, 224.6, 236.8, 246.3, 254.9, 262.3, 268.8, 274.8,
285 279.9, 284.6, 288.6, 291.6, 294.9, 297.5, 299.8, 301.8, 303.1,
286 304.3, 304.9, 306, 306.6, 306.2, 306},
287 {306.2, 306.7, 305.7, 307.1, 307.3, 306.4, 301.8, 296.2, 292.4,
288 290.3, 287.1, 280.9, 273.4, 264.3, 254.1, 242.8, 231, 219, 207.2,
289 195.5, 183.3, 169.7, 154.7, 138.7, 124.1, 113.6, 107.8, 104.7,
290 102.8, 101.7, 100.9, 100.4, 100, 99.79, 99.7, 99.66, 99.68, 99.79,
291 99.94, 100.2, 100.5, 100.9, 101.4, 102.1, 103.4, 107, 115.2, 129.1,
292 148.7, 171, 190.8, 205.6, 218.4, 229.4, 239.6, 248.6, 256.5,
293 263.7, 270.3, 276.6, 282.6, 288.1, 294.5, 300.4, 306.3, 311.4,
294 315.1, 318.3, 320.3, 322.2, 322.8, 321.5, 321.1},
295 {266.5, 264.9, 260.8, 261, 262, 263, 261.3, 259.7, 259.2, 259.8,
296 260.1, 258.6, 256.7, 253.6, 249.5, 243.9, 237.4, 230, 222.1, 213.9,
297 205, 194.4, 180.4, 161.8, 140.7, 122.9, 112.1, 106.7, 104.1, 102.7,
298 101.8, 101.4, 101.1, 101, 101, 101, 101.1, 101.2, 101.5, 101.9,
299 102.4, 103, 103.8, 104.9, 106.8, 110.1, 115.6, 124, 135.2, 148.9,
300 165.2, 181.3, 198, 211.8, 223.5, 233.8, 242.9, 251.5, 259, 266.2,
301 273.1, 279.2, 286.2, 292.8, 299.6, 306, 311.1, 315.5, 318.8, 322.6,
302 325.3, 325.8, 325.8},
303 {220.1, 218.1, 210.8, 207.2, 207.6, 210.5, 211.4, 213.5, 217.3,
304 222.4, 227.9, 232.8, 237.4, 240.8, 242.8, 243, 241.5, 238.6, 234.2,
305 228.5, 221, 210.7, 195.1, 172.9, 147.8, 127.6, 115.6, 109.9, 107.1,
306 105.7, 105, 104.8, 104.8, 104.9, 105, 105.1, 105.3, 105.5, 105.8,
307 106.4, 107, 107.6, 108.1, 108.8, 110, 111.8, 114.2, 117.4, 121.6,
308 127.9, 137.3, 151.2, 169.5, 189, 205.8, 218.9, 229.1, 237.8, 245,
309 251.5, 257.1, 262.3, 268.2, 274, 280.4, 286.7, 292.4, 297.9, 302.9,
310 308.5, 312.2, 313.1, 313.3},
311 {187.4, 184.5, 173.3, 166.1, 165.4, 167.8, 169.6, 173.6, 179.6,
312 187.9, 198.9, 210, 220.5, 229.2, 235.7, 239.9, 241.8, 241.6, 239.6,
313 235.8, 229.4, 218.6, 200.9, 175.9, 149.4, 129.4, 118.3, 113.1,
314 110.8, 109.7, 109.3, 109.4, 109.7, 110, 110.2, 110.4, 110.5, 110.7,
315 111, 111.4, 111.8, 112.1, 112.3, 112.7, 113.2, 113.9, 115, 116.4,
316 117.9, 120.4, 124.1, 130.9, 142.2, 159.6, 179.6, 198.5, 212.9,
317 224.2, 232.7, 239.1, 243.8, 247.7, 252.4, 257.3, 263.2, 269.5,
318 275.4, 281.1, 286.3, 292, 296.3, 298.2, 298.8},
319 {166, 166.4, 155.7, 148.3, 147.1, 149, 152.1, 157, 163.6, 172.4,
320 185.3, 199.2, 212.6, 224, 233.2, 239.6, 243.3, 244.6, 243.6, 240.3,
321 233.9, 222.6, 203.7, 177, 149.5, 129.7, 119, 114, 111.7, 110.7,
322 110.3, 110.3, 110.6, 110.9, 111.1, 111.3, 111.5, 111.6, 111.9,
323 112.2, 112.5, 112.6, 112.8, 113, 113.4, 114, 115.1, 116.5, 118.3,
324 120.9, 124.4, 130.2, 139.4, 154.6, 173.8, 193.1, 208.1, 220.4,
325 230.1, 238.2, 244.7, 249.5, 254.5, 259.3, 264.5, 269.4, 273.7,
326 278.2, 282.6, 287.4, 290.9, 292.5, 293},
327 {171.9, 172.8, 166.2, 162.3, 161.4, 162.5, 165.2, 169.6, 175.3,
328 183.1, 193.8, 205.9, 218.3, 229.6, 238.5, 244.3, 246.9, 246.7,
329 243.8, 238.4, 230.2, 217.9, 199.6, 174.9, 148.9, 129.8, 119.5,
330 114.8, 112.3, 110.9, 110.3, 110.1, 110.2, 110.3, 110.4, 110.5,
331 110.6, 110.8, 111, 111.4, 111.8, 112, 112.2, 112.4, 112.9, 113.6,
332 114.7, 116.3, 118.4, 121.9, 127.1, 136.1, 149.8, 168.4, 186.9,
333 203.3, 217, 229.1, 238.7, 247, 254, 259.3, 264.3, 268.3, 272.5,
334 276.6, 280.4, 284.4, 288.4, 293.3, 297.2, 298.7, 299.1},
335 {191.6, 192.2, 189, 188.1, 190.2, 193.7, 197.8, 202.9, 208.5,
336 215.6, 224.2, 233.1, 241.2, 247.3, 250.8, 251.3, 248.9, 244.2,
337 237.3, 228.4, 217.2, 202.9, 184.5, 162.5, 140.7, 124.8, 116.2,
338 111.8, 109.4, 107.9, 107, 106.7, 106.6, 106.6, 106.7, 106.7,
339 106.8, 107, 107.4, 108, 108.7, 109.3, 109.8, 110.4, 111.2,
340 112.4, 114.2, 116.9, 121.1, 127.9, 139.3, 155.2, 173.6, 190.7,
341 206.1, 220.1, 232.3, 243, 251.8, 259.2, 265.7, 270.6, 275.3,
342 279.3, 283.3, 286.9, 289.7, 292.8, 296.1, 300.5, 303.9, 304.8,
344 {241.5, 239.6, 236.8, 237.4, 239.4, 242.3, 244.2, 246.4, 249.2,
345 253.6, 258.6, 262.7, 264.8, 264.2, 260.6, 254.1, 245.5, 235.3,
346 223.9, 211.7, 198.3, 183.1, 165.6, 147.1, 130.5, 118.7, 111.9,
347 108.1, 105.8, 104.3, 103.4, 102.8, 102.5, 102.4, 102.5, 102.5,
348 102.5, 102.7, 103.1, 103.8, 104.6, 105.4, 106.1, 107, 108.2,
349 109.9, 112.8, 117.5, 126, 140.4, 161, 181.9, 201.2, 216.8, 230.4,
350 241.8, 251.4, 259.9, 266.9, 272.8, 277.4, 280.4, 282.9, 284.6,
351 286.1, 287.4, 288.3, 289.5, 290.9, 294.2, 296.9, 297.5, 297.6},
352 {301.2, 300.3, 296.6, 295.4, 295, 294.3, 291.2, 287.4, 284.9, 284.7,
353 284.1, 281.5, 277.1, 270.4, 261.7, 250.6, 237.6, 223.1, 207.9, 192,
354 175.8, 158.8, 142.1, 127.6, 116.8, 109.9, 106, 103.6, 102.1, 101.1,
355 100.4, 99.96, 99.6, 99.37, 99.32, 99.32, 99.31, 99.46, 99.77, 100.2,
356 100.7, 101.3, 101.8, 102.7, 104.1, 106.8, 111.9, 121, 136.7, 160,
357 186.9, 209.9, 228.1, 241.2, 251.5, 259.5, 265.7, 270.9, 274.8, 278,
358 280.3, 281.8, 283, 283.3, 283.7, 283.8, 283, 282.2, 281.2, 281.4,
361 memcpy(clim->
tropo, tropo,
sizeof(clim->
tropo));
364 double tropomin = 1e99, tropomax = -1e99;
366 for (
int iy = 0; iy < clim->
tropo_nlat; iy++) {
367 tropomin =
MIN(tropomin, clim->
tropo[it][iy]);
368 tropomax =
MAX(tropomax, clim->
tropo[it][iy]);
373 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
377 LOG(2,
"Latitudes: %g, %g ... %g deg",
380 LOG(2,
"Tropopause altitude range: %g ... %g hPa",
Z(tropomax),
382 LOG(2,
"Tropopause pressure range: %g ... %g hPa", tropomin, tropomax);
392 if (t <= ts->time[0])
399 ts->
time[idx + 1], ts->
vmr[idx + 1], t);
412 double sec =
FMOD(t, 365.25 * 86400.);
414 sec += 365.25 * 86400.;
418 if (p < zm->p[zm->
np - 1])
419 p_help = zm->
p[zm->
np - 1];
420 else if (p > zm->
p[0])
424 double lat_help = lat;
425 if (lat < zm->lat[0])
426 lat_help = zm->
lat[0];
427 else if (lat > zm->
lat[zm->
nlat - 1])
428 lat_help = zm->
lat[zm->
nlat - 1];
436 const double aux00 =
LIN(zm->
p[ip], zm->
vmr[isec][ip][ilat],
437 zm->
p[ip + 1], zm->
vmr[isec][ip + 1][ilat],
439 const double aux01 =
LIN(zm->
p[ip], zm->
vmr[isec][ip][ilat + 1],
440 zm->
p[ip + 1], zm->
vmr[isec][ip + 1][ilat + 1],
442 const double aux10 =
LIN(zm->
p[ip], zm->
vmr[isec + 1][ip][ilat],
443 zm->
p[ip + 1], zm->
vmr[isec + 1][ip + 1][ilat],
445 const double aux11 =
LIN(zm->
p[ip], zm->
vmr[isec + 1][ip][ilat + 1],
446 zm->
p[ip + 1], zm->
vmr[isec + 1][ip + 1][ilat + 1],
449 LIN(zm->
lat[ilat], aux00, zm->
lat[ilat + 1], aux01, lat_help);
451 LIN(zm->
lat[ilat], aux10, zm->
lat[ilat + 1], aux11, lat_help);
452 const double aux =
LIN(zm->
time[isec], aux0, zm->
time[isec + 1], aux1, sec);
453 return MAX(aux, 0.0);
467 const int decompress,
471 const size_t nxy = nx * ny;
472 double lon[
EX], lat[
EY];
473 for (
size_t ix = 0; ix < nx; ix++)
474 lon[ix] = 360. * (
double) ix / ((double) nx - 1.);
475 for (
size_t iy = 0; iy < ny; iy++)
476 lat[iy] = 90. - 180. * (
double) iy / ((double) ny - 1.);
479 const char domain[] =
"[0.0, 360.0]x[-90.0, 90.0]";
483 cms_param_t *cms_param
484 = cms_set_parameters(nx, ny, max_level_grid, Nd0_x, Nd0_y, domain);
487 double cr = 0, t_coars = 0, t_eval = 0;
493 for (
size_t ip = 0; ip < np; ip++) {
496 cms_module_t *cms_ptr = cms_init(cms_param);
501 cms_sol = cms_read_zstd_sol(cms_ptr, inout);
503 cms_sol = cms_read_sol(cms_ptr, inout);
506#pragma omp parallel for collapse(2) default(shared)
507 for (
size_t ix = 0; ix < nx; ix++)
508 for (
size_t iy = 0; iy < ny; iy++) {
510 const double x[] = { lon[ix], lat[iy] };
511 cms_eval(cms_ptr, cms_sol, x, &val);
512 array[
ARRAY_3D(ix, iy, ny, ip, np)] = (float) val;
516 cr += 1.0 / cms_compression_rate(cms_ptr, cms_sol);
519 cms_delete_sol(cms_sol);
520 cms_delete_module(cms_ptr);
524 LOG(2,
"Read 3-D variable: %s (CMS, RATIO= %g)", varname,
532 cms_module_t *cms_ptr[
EP];
533 cms_sol_t *cms_sol[
EP];
537 ? (size_t) omp_get_max_threads()
539 for (
size_t ip0 = 0; ip0 < np; ip0 += dip) {
542 double t0 = omp_get_wtime();
545#pragma omp parallel for default(shared)
546 for (
size_t ip = ip0; ip <
MIN(ip0 + dip, np); ip++) {
550 ALLOC(tmp_arr,
float,
554 for (
size_t ix = 0; ix < nx; ++ix)
555 for (
size_t iy = 0; iy < ny; ++iy)
557 array[
ARRAY_3D(ix, iy, ny, ip, np)];
560 double c_thresh_test;
561 if (strcasecmp(varname,
"Z") == 0)
563 else if (strcasecmp(varname,
"T") == 0)
565 else if (strcasecmp(varname,
"U") == 0)
567 else if (strcasecmp(varname,
"V") == 0)
569 else if (strcasecmp(varname,
"W") == 0)
571 else if (strcasecmp(varname,
"PV") == 0)
573 else if (strcasecmp(varname,
"H2O") == 0)
575 else if (strcasecmp(varname,
"O3") == 0)
577 else if (strcasecmp(varname,
"LWC") == 0)
579 else if (strcasecmp(varname,
"RWC") == 0)
581 else if (strcasecmp(varname,
"IWC") == 0)
583 else if (strcasecmp(varname,
"SWC") == 0)
585 else if (strcasecmp(varname,
"CC") == 0)
588 ERRMSG(
"Variable name unknown!");
591 cms_ptr[ip] = cms_init(cms_param);
595 cms_read_arr_new(cms_ptr[ip], tmp_arr, lon, lat,
596 nx, ny, c_thresh_test);
603 t_coars += (omp_get_wtime() - t0);
606 for (
size_t ip = ip0; ip <
MIN(ip0 + dip, np); ip++) {
609 double *tmp_cms, *tmp_org, *tmp_diff;
610 ALLOC(tmp_cms,
double,
612 ALLOC(tmp_org,
double,
614 ALLOC(tmp_diff,
double,
618 t0 = omp_get_wtime();
621#pragma omp parallel for collapse(2) default(shared)
622 for (
size_t ix = 0; ix < nx; ix++)
623 for (
size_t iy = 0; iy < ny; iy++) {
624 const size_t idx =
ARRAY_2D(ix, iy, ny);
625 const double x[] = { lon[ix], lat[iy] };
626 cms_eval(cms_ptr[ip], cms_sol[ip], x, &tmp_cms[idx]);
627 tmp_org[idx] = array[
ARRAY_3D(ix, iy, ny, ip, np)];
628 tmp_diff[idx] = tmp_cms[idx] - tmp_org[idx];
632 t_eval += (omp_get_wtime() - t0);
635 const double bias = gsl_stats_mean(tmp_diff, 1, nxy);
636 const double stddev = gsl_stats_sd_m(tmp_diff, 1, nxy, bias);
639 gsl_stats_max(tmp_org, 1, nxy) - gsl_stats_min(tmp_org, 1, nxy);
640 const double nrmse = (range > 0 ? rmse / range : NAN);
642 "cmultiscale: var= %s / lev= %lu / plev= %g / ratio= %g / rho= %g"
643 " / mean= %g / sd= %g / min= %g / max= %g / NRMSE= %g", varname,
644 ip, plev[ip], cms_compression_rate(cms_ptr[ip], cms_sol[ip]),
645 gsl_stats_correlation(tmp_cms, 1, tmp_org, 1, nxy), bias,
stddev,
646 gsl_stats_min(tmp_diff, 1, nxy), gsl_stats_max(tmp_diff, 1, nxy),
650 cr += 1.0 / cms_compression_rate(cms_ptr[ip], cms_sol[ip]);
654 cms_save_zstd_sol(cms_sol[ip], inout, 3);
656 cms_save_sol(cms_sol[ip], inout);
659 cms_delete_sol(cms_sol[ip]);
660 cms_delete_module(cms_ptr[ip]);
668 LOG(2,
"Write 3-D variable: %s"
669 " (CMS, RATIO= %g, T_COARS= %g s, T_EVAL= %g s)",
670 varname, (
double) np / cr, t_coars, t_eval);
674 cms_delete_param(cms_param);
685 const int decompress,
688 double min[
EP], max[
EP], off[
EP], scl[
EP];
690 unsigned short *sarray;
693 ALLOC(sarray,
unsigned short,
700 LOG(2,
"Read 3-D variable: %s (pck, RATIO= %g)",
701 varname, (
double)
sizeof(
float) / (
double)
sizeof(
unsigned short));
710 FREAD(sarray,
unsigned short,
715#pragma omp parallel for default(shared)
716 for (
size_t ixy = 0; ixy < nxy; ixy++)
717 for (
size_t iz = 0; iz < nz; iz++)
719 = (
float) (sarray[ixy * nz + iz] * scl[iz] + off[iz]);
726 LOG(2,
"Write 3-D variable: %s (pck, RATIO= %g)",
727 varname, (
double)
sizeof(
float) / (
double)
sizeof(
unsigned short));
730 for (
size_t iz = 0; iz < nz; iz++) {
734 for (
size_t ixy = 1; ixy < nxy; ixy++)
735 for (
size_t iz = 0; iz < nz; iz++) {
736 if (array[ixy * nz + iz] < min[iz])
737 min[iz] = array[ixy * nz + iz];
738 if (array[ixy * nz + iz] > max[iz])
739 max[iz] = array[ixy * nz + iz];
743 for (
size_t iz = 0; iz < nz; iz++) {
744 scl[iz] = (max[iz] - min[iz]) / 65533.;
749#pragma omp parallel for default(shared)
750 for (
size_t ixy = 0; ixy < nxy; ixy++)
751 for (
size_t iz = 0; iz < nz; iz++)
753 sarray[ixy * nz + iz] = (
unsigned short)
754 ((array[ixy * nz + iz] - off[iz]) / scl[iz] + .5);
756 sarray[ixy * nz + iz] = 0;
765 FWRITE(sarray,
unsigned short,
787 if ((precision > 0) == (tolerance > 0.0))
788 ERRMSG(
"Exactly one of precision or tolerance must be set for SZ3!");
790 size_t r1 = (size_t) nx, r2 = (
size_t) ny, r3 = (size_t) nz,
791 outSize = 0, total_elems = r1 * r2 * r3;
793 unsigned char *bytes = NULL;
799 FREAD(&sz3size,
size_t,
804 FREAD(bytes,
unsigned char,
808 void *outData = SZ_decompress(SZ_FLOAT, bytes, sz3size, 0, 0, r3, r2, r1);
810 ERRMSG(
"Decompression failed!");
812 memcpy(array, outData, total_elems *
sizeof(
float));
817 LOG(2,
"Read 3-D variable: %s (SZ3, PREC=%d, TOL=%g, RATIO=%g)",
818 varname, precision, tolerance,
819 (
double) (total_elems *
sizeof(
float)) / (
double) sz3size);
825 const int errBoundMode = (precision > 0) ? REL : ABS;
826 const double absBound = (errBoundMode == ABS) ? tolerance : 0.0;
827 const double relBound =
828 (errBoundMode == REL) ? pow(2.0, -(
double) precision) : 0.0;
830 bytes = SZ_compress_args(SZ_FLOAT, array, &outSize,
831 errBoundMode, absBound, relBound, 0.0,
833 if (!bytes || outSize == 0)
834 ERRMSG(
"Compression failed!");
839 FWRITE(bytes,
unsigned char,
845 LOG(2,
"Write 3-D variable: %s (SZ3, PREC=%d, TOL=%g, RATIO=%g)",
846 varname, precision, tolerance,
847 (
double) (total_elems *
sizeof(
float)) / (
double) outSize);
862 const double tolerance,
863 const int decompress,
867 const size_t snx = (size_t) nx;
868 const size_t sny = (size_t) ny;
869 const size_t snz = (size_t) nz;
870 const zfp_type type = zfp_type_float;
871 zfp_field *field = zfp_field_3d(array, type, snx, sny, snz);
874 zfp_stream *zfp = zfp_stream_open(NULL);
876 ERRMSG(
"Failed to allocate zfp structures!");
880 double actual_tol = 0;
881 if ((precision > 0 && tolerance > 0) || (precision <= 0 && tolerance <= 0)) {
882 ERRMSG(
"Exactly one of precision or tolerance must be set for zfp!");
883 }
else if (precision > 0)
885 (int) zfp_stream_set_precision(zfp, (
unsigned int) precision);
886 else if (tolerance > 0)
887 actual_tol = zfp_stream_set_accuracy(zfp, tolerance);
890 const size_t bufsize = zfp_stream_maximum_size(zfp, field);
896 bitstream *stream = stream_open(buffer, bufsize);
897 zfp_stream_set_bit_stream(zfp, stream);
898 zfp_stream_rewind(zfp);
903 FREAD(&zfpsize,
size_t,
906 if (zfpsize > bufsize)
907 ERRMSG(
"Compressed data size exceeds allocated buffer!");
908 FREAD(buffer,
unsigned char,
911 if (!zfp_decompress(zfp, field)) {
912 ERRMSG(
"Decompression failed!");
915 ((double) (snx * sny * snz *
sizeof(
float))) / (double) zfpsize;
916 const double bpv = (8.0 * (double) zfpsize) / (double) (snx * sny * snz);
918 "Read 3-D variable: %s (ZFP, PREC= %d, TOL= %g, RATIO= %g, BPV= %g)",
919 varname, actual_prec, actual_tol, cr, bpv);
924 zfpsize = zfp_compress(zfp, field);
926 ERRMSG(
"Compression failed!");
931 FWRITE(buffer,
unsigned char,
936 ((double) (snx * sny * snz *
sizeof(
float))) / (double) zfpsize;
937 const double bpv = (8.0 * (double) zfpsize) / (double) (snx * sny * snz);
939 "Write 3-D variable: %s (ZFP, PREC= %d, TOL= %g, RATIO= %g, BPV= %g)",
940 varname, actual_prec, actual_tol, cr, bpv);
944 zfp_field_free(field);
945 stream_close(stream);
946 zfp_stream_close(zfp);
958 const int decompress,
963 const size_t uncomprLen = n *
sizeof(float);
964 size_t compsize, comprLen = ZSTD_compressBound(uncomprLen);
967 char *compr = calloc(comprLen, 1);
969 ERRMSG(
"Memory allocation failed!");
970 char *uncompr = (
char *) array;
974 FREAD(&comprLen,
size_t,
977 FREAD(compr,
unsigned char,
980 compsize = ZSTD_decompress(uncompr, uncomprLen, compr, comprLen);
981 if (ZSTD_isError(compsize) || compsize != uncomprLen)
982 ERRMSG(
"Decompression failed or size mismatch!");
983 LOG(2,
"Read 3-D variable: %s (ZSTD, RATIO= %g)",
984 varname, ((
double) uncomprLen) / (
double) comprLen);
989 compsize = ZSTD_compress(compr, comprLen, uncompr, uncomprLen, level);
990 if (ZSTD_isError(compsize)) {
991 ERRMSG(
"Compression failed!");
996 FWRITE(compr,
unsigned char,
1000 LOG(2,
"Write 3-D variable: %s (ZSTD, RATIO= %g)",
1001 varname, ((
double) uncomprLen) / (
double) compsize);
1017 const double D = sec / 86400 - 0.5;
1020 const double g =
DEG2RAD(357.529 + 0.98560028 * D);
1021 const double q = 280.459 + 0.98564736 * D;
1022 const double L =
DEG2RAD(q + 1.915 * sin(g) + 0.020 * sin(2 * g));
1025 const double e =
DEG2RAD(23.439 - 0.00000036 * D);
1028 const double sindec = sin(e) * sin(L);
1031 const double ra = atan2(cos(e) * sin(L), cos(L));
1034 const double GMST = 18.697374558 + 24.06570982441908 * D;
1037 const double LST = GMST + lon / 15;
1040 const double h = LST / 12 * M_PI - ra;
1043 const double lat_help =
DEG2RAD(lat);
1046 return sin(lat_help) * sindec + cos(lat_help) * sqrt(1 -
1047 SQR(sindec)) * cos(h);
1059 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
1060 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
1063 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
1064 *doy = d0l[mon - 1] + day - 1;
1066 *doy = d0[mon - 1] + day - 1;
1082#pragma acc enter data create(dd)
1083#pragma acc update device(dd->rank, dd->subdomain_lon_min, dd->subdomain_lon_max, dd->subdomain_lat_min, dd->subdomain_lat_max)
1084#pragma acc data present(atm, ctl, dd)
1085#pragma acc parallel loop independent gang vector
1087 for (
int ip = 0; ip < atm->
np; ip++) {
1089 double lont = atm->
lon[ip];
1100 (
"DD: Particle is outside the domain (lon: %f, lat: %f, subdomain: %d, subdomain bounds: [%f, %f], [%f, %f])",
1109#pragma acc exit data delete(dd)
1115#pragma acc enter data create(dd)
1116#pragma acc update device(dd->neighbours[:DD_NNMAX], dd->rank, dd->size, dd->subdomain_lon_min, dd->subdomain_lon_max, dd->subdomain_lat_min, dd->subdomain_lat_max)
1117#pragma acc data present(atm, ctl, dd)
1118#pragma acc parallel loop independent gang vector
1120 for (
int ip = 0; ip < atm->
np; ip++) {
1126 double lont = atm->
lon[ip];
1127 double latt = atm->
lat[ip];
1142 bound = (lont - lon_max > 90) ? 1 : 0;
1144 bound = (lon_min - lont > 90) ? 1 : 0;
1147 if ((lont >= lon_max) && (latt >= lat_max)) {
1152 "DD: Particle crossing to upper right: from rank %d to rank %d (lon: %f, lat: %f)",
1154 }
else if ((lont >= lon_max) && (latt <= lat_min)) {
1159 "DD: Particle crossing to lower right: from rank %d to rank %d (lon: %f, lat: %f)",
1161 }
else if ((lont <= lon_min) && (latt >= lat_max)) {
1166 "DD: Particle crossing to upper left: from rank %d to rank %d (lon: %f, lat: %f)",
1168 }
else if ((lont <= lon_min) && (latt <= lat_min)) {
1173 "DD: Particle crossing to lower left: from rank %d to rank %d (lon: %f, lat: %f)",
1175 }
else if (lont >= lon_max) {
1180 "DD: Particle crossing to right: from rank %d to rank %d (lon: %f, lat: %f)",
1182 }
else if (lont <= lon_min) {
1187 "DD: Particle crossing to left: from rank %d to rank %d (lon: %f, lat: %f)",
1189 }
else if (latt <= lat_min) {
1194 "DD: Particle crossing downward: from rank %d to rank %d (lon: %f, lat: %f)",
1196 }
else if (latt >= lat_max) {
1201 "DD: Particle crossing upward: from rank %d to rank %d (lon: %f, lat: %f)",
1209 if ((lont >= lon_max) && (latt >= lat_max)) {
1214 "DD: Particle crossing to upper left (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1216 }
else if ((lont >= lon_max) && (latt <= lat_min)) {
1221 "DD: Particle crossing to lower left (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1223 }
else if ((lont <= lon_min) && (latt >= lat_max)) {
1228 "DD: Particle crossing to upper right (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1230 }
else if ((lont <= lon_min) && (latt <= lat_min)) {
1235 "DD: Particle crossing to lower right (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1237 }
else if (lont >= lon_max) {
1242 "DD: Particle crossing to left (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1244 }
else if (lont <= lon_min) {
1249 "DD: Particle crossing to right (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1251 }
else if (latt <= lat_min) {
1256 "DD: Particle crossing downward (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1258 }
else if (latt >= lat_max) {
1263 "DD: Particle crossing upward (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1273#pragma acc exit data delete(dd)
1294 int npart = *nparticles;
1295#pragma acc enter data create( nparticles, particles[:DD_NPART])
1296#pragma acc update device( nparticles)
1297#pragma acc parallel loop present( atm, ctl, particles, cache, nparticles)
1299 for (
int ip = atm->
np; ip < atm->np + *nparticles; ip++)
1304 particles[ip - atm->
np].
time = atm->
time[ip];
1305 particles[ip - atm->
np].
lon = atm->
lon[ip];
1306 particles[ip - atm->
np].
lat = atm->
lat[ip];
1307 particles[ip - atm->
np].
p = atm->
p[ip];
1308 for (
int iq = 0; iq < ctl->
nq; iq++)
1309 particles[ip - atm->
np].q[iq] = atm->
q[iq][ip];
1312 "DD: Particle being prepared for transfer: subdomain %d -> destination %d (lon: %f, lat: %f)",
1319#pragma acc update host( particles[:npart])
1320#pragma acc exit data delete( nparticles, particles)
1338 double wrapped_lon = lon;
1339 while (wrapped_lon < 0)
1341 while (wrapped_lon >= 360)
1345 double wrapped_lat = lat;
1349 wrapped_lat = 180 - lat;
1350 wrapped_lon = fmod(wrapped_lon + 180, 360);
1351 }
else if (lat < -90) {
1354 wrapped_lat = -180 - lat;
1355 wrapped_lon = fmod(wrapped_lon + 180, 360);
1359 double lon_range = 360.0;
1360 LOG(2,
"nx_glob: %d", nx_glob);
1361 double lat_range = met->
lat[ny_glob - 1] - met->
lat[0];
1362 double global_lon_min = met->
lon[0];
1363 double global_lat_min = met->
lat[0];
1367 (int) ((wrapped_lon -
1370 (int) ((wrapped_lat -
1375 (
"DD: Input Lon: %f, Lat: %f | Wrapped Lon: %f, Lat: %f | Lon Range: %f, Lat Range: %f | Lon Min: %f, Lat Min: %f | Lon Idx: %d, Lat Idx: %d\n",
1376 lon, lat, wrapped_lon, wrapped_lat, lon_range, lat_range, global_lon_min,
1377 global_lat_min, lon_idx, lat_idx);
1382 0) ? 0 : ((lon_idx >=
1387 0) ? 0 : ((lat_idx >=
1389 dd_subdomains_meridional - 1 : lat_idx);
1395 if (target_rank >= mpi_size)
1396 target_rank = mpi_size - 1;
1397 if (target_rank < 0)
1427 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
1430 MPI_Request *requests_snd_nbr =
1431 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1432 MPI_Request *requests_rcv_nbr =
1433 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1434 MPI_Request *requests_snd_part =
1435 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1436 MPI_Request *requests_rcv_part =
1437 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1438 MPI_Status *states =
1439 (MPI_Status *) calloc((
size_t) nneighbours,
sizeof(MPI_Status));
1442 for (
int i = 0; i < nneighbours; i++) {
1443 requests_snd_nbr[i] = MPI_REQUEST_NULL;
1444 requests_rcv_nbr[i] = MPI_REQUEST_NULL;
1445 requests_snd_part[i] = MPI_REQUEST_NULL;
1446 requests_rcv_part[i] = MPI_REQUEST_NULL;
1450 for (
int idest = 0; idest < nneighbours; idest++) {
1453 if (neighbours[idest] < 0)
1459 for (
int ip = 0; ip < *nparticles; ip++)
1462 nbs[idest] = help_sum;
1465 LOG(3,
"DD: Rank %d sending %d particles to neighbour %d (rank %d)",
1466 rank, help_sum, idest, neighbours[idest]);
1471 MPI_Isend(&nbs[idest], 1, MPI_INT,
1472 neighbours[idest], 0, MPI_COMM_WORLD, &requests_snd_nbr[idest]);
1475 if (nbs[idest] == 0)
1484 for (
int ip = 0; ip < *nparticles; ip++) {
1485 if ((
int) particles[ip].q[ctl.
qnt_destination] == neighbours[idest]) {
1486 memcpy(&send_buffers[idest][ibs], &particles[ip],
sizeof(
particle_t));
1490 if (ibs == nbs[idest])
1497 MPI_Isend(send_buffers[idest], nbs[idest], MPI_Particle,
1498 neighbours[idest], 1, MPI_COMM_WORLD,
1499 &requests_snd_part[idest]);
1505 for (
int isourc = 0; isourc < nneighbours; isourc++) {
1508 if (neighbours[isourc] < 0) {
1509 requests_rcv_nbr[isourc] = MPI_REQUEST_NULL;
1514 MPI_Irecv(&nbr[isourc], 1, MPI_INT, neighbours[isourc], 0, MPI_COMM_WORLD,
1515 &requests_rcv_nbr[isourc]);
1519 MPI_Waitall(nneighbours, requests_rcv_nbr, states);
1522 for (
int isourc = 0; isourc < nneighbours; isourc++) {
1525 if ((neighbours[isourc] < 0) || (nbr[isourc] == 0)) {
1526 requests_rcv_part[isourc] = MPI_REQUEST_NULL;
1534 MPI_Irecv(recieve_buffers[isourc], nbr[isourc], MPI_Particle,
1535 neighbours[isourc], 1, MPI_COMM_WORLD,
1536 &requests_rcv_part[isourc]);
1540 MPI_Waitall(nneighbours, requests_rcv_part, states);
1548 for (
int isourc = 0; isourc < nneighbours; isourc++) {
1551 if (neighbours[isourc] < 0)
1554 if (nbr[isourc] > 0) {
1555 LOG(3,
"DD: Rank %d receiving %d particles from neighbour %d (rank %d)",
1556 rank, nbr[isourc], isourc, neighbours[isourc]);
1560 for (
int ip = 0; ip < nbr[isourc]; ip++) {
1561 memcpy(&particles[ip + api], &recieve_buffers[isourc][ip],
1575 MPI_Waitall(nneighbours, requests_snd_part, states);
1576 MPI_Waitall(nneighbours, requests_snd_nbr, states);
1579 for (
int i = 0; i < nneighbours; i++) {
1581 if ((send_buffers[i] != NULL) && (nbs[i] != 0)) {
1582 free(send_buffers[i]);
1583 send_buffers[i] = NULL;
1586 if ((recieve_buffers[i] != NULL) && (nbr[i] != 0)) {
1587 free(recieve_buffers[i]);
1588 recieve_buffers[i] = NULL;
1605 const int rank = dd->
rank;
1606 const int size = dd->
size;
1610 nb[0] = (size + rank - m) % size;
1611 nb[3] = (rank + m) % size;
1612 nb[1] = ((rank + 1) % m == 0) ?
DD_SPOLE : (size + rank - m + 1) % size;
1613 nb[2] = (rank % m == 0) ?
DD_NPOLE : (size + rank - m - 1) % size;
1614 nb[4] = ((rank + 1) % m == 0) ?
DD_SPOLE : (rank + m + 1) % size;
1615 nb[5] = (rank % m == 0) ?
DD_NPOLE : (rank + m - 1) % size;
1616 nb[6] = (rank % m == 0) ?
DD_NPOLE : rank - 1;
1617 nb[7] = ((rank + 1) % m == 0) ?
DD_SPOLE : rank + 1;
1633 double lon_spacing = met->
lon[1] - met->
lon[0];
1637 double total_range = met->
lon[nx_glob - 1] - met->
lon[0] + lon_spacing;
1640 return (fabs(total_range - 360.0) < 0.01);
1654 ERRMSG(
"The number of tasks and subdomains is not identical.");
1683 int npart = *nparticles;
1684#pragma acc enter data create(nparticles, particles[:DD_NPART])
1685#pragma acc update device(particles[:npart], nparticles)
1686#pragma acc data present(atm, ctl, cache, particles, nparticles)
1687#pragma acc parallel loop
1689 for (
int ip = atm->
np; ip < atm->np + *nparticles; ip++) {
1690 atm->
time[ip] = particles[ip - atm->
np].
time;
1691 atm->
lon[ip] = particles[ip - atm->
np].
lon;
1692 atm->
lat[ip] = particles[ip - atm->
np].
lat;
1693 atm->
p[ip] = particles[ip - atm->
np].
p;
1694 for (
int iq = 0; iq < ctl->
nq; iq++)
1695 atm->
q[iq][ip] = particles[ip - atm->
np].q[iq];
1699#pragma acc exit data delete(nparticles, particles)
1703 atm->
np += *nparticles;
1705#pragma acc update device(atm->np)
1708 ERRMSG(
"Number of particles to high. Increase NP!");
1718 MPI_Datatype types[5] = { MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE,
1719 MPI_DOUBLE, MPI_DOUBLE
1722 int blocklengths[5] = { 1, 1, 1, 1,
NQ };
1724 MPI_Aint displacements[5] = { offsetof(
particle_t, time),
1731 MPI_Type_create_struct(5, blocklengths, displacements, types, MPI_Particle);
1732 MPI_Type_commit(MPI_Particle);
1751 const int np = atm->
np;
1752 double amax = (met0->
nx * met0->
ny + met0->
ny) * met0->
np + met0->
np;
1754#pragma acc enter data create(amax, rank)
1755#pragma acc update device(rank, amax)
1756#pragma acc data present(ctl,met0,atm,dd,amax,rank)
1761#pragma acc parallel loop independent gang vector
1763#pragma omp parallel for default(shared)
1765 for (
int ip = 0; ip < np; ip++) {
1773 dd->a[ip] = amax + 1;
1775 dd->a[ip] = amax + 2;
1783#pragma acc host_data use_device(dd->a,dd->p)
1785 thrustSortWrapper(dd->a, np, dd->p);
1788 ERRMSG(
"GSL sort fallback not available on GPU, use THRUST!");
1790 gsl_sort_index((
size_t *) (dd->p), (dd->a), 1, (
size_t) np);
1798 for (
int iq = 0; iq < ctl->
nq; iq++)
1804#pragma acc parallel loop reduction(+:npt) present(atm, rank, ctl)
1806 for (
int ip = 0; ip < np; ip++)
1812 int nparticlest = 0;
1814#pragma acc parallel loop reduction(+:nparticlest) present(atm, rank, ctl)
1816 for (
int ip = npt; ip < np; ip++)
1822 *nparticles = nparticlest;
1826 for (
int ip = 0; ip < np; ip++)
1832 (
"DD: Rank %d: %d particles have subdomain index -1 and will be lost (kept: %d, to_send: %d, total_before: %d)",
1833 *rank, nlost, npt, nparticlest, np);
1838#pragma acc update device(atm->np)
1843 (
"Number of particles to send and recieve to small. Increase DD_NPART!");
1847#pragma acc exit data delete(amax, rank)
1862#pragma acc data present(dd,a)
1863#pragma acc parallel loop independent gang vector
1865#pragma omp parallel for default(shared)
1867 for (
int ip = 0; ip < np; ip++)
1868 dd->help[ip] = a[dd->p[ip]];
1870#pragma acc parallel loop independent gang vector
1872#pragma omp parallel
for default(shared)
1874 for (
int ip = 0; ip < np; ip++)
1875 a[ip] = dd->help[ip];
1888 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
1889 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
1894 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
1895 for (i = 11; i > 0; i--)
1899 *day = doy - d0l[i] + 1;
1901 for (i = 11; i > 0; i--)
1905 *day = doy - d0[i] + 1;
1916 double data[2 *
EX];
1920 ERRMSG(
"Too many data points!");
1923 gsl_fft_complex_wavetable *wavetable =
1924 gsl_fft_complex_wavetable_alloc((
size_t) n);
1925 gsl_fft_complex_workspace *workspace =
1926 gsl_fft_complex_workspace_alloc((
size_t) n);
1929 for (
int i = 0; i < n; i++) {
1930 data[2 * i] = fcReal[i];
1931 data[2 * i + 1] = fcImag[i];
1935 gsl_fft_complex_forward(data, 1, (
size_t) n, wavetable, workspace);
1938 for (
int i = 0; i < n; i++) {
1939 fcReal[i] = data[2 * i];
1940 fcImag[i] = data[2 * i + 1];
1944 gsl_fft_complex_wavetable_free(wavetable);
1945 gsl_fft_complex_workspace_free(workspace);
1956 const double radius = z +
RE;
1957 const double latrad =
DEG2RAD(lat);
1958 const double lonrad =
DEG2RAD(lon);
1959 const double coslat = cos(latrad);
1961 x[0] = radius * coslat * cos(lonrad);
1962 x[1] = radius * coslat * sin(lonrad);
1963 x[2] = radius * sin(latrad);
1972 const char *metbase,
1973 const double dt_met,
1980 int year, mon, day, hour, min, sec;
1984 t6 = floor(t / dt_met) * dt_met;
1986 t6 = ceil(t / dt_met) * dt_met;
1989 jsec2time(t6, &year, &mon, &day, &hour, &min, &sec, &r);
1994 sprintf(filename,
"%s_YYYY_MM_DD_HH.nc", metbase);
1996 sprintf(filename,
"%s_YYYY_MM_DD_HH.bin", metbase);
1998 sprintf(filename,
"%s_YYYY_MM_DD_HH.pck", metbase);
2000 sprintf(filename,
"%s_YYYY_MM_DD_HH.zfp", metbase);
2002 sprintf(filename,
"%s_YYYY_MM_DD_HH.zstd", metbase);
2004 sprintf(filename,
"%s_YYYY_MM_DD_HH.cms", metbase);
2006 sprintf(filename,
"%s_YYYY_MM_DD_HH.sz3", metbase);
2007 sprintf(repl,
"%d", year);
2009 sprintf(repl,
"%02d", mon);
2011 sprintf(repl,
"%02d", day);
2013 sprintf(repl,
"%02d", hour);
2019 sprintf(filename,
"%s_YYMMDDHH.nc", metbase);
2020 sprintf(repl,
"%d", year);
2022 sprintf(repl,
"%02d", year % 100);
2024 sprintf(repl,
"%02d", mon);
2026 sprintf(repl,
"%02d", day);
2028 sprintf(repl,
"%02d", hour);
2043 for (
int i = 0; i < 3; i++) {
2047 if (!(ch = strstr(orig, search)))
2049 strncpy(buffer, orig, (
size_t) (ch - orig));
2050 buffer[ch - orig] = 0;
2051 sprintf(buffer + (ch - orig),
"%s%s", repl, ch + strlen(search));
2053 strcpy(orig, buffer);
2060 const int met_tropo,
2080#pragma omp parallel for default(shared) private(ci,cw)
2081 for (
int ix = 0; ix < nx; ix++)
2082 for (
int iy = 0; iy < ny; iy++) {
2084 &pt[iy * nx + ix], ci, cw, 1);
2086 &ps[iy * nx + ix], ci, cw, 0);
2088 &zs[iy * nx + ix], ci, cw, 0);
2090 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
2092 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
2094 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
2096 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
2113 *lon2 =
FMOD(lon, 360.);
2114 if (*lon2 < lons[0])
2116 else if (*lon2 > lons[nlon - 1])
2121 if (lats[0] < lats[nlat - 1])
2122 *lat2 =
MIN(
MAX(*lat2, lats[0]), lats[nlat - 1]);
2124 *lat2 =
MIN(
MAX(*lat2, lats[nlat - 1]), lats[0]);
2131 float heights0[
EX][
EY][
EP],
2132 float array0[
EX][
EY][
EP],
2134 float heights1[
EX][
EY][
EP],
2135 float array1[
EX][
EY][
EP],
2137 const double height,
2163 int k_max = ind[0][0];
2164 for (
int i = 0; i < 2; i++)
2165 for (
int j = 0; j < 4; j++) {
2166 if (ci[2] > ind[i][j])
2168 if (k_max < ind[i][j])
2174 cw[0] = (lon2 - met0->
lon[ci[0]]) /
2175 (met0->
lon[ci[0] + 1] - met0->
lon[ci[0]]);
2176 cw[1] = (lat2 - met0->
lat[ci[1]]) /
2177 (met0->
lat[ci[1] + 1] - met0->
lat[ci[1]]);
2180 double height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2]]
2181 - heights0[ci[0]][ci[1]][ci[2]])
2182 + heights0[ci[0]][ci[1]][ci[2]];
2183 double height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2]]
2184 - heights0[ci[0]][ci[1] + 1][ci[2]])
2185 + heights0[ci[0]][ci[1] + 1][ci[2]];
2186 double height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2]]
2187 - heights0[ci[0] + 1][ci[1]][ci[2]])
2188 + heights0[ci[0] + 1][ci[1]][ci[2]];
2189 double height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2]]
2190 - heights0[ci[0] + 1][ci[1] + 1][ci[2]])
2191 + heights0[ci[0] + 1][ci[1] + 1][ci[2]];
2194 double height0 = cw[1] * (height01 - height00) + height00;
2195 double height1 = cw[1] * (height11 - height10) + height10;
2198 double height_bot = cw[0] * (height1 - height0) + height0;
2201 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
2202 - heights0[ci[0]][ci[1]][ci[2] + 1])
2203 + heights0[ci[0]][ci[1]][ci[2] + 1];
2204 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
2205 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
2206 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
2207 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
2208 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
2209 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
2210 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2211 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2212 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2215 height0 = cw[1] * (height01 - height00) + height00;
2216 height1 = cw[1] * (height11 - height10) + height10;
2219 double height_top = cw[0] * (height1 - height0) + height0;
2222 while (((heights0[0][0][0] > heights0[0][0][1]) &&
2223 ((height_bot <= height) || (height_top > height))
2224 && (height_bot >= height) && (ci[2] < k_max))
2226 ((heights0[0][0][0] < heights0[0][0][1]) &&
2227 ((height_bot >= height) || (height_top < height))
2228 && (height_bot <= height) && (ci[2] < k_max))
2232 height_bot = height_top;
2235 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
2236 - heights0[ci[0]][ci[1]][ci[2] + 1])
2237 + heights0[ci[0]][ci[1]][ci[2] + 1];
2238 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
2239 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
2240 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
2241 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
2242 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
2243 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
2244 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2245 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2246 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2249 height0 = cw[1] * (height01 - height00) + height00;
2250 height1 = cw[1] * (height11 - height10) + height10;
2253 height_top = cw[0] * (height1 - height0) + height0;
2257 cw[2] = (height - height_bot)
2258 / (height_top - height_bot);
2262 const double array000 = cw[3] * (array1[ci[0]][ci[1]][ci[2]]
2263 - array0[ci[0]][ci[1]][ci[2]])
2264 + array0[ci[0]][ci[1]][ci[2]];
2265 const double array100 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2]]
2266 - array0[ci[0] + 1][ci[1]][ci[2]])
2267 + array0[ci[0] + 1][ci[1]][ci[2]];
2268 const double array010 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2]]
2269 - array0[ci[0]][ci[1] + 1][ci[2]])
2270 + array0[ci[0]][ci[1] + 1][ci[2]];
2271 const double array110 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2]]
2272 - array0[ci[0] + 1][ci[1] + 1][ci[2]])
2273 + array0[ci[0] + 1][ci[1] + 1][ci[2]];
2274 const double array001 = cw[3] * (array1[ci[0]][ci[1]][ci[2] + 1]
2275 - array0[ci[0]][ci[1]][ci[2] + 1])
2276 + array0[ci[0]][ci[1]][ci[2] + 1];
2277 const double array101 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2] + 1]
2278 - array0[ci[0] + 1][ci[1]][ci[2] + 1])
2279 + array0[ci[0] + 1][ci[1]][ci[2] + 1];
2280 const double array011 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2] + 1]
2281 - array0[ci[0]][ci[1] + 1][ci[2] + 1])
2282 + array0[ci[0]][ci[1] + 1][ci[2] + 1];
2283 const double array111 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2284 - array0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2285 + array0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2287 const double array00 = cw[0] * (array100 - array000) + array000;
2288 const double array10 = cw[0] * (array110 - array010) + array010;
2289 const double array01 = cw[0] * (array101 - array001) + array001;
2290 const double array11 = cw[0] * (array111 - array011) + array011;
2292 const double aux0 = cw[1] * (array10 - array00) + array00;
2293 const double aux1 = cw[1] * (array11 - array01) + array01;
2296 *var = cw[2] * (aux1 - aux0) + aux0;
2326 cw[0] = (met->
p[ci[0] + 1] - p)
2327 / (met->
p[ci[0] + 1] - met->
p[ci[0]]);
2328 cw[1] = (met->
lon[ci[1] + 1] - lon2)
2329 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
2330 cw[2] = (met->
lat[ci[2] + 1] - lat2)
2331 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
2335 const double aux00 =
2336 cw[0] * (array[ci[1]][ci[2]][ci[0]] - array[ci[1]][ci[2]][ci[0] + 1])
2337 + array[ci[1]][ci[2]][ci[0] + 1];
2338 const double aux01 =
2339 cw[0] * (array[ci[1]][ci[2] + 1][ci[0]] -
2340 array[ci[1]][ci[2] + 1][ci[0] + 1])
2341 + array[ci[1]][ci[2] + 1][ci[0] + 1];
2342 const double aux10 =
2343 cw[0] * (array[ci[1] + 1][ci[2]][ci[0]] -
2344 array[ci[1] + 1][ci[2]][ci[0] + 1])
2345 + array[ci[1] + 1][ci[2]][ci[0] + 1];
2346 const double aux11 =
2347 cw[0] * (array[ci[1] + 1][ci[2] + 1][ci[0]] -
2348 array[ci[1] + 1][ci[2] + 1][ci[0] + 1])
2349 + array[ci[1] + 1][ci[2] + 1][ci[0] + 1];
2352 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
2353 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
2354 *var = cw[1] * (aux0 - aux1) + aux1;
2361 float array[
EX][
EY],
2382 cw[1] = (met->
lon[ci[1] + 1] - lon2)
2383 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
2384 cw[2] = (met->
lat[ci[2] + 1] - lat2)
2385 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
2389 const double aux00 = array[ci[1]][ci[2]];
2390 const double aux01 = array[ci[1]][ci[2] + 1];
2391 const double aux10 = array[ci[1] + 1][ci[2]];
2392 const double aux11 = array[ci[1] + 1][ci[2] + 1];
2395 if (isfinite(aux00) && isfinite(aux01)
2396 && isfinite(aux10) && isfinite(aux11)) {
2397 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
2398 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
2399 *var = cw[1] * (aux0 - aux1) + aux1;
2419 float array0[
EX][
EY][
EP],
2421 float array1[
EX][
EY][
EP],
2438 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
2441 *var = wt * (var0 - var1) + var1;
2448 float array0[
EX][
EY],
2450 float array1[
EX][
EY],
2466 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
2469 if (isfinite(var0) && isfinite(var1))
2470 *var = wt * (var0 - var1) + var1;
2481 float array0[
EX][
EY],
2483 float array1[
EX][
EY],
2484 const double lons[
EX],
2485 const double lats[
EY],
2504 const int ix =
locate_reg(lons, (
int) nlon, lon2);
2505 const int iy =
locate_irr(lats, (
int) nlat, lat2);
2509 for (
int dx = 0; dx < 2; dx++)
2510 for (
int dy = 0; dy < 2; dy++) {
2511 if (isfinite(array0[ix + dx][iy + dy])) {
2512 mean += array0[ix + dx][iy + dy];
2513 *sigma +=
SQR(array0[ix + dx][iy + dy]);
2516 if (isfinite(array1[ix + dx][iy + dy])) {
2517 mean += array1[ix + dx][iy + dy];
2518 *sigma +=
SQR(array1[ix + dx][iy + dy]);
2523 *sigma = sqrt(
MAX(*sigma / n -
SQR(mean / n), 0.0));
2526 if (method == 1 && isfinite(array0[ix][iy])
2527 && isfinite(array0[ix][iy + 1])
2528 && isfinite(array0[ix + 1][iy])
2529 && isfinite(array0[ix + 1][iy + 1])
2530 && isfinite(array1[ix][iy])
2531 && isfinite(array1[ix][iy + 1])
2532 && isfinite(array1[ix + 1][iy])
2533 && isfinite(array1[ix + 1][iy + 1])) {
2535 const double aux00 =
LIN(lons[ix], array0[ix][iy],
2536 lons[ix + 1], array0[ix + 1][iy], lon2);
2537 const double aux01 =
LIN(lons[ix], array0[ix][iy + 1],
2538 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
2539 const double aux0 =
LIN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
2541 const double aux10 =
LIN(lons[ix], array1[ix][iy],
2542 lons[ix + 1], array1[ix + 1][iy], lon2);
2543 const double aux11 =
LIN(lons[ix], array1[ix][iy + 1],
2544 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
2545 const double aux1 =
LIN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
2547 *var =
LIN(time0, aux0, time1, aux1, time);
2552 const double aux00 =
NN(lons[ix], array0[ix][iy],
2553 lons[ix + 1], array0[ix + 1][iy], lon2);
2554 const double aux01 =
NN(lons[ix], array0[ix][iy + 1],
2555 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
2556 const double aux0 =
NN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
2558 const double aux10 =
NN(lons[ix], array1[ix][iy],
2559 lons[ix + 1], array1[ix + 1][iy], lon2);
2560 const double aux11 =
NN(lons[ix], array1[ix][iy + 1],
2561 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
2562 const double aux1 =
NN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
2564 *var =
NN(time0, aux0, time1, aux1, time);
2589 const time_t jsec0 = (time_t) jsec + timegm(&t0);
2590 t1 = gmtime(&jsec0);
2592 *year = t1->tm_year + 1900;
2593 *mon = t1->tm_mon + 1;
2595 *hour = t1->tm_hour;
2598 *remain = jsec - floor(jsec);
2604 const double kz[
EP],
2605 const double kw[
EP],
2614 const double z =
Z(p);
2619 else if (z > kz[nk - 1])
2623 return LIN(kz[idx], kw[idx], kz[idx + 1], kw[idx + 1], z);
2640 const double a =
RA *
SQR(t), r =
SH(h2o) / (1. -
SH(h2o));
2652 ERRMSG(
"MET_PRESS_LEVEL_DEF=0 is disabled. Use 3 for the extended L137 set.");
2656 ERRMSG(
"MET_PRESS_LEVEL_DEF=1 is disabled. Use 4 for the extended L91 set.");
2660 ERRMSG(
"MET_PRESS_LEVEL_DEF=2 is disabled. Use 5 for the extended L60 set.");
2666 const double press[147] = {
2667 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
2668 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
2669 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
2670 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
2671 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2672 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
2673 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
2674 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
2675 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
2676 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
2677 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
2678 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
2679 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
2680 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
2681 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
2682 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
2683 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
2684 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
2685 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73, 1028.85,
2687 1035.09, 1038.21, 1041.33, 1044.45
2690 for (
int ip = 0; ip < ctl->
met_np; ip++)
2697 const double press[101] = {
2698 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
2699 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
2700 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
2701 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
2702 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
2704 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
2705 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
2706 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
2707 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
2708 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
2709 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
2710 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
2711 1007.4431, 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73,
2713 1035.09, 1038.21, 1041.33, 1044.45
2716 for (
int ip = 0; ip < ctl->
met_np; ip++)
2723 const double press[62] = {
2724 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
2725 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
2726 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
2727 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
2728 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
2729 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
2730 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
2731 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1034.86, 1039.65,
2735 for (
int ip = 0; ip < ctl->
met_np; ip++)
2742 const double press[137] = {
2743 0.01, 0.02, 0.031, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861,
2744 0.2499, 0.3299, 0.4288, 0.5496, 0.6952, 0.869, 1.0742,
2745 1.3143, 1.5928, 1.9134, 2.2797, 2.6954, 3.1642, 3.6898,
2746 4.2759, 4.9262, 5.6441, 6.4334, 7.2974, 8.2397, 9.2634,
2747 10.372, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945, 18.9752,
2748 20.761, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2749 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.199, 54.5299,
2750 57.9834, 61.5607, 65.2695, 69.1187, 73.1187, 77.281, 81.6182,
2751 86.145, 90.8774, 95.828, 101.005, 106.415, 112.068, 117.971,
2752 124.134, 130.564, 137.27, 144.262, 151.549, 159.14, 167.045,
2753 175.273, 183.834, 192.739, 201.997, 211.619, 221.615, 231.995,
2754 242.772, 253.955, 265.556, 277.585, 290.055, 302.976, 316.361,
2755 330.22, 344.566, 359.411, 374.767, 390.645, 407.058, 424.019,
2756 441.539, 459.632, 478.31, 497.584, 517.42, 537.72, 558.343,
2757 579.193, 600.167, 621.162, 642.076, 662.808, 683.262, 703.347,
2758 722.979, 742.086, 760.6, 778.466, 795.64, 812.085, 827.776,
2759 842.696, 856.838, 870.2, 882.791, 894.622, 905.712, 916.081,
2760 925.757, 934.767, 943.14, 950.908, 958.104, 965.299, 972.495,
2761 979.69, 986.886, 994.081, 1001.28, 1008.47, 1015.67, 1022.86,
2762 1030.06, 1037.25, 1044.45
2765 for (
int ip = 0; ip < ctl->
met_np; ip++)
2772 const double press[59] = {
2773 0.1, 0.2, 0.3843, 0.6365, 0.9564, 1.3448, 1.8058, 2.3478,
2774 2.985, 3.7397, 4.6462, 5.7565, 7.1322, 8.8366, 10.9483,
2775 13.5647, 16.8064, 20.8227, 25.7989, 31.9642, 39.6029, 49.0671,
2776 60.1802, 73.0663, 87.7274, 104.229, 122.614, 142.902, 165.089,
2777 189.147, 215.025, 242.652, 272.059, 303.217, 336.044, 370.407,
2778 406.133, 443.009, 480.791, 519.209, 557.973, 596.777, 635.306,
2779 673.24, 710.263, 746.063, 780.346, 812.83, 843.263, 871.42,
2780 897.112, 920.189, 940.551, 958.148, 975.744, 993.341, 1010.94,
2784 for (
int ip = 0; ip < ctl->
met_np; ip++)
2788 ERRMSG(
"Use values between 3 and 7.");
2792 ERRMSG(
"Recompile with larger EP to use this pressure level definition.");
2805 int i = (ihi + ilo) >> 1;
2807 if (xx[i] < xx[i + 1])
2808 while (ihi > ilo + 1) {
2809 i = (ihi + ilo) >> 1;
2815 while (ihi > ilo + 1) {
2816 i = (ihi + ilo) >> 1;
2836 int i = (ihi + ilo) >> 1;
2838 if ((xx[ig] <= x && x < xx[ig + 1]) || (xx[ig] >= x && x > xx[ig + 1]))
2841 if (xx[i] < xx[i + 1])
2842 while (ihi > ilo + 1) {
2843 i = (ihi + ilo) >> 1;
2849 while (ihi > ilo + 1) {
2850 i = (ihi + ilo) >> 1;
2868 const int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
2882 float profiles[
EX][
EY][
EP],
2884 const int lon_ap_ind,
2885 const int lat_ap_ind,
2886 const double height_ap,
2892 np, height_ap, ind[0]);
2894 np, height_ap, ind[1]);
2896 np, height_ap, ind[2]);
2915 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2919 double dts, u[4], um = 0, v[4], vm = 0, w[4], wm = 0,
2923 for (
int i = 0; i < ctl->
advect; i++) {
2928 x[0] = atm->
lon[ip];
2929 x[1] = atm->
lat[ip];
2932 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
2933 x[0] = atm->
lon[ip] +
DX2DEG(dts * u[i - 1] / 1000., atm->
lat[ip]);
2934 x[1] = atm->
lat[ip] +
DY2DEG(dts * v[i - 1] / 1000.);
2935 x[2] = atm->
p[ip] + dts * w[i - 1];
2937 const double tm = atm->
time[ip] + dts;
2942 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2944 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2946 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
2952 met1, met1->
pl, met1->
ul,
2953 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2955 met1, met1->
pl, met1->
vl,
2956 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2958 met1, met1->
pl, met1->
wl,
2959 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
2965 k = (i == 0 ? 0.0 : 1.0);
2966 else if (ctl->
advect == 4)
2967 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2974 atm->
time[ip] += cache->
dt[ip];
2975 atm->
lon[ip] +=
DX2DEG(cache->
dt[ip] * um / 1000.,
2976 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
2977 atm->
lat[ip] +=
DY2DEG(cache->
dt[ip] * vm / 1000.);
2978 atm->
p[ip] += cache->
dt[ip] * wm;
2990 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2996 atm->
time[ip], atm->
p[ip],
2997 atm->
lon[ip], atm->
lat[ip],
2998 &atm->
q[qnt][ip], ci, cw, 1);
3001 double dts, u[4], um = 0, v[4], vm = 0, wdot[4],
3002 wdotm = 0, x[3] = { 0, 0, 0 };
3005 for (
int i = 0; i < ctl->
advect; i++) {
3010 x[0] = atm->
lon[ip];
3011 x[1] = atm->
lat[ip];
3012 x[2] = atm->
q[qnt][ip];
3014 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
3015 x[0] = atm->
lon[ip] +
DX2DEG(dts * u[i - 1] / 1000., atm->
lat[ip]);
3016 x[1] = atm->
lat[ip] +
DY2DEG(dts * v[i - 1] / 1000.);
3017 x[2] = atm->
q[qnt][ip] + dts * wdot[i - 1];
3020 const double tm = atm->
time[ip] + dts;
3025 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3028 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3031 tm, x[2], x[0], x[1], &wdot[i], ci, cw, 0);
3036 k = (i == 0 ? 0.0 : 1.0);
3037 else if (ctl->
advect == 4)
3038 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
3042 wdotm += k * wdot[i];
3046 atm->
time[ip] += cache->
dt[ip];
3047 atm->
lon[ip] +=
DX2DEG(cache->
dt[ip] * um / 1000.,
3048 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
3049 atm->
lat[ip] +=
DY2DEG(cache->
dt[ip] * vm / 1000.);
3050 atm->
q[qnt][ip] += cache->
dt[ip] * wdotm;
3056 atm->
q[qnt][ip], atm->
lon[ip], atm->
lat[ip],
3057 &atm->
p[ip], ci, cw, 1);
3085 atm->
lon[ip], atm->
lat[ip], &atm->
p[ip], ci, cw, 1);
3110 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3146 if (atm->
p[ip] < pbl)
3198 ERRMSG(
"Molar mass is not defined!");
3204 const int ensemble_mode = (ctl->
nens > 0);
3205 const int np = atm->
np;
3209 const int ngrid = nx * ny * nz;
3210 const int nens = ensemble_mode ? ctl->
nens : 1;
3212 double *restrict
const z = (
double *) malloc((
size_t) nz *
sizeof(double));
3213 double *restrict
const press =
3214 (
double *) malloc((
size_t) nz *
sizeof(double));
3215 double *restrict
const mass =
3216 (
double *) calloc((
size_t) ngrid * (size_t) nens,
sizeof(
double));
3217 double *restrict
const area =
3218 (
double *) malloc((
size_t) ny *
sizeof(double));
3219 double *restrict
const lon =
3220 (
double *) malloc((
size_t) nx *
sizeof(double));
3221 double *restrict
const lat =
3222 (
double *) malloc((
size_t) ny *
sizeof(double));
3224 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
3225 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
3226 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
3235#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np],z[0:nz],press[0:nz],mass[0:ngrid*nens],area[0:ny],lon[0:nx],lat[0:ny])
3236#pragma acc data present(ctl,met0,met1,atm,ixs,iys,izs,z,press,mass,area,lon,lat)
3237#pragma acc parallel loop independent gang vector
3239#pragma omp parallel for default(shared)
3241 for (
int iz = 0; iz < nz; iz++) {
3243 press[iz] =
P(z[iz]);
3247 const double t0 = tt - 0.5 * ctl->
dt_mod;
3248 const double t1 = tt + 0.5 * ctl->
dt_mod;
3252#pragma acc parallel loop independent gang vector
3254#pragma omp parallel for default(shared)
3256 for (
int ip = 0; ip < np; ip++) {
3260 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
3261 || ixs[ip] < 0 || ixs[ip] >= nx
3262 || iys[ip] < 0 || iys[ip] >= ny || izs[ip] < 0 || izs[ip] >= nz)
3268#pragma acc parallel loop independent gang vector
3270#pragma omp parallel for default(shared)
3272 for (
int ix = 0; ix < nx; ix++)
3276#pragma acc parallel loop independent gang vector
3278#pragma omp parallel for default(shared)
3280 for (
int iy = 0; iy < ny; iy++) {
3282 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
3287#pragma acc parallel loop independent gang vector
3289 for (
int ip = 0; ip < np; ip++) {
3291 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
3292 if (ensemble_mode) {
3293 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
3294 mass_idx += ens * ngrid;
3297#pragma acc atomic update
3299 mass[mass_idx] += atm->
q[ctl->
qnt_m][ip];
3305#pragma acc parallel loop independent gang vector
3307#pragma omp parallel for default(shared)
3309 for (
int ip = 0; ip < np; ip++)
3317 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
3320 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
3321 if (ensemble_mode) {
3322 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
3323 mass_idx += ens * ngrid;
3327 const double m = mass[mass_idx];
3329 / (
RHO(press[izs[ip]], temp) * area[iys[ip]] * dz * 1e9);
3334#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
3362 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3379 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
3381 atm->
lat[ip], atm->
p[ip]));
3383 atm->
lat[ip], atm->
p[ip]));
3385 atm->
lat[ip], atm->
p[ip]));
3405 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3413 double pbot = ps, ptop = ps;
3430 double cape, cin, pel;
3436 if (isfinite(cape) && cape >= ctl->
conv_cape
3438 ptop = GSL_MIN(ptop, pel);
3442 if (ptop != pbot && atm->
p[ip] >= ptop) {
3447 pbot, atm->
lon[ip], atm->
lat[ip], &tbot, ci, cw, 1);
3449 atm->
lon[ip], atm->
lat[ip], &ttop, ci, cw, 1);
3450 const double rhobot = pbot / tbot;
3451 const double rhotop = ptop / ttop;
3454 const double rho = rhobot + (rhotop - rhobot) * cache->
rs[ip];
3457 atm->
p[ip] =
LIN(rhobot, pbot, rhotop, ptop, rho);
3481 dd_sort(ctl, *met, atm, dd, &nparticles, &dd->
rank);
3515 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3518 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,clim,atm)") {
3527 const double aux = exp(-cache->
dt[ip] / tdec);
3528 if (ctl->
qnt_m >= 0) {
3531 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
3532 atm->
q[ctl->
qnt_m][ip] *= aux;
3557 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3565 float umean = 0, usig = 0, vmean = 0, vsig = 0, wmean = 0, wsig = 0;
3566 for (
int i = 0; i < 2; i++)
3567 for (
int j = 0; j < 2; j++)
3568 for (
int k = 0; k < 2; k++) {
3569 umean += met0->
u[ix + i][iy + j][iz + k];
3570 usig +=
SQR(met0->
u[ix + i][iy + j][iz + k]);
3571 vmean += met0->
v[ix + i][iy + j][iz + k];
3572 vsig +=
SQR(met0->
v[ix + i][iy + j][iz + k]);
3573 wmean += met0->
w[ix + i][iy + j][iz + k];
3574 wsig +=
SQR(met0->
w[ix + i][iy + j][iz + k]);
3576 umean += met1->
u[ix + i][iy + j][iz + k];
3577 usig +=
SQR(met1->
u[ix + i][iy + j][iz + k]);
3578 vmean += met1->
v[ix + i][iy + j][iz + k];
3579 vsig +=
SQR(met1->
v[ix + i][iy + j][iz + k]);
3580 wmean += met1->
w[ix + i][iy + j][iz + k];
3581 wsig +=
SQR(met1->
w[ix + i][iy + j][iz + k]);
3583 usig = usig / 16.f -
SQR(umean / 16.f);
3584 usig = (usig > 0 ? sqrtf(usig) : 0);
3585 vsig = vsig / 16.f -
SQR(vmean / 16.f);
3586 vsig = (vsig > 0 ? sqrtf(vsig) : 0);
3587 wsig = wsig / 16.f -
SQR(wmean / 16.f);
3588 wsig = (wsig > 0 ? sqrtf(wsig) : 0);
3591 const double r = 1 - 2 * fabs(cache->
dt[ip]) / ctl->
dt_met;
3592 const double r2 = sqrt(1 - r * r);
3596 cache->
uvwp[ip][0] =
3597 (float) (r * cache->
uvwp[ip][0] +
3602 cache->
uvwp[ip][1] =
3603 (float) (r * cache->
uvwp[ip][1] +
3610 cache->
uvwp[ip][2] =
3611 (float) (r * cache->
uvwp[ip][2] +
3613 atm->
p[ip] += cache->
uvwp[ip][2] * cache->
dt[ip];
3634 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3636 double dsigw_dz = 0.0, sig_u = 0.25, sig_w = 0.1,
3637 tau_u = 300., tau_w = 100.;
3646 if (atm->
p[ip] >= pbl) {
3649 const double p =
MIN(atm->
p[ip], ps);
3650 const double zs =
Z(ps);
3651 const double z = 1e3 * (
Z(p) - zs);
3652 const double zi = 1e3 * (
Z(pbl) - zs);
3653 const double zratio = z / zi;
3656 double ess, nss, h2o, t;
3661 const double rho =
RHO(p,
TVIRT(t, h2o));
3662 const double tau = sqrt(
SQR(ess) +
SQR(nss));
3663 const double ustar = sqrt(tau / rho);
3673 sig_u = 1e-2 + 2.0 * ustar * (1.0 - zratio);
3674 sig_w = 1e-2 + 1.3 * ustar * (1.0 - zratio);
3677 dsigw_dz = -1.3 * ustar / zi;
3680 tau_u = 0.07 * zi / sig_u * sqrt(zratio);
3681 tau_w = 0.1 * zi / sig_w * pow(zratio, 0.8);
3688 const double wstar =
3689 pow(
G0 /
THETAVIRT(p, t, h2o) * shf / (rho *
CPD) * zi, 1. / 3.);
3693 + sqrt(0.4 *
SQR(wstar) + (5.0 - 4.0 * zratio) *
SQR(ustar));
3694 sig_w = 1e-2 + sqrt(1.2 *
SQR(wstar) * (1.0 - 0.9 * zratio)
3695 * pow(zratio, 2.0 / 3.0)
3696 + (1.8 - 1.4 * zratio) *
SQR(ustar));
3699 dsigw_dz = 0.5 / sig_w / zi * (-1.4 *
SQR(ustar) +
SQR(wstar)
3701 pow(
MAX(zratio, 1e-3), -1.0 / 3.0)
3702 - 1.8 * pow(zratio, 2.0 / 3.0)));
3705 const double C0 = 3.0;
3707 (1.5 - 1.2 * pow(zratio, 1.0 / 3.0)) *
SQR(wstar) * wstar / zi
3708 +
SQR(ustar) * ustar * (1.0 - 0.8 * zratio) / (
KARMAN * z);
3709 tau_u = 2 *
SQR(sig_u) / (C0 * eps);
3710 tau_w = 2 *
SQR(sig_w) / (C0 * eps);
3715 sig_u =
MAX(sig_u, 0.25);
3716 sig_w =
MAX(sig_w, 0.1);
3717 tau_u =
MAX(tau_u, 300.);
3718 tau_w =
MAX(tau_w, 100.);
3721 const double ru = exp(-fabs(cache->
dt[ip]) / tau_u);
3722 const double ru2 = sqrt(1.0 -
SQR(ru));
3724 = (float) (cache->
uvwp[ip][0] * ru + ru2 * cache->
rs[3 * ip]);
3726 = (float) (cache->
uvwp[ip][1] * ru + ru2 * cache->
rs[3 * ip + 1]);
3728 const double rw = exp(-fabs(cache->
dt[ip]) / tau_w);
3729 const double rw2 = sqrt(1.0 -
SQR(rw));
3731 = (float) (cache->
uvwp[ip][2] * rw + rw2 * cache->
rs[3 * ip + 2]
3732 + sig_w * dsigw_dz * cache->
dt[ip]);
3739 DZ2DP(cache->
uvwp[ip][2] * cache->
dt[ip] / 1000., atm->
p[ip]);
3761 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3770 const double wpbl =
pbl_weight(ctl, atm, ip, pbl, ps);
3771 const double wtrop =
tropo_weight(clim, atm, ip) * (1.0 - wpbl);
3772 const double wstrat = 1.0 - wpbl - wtrop;
3782 const double sigma = sqrt(2.0 * dx * fabs(cache->
dt[ip])) / 1000.;
3784 atm->
lat[ip] +=
DY2DEG(cache->
rs[3 * ip + 1] * sigma);
3789 const double sigma = sqrt(2.0 * dz * fabs(cache->
dt[ip])) / 1000.;
3790 atm->
p[ip] +=
DZ2DP(cache->
rs[3 * ip + 2] * sigma, atm->
p[ip]);
3809 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3812 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3824 const double dz = 1000. * (
Z(ps - ctl->
dry_depo_dp) -
Z(ps));
3844 const double aux = exp(-cache->
dt[ip] * v_dep / dz);
3845 if (ctl->
qnt_m >= 0) {
3848 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
3849 atm->
q[ctl->
qnt_m][ip] *= aux;
3873 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3876 const double a = 3.12541941e-06;
3877 const double b = -5.72532259e-01;
3878 const double low = pow(1. / a, 1. / b);
3881 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3888 if (!(lwc > 0 || rwc > 0))
3899 const double k = 9.1e7 * exp(-29700. /
RI * (1. / t - 1. / 298.15));
3902 const double H_SO2 =
3903 1.3e-2 * exp(2900. * (1. / t - 1. / 298.15)) *
RI * t;
3904 const double K_1S = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
3907 const double H_h2o2 =
3908 8.3e2 * exp(7600. * (1. / t - 1. / 298.15)) *
RI * t;
3914 cor = atm->
q[ctl->
qnt_Cx][ip] >
3915 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
3917 const double h2o2 = H_h2o2
3919 * M * cor * 1000. /
AVO;
3922 const double rho_air = atm->
p[ip] / (
RI * t) *
MA / 10.;
3923 const double CWC = (lwc + rwc) * rho_air / 1e3;
3926 const double rate_coef = k * K_1S * h2o2 * H_SO2 * CWC;
3927 const double aux = exp(-cache->
dt[ip] * rate_coef);
3928 if (ctl->
qnt_m >= 0) {
3931 atm->
q[ctl->
qnt_m][ip] *= aux;
3963 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
3966 cache->
iso_var[ip] = atm->
p[ip] / t;
3972 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
3983 LOG(1,
"Read balloon pressure data: %s", ctl->
balloon);
3987 if (!(in = fopen(ctl->
balloon,
"r")))
3988 ERRMSG(
"Cannot open file!");
3992 while (fgets(line,
LEN, in))
3993 if (sscanf(line,
"%lg %lg", &(cache->
iso_ts[cache->
iso_n]),
3996 ERRMSG(
"Too many data points!");
3999 if (cache->
iso_n < 1)
4000 ERRMSG(
"Could not read any data!");
4023 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,met1,atm)") {
4036 atm->
p[ip] = cache->
iso_var[ip] * t;
4042 atm->
p[ip] = 1000. * pow(cache->
iso_var[ip] / t, -1. / 0.286);
4048 atm->
p[ip] = cache->
iso_ps[0];
4076 const int nvar = NVAR, nfix = NFIX, nreact = NREACT;
4077 double rtol[1] = { 1.0e-3 };
4078 double atol[1] = { 1.0 };
4082#pragma acc data copy(rtol,atol,nvar,nfix,nreact)
4085 "acc data present(ctl,cache,clim,met0,met1,atm) ") {
4088 double var[nvar], fix[nfix], rconst[nreact];
4089 for (
int i = 0; i < nvar; i++)
4091 for (
int i = 0; i < nfix; i++)
4093 for (
int i = 0; i < nreact; i++)
4095 kpp_chem_initialize(ctl, clim, met0, met1, atm, var, fix, rconst, ip);
4100 for (
int i = 0; i < 20; i++) {
4107 Rosenbrock(var, fix, rconst, 0, ctl->
dt_kpp,
4108 atol, rtol, &FunTemplate, &JacTemplate, rpar, ipar);
4111 kpp_chem_output2atm(atm, ctl, met0, met1, var, ip);
4132 ERRMSG(
"Need T_ice and T_NAT to calculate T_STS!");
4136 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4138 double ps, ts, zs, us, vs, ess, nss, shf, lsm, sst, pbl, pt, pct, pcb,
4139 cl, plcl, plfc, pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot,
4140 o3, lwc, rwc, iwc, swc, cc, z, zt;
4188 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
4190 atm->
lat[ip], atm->
p[ip]));
4192 atm->
lat[ip], atm->
p[ip]));
4194 atm->
lat[ip], atm->
p[ip]));
4195 SET_ATM(qnt_vh, sqrt(u * u + v * v));
4217 atm->
lat[ip], atm->
p[ip])));
4235 const int np = atm->
np;
4236 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
4237 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
4238 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
4246 const double t0 = t - 0.5 * ctl->
dt_mod;
4247 const double t1 = t + 0.5 * ctl->
dt_mod;
4251#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
4252#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
4253#pragma acc parallel loop independent gang vector
4255#pragma omp parallel for default(shared)
4257 for (
int ip = 0; ip < np; ip++) {
4260 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
mixing_z0) / dz);
4261 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
4262 || ixs[ip] < 0 || ixs[ip] >= ctl->
mixing_nx
4263 || iys[ip] < 0 || iys[ip] >= ctl->
mixing_ny
4264 || izs[ip] < 0 || izs[ip] >= ctl->
mixing_nz)
4269 const int use_ensemble = (ctl->
nens > 0);
4271 const int quantities[] = {
4279 const int n_qnt =
sizeof(quantities) /
sizeof(quantities[0]);
4281 for (
int i = 0; i < n_qnt; i++)
4282 if (quantities[i] >= 0)
4288#pragma acc exit data delete(ixs,iys,izs)
4305 const int use_ensemble) {
4307 const int np = atm->
np;
4309 const int nens = use_ensemble ? ctl->
nens : 1;
4310 const int total_grid = ngrid * nens;
4312 double *restrict
const cmean =
4313 (
double *) malloc((
size_t) total_grid *
sizeof(double));
4314 int *restrict
const count =
4315 (
int *) malloc((
size_t) total_grid *
sizeof(int));
4319#pragma acc enter data create(cmean[0:total_grid],count[0:total_grid])
4320#pragma acc data present(ctl,clim,atm,ixs,iys,izs,cmean,count)
4321#pragma acc parallel loop independent gang vector
4326#pragma omp parallel for
4328 for (
int i = 0; i < total_grid; i++) {
4335#pragma acc parallel loop independent gang vector
4337 for (
int ip = 0; ip < np; ip++)
4339 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
4344#pragma acc atomic update
4346 cmean[idx] += atm->
q[qnt_idx][ip];
4348#pragma acc atomic update
4355#pragma acc parallel loop independent gang vector
4360#pragma omp parallel for
4362 for (
int i = 0; i < total_grid; i++)
4364 cmean[i] /= count[i];
4368#pragma acc parallel loop independent gang vector
4370#pragma omp parallel for
4372 for (
int ip = 0; ip < np; ip++) {
4374 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
4376 double mixparam = 1.0;
4385 atm->
q[qnt_idx][ip] += (cmean[idx] - atm->
q[qnt_idx][ip]) * mixparam;
4391#pragma acc exit data delete(cmean,count)
4412 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4415 const double a = 4.71572206e-08;
4416 const double b = -8.28782867e-01;
4417 const double low = pow(1. / a, 1. / b);
4421 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4447 0 ? pow(298. / t, ctl->
oh_chem[1]) : 1.);
4450 0 ? pow(298. / t, ctl->
oh_chem[3]) : 1.);
4451 const double c = log10(k0 * M / ki);
4452 k = k0 * M / (1. + k0 * M / ki) * pow(0.6, 1. / (1. + c * c));
4461 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
4464 const double rate_coef =
4466 atm->
lat[ip], atm->
p[ip]) * M * cor;
4467 const double aux = exp(-cache->
dt[ip] * rate_coef);
4468 if (ctl->
qnt_m >= 0) {
4471 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
4472 atm->
q[ctl->
qnt_m][ip] *= aux;
4493 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(cache,met0,met1,atm)") {
4504 while (atm->
lat[ip] < -90 || atm->
lat[ip] > 90) {
4505 if (atm->
lat[ip] > 90) {
4506 atm->
lat[ip] = 180 - atm->
lat[ip];
4507 atm->
lon[ip] += 180;
4509 if (atm->
lat[ip] < -90) {
4510 atm->
lat[ip] = -180 - atm->
lat[ip];
4511 atm->
lon[ip] += 180;
4516 while (atm->
lon[ip] < -180)
4517 atm->
lon[ip] += 360;
4518 while (atm->
lon[ip] >= 180)
4519 atm->
lon[ip] -= 360;
4522 if (atm->
p[ip] < met0->
p[met0->
np - 1]) {
4523 atm->
p[ip] = met0->
p[met0->
np - 1];
4524 }
else if (atm->
p[ip] > 300.) {
4526 if (atm->
p[ip] > ps)
4543 const double lambda_rn222 = log(2.0) / (3.8235 * 86400.0);
4544 const double lambda_pb210 = log(2.0) / (22.3 * 365.25 * 86400.0);
4545 const double lambda_be7 = log(2.0) / (53.22 * 86400.0);
4546 const double lambda_cs137 = log(2.0) / (30.05 * 365.25 * 86400.0);
4547 const double lambda_i131 = log(2.0) / (8.02 * 86400.0);
4548 const double lambda_xe133 = log(2.0) / (5.2474 * 86400.0);
4554 const double dt = cache->
dt[ip];
4558 atm->
q[ctl->
qnt_Apb210][ip] *= exp(-dt * lambda_pb210);
4563 const double aux = exp(-dt * lambda_rn222);
4564 const double lost = old * (1.0 - aux);
4569 atm->
q[ctl->
qnt_Apb210][ip] += lost * lambda_pb210 / lambda_rn222;
4574 atm->
q[ctl->
qnt_Abe7][ip] *= exp(-dt * lambda_be7);
4578 atm->
q[ctl->
qnt_Acs137][ip] *= exp(-dt * lambda_cs137);
4582 atm->
q[ctl->
qnt_Ai131][ip] *= exp(-dt * lambda_i131);
4586 atm->
q[ctl->
qnt_Axe133][ip] *= exp(-dt * lambda_xe133);
4596 gsl_rng_env_setup();
4597 if (omp_get_max_threads() >
NTHREADS)
4598 ERRMSG(
"Too many threads!");
4599 for (
int i = 0; i <
NTHREADS; i++) {
4600 rng[i] = gsl_rng_alloc(gsl_rng_default);
4601 gsl_rng_set(rng[i], gsl_rng_default_seed
4602 + (
long unsigned) (ntask *
NTHREADS + i));
4607 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
4608 CURAND_STATUS_SUCCESS)
4609 ERRMSG(
"Cannot create random number generator!");
4610 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
4611 CURAND_STATUS_SUCCESS)
4612 ERRMSG(
"Cannot set seed for random number generator!");
4615 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
4616 CURAND_STATUS_SUCCESS)
4617 ERRMSG(
"Cannot set stream for random number generator!");
4634#pragma omp parallel for default(shared)
4635 for (
size_t i = 0; i < n; ++i)
4636 rs[i] = gsl_rng_uniform(rng[omp_get_thread_num()]);
4640 else if (method == 1) {
4641#pragma omp parallel for default(shared)
4642 for (
size_t i = 0; i < n; ++i)
4643 rs[i] = gsl_ran_gaussian_ziggurat(rng[omp_get_thread_num()], 1.0);
4649#pragma acc update device(rs[:n])
4657 const uint64_t key = 0xc8e4fd154ce32f6d;
4661#pragma acc data present(rs)
4662#pragma acc parallel loop independent gang vector
4664#pragma omp parallel for default(shared)
4666 for (
size_t i = 0; i < n + 1; ++i) {
4667 uint64_t r, t, x, y, z;
4668 y = x = (rng_ctr + i) * key;
4671 x = (x >> 32) | (x << 32);
4673 x = (x >> 32) | (x << 32);
4675 x = (x >> 32) | (x << 32);
4677 x = (x >> 32) | (x << 32);
4678 r = t ^ ((x * x + y) >> 32);
4679 rs[i] = (double) r / (
double) UINT64_MAX;
4686#pragma acc parallel loop independent gang vector
4688#pragma omp parallel for default(shared)
4690 for (
size_t i = 0; i < n; i += 2) {
4691 const double r = sqrt(-2.0 * log(rs[i]));
4692 const double phi = 2.0 * M_PI * rs[i + 1];
4693 rs[i] = r * cosf((
float) phi);
4694 rs[i + 1] = r * sinf((
float) phi);
4702#pragma acc host_data use_device(rs)
4707 if (curandGenerateUniformDouble(rng_curand, rs, (n < 4 ? 4 : n)) !=
4708 CURAND_STATUS_SUCCESS)
4709 ERRMSG(
"Cannot create random numbers!");
4713 else if (method == 1) {
4714 if (curandGenerateNormalDouble
4715 (rng_curand, rs, (n < 4 ? 4 : n), 0.0,
4716 1.0) != CURAND_STATUS_SUCCESS)
4717 ERRMSG(
"Cannot create random numbers!");
4721 ERRMSG(
"MPTRAC was compiled without cuRAND!");
4739 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4747 const double v_s =
sedi(atm->
p[ip], t, atm->
q[ctl->
qnt_rp][ip],
4751 atm->
p[ip] +=
DZ2DP(v_s * cache->
dt[ip] / 1000., atm->
p[ip]);
4766 const int np = atm->
np;
4767 double *restrict
const a = (
double *) malloc((
size_t) np *
sizeof(double));
4768 int *restrict
const p = (
int *) malloc((
size_t) np *
sizeof(int));
4769 if (a == NULL || p == NULL)
4770 ERRMSG(
"Out of memory!");
4773#pragma acc enter data create(a[0:np],p[0:np])
4774#pragma acc data present(ctl,met0,atm,a,p)
4779#pragma acc parallel loop independent gang vector
4781#pragma omp parallel for default(shared)
4783 for (
int ip = 0; ip < np; ip++) {
4794#pragma acc host_data use_device(a,p)
4796 thrustSortWrapper(a, np, p);
4799 ERRMSG(
"GSL sort fallback not available on GPU, use THRUST!");
4801 gsl_sort_index((
size_t *) p, a, 1, (
size_t) np);
4809 for (
int iq = 0; iq < ctl->
nq; iq++)
4814#pragma acc exit data delete(a,p)
4828 double *restrict
const help =
4829 (
double *) malloc((
size_t) np *
sizeof(double));
4831 ERRMSG(
"Out of memory!");
4835#pragma acc enter data create(help[0:np])
4836#pragma acc data present(a,p,help)
4837#pragma acc parallel loop independent gang vector
4839#pragma omp parallel for default(shared)
4841 for (
int ip = 0; ip < np; ip++)
4842 help[ip] = a[p[ip]];
4844#pragma acc parallel loop independent gang vector
4846#pragma omp parallel for default(shared)
4848 for (
int ip = 0; ip < np; ip++)
4853#pragma acc exit data delete(help)
4870 const double latmin = gsl_stats_min(met0->
lat, 1, (
size_t) met0->
ny),
4871 latmax = gsl_stats_max(met0->
lat, 1, (
size_t) met0->
ny);
4874 (fabs(met0->
lon[met0->
nx - 1] - met0->
lon[0] - 360.0) >= 0.01);
4877 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,atm)") {
4883 cache->
dt[ip] = t - atm->
time[ip];
4885 cache->
dt[ip] = 0.0;
4894 if (local && (atm->
lon[ip] <= met0->
lon[0]
4895 || atm->
lon[ip] >= met0->
lon[met0->
nx - 1]
4896 || atm->
lat[ip] <= latmin || atm->
lat[ip] >= latmax))
4897 cache->
dt[ip] = 0.0;
4916 ctl->
t_start = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
4918 ctl->
t_stop = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
4920 ctl->
t_start = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
4922 ctl->
t_stop = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
4927 ERRMSG(
"Nothing to do! Check T_STOP and DIRECTION!");
4951 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4975 const double K_o1d =
ARRHENIUS(3.30e-10, 0, t) * o1d * M;
4977 atm->
p[ip], sza, o3c);
4978 atm->
q[ctl->
qnt_Cccl4][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4983 const double K_o1d =
ARRHENIUS(2.30e-10, 0, t) * o1d * M;
4985 atm->
p[ip], sza, o3c);
4986 atm->
q[ctl->
qnt_Cccl3f][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4991 const double K_o1d =
ARRHENIUS(1.40e-10, -25, t) * o1d * M;
4993 atm->
p[ip], sza, o3c);
4994 atm->
q[ctl->
qnt_Cccl2f2][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4999 const double K_o1d =
ARRHENIUS(1.19e-10, -20, t) * o1d * M;
5001 atm->
p[ip], sza, o3c);
5002 atm->
q[ctl->
qnt_Cn2o][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5021 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
5024 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
5030 if (!isfinite(pct) || atm->
p[ip] <= pct)
5046 double lwc, rwc, iwc, swc;
5051 const int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
5065 else if (t <= 238.15)
5085 const double K_1 = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
5086 const double K_2 = 6e-8 * exp(1.12e3 * (1. / t - 1. / 298.15));
5087 h *= (1. + K_1 / H_ion + K_1 * K_2 /
SQR(H_ion));
5091 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
5094 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
5120 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
5123 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
5128 const double aux = exp(-cache->
dt[ip] * lambda);
5129 if (ctl->
qnt_m >= 0) {
5132 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
5133 atm->
q[ctl->
qnt_m][ip] *= aux;
5158 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
5160 if (acc_get_num_devices(acc_device_nvidia) <= 0)
5161 ERRMSG(
"Not running on a GPU device!");
5162 acc_set_device_num(rank % acc_get_num_devices(acc_device_nvidia),
5164 acc_device_t device_type = acc_get_device_type();
5165 acc_init(device_type);
5181 ctl_t *ctlup = *ctl;
5184 met_t *met0up = *met0;
5185 met_t *met1up = *met1;
5186 atm_t *atmup = *atm;
5187#pragma acc enter data create(ctlup[:1],cacheup[:1],climup[:1],met0up[:1],met1up[:1],atmup[:1])
5190#pragma acc enter data create(ddup[:1])
5209#pragma acc exit data delete (ctl,cache,clim,met0,met1,atm)
5223 MPI_Type_free(&dd->MPI_Particle);
5242 char cachefile[
LEN], cmd[2 *
LEN], filename[
LEN];
5248 if (t == ctl->
t_start || !init) {
5255 ERRMSG(
"Cannot open file!");
5260 ERRMSG(
"Cannot open file!");
5270 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5271 LOG(1,
"Caching: %s", cachefile);
5272 if (system(cmd) != 0)
5273 WARN(
"Caching command failed!");
5278 if (t > (*met1)->time) {
5288 ERRMSG(
"Cannot open file!");
5298 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5299 LOG(1,
"Caching: %s", cachefile);
5300 if (system(cmd) != 0)
5301 WARN(
"Caching command failed!");
5306 if (t < (*met0)->time) {
5316 ERRMSG(
"Cannot open file!");
5326 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5327 LOG(1,
"Caching: %s", cachefile);
5328 if (system(cmd) != 0)
5329 WARN(
"Caching command failed!");
5334 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
5335 if ((*met0)->nx != (*met1)->nx
5336 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
5337 ERRMSG(
"Meteo grid dimensions do not match!");
5338 for (
int ix = 0; ix < (*met0)->nx; ix++)
5339 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
5340 ERRMSG(
"Meteo grid longitudes do not match!");
5341 for (
int iy = 0; iy < (*met0)->ny; iy++)
5342 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
5343 ERRMSG(
"Meteo grid latitudes do not match!");
5344 for (
int ip = 0; ip < (*met0)->np; ip++)
5345 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
5346 ERRMSG(
"Meteo grid pressure levels do not match!");
5372 const char *filename,
5385 LOG(1,
"Read atmospheric data: %s", filename);
5405 ERRMSG(
"Atmospheric data type not supported!");
5413 ERRMSG(
"Can not read any data!");
5417 LOG(2,
"Number of particles: %d", atm->
np);
5418 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
5419 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
5420 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
5421 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
5422 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
5423 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
5424 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
5425 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
5426 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
5427 for (
int iq = 0; iq < ctl->
nq; iq++) {
5429 sprintf(msg,
"Quantity %s range: %s ... %s %s",
5432 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
5433 LOG(2, msg, mini, maxi);
5503 const char *filename,
5512 LOG(1,
"\nMassive-Parallel Trajectory Calculations (MPTRAC)\n"
5513 "(executable: %s | version: %s | compiled: %s, %s)\n",
5514 argv[0], VERSION, __DATE__, __TIME__);
5621 ctl->
nq = (int)
scan_ctl(filename, argc, argv,
"NQ", -1,
"0", NULL);
5623 ERRMSG(
"Too many quantities!");
5624 for (
int iq = 0; iq < ctl->
nq; iq++) {
5630 scan_ctl(filename, argc, argv,
"QNT_FORMAT", iq,
"%g",
5632 if (strcasecmp(ctl->
qnt_name[iq],
"aoa") == 0)
5636 SET_QNT(qnt_idx,
"idx",
"particle index",
"-")
5637 SET_QNT(qnt_ens,
"ens",
"ensemble index",
"-")
5638 SET_QNT(qnt_stat,
"stat",
"station flag",
"-")
5639 SET_QNT(qnt_m,
"m",
"mass",
"kg")
5640 SET_QNT(qnt_vmr,
"vmr",
"volume mixing ratio",
"ppv")
5641 SET_QNT(qnt_rp,
"rp",
"particle radius",
"microns")
5642 SET_QNT(qnt_rhop,
"rhop",
"particle density",
"kg/m^3")
5643 SET_QNT(qnt_ps,
"ps",
"surface pressure",
"hPa")
5644 SET_QNT(qnt_ts,
"ts",
"surface temperature",
"K")
5645 SET_QNT(qnt_zs,
"zs",
"surface height",
"km")
5646 SET_QNT(qnt_us,
"us",
"surface zonal wind",
"m/s")
5647 SET_QNT(qnt_vs,
"vs",
"surface meridional wind",
"m/s")
5648 SET_QNT(qnt_ess,
"ess",
"eastward turbulent surface stress",
"N/m^2")
5649 SET_QNT(qnt_nss,
"nss",
"northward turbulent surface stress",
"N/m^2")
5650 SET_QNT(qnt_shf,
"shf",
"surface sensible heat flux",
"W/m^2")
5651 SET_QNT(qnt_lsm,
"lsm",
"land-sea mask",
"1")
5652 SET_QNT(qnt_sst,
"sst",
"sea surface temperature",
"K")
5653 SET_QNT(qnt_pbl,
"pbl",
"planetary boundary layer",
"hPa")
5654 SET_QNT(qnt_pt,
"pt",
"tropopause pressure",
"hPa")
5655 SET_QNT(qnt_tt,
"tt",
"tropopause temperature",
"K")
5656 SET_QNT(qnt_zt,
"zt",
"tropopause geopotential height",
"km")
5657 SET_QNT(qnt_h2ot,
"h2ot",
"tropopause water vapor",
"ppv")
5658 SET_QNT(qnt_zg,
"zg",
"geopotential height",
"km")
5659 SET_QNT(qnt_p,
"p",
"pressure",
"hPa")
5660 SET_QNT(qnt_t,
"t",
"temperature",
"K")
5661 SET_QNT(qnt_rho,
"rho",
"air density",
"kg/m^3")
5662 SET_QNT(qnt_u,
"u",
"zonal wind",
"m/s")
5663 SET_QNT(qnt_v,
"v",
"meridional wind",
"m/s")
5664 SET_QNT(qnt_w,
"w",
"vertical velocity",
"hPa/s")
5665 SET_QNT(qnt_h2o,
"h2o",
"water vapor",
"ppv")
5666 SET_QNT(qnt_o3,
"o3",
"ozone",
"ppv")
5667 SET_QNT(qnt_lwc,
"lwc",
"cloud liquid water content",
"kg/kg")
5668 SET_QNT(qnt_rwc,
"rwc",
"cloud rain water content",
"kg/kg")
5669 SET_QNT(qnt_iwc,
"iwc",
"cloud ice water content",
"kg/kg")
5670 SET_QNT(qnt_swc,
"swc",
"cloud snow water content",
"kg/kg")
5671 SET_QNT(qnt_cc,
"cc",
"cloud cover",
"1")
5672 SET_QNT(qnt_pct,
"pct",
"cloud top pressure",
"hPa")
5673 SET_QNT(qnt_pcb,
"pcb",
"cloud bottom pressure",
"hPa")
5674 SET_QNT(qnt_cl,
"cl",
"total column cloud water",
"kg/m^2")
5675 SET_QNT(qnt_plcl,
"plcl",
"lifted condensation level",
"hPa")
5676 SET_QNT(qnt_plfc,
"plfc",
"level of free convection",
"hPa")
5677 SET_QNT(qnt_pel,
"pel",
"equilibrium level",
"hPa")
5678 SET_QNT(qnt_cape,
"cape",
"convective available potential energy",
5680 SET_QNT(qnt_cin,
"cin",
"convective inhibition",
"J/kg")
5681 SET_QNT(qnt_o3c,
"o3c",
"total column ozone",
"DU")
5682 SET_QNT(qnt_hno3,
"hno3",
"nitric acid",
"ppv")
5683 SET_QNT(qnt_oh,
"oh",
"hydroxyl radical",
"ppv")
5684 SET_QNT(qnt_h2o2,
"h2o2",
"hydrogen peroxide",
"ppv")
5685 SET_QNT(qnt_ho2,
"ho2",
"hydroperoxyl radical",
"ppv")
5686 SET_QNT(qnt_o1d,
"o1d",
"atomic oxygen",
"ppv")
5687 SET_QNT(qnt_mloss_oh,
"mloss_oh",
"mass loss due to OH chemistry",
"kg")
5688 SET_QNT(qnt_mloss_h2o2,
"mloss_h2o2",
5689 "mass loss due to H2O2 chemistry",
"kg")
5690 SET_QNT(qnt_mloss_kpp,
"mloss_kpp",
"mass loss due to kpp chemistry",
5692 SET_QNT(qnt_mloss_wet,
"mloss_wet",
"mass loss due to wet deposition",
5694 SET_QNT(qnt_mloss_dry,
"mloss_dry",
"mass loss due to dry deposition",
5696 SET_QNT(qnt_mloss_decay,
"mloss_decay",
5697 "mass loss due to exponential decay",
"kg")
5698 SET_QNT(qnt_loss_rate,
"loss_rate",
"total loss rate",
"s^-1")
5699 SET_QNT(qnt_psat,
"psat",
"saturation pressure over water",
"hPa")
5700 SET_QNT(qnt_psice,
"psice",
"saturation pressure over ice",
"hPa")
5701 SET_QNT(qnt_pw,
"pw",
"partial water vapor pressure",
"hPa")
5702 SET_QNT(qnt_sh,
"sh",
"specific humidity",
"kg/kg")
5703 SET_QNT(qnt_rh,
"rh",
"relative humidity",
"%%")
5704 SET_QNT(qnt_rhice,
"rhice",
"relative humidity over ice",
"%%")
5705 SET_QNT(qnt_theta,
"theta",
"potential temperature",
"K")
5706 SET_QNT(qnt_zeta,
"zeta",
"zeta coordinate",
"K")
5707 SET_QNT(qnt_zeta_d,
"zeta_d",
"diagnosed zeta coordinate",
"K")
5708 SET_QNT(qnt_zeta_dot,
"zeta_dot",
"velocity of zeta coordinate",
5710 SET_QNT(qnt_eta,
"eta",
"eta coordinate",
"1")
5711 SET_QNT(qnt_eta_dot,
"eta_dot",
"velocity of eta coordinate",
"1/s")
5712 SET_QNT(qnt_tvirt,
"tvirt",
"virtual temperature",
"K")
5713 SET_QNT(qnt_lapse,
"lapse",
"temperature lapse rate",
"K/km")
5714 SET_QNT(qnt_vh,
"vh",
"horizontal velocity",
"m/s")
5715 SET_QNT(qnt_vz,
"vz",
"vertical velocity",
"m/s")
5716 SET_QNT(qnt_pv,
"pv",
"potential vorticity",
"PVU")
5717 SET_QNT(qnt_tdew,
"tdew",
"dew point temperature",
"K")
5718 SET_QNT(qnt_tice,
"tice",
"frost point temperature",
"K")
5719 SET_QNT(qnt_tsts,
"tsts",
"STS existence temperature",
"K")
5720 SET_QNT(qnt_tnat,
"tnat",
"NAT existence temperature",
"K")
5721 SET_QNT(qnt_Cx,
"Cx",
"Trace species x volume mixing ratio",
"ppv")
5722 SET_QNT(qnt_Ch2o,
"Ch2o",
"H2O volume mixing ratio",
"ppv")
5723 SET_QNT(qnt_Co3,
"Co3",
"O3 volume mixing ratio",
"ppv")
5724 SET_QNT(qnt_Cco,
"Cco",
"CO volume mixing ratio",
"ppv")
5725 SET_QNT(qnt_Coh,
"Coh",
"HO volume mixing ratio",
"ppv")
5726 SET_QNT(qnt_Ch,
"Ch",
"H radical volume mixing ratio",
"ppv")
5727 SET_QNT(qnt_Cho2,
"Cho2",
"HO2 volume mixing ratio",
"ppv")
5728 SET_QNT(qnt_Ch2o2,
"Ch2o2",
"H2O2 volume mixing ratio",
"ppv")
5729 SET_QNT(qnt_Co1d,
"Co1d",
"O(1D) volume mixing ratio",
"ppv")
5730 SET_QNT(qnt_Co3p,
"Co3p",
"O(3P) radical volume mixing ratio",
"ppv")
5731 SET_QNT(qnt_Cccl4,
"Cccl4",
"CCl4 (CFC-10) volume mixing ratio",
"ppv")
5732 SET_QNT(qnt_Cccl3f,
"Cccl3f",
"CCl3F (CFC-11) volume mixing ratio",
5734 SET_QNT(qnt_Cccl2f2,
"Cccl2f2",
"CCl2F2 (CFC-12) volume mixing ratio",
5736 SET_QNT(qnt_Cn2o,
"Cn2o",
"N2O volume mixing ratio",
"ppv")
5737 SET_QNT(qnt_Csf6,
"Csf6",
"SF6 volume mixing ratio",
"ppv")
5738 SET_QNT(qnt_aoa,
"aoa",
"age of air",
"s")
5739 SET_QNT(qnt_Arn222,
"Arn222",
"Rn-222 activity",
"Bq")
5740 SET_QNT(qnt_Apb210,
"Apb210",
"Pb-210 activity",
"Bq")
5741 SET_QNT(qnt_Abe7,
"Abe7",
"Be-7 activity",
"Bq")
5742 SET_QNT(qnt_Acs137,
"Acs137",
"Cs-137 activity",
"Bq")
5743 SET_QNT(qnt_Ai131,
"Ai131",
"I-131 activity",
"Bq")
5744 SET_QNT(qnt_Axe133,
"Axe133",
"Xe-133 activity",
"Bq")
5745 SET_QNT(qnt_subdomain,
"subdomain",
"current subdomain index",
"-")
5746 SET_QNT(qnt_destination,
"destination",
5747 "subdomain index of destination",
"-")
5753 (int)
scan_ctl(filename, argc, argv,
"ADVECT_VERT_COORD", -1,
"0", NULL);
5755 ERRMSG(
"ADVECT_VERT_COORD must be 0, 1, 2, or 3!");
5758 ERRMSG(
"Add quantity zeta for diabatic advection!");
5760 ERRMSG(
"Add quantity eta for etadot avection!");
5763 (int)
scan_ctl(filename, argc, argv,
"MET_VERT_COORD", -1,
"0", NULL);
5765 ERRMSG(
"MET_VERT_COORD must be 0, 1, 2, 3, or 4!");
5769 (
"Using ADVECT_VERT_COORD = 2 requires meteo data on model levels!");
5772 (
"Using ADVECT_VERT_COORD = 3 requires A and B model level coefficients!");
5776 (int)
scan_ctl(filename, argc, argv,
"DIRECTION", -1,
"1", NULL);
5778 ERRMSG(
"Set DIRECTION to -1 or 1!");
5779 ctl->
t_stop =
scan_ctl(filename, argc, argv,
"T_STOP", -1,
"1e100", NULL);
5780 ctl->
dt_mod =
scan_ctl(filename, argc, argv,
"DT_MOD", -1,
"180", NULL);
5784 ctl->
dt_met =
scan_ctl(filename, argc, argv,
"DT_MET", -1,
"3600", NULL);
5786 (int)
scan_ctl(filename, argc, argv,
"MET_CONVENTION", -1,
"0", NULL);
5788 (int)
scan_ctl(filename, argc, argv,
"MET_TYPE", -1,
"0", NULL);
5791 (
"Please use meteo files in netcdf format for diabatic calculations.");
5794 (
"Please use meteo files in netcdf format for etadot calculations.");
5796 (int)
scan_ctl(filename, argc, argv,
"MET_CLAMS", -1,
"0", NULL);
5798 (int)
scan_ctl(filename, argc, argv,
"MET_NC_SCALE", -1,
"1", NULL);
5800 (int)
scan_ctl(filename, argc, argv,
"MET_NC_LEVEL", -1,
"0", NULL);
5802 (int)
scan_ctl(filename, argc, argv,
"MET_NC_QUANT", -1,
"0", NULL);
5804 (int)
scan_ctl(filename, argc, argv,
"MET_ZSTD_LEVEL", -1,
"0", NULL);
5805 for (
int i = 0; i <
METVAR; i++) {
5806 char defprec[
LEN] =
"0", deftol[
LEN] =
"0.0";
5808 sprintf(deftol,
"0.5");
5810 sprintf(deftol,
"5.0");
5812 sprintf(defprec,
"8");
5814 (int)
scan_ctl(filename, argc, argv,
"MET_COMP_PREC", i, defprec, NULL);
5816 scan_ctl(filename, argc, argv,
"MET_COMP_TOL", i, deftol, NULL);
5819 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_BATCH", -1,
"-1", NULL);
5821 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ZSTD", -1,
"1", NULL);
5823 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ND0X", -1,
"48", NULL);
5825 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ND0Y", -1,
"24", NULL);
5827 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_MAXLEV", -1,
"6", NULL);
5829 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_Z", -1,
"1.0", NULL);
5831 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_T", -1,
"0.05", NULL);
5833 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_U", -1,
"0.05", NULL);
5835 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_V", -1,
"0.05", NULL);
5837 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_W", -1,
"1.0", NULL);
5839 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_PV", -1,
"1.0", NULL);
5841 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_H2O", -1,
"1.0", NULL);
5843 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_O3", -1,
"1.0", NULL);
5845 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_LWC", -1,
"1.0", NULL);
5847 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_RWC", -1,
"1.0", NULL);
5849 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_IWC", -1,
"1.0", NULL);
5851 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_SWC", -1,
"1.0", NULL);
5853 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_CC", -1,
"1.0", NULL);
5854 ctl->
met_dx = (int)
scan_ctl(filename, argc, argv,
"MET_DX", -1,
"1", NULL);
5855 ctl->
met_dy = (int)
scan_ctl(filename, argc, argv,
"MET_DY", -1,
"1", NULL);
5856 ctl->
met_dp = (int)
scan_ctl(filename, argc, argv,
"MET_DP", -1,
"1", NULL);
5858 ERRMSG(
"MET_DX, MET_DY, and MET_DP need to be greater than zero!");
5859 ctl->
met_sx = (int)
scan_ctl(filename, argc, argv,
"MET_SX", -1,
"1", NULL);
5860 ctl->
met_sy = (int)
scan_ctl(filename, argc, argv,
"MET_SY", -1,
"1", NULL);
5861 ctl->
met_sp = (int)
scan_ctl(filename, argc, argv,
"MET_SP", -1,
"1", NULL);
5863 ERRMSG(
"MET_SX, MET_SY, and MET_SP need to be greater than zero!");
5865 scan_ctl(filename, argc, argv,
"MET_DETREND", -1,
"-999", NULL);
5866 ctl->
met_np = (int)
scan_ctl(filename, argc, argv,
"MET_NP", -1,
"0", NULL);
5868 ERRMSG(
"Too many pressure levels!");
5870 (int)
scan_ctl(filename, argc, argv,
"MET_PRESS_LEVEL_DEF", -1,
"-1",
5876 for (
int ip = 0; ip < ctl->
met_np; ip++)
5878 scan_ctl(filename, argc, argv,
"MET_P", ip,
"", NULL);
5882 (int)
scan_ctl(filename, argc, argv,
"MET_NLEV", -1,
"0", NULL);
5884 ERRMSG(
"Too many model levels!");
5885 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
5887 scan_ctl(filename, argc, argv,
"MET_LEV_HYAM", ip,
"", NULL);
5888 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
5890 scan_ctl(filename, argc, argv,
"MET_LEV_HYBM", ip,
"", NULL);
5892 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SX", -1,
"-1", NULL);
5894 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SY", -1,
"-1", NULL);
5896 (int)
scan_ctl(filename, argc, argv,
"MET_RELHUM", -1,
"0", NULL);
5898 (int)
scan_ctl(filename, argc, argv,
"MET_CAPE", -1,
"1", NULL);
5900 ERRMSG(
"Set MET_CAPE to 0 or 1!");
5902 (int)
scan_ctl(filename, argc, argv,
"MET_PBL", -1,
"3", NULL);
5904 ERRMSG(
"Set MET_PBL to 0 ... 3!");
5906 scan_ctl(filename, argc, argv,
"MET_PBL_MIN", -1,
"0.1", NULL);
5908 scan_ctl(filename, argc, argv,
"MET_PBL_MAX", -1,
"5.0", NULL);
5910 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO", -1,
"3", NULL);
5912 ERRMSG(
"Set MET_TROPO to 0 ... 5!");
5914 scan_ctl(filename, argc, argv,
"MET_TROPO_PV", -1,
"3.5", NULL);
5916 scan_ctl(filename, argc, argv,
"MET_TROPO_THETA", -1,
"380", NULL);
5918 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO_SPLINE", -1,
"1", NULL);
5920 scan_ctl(filename, argc, argv,
"MET_DT_OUT", -1,
"0.1", NULL);
5922 (int)
scan_ctl(filename, argc, argv,
"MET_CACHE", -1,
"0", NULL);
5924 (int)
scan_ctl(filename, argc, argv,
"MET_MPI_SHARE", -1,
"0", NULL);
5927 ctl->
sort_dt =
scan_ctl(filename, argc, argv,
"SORT_DT", -1,
"-999", NULL);
5931 (int)
scan_ctl(filename, argc, argv,
"ISOSURF", -1,
"0", NULL);
5936 (int)
scan_ctl(filename, argc, argv,
"RNG_TYPE", -1,
"1", NULL);
5938 ERRMSG(
"Set RNG_TYPE to 0, 1, or 2!");
5941 ctl->
advect = (int)
scan_ctl(filename, argc, argv,
"ADVECT", -1,
"2", NULL);
5945 ERRMSG(
"Set ADVECT to 0, 1, 2, or 4!");
5949 = (int)
scan_ctl(filename, argc, argv,
"DIFFUSION", -1,
"0", NULL);
5951 ERRMSG(
"Set DIFFUSION to 0, 1 or 2!");
5953 scan_ctl(filename, argc, argv,
"TURB_DX_PBL", -1,
"50", NULL);
5955 scan_ctl(filename, argc, argv,
"TURB_DX_TROP", -1,
"50", NULL);
5957 scan_ctl(filename, argc, argv,
"TURB_DX_STRAT", -1,
"0", NULL);
5959 scan_ctl(filename, argc, argv,
"TURB_DZ_PBL", -1,
"0", NULL);
5961 scan_ctl(filename, argc, argv,
"TURB_DZ_TROP", -1,
"0", NULL);
5963 scan_ctl(filename, argc, argv,
"TURB_DZ_STRAT", -1,
"0.1", NULL);
5965 scan_ctl(filename, argc, argv,
"TURB_MESOX", -1,
"0.16", NULL);
5967 scan_ctl(filename, argc, argv,
"TURB_MESOZ", -1,
"0.16", NULL);
5971 = (int)
scan_ctl(filename, argc, argv,
"CONV_MIX_PBL", -1,
"0", NULL);
5973 =
scan_ctl(filename, argc, argv,
"CONV_PBL_TRANS", -1,
"0", NULL);
5975 =
scan_ctl(filename, argc, argv,
"CONV_CAPE", -1,
"-999", NULL);
5977 =
scan_ctl(filename, argc, argv,
"CONV_CIN", -1,
"-999", NULL);
5978 ctl->
conv_dt =
scan_ctl(filename, argc, argv,
"CONV_DT", -1,
"-999", NULL);
5982 scan_ctl(filename, argc, argv,
"BOUND_MASS", -1,
"-999", NULL);
5984 scan_ctl(filename, argc, argv,
"BOUND_MASS_TREND", -1,
"0", NULL);
5986 scan_ctl(filename, argc, argv,
"BOUND_VMR", -1,
"-999", NULL);
5988 scan_ctl(filename, argc, argv,
"BOUND_VMR_TREND", -1,
"0", NULL);
5990 scan_ctl(filename, argc, argv,
"BOUND_LAT0", -1,
"-999", NULL);
5992 scan_ctl(filename, argc, argv,
"BOUND_LAT1", -1,
"-999", NULL);
5994 scan_ctl(filename, argc, argv,
"BOUND_P0", -1,
"-999", NULL);
5996 scan_ctl(filename, argc, argv,
"BOUND_P1", -1,
"-999", NULL);
5998 scan_ctl(filename, argc, argv,
"BOUND_DPS", -1,
"-999", NULL);
6000 scan_ctl(filename, argc, argv,
"BOUND_DZS", -1,
"-999", NULL);
6002 scan_ctl(filename, argc, argv,
"BOUND_ZETAS", -1,
"-999", NULL);
6004 (int)
scan_ctl(filename, argc, argv,
"BOUND_PBL", -1,
"0", NULL);
6008 if (strcasecmp(ctl->
species,
"CF2Cl2") == 0) {
6012 }
else if (strcasecmp(ctl->
species,
"CFCl3") == 0) {
6016 }
else if (strcasecmp(ctl->
species,
"CH4") == 0) {
6023 }
else if (strcasecmp(ctl->
species,
"CO") == 0) {
6032 }
else if (strcasecmp(ctl->
species,
"CO2") == 0) {
6036 }
else if (strcasecmp(ctl->
species,
"H2O") == 0) {
6038 }
else if (strcasecmp(ctl->
species,
"N2O") == 0) {
6042 }
else if (strcasecmp(ctl->
species,
"NH3") == 0) {
6049 }
else if (strcasecmp(ctl->
species,
"HNO3") == 0) {
6053 }
else if (strcasecmp(ctl->
species,
"NO") == 0) {
6062 }
else if (strcasecmp(ctl->
species,
"NO2") == 0) {
6071 }
else if (strcasecmp(ctl->
species,
"O3") == 0) {
6078 }
else if (strcasecmp(ctl->
species,
"SF6") == 0) {
6082 }
else if (strcasecmp(ctl->
species,
"SO2") == 0) {
6095 sprintf(defstr,
"%g", ctl->
molmass);
6096 ctl->
molmass =
scan_ctl(filename, argc, argv,
"MOLMASS", -1, defstr, NULL);
6101 (int)
scan_ctl(filename, argc, argv,
"OH_CHEM_REACTION", -1, defstr,
6103 for (
int ip = 0; ip < 4; ip++) {
6104 sprintf(defstr,
"%g", ctl->
oh_chem[ip]);
6106 scan_ctl(filename, argc, argv,
"OH_CHEM", ip, defstr, NULL);
6109 scan_ctl(filename, argc, argv,
"OH_CHEM_BETA", -1,
"0", NULL);
6113 (int)
scan_ctl(filename, argc, argv,
"H2O2_CHEM_REACTION", -1,
"0", NULL);
6117 (int)
scan_ctl(filename, argc, argv,
"KPP_CHEM", -1,
"0", NULL);
6118 ctl->
dt_kpp =
scan_ctl(filename, argc, argv,
"DT_KPP", -1,
"1800", NULL);
6122 (int)
scan_ctl(filename, argc, argv,
"TRACER_CHEM", -1,
"0", NULL);
6126 (int)
scan_ctl(filename, argc, argv,
"RADIO_DECAY", -1,
"0", NULL);
6129 for (
int ip = 0; ip < 2; ip++) {
6132 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_H", ip, defstr, NULL);
6134 for (
int ip = 0; ip < 1; ip++) {
6137 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_H", ip, defstr, NULL);
6140 scan_ctl(filename, argc, argv,
"WET_DEPO_SO2_PH", -1,
"0", NULL);
6142 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_A", -1,
"0", NULL);
6144 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_B", -1,
"0", NULL);
6146 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_A", -1,
"0", NULL);
6148 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_B", -1,
"0", NULL);
6150 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 0,
"0.5", NULL);
6152 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 1,
"0.36", NULL);
6154 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_RET_RATIO", -1,
"1", NULL);
6156 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_RET_RATIO", -1,
"1", NULL);
6160 scan_ctl(filename, argc, argv,
"DRY_DEPO_VDEP", -1,
"0", NULL);
6162 scan_ctl(filename, argc, argv,
"DRY_DEPO_DP", -1,
"30", NULL);
6165 scan_ctl(filename, argc, argv,
"CLIM_PHOTO", -1,
6166 "../../data/clams_photolysis_rates.nc", ctl->
clim_photo);
6167 scan_ctl(filename, argc, argv,
"CLIM_HNO3_FILENAME", -1,
6169 scan_ctl(filename, argc, argv,
"CLIM_OH_FILENAME", -1,
6171 scan_ctl(filename, argc, argv,
"CLIM_H2O2_FILENAME", -1,
6173 scan_ctl(filename, argc, argv,
"CLIM_HO2_FILENAME", -1,
6175 scan_ctl(filename, argc, argv,
"CLIM_O1D_FILENAME", -1,
6177 scan_ctl(filename, argc, argv,
"CLIM_CCL4_TIMESERIES", -1,
6179 scan_ctl(filename, argc, argv,
"CLIM_CCL3F_TIMESERIES", -1,
6181 scan_ctl(filename, argc, argv,
"CLIM_CCL2F2_TIMESERIES", -1,
6183 scan_ctl(filename, argc, argv,
"CLIM_N2O_TIMESERIES", -1,
6185 scan_ctl(filename, argc, argv,
"CLIM_SF6_TIMESERIES", -1,
6190 scan_ctl(filename, argc, argv,
"MIXING_DT", -1,
"3600.", NULL);
6192 scan_ctl(filename, argc, argv,
"MIXING_TROP", -1,
"-999", NULL);
6194 scan_ctl(filename, argc, argv,
"MIXING_STRAT", -1,
"-999", NULL);
6196 scan_ctl(filename, argc, argv,
"MIXING_Z0", -1,
"-5", NULL);
6198 scan_ctl(filename, argc, argv,
"MIXING_Z1", -1,
"85", NULL);
6200 (int)
scan_ctl(filename, argc, argv,
"MIXING_NZ", -1,
"90", NULL);
6202 scan_ctl(filename, argc, argv,
"MIXING_LON0", -1,
"-180", NULL);
6204 scan_ctl(filename, argc, argv,
"MIXING_LON1", -1,
"180", NULL);
6206 (int)
scan_ctl(filename, argc, argv,
"MIXING_NX", -1,
"360", NULL);
6208 scan_ctl(filename, argc, argv,
"MIXING_LAT0", -1,
"-90", NULL);
6210 scan_ctl(filename, argc, argv,
"MIXING_LAT1", -1,
"90", NULL);
6212 (int)
scan_ctl(filename, argc, argv,
"MIXING_NY", -1,
"180", NULL);
6216 scan_ctl(filename, argc, argv,
"CHEMGRID_Z0", -1,
"-5", NULL);
6218 scan_ctl(filename, argc, argv,
"CHEMGRID_Z1", -1,
"85", NULL);
6220 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NZ", -1,
"90", NULL);
6222 scan_ctl(filename, argc, argv,
"CHEMGRID_LON0", -1,
"-180", NULL);
6224 scan_ctl(filename, argc, argv,
"CHEMGRID_LON1", -1,
"180", NULL);
6226 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NX", -1,
"360", NULL);
6228 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT0", -1,
"-90", NULL);
6230 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT1", -1,
"90", NULL);
6232 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NY", -1,
"180", NULL);
6237 scan_ctl(filename, argc, argv,
"TDEC_STRAT", -1,
"0", NULL);
6240 ctl->
psc_h2o =
scan_ctl(filename, argc, argv,
"PSC_H2O", -1,
"4e-6", NULL);
6242 scan_ctl(filename, argc, argv,
"PSC_HNO3", -1,
"9e-9", NULL);
6248 scan_ctl(filename, argc, argv,
"ATM_DT_OUT", -1,
"86400", NULL);
6250 (int)
scan_ctl(filename, argc, argv,
"ATM_FILTER", -1,
"0", NULL);
6252 (int)
scan_ctl(filename, argc, argv,
"ATM_STRIDE", -1,
"1", NULL);
6254 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE", -1,
"0", NULL);
6256 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE_OUT", -1,
"-1", NULL);
6260 (int)
scan_ctl(filename, argc, argv,
"ATM_NC_LEVEL", -1,
"0", NULL);
6261 for (
int iq = 0; iq < ctl->
nq; iq++)
6263 (
int)
scan_ctl(filename, argc, argv,
"ATM_NC_QUANT", iq,
"0", NULL);
6265 (int)
scan_ctl(filename, argc, argv,
"OBS_TYPE", -1,
"0", NULL);
6271 scan_ctl(filename, argc, argv,
"CSI_DT_OUT", -1,
"86400", NULL);
6274 scan_ctl(filename, argc, argv,
"CSI_OBSMIN", -1,
"0", NULL);
6276 scan_ctl(filename, argc, argv,
"CSI_MODMIN", -1,
"0", NULL);
6277 ctl->
csi_z0 =
scan_ctl(filename, argc, argv,
"CSI_Z0", -1,
"-5", NULL);
6278 ctl->
csi_z1 =
scan_ctl(filename, argc, argv,
"CSI_Z1", -1,
"85", NULL);
6279 ctl->
csi_nz = (int)
scan_ctl(filename, argc, argv,
"CSI_NZ", -1,
"1", NULL);
6281 scan_ctl(filename, argc, argv,
"CSI_LON0", -1,
"-180", NULL);
6282 ctl->
csi_lon1 =
scan_ctl(filename, argc, argv,
"CSI_LON1", -1,
"180", NULL);
6284 (int)
scan_ctl(filename, argc, argv,
"CSI_NX", -1,
"360", NULL);
6285 ctl->
csi_lat0 =
scan_ctl(filename, argc, argv,
"CSI_LAT0", -1,
"-90", NULL);
6286 ctl->
csi_lat1 =
scan_ctl(filename, argc, argv,
"CSI_LAT1", -1,
"90", NULL);
6288 (int)
scan_ctl(filename, argc, argv,
"CSI_NY", -1,
"180", NULL);
6291 ctl->
nens = (int)
scan_ctl(filename, argc, argv,
"NENS", -1,
"0", NULL);
6294 scan_ctl(filename, argc, argv,
"ENS_DT_OUT", -1,
"86400", NULL);
6297 scan_ctl(filename, argc, argv,
"GRID_BASENAME", -1,
"-",
6302 scan_ctl(filename, argc, argv,
"GRID_DT_OUT", -1,
"86400", NULL);
6304 (int)
scan_ctl(filename, argc, argv,
"GRID_SPARSE", -1,
"0", NULL);
6306 (int)
scan_ctl(filename, argc, argv,
"GRID_NC_LEVEL", -1,
"0", NULL);
6307 for (
int iq = 0; iq < ctl->
nq; iq++)
6309 (
int)
scan_ctl(filename, argc, argv,
"GRID_NC_QUANT", iq,
"0", NULL);
6311 (int)
scan_ctl(filename, argc, argv,
"GRID_STDDEV", -1,
"0", NULL);
6312 ctl->
grid_z0 =
scan_ctl(filename, argc, argv,
"GRID_Z0", -1,
"-5", NULL);
6313 ctl->
grid_z1 =
scan_ctl(filename, argc, argv,
"GRID_Z1", -1,
"85", NULL);
6315 (int)
scan_ctl(filename, argc, argv,
"GRID_NZ", -1,
"1", NULL);
6317 scan_ctl(filename, argc, argv,
"GRID_LON0", -1,
"-180", NULL);
6319 scan_ctl(filename, argc, argv,
"GRID_LON1", -1,
"180", NULL);
6321 (int)
scan_ctl(filename, argc, argv,
"GRID_NX", -1,
"360", NULL);
6323 scan_ctl(filename, argc, argv,
"GRID_LAT0", -1,
"-90", NULL);
6325 scan_ctl(filename, argc, argv,
"GRID_LAT1", -1,
"90", NULL);
6327 (int)
scan_ctl(filename, argc, argv,
"GRID_NY", -1,
"180", NULL);
6329 (int)
scan_ctl(filename, argc, argv,
"GRID_TYPE", -1,
"0", NULL);
6332 scan_ctl(filename, argc, argv,
"PROF_BASENAME", -1,
"-",
6335 ctl->
prof_z0 =
scan_ctl(filename, argc, argv,
"PROF_Z0", -1,
"0", NULL);
6336 ctl->
prof_z1 =
scan_ctl(filename, argc, argv,
"PROF_Z1", -1,
"60", NULL);
6338 (int)
scan_ctl(filename, argc, argv,
"PROF_NZ", -1,
"60", NULL);
6340 scan_ctl(filename, argc, argv,
"PROF_LON0", -1,
"-180", NULL);
6342 scan_ctl(filename, argc, argv,
"PROF_LON1", -1,
"180", NULL);
6344 (int)
scan_ctl(filename, argc, argv,
"PROF_NX", -1,
"360", NULL);
6346 scan_ctl(filename, argc, argv,
"PROF_LAT0", -1,
"-90", NULL);
6348 scan_ctl(filename, argc, argv,
"PROF_LAT1", -1,
"90", NULL);
6350 (int)
scan_ctl(filename, argc, argv,
"PROF_NY", -1,
"180", NULL);
6353 scan_ctl(filename, argc, argv,
"SAMPLE_BASENAME", -1,
"-",
6355 scan_ctl(filename, argc, argv,
"SAMPLE_KERNEL", -1,
"-",
6357 scan_ctl(filename, argc, argv,
"SAMPLE_OBSFILE", -1,
"-",
6360 scan_ctl(filename, argc, argv,
"SAMPLE_DX", -1,
"50", NULL);
6362 scan_ctl(filename, argc, argv,
"SAMPLE_DZ", -1,
"-999", NULL);
6365 scan_ctl(filename, argc, argv,
"STAT_BASENAME", -1,
"-",
6369 ctl->
stat_r =
scan_ctl(filename, argc, argv,
"STAT_R", -1,
"50", NULL);
6371 scan_ctl(filename, argc, argv,
"STAT_T0", -1,
"-1e100", NULL);
6372 ctl->
stat_t1 =
scan_ctl(filename, argc, argv,
"STAT_T1", -1,
"1e100", NULL);
6377 scan_ctl(filename, argc, argv,
"VTK_DT_OUT", -1,
"86400", NULL);
6379 (int)
scan_ctl(filename, argc, argv,
"VTK_STRIDE", -1,
"1", NULL);
6381 scan_ctl(filename, argc, argv,
"VTK_SCALE", -1,
"1.0", NULL);
6383 scan_ctl(filename, argc, argv,
"VTK_OFFSET", -1,
"0.0", NULL);
6385 (int)
scan_ctl(filename, argc, argv,
"VTK_SPHERE", -1,
"0", NULL);
6388 ctl->
dd = (int)
scan_ctl(filename, argc, argv,
"DD", -1,
"0", NULL);
6390 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_MERIDIONAL", -1,
6391 (ctl->
dd == 1) ?
"2" :
"1", NULL);
6393 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_ZONAL", -1,
6394 (ctl->
dd == 1) ?
"2" :
"1", NULL);
6397 else if (ctl->
dd == 1)
6398 ERRMSG(
"Please provide zonal and meridional subdomain numbers!")
6400 (int)
scan_ctl(filename, argc, argv,
"DD_NBR_NEIGHBOURS", -1,
"8",
6403 (int)
scan_ctl(filename, argc, argv,
"DD_HALOS_SIZE", -1,
"1", NULL);
6409 const char *filename,
6416 LOG(1,
"Read meteo data: %s", filename);
6422 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
6450 ERRMSG(
"MET_TYPE not implemented!");
6504 LOG(2,
"Broadcast data on rank %d...", rank);
6639 ERRMSG(
"DD initialized, but model is compiled without DD.")
6648 ERRMSG(
"Code was compiled without KPP!");
6681#pragma acc update device(ctl[:1])
6685 if (cache != NULL) {
6688#pragma acc update device(cache[:1])
6695#pragma acc update device(clim[:1])
6702 met_t *met0up = *met0;
6703#pragma acc update device(met0up[:1])
6710 met_t *met1up = *met1;
6711#pragma acc update device(met1up[:1])
6718#pragma acc update device(atm[:1])
6737#pragma acc update host(ctl[:1])
6741 if (cache != NULL) {
6744#pragma acc update host(cache[:1])
6751#pragma acc update host(clim[:1])
6758 met_t *met0up = *met0;
6759#pragma acc update host(met0up[:1])
6766 met_t *met1up = *met1;
6767#pragma acc update host(met1up[:1])
6774#pragma acc update host(atm[:1])
6782 const char *filename,
6791 LOG(1,
"Write atmospheric data: %s", filename);
6815 ERRMSG(
"Atmospheric data type not supported!");
6819 LOG(2,
"Number of particles: %d", atm->
np);
6820 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
6821 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
6822 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
6823 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
6824 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
6825 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
6826 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
6827 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
6828 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
6829 for (
int iq = 0; iq < ctl->
nq; iq++) {
6831 sprintf(msg,
"Quantity %s range: %s ... %s %s",
6834 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
6835 LOG(2, msg, mini, maxi);
6842 const char *filename,
6850 LOG(1,
"Write meteo data: %s", filename);
6855 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
6859 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
6863 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
6867 ERRMSG(
"MPTRAC was compiled without SZ3 compression!");
6880 ERRMSG(
"MET_TYPE not implemented!");
6886 const char *dirname,
6893 char ext[10], filename[2 *
LEN];
6897 int year, mon, day, hour, min, sec;
6900 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
6915 sprintf(ext,
"tab");
6917 sprintf(ext,
"bin");
6920 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6921 dirname, ctl->
atm_basename, year, mon, day, hour, min, ext);
6927 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6930 write_grid(filename, ctl, met0, met1, atm, t);
6935 sprintf(filename,
"%s/%s.tab", dirname, ctl->
csi_basename);
6941 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.tab",
6942 dirname, ctl->
ens_basename, year, mon, day, hour, min);
6948 sprintf(filename,
"%s/%s.tab", dirname, ctl->
prof_basename);
6949 write_prof(filename, ctl, met0, met1, atm, t);
6960 sprintf(filename,
"%s/%s.tab", dirname, ctl->
stat_basename);
6969 sprintf(filename,
"%s/%s_%05d.vtk", dirname, ctl->
vtk_basename, ++nvtk);
6979 const double hno3) {
6982 const double h2o_help =
MAX(h2o, 0.1e-6);
6985 const double p_hno3 = hno3 * p / 1.333224;
6986 const double p_h2o = h2o_help * p / 1.333224;
6987 const double a = 0.009179 - 0.00088 * log10(p_h2o);
6988 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
6989 const double c = -11397.0 / a;
6990 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
6991 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
7009 const double p0 = pbl;
7012 if (atm->
p[ip] > p0)
7014 else if (atm->
p[ip] < p1)
7017 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
7023 const char *filename,
7029 if (!(in = fopen(filename,
"r"))) {
7030 WARN(
"Cannot open file!");
7036 while (fgets(line,
LEN, in)) {
7040 TOK(line, tok,
"%lg", atm->
time[atm->
np]);
7041 TOK(NULL, tok,
"%lg", atm->
p[atm->
np]);
7042 TOK(NULL, tok,
"%lg", atm->
lon[atm->
np]);
7043 TOK(NULL, tok,
"%lg", atm->
lat[atm->
np]);
7044 for (
int iq = 0; iq < ctl->
nq; iq++)
7045 TOK(NULL, tok,
"%lg", atm->
q[iq][atm->
np]);
7048 atm->
p[atm->
np] =
P(atm->
p[atm->
np]);
7051 if ((++atm->
np) >
NP)
7052 ERRMSG(
"Too many data points!");
7065 const char *filename,
7071 if (!(in = fopen(filename,
"r")))
7076 FREAD(&version,
int,
7080 ERRMSG(
"Wrong version of binary data!");
7098 for (
int iq = 0; iq < ctl->
nq; iq++)
7099 FREAD(atm->
q[iq],
double,
7109 ERRMSG(
"Error while reading binary data!");
7121 const char *filename,
7128 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
7135 if (nc_inq_varid(ncid,
"TIME_INIT", &varid) == NC_NOERR) {
7136 NC(nc_get_var_double(ncid, varid, atm->
time));
7138 WARN(
"TIME_INIT not found use time instead!");
7141 for (
int ip = 0; ip < atm->
np; ip++) {
7142 atm->
time[ip] = time_init;
7154 if (nc_inq_varid(ncid,
"PRESS_INIT", &varid) == NC_NOERR) {
7155 NC(nc_get_var_double(ncid, varid, atm->
p));
7157 WARN(
"PRESS_INIT not found use PRESS instead!");
7158 nc_inq_varid(ncid,
"PRESS", &varid);
7159 NC(nc_get_var_double(ncid, varid, atm->
p));
7164 for (
int iq = 0; iq < ctl->
nq; iq++)
7181 const char *filename,
7188 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
7201 for (
int iq = 0; iq < ctl->
nq; iq++)
7214 const char *filename,
7220 LOG(1,
"Read photolysis rates: %s", filename);
7223 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
7224 WARN(
"Photolysis rate data are missing!");
7231 if (photo->
p[0] < photo->
p[1])
7232 ERRMSG(
"Pressure data are not descending!");
7237 if (photo->
o3c[0] > photo->
o3c[1])
7238 ERRMSG(
"Total column ozone data are not ascending!");
7243 if (photo->
sza[0] > photo->
sza[1])
7244 ERRMSG(
"Solar zenith angle data are not ascending!");
7261 LOG(2,
"Number of pressure levels: %d", photo->
np);
7262 LOG(2,
"Altitude levels: %g, %g ... %g km",
7263 Z(photo->
p[0]),
Z(photo->
p[1]),
Z(photo->
p[photo->
np - 1]));
7264 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
7265 photo->
p[0], photo->
p[1], photo->
p[photo->
np - 1]);
7266 LOG(2,
"Number of solar zenith angles: %d", photo->
nsza);
7267 LOG(2,
"Solar zenith angles: %g, %g ... %g deg",
7270 LOG(2,
"Number of total column ozone values: %d", photo->
no3c);
7271 LOG(2,
"Total column ozone: %g, %g ... %g DU",
7273 LOG(2,
"N2O photolysis rate: %g, %g ... %g s**-1",
7274 photo->
n2o[0][0][0], photo->
n2o[1][0][0],
7275 photo->
n2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7276 LOG(2,
"CCl4 photolysis rate: %g, %g ... %g s**-1",
7277 photo->
ccl4[0][0][0], photo->
ccl4[1][0][0],
7279 LOG(2,
"CFC-11 photolysis rate: %g, %g ... %g s**-1",
7280 photo->
ccl3f[0][0][0], photo->
ccl3f[1][0][0],
7282 LOG(2,
"CFC-12 photolysis rate: %g, %g ... %g s**-1",
7285 LOG(2,
"O2 photolysis rate: %g, %g ... %g s**-1",
7286 photo->
o2[0][0][0], photo->
o2[1][0][0],
7287 photo->
o2[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7288 LOG(2,
"O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
7289 photo->
o3_1[0][0][0], photo->
o3_1[1][0][0],
7291 LOG(2,
"O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
7292 photo->
o3_2[0][0][0], photo->
o3_2[1][0][0],
7294 LOG(2,
"H2O2 photolysis rate: %g, %g ... %g s**-1",
7295 photo->
h2o2[0][0][0], photo->
h2o2[1][0][0],
7297 LOG(2,
"H2O photolysis rate: %g, %g ... %g s**-1",
7298 photo->
h2o[0][0][0], photo->
h2o[1][0][0],
7299 photo->
h2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7306 const char *varname,
7320 for (
int ip = 0; ip < photo->
np; ip++)
7321 for (
int is = 0; is < photo->
nsza; is++)
7322 for (
int io = 0; io < photo->
no3c; io++)
7333 const char *filename,
7337 LOG(1,
"Read climatological time series: %s", filename);
7341 if (!(in = fopen(filename,
"r"))) {
7342 WARN(
"Cannot open file!");
7349 while (fgets(line,
LEN, in))
7350 if (sscanf(line,
"%lg %lg", &ts->
time[nh], &ts->
vmr[nh]) == 2) {
7353 ts->
time[nh] = (ts->
time[nh] - 2000.0) * 365.25 * 86400.;
7356 if (nh > 0 && ts->
time[nh] <= ts->
time[nh - 1])
7357 ERRMSG(
"Time series must be ascending!");
7361 ERRMSG(
"Too many data points!");
7370 ERRMSG(
"Not enough data points!");
7373 LOG(2,
"Number of time steps: %d", ts->
ntime);
7374 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s", ts->
time[0], ts->
time[1],
7376 LOG(2,
"Volume mixing ratio range: %g ... %g ppv",
7377 gsl_stats_min(ts->
vmr, 1, (
size_t) nh), gsl_stats_max(ts->
vmr, 1,
7387 const char *filename,
7388 const char *varname,
7391 int ncid, varid, it, iy, iz, iz2, nt;
7393 double *help, varmin = 1e99, varmax = -1e99;
7396 LOG(1,
"Read %s data: %s", varname, filename);
7399 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
7400 WARN(
"%s climatology data are missing!", varname);
7407 if (zm->
p[0] < zm->
p[1])
7408 ERRMSG(
"Pressure data are not descending!");
7413 if (zm->
lat[0] > zm->
lat[1])
7414 ERRMSG(
"Latitude data are not ascending!");
7418 zm->
time[0] = 1209600.00;
7419 zm->
time[1] = 3888000.00;
7420 zm->
time[2] = 6393600.00;
7421 zm->
time[3] = 9072000.00;
7422 zm->
time[4] = 11664000.00;
7423 zm->
time[5] = 14342400.00;
7424 zm->
time[6] = 16934400.00;
7425 zm->
time[7] = 19612800.00;
7426 zm->
time[8] = 22291200.00;
7427 zm->
time[9] = 24883200.00;
7428 zm->
time[10] = 27561600.00;
7429 zm->
time[11] = 30153600.00;
7438 for (it = 0; it < zm->
ntime; it++)
7439 for (iz = 0; iz < zm->
np; iz++)
7440 for (iy = 0; iy < zm->
nlat; iy++)
7445 for (it = 0; it < zm->
ntime; it++)
7446 for (iy = 0; iy < zm->
nlat; iy++)
7447 for (iz = 0; iz < zm->
np; iz++) {
7448 if (zm->
vmr[it][iz][iy] < 0) {
7449 for (iz2 = 0; iz2 < zm->
np; iz2++)
7450 if (zm->
vmr[it][iz2][iy] >= 0) {
7451 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
7454 for (iz2 = zm->
np - 1; iz2 >= 0; iz2--)
7455 if (zm->
vmr[it][iz2][iy] >= 0) {
7456 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
7460 varmin =
MIN(varmin, zm->
vmr[it][iz][iy]);
7461 varmax =
MAX(varmax, zm->
vmr[it][iz][iy]);
7468 LOG(2,
"Number of time steps: %d", zm->
ntime);
7469 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
7471 LOG(2,
"Number of pressure levels: %d", zm->
np);
7472 LOG(2,
"Altitude levels: %g, %g ... %g km",
7473 Z(zm->
p[0]),
Z(zm->
p[1]),
Z(zm->
p[zm->
np - 1]));
7474 LOG(2,
"Pressure levels: %g, %g ... %g hPa", zm->
p[0],
7475 zm->
p[1], zm->
p[zm->
np - 1]);
7476 LOG(2,
"Number of latitudes: %d", zm->
nlat);
7477 LOG(2,
"Latitudes: %g, %g ... %g deg",
7479 LOG(2,
"%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
7486 const char *filename,
7492 LOG(1,
"Read kernel function: %s", filename);
7496 if (!(in = fopen(filename,
"r")))
7497 ERRMSG(
"Cannot open file!");
7502 while (fgets(line,
LEN, in))
7503 if (sscanf(line,
"%lg %lg", &kz[n], &kw[n]) == 2) {
7504 if (n > 0 && kz[n] < kz[n - 1])
7505 ERRMSG(
"Height levels must be ascending!");
7507 ERRMSG(
"Too many height levels!");
7516 ERRMSG(
"Not enough height levels!");
7519 const double kmax = gsl_stats_max(kw, 1, (
size_t) n);
7520 for (
int iz = 0; iz < n; iz++)
7527 const char *filename,
7535 int year, mon, day, hour, min, sec;
7541 if (!(in = fopen(filename,
"r"))) {
7542 WARN(
"Cannot open file!");
7548 FREAD(&met_type,
int,
7552 ERRMSG(
"Wrong MET_TYPE of binary data!");
7556 FREAD(&version,
int,
7560 ERRMSG(
"Wrong version of binary data!");
7566 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
7567 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
7568 met->
time, year, mon, day, hour, min);
7569 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
7570 || day < 1 || day > 31 || hour < 0 || hour > 23)
7571 ERRMSG(
"Error while reading time!");
7577 LOG(2,
"Number of longitudes: %d", met->
nx);
7578 if (met->
nx < 2 || met->
nx >
EX)
7579 ERRMSG(
"Number of longitudes out of range!");
7584 LOG(2,
"Number of latitudes: %d", met->
ny);
7585 if (met->
ny < 2 || met->
ny >
EY)
7586 ERRMSG(
"Number of latitudes out of range!");
7591 LOG(2,
"Number of levels: %d", met->
np);
7592 if (met->
np < 2 || met->
np >
EP)
7593 ERRMSG(
"Number of levels out of range!");
7599 LOG(2,
"Longitudes: %g, %g ... %g deg",
7605 LOG(2,
"Latitudes: %g, %g ... %g deg",
7611 LOG(2,
"Altitude levels: %g, %g ... %g km",
7612 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
7613 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
7614 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
7663 ERRMSG(
"Error while reading binary data!");
7678 const char *varname) {
7687 LOG(2,
"Read 2-D variable: %s (uncompressed)", varname);
7689 (
size_t) (met->
nx * met->
ny),
7693 for (
int ix = 0; ix < met->
nx; ix++)
7694 for (
int iy = 0; iy < met->
ny; iy++)
7695 var[ix][iy] = help[
ARRAY_2D(ix, iy, met->
ny)];
7708 const char *varname,
7709 const float bound_min,
7710 const float bound_max) {
7720 LOG(2,
"Read 3-D variable: %s (uncompressed)", varname);
7722 (
size_t) (met->
nx * met->
ny * met->
np),
7729 (
size_t) met->
np, 1, in);
7735 FREAD(&precision,
int,
7740 FREAD(&tolerance,
double,
7747 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
7757 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
7765 (
size_t) met->
np, met->
p, 1, in);
7767 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
7775 FREAD(&precision,
int,
7780 FREAD(&tolerance,
double,
7787 ERRMSG(
"MPTRAC was compiled without sz3 compression!");
7792#pragma omp parallel for default(shared) collapse(2)
7793 for (
int ix = 0; ix < met->
nx; ix++)
7794 for (
int iy = 0; iy < met->
ny; iy++)
7795 for (
int ip = 0; ip < met->
np; ip++) {
7796 var[ix][iy][ip] = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
7797 if (var[ix][iy][ip] < bound_min)
7798 var[ix][iy][ip] = bound_min;
7799 else if (var[ix][iy][ip] > bound_max)
7800 var[ix][iy][ip] = bound_max;
7820 LOG(2,
"Calculate CAPE...");
7823 const double pfac = 1.01439, dz0 =
RI /
MA /
G0 * log(pfac);
7826#pragma omp parallel for default(shared) collapse(2)
7827 for (
int ix = 0; ix < met->
nx; ix++)
7828 for (
int iy = 0; iy < met->
ny; iy++) {
7832 double h2o = 0, t, theta = 0;
7833 double pbot =
MIN(met->
ps[ix][iy], met->
p[0]);
7834 double ptop = pbot - 50.;
7835 for (
int ip = 0; ip < met->
np; ip++) {
7836 if (met->
p[ip] <= pbot) {
7837 theta +=
THETA(met->
p[ip], met->
t[ix][iy][ip]);
7838 h2o += met->
h2o[ix][iy][ip];
7841 if (met->
p[ip] < ptop && n > 0)
7848 met->
plcl[ix][iy] = NAN;
7849 met->
plfc[ix][iy] = NAN;
7850 met->
pel[ix][iy] = NAN;
7851 met->
cape[ix][iy] = NAN;
7852 met->
cin[ix][iy] = NAN;
7858 pbot = met->
ps[ix][iy];
7860 met->
plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
7861 t = theta / pow(1000. / met->
plcl[ix][iy], 0.286);
7862 if (
RH(met->
plcl[ix][iy], t, h2o) > 100.)
7863 ptop = met->
plcl[ix][iy];
7865 pbot = met->
plcl[ix][iy];
7866 }
while (pbot - ptop > 0.1);
7870 double dcape, dz, h2o_env, t_env;
7871 double p = met->
ps[ix][iy];
7872 met->
cape[ix][iy] = met->
cin[ix][iy] = 0;
7874 dz = dz0 *
TVIRT(t, h2o);
7876 t = theta / pow(1000. / p, 0.286);
7880 &h2o_env, ci, cw, 0);
7881 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
7882 TVIRT(t_env, h2o_env) * dz;
7884 met->
cin[ix][iy] += fabsf((
float) dcape);
7885 }
while (p > met->
plcl[ix][iy]);
7890 p = met->
plcl[ix][iy];
7891 t = theta / pow(1000. / p, 0.286);
7894 dz = dz0 *
TVIRT(t, h2o);
7897 double psat =
PSAT(t);
7898 h2o = psat / (p - (1. -
EPS) * psat);
7902 &h2o_env, ci, cw, 0);
7903 double dcape_old = dcape;
7904 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
7905 TVIRT(t_env, h2o_env) * dz;
7907 met->
cape[ix][iy] += (float) dcape;
7908 if (!isfinite(met->
plfc[ix][iy]))
7909 met->
plfc[ix][iy] = (
float) p;
7910 }
else if (dcape_old > 0)
7911 met->
pel[ix][iy] = (float) p;
7912 if (dcape < 0 && !isfinite(met->
plfc[ix][iy]))
7913 met->
cin[ix][iy] += fabsf((
float) dcape);
7917 if (!isfinite(met->
plfc[ix][iy]))
7918 met->
cin[ix][iy] = NAN;
7929 LOG(2,
"Calculate cloud data...");
7932 const double ccmin = 0.01, cwmin = 1e-6;
7935#pragma omp parallel for default(shared) collapse(2)
7936 for (
int ix = 0; ix < met->
nx; ix++)
7937 for (
int iy = 0; iy < met->
ny; iy++) {
7940 met->
pct[ix][iy] = NAN;
7941 met->
pcb[ix][iy] = NAN;
7942 met->
cl[ix][iy] = 0;
7945 for (
int ip = 0; ip < met->
np - 1; ip++) {
7948 if (met->
p[ip] > met->
ps[ix][iy] || met->
p[ip] <
P(20.))
7952 if (met->
cc[ix][iy][ip] > ccmin
7953 && (met->
lwc[ix][iy][ip] > cwmin
7954 || met->
rwc[ix][iy][ip] > cwmin
7955 || met->
iwc[ix][iy][ip] > cwmin
7956 || met->
swc[ix][iy][ip] > cwmin)) {
7960 = (float) (0.5 * (met->
p[ip] + (
float) met->
p[ip + 1]));
7963 if (!isfinite(met->
pcb[ix][iy]))
7965 = (
float) (0.5 * (met->
p[ip] + met->
p[
MAX(ip - 1, 0)]));
7969 met->
cl[ix][iy] += (float)
7970 (0.5 * (met->
lwc[ix][iy][ip] + met->
lwc[ix][iy][ip + 1]
7971 + met->
rwc[ix][iy][ip] + met->
rwc[ix][iy][ip + 1]
7972 + met->
iwc[ix][iy][ip] + met->
iwc[ix][iy][ip + 1]
7973 + met->
swc[ix][iy][ip] + met->
swc[ix][iy][ip + 1])
7974 * 100. * (met->
p[ip] - met->
p[ip + 1]) /
G0);
7993 LOG(2,
"Detrend meteo data...");
8000 const double tssq = 2. *
SQR(sigma);
8003 int sy = (int) (3. *
DY2DEG(sigma) / fabs(met->
lat[1] - met->
lat[0]));
8007#pragma omp parallel for default(shared) collapse(2)
8008 for (
int ix = 0; ix < met->
nx; ix++) {
8009 for (
int iy = 0; iy < met->
ny; iy++) {
8017 (int) (3. *
DX2DEG(sigma, met->
lat[iy]) /
8018 fabs(met->
lon[1] - met->
lon[0]));
8023 for (
int ip = 0; ip < met->
np; ip++) {
8024 help->
t[ix][iy][ip] = 0;
8025 help->
u[ix][iy][ip] = 0;
8026 help->
v[ix][iy][ip] = 0;
8027 help->
w[ix][iy][ip] = 0;
8031 for (
int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
8035 else if (ix3 >= met->
nx)
8037 for (
int iy2 =
MAX(iy - sy, 0);
8038 iy2 <=
MIN(iy + sy, met->
ny - 1); iy2++) {
8045 const float w = (float) exp(-
DIST2(x0, x1) / tssq);
8049 for (
int ip = 0; ip < met->
np; ip++) {
8050 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip];
8051 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip];
8052 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip];
8053 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip];
8059 for (
int ip = 0; ip < met->
np; ip++) {
8060 help->
t[ix][iy][ip] /= wsum;
8061 help->
u[ix][iy][ip] /= wsum;
8062 help->
v[ix][iy][ip] /= wsum;
8063 help->
w[ix][iy][ip] /= wsum;
8069#pragma omp parallel for default(shared) collapse(3)
8070 for (
int ix = 0; ix < met->
nx; ix++)
8071 for (
int iy = 0; iy < met->
ny; iy++)
8072 for (
int ip = 0; ip < met->
np; ip++) {
8073 met->
t[ix][iy][ip] -= help->
t[ix][iy][ip];
8074 met->
u[ix][iy][ip] -= help->
u[ix][iy][ip];
8075 met->
v[ix][iy][ip] -= help->
v[ix][iy][ip];
8076 met->
w[ix][iy][ip] -= help->
w[ix][iy][ip];
8090 LOG(2,
"Extrapolate meteo data...");
8093#pragma omp parallel for default(shared) collapse(2)
8094 for (
int ix = 0; ix < met->
nx; ix++)
8095 for (
int iy = 0; iy < met->
ny; iy++) {
8099 for (ip0 = met->
np - 1; ip0 >= 0; ip0--)
8100 if (!isfinite(met->
t[ix][iy][ip0])
8101 || !isfinite(met->
u[ix][iy][ip0])
8102 || !isfinite(met->
v[ix][iy][ip0])
8103 || !isfinite(met->
w[ix][iy][ip0]))
8107 for (
int ip = ip0; ip >= 0; ip--) {
8108 met->
t[ix][iy][ip] = met->
t[ix][iy][ip + 1];
8109 met->
u[ix][iy][ip] = met->
u[ix][iy][ip + 1];
8110 met->
v[ix][iy][ip] = met->
v[ix][iy][ip + 1];
8111 met->
w[ix][iy][ip] = met->
w[ix][iy][ip + 1];
8112 met->
h2o[ix][iy][ip] = met->
h2o[ix][iy][ip + 1];
8113 met->
o3[ix][iy][ip] = met->
o3[ix][iy][ip + 1];
8114 met->
lwc[ix][iy][ip] = met->
lwc[ix][iy][ip + 1];
8115 met->
rwc[ix][iy][ip] = met->
rwc[ix][iy][ip + 1];
8116 met->
iwc[ix][iy][ip] = met->
iwc[ix][iy][ip + 1];
8117 met->
swc[ix][iy][ip] = met->
swc[ix][iy][ip + 1];
8118 met->
cc[ix][iy][ip] = met->
cc[ix][iy][ip + 1];
8137 LOG(2,
"Calculate geopotential heights...");
8144#pragma omp parallel for default(shared)
8145 for (
int ip = 0; ip < met->
np; ip++)
8146 logp[ip] = log(met->
p[ip]);
8149#pragma omp parallel for default(shared) collapse(2)
8150 for (
int ix = 0; ix < met->
nx; ix++)
8151 for (
int iy = 0; iy < met->
ny; iy++) {
8154 const double zs = met->
zs[ix][iy];
8155 const double lnps = log(met->
ps[ix][iy]);
8159 const double ts =
LIN(met->
p[ip0], met->
t[ix][iy][ip0], met->
p[ip0 + 1],
8160 met->
t[ix][iy][ip0 + 1], met->
ps[ix][iy]);
8162 LIN(met->
p[ip0], met->
h2o[ix][iy][ip0], met->
p[ip0 + 1],
8163 met->
h2o[ix][iy][ip0 + 1], met->
ps[ix][iy]);
8166 met->
z[ix][iy][ip0 + 1]
8168 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
8169 met->
t[ix][iy][ip0 + 1], met->
h2o[ix][iy][ip0 + 1]));
8170 for (
int ip = ip0 + 2; ip < met->
np; ip++)
8172 = (
float) (met->
z[ix][iy][ip - 1] +
8173 ZDIFF(logp[ip - 1], met->
t[ix][iy][ip - 1],
8174 met->
h2o[ix][iy][ip - 1], logp[ip],
8175 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
8180 ZDIFF(lnps, ts, h2os, logp[ip0],
8181 met->
t[ix][iy][ip0], met->
h2o[ix][iy][ip0]));
8182 for (
int ip = ip0 - 1; ip >= 0; ip--)
8184 = (
float) (met->
z[ix][iy][ip + 1] +
8185 ZDIFF(logp[ip + 1], met->
t[ix][iy][ip + 1],
8186 met->
h2o[ix][iy][ip + 1], logp[ip],
8187 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
8191 if (dx == 0 || dy == 0)
8195 if (dx < 0 || dy < 0) {
8196 if (fabs(met->
lon[1] - met->
lon[0]) < 0.5) {
8206 float ws[dx + 1][dy + 1];
8207#pragma omp parallel for default(shared) collapse(2)
8208 for (
int ix = 0; ix <= dx; ix++)
8209 for (
int iy = 0; iy < dy; iy++)
8210 ws[ix][iy] = (1.0f - (
float) ix / (float) dx)
8211 * (1.0f - (float) iy / (
float) dy);
8214#pragma omp parallel for default(shared) collapse(3)
8215 for (
int ix = 0; ix < met->
nx; ix++)
8216 for (
int iy = 0; iy < met->
ny; iy++)
8217 for (
int ip = 0; ip < met->
np; ip++)
8218 help[
ARRAY_3D(ip, ix, met->
nx, iy, met->
ny)] = met->
z[ix][iy][ip];
8221#pragma omp parallel for default(shared) collapse(3)
8222 for (
int ip = 0; ip < met->
np; ip++)
8223 for (
int ix = 0; ix < met->
nx; ix++)
8224 for (
int iy = 0; iy < met->
ny; iy++) {
8225 float res = 0, wsum = 0;
8226 int iy0 =
MAX(iy - dy + 1, 0);
8227 int iy1 =
MIN(iy + dy - 1, met->
ny - 1);
8228 for (
int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
8232 else if (ix3 >= met->
nx)
8234 for (
int iy2 = iy0; iy2 <= iy1; ++iy2)
8235 if (isfinite(help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)])) {
8236 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
8237 res += w * help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)];
8242 met->
z[ix][iy][ip] = res / wsum;
8244 met->
z[ix][iy][ip] = NAN;
8254 const char *filename,
8260 char levname[
LEN], tstr[10];
8262 double rtime = 0, r, r2;
8264 int varid, ndims, dimids[NC_MAX_DIMS], year2, mon2, day2, hour2, min2, sec2,
8265 year, mon, day, hour, min, sec;
8271 LOG(2,
"Read meteo grid information...");
8280 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
8281 if (nc_inq_varid(ncid,
"time", &varid) == NC_NOERR) {
8282 NC(nc_get_var_double(ncid, varid, &rtime));
8283 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
8284 WARN(
"Time information in meteo file does not match filename!");
8286 WARN(
"Time information in meteo file is missing!");
8297 sprintf(tstr,
"19%.2s", &filename[strlen(filename) - 11]);
8299 sprintf(tstr,
"20%.2s", &filename[strlen(filename) - 11]);
8301 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 9]);
8303 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 7]);
8305 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 5]);
8311 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
8312 || day < 1 || day > 31 || hour < 0 || hour > 23)
8313 ERRMSG(
"Cannot read time from filename!");
8314 jsec2time(met->
time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
8315 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
8316 met->
time, year2, mon2, day2, hour2, min2);
8319 if (nc_inq_varid(ncid,
"u", &varid) != NC_NOERR)
8320 if (nc_inq_varid(ncid,
"U", &varid) != NC_NOERR)
8322 (
"Variable 'u' or 'U' not found, cannot determine vertical dimension!");
8324 NC(nc_inq_varndims(ncid, varid, &ndims));
8325 NC(nc_inq_vardimid(ncid, varid, dimids));
8329 (ncid, dimids[ctl->
met_convention == 0 ? 1 : 3], levname, &dimlen));
8330 }
else if (ndims == 3) {
8332 (ncid, dimids[ctl->
met_convention == 0 ? 0 : 2], levname, &dimlen));
8334 ERRMSG(
"Cannot determine vertical dimension!")
8335 met->
np = (int) dimlen;
8337 LOG(2,
"Number of levels: %d", met->
np);
8338 if (met->
np < 2 || met->
np >
EP)
8339 ERRMSG(
"Number of levels out of range!");
8345 LOG(2,
"Number of longitudes: %d", met->
nx);
8348 LOG(2,
"Number of latitudes: %d", met->
ny);
8352 LOG(2,
"Longitudes: %g, %g ... %g deg",
8355 LOG(2,
"Latitudes: %g, %g ... %g deg",
8368 for (
int ip = 0; ip < met->
np; ip++)
8370 LOG(2,
"Altitude levels: %g, %g ... %g km",
8371 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
8372 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
8373 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
8377 if (strcasecmp(levname,
"hybrid") == 0)
8389 ERRMSG(
"You need to specify MET_NLEV, MET_LEV_HYAM, and MET_LEV_HYBM!");
8390 for (
int ip = 0; ip < ctl->
met_nlev; ip++) {
8398 met->
eta[k] = met->
hyam[k] / 100000.0 + met->
hybm[k];
8400 ERRMSG(
"Eta levels must be ascending!");
8404 for (
int ix = 2; ix < met->
nx; ix++)
8406 (fabs(met->
lon[ix] - met->
lon[ix - 1]) -
8407 fabs(met->
lon[1] - met->
lon[0])) > 0.001)
8408 ERRMSG(
"No regular grid spacing in longitudes!");
8409 for (
int iy = 2; iy < met->
ny; iy++)
8411 (fabs(met->
lat[iy] - met->
lat[iy - 1]) -
8412 fabs(met->
lat[1] - met->
lat[0])) > 0.001) {
8413 WARN(
"No regular grid spacing in latitudes!");
8428 LOG(2,
"Read surface data...");
8432 (ncid,
"lnsp",
"LNSP", NULL, NULL, NULL, NULL, ctl, met, dd, met->
ps,
8434 for (
int ix = 0; ix < met->
nx; ix++)
8435 for (
int iy = 0; iy < met->
ny; iy++)
8436 met->
ps[ix][iy] = (
float) (exp(met->
ps[ix][iy]) / 100.);
8439 (ncid,
"ps",
"PS",
"sp",
"SP", NULL, NULL, ctl, met, dd, met->
ps,
8441 WARN(
"Cannot not read surface pressure data (use lowest level)!");
8442 for (
int ix = 0; ix < met->
nx; ix++)
8443 for (
int iy = 0; iy < met->
ny; iy++)
8445 = (ctl->
met_np > 0 ? (
float) ctl->
met_p[0] : (
float) met->
p[0]);
8453 (ncid,
"z",
"Z", NULL, NULL, NULL, NULL, ctl, met, dd, met->
zs,
8454 (
float) (1. / (1000. *
G0)), 1))
8456 (ncid,
"zm",
"ZM", NULL, NULL, NULL, NULL, ctl, met, dd, met->
zs,
8457 (
float) (1. / 1000.), 1))
8458 WARN(
"Cannot read surface geopotential height!");
8469 memcpy(help, met->
pl,
sizeof(met->
pl));
8471 (ncid,
"gph",
"GPH", NULL, NULL, ctl, met, dd, met->
pl,
8472 (
float) (1e-3 /
G0)))
8473 ERRMSG(
"Cannot read geopotential height!");
8474 for (
int ix = 0; ix < met->
nx; ix++)
8475 for (
int iy = 0; iy < met->
ny; iy++)
8476 met->
zs[ix][iy] = met->
pl[ix][iy][0];
8477 memcpy(met->
pl, help,
sizeof(met->
pl));
8483 (ncid,
"t2m",
"T2M",
"2t",
"2T",
"t2",
"T2", ctl, met, dd, met->
ts, 1.0,
8485 WARN(
"Cannot read surface temperature!");
8489 (ncid,
"u10m",
"U10M",
"10u",
"10U",
"u10",
"U10", ctl, met, dd,
8491 WARN(
"Cannot read surface zonal wind!");
8495 (ncid,
"v10m",
"V10M",
"10v",
"10V",
"v10",
"V10", ctl, met, dd,
8497 WARN(
"Cannot read surface meridional wind!");
8501 (ncid,
"iews",
"IEWS", NULL, NULL, NULL, NULL, ctl, met, dd, met->
ess,
8503 WARN(
"Cannot read eastward turbulent surface stress!");
8507 (ncid,
"inss",
"INSS", NULL, NULL, NULL, NULL, ctl, met, dd, met->
nss,
8509 WARN(
"Cannot read nothward turbulent surface stress!");
8513 (ncid,
"ishf",
"ISHF", NULL, NULL, NULL, NULL, ctl, met, dd, met->
shf,
8515 WARN(
"Cannot read surface sensible heat flux!");
8519 (ncid,
"lsm",
"LSM", NULL, NULL, NULL, NULL, ctl, met, dd, met->
lsm,
8521 WARN(
"Cannot read land-sea mask!");
8525 (ncid,
"sstk",
"SSTK",
"sst",
"SST", NULL, NULL, ctl, met, dd, met->
sst,
8527 WARN(
"Cannot read sea surface temperature!");
8532 (ncid,
"blp",
"BLP", NULL, NULL, NULL, NULL, ctl, met, dd, met->
pbl,
8534 WARN(
"Cannot read planetary boundary layer pressure!");
8537 (ncid,
"blh",
"BLH", NULL, NULL, NULL, NULL, ctl, met, dd, met->
pbl,
8539 WARN(
"Cannot read planetary boundary layer height!");
8544 (ncid,
"cape",
"CAPE", NULL, NULL, NULL, NULL, ctl, met, dd,
8546 WARN(
"Cannot read CAPE!");
8551 (ncid,
"cin",
"CIN", NULL, NULL, NULL, NULL, ctl, met, dd, met->
cin,
8553 WARN(
"Cannot read convective inhibition!");
8566 LOG(2,
"Read level data...");
8570 (ncid,
"t",
"T",
"temp",
"TEMP", ctl, met, dd, met->
t, 1.0))
8571 ERRMSG(
"Cannot read temperature!");
8574 if (!
read_met_nc_3d(ncid,
"u",
"U", NULL, NULL, ctl, met, dd, met->
u, 1.0))
8575 ERRMSG(
"Cannot read zonal wind!");
8576 if (!
read_met_nc_3d(ncid,
"v",
"V", NULL, NULL, ctl, met, dd, met->
v, 1.0))
8577 ERRMSG(
"Cannot read meridional wind!");
8579 (ncid,
"w",
"W",
"omega",
"OMEGA", ctl, met, dd, met->
w, 0.01f))
8580 WARN(
"Cannot read vertical velocity!");
8585 (ncid,
"q",
"Q",
"sh",
"SH", ctl, met, dd, met->
h2o,
8587 WARN(
"Cannot read specific humidity!");
8590 (ncid,
"rh",
"RH", NULL, NULL, ctl, met, dd, met->
h2o, 0.01f))
8591 WARN(
"Cannot read relative humidity!");
8592#pragma omp parallel for default(shared) collapse(2)
8593 for (
int ix = 0; ix < met->
nx; ix++)
8594 for (
int iy = 0; iy < met->
ny; iy++)
8595 for (
int ip = 0; ip < met->
np; ip++) {
8596 double pw = met->
h2o[ix][iy][ip] *
PSAT(met->
t[ix][iy][ip]);
8597 met->
h2o[ix][iy][ip] =
8598 (float) (pw / (met->
p[ip] - (1.0 -
EPS) * pw));
8604 (ncid,
"o3",
"O3", NULL, NULL, ctl, met, dd, met->
o3,
8605 (
float) (
MA /
MO3)))
8606 WARN(
"Cannot read ozone data!");
8610 (ncid,
"clwc",
"CLWC", NULL, NULL, ctl, met, dd, met->
lwc, 1.0))
8611 WARN(
"Cannot read cloud liquid water content!");
8613 (ncid,
"crwc",
"CRWC", NULL, NULL, ctl, met, dd, met->
rwc, 1.0))
8614 WARN(
"Cannot read cloud rain water content!");
8616 (ncid,
"ciwc",
"CIWC", NULL, NULL, ctl, met, dd, met->
iwc, 1.0))
8617 WARN(
"Cannot read cloud ice water content!");
8619 (ncid,
"cswc",
"CSWC", NULL, NULL, ctl, met, dd, met->
swc, 1.0))
8620 WARN(
"Cannot read cloud snow water content!");
8622 (ncid,
"cc",
"CC", NULL, NULL, ctl, met, dd, met->
cc, 1.0))
8623 WARN(
"Cannot read cloud cover!");
8628 (ncid,
"ZETA",
"zeta", NULL, NULL, ctl, met, dd, met->
zetal, 1.0))
8629 WARN(
"Cannot read ZETA!");
8631 (ncid,
"ZETA_DOT_TOT",
"ZETA_DOT_clr",
"zeta_dot_clr",
8632 NULL, ctl, met, dd, met->
zeta_dotl, 0.00001157407f))
8633 WARN(
"Cannot read ZETA_DOT!");
8638#pragma omp parallel for default(shared)
8639 for (
int ix = 0; ix < met->
nx; ix++)
8640 for (
int iy = 0; iy < met->
ny; iy++)
8641 for (
int ip = 0; ip < met->
np; ip++)
8642 met->
zetal[ix][iy][ip] =
8643 (
float) (met->
hyam[ip] / 100000.0 + met->
hybm[ip]);
8645 (ncid,
"etadot",
"ETADOT", NULL, NULL, ctl, met, dd, met->
zeta_dotl,
8647 WARN(
"Cannot read eta vertical velocity!");
8652#pragma omp parallel for default(shared)
8653 for (
int ix = 0; ix < met->
nx; ix++)
8654 for (
int iy = 0; iy < met->
ny; iy++)
8655 for (
int ip = 0; ip < met->
np; ip++) {
8656 met->
ul[ix][iy][ip] = met->
u[ix][iy][ip];
8657 met->
vl[ix][iy][ip] = met->
v[ix][iy][ip];
8658 met->
wl[ix][iy][ip] = met->
w[ix][iy][ip];
8671 (ncid,
"pl",
"PL",
"pressure",
"PRESSURE", ctl, met, dd, met->
pl,
8674 (ncid,
"press",
"PRESS", NULL, NULL, ctl, met, dd, met->
pl, 1.0))
8675 ERRMSG(
"Cannot read pressure on model levels!");
8683 ERRMSG(
"Mismatch in number of model levels!");
8686 for (
int ix = 0; ix < met->
nx; ix++)
8687 for (
int iy = 0; iy < met->
ny; iy++)
8688 for (
int ip = 0; ip < met->
np; ip++)
8689 met->
pl[ix][iy][ip] =
8690 (
float) (met->
hyam[ip] / 100. +
8691 met->
hybm[ip] * met->
ps[ix][iy]);
8699 ERRMSG(
"Mismatch in number of model levels!");
8702#pragma omp parallel for default(shared) collapse(2)
8703 for (
int ix = 0; ix < met->
nx; ix++)
8704 for (
int iy = 0; iy < met->
ny; iy++)
8705 for (
int ip = 0; ip < met->
np; ip++) {
8707 met->
hyam[ip] / 100. + met->
hybm[ip] * met->
ps[ix][iy];
8709 met->
hyam[ip + 1] / 100. + met->
hybm[ip + 1] * met->
ps[ix][iy];
8710 met->
pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
8715 for (
int ix = 0; ix < met->
nx; ix++)
8716 for (
int iy = 0; iy < met->
ny; iy++)
8717 for (
int ip = 1; ip < met->
np; ip++)
8718 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
8719 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
8720 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
8721 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip]))
8722 ERRMSG(
"Pressure profiles are not monotonic!");
8743 for (
int ip = 0; ip < met->
np; ip++)
8744 met->
p[ip] = ctl->
met_p[ip];
8748 for (
int ip = 1; ip < met->
np; ip++)
8749 if (met->
p[ip - 1] < met->
p[ip])
8750 ERRMSG(
"Pressure levels must be descending!");
8757 const char *varname,
8758 const char *varname2,
8759 const char *varname3,
8760 const char *varname4,
8761 const char *varname5,
8762 const char *varname6,
8772 float offset, scalfac;
8777 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
8778 sprintf(varsel,
"%s", varname);
8779 else if (varname2 != NULL
8780 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
8781 sprintf(varsel,
"%s", varname2);
8782 else if (varname3 != NULL
8783 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
8784 sprintf(varsel,
"%s", varname3);
8785 else if (varname4 != NULL
8786 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
8787 sprintf(varsel,
"%s", varname4);
8788 else if (varname5 != NULL
8789 && nc_inq_varid(ncid, varname5, &varid) == NC_NOERR)
8790 sprintf(varsel,
"%s", varname5);
8791 else if (varname6 != NULL
8792 && nc_inq_varid(ncid, varname6, &varid) == NC_NOERR)
8793 sprintf(varsel,
"%s", varname6);
8799 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
8800 && nc_get_att_float(ncid, varid,
"scale_factor",
8801 &scalfac) == NC_NOERR) {
8809 short fillval, missval;
8810 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8812 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8816 LOG(2,
"Read 2-D variable: %s"
8817 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
8818 varsel, fillval, missval, scalfac, offset);
8821 NC(nc_get_var_short(ncid, varid, help));
8825 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
8829#pragma omp parallel for default(shared)
8830 for (
int ix = 0; ix < met->
nx; ix++)
8831 for (
int iy = 0; iy < met->
ny; iy++) {
8834 const short aux = help[
ARRAY_2D(iy, ix, met->
nx)];
8835 if ((fillval == 0 || aux != fillval)
8836 && (missval == 0 || aux != missval)
8837 && fabsf(aux * scalfac + offset) < 1e14f)
8838 dest[ix][iy] += scl * (aux * scalfac + offset);
8849 else if (!ctl->
dd) {
8857 float fillval, missval;
8858 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8860 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8864 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
8865 varsel, fillval, missval);
8868 NC(nc_get_var_float(ncid, varid, help));
8875#pragma omp parallel for default(shared)
8876 for (
int ix = 0; ix < met->
nx; ix++)
8877 for (
int iy = 0; iy < met->
ny; iy++) {
8880 const float aux = help[
ARRAY_2D(iy, ix, met->
nx)];
8881 if ((fillval == 0 || aux != fillval)
8882 && (missval == 0 || aux != missval)
8883 && fabsf(aux) < 1e14f)
8884 dest[ix][iy] += scl * aux;
8894#pragma omp parallel for default(shared)
8895 for (
int iy = 0; iy < met->
ny; iy++)
8896 for (
int ix = 0; ix < met->
nx; ix++) {
8899 const float aux = help[
ARRAY_2D(ix, iy, met->
ny)];
8900 if ((fillval == 0 || aux != fillval)
8901 && (missval == 0 || aux != missval)
8902 && fabsf(aux) < 1e14f)
8903 dest[ix][iy] += scl * aux;
8918 float fillval, missval;
8919 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8921 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8925 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
8926 varsel, fillval, missval);
8930 size_t help_subdomain_start[3];
8931 size_t help_subdomain_count[3];
8933 help_subdomain_start[0] = 0;
8937 help_subdomain_count[0] = 1;
8946 NC(nc_get_vara_float
8947 (ncid, varid, help_subdomain_start, help_subdomain_count, help));
8950 size_t help_halo_bnd_start[3];
8951 size_t help_halo_bnd_count[3];
8953 help_halo_bnd_start[0] = 0;
8957 help_halo_bnd_count[0] = 1;
8962 ALLOC(help_halo,
float,
8963 help_halo_bnd_count[1] * help_halo_bnd_count[2]);
8964 NC(nc_get_vara_float
8965 (ncid, varid, help_halo_bnd_start, help_halo_bnd_count, help_halo));
8970#pragma omp parallel for default(shared) num_threads(12)
8971 for (
int ix = 0; ix < (int) help_subdomain_count[2]; ix++)
8972 for (
int iy = 0; iy < (int) help_subdomain_count[1]; iy++) {
8976 help[
ARRAY_2D(iy, ix, (
int) help_subdomain_count[2])];
8977 if ((fillval == 0 || aux != fillval)
8978 && (missval == 0 || aux != missval)
8979 && fabsf(aux) < 1e14f) {
8986#pragma omp parallel for default(shared) num_threads(12)
8987 for (
int ix = 0; ix < (int) help_halo_bnd_count[2]; ix++)
8988 for (
int iy = 0; iy < (int) help_halo_bnd_count[1]; iy++) {
8992 help_halo[
ARRAY_2D(iy, ix, (
int) help_halo_bnd_count[2])];
8993 if ((fillval == 0 || aux != fillval)
8994 && (missval == 0 || aux != missval)
8995 && fabsf(aux) < 1e14f)
9003 ERRMSG(
"Domain decomposition with data convection incompatible!");
9019 const char *varname,
9020 const char *varname2,
9021 const char *varname3,
9022 const char *varname4,
9033 float offset, scalfac;
9038 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
9039 sprintf(varsel,
"%s", varname);
9040 else if (varname2 != NULL
9041 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
9042 sprintf(varsel,
"%s", varname2);
9043 else if (varname3 != NULL
9044 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
9045 sprintf(varsel,
"%s", varname3);
9046 else if (varname4 != NULL
9047 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
9048 sprintf(varsel,
"%s", varname4);
9053 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
9054 && nc_get_att_float(ncid, varid,
"scale_factor",
9055 &scalfac) == NC_NOERR) {
9063 short fillval, missval;
9064 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9066 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9070 LOG(2,
"Read 3-D variable: %s "
9071 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
9072 varsel, fillval, missval, scalfac, offset);
9075 NC(nc_get_var_short(ncid, varid, help));
9079 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
9083#pragma omp parallel for default(shared)
9084 for (
int ix = 0; ix < met->
nx; ix++)
9085 for (
int iy = 0; iy < met->
ny; iy++)
9086 for (
int ip = 0; ip < met->
np; ip++) {
9087 const short aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
9088 if ((fillval == 0 || aux != fillval)
9089 && (missval == 0 || aux != missval)
9090 && fabsf(aux * scalfac + offset) < 1e14f)
9091 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
9093 dest[ix][iy][ip] = NAN;
9102 else if (!ctl->
dd) {
9110 float fillval, missval;
9111 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9113 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9117 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
9118 varsel, fillval, missval);
9121 NC(nc_get_var_float(ncid, varid, help));
9128#pragma omp parallel for default(shared)
9129 for (
int ix = 0; ix < met->
nx; ix++)
9130 for (
int iy = 0; iy < met->
ny; iy++)
9131 for (
int ip = 0; ip < met->
np; ip++) {
9132 const float aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
9133 if ((fillval == 0 || aux != fillval)
9134 && (missval == 0 || aux != missval)
9135 && fabsf(aux) < 1e14f)
9136 dest[ix][iy][ip] = scl * aux;
9138 dest[ix][iy][ip] = NAN;
9146#pragma omp parallel for default(shared)
9147 for (
int ip = 0; ip < met->
np; ip++)
9148 for (
int iy = 0; iy < met->
ny; iy++)
9149 for (
int ix = 0; ix < met->
nx; ix++) {
9150 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9151 if ((fillval == 0 || aux != fillval)
9152 && (missval == 0 || aux != missval)
9153 && fabsf(aux) < 1e14f)
9154 dest[ix][iy][ip] = scl * aux;
9156 dest[ix][iy][ip] = NAN;
9169 float fillval, missval;
9170 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9172 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9176 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
9177 varsel, fillval, missval);
9192 NC(nc_get_vara_float
9197 ALLOC(help_halo,
float,
9204 NC(nc_get_vara_float(ncid,
9213#pragma omp parallel for default(shared) num_threads(12)
9216 for (
int ip = 0; ip < met->
np; ip++) {
9220 if ((fillval == 0 || aux != fillval)
9221 && (missval == 0 || aux != missval)
9222 && fabsf(aux) < 1e14f)
9228#pragma omp parallel for default(shared) num_threads(12)
9231 for (
int ip = 0; ip < met->
np; ip++) {
9235 if ((fillval == 0 || aux != fillval)
9236 && (missval == 0 || aux != missval)
9237 && fabsf(aux) < 1e14f)
9246#pragma omp parallel for default(shared) num_threads(12)
9247 for (
int ip = 0; ip < met->
np; ip++)
9250 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9251 if ((fillval == 0 || aux != fillval)
9252 && (missval == 0 || aux != missval)
9253 && fabsf(aux) < 1e14f)
9259#pragma omp parallel for default(shared) num_threads(12)
9260 for (
int ip = 0; ip < met->
np; ip++)
9263 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9264 if ((fillval == 0 || aux != fillval)
9265 && (missval == 0 || aux != missval)
9266 && fabsf(aux) < 1e14f)
9286 const char *filename,
9291 size_t filename_len = strlen(filename) + 1;
9292 char sf_filename[filename_len];
9293 char ml_filename[filename_len];
9294 strcpy(sf_filename, filename);
9295 strcpy(ml_filename, filename);
9300 FILE *ml_file = fopen(ml_filename,
"rb");
9301 FILE *sf_file = fopen(sf_filename,
"rb");
9302 if (ml_file == NULL || sf_file == NULL) {
9303 if (ml_file != NULL) {
9305 WARN(
"Cannot open file: %s", sf_filename);
9307 if (sf_file != NULL) {
9309 WARN(
"Cannot open file: %s", ml_filename);
9315 int ml_num_messages = 0, err = 0;
9316 ECC(codes_count_in_file(0, ml_file, &ml_num_messages));
9319 (size_t) ml_num_messages);
9320 for (
int i = 0; i < ml_num_messages; i++) {
9322 if ((h = codes_grib_handle_new_from_file(0, ml_file, &err)) != NULL)
9327 int sf_num_messages = 0;
9328 ECC(codes_count_in_file(0, sf_file, &sf_num_messages));
9331 (size_t) sf_num_messages);
9332 for (
int i = 0; i < sf_num_messages; i++) {
9334 if ((h = codes_grib_handle_new_from_file(0, sf_file, &err)) != NULL)
9347 for (
int i = 0; i < sf_num_messages; i++)
9348 codes_handle_delete(sf_handles[i]);
9352 size_t value_count = 0;
9353 ECC(codes_get_size(ml_handles[0],
"pv", &value_count));
9354 if (value_count % 2 != 0)
9355 ERRMSG(
"Unexpected pv array length!");
9356 size_t nlevels = value_count / 2 - 1;
9358 ALLOC(values,
double,
9360 ECC(codes_get_double_array(ml_handles[0],
"pv", values, &value_count));
9361 double *a_vals = values;
9362 double *b_vals = values + nlevels;
9363 if (met->
npl > (
int) nlevels)
9364 ERRMSG(
"met->npl exceeds number of pressure levels in GRIB!");
9365 for (
int nx = 0; nx < met->
nx; nx++)
9366 for (
int ny = 0; ny < met->
ny; ny++)
9367 for (
int level = 0; level <= met->
npl; level++) {
9368 const float p1 = (float) (a_vals[level] * 0.01f +
9369 met->
ps[nx][ny] * b_vals[level]);
9370 const float p2 = (float) (a_vals[level + 1] * 0.01f +
9371 met->
ps[nx][ny] * b_vals[level + 1]);
9372 met->
pl[nx][ny][level] = 0.5f * (p1 + p2);
9378 for (
int i = 0; i < ml_num_messages; i++)
9379 codes_handle_delete(ml_handles[i]);
9397 LOG(2,
"Read meteo grid information...");
9400 char datestr[
LEN], timestr[
LEN];
9401 size_t s_date =
sizeof(datestr);
9402 ECC(codes_get_string(handles[0],
"dataDate", datestr, &s_date));
9403 size_t s_time =
sizeof(timestr);
9404 ECC(codes_get_string(handles[0],
"dataTime", timestr, &s_time));
9405 int year, month, day, hour;
9406 if (sscanf(datestr,
"%4d%2d%2d", &year, &month, &day) != 3)
9407 ERRMSG(
"Failed to parse dataDate: %s", datestr);
9408 if (sscanf(timestr,
"%2d", &hour) != 1)
9409 ERRMSG(
"Failed to parse dataTime: %s", timestr);
9411 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)", met->
time, year, month,
9415 long count_lat = 0, count_lon = 0;
9416 ECC(codes_get_long(handles[0],
"Nj", &count_lat));
9417 ECC(codes_get_long(handles[0],
"Ni", &count_lon));
9418 met->
ny = (int) count_lat;
9419 met->
nx = (int) count_lon;
9422 LOG(2,
"Number of longitudes: %d", met->
nx);
9423 if (met->
nx < 2 || met->
nx >
EX)
9424 ERRMSG(
"Number of longitudes out of range!");
9425 LOG(2,
"Number of latitudes: %d", met->
ny);
9426 if (met->
ny < 2 || met->
ny >
EY)
9427 ERRMSG(
"Number of latitudes out of range!");
9429 double first_lon, last_lon, first_lat, last_lat, inc_lon, inc_lat;
9430 ECC(codes_get_double
9431 (handles[0],
"longitudeOfFirstGridPointInDegrees", &first_lon));
9432 ECC(codes_get_double
9433 (handles[0],
"latitudeOfFirstGridPointInDegrees", &first_lat));
9434 ECC(codes_get_double
9435 (handles[0],
"longitudeOfLastGridPointInDegrees", &last_lon));
9436 ECC(codes_get_double
9437 (handles[0],
"latitudeOfLastGridPointInDegrees", &last_lat));
9438 ECC(codes_get_double(handles[0],
"iDirectionIncrementInDegrees", &inc_lon));
9439 ECC(codes_get_double(handles[0],
"jDirectionIncrementInDegrees", &inc_lat));
9441 long jscanpos, iscanneg;
9442 ECC(codes_get_long(handles[0],
"iScansNegatively", &iscanneg));
9443 ECC(codes_get_long(handles[0],
"jScansPositively", &jscanpos));
9448 for (
double i = first_lon; i <= last_lon + 1e-6; i += inc_lon) {
9449 met->
lon[counter] = i;
9452 for (
double i = first_lon; i > last_lon - 1e-6; i -= inc_lon) {
9453 met->
lon[counter] = i;
9459 for (
double i = first_lat; i > last_lat - 1e-6; i -= inc_lat) {
9460 met->
lat[counter] = i;
9463 for (
double i = first_lat; i <= last_lat + 1e-6; i += inc_lat) {
9464 met->
lat[counter] = i;
9469 LOG(2,
"Longitudes: %g, %g ... %g deg",
9471 LOG(2,
"Latitudes: %g, %g ... %g deg",
9476 for (
int i = 0; i < count_handles; i++) {
9478 ECC(codes_get_long(handles[i],
"level", &level));
9479 if (level > max_level)
9480 max_level = (int) level;
9482 met->
npl = max_level;
9485 LOG(2,
"Number of levels: %d", met->
npl);
9487 ERRMSG(
"Number of levels out of range!");
9496 const int num_messages,
9502 LOG(2,
"Read level data...");
9505 int t_flag = 0, u_flag = 0, v_flag = 0, w_flag = 0, o3_flag = 0, h2o_flag =
9506 0, lwc_flag = 0, rwc_flag = 0, iwc_flag = 0, swc_flag = 0, cc_flag = 0;
9509 for (
int i = 0; i < num_messages; i++) {
9511 size_t max_size =
LEN;
9512 char short_name[max_size];
9518 ECC(codes_get_long(handles[i],
"level", ¤t_level));
9522 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
9523 ECC(codes_get_size(handles[i],
"values", &value_count));
9524 ALLOC(values,
double,
9526 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
9534 ECC_READ_3D(
"w", current_level, met->
w, 0.01f, w_flag);
9552 if (t_flag != met->
npl)
9553 ERRMSG(
"Cannot read temperature!");
9554 if (u_flag != met->
npl)
9555 ERRMSG(
"Cannot read zonal wind!");
9556 if (v_flag != met->
npl)
9557 ERRMSG(
"Cannot read meridional wind!");
9558 if (w_flag != met->
npl)
9559 WARN(
"Cannot read vertical velocity!");
9560 if (h2o_flag != met->
npl)
9561 WARN(
"Cannot read specific humidity!");
9562 if (o3_flag != met->
npl)
9563 WARN(
"Cannot read ozone data!");
9564 if (lwc_flag != met->
npl)
9565 WARN(
"Cannot read cloud liquid water content!");
9566 if (rwc_flag != met->
npl)
9567 WARN(
"Cannot read cloud rain water content!");
9568 if (iwc_flag != met->
npl)
9569 WARN(
"Cannot read cloud ice water content!");
9570 if (swc_flag != met->
npl)
9571 WARN(
"Cannot read cloud snow water content!");
9572 if (cc_flag != met->
npl)
9573 WARN(
"Cannot read cloud cover!");
9576 for (
int ix = 0; ix < met->
nx; ix++)
9577 for (
int iy = 0; iy < met->
ny; iy++)
9578 for (
int ip = 1; ip < met->
np; ip++)
9579 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
9580 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
9581 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
9582 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip])) {
9583 LOG(1,
"%f %f %f %f", met->
pl[ix][iy][0], met->
pl[ix][iy][1],
9584 met->
pl[ix][iy][ip - 1], met->
pl[ix][iy][ip]);
9585 ERRMSG(
"Pressure profiles are not monotonic!");
9606 for (
int ip = 0; ip < met->
np; ip++)
9607 met->
p[ip] = ctl->
met_p[ip];
9611 for (
int ip = 1; ip < met->
np; ip++)
9612 if (met->
p[ip - 1] < met->
p[ip])
9613 ERRMSG(
"Pressure levels must be descending!");
9622 const int num_messages,
9628 LOG(2,
"Read surface data...");
9631 int sp_flag = 0, z_flag = 0, t_flag = 0, u_flag = 0, v_flag = 0, lsm_flag =
9632 0, sst_flag = 0, cape_flag = 0, cin_flag = 0, pbl_flag = 0;
9635 for (
int i = 0; i < num_messages; i++) {
9637 size_t max_size =
LEN, value_count;
9639 char short_name[max_size];
9642 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
9643 ECC(codes_get_size(handles[i],
"values", &value_count));
9644 double *values = (
double *) malloc(value_count *
sizeof(
double));
9645 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
9683 WARN(
"Cannot read surface pressure data!");
9685 WARN(
"Cannot read surface geopotential height!");
9687 WARN(
"Cannot read surface temperature!");
9689 WARN(
"Cannot read surface zonal wind!");
9691 WARN(
"Cannot read surface meridional wind!");
9693 WARN(
"Cannot read land-sea mask!");
9695 WARN(
"Cannot read sea surface temperature!");
9698 WARN(
"Cannot read CAPE!");
9700 WARN(
"Cannot read convective inhibition!");
9702 if (ctl->
met_pbl == 0 && pbl_flag == 0)
9703 WARN(
"Cannot read planetary boundary layer!");
9713 const char *varname) {
9715 double aux[
EP], p[
EP];
9719 LOG(2,
"Interpolate meteo data to pressure levels: %s", varname);
9722#pragma omp parallel for default(shared) private(aux,p) collapse(2)
9723 for (
int ix = 0; ix < met->
nx; ix++)
9724 for (
int iy = 0; iy < met->
ny; iy++) {
9727 for (
int ip = 0; ip < met->
np; ip++)
9728 p[ip] = met->
pl[ix][iy][ip];
9731 for (
int ip = 0; ip < ctl->
met_np; ip++) {
9732 double pt = ctl->
met_p[ip];
9733 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
9735 else if ((pt > p[met->
np - 1] && p[1] > p[0])
9736 || (pt < p[met->
np - 1] && p[1] < p[0]))
9737 pt = p[met->
np - 1];
9739 aux[ip] =
LIN(p[ip2], var[ix][iy][ip2],
9740 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
9744 for (
int ip = 0; ip < ctl->
met_np; ip++)
9745 var[ix][iy][ip] = (
float) aux[ip];
9761 LOG(2,
"Make zeta profiles monotone...");
9764#pragma omp parallel for default(shared) collapse(2)
9765 for (
int i = 0; i < met->
nx; i++)
9766 for (
int j = 0; j < met->
ny; j++) {
9769 while (k < met->npl) {
9770 if ((met->
zetal[i][j][k - 1] >= met->
zetal[i][j][k])) {
9776 while ((met->
zetal[i][j][k - 1] >=
9777 met->
zetal[i][j][k + l]) & (k + l < met->npl));
9782 (float) (met->
zetal[i][j][k + l] - met->
zetal[i][j][k - 1])
9785 for (
int m = k; m < k + l; m++) {
9786 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
9787 met->
zetal[i][j][m] = s * d + met->
zetal[i][j][k - 1];
9799#pragma omp parallel for default(shared) collapse(2)
9800 for (
int i = 0; i < met->
nx; i++)
9801 for (
int j = 0; j < met->
ny; j++) {
9804 while (k < met->npl) {
9805 if ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k])) {
9812 while ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k + l]) & (k + l <
9817 float s = (float) (met->
pl[i][j][k + l] - met->
pl[i][j][k - 1])
9820 for (
int m = k; m < k + l; m++) {
9821 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
9822 met->
pl[i][j][m] = s * d + met->
pl[i][j][k - 1];
9837 const char *filename,
9848 (filename, NC_NOWRITE | NC_SHARE, MPI_COMM_WORLD, MPI_INFO_NULL,
9852 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
9853 WARN(
"Cannot open file!");
9886 MPI_Comm_rank(MPI_COMM_WORLD, &dd->
rank);
9887 MPI_Comm_size(MPI_COMM_WORLD, &dd->
size);
9895 LOG(2,
"Number of longitudes: %d", help_nx_glob);
9899 LOG(2,
"Number of latitudes: %d", help_ny_glob);
9902 double *help_lon_glob;
9903 double *help_lat_glob;
9904 ALLOC(help_lon_glob,
double,
9906 ALLOC(help_lat_glob,
double,
9911 LOG(2,
"Longitudes: %g, %g ... %g deg",
9912 help_lon_glob[0], help_lon_glob[1], help_lon_glob[help_nx_glob - 1]);
9914 LOG(2,
"Latitudes: %g, %g ... %g deg",
9915 help_lat_glob[0], help_lat_glob[1], help_lat_glob[help_ny_glob - 1]);
9939 met->
nx = met->
nx + gap;
9940 WARN(
"Extended subdomains at the right to fit to full domain.");
9946 met->
ny = met->
ny + gap;
9947 WARN(
"Extended subdomains at the bottom to fit to full domain.");
9958 if (!left && !right) {
9975 if (!top && !bottom) {
9993 double lon_shift = 0;
9994 if (left || right) {
10012 lon_shift = (left ? -360 : 360);
10028 double lon_range = 360;
10029 double lat_range = help_lat_glob[help_ny_glob - 1] - help_lat_glob[0];
10056 if (lat_range < 0) {
10063 (
"lat_range > 0, but is expected to be negative, i.e. latitudes should range from 90 to -90")
10070 LOG(2,
"Total longitude range: %g deg", lon_range);
10071 LOG(2,
"Total latitude range: %g deg", lat_range);
10073 LOG(2,
"Define subdomain properties.");
10074 LOG(2,
"MPI information: Rank %d, Size %d", dd->
rank, dd->
size);
10075 LOG(2,
"Edge position: l=%d,r=%d,t=%d, b=%d", (
int) left, (
int) right,
10076 (
int) top, (
int) bottom);
10077 LOG(2,
"Sizes for limits: EX %d EY %d EP %d",
EX,
EY,
EP);
10078 LOG(2,
"Total size for subdomain meteo data: nx %d ny %d np %d", met->
nx,
10080 LOG(2,
"Hyperslab sizes for boundary halos: nx %d ny %d np %d",
10083 LOG(2,
"Hyperslab sizes for subdomain and inner halos: nx %d ny %d np %d",
10092 LOG(2,
" %d Subdomain longitudes: %g, %g ... %g deg (edges: %g to %g)",
10095 LOG(2,
" %d Subdomain latitudes: %g, %g ... %g deg (edges: %g to %g)",
10099 free(help_lon_glob);
10100 free(help_lat_glob);
10111 LOG(2,
"Calculate planetary boundary layer...");
10117#pragma omp parallel for default(shared) collapse(2)
10118 for (
int ix = 0; ix < met->
nx; ix++)
10119 for (
int iy = 0; iy < met->
ny; iy++) {
10122 const float z = met->
zs[ix][iy] + met->
pbl[ix][iy];
10125 (float) (
LIN(met->
z[ix][iy][ip], met->
p[ip],
10126 met->
z[ix][iy][ip + 1], met->
p[ip + 1], z));
10131 else if (ctl->
met_pbl == 2) {
10135 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
10138#pragma omp parallel for default(shared) collapse(2)
10139 for (
int ix = 0; ix < met->
nx; ix++)
10140 for (
int iy = 0; iy < met->
ny; iy++) {
10143 const double pbl_bot = met->
ps[ix][iy] * exp(-dz /
H0);
10147 for (ip = 1; ip < met->
np; ip++)
10148 if (met->
p[ip] < pbl_bot)
10152 const double h2os =
LIN(met->
p[ip - 1], met->
h2o[ix][iy][ip - 1],
10153 met->
p[ip], met->
h2o[ix][iy][ip], pbl_bot);
10154 const double tvs =
THETAVIRT(pbl_bot, met->
ts[ix][iy], h2os);
10157 double rib_old = 0;
10160 for (; ip < met->
np; ip++) {
10163 double vh2 =
SQR(met->
u[ix][iy][ip] - met->
us[ix][iy])
10164 +
SQR(met->
v[ix][iy][ip] - met->
vs[ix][iy]);
10165 vh2 =
MAX(vh2,
SQR(umin));
10169 G0 * 1e3 * (met->
z[ix][iy][ip] - met->
zs[ix][iy]) / tvs
10171 met->
h2o[ix][iy][ip]) - tvs) / vh2;
10174 if (rib >= rib_crit) {
10175 met->
pbl[ix][iy] = (float) (
LIN(rib_old, met->
p[ip - 1],
10176 rib, met->
p[ip], rib_crit));
10177 if (met->
pbl[ix][iy] > pbl_bot)
10178 met->
pbl[ix][iy] = (float) pbl_bot;
10193 const double dtheta = 2.0, zmin = 0.1;
10196#pragma omp parallel for default(shared) collapse(2)
10197 for (
int ix = 0; ix < met->
nx; ix++)
10198 for (
int iy = 0; iy < met->
ny; iy++) {
10201 const double theta0 =
THETA(met->
ps[ix][iy], met->
ts[ix][iy]);
10205 for (ip = met->
np - 2; ip > 0; ip--)
10206 if (met->
p[ip] >= 300.)
10207 if (met->
p[ip] > met->
ps[ix][iy]
10208 ||
THETA(met->
p[ip], met->
t[ix][iy][ip]) <= theta0 + dtheta)
10213 = (float) (
LIN(
THETA(met->
p[ip + 1], met->
t[ix][iy][ip + 1]),
10215 THETA(met->
p[ip], met->
t[ix][iy][ip]),
10216 met->
p[ip], theta0 + dtheta));
10219 double pbl_min = met->
ps[ix][iy] * exp(-zmin /
H0);
10220 if (met->
pbl[ix][iy] > pbl_min || met->
p[ip] > met->
ps[ix][iy])
10221 met->
pbl[ix][iy] = (float) pbl_min;
10226#pragma omp parallel for default(shared) collapse(2)
10227 for (
int ix = 0; ix < met->
nx; ix++)
10228 for (
int iy = 0; iy < met->
ny; iy++) {
10232 met->
pbl[ix][iy] =
MIN(met->
pbl[ix][iy], (
float) pbl_min);
10236 met->
pbl[ix][iy] =
MAX(met->
pbl[ix][iy], (
float) pbl_max);
10247 LOG(2,
"Apply periodic boundary conditions...");
10250 if (!(fabs(met->
lon[met->
nx - 1] - met->
lon[0]
10251 + met->
lon[1] - met->
lon[0] - 360) < 0.01))
10255 if ((++met->
nx) >=
EX)
10256 ERRMSG(
"Cannot create periodic boundary conditions!");
10259 met->
lon[met->
nx - 1] = met->
lon[met->
nx - 2] + met->
lon[1] - met->
lon[0];
10262#pragma omp parallel for default(shared)
10263 for (
int iy = 0; iy < met->
ny; iy++) {
10264 met->
ps[met->
nx - 1][iy] = met->
ps[0][iy];
10265 met->
zs[met->
nx - 1][iy] = met->
zs[0][iy];
10266 met->
ts[met->
nx - 1][iy] = met->
ts[0][iy];
10267 met->
us[met->
nx - 1][iy] = met->
us[0][iy];
10268 met->
vs[met->
nx - 1][iy] = met->
vs[0][iy];
10269 met->
ess[met->
nx - 1][iy] = met->
ess[0][iy];
10270 met->
nss[met->
nx - 1][iy] = met->
nss[0][iy];
10271 met->
shf[met->
nx - 1][iy] = met->
shf[0][iy];
10272 met->
lsm[met->
nx - 1][iy] = met->
lsm[0][iy];
10273 met->
sst[met->
nx - 1][iy] = met->
sst[0][iy];
10274 met->
pbl[met->
nx - 1][iy] = met->
pbl[0][iy];
10275 met->
cape[met->
nx - 1][iy] = met->
cape[0][iy];
10276 met->
cin[met->
nx - 1][iy] = met->
cin[0][iy];
10277 for (
int ip = 0; ip < met->
np; ip++) {
10278 met->
t[met->
nx - 1][iy][ip] = met->
t[0][iy][ip];
10279 met->
u[met->
nx - 1][iy][ip] = met->
u[0][iy][ip];
10280 met->
v[met->
nx - 1][iy][ip] = met->
v[0][iy][ip];
10281 met->
w[met->
nx - 1][iy][ip] = met->
w[0][iy][ip];
10282 met->
h2o[met->
nx - 1][iy][ip] = met->
h2o[0][iy][ip];
10283 met->
o3[met->
nx - 1][iy][ip] = met->
o3[0][iy][ip];
10284 met->
lwc[met->
nx - 1][iy][ip] = met->
lwc[0][iy][ip];
10285 met->
rwc[met->
nx - 1][iy][ip] = met->
rwc[0][iy][ip];
10286 met->
iwc[met->
nx - 1][iy][ip] = met->
iwc[0][iy][ip];
10287 met->
swc[met->
nx - 1][iy][ip] = met->
swc[0][iy][ip];
10288 met->
cc[met->
nx - 1][iy][ip] = met->
cc[0][iy][ip];
10290 for (
int ip = 0; ip < met->
npl; ip++) {
10291 met->
ul[met->
nx - 1][iy][ip] = met->
ul[0][iy][ip];
10292 met->
vl[met->
nx - 1][iy][ip] = met->
vl[0][iy][ip];
10293 met->
wl[met->
nx - 1][iy][ip] = met->
wl[0][iy][ip];
10294 met->
pl[met->
nx - 1][iy][ip] = met->
pl[0][iy][ip];
10295 met->
zetal[met->
nx - 1][iy][ip] = met->
zetal[0][iy][ip];
10308 LOG(2,
"Apply fix for polar winds...");
10311 if (fabs(met->
lat[0]) < 89.999 || fabs(met->
lat[met->
ny - 1]) < 89.999)
10315 for (
int ihem = 0; ihem < 2; ihem++) {
10318 int i89 = 1, i90 = 0, sign = 1;
10323 if (met->
lat[i90] < 0)
10327 double clon[
EX], slon[
EX];
10328#pragma omp parallel for default(shared)
10329 for (
int ix = 0; ix < met->
nx; ix++) {
10330 clon[ix] = cos(sign *
DEG2RAD(met->
lon[ix]));
10331 slon[ix] = sin(sign *
DEG2RAD(met->
lon[ix]));
10335#pragma omp parallel for default(shared)
10336 for (
int ip = 0; ip < met->
np; ip++) {
10339 double vel89x = 0, vel89y = 0;
10340 for (
int ix = 0; ix < met->
nx; ix++) {
10342 (met->
u[ix][i89][ip] * clon[ix] -
10343 met->
v[ix][i89][ip] * slon[ix]) / met->
nx;
10345 (met->
u[ix][i89][ip] * slon[ix] +
10346 met->
v[ix][i89][ip] * clon[ix]) / met->
nx;
10350 for (
int ix = 0; ix < met->
nx; ix++) {
10351 met->
u[ix][i90][ip]
10352 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
10353 met->
v[ix][i90][ip]
10354 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
10369 LOG(2,
"Calculate potential vorticity...");
10372#pragma omp parallel for default(shared)
10373 for (
int ip = 0; ip < met->
np; ip++)
10374 pows[ip] = pow(1000. / met->
p[ip], 0.286);
10377#pragma omp parallel for default(shared)
10378 for (
int ix = 0; ix < met->
nx; ix++) {
10381 const int ix0 =
MAX(ix - 1, 0);
10382 const int ix1 =
MIN(ix + 1, met->
nx - 1);
10385 for (
int iy = 0; iy < met->
ny; iy++) {
10388 const int iy0 =
MAX(iy - 1, 0);
10389 const int iy1 =
MIN(iy + 1, met->
ny - 1);
10392 const double latr = 0.5 * (met->
lat[iy1] + met->
lat[iy0]);
10393 const double dx = 1000. *
DEG2DX(met->
lon[ix1] - met->
lon[ix0], latr);
10394 const double dy = 1000. *
DEG2DY(met->
lat[iy1] - met->
lat[iy0]);
10395 const double c0 = cos(
DEG2RAD(met->
lat[iy0]));
10396 const double c1 = cos(
DEG2RAD(met->
lat[iy1]));
10397 const double cr = cos(
DEG2RAD(latr));
10398 const double vort = 2 * 7.2921e-5 * sin(
DEG2RAD(latr));
10401 for (
int ip = 0; ip < met->
np; ip++) {
10405 = (met->
t[ix1][iy][ip] - met->
t[ix0][iy][ip]) * pows[ip] / dx;
10406 const double dvdx = (met->
v[ix1][iy][ip] - met->
v[ix0][iy][ip]) / dx;
10410 = (met->
t[ix][iy1][ip] - met->
t[ix][iy0][ip]) * pows[ip] / dy;
10412 = (met->
u[ix][iy1][ip] * c1 - met->
u[ix][iy0][ip] * c0) / dy;
10415 const int ip0 =
MAX(ip - 1, 0);
10416 const int ip1 =
MIN(ip + 1, met->
np - 1);
10419 double dtdp, dudp, dvdp;
10420 const double dp0 = 100. * (met->
p[ip] - met->
p[ip0]);
10421 const double dp1 = 100. * (met->
p[ip1] - met->
p[ip]);
10422 if (ip != ip0 && ip != ip1) {
10423 double denom = dp0 * dp1 * (dp0 + dp1);
10424 dtdp = (dp0 * dp0 * met->
t[ix][iy][ip1] * pows[ip1]
10425 - dp1 * dp1 * met->
t[ix][iy][ip0] * pows[ip0]
10426 + (dp1 * dp1 - dp0 * dp0) * met->
t[ix][iy][ip] * pows[ip])
10428 dudp = (dp0 * dp0 * met->
u[ix][iy][ip1]
10429 - dp1 * dp1 * met->
u[ix][iy][ip0]
10430 + (dp1 * dp1 - dp0 * dp0) * met->
u[ix][iy][ip])
10432 dvdp = (dp0 * dp0 * met->
v[ix][iy][ip1]
10433 - dp1 * dp1 * met->
v[ix][iy][ip0]
10434 + (dp1 * dp1 - dp0 * dp0) * met->
v[ix][iy][ip])
10437 const double denom = dp0 + dp1;
10439 (met->
t[ix][iy][ip1] * pows[ip1] -
10440 met->
t[ix][iy][ip0] * pows[ip0]) / denom;
10441 dudp = (met->
u[ix][iy][ip1] - met->
u[ix][iy][ip0]) / denom;
10442 dvdp = (met->
v[ix][iy][ip1] - met->
v[ix][iy][ip0]) / denom;
10446 met->
pv[ix][iy][ip] = (float)
10448 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
10454#pragma omp parallel for default(shared)
10455 for (
int ix = 0; ix < met->
nx; ix++)
10456 for (
int ip = 0; ip < met->
np; ip++) {
10458 = met->
pv[ix][1][ip]
10459 = met->
pv[ix][2][ip];
10460 met->
pv[ix][met->
ny - 1][ip]
10461 = met->
pv[ix][met->
ny - 2][ip]
10462 = met->
pv[ix][met->
ny - 3][ip];
10473 LOG(2,
"Calculate total column ozone...");
10476#pragma omp parallel for default(shared) collapse(2)
10477 for (
int ix = 0; ix < met->
nx; ix++)
10478 for (
int iy = 0; iy < met->
ny; iy++) {
10482 for (
int ip = 1; ip < met->
np; ip++)
10483 if (met->
p[ip - 1] <= met->
ps[ix][iy]) {
10485 0.5 * (met->
o3[ix][iy][ip - 1] + met->
o3[ix][iy][ip]);
10486 const double dp = met->
p[ip - 1] - met->
p[ip];
10487 cd += vmr *
MO3 /
MA * dp * 1e2 /
G0;
10491 met->
o3c[ix][iy] = (float) (cd / 2.1415e-5);
10510 LOG(2,
"Downsampling of meteo data...");
10516 help->
nx = met->
nx;
10517 help->
ny = met->
ny;
10518 help->
np = met->
np;
10519 memcpy(help->
lon, met->
lon,
sizeof(met->
lon));
10520 memcpy(help->
lat, met->
lat,
sizeof(met->
lat));
10521 memcpy(help->
p, met->
p,
sizeof(met->
p));
10524 for (
int ix = 0; ix < met->
nx; ix += ctl->
met_dx) {
10525 for (
int iy = 0; iy < met->
ny; iy += ctl->
met_dy) {
10526 for (
int ip = 0; ip < met->
np; ip += ctl->
met_dp) {
10527 help->
ps[ix][iy] = 0;
10528 help->
zs[ix][iy] = 0;
10529 help->
ts[ix][iy] = 0;
10530 help->
us[ix][iy] = 0;
10531 help->
vs[ix][iy] = 0;
10532 help->
ess[ix][iy] = 0;
10533 help->
nss[ix][iy] = 0;
10534 help->
shf[ix][iy] = 0;
10535 help->
lsm[ix][iy] = 0;
10536 help->
sst[ix][iy] = 0;
10537 help->
pbl[ix][iy] = 0;
10538 help->
cape[ix][iy] = 0;
10539 help->
cin[ix][iy] = 0;
10540 help->
t[ix][iy][ip] = 0;
10541 help->
u[ix][iy][ip] = 0;
10542 help->
v[ix][iy][ip] = 0;
10543 help->
w[ix][iy][ip] = 0;
10544 help->
h2o[ix][iy][ip] = 0;
10545 help->
o3[ix][iy][ip] = 0;
10546 help->
lwc[ix][iy][ip] = 0;
10547 help->
rwc[ix][iy][ip] = 0;
10548 help->
iwc[ix][iy][ip] = 0;
10549 help->
swc[ix][iy][ip] = 0;
10550 help->
cc[ix][iy][ip] = 0;
10552 for (
int ix2 = ix - ctl->
met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
10557 else if (ix3 >= met->
nx)
10560 for (
int iy2 =
MAX(iy - ctl->
met_sy + 1, 0);
10561 iy2 <=
MIN(iy + ctl->
met_sy - 1, met->
ny - 1); iy2++)
10562 for (
int ip2 =
MAX(ip - ctl->
met_sp + 1, 0);
10563 ip2 <=
MIN(ip + ctl->
met_sp - 1, met->
np - 1); ip2++) {
10565 (1.0f - (float) abs(ix - ix2) / (float) ctl->
met_sx)
10566 * (1.0f - (float) abs(iy - iy2) / (float) ctl->
met_sy)
10567 * (1.0f - (float) abs(ip - ip2) / (float) ctl->
met_sp);
10568 help->
ps[ix][iy] += w * met->
ps[ix3][iy2];
10569 help->
zs[ix][iy] += w * met->
zs[ix3][iy2];
10570 help->
ts[ix][iy] += w * met->
ts[ix3][iy2];
10571 help->
us[ix][iy] += w * met->
us[ix3][iy2];
10572 help->
vs[ix][iy] += w * met->
vs[ix3][iy2];
10573 help->
ess[ix][iy] += w * met->
ess[ix3][iy2];
10574 help->
nss[ix][iy] += w * met->
nss[ix3][iy2];
10575 help->
shf[ix][iy] += w * met->
shf[ix3][iy2];
10576 help->
lsm[ix][iy] += w * met->
lsm[ix3][iy2];
10577 help->
sst[ix][iy] += w * met->
sst[ix3][iy2];
10578 help->
pbl[ix][iy] += w * met->
pbl[ix3][iy2];
10579 help->
cape[ix][iy] += w * met->
cape[ix3][iy2];
10580 help->
cin[ix][iy] += w * met->
cin[ix3][iy2];
10581 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip2];
10582 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip2];
10583 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip2];
10584 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip2];
10585 help->
h2o[ix][iy][ip] += w * met->
h2o[ix3][iy2][ip2];
10586 help->
o3[ix][iy][ip] += w * met->
o3[ix3][iy2][ip2];
10587 help->
lwc[ix][iy][ip] += w * met->
lwc[ix3][iy2][ip2];
10588 help->
rwc[ix][iy][ip] += w * met->
rwc[ix3][iy2][ip2];
10589 help->
iwc[ix][iy][ip] += w * met->
iwc[ix3][iy2][ip2];
10590 help->
swc[ix][iy][ip] += w * met->
swc[ix3][iy2][ip2];
10591 help->
cc[ix][iy][ip] += w * met->
cc[ix3][iy2][ip2];
10595 help->
ps[ix][iy] /= wsum;
10596 help->
zs[ix][iy] /= wsum;
10597 help->
ts[ix][iy] /= wsum;
10598 help->
us[ix][iy] /= wsum;
10599 help->
vs[ix][iy] /= wsum;
10600 help->
ess[ix][iy] /= wsum;
10601 help->
nss[ix][iy] /= wsum;
10602 help->
shf[ix][iy] /= wsum;
10603 help->
lsm[ix][iy] /= wsum;
10604 help->
sst[ix][iy] /= wsum;
10605 help->
pbl[ix][iy] /= wsum;
10606 help->
cape[ix][iy] /= wsum;
10607 help->
cin[ix][iy] /= wsum;
10608 help->
t[ix][iy][ip] /= wsum;
10609 help->
u[ix][iy][ip] /= wsum;
10610 help->
v[ix][iy][ip] /= wsum;
10611 help->
w[ix][iy][ip] /= wsum;
10612 help->
h2o[ix][iy][ip] /= wsum;
10613 help->
o3[ix][iy][ip] /= wsum;
10614 help->
lwc[ix][iy][ip] /= wsum;
10615 help->
rwc[ix][iy][ip] /= wsum;
10616 help->
iwc[ix][iy][ip] /= wsum;
10617 help->
swc[ix][iy][ip] /= wsum;
10618 help->
cc[ix][iy][ip] /= wsum;
10625 for (
int ix = 0; ix < help->
nx; ix += ctl->
met_dx) {
10626 met->
lon[met->
nx] = help->
lon[ix];
10628 for (
int iy = 0; iy < help->
ny; iy += ctl->
met_dy) {
10629 met->
lat[met->
ny] = help->
lat[iy];
10630 met->
ps[met->
nx][met->
ny] = help->
ps[ix][iy];
10631 met->
zs[met->
nx][met->
ny] = help->
zs[ix][iy];
10632 met->
ts[met->
nx][met->
ny] = help->
ts[ix][iy];
10633 met->
us[met->
nx][met->
ny] = help->
us[ix][iy];
10634 met->
vs[met->
nx][met->
ny] = help->
vs[ix][iy];
10635 met->
ess[met->
nx][met->
ny] = help->
ess[ix][iy];
10636 met->
nss[met->
nx][met->
ny] = help->
nss[ix][iy];
10637 met->
shf[met->
nx][met->
ny] = help->
shf[ix][iy];
10638 met->
lsm[met->
nx][met->
ny] = help->
lsm[ix][iy];
10639 met->
sst[met->
nx][met->
ny] = help->
sst[ix][iy];
10640 met->
pbl[met->
nx][met->
ny] = help->
pbl[ix][iy];
10642 met->
cin[met->
nx][met->
ny] = help->
cin[ix][iy];
10644 for (
int ip = 0; ip < help->
np; ip += ctl->
met_dp) {
10645 met->
p[met->
np] = help->
p[ip];
10646 met->
t[met->
nx][met->
ny][met->
np] = help->
t[ix][iy][ip];
10647 met->
u[met->
nx][met->
ny][met->
np] = help->
u[ix][iy][ip];
10648 met->
v[met->
nx][met->
ny][met->
np] = help->
v[ix][iy][ip];
10649 met->
w[met->
nx][met->
ny][met->
np] = help->
w[ix][iy][ip];
10650 met->
h2o[met->
nx][met->
ny][met->
np] = help->
h2o[ix][iy][ip];
10651 met->
o3[met->
nx][met->
ny][met->
np] = help->
o3[ix][iy][ip];
10652 met->
lwc[met->
nx][met->
ny][met->
np] = help->
lwc[ix][iy][ip];
10653 met->
rwc[met->
nx][met->
ny][met->
np] = help->
rwc[ix][iy][ip];
10654 met->
iwc[met->
nx][met->
ny][met->
np] = help->
iwc[ix][iy][ip];
10655 met->
swc[met->
nx][met->
ny][met->
np] = help->
swc[ix][iy][ip];
10656 met->
cc[met->
nx][met->
ny][met->
np] = help->
cc[ix][iy][ip];
10675 double p2[200], pv[
EP], pv2[200], t[
EP], t2[200], th[
EP],
10676 th2[200], z[
EP], z2[200];
10680 LOG(2,
"Calculate tropopause...");
10683#pragma omp parallel for default(shared)
10684 for (
int iz = 0; iz < met->
np; iz++)
10685 z[iz] =
Z(met->
p[iz]);
10686#pragma omp parallel for default(shared)
10687 for (
int iz = 0; iz <= 190; iz++) {
10688 z2[iz] = 4.5 + 0.1 * iz;
10689 p2[iz] =
P(z2[iz]);
10694#pragma omp parallel for default(shared) collapse(2)
10695 for (
int ix = 0; ix < met->
nx; ix++)
10696 for (
int iy = 0; iy < met->
ny; iy++)
10697 met->
pt[ix][iy] = NAN;
10701#pragma omp parallel for default(shared) collapse(2)
10702 for (
int ix = 0; ix < met->
nx; ix++)
10703 for (
int iy = 0; iy < met->
ny; iy++)
10711#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10712 for (
int ix = 0; ix < met->
nx; ix++)
10713 for (
int iy = 0; iy < met->
ny; iy++) {
10716 for (
int iz = 0; iz < met->
np; iz++)
10717 t[iz] = met->
t[ix][iy][iz];
10721 int iz = (int) gsl_stats_min_index(t2, 1, 171);
10722 if (iz > 0 && iz < 170)
10723 met->
pt[ix][iy] = (float) p2[iz];
10725 met->
pt[ix][iy] = NAN;
10733#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10734 for (
int ix = 0; ix < met->
nx; ix++)
10735 for (
int iy = 0; iy < met->
ny; iy++) {
10739 for (iz = 0; iz < met->
np; iz++)
10740 t[iz] = met->
t[ix][iy][iz];
10744 met->
pt[ix][iy] = NAN;
10745 for (iz = 0; iz <= 170; iz++) {
10747 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10748 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10753 if (iz > 0 && iz < 170)
10754 met->
pt[ix][iy] = (float) p2[iz];
10761 met->
pt[ix][iy] = NAN;
10762 for (; iz <= 170; iz++) {
10764 for (
int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
10765 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
10772 for (; iz <= 170; iz++) {
10774 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10775 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10780 if (iz > 0 && iz < 170)
10781 met->
pt[ix][iy] = (float) p2[iz];
10793#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
10794 for (
int ix = 0; ix < met->
nx; ix++)
10795 for (
int iy = 0; iy < met->
ny; iy++) {
10798 for (
int iz = 0; iz < met->
np; iz++)
10799 pv[iz] = met->
pv[ix][iy][iz];
10803 for (
int iz = 0; iz < met->
np; iz++)
10804 th[iz] =
THETA(met->
p[iz], met->
t[ix][iy][iz]);
10808 met->
pt[ix][iy] = NAN;
10809 for (
int iz = 0; iz <= 170; iz++)
10812 if (iz > 0 && iz < 170)
10813 met->
pt[ix][iy] = (float) p2[iz];
10820 ERRMSG(
"Cannot calculate tropopause!");
10823#pragma omp parallel for default(shared) collapse(2)
10824 for (
int ix = 0; ix < met->
nx; ix++)
10825 for (
int iy = 0; iy < met->
ny; iy++) {
10826 double h2ot, tt, zt;
10829 met->
lat[iy], &tt, ci, cw, 1);
10831 met->
lat[iy], &zt, ci, cw, 0);
10833 met->
lat[iy], &h2ot, ci, cw, 0);
10834 met->
tt[ix][iy] = (float) tt;
10835 met->
zt[ix][iy] = (float) zt;
10836 met->
h2ot[ix][iy] = (float) h2ot;
10843 const char *filename,
10853 LOG(1,
"Read observation data: %s", filename);
10857 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
10859 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
10861 ERRMSG(
"Set OBS_TYPE to 0 or 1!");
10864 for (
int i = 1; i < *nobs; i++)
10865 if (rt[i] < rt[i - 1])
10866 ERRMSG(
"Time must be ascending!");
10871 LOG(2,
"Number of observations: %d", *nobs);
10872 gsl_stats_minmax(&mini, &maxi, rt, 1, (
size_t) n);
10873 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
10874 gsl_stats_minmax(&mini, &maxi, rz, 1, (
size_t) n);
10875 LOG(2,
"Altitude range: %g ... %g km", mini, maxi);
10876 gsl_stats_minmax(&mini, &maxi, rlon, 1, (
size_t) n);
10877 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
10878 gsl_stats_minmax(&mini, &maxi, rlat, 1, (
size_t) n);
10879 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
10880 gsl_stats_minmax(&mini, &maxi, robs, 1, (
size_t) n);
10881 LOG(2,
"Observation range: %g ... %g", mini, maxi);
10887 const char *filename,
10897 if (!(in = fopen(filename,
"r")))
10898 ERRMSG(
"Cannot open file!");
10902 while (fgets(line,
LEN, in))
10903 if (sscanf(line,
"%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
10904 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
10905 if ((++(*nobs)) >=
NOBS)
10906 ERRMSG(
"Too many observations!");
10915 const char *filename,
10926 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
10927 ERRMSG(
"Cannot open file!");
10938 NC(nc_close(ncid));
10944 const char *filename,
10947 const char *varname,
10949 const char *defvalue,
10954 char fullname1[
LEN], fullname2[
LEN], rval[
LEN];
10956 int contain = 0, i;
10959 if (filename[strlen(filename) - 1] !=
'-')
10960 if (!(in = fopen(filename,
"r")))
10961 ERRMSG(
"Cannot open file!");
10965 sprintf(fullname1,
"%s[%d]", varname, arridx);
10966 sprintf(fullname2,
"%s[*]", varname);
10968 sprintf(fullname1,
"%s", varname);
10969 sprintf(fullname2,
"%s", varname);
10974 char dummy[
LEN], line[
LEN], rvarname[
LEN];
10975 while (fgets(line,
LEN, in)) {
10976 if (sscanf(line,
"%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
10977 if (strcasecmp(rvarname, fullname1) == 0 ||
10978 strcasecmp(rvarname, fullname2) == 0) {
10984 for (i = 1; i < argc - 1; i++)
10985 if (strcasecmp(argv[i], fullname1) == 0 ||
10986 strcasecmp(argv[i], fullname2) == 0) {
10987 sprintf(rval,
"%s", argv[i + 1]);
10998 if (strlen(defvalue) > 0)
10999 sprintf(rval,
"%s", defvalue);
11001 ERRMSG(
"Missing variable %s!\n", fullname1);
11005 LOG(1,
"%s = %s", fullname1, rval);
11009 sprintf(value,
"%s", rval);
11019 const double rhop) {
11022 const double rp_help = rp * 1e-6;
11025 const double rho =
RHO(p, T);
11028 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
11031 const double v = sqrt(8. *
KB * T / (M_PI * 4.8096e-26));
11034 const double lambda = 2. * eta / (rho * v);
11037 const double K = lambda / rp_help;
11040 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
11043 return 2. *
SQR(rp_help) * (rhop - rho) *
G0 / (9. * eta) * G;
11055 const int method) {
11061 gsl_interp_accel *acc = gsl_interp_accel_alloc();
11062 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (
size_t) n);
11065 gsl_spline_init(s, x, y, (
size_t) n);
11066 for (
int i = 0; i < n2; i++)
11069 else if (x2[i] >= x[n - 1])
11072 y2[i] = gsl_spline_eval(s, x2[i], acc);
11075 gsl_spline_free(s);
11076 gsl_interp_accel_free(acc);
11081 for (
int i = 0; i < n2; i++)
11084 else if (x2[i] >= x[n - 1])
11088 y2[i] =
LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
11102 float mean = 0, var = 0;
11104 for (
int i = 0; i < n; ++i) {
11106 var +=
SQR(data[i]);
11109 var = var / (float) n -
SQR(mean / (
float) n);
11111 return (var > 0 ? sqrtf(var) : 0);
11123 const double remain,
11135 t1.tm_year = year - 1900;
11136 t1.tm_mon = mon - 1;
11142 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
11150 const int output) {
11157 static int iname = -1, igroup = -1, nname, ngroup, ct_name[
NTIMER];
11160 t1 = omp_get_wtime();
11165 rt_name[iname] += dt;
11166 rt_min[iname] = (ct_name[iname] <= 0 ? dt :
MIN(rt_min[iname], dt));
11167 rt_max[iname] = (ct_name[iname] <= 0 ? dt :
MAX(rt_max[iname], dt));
11171 rt_group[igroup] += t1 - t0;
11175 for (
int i = 0; i < nname; i++)
11176 LOG(1,
"TIMER_%s = %.3f s (min= %g s, mean= %g s,"
11177 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
11178 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
11179 for (
int i = 0; i < ngroup; i++)
11180 LOG(1,
"TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
11181 double total = 0.0;
11182 for (
int i = 0; i < nname; i++)
11183 total += rt_name[i];
11184 LOG(1,
"TIMER_TOTAL = %.3f s", total);
11188 for (iname = 0; iname < nname; iname++)
11189 if (strcasecmp(name, names[iname]) == 0)
11191 for (igroup = 0; igroup < ngroup; igroup++)
11192 if (strcasecmp(group, groups[igroup]) == 0)
11196 if (iname >= nname) {
11197 sprintf(names[iname],
"%s", name);
11198 if ((++nname) >=
NTIMER)
11199 ERRMSG(
"Too many timers!");
11203 if (igroup >= ngroup) {
11204 sprintf(groups[igroup],
"%s", group);
11205 if ((++ngroup) >=
NTIMER)
11206 ERRMSG(
"Too many groups!");
11216 const char *filename,
11217 const int offset) {
11224 int len = (int) strlen(filename);
11225 sprintf(tstr,
"%.4s", &filename[len - offset]);
11226 int year = atoi(tstr);
11227 sprintf(tstr,
"%.2s", &filename[len - offset + 5]);
11228 int mon = atoi(tstr);
11229 sprintf(tstr,
"%.2s", &filename[len - offset + 8]);
11230 int day = atoi(tstr);
11231 sprintf(tstr,
"%.2s", &filename[len - offset + 11]);
11232 int hour = atoi(tstr);
11233 sprintf(tstr,
"%.2s", &filename[len - offset + 14]);
11234 int min = atoi(tstr);
11237 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
11238 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
11239 ERRMSG(
"Cannot read time from filename!");
11242 time2jsec(year, mon, day, hour, min, 0, 0.0, &t);
11259 const double p1 = pt * 0.866877899;
11260 const double p0 = pt / 0.866877899;
11263 if (atm->
p[ip] > p0)
11265 else if (atm->
p[ip] < p1)
11268 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
11274 const char *filename,
11282 const double t0 = t - 0.5 * ctl->
dt_mod;
11283 const double t1 = t + 0.5 * ctl->
dt_mod;
11289 if (!(out = popen(
"gnuplot",
"w")))
11290 ERRMSG(
"Cannot create pipe to gnuplot!");
11293 fprintf(out,
"set out \"%s.png\"\n", filename);
11297 int year, mon, day, hour, min, sec;
11298 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11299 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
11300 year, mon, day, hour, min);
11305 ERRMSG(
"Cannot open file!");
11307 while (fgets(line,
LEN, in))
11308 fprintf(out,
"%s", line);
11315 if (!(out = fopen(filename,
"w")))
11316 ERRMSG(
"Cannot create file!");
11321 "# $1 = time [s]\n"
11322 "# $2 = altitude [km]\n"
11323 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
11324 for (
int iq = 0; iq < ctl->
nq; iq++)
11325 fprintf(out,
"# $%i = %s [%s]\n", iq + 5, ctl->
qnt_name[iq],
11327 fprintf(out,
"\n");
11330 for (
int ip = 0; ip < atm->
np; ip += ctl->
atm_stride) {
11337 fprintf(out,
"%.2f %g %g %g", atm->
time[ip],
Z(atm->
p[ip]),
11338 atm->
lon[ip], atm->
lat[ip]);
11339 for (
int iq = 0; iq < ctl->
nq; iq++) {
11344 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
11346 fprintf(out,
"\n");
11356 const char *filename,
11358 const atm_t *atm) {
11363 if (!(out = fopen(filename,
"w")))
11364 ERRMSG(
"Cannot create file!");
11388 for (
int iq = 0; iq < ctl->
nq; iq++)
11406 const char *filename,
11408 const atm_t *atm) {
11410 int tid, pid, ncid, varid;
11411 size_t start[2], count[2];
11414 NC(nc_create(filename, NC_NETCDF4, &ncid));
11417 NC(nc_def_dim(ncid,
"time", 1, &tid));
11418 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11421 int dim_ids[2] = { tid, pid };
11422 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11423 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11424 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
11426 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
11428 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
11431 for (
int iq = 0; iq < ctl->
nq; iq++)
11441 NC(nc_enddef(ncid));
11449 for (
int iq = 0; iq < ctl->
nq; iq++)
11453 NC(nc_close(ncid));
11459 const char *dirname,
11465 static size_t out_cnt = 0;
11467 double r, r_start, r_stop;
11468 int year, mon, day, hour, min, sec;
11469 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
11470 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
11471 char filename_out[2 *
LEN] =
"traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
11473 int ncid, varid, tid, pid, cid;
11481 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11483 &min_start, &sec_start, &r_start);
11485 &min_stop, &sec_stop, &r_stop);
11487 sprintf(filename_out,
11488 "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc", dirname,
11489 year_start % 100, mon_start, day_start, hour_start,
11490 year_stop % 100, mon_stop, day_stop, hour_stop);
11491 LOG(1,
"Write traj file: %s", filename_out);
11494 start[0] = out_cnt;
11497 count[1] = (size_t) atm->
np;
11500 if (out_cnt == 0) {
11503 NC(nc_create(filename_out, NC_NETCDF4, &ncid));
11506 NC(nc_def_dim(ncid,
"time", NC_UNLIMITED, &tid));
11507 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11508 NC(nc_def_dim(ncid,
"TMDT", 7, &cid));
11513 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11514 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11515 NC_DEF_VAR(
"LAT", NC_DOUBLE, 2, dim_ids,
"Latitude",
"deg",
11517 NC_DEF_VAR(
"LON", NC_DOUBLE, 2, dim_ids,
"Longitude",
"deg",
11519 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 2, dim_ids,
"Pressure",
"hPa",
11521 NC_DEF_VAR(
"ZETA", NC_DOUBLE, 2, dim_ids,
"Zeta",
"K",
11523 for (
int iq = 0; iq < ctl->
nq; iq++)
11533 NC(nc_enddef(ncid));
11534 NC(nc_close(ncid));
11541 NC(nc_open(filename_out, NC_WRITE, &ncid));
11553 for (
int iq = 0; iq < ctl->
nq; iq++)
11557 NC(nc_close(ncid));
11560 if ((year == year_stop) && (mon == mon_stop)
11561 && (day == day_stop) && (hour == hour_stop)) {
11564 char filename_init[2 *
LEN] =
"./init_fix_YYYYMMDDHH.nc";
11565 sprintf(filename_init,
"%s/init_fix_%02d%02d%02d%02d.nc",
11566 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
11567 LOG(1,
"Write init file: %s", filename_init);
11570 NC(nc_create(filename_init, NC_NETCDF4, &ncid));
11573 NC(nc_def_dim(ncid,
"time", 1, &tid));
11574 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11579 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11580 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11581 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
11583 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
11585 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
11588 for (
int iq = 0; iq < ctl->
nq; iq++)
11598 NC(nc_enddef(ncid));
11606 for (
int iq = 0; iq < ctl->
nq; iq++)
11610 NC(nc_close(ncid));
11617 const char *filename,
11619 const atm_t *atm) {
11621 int ncid, obsid, varid;
11623 size_t start[2], count[2];
11626 NC(nc_create(filename, NC_NETCDF4, &ncid));
11629 NC(nc_def_dim(ncid,
"obs", (
size_t) atm->
np, &obsid));
11632 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &obsid,
"time",
11633 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11634 NC_DEF_VAR(
"press", NC_DOUBLE, 1, &obsid,
"pressure",
"hPa",
11636 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &obsid,
"longitude",
"degrees_east",
11638 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &obsid,
"latitude",
"degrees_north",
11640 for (
int iq = 0; iq < ctl->
nq; iq++)
11649 NC(nc_enddef(ncid));
11656 for (
int iq = 0; iq < ctl->
nq; iq++)
11660 NC(nc_close(ncid));
11666 const char *filename,
11673 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
11676 static int *obscount, nobs, nk;
11680 const int ensemble = (ctl->
nens > 0);
11686 if (ctl->
qnt_m < 0)
11687 ERRMSG(
"Need quantity mass!");
11690 ERRMSG(
"Missing ensemble IDs!");
11692 ERRMSG(
"Too many ensembles!");
11699 ALLOC(area,
double,
11705 ALLOC(rlon,
double,
11707 ALLOC(rlat,
double,
11709 ALLOC(robs,
double,
11720 LOG(1,
"Write CSI%s data: %s", ensemble ?
" ensemble" :
"", filename);
11721 if (!(out = fopen(filename,
"w")))
11722 ERRMSG(
"Cannot create file!");
11726 "# $1 = time [s]\n"
11727 "# $2 = ensemble ID\n"
11728 "# $3 = number of hits (cx)\n"
11729 "# $4 = number of misses (cy)\n"
11730 "# $5 = number of false alarms (cz)\n"
11731 "# $6 = number of observations (cx + cy)\n"
11732 "# $7 = number of forecasts (cx + cz)\n"
11733 "# $8 = bias (%%)\n"
11734 "# $9 = POD (%%)\n"
11735 "# $10 = FAR (%%)\n"
11736 "# $11 = CSI (%%)\n"
11737 "# $12 = hits by random chance\n"
11738 "# $13 = ETS (%%)\n"
11739 "# $14 = Pearson R\n"
11740 "# $15 = Spearman R\n"
11741 "# $16 = mean error [kg/m²]\n"
11742 "# $17 = RMSE [kg/m²]\n"
11743 "# $18 = MAE [kg/m²]\n"
11744 "# $19 = log-likelihood\n" "# $20 = number of points\n\n");
11752 for (
int iy = 0; iy < ctl->
csi_ny; iy++) {
11753 const double lat = ctl->
csi_lat0 + dlat * (iy + 0.5);
11754 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.0) * cos(
DEG2RAD(lat));
11759 const double t0 = t - 0.5 * ctl->
dt_mod;
11760 const double t1 = t + 0.5 * ctl->
dt_mod;
11764 ALLOC(modmean,
double,
11765 (ensemble ? ctl->
nens : 1) * grid_size);
11766 ALLOC(obsmean,
double,
11768 ALLOC(obscount,
int,
11770 ALLOC(obsstd,
double,
11774 for (
int i = 0; i < (ensemble ? ctl->
nens : 1); i++)
11775 ct[i] = cx[i] = cy[i] = cz[i] = n[i] = 0;
11778 for (
int i = 0; i < nobs; i++) {
11779 if (rt[i] < t0 || rt[i] >= t1 || !isfinite(robs[i]))
11783 const int ix = (int) ((rlon[i] - ctl->
csi_lon0) / dlon);
11784 const int iy = (int) ((rlat[i] - ctl->
csi_lat0) / dlat);
11785 const int iz = (int) ((rz[i] - ctl->
csi_z0) / dz);
11786 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
11792 obsmean[idx] += robs[i];
11793 obsstd[idx] +=
SQR(robs[i]);
11798 for (
int ip = 0; ip < atm->
np; ip++) {
11801 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11805 int ens_id = ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
11806 if (ens_id < 0 || ens_id >= (ensemble ? ctl->
nens : 1))
11807 ERRMSG(
"Ensemble ID out of range!");
11810 const int ix = (int) ((atm->
lon[ip] - ctl->
csi_lon0) / dlon);
11811 const int iy = (int) ((atm->
lat[ip] - ctl->
csi_lat0) / dlat);
11812 const int iz = (int) ((
Z(atm->
p[ip]) - ctl->
csi_z0) / dz);
11813 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
11823 for (
int e = 0; e < (ensemble ? ctl->
nens : 1); e++) {
11825 for (
int ix = 0; ix < ctl->
csi_nx; ix++)
11826 for (
int iy = 0; iy < ctl->
csi_ny; iy++)
11827 for (
int iz = 0; iz < ctl->
csi_nz; iz++) {
11832 if (obscount[idx]) {
11833 obsmean[idx] /= obscount[idx];
11835 sqrt(obsstd[idx] / obscount[idx] -
SQR(obsmean[idx]));
11839 const int midx = e * grid_size + idx;
11840 if (modmean[midx] > 0)
11841 modmean[midx] /= (1e6 * area[iy]);
11844 if (obscount[idx]) {
11859 x[n[e]] = modmean[midx];
11860 y[n[e]] = obsmean[idx];
11862 obsstdn[n[e]] = obsstd[idx];
11863 if ((++n[e]) >=
NCSI)
11864 ERRMSG(
"Too many points for statistics!");
11876 static double work[2 *
NCSI], work2[2 *
NCSI];
11877 const int n_obs = cx[e] + cy[e];
11878 const int n_for = cx[e] + cz[e];
11879 const double cx_rd = (ct[e] > 0) ? (1. * n_obs * n_for) / ct[e] : NAN;
11880 const double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
11881 const double pod = (n_obs > 0) ? 100. * cx[e] / n_obs : NAN;
11882 const double far = (n_for > 0) ? 100. * cz[e] / n_for : NAN;
11884 (cx[e] + cy[e] + cz[e] >
11885 0) ? 100. * cx[e] / (cx[e] + cy[e] + cz[e]) : NAN;
11887 (cx[e] + cy[e] + cz[e] - cx_rd >
11888 0) ? 100. * (cx[e] - cx_rd) / (cx[e] + cy[e] + cz[e] - cx_rd) : NAN;
11889 const double rho_p = gsl_stats_correlation(x, 1, y, 1, (
size_t) n[e]);
11890 const double rho_s =
11891 gsl_stats_spearman(x, 1, y, 1, (
size_t) n[e], work);
11892 for (
int i = 0; i < n[e]; i++) {
11893 work[i] = x[i] - y[i];
11894 work2[i] = (obsstdn[i] != 0) ? work[i] / obsstdn[i] : 0;
11896 const double mean = gsl_stats_mean(work, 1, (
size_t) n[e]);
11897 const double rmse =
11898 gsl_stats_sd_with_fixed_mean(work, 1, (
size_t) n[e], 0.0);
11899 const double absdev = gsl_stats_absdev_m(work, 1, (
size_t) n[e], 0.0);
11900 const double loglikelihood =
11901 gsl_stats_tss_m(work2, 1, (
size_t) n[e], 0.0) * -0.5;
11905 "%.2f %d %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n",
11906 t, ensemble ? e : -999, cx[e], cy[e], cz[e], n_obs, n_for, bias,
11907 pod, far, csi, cx_rd, ets, rho_p, rho_s, mean, rmse, absdev,
11908 loglikelihood, n[e]);
11911 for (
int i = 0; i < n[e]; i++)
11912 work[i] = work2[i] = x[i] = y[i] = obsstdn[i] = 0;
11913 ct[e] = cx[e] = cy[e] = cz[e] = n[e] = 0;
11941 const char *filename,
11951 static int n[
NENS];
11958 ERRMSG(
"Missing ensemble IDs!");
11961 const double t0 = t - 0.5 * ctl->
dt_mod;
11962 const double t1 = t + 0.5 * ctl->
dt_mod;
11965 for (
int i = 0; i <
NENS; i++) {
11966 for (
int iq = 0; iq < ctl->
nq; iq++)
11967 qm[iq][i] = qs[iq][i] = 0;
11968 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
11973 for (
int ip = 0; ip < atm->
np; ip++) {
11976 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11981 ERRMSG(
"Ensemble ID is out of range!");
11985 for (
int iq = 0; iq < ctl->
nq; iq++) {
11986 qm[iq][ctl->
qnt_ens] += atm->
q[iq][ip];
11997 LOG(1,
"Write ensemble data: %s", filename);
11998 if (!(out = fopen(filename,
"w")))
11999 ERRMSG(
"Cannot create file!");
12003 "# $1 = time [s]\n"
12004 "# $2 = altitude [km]\n"
12005 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
12006 for (
int iq = 0; iq < ctl->
nq; iq++)
12007 fprintf(out,
"# $%d = %s (mean) [%s]\n", 5 + iq,
12009 for (
int iq = 0; iq < ctl->
nq; iq++)
12010 fprintf(out,
"# $%d = %s (sigma) [%s]\n", 5 + ctl->
nq + iq,
12012 fprintf(out,
"# $%d = number of members\n\n", 5 + 2 * ctl->
nq);
12015 for (
int i = 0; i <
NENS; i++)
12017 cart2geo(xm[i], &dummy, &lon, &lat);
12018 fprintf(out,
"%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
12019 for (
int iq = 0; iq < ctl->
nq; iq++) {
12021 fprintf(out, ctl->
qnt_format[iq], qm[iq][i] / n[i]);
12023 for (
int iq = 0; iq < ctl->
nq; iq++) {
12025 double var = qs[iq][i] / n[i] -
SQR(qm[iq][i] / n[i]);
12026 fprintf(out, ctl->
qnt_format[iq], (var > 0 ? sqrt(var) : 0));
12028 fprintf(out,
" %d\n", n[i]);
12038 const char *filename,
12045 static double kz[
EP], kw[
EP];
12049 double *cd, *mean[
NQ], *sigma[
NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
12051 int *ixs, *iys, *izs, *np;
12057 LOG(1,
"Write grid data: %s", filename);
12070 for (
int iq = 0; iq < ctl->
nq; iq++) {
12071 ALLOC(mean[iq],
double,
12073 ALLOC(sigma[iq],
double,
12076 ALLOC(vmr_impl,
double,
12084 ALLOC(area,
double,
12086 ALLOC(press,
double,
12103#pragma omp parallel
for default(shared)
12104 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
12105 z[iz] = ctl->
grid_z0 + dz * (iz + 0.5);
12106 press[iz] =
P(z[iz]);
12110 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12111 lon[ix] = ctl->
grid_lon0 + dlon * (ix + 0.5);
12112#pragma omp parallel for default(shared)
12113 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
12114 lat[iy] = ctl->
grid_lat0 + dlat * (iy + 0.5);
12115 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
12119 const double t0 = t - 0.5 * ctl->
dt_mod;
12120 const double t1 = t + 0.5 * ctl->
dt_mod;
12123#pragma omp parallel for default(shared)
12124 for (
int ip = 0; ip < atm->
np; ip++) {
12125 ixs[ip] = (int) ((atm->
lon[ip] - ctl->
grid_lon0) / dlon);
12126 iys[ip] = (int) ((atm->
lat[ip] - ctl->
grid_lat0) / dlat);
12127 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
grid_z0) / dz);
12128 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
12129 || ixs[ip] < 0 || ixs[ip] >= ctl->
grid_nx
12130 || iys[ip] < 0 || iys[ip] >= ctl->
grid_ny
12131 || izs[ip] < 0 || izs[ip] >= ctl->
grid_nz)
12136 for (
int ip = 0; ip < atm->
np; ip++)
12137 if (izs[ip] >= 0) {
12142 for (
int iq = 0; iq < ctl->
nq; iq++) {
12143 mean[iq][idx] += kernel * atm->
q[iq][ip];
12144 sigma[iq][idx] +=
SQR(kernel * atm->
q[iq][ip]);
12149#pragma omp parallel for default(shared)
12150 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12151 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12152 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
12159 if (ctl->
qnt_m >= 0)
12160 cd[idx] = mean[ctl->
qnt_m][idx] / (1e6 * area[iy]);
12163 vmr_impl[idx] = NAN;
12164 if (ctl->
qnt_m >= 0 && ctl->
molmass > 0 && met0 != NULL
12167 if (mean[ctl->
qnt_m][idx] > 0) {
12173 lon[ix], lat[iy], &temp, ci, cw, 1);
12177 MA / ctl->
molmass * cd[idx] / (
RHO(press[iz], temp) * dz * 1e3);
12183 for (
int iq = 0; iq < ctl->
nq; iq++) {
12184 mean[iq][idx] /= np[idx];
12185 const double var = sigma[iq][idx] / np[idx] -
SQR(mean[iq][idx]);
12186 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
12188 for (
int iq = 0; iq < ctl->
nq; iq++) {
12189 mean[iq][idx] = NAN;
12190 sigma[iq][idx] = NAN;
12197 t, z, lon, lat, area, dz, np);
12202 t, z, lon, lat, area, dz, np);
12206 ERRMSG(
"Grid data format GRID_TYPE unknown!");
12210 for (
int iq = 0; iq < ctl->
nq; iq++) {
12229 const char *filename,
12234 const double *vmr_impl,
12239 const double *area,
12249 if (!(out = popen(
"gnuplot",
"w")))
12250 ERRMSG(
"Cannot create pipe to gnuplot!");
12253 fprintf(out,
"set out \"%s.png\"\n", filename);
12257 int year, mon, day, hour, min, sec;
12258 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
12259 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
12260 year, mon, day, hour, min);
12266 ERRMSG(
"Cannot open file!");
12267 while (fgets(line,
LEN, in))
12268 fprintf(out,
"%s", line);
12275 if (!(out = fopen(filename,
"w")))
12276 ERRMSG(
"Cannot create file!");
12281 "# $1 = time [s]\n"
12282 "# $2 = altitude [km]\n"
12283 "# $3 = longitude [deg]\n"
12284 "# $4 = latitude [deg]\n"
12285 "# $5 = surface area [km^2]\n"
12286 "# $6 = layer depth [km]\n"
12287 "# $7 = column density (implicit) [kg/m^2]\n"
12288 "# $8 = volume mixing ratio (implicit) [ppv]\n"
12289 "# $9 = number of particles [1]\n");
12290 for (
int iq = 0; iq < ctl->
nq; iq++)
12291 fprintf(out,
"# $%i = %s (mean) [%s]\n", 10 + iq, ctl->
qnt_name[iq],
12294 for (
int iq = 0; iq < ctl->
nq; iq++)
12295 fprintf(out,
"# $%i = %s (stddev) [%s]\n", 10 + ctl->
nq + iq,
12297 fprintf(out,
"\n");
12300 for (
int ix = 0; ix < ctl->
grid_nx; ix++) {
12302 fprintf(out,
"\n");
12303 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
12305 fprintf(out,
"\n");
12306 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
12309 fprintf(out,
"%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
12310 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
12311 for (
int iq = 0; iq < ctl->
nq; iq++) {
12313 fprintf(out, ctl->
qnt_format[iq], mean[iq][idx]);
12316 for (
int iq = 0; iq < ctl->
nq; iq++) {
12318 fprintf(out, ctl->
qnt_format[iq], sigma[iq][idx]);
12320 fprintf(out,
"\n");
12333 const char *filename,
12338 const double *vmr_impl,
12343 const double *area,
12347 char longname[2 *
LEN], varname[2 *
LEN];
12351 int *help2, ncid, dimid[10], varid;
12353 size_t start[2], count[2];
12356 ALLOC(help,
double,
12362 NC(nc_create(filename, NC_NETCDF4, &ncid));
12365 NC(nc_def_dim(ncid,
"time", 1, &dimid[0]));
12366 NC(nc_def_dim(ncid,
"z", (
size_t) ctl->
grid_nz, &dimid[1]));
12367 NC(nc_def_dim(ncid,
"lat", (
size_t) ctl->
grid_ny, &dimid[2]));
12368 NC(nc_def_dim(ncid,
"lon", (
size_t) ctl->
grid_nx, &dimid[3]));
12369 NC(nc_def_dim(ncid,
"dz", 1, &dimid[4]));
12372 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &dimid[0],
"time",
12373 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
12374 NC_DEF_VAR(
"z", NC_DOUBLE, 1, &dimid[1],
"altitude",
"km", 0, 0);
12375 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &dimid[2],
"latitude",
"degrees_north", 0,
12377 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &dimid[3],
"longitude",
"degrees_east", 0,
12379 NC_DEF_VAR(
"dz", NC_DOUBLE, 1, &dimid[1],
"layer depth",
"km", 0, 0);
12380 NC_DEF_VAR(
"area", NC_DOUBLE, 1, &dimid[2],
"surface area",
"km**2", 0, 0);
12382 NC_DEF_VAR(
"cd", NC_FLOAT, 4, dimid,
"column density",
"kg m**-2",
12385 "volume mixing ratio (implicit)",
"ppv", ctl->
grid_nc_level, 0);
12386 NC_DEF_VAR(
"np", NC_INT, 4, dimid,
"number of particles",
"1", 0, 0);
12387 for (
int iq = 0; iq < ctl->
nq; iq++) {
12388 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
12389 sprintf(longname,
"%s (mean)", ctl->
qnt_longname[iq]);
12393 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
12394 sprintf(longname,
"%s (stddev)", ctl->
qnt_longname[iq]);
12400 NC(nc_enddef(ncid));
12410 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12411 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12412 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12417 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12418 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12419 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12424 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12425 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12426 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12431 for (
int iq = 0; iq < ctl->
nq; iq++) {
12432 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
12433 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12434 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12435 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12442 for (
int iq = 0; iq < ctl->
nq; iq++) {
12443 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
12444 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12445 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12446 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12453 NC(nc_close(ncid));
12463 const char *filename,
12469 if (!(out = fopen(filename,
"w")))
12470 ERRMSG(
"Cannot create file!");
12560 ERRMSG(
"Number of meteo variables doesn't match!");
12578 const char *varname) {
12587 for (
int ix = 0; ix < met->
nx; ix++)
12588 for (
int iy = 0; iy < met->
ny; iy++)
12589 help[
ARRAY_2D(ix, iy, met->
ny)] = var[ix][iy];
12592 LOG(2,
"Write 2-D variable: %s (uncompressed)", varname);
12594 (
size_t) (met->
nx * met->
ny),
12608 const char *varname,
12609 const int precision,
12610 const double tolerance) {
12619#pragma omp parallel for default(shared) collapse(2)
12620 for (
int ix = 0; ix < met->
nx; ix++)
12621 for (
int iy = 0; iy < met->
ny; iy++)
12622 for (
int ip = 0; ip < met->
np; ip++)
12623 help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)] = var[ix][iy][ip];
12627 LOG(2,
"Write 3-D variable: %s (uncompressed)", varname);
12629 (
size_t) (met->
nx * met->
ny * met->
np),
12636 (
size_t) met->
np, 0, out);
12644 FWRITE(&tolerance,
double,
12648 tolerance, 0, out);
12663 (
size_t) met->
np, met->
p, 0, out);
12673 FWRITE(&tolerance,
double,
12677 tolerance, 0, out);
12683 ERRMSG(
"MET_TYPE not supported!");
12684 LOG(3,
"%d %g", precision, tolerance);
12694 const char *filename,
12700 size_t start[4], count[4];
12701 NC(nc_create(filename, NC_NETCDF4, &ncid));
12704 int tid, lonid, latid, levid;
12705 NC(nc_def_dim(ncid,
"time", 1, &tid));
12706 NC(nc_def_dim(ncid,
"lon", (
size_t) met->
nx, &lonid));
12707 NC(nc_def_dim(ncid,
"lat", (
size_t) met->
ny, &latid));
12708 NC(nc_def_dim(ncid,
"lev", (
size_t) met->
np, &levid));
12711 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"time",
12712 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
12713 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &lonid,
"longitude",
"degrees_east", 0, 0);
12714 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &latid,
"latitude",
"degrees_north", 0, 0);
12715 NC_DEF_VAR(
"lev", NC_DOUBLE, 1, &levid,
"pressure",
"Pa", 0, 0);
12718 int dimid2[2] = { latid, lonid };
12719 NC_DEF_VAR(
"sp", NC_FLOAT, 2, dimid2,
"Surface pressure",
"Pa",
12721 NC_DEF_VAR(
"z", NC_FLOAT, 2, dimid2,
"Geopotential",
"m**2 s**-2",
12723 NC_DEF_VAR(
"t2m", NC_FLOAT, 2, dimid2,
"2 metre temperature",
"K",
12725 NC_DEF_VAR(
"u10m", NC_FLOAT, 2, dimid2,
"10 metre U wind component",
12727 NC_DEF_VAR(
"v10m", NC_FLOAT, 2, dimid2,
"10 metre V wind component",
12730 "Instantaneous eastward turbulent surface stress",
"N m**-2",
12733 "Instantaneous northward turbulent surface stress",
"N m**-2",
12736 "Instantaneous surface sensible heat flux",
"W m**-1",
12738 NC_DEF_VAR(
"lsm", NC_FLOAT, 2, dimid2,
"Land/sea mask",
"-",
12740 NC_DEF_VAR(
"sstk", NC_FLOAT, 2, dimid2,
"Sea surface temperature",
"K",
12742 NC_DEF_VAR(
"blp", NC_FLOAT, 2, dimid2,
"Boundary layer pressure",
"Pa",
12744 NC_DEF_VAR(
"pt", NC_FLOAT, 2, dimid2,
"Tropopause pressure",
"Pa",
12746 NC_DEF_VAR(
"tt", NC_FLOAT, 2, dimid2,
"Tropopause temperature",
"K",
12748 NC_DEF_VAR(
"zt", NC_FLOAT, 2, dimid2,
"Tropopause height",
"m",
12750 NC_DEF_VAR(
"h2ot", NC_FLOAT, 2, dimid2,
"Tropopause water vapor",
"ppv",
12752 NC_DEF_VAR(
"pct", NC_FLOAT, 2, dimid2,
"Cloud top pressure",
"Pa",
12754 NC_DEF_VAR(
"pcb", NC_FLOAT, 2, dimid2,
"Cloud bottom pressure",
"Pa",
12756 NC_DEF_VAR(
"cl", NC_FLOAT, 2, dimid2,
"Total column cloud water",
12759 "Pressure at lifted condensation level (LCL)",
"Pa",
12762 "Pressure at level of free convection (LFC)",
"Pa",
12765 "Pressure at equilibrium level (EL)",
"Pa", ctl->
met_nc_level,
12768 "Convective available potential energy",
"J kg**-1",
12770 NC_DEF_VAR(
"cin", NC_FLOAT, 2, dimid2,
"Convective inhibition",
12772 NC_DEF_VAR(
"o3c", NC_FLOAT, 2, dimid2,
"Total column ozone",
"DU",
12776 int dimid3[3] = { levid, latid, lonid };
12777 NC_DEF_VAR(
"t", NC_FLOAT, 3, dimid3,
"Temperature",
"K",
12779 NC_DEF_VAR(
"u", NC_FLOAT, 3, dimid3,
"U velocity",
"m s**-1",
12781 NC_DEF_VAR(
"v", NC_FLOAT, 3, dimid3,
"V velocity",
"m s**-1",
12783 NC_DEF_VAR(
"w", NC_FLOAT, 3, dimid3,
"Vertical velocity",
"Pa s**-1",
12785 NC_DEF_VAR(
"q", NC_FLOAT, 3, dimid3,
"Specific humidity",
"kg kg**-1",
12787 NC_DEF_VAR(
"o3", NC_FLOAT, 3, dimid3,
"Ozone mass mixing ratio",
12789 NC_DEF_VAR(
"clwc", NC_FLOAT, 3, dimid3,
"Cloud liquid water content",
12791 NC_DEF_VAR(
"crwc", NC_FLOAT, 3, dimid3,
"Cloud rain water content",
12793 NC_DEF_VAR(
"ciwc", NC_FLOAT, 3, dimid3,
"Cloud ice water content",
12795 NC_DEF_VAR(
"cswc", NC_FLOAT, 3, dimid3,
"Cloud snow water content",
12797 NC_DEF_VAR(
"cc", NC_FLOAT, 3, dimid3,
"Cloud cover",
"-",
12801 NC(nc_enddef(ncid));
12808 for (
int ip = 0; ip < met->
np; ip++)
12809 phelp[ip] = 100. * met->
p[ip];
12852 NC(nc_close(ncid));
12859 const char *varname,
12865 size_t start[4], count[4];
12873 for (
int ix = 0; ix < met->
nx; ix++)
12874 for (
int iy = 0; iy < met->
ny; iy++)
12875 help[
ARRAY_2D(iy, ix, met->
nx)] = scl * var[ix][iy];
12888 const char *varname,
12894 size_t start[4], count[4];
12902 for (
int ix = 0; ix < met->
nx; ix++)
12903 for (
int iy = 0; iy < met->
ny; iy++)
12904 for (
int ip = 0; ip < met->
np; ip++)
12905 help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)] = scl * var[ix][iy][ip];
12917 const char *filename,
12926 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
12927 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
12929 static int nobs, *obscount, ip, okay;
12938 if (ctl->
qnt_m < 0)
12939 ERRMSG(
"Need quantity mass!");
12943 ERRMSG(
"Specify molar mass!");
12950 ALLOC(area,
double,
12954 ALLOC(press,
double,
12960 ALLOC(rlon,
double,
12962 ALLOC(rlat,
double,
12964 ALLOC(robs,
double,
12971 LOG(1,
"Write profile data: %s", filename);
12972 if (!(out = fopen(filename,
"w")))
12973 ERRMSG(
"Cannot create file!");
12977 "# $1 = time [s]\n"
12978 "# $2 = altitude [km]\n"
12979 "# $3 = longitude [deg]\n"
12980 "# $4 = latitude [deg]\n"
12981 "# $5 = pressure [hPa]\n"
12982 "# $6 = temperature [K]\n"
12983 "# $7 = volume mixing ratio [ppv]\n"
12984 "# $8 = H2O volume mixing ratio [ppv]\n"
12985 "# $9 = O3 volume mixing ratio [ppv]\n"
12986 "# $10 = observed BT index [K]\n"
12987 "# $11 = number of observations\n");
12995 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
12996 z[iz] = ctl->
prof_z0 + dz * (iz + 0.5);
12997 press[iz] =
P(z[iz]);
13001 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
13002 lon[ix] = ctl->
prof_lon0 + dlon * (ix + 0.5);
13003 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
13004 lat[iy] = ctl->
prof_lat0 + dlat * (iy + 0.5);
13005 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
13010 const double t0 = t - 0.5 * ctl->
dt_mod;
13011 const double t1 = t + 0.5 * ctl->
dt_mod;
13014 ALLOC(mass,
double,
13016 ALLOC(obsmean,
double,
13018 ALLOC(obscount,
int,
13022 for (
int i = 0; i < nobs; i++) {
13027 else if (rt[i] >= t1)
13031 if (!isfinite(robs[i]))
13035 const int ix = (int) ((rlon[i] - ctl->
prof_lon0) / dlon);
13036 const int iy = (int) ((rlat[i] - ctl->
prof_lat0) / dlat);
13039 if (ix < 0 || ix >= ctl->
prof_nx || iy < 0 || iy >= ctl->
prof_ny)
13044 obsmean[idx] += robs[i];
13049 for (ip = 0; ip < atm->
np; ip++) {
13052 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13056 const int ix = (int) ((atm->
lon[ip] - ctl->
prof_lon0) / dlon);
13057 const int iy = (int) ((atm->
lat[ip] - ctl->
prof_lat0) / dlat);
13058 const int iz = (int) ((
Z(atm->
p[ip]) - ctl->
prof_z0) / dz);
13061 if (ix < 0 || ix >= ctl->
prof_nx ||
13067 mass[idx] += atm->
q[ctl->
qnt_m][ip];
13071 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
13072 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
13074 if (obscount[idx2] > 0) {
13078 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
13080 if (mass[idx3] > 0) {
13089 fprintf(out,
"\n");
13092 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
13097 lon[ix], lat[iy], &temp, ci, cw, 1);
13099 lon[ix], lat[iy], &h2o, ci, cw, 0);
13101 lon[ix], lat[iy], &o3, ci, cw, 0);
13106 / (
RHO(press[iz], temp) * area[iy] * dz * 1e9);
13109 fprintf(out,
"%.2f %g %g %g %g %g %g %g %g %g %d\n",
13110 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
13111 obsmean[idx2] / obscount[idx2], obscount[idx2]);
13144 const char *filename,
13153 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[
EP],
13156 static int nobs, nk;
13169 ALLOC(rlon,
double,
13171 ALLOC(rlat,
double,
13173 ALLOC(robs,
double,
13184 LOG(1,
"Write sample data: %s", filename);
13185 if (!(out = fopen(filename,
"w")))
13186 ERRMSG(
"Cannot create file!");
13190 "# $1 = time [s]\n"
13191 "# $2 = altitude [km]\n"
13192 "# $3 = longitude [deg]\n"
13193 "# $4 = latitude [deg]\n"
13194 "# $5 = surface area [km^2]\n"
13195 "# $6 = layer depth [km]\n"
13196 "# $7 = number of particles [1]\n"
13197 "# $8 = column density [kg/m^2]\n"
13198 "# $9 = volume mixing ratio [ppv]\n"
13199 "# $10 = observed BT index [K]\n\n");
13204 area = M_PI * rmax2;
13208 const double t0 = t - 0.5 * ctl->
dt_mod;
13209 const double t1 = t + 0.5 * ctl->
dt_mod;
13212 for (
int i = 0; i < nobs; i++) {
13217 else if (rt[i] >= t1)
13222 geo2cart(0, rlon[i], rlat[i], x0);
13225 const double rp =
P(rz[i]);
13226 const double ptop =
P(rz[i] + ctl->
sample_dz);
13227 const double pbot =
P(rz[i] - ctl->
sample_dz);
13235 for (
int ip = 0; ip < atm->
np; ip++) {
13238 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13242 if (fabs(rlat[i] - atm->
lat[ip]) > dlat)
13248 if (
DIST2(x0, x1) > rmax2)
13253 if (atm->
p[ip] > pbot || atm->
p[ip] < ptop)
13257 if (ctl->
qnt_m >= 0)
13264 const double cd = mass / (1e6 * area);
13275 rlon[i], rlat[i], &temp, ci, cw, 1);
13284 fprintf(out,
"%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
13285 rlon[i], rlat[i], area, ctl->
sample_dz, np, cd, vmr, robs[i]);
13306 const char *filename,
13313 static double rmax2, x0[3], x1[3];
13322 LOG(1,
"Write station data: %s", filename);
13325 if (!(out = fopen(filename,
"w")))
13326 ERRMSG(
"Cannot create file!");
13330 "# $1 = time [s]\n"
13331 "# $2 = altitude [km]\n"
13332 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
13333 for (
int iq = 0; iq < ctl->
nq; iq++)
13334 fprintf(out,
"# $%i = %s [%s]\n", (iq + 5),
13336 fprintf(out,
"\n");
13344 const double t0 = t - 0.5 * ctl->
dt_mod;
13345 const double t1 = t + 0.5 * ctl->
dt_mod;
13348 for (
int ip = 0; ip < atm->
np; ip++) {
13351 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13367 if (
DIST2(x0, x1) > rmax2)
13375 fprintf(out,
"%.2f %g %g %g",
13376 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]);
13377 for (
int iq = 0; iq < ctl->
nq; iq++) {
13379 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
13381 fprintf(out,
"\n");
13392 const char *filename,
13403 LOG(1,
"Write VTK data: %s", filename);
13406 const double t0 = t - 0.5 * ctl->
dt_mod;
13407 const double t1 = t + 0.5 * ctl->
dt_mod;
13410 if (!(out = fopen(filename,
"w")))
13411 ERRMSG(
"Cannot create file!");
13415 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13416 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13423 "# vtk DataFile Version 3.0\n"
13424 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
13427 fprintf(out,
"POINTS %d float\n", np);
13429 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13430 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13434 const double coslat = cos(
DEG2RAD(atm->
lat[ip]));
13435 const double x = radius * coslat * cos(
DEG2RAD(atm->
lon[ip]));
13436 const double y = radius * coslat * sin(
DEG2RAD(atm->
lon[ip]));
13437 const double z = radius * sin(
DEG2RAD(atm->
lat[ip]));
13438 fprintf(out,
"%g %g %g\n", x, y, z);
13441 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13442 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13444 fprintf(out,
"%g %g %g\n", atm->
lon[ip], atm->
lat[ip],
13449 fprintf(out,
"POINT_DATA %d\n", np);
13450 for (
int iq = 0; iq < ctl->
nq; iq++) {
13451 fprintf(out,
"SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
13453 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13454 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13456 fprintf(out,
"%g\n", atm->
q[iq][ip]);
void read_met_geopot(const ctl_t *ctl, met_t *met)
Calculates geopotential heights from meteorological data.
void mptrac_alloc(ctl_t **ctl, cache_t **cache, clim_t **clim, met_t **met0, met_t **met1, atm_t **atm, dd_t **dd)
Allocates and initializes memory resources for MPTRAC.
void mptrac_write_atm(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes air parcel data to a file in various formats.
void day2doy(const int year, const int mon, const int day, int *doy)
Get day of year from date.
void read_met_extrapolate(met_t *met)
Extrapolates meteorological data.
void write_atm_clams_traj(const char *dirname, const ctl_t *ctl, const atm_t *atm, const double t)
Writes CLaMS trajectory data to a NetCDF file.
int read_met_nc_2d(const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const char *varname5, const char *varname6, const ctl_t *ctl, const met_t *met, dd_t *dd, float dest[EX][EY], const float scl, const int init)
Reads a 2-dimensional meteorological variable from a NetCDF file.
void write_met_nc_2d(const int ncid, const char *varname, met_t *met, float var[EX][EY], const float scl)
Writes a 2D meteorological variable to a NetCDF file.
void read_met_sample(const ctl_t *ctl, met_t *met)
Downsamples meteorological data based on specified parameters.
void write_met_bin_3d(FILE *out, const ctl_t *ctl, met_t *met, float var[EX][EY][EP], const char *varname, const int precision, const double tolerance)
Writes a 3-dimensional meteorological variable to a binary file.
void read_obs(const char *filename, const ctl_t *ctl, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from a file and stores it in arrays.
void module_advect(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Advances particle positions using different advection schemes.
void module_timesteps(const ctl_t *ctl, cache_t *cache, met_t *met0, atm_t *atm, const double t)
Calculate time steps for air parcels based on specified conditions.
void module_meteo(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Update atmospheric properties using meteorological data.
void read_clim_photo(const char *filename, clim_photo_t *photo)
Reads photolysis rates from a NetCDF file and populates the given photolysis structure.
void read_met_cloud(met_t *met)
Calculates cloud-related variables for each grid point.
void module_decay(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, atm_t *atm)
Simulate exponential decay processes for atmospheric particles.
double sedi(const double p, const double T, const double rp, const double rhop)
Calculates the sedimentation velocity of a particle in air.
double cos_sza(const double sec, const double lon, const double lat)
Calculates the cosine of the solar zenith angle.
void intpol_met_space_2d(const met_t *met, float array[EX][EY], const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables in 2D space.
int read_met_nc_3d(const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const ctl_t *ctl, const met_t *met, dd_t *dd, float dest[EX][EY][EP], const float scl)
Reads a 3-dimensional meteorological variable from a NetCDF file.
int read_atm_nc(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a generic netCDF file and populates the given atmospheric structure.
void read_met_pbl(const ctl_t *ctl, met_t *met)
Computes the planetary boundary layer (PBL) pressure based on meteorological data.
void read_met_detrend(const ctl_t *ctl, met_t *met)
Detrends meteorological data.
void read_met_tropo(const ctl_t *ctl, const clim_t *clim, met_t *met)
Calculates the tropopause and related meteorological variables based on various methods and stores th...
void read_obs_asc(const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from an ASCII file.
void module_chem_init(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Initializes the chemistry modules by setting atmospheric composition.
int locate_reg(const double *xx, const int n, const double x)
Locate the index of the interval containing a given value in a regular grid.
void get_tropo(const int met_tropo, ctl_t *ctl, clim_t *clim, met_t *met, const double *lons, const int nx, const double *lats, const int ny, double *pt, double *zt, double *tt, double *qt, double *o3t, double *ps, double *zs)
Calculate tropopause data.
void read_met_nc_levels(const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads and processes meteorological level data from NetCDF files with domain decomposition.
void read_met_monotonize(const ctl_t *ctl, met_t *met)
Makes zeta and pressure profiles monotone.
int read_clim_ts(const char *filename, clim_ts_t *ts)
Reads a climatological time series from a file and populates the given time series structure.
void read_met_periodic(met_t *met)
Applies periodic boundary conditions to meteorological data along longitudinal axis.
void mptrac_run_timestep(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t **met0, met_t **met1, atm_t *atm, double t, dd_t *dd)
Executes a single timestep of the MPTRAC model simulation.
void module_timesteps_init(ctl_t *ctl, const atm_t *atm)
Initialize start time and time interval for time-stepping.
void write_ens(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes ensemble data to a file.
void module_mixing(const ctl_t *ctl, const clim_t *clim, atm_t *atm, const double t)
Update atmospheric properties through interparcel mixing.
double clim_zm(const clim_zm_t *zm, const double t, const double lat, const double p)
Interpolates monthly mean zonal mean climatological variables.
void module_mixing_help(const ctl_t *ctl, const clim_t *clim, atm_t *atm, const int *ixs, const int *iys, const int *izs, const int qnt_idx, const int use_ensemble)
Perform subgrid-scale interparcel mixing of a given quantity.
void read_clim_photo_help(const int ncid, const char *varname, const clim_photo_t *photo, double var[CP][CSZA][CO3])
Reads a 3D climatological photochemistry variable from a NetCDF file.
void read_met_ml2pl(const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname)
Interpolates meteorological data to specified pressure levels.
double clim_tropo(const clim_t *clim, const double t, const double lat)
Calculates the tropopause pressure based on climatological data.
void read_obs_nc(const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from a NetCDF file.
void read_met_bin_2d(FILE *in, const met_t *met, float var[EX][EY], const char *varname)
Reads a 2-dimensional meteorological variable from a binary file and stores it in the provided array.
int locate_irr(const double *xx, const int n, const double x)
Locate the index of the interval containing a given value in a sorted array.
void module_isosurf_init(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Initialize the isosurface module based on atmospheric data.
void level_definitions(ctl_t *ctl)
Defines pressure levels for meteorological data.
void write_grid_asc(const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
Writes grid data to an ASCII file.
void mptrac_update_device(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
Updates device memory for specified data structures.
void time2jsec(const int year, const int mon, const int day, const int hour, const int min, const int sec, const double remain, double *jsec)
Converts time components to seconds since January 1, 2000, 12:00:00 UTC.
void mptrac_init(ctl_t *ctl, cache_t *cache, clim_t *clim, atm_t *atm, const int ntask)
Initializes the MPTRAC model and its associated components.
void intpol_met_time_3d(const met_t *met0, float array0[EX][EY][EP], const met_t *met1, float array1[EX][EY][EP], const double ts, const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological data in 3D space and time.
void fft_help(double *fcReal, double *fcImag, const int n)
Computes the Fast Fourier Transform (FFT) of a complex sequence.
void module_wet_depo(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Perform wet deposition calculations for air parcels.
void compress_pck(const char *varname, float *array, const size_t nxy, const size_t nz, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats.
double nat_temperature(const double p, const double h2o, const double hno3)
Calculates the nitric acid trihydrate (NAT) temperature.
void spline(const double *x, const double *y, const int n, const double *x2, double *y2, const int n2, const int method)
Performs spline interpolation or linear interpolation.
void module_chem_grid(const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double tt)
Computes gridded chemical tracer concentrations (volume mixing ratio) from individual air parcel mass...
double clim_photo(const double rate[CP][CSZA][CO3], const clim_photo_t *photo, const double p, const double sza, const double o3c)
Calculates the photolysis rate for a given set of atmospheric conditions.
void read_clim_zm(const char *filename, const char *varname, clim_zm_t *zm)
Reads zonally averaged climatological data from a netCDF file and populates the given structure.
void read_met_nc_grid_dd_naive(dd_t *dd, const ctl_t *ctl, met_t *met, const int ncid)
Read meteorological grid data from a NetCDF file and set up subdomain decomposition with halos.
void module_sedi(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate sedimentation of particles in the atmosphere.
int read_met_nc(const char *filename, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads meteorological data from a NetCDF file and processes it.
void timer(const char *name, const char *group, const int output)
Measures and reports elapsed time for named and grouped timers.
void write_atm_asc(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes air parcel data to an ASCII file or gnuplot.
void intpol_met_space_3d(const met_t *met, float array[EX][EY][EP], const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables in 3D space.
void module_convection(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Performs convective mixing of atmospheric particles.
void read_kernel(const char *filename, double kz[EP], double kw[EP], int *nk)
Reads kernel function data from a file and populates the provided arrays.
void module_bound_cond(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Apply boundary conditions to particles based on meteorological and climatological data.
double scan_ctl(const char *filename, int argc, char *argv[], const char *varname, const int arridx, const char *defvalue, char *value)
Scans a control file or command-line arguments for a specified variable.
void module_advect_init(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Initializes the advection module by setting up pressure fields.
void module_radio_decay(const ctl_t *ctl, const cache_t *cache, atm_t *atm)
Apply radioactive decay to atmospheric tracer species.
void mptrac_get_met(ctl_t *ctl, clim_t *clim, const double t, met_t **met0, met_t **met1, dd_t *dd)
Retrieves meteorological data for the specified time.
void module_sort_help(double *a, const int *p, const int np)
Reorder an array based on a given permutation.
float stddev(const float *data, const int n)
Calculates the standard deviation of a set of data.
void intpol_tropo_3d(const double time0, float array0[EX][EY], const double time1, float array1[EX][EY], const double lons[EX], const double lats[EY], const int nlon, const int nlat, const double time, const double lon, const double lat, const int method, double *var, double *sigma)
Interpolates tropopause data in 3D (latitude, longitude, and time).
void read_met_bin_3d(FILE *in, const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname, const float bound_min, const float bound_max)
Reads 3D meteorological data from a binary file, potentially using different compression methods.
int locate_irr_float(const float *xx, const int n, const double x, const int ig)
Locate the index of the interval containing a given value in an irregularly spaced array.
double time_from_filename(const char *filename, const int offset)
Extracts and converts a timestamp from a filename to Julian seconds.
void write_prof(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes profile data to a specified file.
void mptrac_read_clim(const ctl_t *ctl, clim_t *clim)
Reads various climatological data and populates the given climatology structure.
double tropo_weight(const clim_t *clim, const atm_t *atm, const int ip)
Computes a weighting factor based on tropopause pressure.
void write_met_nc(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a NetCDF file.
void module_rng_init(const int ntask)
Initialize random number generators for parallel tasks.
int mptrac_read_atm(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a specified file into the given atmospheric structure.
void mptrac_update_host(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
Updates host memory for specified data structures.
void mptrac_write_output(const char *dirname, const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double t)
Writes various types of output data to files in a specified directory.
double clim_oh(const ctl_t *ctl, const clim_t *clim, const double t, const double lon, const double lat, const double p)
Calculates the hydroxyl radical (OH) concentration from climatology data, with an optional diurnal co...
void read_met_ozone(met_t *met)
Calculates the total column ozone from meteorological ozone data.
void read_met_nc_surface(const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads and processes surface meteorological data from NetCDF files with domain decomposition.
void clim_tropo_init(clim_t *clim)
Initializes the tropopause data in the climatology structure.
void module_rng(const ctl_t *ctl, double *rs, const size_t n, const int method)
Generate random numbers using various methods and distributions.
void get_met_help(const ctl_t *ctl, const double t, const int direct, const char *metbase, const double dt_met, char *filename)
Generates a formatted filename for meteorological data files based on the input parameters.
void write_station(const char *filename, const ctl_t *ctl, atm_t *atm, const double t)
Writes station data to a specified file.
void cart2geo(const double *x, double *z, double *lon, double *lat)
State variables of cuRAND random number generator.
void doy2day(const int year, const int doy, int *mon, int *day)
Converts a given day of the year (DOY) to a date (month and day).
void intpol_met_4d_zeta(const met_t *met0, float heights0[EX][EY][EP], float array0[EX][EY][EP], const met_t *met1, float heights1[EX][EY][EP], float array1[EX][EY][EP], const double ts, const double height, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables to a given position and time.
void intpol_met_time_2d(const met_t *met0, float array0[EX][EY], const met_t *met1, float array1[EX][EY], const double ts, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological data in 2D space and time.
void module_position(const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Update the positions and pressure levels of atmospheric particles.
void clim_oh_diurnal_correction(const ctl_t *ctl, clim_t *clim)
Applies a diurnal correction to the hydroxyl radical (OH) concentration in climatology data.
void locate_vert(float profiles[EX][EY][EP], const int np, const int lon_ap_ind, const int lat_ap_ind, const double height_ap, int *ind)
Locate the four vertical indizes of a box for a given height value.
void write_met_bin_2d(FILE *out, met_t *met, float var[EX][EY], const char *varname)
Writes a 2-dimensional meteorological variable to a binary file.
void read_met_pv(met_t *met)
Calculates potential vorticity (PV) from meteorological data.
int read_atm_bin(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a binary file and populates the given atmospheric structure.
void get_met_replace(char *orig, char *search, char *repl)
Replaces occurrences of a substring in a string with another substring.
void module_diff_meso(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate mesoscale diffusion for atmospheric particles.
void module_sort(const ctl_t *ctl, met_t *met0, atm_t *atm)
Sort particles according to box index.
double clim_ts(const clim_ts_t *ts, const double t)
Interpolates a time series of climatological variables.
void jsec2time(const double jsec, int *year, int *mon, int *day, int *hour, int *min, int *sec, double *remain)
Converts Julian seconds to calendar date and time components.
int read_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a binary file.
void write_atm_clams(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a NetCDF file in the CLaMS format.
void module_diff_turb(const ctl_t *ctl, cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Applies turbulent diffusion processes to atmospheric particles.
int read_atm_clams(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads atmospheric data from a CLAMS NetCDF file.
int mptrac_read_met(const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met, dd_t *dd)
Reads meteorological data from a file, supporting multiple formats and MPI broadcasting.
void write_vtk(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes VTK (Visualization Toolkit) data to a specified file.
void module_tracer_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Simulate chemical reactions involving long-lived atmospheric tracers.
void mptrac_read_ctl(const char *filename, int argc, char *argv[], ctl_t *ctl)
Reads control parameters from a configuration file and populates the given structure.
void mptrac_free(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm, dd_t *dd)
Frees memory resources allocated for MPTRAC.
void read_met_polar_winds(met_t *met)
Applies a fix for polar winds in meteorological data.
void module_h2o2_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Perform chemical reactions involving H2O2 within cloud particles.
void write_grid_nc(const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
Writes grid data to a NetCDF file.
double pbl_weight(const ctl_t *ctl, const atm_t *atm, const int ip, const double pbl, const double ps)
Computes a weighting factor based on planetary boundary layer pressure.
void module_diff_pbl(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Computes particle diffusion within the planetary boundary layer (PBL).
void write_met_nc_3d(const int ncid, const char *varname, met_t *met, float var[EX][EY][EP], const float scl)
Writes a 3D meteorological variable to a NetCDF file.
void module_isosurf(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Apply the isosurface module to adjust atmospheric properties.
void module_oh_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Perform hydroxyl chemistry calculations for atmospheric particles.
void geo2cart(const double z, const double lon, const double lat, double *x)
Converts geographic coordinates (longitude, latitude, altitude) to Cartesian coordinates.
void read_met_nc_grid(const char *filename, const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads meteorological grid data from NetCDF files with domain decomposition.
double kernel_weight(const double kz[EP], const double kw[EP], const int nk, const double p)
Calculates the kernel weight based on altitude and given kernel data.
int read_atm_asc(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from an ASCII file and populates the given atmospheric structure.
void intpol_check_lon_lat(const double *lons, const int nlon, const double *lats, const int nlat, const double lon, const double lat, double *lon2, double *lat2)
Adjusts longitude and latitude to ensure they fall within valid bounds.
void write_sample(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes sample data to a specified file.
void write_grid(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes grid data to a file in ASCII or netCDF format.
void module_dry_depo(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate dry deposition of atmospheric particles.
void write_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data in binary format to a specified file.
void write_atm_bin(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a binary file.
void read_met_cape(const ctl_t *ctl, const clim_t *clim, met_t *met)
Calculates Convective Available Potential Energy (CAPE) for each grid point.
void mptrac_write_met(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a file, supporting multiple formats and compression options.
double lapse_rate(const double t, const double h2o)
Calculates the moist adiabatic lapse rate in Kelvin per kilometer.
void write_csi(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes Critical Success Index (CSI) data to a file.
void write_atm_nc(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a NetCDF file.
MPTRAC library declarations.
#define NN(x0, y0, x1, y1, x)
Perform nearest-neighbor interpolation.
int dd_init(ctl_t *ctl, dd_t *dd, atm_t *atm)
Initializes domain decomposition for parallel processing.
void compress_zstd(const char *varname, float *array, const size_t n, const int decompress, const int level, FILE *inout)
Compresses or decompresses a float array using Zstandard (ZSTD).
#define LEN
Maximum length of ASCII data lines.
#define RE
Mean radius of Earth [km].
#define TVIRT(t, h2o)
Compute virtual temperature.
#define DD_NPOLE
Constant indicating the North pole [-].
void read_met_grib_surface(codes_handle **handles, const int num_messages, const ctl_t *ctl, met_t *met)
Reads surface meteorological data from a grib file and stores it in the meteorological data structure...
#define ARRAY_3D(ix, iy, ny, iz, nz)
Compute the linear index of a 3D array element.
#define PARTICLE_LOOP(ip0, ip1, check_dt,...)
Loop over particle indices with OpenACC acceleration.
#define MA
Molar mass of dry air [g/mol].
#define AVO
Avogadro constant [1/mol].
#define KB
Boltzmann constant [kg m^2/(K s^2)].
#define MH2O
Molar mass of water vapor [g/mol].
#define METVAR
Number of 3-D meteorological variables.
#define NENS
Maximum number of data points for ensemble analysis.
#define FWRITE(ptr, type, size, out)
Write data from memory to a file stream.
#define PW(p, h2o)
Calculate partial water vapor pressure.
#define H0
Scale height [km].
#define NC_PUT_ATT_GLOBAL(attname, text)
Add a global text attribute to a NetCDF file.
#define MOLEC_DENS(p, t)
Calculate the density of a gas molecule.
void dd_sort(const ctl_t *ctl, met_t *met0, atm_t *atm, dd_t *dd, int *nparticles, int *rank)
Sort particles according to box index and target rank for neighbours.
#define DD_SPOLE
Constant indicating the South pole [-].
#define LAPSE(p1, t1, p2, t2)
Calculate lapse rate.
#define NC(cmd)
Execute a NetCDF command and check for errors.
#define SELECT_TIMER(id, group)
Select and start a timer with specific attributes.
#define ECC_READ_3D(variable, level, target, scaling_factor, found_flag)
Writes 3D data from a grib message into the meteo struct.
void compress_cms(const ctl_t *ctl, const char *varname, float *array, const size_t nx, const size_t ny, const size_t np, const double *plev, const int decompress, FILE *inout)
Compresses or decompresses a 3-D meteorological field using cmultiscale.
#define DOTP(a, b)
Calculate the dot product of two vectors.
#define RA
Specific gas constant of dry air [J/(kg K)].
#define KARMAN
Karman's constant.
#define INTPOL_INIT
Initialize arrays for interpolation.
#define MIN(a, b)
Macro to determine the minimum of two values.
#define ERRMSG(...)
Print an error message with contextual information and terminate the program.
#define NC_PUT_INT(varname, ptr, hyperslab)
Write integer data to a NetCDF variable.
void compress_zfp(const char *varname, float *array, const int nx, const int ny, const int nz, const int precision, const double tolerance, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using the ZFP library.
#define EY
Maximum number of latitudes for meteo data.
void dd_particles2atm(atm_t *atm, particle_t *particles, ctl_t *ctl, int *nparticles, cache_t *cache)
Converts particle data to atmospheric data.
#define SH(h2o)
Compute specific humidity from water vapor volume mixing ratio.
#define INTPOL_3D(var, init)
Perform 3D interpolation for a meteorological variable.
#define NOBS
Maximum number of observation data points.
#define NTHREADS
Maximum number of OpenMP threads.
#define ARRAY_2D(ix, iy, ny)
Macro for computing the linear index of a 2D array element.
#define Z(p)
Convert pressure to altitude.
#define codes_handle
Placeholder when ECCODES is not available.
#define P(z)
Compute pressure at given altitude.
#define LV
Latent heat of vaporization of water [J/kg].
#define G0
Standard gravity [m/s^2].
#define CP
Maximum number of pressure levels for climatological data.
#define NQ
Maximum number of quantities per data point.
#define FREAD(ptr, type, size, in)
Read data from a file stream and store it in memory.
#define DX2DEG(dx, lat)
Convert a distance in kilometers to degrees longitude at a given latitude.
#define DEG2DY(dlat)
Convert a latitude difference to a distance in the y-direction (north-south).
#define EX
Maximum number of longitudes for meteo data.
#define EPS
Ratio of the specific gas constant of dry air and water vapor [1].
#define PSICE(t)
Compute saturation pressure over ice (WMO, 2018).
#define THETA(p, t)
Compute potential temperature.
#define RI
Ideal gas constant [J/(mol K)].
int dd_is_periodic_longitude(met_t *met, int nx_glob)
Check whether the longitude grid is periodic (global coverage).
int read_met_grib(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a grib file and processes it.
#define SET_QNT(qnt, name, longname, unit)
Set atmospheric quantity index.
#define TICE(p, h2o)
Calculate frost point temperature (WMO, 2018).
#define TOK(line, tok, format, var)
Get string tokens.
void dd_get_rect_neighbour(const ctl_t ctl, dd_t *dd)
Determines rectangular neighbouring ranks for MPI processes.
#define ZDIFF(lnp0, t0, h2o0, lnp1, t1, h2o1)
Calculate geopotential height difference.
#define THETAVIRT(p, t, h2o)
Compute virtual potential temperature.
#define DZ2DP(dz, p)
Convert a change in altitude to a change in pressure.
void dd_atm2particles(atm_t *atm, particle_t *particles, ctl_t *ctl, int *nparticles, cache_t *cache, int rank)
Extracts particles from an atmospheric state and prepares them for inter-domain transfer.
#define WARN(...)
Print a warning message with contextual information.
#define ZETA(ps, p, t)
Computes the value of the zeta vertical coordinate.
#define RHICE(p, t, h2o)
Compute relative humidity over ice.
#define INTPOL_TIME_ALL(time, p, lon, lat)
Interpolate multiple meteorological variables in time.
#define ALLOC(ptr, type, n)
Allocate memory for a pointer with error handling.
void read_met_grib_levels(codes_handle **handles, const int num_messages, const ctl_t *ctl, met_t *met)
Reads meteorological variables at different vertical levels from a grib file.
#define SET_ATM(qnt, val)
Set atmospheric quantity value.
#define CTS
Maximum number of data points of climatological time series.
#define ECC_READ_2D(variable, target, scaling_factor, found_flag)
Writes 2-D data from a grib message into the meteo struct.
int dd_calc_subdomain_from_coords(double lon, double lat, met_t *met, ctl_t *ctl, int mpi_size, int nx_glob, int ny_glob)
Computes the destination subdomain (MPI rank) for a particle based on its geographic coordinates.
#define DEG2RAD(deg)
Converts degrees to radians.
void broadcast_large_data(void *data, size_t N)
Broadcasts large data across all processes in an MPI communicator.
#define MO3
Molar mass of ozone [g/mol].
#define SQR(x)
Compute the square of a value.
#define RAD2DEG(rad)
Converts radians to degrees.
#define NP
Maximum number of atmospheric data points.
#define NTIMER
Maximum number of timers.
#define INTPOL_2D(var, init)
Perform 2D interpolation for a meteorological variable.
void dd_communicate_particles(particle_t *particles, int *nparticles, MPI_Datatype MPI_Particle, int *neighbours, int nneighbours, ctl_t ctl)
Communicates particles between MPI processes.
#define RH(p, t, h2o)
Compute relative humidity over water.
#define NC_PUT_FLOAT(varname, ptr, hyperslab)
Write a float array to a NetCDF file.
#define CY
Maximum number of latitudes for climatological data.
void module_dd(ctl_t *ctl, atm_t *atm, cache_t *cache, dd_t *dd, met_t **met)
Manages domain decomposition and particle communication in parallel processing.
void dd_sort_help(double *a, dd_t *dd, const int np)
Reorder an array according to a permutation vector.
#define LOG(level,...)
Print a log message with a specified logging level.
#define NC_DEF_VAR(varname, type, ndims, dims, long_name, units, level, quant)
Define a NetCDF variable with attributes.
#define TDEW(p, h2o)
Calculate dew point temperature.
#define ARRHENIUS(a, b, t)
Calculate the Arrhenius rate constant.
void dd_assign_rect_subdomains_atm(atm_t *atm, ctl_t *ctl, dd_t *dd, int init)
Assign atmospheric particles to rectangular subdomains.
#define NCSI
Maximum number of data points for CSI calculation.
#define NC_GET_DOUBLE(varname, ptr, force)
Retrieve a double-precision variable from a NetCDF file.
#define MPI_Datatype
Placeholder when MPI is not available.
#define EP
Maximum number of pressure levels for meteo data.
#define PSAT(t)
Compute saturation pressure over water.
#define DD_NPART
Maximum number of particles to send and recieve in domain decomposition.
#define RHO(p, t)
Compute density of air.
void module_kpp_chem(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
KPP chemistry module.
#define CO3
Maximum number of total column ozone data for climatological data.
void read_met_grib_grid(codes_handle **handles, int count_handles, met_t *met)
Reads global meteorological information from a grib file.
void compress_sz3(const char *varname, float *array, const int nx, const int ny, const int nz, const int precision, const double tolerance, const int decompress, FILE *inout)
Compresses or decompresses a 3-D float array using the SZ3 library.
void dd_register_MPI_type_particle(MPI_Datatype *MPI_Particle)
Registers a custom MPI datatype for particle structures.
#define NC_PUT_DOUBLE(varname, ptr, hyperslab)
Write double precision data to a NetCDF variable.
#define ECC(cmd)
Execute an ECCODES command and check for errors.
#define LIN(x0, y0, x1, y1, x)
Linear interpolation.
#define DIST2(a, b)
Calculate the squared Euclidean distance between two points in Cartesian coordinates.
#define NC_INQ_DIM(dimname, ptr, min, max, check)
Inquire the length of a dimension in a NetCDF file.
#define DEG2DX(dlon, lat)
Convert a longitude difference to a distance in the x-direction (east-west) at a specific latitude.
#define CPD
Specific heat of dry air at constant pressure [J/(kg K)].
#define CSZA
Maximum number of solar zenith angles for climatological data.
#define DY2DEG(dy)
Convert a distance in kilometers to degrees latitude.
#define MAX(a, b)
Macro to determine the maximum of two values.
#define DD_NNMAX
Maximum number of neighbours to communicate with in domain decomposition.
#define FMOD(x, y)
Calculate the floating-point remainder of dividing x by y.
double lat[NP]
Latitude [deg].
double lon[NP]
Longitude [deg].
int np
Number of air parcels.
double q[NQ][NP]
Quantity data (for various, user-defined attributes).
double p[NP]
Pressure [hPa].
double dt[NP]
Timesteps [s].
double iso_ts[NP]
Isosurface balloon time [s].
int iso_n
Isosurface balloon number of data points.
double iso_ps[NP]
Isosurface balloon pressure [hPa].
double rs[3 *NP+1]
Random numbers.
float uvwp[NP][3]
Wind perturbations [m/s].
double iso_var[NP]
Isosurface variables.
Climatological data in the form of photolysis rates.
int nsza
Number of solar zenith angles.
double sza[CSZA]
Solar zenith angle [rad].
double o3_1[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O1d + O2) [1/s].
double p[CP]
Pressure [hPa].
double ccl2f2[CP][CSZA][CO3]
CCl2F2 photolysis rate [1/s].
double o2[CP][CSZA][CO3]
O2 photolysis rate [1/s].
double ccl3f[CP][CSZA][CO3]
CCl3F photolysis rate [1/s].
double n2o[CP][CSZA][CO3]
N2O photolysis rate [1/s].
double h2o2[CP][CSZA][CO3]
H2O2 photolysis rate [1/s].
double h2o[CP][CSZA][CO3]
H2O photolysis rate [1/s].
double ccl4[CP][CSZA][CO3]
CCl4 photolysis rate [1/s].
double o3_2[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O3p + O2) [1/s].
double o3c[CO3]
Total column ozone [DU].
int np
Number of pressure levels.
int no3c
Number of total ozone columns.
clim_ts_t ccl2f2
CFC-12 time series.
clim_photo_t photo
Photolysis rates.
clim_zm_t ho2
HO2 zonal means.
clim_zm_t hno3
HNO3 zonal means.
int tropo_ntime
Number of tropopause timesteps.
clim_ts_t sf6
SF6 time series.
clim_ts_t ccl4
CFC-10 time series.
clim_ts_t ccl3f
CFC-11 time series.
clim_zm_t o1d
O(1D) zonal means.
double tropo_lat[73]
Tropopause latitudes [deg].
clim_zm_t h2o2
H2O2 zonal means.
int tropo_nlat
Number of tropopause latitudes.
clim_zm_t oh
OH zonal means.
double tropo[12][73]
Tropopause pressure values [hPa].
double tropo_time[12]
Tropopause time steps [s].
clim_ts_t n2o
N2O time series.
Climatological data in the form of time series.
double vmr[CTS]
Volume mixing ratio [ppv].
double time[CTS]
Time [s].
int ntime
Number of timesteps.
Climatological data in the form of zonal means.
int np
Number of pressure levels.
double p[CP]
Pressure [hPa].
double vmr[CT][CP][CY]
Volume mixing ratio [ppv].
int ntime
Number of timesteps.
int nlat
Number of latitudes.
double lat[CY]
Latitude [deg].
double grid_z0
Lower altitude of gridded data [km].
int qnt_o3
Quantity array index for ozone volume mixing ratio.
double csi_lat1
Upper latitude of gridded CSI data [deg].
char csi_obsfile[LEN]
Observation data file for CSI analysis.
int qnt_Coh
Quantity array index for OH volume mixing ratio (chemistry code).
double wet_depo_ic_a
Coefficient A for wet deposition in cloud (exponential form).
int met_nc_scale
Check netCDF scaling factors (0=no, 1=yes).
int qnt_pel
Quantity array index for pressure at equilibrium level (EL).
int csi_nz
Number of altitudes of gridded CSI data.
double molmass
Molar mass [g/mol].
int qnt_p
Quantity array index for pressure.
int qnt_Cccl2f2
Quantity array index for CFC-12 volume mixing ratio (chemistry code).
int dd_halos_size
Domain decomposition size of halos given in grid-points.
char atm_gpfile[LEN]
Gnuplot file for atmospheric data.
int mixing_nx
Number of longitudes of mixing grid.
double chemgrid_z1
Upper altitude of chemistry grid [km].
char qnt_format[NQ][LEN]
Quantity output format.
int qnt_m
Quantity array index for mass.
int qnt_aoa
Quantity array index for age of air.
int qnt_rhop
Quantity array index for particle density.
int qnt_swc
Quantity array index for cloud snow water content.
double csi_obsmin
Minimum observation index to trigger detection.
int qnt_pcb
Quantity array index for cloud bottom pressure.
char clim_n2o_timeseries[LEN]
Filename of N2O time series.
double bound_dzs
Boundary conditions surface layer depth [km].
double csi_lon1
Upper longitude of gridded CSI data [deg].
int qnt_u
Quantity array index for zonal wind.
double stat_lon
Longitude of station [deg].
double mixing_trop
Interparcel exchange parameter for mixing in the troposphere.
double sort_dt
Time step for sorting of particle data [s].
double mixing_z1
Upper altitude of mixing grid [km].
double stat_r
Search radius around station [km].
double wet_depo_bc_a
Coefficient A for wet deposition below cloud (exponential form).
int met_zstd_level
ZSTD compression level (from -5 to 22).
int csi_ny
Number of latitudes of gridded CSI data.
int vtk_sphere
Spherical projection for VTK data (0=no, 1=yes).
double chemgrid_z0
Lower altitude of chemistry grid [km].
double met_pbl_min
Minimum depth of planetary boundary layer [km].
int qnt_iwc
Quantity array index for cloud ice water content.
double chemgrid_lat0
Lower latitude of chemistry grid [deg].
double conv_cape
CAPE threshold for convection module [J/kg].
int qnt_Co1d
Quantity array index for O(1D) volume mixing ratio (chemistry code).
double met_cms_eps_pv
cmultiscale compression epsilon for potential vorticity.
int qnt_pw
Quantity array index for partial water vapor pressure.
char prof_basename[LEN]
Basename for profile output file.
double grid_z1
Upper altitude of gridded data [km].
int direction
Direction flag (1=forward calculation, -1=backward calculation).
char balloon[LEN]
Balloon position filename.
int qnt_Cccl4
Quantity array index for CFC-10 volume mixing ratio (chemistry code).
int met_dp
Stride for pressure levels.
double met_dt_out
Time step for sampling of meteo data along trajectories [s].
int qnt_h2o2
Quantity array index for H2O2 volume mixing ratio (climatology).
int qnt_vh
Quantity array index for horizontal wind.
char species[LEN]
Species.
int csi_nx
Number of longitudes of gridded CSI data.
double csi_lat0
Lower latitude of gridded CSI data [deg].
double turb_dz_trop
Vertical turbulent diffusion coefficient (troposphere) [m^2/s].
int met_pbl
Planetary boundary layer data (0=file, 1=z2p, 2=Richardson, 3=theta).
double met_comp_tol[METVAR]
Compression tolerance for SZ3 or ZFP.
int qnt_lwc
Quantity array index for cloud liquid water content.
double turb_mesoz
Vertical scaling factor for mesoscale wind fluctuations.
int grid_nc_level
zlib compression level of netCDF grid data files (0=off).
int grid_nx
Number of longitudes of gridded data.
int atm_type
Type of atmospheric data files (0=ASCII, 1=binary, 2=netCDF, 3=CLaMS_traj, 4=CLaMS_pos).
double bound_mass
Boundary conditions mass per particle [kg].
double grid_lat0
Lower latitude of gridded data [deg].
int qnt_ts
Quantity array index for surface temperature.
int qnt_loss_rate
Quantity array index for total loss rate.
double met_cms_eps_h2o
cmultiscale compression epsilon for water vapor.
int qnt_plfc
Quantity array index for pressure at level of free convection (LCF).
int qnt_Acs137
Quantity array index for radioactive activity of Cs-137.
double grid_lon0
Lower longitude of gridded data [deg].
int qnt_o1d
Quantity array index for O(1D) volume mixing ratio (climatology).
int met_tropo_spline
Tropopause interpolation method (0=linear, 1=spline).
char sample_kernel[LEN]
Kernel data file for sample output.
int qnt_tvirt
Quantity array index for virtual temperature.
double dt_met
Time step of meteo data [s].
char clim_ho2_filename[LEN]
Filename of HO2 climatology.
double chemgrid_lat1
Upper latitude of chemistry grid [deg].
int met_geopot_sy
Latitudinal smoothing of geopotential heights.
char grid_gpfile[LEN]
Gnuplot file for gridded data.
double met_cms_eps_u
cmultiscale compression epsilon for zonal wind.
double turb_dx_strat
Horizontal turbulent diffusion coefficient (stratosphere) [m^2/s].
int qnt_vmr
Quantity array index for volume mixing ratio.
int qnt_lsm
Quantity array index for land-sea mask.
int qnt_theta
Quantity array index for potential temperature.
double bound_lat1
Boundary conditions maximum longitude [deg].
double stat_t1
Stop time for station output [s].
char csi_kernel[LEN]
Kernel data file for CSI output.
double turb_dx_trop
Horizontal turbulent diffusion coefficient (troposphere) [m^2/s].
int grid_type
Type of grid data files (0=ASCII, 1=netCDF).
double csi_lon0
Lower longitude of gridded CSI data [deg].
int qnt_pbl
Quantity array index for boundary layer pressure.
double oh_chem[4]
Coefficients for OH reaction rate (A, E/R or k0, n, kinf, m).
int grid_stddev
Include standard deviations in grid output (0=no, 1=yes).
int qnt_psice
Quantity array index for saturation pressure over ice.
double chemgrid_lon0
Lower longitude of chemistry grid [deg].
int bound_pbl
Boundary conditions planetary boundary layer (0=no, 1=yes).
int qnt_mloss_wet
Quantity array index for total mass loss due to wet deposition.
int radio_decay
Switch for radioactive decay module (0=off, 1=on).
int met_geopot_sx
Longitudinal smoothing of geopotential heights.
int met_sy
Smoothing for latitudes.
int qnt_ps
Quantity array index for surface pressure.
int rng_type
Random number generator (0=GSL, 1=Squares, 2=cuRAND).
char prof_obsfile[LEN]
Observation data file for profile output.
int isosurf
Isosurface parameter (0=none, 1=pressure, 2=density, 3=theta, 4=balloon).
double bound_p1
Boundary conditions top pressure [hPa].
int qnt_zs
Quantity array index for surface geopotential height.
int prof_nz
Number of altitudes of gridded profile data.
double csi_dt_out
Time step for CSI output [s].
int met_cape
Convective available potential energy data (0=file, 1=calculate).
double csi_modmin
Minimum column density to trigger detection [kg/m^2].
int met_sx
Smoothing for longitudes.
double chemgrid_lon1
Upper longitude of chemistry grid [deg].
double turb_mesox
Horizontal scaling factor for mesoscale wind fluctuations.
double met_cms_eps_iwc
cmultiscale compression epsilon for cloud ice water content.
double met_cms_eps_swc
cmultiscale compression epsilon for cloud snow water content.
char grid_kernel[LEN]
Kernel data file for grid output.
double met_cms_eps_v
cmultiscale compression epsilon for meridional wind.
double prof_z0
Lower altitude of gridded profile data [km].
int qnt_w
Quantity array index for vertical velocity.
double bound_vmr
Boundary conditions volume mixing ratio [ppv].
double met_tropo_pv
Dynamical tropopause potential vorticity threshold [PVU].
int prof_nx
Number of longitudes of gridded profile data.
int qnt_stat
Quantity array index for station flag.
int met_tropo
Tropopause definition (0=none, 1=clim, 2=cold point, 3=WMO_1st, 4=WMO_2nd, 5=dynamical).
int qnt_rp
Quantity array index for particle radius.
int met_mpi_share
Use MPI to share meteo (0=no, 1=yes).
double mixing_strat
Interparcel exchange parameter for mixing in the stratosphere.
int qnt_vz
Quantity array index for vertical velocity.
int qnt_ho2
Quantity array index for HO2 volume mixing ratio (climatology).
double csi_z1
Upper altitude of gridded CSI data [km].
double stat_t0
Start time for station output [s].
double oh_chem_beta
Beta parameter for diurnal variablity of OH.
int dd
Domain decomposition (0=no, 1=yes, with 2x2 if not specified).
char clim_o1d_filename[LEN]
Filename of O(1D) climatology.
int qnt_eta
Quantity array index for eta vertical coordinate.
char clim_photo[LEN]
Filename of photolysis rates climatology.
double wet_depo_so2_ph
pH value used to calculate effective Henry constant of SO2.
double mixing_z0
Lower altitude of mixing grid [km].
int qnt_mloss_decay
Quantity array index for total mass loss due to exponential decay.
int atm_type_out
Type of atmospheric data files for output (-1=same as ATM_TYPE, 0=ASCII, 1=binary,...
int met_cms_nd0x
cmultiscale number of cells of coarsest grid in x-direction.
int met_nlev
Number of meteo data model levels.
double dt_kpp
Time step for KPP chemistry [s].
char csi_basename[LEN]
Basename of CSI data files.
double dry_depo_dp
Dry deposition surface layer [hPa].
int qnt_shf
Quantity array index for surface sensible heat flux.
int qnt_vs
Quantity array index for surface meridional wind.
int qnt_Cco
Quantity array index for CO volume mixing ratio (chemistry code).
double vtk_dt_out
Time step for VTK data output [s].
double t_stop
Stop time of simulation [s].
double conv_dt
Time interval for convection module [s].
char sample_obsfile[LEN]
Observation data file for sample output.
int qnt_hno3
Quantity array index for HNO3 volume mixing ratio (climatology).
char grid_basename[LEN]
Basename of grid data files.
int met_clams
Read MPTRAC or CLaMS meteo data (0=MPTRAC, 1=CLaMS).
int met_comp_prec[METVAR]
Compression precision for SZ3 or ZFP.
int qnt_h2ot
Quantity array index for tropopause water vapor volume mixing ratio.
int qnt_rh
Quantity array index for relative humidity over water.
double met_cms_eps_cc
cmultiscale compression epsilon for cloud cover.
double bound_lat0
Boundary conditions minimum longitude [deg].
double met_pbl_max
Maximum depth of planetary boundary layer [km].
int met_dx
Stride for longitudes.
int qnt_destination
Quantity array index for destination subdomain in domain decomposition.
int mixing_ny
Number of latitudes of mixing grid.
int met_convention
Meteo data layout (0=[lev, lat, lon], 1=[lon, lat, lev]).
int qnt_zeta_d
Quantity array index for diagnosed zeta vertical coordinate.
char clim_h2o2_filename[LEN]
Filename of H2O2 climatology.
int tracer_chem
Switch for first order tracer chemistry module (0=off, 1=on).
double dt_mod
Time step of simulation [s].
int diffusion
Diffusion scheme (0=off, 1=fixed-K, 2=PBL).
int qnt_tnat
Quantity array index for T_NAT.
int qnt_eta_dot
Quantity array index for velocity of eta vertical coordinate.
int qnt_tice
Quantity array index for T_ice.
int qnt_zg
Quantity array index for geopotential height.
double vtk_offset
Vertical offset for VTK data [km].
int qnt_v
Quantity array index for meridional wind.
int qnt_mloss_dry
Quantity array index for total mass loss due to dry deposition.
double bound_vmr_trend
Boundary conditions volume mixing ratio trend [ppv/s].
int met_cache
Preload meteo data into disk cache (0=no, 1=yes).
int qnt_oh
Quantity array index for OH volume mixing ratio (climatology).
char qnt_unit[NQ][LEN]
Quantity units.
int qnt_Ch
Quantity array index for H volume mixing ratio (chemistry code).
int met_press_level_def
Use predefined pressure levels or not.
int oh_chem_reaction
Reaction type for OH chemistry (0=none, 2=bimolecular, 3=termolecular).
int qnt_h2o
Quantity array index for water vapor volume mixing ratio.
int prof_ny
Number of latitudes of gridded profile data.
int qnt_rhice
Quantity array index for relative humidity over ice.
int qnt_rho
Quantity array index for density of air.
double sample_dz
Layer depth for sample output [km].
double tdec_strat
Life time of particles in the stratosphere [s].
int obs_type
Type of observation data files (0=ASCII, 1=netCDF).
int grid_nc_quant[NQ]
Number of digits for quantization of netCDF grid data files (0=off).
double met_cms_eps_lwc
cmultiscale compression epsilon for cloud liquid water content.
int qnt_us
Quantity array index for surface zonal wind.
double met_cms_eps_z
cmultiscale compression epsilon for geopotential height.
double grid_lon1
Upper longitude of gridded data [deg].
int qnt_Cn2o
Quantity array index for N2O volume mixing ratio (chemistry code).
int qnt_Cccl3f
Quantity array index for CFC-11 volume mixing ratio (chemistry code).
char qnt_name[NQ][LEN]
Quantity names.
char atm_basename[LEN]
Basename of atmospheric data files.
double mixing_lat0
Lower latitude of mixing grid [deg].
int nens
Number of ensembles.
int qnt_pt
Quantity array index for tropopause pressure.
int qnt_cl
Quantity array index for total column cloud water.
int advect
Advection scheme (0=off, 1=Euler, 2=midpoint, 4=Runge-Kutta).
double prof_z1
Upper altitude of gridded profile data [km].
double met_lev_hyam[EP]
Meteo data model level a coefficients.
int qnt_t
Quantity array index for temperature.
int atm_filter
Time filter for atmospheric data output (0=none, 1=missval, 2=remove).
int kpp_chem
Switch for KPP chemistry module (0=off, 1=on).
int qnt_zeta
Quantity array index for zeta vertical coordinate.
double conv_pbl_trans
Depth of PBL transition layer (fraction of PBL depth).
char ens_basename[LEN]
Basename of ensemble data file.
int qnt_Ai131
Quantity array index for radioactive activity of I-131.
double wet_depo_pre[2]
Coefficients for precipitation calculation.
int met_vert_coord
Vertical coordinate of input meteo data (0=plev, 1=mlev_p_file, 2=mlev_ab_file, 3=mlev_ab_full,...
double csi_z0
Lower altitude of gridded CSI data [km].
int qnt_lapse
Quantity array index for lapse rate.
int qnt_Apb210
Quantity array index for radioactive activity of Pb-210.
double stat_lat
Latitude of station [deg].
int qnt_Cho2
Quantity array index for HO2 volume mixing ratio (chemistry code).
double wet_depo_bc_h[2]
Coefficients for wet deposition below cloud (Henry's law: Hb, Cb).
int grid_ny
Number of latitudes of gridded data.
int qnt_Csf6
Quantity array index for SF6 volume mixing ratio (chemistry code).
int qnt_Ch2o
Quantity array index for H2O volume mixing ratio (chemistry code).
double met_detrend
FWHM of horizontal Gaussian used for detrending [km].
int conv_mix_pbl
Vertical mixing in the PBL (0=off, 1=on).
char metbase[LEN]
Basename for meteo data.
double bound_dps
Boundary conditions surface layer depth [hPa].
int dd_nbr_neighbours
Domain decomposition number of neighbours to communicate with.
double met_cms_eps_t
cmultiscale compression epsilon for temperature.
int chemgrid_nz
Number of altitudes of chemistry grid.
int qnt_cape
Quantity array index for convective available potential energy (CAPE).
int qnt_zeta_dot
Quantity array index for velocity of zeta vertical coordinate.
double bound_mass_trend
Boundary conditions mass per particle trend [kg/s].
int met_cms_nd0y
cmultiscale number of cells of coarsest grid in y-direction.
int mixing_nz
Number of altitudes of mixing grid.
int qnt_o3c
Quantity array index for total column ozone.
double bound_p0
Boundary conditions bottom pressure [hPa].
double mixing_lon0
Lower longitude of mixing grid [deg].
char clim_ccl4_timeseries[LEN]
Filename of CFC-10 time series.
int qnt_Co3
Quantity array index for O3 volume mixing ratio (chemistry code).
int qnt_tsts
Quantity array index for T_STS.
int grid_nz
Number of altitudes of gridded data.
char clim_oh_filename[LEN]
Filename of OH climatology.
int qnt_nss
Quantity array index for northward turbulent surface stress.
double ens_dt_out
Time step for ensemble output [s].
char sample_basename[LEN]
Basename of sample data file.
int atm_stride
Particle index stride for atmospheric data files.
int met_relhum
Try to read relative humidity (0=no, 1=yes).
double mixing_lat1
Upper latitude of mixing grid [deg].
double atm_dt_out
Time step for atmospheric data output [s].
char clim_sf6_timeseries[LEN]
Filename of SF6 time series.
double prof_lat1
Upper latitude of gridded profile data [deg].
int met_cms_batch
cmultiscale batch size.
double psc_h2o
H2O volume mixing ratio for PSC analysis.
int met_sp
Smoothing for pressure levels.
double prof_lon0
Lower longitude of gridded profile data [deg].
int qnt_Axe133
Quantity array index for radioactive activity of Xe-133.
int chemgrid_nx
Number of longitudes of chemistry grid.
int qnt_pct
Quantity array index for cloud top pressure.
int qnt_mloss_kpp
Quantity array index for total mass loss due to KPP chemistry.
int qnt_psat
Quantity array index for saturation pressure over water.
int qnt_subdomain
Quantity array index for current subdomain in domain decomposition.
double met_lev_hybm[EP]
Meteo data model level b coefficients.
double prof_lat0
Lower latitude of gridded profile data [deg].
int qnt_cin
Quantity array index for convective inhibition (CIN).
double psc_hno3
HNO3 volume mixing ratio for PSC analysis.
double prof_lon1
Upper longitude of gridded profile data [deg].
double met_cms_eps_rwc
cmultiscale compression epsilon for cloud rain water content.
int met_nc_quant
Number of digits for quantization of netCDF meteo files (0=off).
int h2o2_chem_reaction
Reaction type for H2O2 chemistry (0=none, 1=SO2).
int qnt_Co3p
Quantity array index for O(3P) volume mixing ratio (chemistry code).
int atm_nc_quant[NQ]
Number of digits for quantization of netCDF atmospheric data files (0=off).
double wet_depo_bc_ret_ratio
Coefficients for wet deposition below cloud: retention ratio.
int chemgrid_ny
Number of latitudes of chemistry grid.
int qnt_Abe7
Quantity array index for radioactive activity of Be-7.
char clim_ccl3f_timeseries[LEN]
Filename of CFC-11 time series.
double met_cms_eps_o3
cmultiscale compression epsilon for ozone.
int met_cms_zstd
cmultiscale ZSTD compression (0=off, 1=on).
int met_cms_maxlev
cmultiscale maximum refinement level.
int grid_sparse
Sparse output in grid data files (0=no, 1=yes).
char vtk_basename[LEN]
Basename of VTK data files.
double dry_depo_vdep
Dry deposition velocity [m/s].
int qnt_tt
Quantity array index for tropopause temperature.
int met_np
Number of target pressure levels.
int qnt_ens
Quantity array index for ensemble IDs.
int met_nc_level
zlib compression level of netCDF meteo files (0=off).
double mixing_dt
Time interval for mixing [s].
int qnt_Arn222
Quantity array index for radioactive activity of Rn-222.
int qnt_mloss_h2o2
Quantity array index for total mass loss due to H2O2 chemistry.
double vtk_scale
Vertical scaling factor for VTK data.
char clim_ccl2f2_timeseries[LEN]
Filename of CFC-12 time series.
double met_cms_eps_w
cmultiscale compression epsilon for vertical velocity.
double wet_depo_ic_h[2]
Coefficients for wet deposition in cloud (Henry's law: Hb, Cb).
double turb_dx_pbl
Horizontal turbulent diffusion coefficient (PBL) [m^2/s].
double conv_cin
CIN threshold for convection module [J/kg].
int qnt_pv
Quantity array index for potential vorticity.
int advect_vert_coord
Vertical velocity of air parcels (0=omega_on_plev, 1=zetadot_on_mlev, 2=omega_on_mlev,...
int qnt_mloss_oh
Quantity array index for total mass loss due to OH chemistry.
int qnt_Ch2o2
Quantity array index for H2O2 volume mixing ratio (chemistry code).
int qnt_sst
Quantity array index for sea surface temperature.
double mixing_lon1
Upper longitude of mixing grid [deg].
int atm_nc_level
zlib compression level of netCDF atmospheric data files (0=off).
char clim_hno3_filename[LEN]
Filename of HNO3 climatology.
double wet_depo_ic_ret_ratio
Coefficients for wet deposition in cloud: retention ratio.
int qnt_sh
Quantity array index for specific humidity.
int qnt_ess
Quantity array index for eastward turbulent surface stress.
double wet_depo_ic_b
Coefficient B for wet deposition in cloud (exponential form).
double wet_depo_bc_b
Coefficient B for wet deposition below cloud (exponential form).
int met_dy
Stride for latitudes.
int qnt_Cx
Quantity array index for trace species x volume mixing ratio (chemistry code).
double turb_dz_strat
Vertical turbulent diffusion coefficient (stratosphere) [m^2/s].
double bound_zetas
Boundary conditions surface layer zeta [K].
int dd_subdomains_zonal
Domain decomposition zonal subdomain number.
int qnt_idx
Quantity array index for air parcel IDs.
double met_tropo_theta
Dynamical tropopause potential temperature threshold [K].
int qnt_rwc
Quantity array index for cloud rain water content.
double t_start
Start time of simulation [s].
char qnt_longname[NQ][LEN]
Quantity long names.
double met_p[EP]
Target pressure levels [hPa].
int nq
Number of quantities.
double tdec_trop
Life time of particles in the troposphere [s].
double sample_dx
Horizontal radius for sample output [km].
int vtk_stride
Particle index stride for VTK data.
char stat_basename[LEN]
Basename of station data file.
double turb_dz_pbl
Vertical turbulent diffusion coefficient (PBL) [m^2/s].
double grid_lat1
Upper latitude of gridded data [deg].
int dd_subdomains_meridional
Domain decomposition meridional subdomain number.
int qnt_zt
Quantity array index for tropopause geopotential height.
int met_type
Type of meteo data files (0=netCDF, 1=binary, 2=pck, 3=ZFP, 4=ZSTD, 5=cms, 6=grib,...
int qnt_cc
Quantity array index for cloud cover.
int qnt_plcl
Quantity array index for pressure at lifted condensation level (LCL).
double grid_dt_out
Time step for gridded data output [s].
int qnt_tdew
Quantity array index for dew point temperature.
Domain decomposition data structure.
size_t halo_bnd_count[4]
Hyperslab of boundary halos count.
int halo_offset_end
Hyperslab of boundary halos count.
int neighbours[DD_NNMAX]
Rank of neighbouring nodes.
double subdomain_lon_min
Rectangular grid limit of subdomain.
size_t halo_bnd_start[4]
Hyperslab of boundary halos start.
double subdomain_lat_max
Rectangular grid limit of subdomain.
int init
Shows if domain decomposition was initialized.
double subdomain_lon_max
Rectangular grid limit of subdomain.
int halo_offset_start
Hyperslab of boundary halos count.
size_t subdomain_count[4]
Hyperslab start and count for subdomain.
size_t subdomain_start[4]
Hyperslab start and count for subdomain.
double subdomain_lat_min
Rectangular grid limit of subdomain.
float zt[EX][EY]
Tropopause geopotential height [km].
float sst[EX][EY]
Sea surface temperature [K].
float rwc[EX][EY][EP]
Cloud rain water content [kg/kg].
float o3c[EX][EY]
Total column ozone [DU].
float zeta_dotl[EX][EY][EP]
Vertical velocity on model levels [K/s].
float h2o[EX][EY][EP]
Water vapor volume mixing ratio [1].
float cape[EX][EY]
Convective available potential energy [J/kg].
float w[EX][EY][EP]
Vertical velocity [hPa/s].
float pct[EX][EY]
Cloud top pressure [hPa].
double hybrid[EP]
Model hybrid levels.
int nx
Number of longitudes.
int ny
Number of latitudes.
float shf[EX][EY]
Surface sensible heat flux [W/m^2].
float ps[EX][EY]
Surface pressure [hPa].
float lwc[EX][EY][EP]
Cloud liquid water content [kg/kg].
float us[EX][EY]
Surface zonal wind [m/s].
float wl[EX][EY][EP]
Vertical velocity on model levels [hPa/s].
float vl[EX][EY][EP]
Meridional wind on model levels [m/s].
float zs[EX][EY]
Surface geopotential height [km].
float o3[EX][EY][EP]
Ozone volume mixing ratio [1].
float cc[EX][EY][EP]
Cloud cover [1].
int np
Number of pressure levels.
float t[EX][EY][EP]
Temperature [K].
float ts[EX][EY]
Surface temperature [K].
float u[EX][EY][EP]
Zonal wind [m/s].
float ess[EX][EY]
Eastward turbulent surface stress [N/m^2].
float ul[EX][EY][EP]
Zonal wind on model levels [m/s].
float pcb[EX][EY]
Cloud bottom pressure [hPa].
float pel[EX][EY]
Pressure at equilibrium level (EL) [hPa].
float cin[EX][EY]
Convective inhibition [J/kg].
float plcl[EX][EY]
Pressure at lifted condensation level (LCL) [hPa].
double lon[EX]
Longitudes [deg].
float pt[EX][EY]
Tropopause pressure [hPa].
float tt[EX][EY]
Tropopause temperature [K].
float pbl[EX][EY]
Boundary layer pressure [hPa].
float vs[EX][EY]
Surface meridional wind [m/s].
float z[EX][EY][EP]
Geopotential height [km].
float v[EX][EY][EP]
Meridional wind [m/s].
int npl
Number of model levels.
float lsm[EX][EY]
Land-sea mask [1].
float iwc[EX][EY][EP]
Cloud ice water content [kg/kg].
float h2ot[EX][EY]
Tropopause water vapor volume mixing ratio [ppv].
float pv[EX][EY][EP]
Potential vorticity [PVU].
double eta[EP]
Model level eta values.
float cl[EX][EY]
Total column cloud water [kg/m^2].
float nss[EX][EY]
Northward turbulent surface stress [N/m^2].
float pl[EX][EY][EP]
Pressure on model levels [hPa].
float plfc[EX][EY]
Pressure at level of free convection (LFC) [hPa].
double hyam[EP]
Model level a coefficients [Pa].
double lat[EY]
Latitudes [deg].
float swc[EX][EY][EP]
Cloud snow water content [kg/kg].
double hybm[EP]
Model level b coefficients.
float zetal[EX][EY][EP]
Zeta on model levels [K].
double p[EP]
Pressure levels [hPa].
double lat
Latitude [deg].
double lon
Longitude [deg].
double q[NQ]
Quantity data (for various, user-defined attributes).