37static uint64_t rng_ctr;
41static curandGenerator_t rng_curand;
51#define CHUNK_SIZE 2147483647
54 MPI_Bcast(&N, 1, MPI_UINT64_T, 0, MPI_COMM_WORLD);
60 for (
size_t i = 0; i < num_chunks; i++) {
65 const size_t chunk_size = end - start;
68 MPI_Bcast((
char *) data + start, (
int) chunk_size, MPI_BYTE, 0,
82 const double radius = sqrt(
DOTP(x, x));
84 *lat =
RAD2DEG(asin(x[2] / radius));
85 *lon =
RAD2DEG(atan2(x[1], x[0]));
100 const double sza_thresh =
DEG2RAD(85.), csza_thresh = cos(sza_thresh);
103 const double lat_ref =
106 while (lon_ref < -180.0)
108 while (lon_ref >= 180.0)
112 const double oh =
clim_zm(&clim->
oh, t, lat_ref, p);
119 const double csza =
cos_sza(t, lon_ref, lat_ref);
120 const double denom = (csza >= csza_thresh) ? csza : csza_thresh;
131 const double sza_thresh =
DEG2RAD(85.), csza_thresh = cos(sza_thresh);
134 for (
int it = 0; it < clim->
oh.
ntime; it++)
135 for (
int iz = 0; iz < clim->
oh.
np; iz++)
136 for (
int iy = 0; iy < clim->
oh.
nlat; iy++) {
143 for (
double lon = -180; lon < 180; lon += 1.0) {
146 const double denom = (csza >= csza_thresh) ? csza : csza_thresh;
152 clim->
oh.
vmr[it][iz][iy] /= (sum / (double) n);
167 if (p < photo->p[photo->
np - 1])
168 p_help = photo->
p[photo->
np - 1];
169 else if (p > photo->
p[0])
170 p_help = photo->
p[0];
173 double sza_help = sza;
174 if (sza < photo->sza[0])
175 sza_help = photo->
sza[0];
176 else if (sza > photo->
sza[photo->
nsza - 1])
177 sza_help = photo->
sza[photo->
nsza - 1];
180 double o3c_help = o3c;
181 if (o3c < photo->o3c[0])
182 o3c_help = photo->
o3c[0];
183 else if (o3c > photo->
o3c[photo->
no3c - 1])
184 o3c_help = photo->
o3c[photo->
no3c - 1];
192 const double aux00 =
LIN(photo->
p[ip], rate[ip][isza][io3c],
193 photo->
p[ip + 1], rate[ip + 1][isza][io3c],
195 const double aux01 =
LIN(photo->
p[ip], rate[ip][isza][io3c + 1],
196 photo->
p[ip + 1], rate[ip + 1][isza][io3c + 1],
198 const double aux10 =
LIN(photo->
p[ip], rate[ip][isza + 1][io3c],
199 photo->
p[ip + 1], rate[ip + 1][isza + 1][io3c],
201 const double aux11 =
LIN(photo->
p[ip], rate[ip][isza + 1][io3c + 1],
202 photo->
p[ip + 1], rate[ip + 1][isza + 1][io3c + 1],
205 LIN(photo->
o3c[io3c], aux00, photo->
o3c[io3c + 1], aux01, o3c_help);
207 LIN(photo->
o3c[io3c], aux10, photo->
o3c[io3c + 1], aux11, o3c_help);
209 LIN(photo->
sza[isza], aux0, photo->
sza[isza + 1], aux1, sza_help);
210 return MAX(aux, 0.0);
221 double sec =
FMOD(t, 365.25 * 86400.);
223 sec += 365.25 * 86400.;
231 clim->
tropo[isec][ilat],
233 clim->
tropo[isec][ilat + 1], lat);
235 clim->
tropo[isec + 1][ilat],
237 clim->
tropo[isec + 1][ilat + 1], lat);
247 LOG(1,
"Initialize tropopause data...");
251 double tropo_time[12] = {
252 1209600.00, 3888000.00, 6393600.00,
253 9072000.00, 11664000.00, 14342400.00,
254 16934400.00, 19612800.00, 22291200.00,
255 24883200.00, 27561600.00, 30153600.00
261 const double tropo_lat[73] = {
262 -90, -87.5, -85, -82.5, -80, -77.5, -75, -72.5, -70, -67.5,
263 -65, -62.5, -60, -57.5, -55, -52.5, -50, -47.5, -45, -42.5,
264 -40, -37.5, -35, -32.5, -30, -27.5, -25, -22.5, -20, -17.5,
265 -15, -12.5, -10, -7.5, -5, -2.5, 0, 2.5, 5, 7.5, 10, 12.5,
266 15, 17.5, 20, 22.5, 25, 27.5, 30, 32.5, 35, 37.5, 40, 42.5,
267 45, 47.5, 50, 52.5, 55, 57.5, 60, 62.5, 65, 67.5, 70, 72.5,
268 75, 77.5, 80, 82.5, 85, 87.5, 90
273 const double tropo[12][73] = {
274 {324.1, 325.6, 325, 324.3, 322.5, 319.7, 314, 307.2, 301.8, 299.6,
275 297.1, 292.2, 285.6, 276.1, 264, 248.9, 231.9, 213.5, 194.4,
276 175.3, 157, 140.4, 126.7, 116.3, 109.5, 105.4, 103, 101.4, 100.4,
277 99.69, 99.19, 98.84, 98.56, 98.39, 98.39, 98.42, 98.44, 98.54,
278 98.68, 98.81, 98.89, 98.96, 99.12, 99.65, 101.4, 105.4, 113.5, 128,
279 152.1, 184.7, 214, 234.1, 247.3, 255.8, 262.6, 267.7, 271.7, 275,
280 277.2, 279, 280.1, 280.4, 280.6, 280.1, 279.3, 278.3, 276.8, 275.8,
281 275.3, 275.6, 275.4, 274.1, 273.5},
282 {337.3, 338.7, 337.8, 336.4, 333, 328.8, 321.1, 312.6, 306.6, 303.7,
283 300.2, 293.8, 285.4, 273.8, 259.6, 242.7, 224.4, 205.2, 186, 167.5,
284 150.3, 135, 122.8, 113.9, 108.2, 104.7, 102.5, 101.1, 100.2, 99.42,
285 98.88, 98.52, 98.25, 98.09, 98.07, 98.1, 98.12, 98.2, 98.25, 98.27,
286 98.26, 98.27, 98.36, 98.79, 100.2, 104.2, 113.7, 131.2, 159.5, 193,
287 220.4, 238.1, 250.2, 258.1, 264.7, 269.7, 273.7, 277.3, 280.2, 282.8,
288 284.9, 286.5, 288.1, 288.8, 289, 288.5, 287.2, 286.3, 286.1, 287.2,
289 287.5, 286.2, 285.8},
290 {335, 336, 335.7, 335.1, 332.3, 328.1, 320.6, 311.8, 305.1, 301.9,
291 297.6, 290, 280.4, 268.3, 254.6, 239.6, 223.9, 207.9, 192.2, 176.9,
292 161.7, 146.4, 132.2, 120.6, 112.3, 107.2, 104.3, 102.4, 101.3,
293 100.4, 99.86, 99.47, 99.16, 98.97, 98.94, 98.97, 99, 99.09, 99.2,
294 99.31, 99.35, 99.41, 99.51, 99.86, 101.1, 104.9, 114.3, 131, 156.8,
295 186.3, 209.3, 224.6, 236.8, 246.3, 254.9, 262.3, 268.8, 274.8,
296 279.9, 284.6, 288.6, 291.6, 294.9, 297.5, 299.8, 301.8, 303.1,
297 304.3, 304.9, 306, 306.6, 306.2, 306},
298 {306.2, 306.7, 305.7, 307.1, 307.3, 306.4, 301.8, 296.2, 292.4,
299 290.3, 287.1, 280.9, 273.4, 264.3, 254.1, 242.8, 231, 219, 207.2,
300 195.5, 183.3, 169.7, 154.7, 138.7, 124.1, 113.6, 107.8, 104.7,
301 102.8, 101.7, 100.9, 100.4, 100, 99.79, 99.7, 99.66, 99.68, 99.79,
302 99.94, 100.2, 100.5, 100.9, 101.4, 102.1, 103.4, 107, 115.2, 129.1,
303 148.7, 171, 190.8, 205.6, 218.4, 229.4, 239.6, 248.6, 256.5,
304 263.7, 270.3, 276.6, 282.6, 288.1, 294.5, 300.4, 306.3, 311.4,
305 315.1, 318.3, 320.3, 322.2, 322.8, 321.5, 321.1},
306 {266.5, 264.9, 260.8, 261, 262, 263, 261.3, 259.7, 259.2, 259.8,
307 260.1, 258.6, 256.7, 253.6, 249.5, 243.9, 237.4, 230, 222.1, 213.9,
308 205, 194.4, 180.4, 161.8, 140.7, 122.9, 112.1, 106.7, 104.1, 102.7,
309 101.8, 101.4, 101.1, 101, 101, 101, 101.1, 101.2, 101.5, 101.9,
310 102.4, 103, 103.8, 104.9, 106.8, 110.1, 115.6, 124, 135.2, 148.9,
311 165.2, 181.3, 198, 211.8, 223.5, 233.8, 242.9, 251.5, 259, 266.2,
312 273.1, 279.2, 286.2, 292.8, 299.6, 306, 311.1, 315.5, 318.8, 322.6,
313 325.3, 325.8, 325.8},
314 {220.1, 218.1, 210.8, 207.2, 207.6, 210.5, 211.4, 213.5, 217.3,
315 222.4, 227.9, 232.8, 237.4, 240.8, 242.8, 243, 241.5, 238.6, 234.2,
316 228.5, 221, 210.7, 195.1, 172.9, 147.8, 127.6, 115.6, 109.9, 107.1,
317 105.7, 105, 104.8, 104.8, 104.9, 105, 105.1, 105.3, 105.5, 105.8,
318 106.4, 107, 107.6, 108.1, 108.8, 110, 111.8, 114.2, 117.4, 121.6,
319 127.9, 137.3, 151.2, 169.5, 189, 205.8, 218.9, 229.1, 237.8, 245,
320 251.5, 257.1, 262.3, 268.2, 274, 280.4, 286.7, 292.4, 297.9, 302.9,
321 308.5, 312.2, 313.1, 313.3},
322 {187.4, 184.5, 173.3, 166.1, 165.4, 167.8, 169.6, 173.6, 179.6,
323 187.9, 198.9, 210, 220.5, 229.2, 235.7, 239.9, 241.8, 241.6, 239.6,
324 235.8, 229.4, 218.6, 200.9, 175.9, 149.4, 129.4, 118.3, 113.1,
325 110.8, 109.7, 109.3, 109.4, 109.7, 110, 110.2, 110.4, 110.5, 110.7,
326 111, 111.4, 111.8, 112.1, 112.3, 112.7, 113.2, 113.9, 115, 116.4,
327 117.9, 120.4, 124.1, 130.9, 142.2, 159.6, 179.6, 198.5, 212.9,
328 224.2, 232.7, 239.1, 243.8, 247.7, 252.4, 257.3, 263.2, 269.5,
329 275.4, 281.1, 286.3, 292, 296.3, 298.2, 298.8},
330 {166, 166.4, 155.7, 148.3, 147.1, 149, 152.1, 157, 163.6, 172.4,
331 185.3, 199.2, 212.6, 224, 233.2, 239.6, 243.3, 244.6, 243.6, 240.3,
332 233.9, 222.6, 203.7, 177, 149.5, 129.7, 119, 114, 111.7, 110.7,
333 110.3, 110.3, 110.6, 110.9, 111.1, 111.3, 111.5, 111.6, 111.9,
334 112.2, 112.5, 112.6, 112.8, 113, 113.4, 114, 115.1, 116.5, 118.3,
335 120.9, 124.4, 130.2, 139.4, 154.6, 173.8, 193.1, 208.1, 220.4,
336 230.1, 238.2, 244.7, 249.5, 254.5, 259.3, 264.5, 269.4, 273.7,
337 278.2, 282.6, 287.4, 290.9, 292.5, 293},
338 {171.9, 172.8, 166.2, 162.3, 161.4, 162.5, 165.2, 169.6, 175.3,
339 183.1, 193.8, 205.9, 218.3, 229.6, 238.5, 244.3, 246.9, 246.7,
340 243.8, 238.4, 230.2, 217.9, 199.6, 174.9, 148.9, 129.8, 119.5,
341 114.8, 112.3, 110.9, 110.3, 110.1, 110.2, 110.3, 110.4, 110.5,
342 110.6, 110.8, 111, 111.4, 111.8, 112, 112.2, 112.4, 112.9, 113.6,
343 114.7, 116.3, 118.4, 121.9, 127.1, 136.1, 149.8, 168.4, 186.9,
344 203.3, 217, 229.1, 238.7, 247, 254, 259.3, 264.3, 268.3, 272.5,
345 276.6, 280.4, 284.4, 288.4, 293.3, 297.2, 298.7, 299.1},
346 {191.6, 192.2, 189, 188.1, 190.2, 193.7, 197.8, 202.9, 208.5,
347 215.6, 224.2, 233.1, 241.2, 247.3, 250.8, 251.3, 248.9, 244.2,
348 237.3, 228.4, 217.2, 202.9, 184.5, 162.5, 140.7, 124.8, 116.2,
349 111.8, 109.4, 107.9, 107, 106.7, 106.6, 106.6, 106.7, 106.7,
350 106.8, 107, 107.4, 108, 108.7, 109.3, 109.8, 110.4, 111.2,
351 112.4, 114.2, 116.9, 121.1, 127.9, 139.3, 155.2, 173.6, 190.7,
352 206.1, 220.1, 232.3, 243, 251.8, 259.2, 265.7, 270.6, 275.3,
353 279.3, 283.3, 286.9, 289.7, 292.8, 296.1, 300.5, 303.9, 304.8,
355 {241.5, 239.6, 236.8, 237.4, 239.4, 242.3, 244.2, 246.4, 249.2,
356 253.6, 258.6, 262.7, 264.8, 264.2, 260.6, 254.1, 245.5, 235.3,
357 223.9, 211.7, 198.3, 183.1, 165.6, 147.1, 130.5, 118.7, 111.9,
358 108.1, 105.8, 104.3, 103.4, 102.8, 102.5, 102.4, 102.5, 102.5,
359 102.5, 102.7, 103.1, 103.8, 104.6, 105.4, 106.1, 107, 108.2,
360 109.9, 112.8, 117.5, 126, 140.4, 161, 181.9, 201.2, 216.8, 230.4,
361 241.8, 251.4, 259.9, 266.9, 272.8, 277.4, 280.4, 282.9, 284.6,
362 286.1, 287.4, 288.3, 289.5, 290.9, 294.2, 296.9, 297.5, 297.6},
363 {301.2, 300.3, 296.6, 295.4, 295, 294.3, 291.2, 287.4, 284.9, 284.7,
364 284.1, 281.5, 277.1, 270.4, 261.7, 250.6, 237.6, 223.1, 207.9, 192,
365 175.8, 158.8, 142.1, 127.6, 116.8, 109.9, 106, 103.6, 102.1, 101.1,
366 100.4, 99.96, 99.6, 99.37, 99.32, 99.32, 99.31, 99.46, 99.77, 100.2,
367 100.7, 101.3, 101.8, 102.7, 104.1, 106.8, 111.9, 121, 136.7, 160,
368 186.9, 209.9, 228.1, 241.2, 251.5, 259.5, 265.7, 270.9, 274.8, 278,
369 280.3, 281.8, 283, 283.3, 283.7, 283.8, 283, 282.2, 281.2, 281.4,
372 memcpy(clim->
tropo, tropo,
sizeof(clim->
tropo));
375 double tropomin = 1e99, tropomax = -1e99;
377 for (
int iy = 0; iy < clim->
tropo_nlat; iy++) {
378 tropomin =
MIN(tropomin, clim->
tropo[it][iy]);
379 tropomax =
MAX(tropomax, clim->
tropo[it][iy]);
384 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
388 LOG(2,
"Latitudes: %g, %g ... %g deg",
391 LOG(2,
"Tropopause altitude range: %g ... %g hPa",
Z(tropomax),
393 LOG(2,
"Tropopause pressure range: %g ... %g hPa", tropomin, tropomax);
403 if (t <= ts->time[0])
410 ts->
time[idx + 1], ts->
vmr[idx + 1], t);
423 double sec =
FMOD(t, 365.25 * 86400.);
425 sec += 365.25 * 86400.;
429 if (p < zm->p[zm->
np - 1])
430 p_help = zm->
p[zm->
np - 1];
431 else if (p > zm->
p[0])
435 double lat_help = lat;
436 if (lat < zm->lat[0])
437 lat_help = zm->
lat[0];
438 else if (lat > zm->
lat[zm->
nlat - 1])
439 lat_help = zm->
lat[zm->
nlat - 1];
447 const double aux00 =
LIN(zm->
p[ip], zm->
vmr[isec][ip][ilat],
448 zm->
p[ip + 1], zm->
vmr[isec][ip + 1][ilat],
450 const double aux01 =
LIN(zm->
p[ip], zm->
vmr[isec][ip][ilat + 1],
451 zm->
p[ip + 1], zm->
vmr[isec][ip + 1][ilat + 1],
453 const double aux10 =
LIN(zm->
p[ip], zm->
vmr[isec + 1][ip][ilat],
454 zm->
p[ip + 1], zm->
vmr[isec + 1][ip + 1][ilat],
456 const double aux11 =
LIN(zm->
p[ip], zm->
vmr[isec + 1][ip][ilat + 1],
457 zm->
p[ip + 1], zm->
vmr[isec + 1][ip + 1][ilat + 1],
460 LIN(zm->
lat[ilat], aux00, zm->
lat[ilat + 1], aux01, lat_help);
462 LIN(zm->
lat[ilat], aux10, zm->
lat[ilat + 1], aux11, lat_help);
463 const double aux =
LIN(zm->
time[isec], aux0, zm->
time[isec + 1], aux1, sec);
464 return MAX(aux, 0.0);
475 const int decompress,
479 const size_t nx = (size_t) met->
nx;
480 const size_t ny = (
size_t) met->
ny;
481 const size_t np = (size_t) met->
np;
482 const size_t nxy = nx * ny;
488 double lon[
EX], lat[
EY];
489 for (
size_t ix = 0; ix < nx; ix++)
490 lon[ix] = 360. * (
double) ix / ((double) nx - 1.);
491 for (
size_t iy = 0; iy < ny; iy++)
492 lat[iy] = 90. - 180. * (
double) iy / ((double) ny - 1.);
495 const char domain[] =
"[0.0, 360.0]x[-90.0, 90.0]";
499 cms_param_t *cms_param
500 = cms_set_parameters(nx, ny, max_level_grid, Nd0_x, Nd0_y, domain);
503 double cr = 0, t_coars = 0, t_eval = 0;
510 for (
size_t ip = 0; ip < np; ip++) {
513 cms_module_t *cms_ptr = cms_init(cms_param);
518 cms_sol = cms_read_zstd_sol(cms_ptr, inout);
520 cms_sol = cms_read_sol(cms_ptr, inout);
523 const double t0 = omp_get_wtime();
524#pragma omp parallel for collapse(2) default(shared)
525 for (
size_t ix = 0; ix < nx; ix++)
526 for (
size_t iy = 0; iy < ny; iy++) {
528 const double x[] = { lon[ix], lat[iy] };
529 cms_eval(cms_ptr, cms_sol, x, &val);
530 array[
ARRAY_3D(ix, iy, ny, ip, np)] = (float) val;
532 t_eval += omp_get_wtime() - t0;
535 cr += 1.0 / cms_compression_rate(cms_ptr, cms_sol);
538 cms_delete_sol(cms_sol);
539 cms_delete_module(cms_ptr);
543 LOG(2,
"Read 3-D variable: %s"
544 " (CMS, RATIO=%g, BPV=%g, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
545 varname, (
double) np / cr, 32. * cr / (
double) np, t_eval,
553 cms_module_t *cms_ptr[
EP];
554 cms_sol_t *cms_sol[
EP];
555 double ratio[
EP], t_coars_level[
EP], t_eval_level[
EP];
559 ? (size_t) omp_get_max_threads()
561 for (
size_t ip0 = 0; ip0 < np; ip0 += dip) {
564 double t0 = omp_get_wtime();
567#pragma omp parallel for default(shared)
568 for (
size_t ip = ip0; ip <
MIN(ip0 + dip, np); ip++) {
569 const double t1 = omp_get_wtime();
573 ALLOC(tmp_arr,
float,
577 for (
size_t ix = 0; ix < nx; ++ix)
578 for (
size_t iy = 0; iy < ny; ++iy)
580 array[
ARRAY_3D(ix, iy, ny, ip, np)];
583 cms_ptr[ip] = cms_init(cms_param);
587 cms_read_arr_new(cms_ptr[ip], tmp_arr, lon, lat,
589 t_coars_level[ip] = omp_get_wtime() - t1;
596 t_coars += (omp_get_wtime() - t0);
599 for (
size_t ip = ip0; ip <
MIN(ip0 + dip, np); ip++) {
602 float *tmp_cms, *tmp_org;
603 ALLOC(tmp_cms,
float,
605 ALLOC(tmp_org,
float,
609 t0 = omp_get_wtime();
612#pragma omp parallel for collapse(2) default(shared)
613 for (
size_t ix = 0; ix < nx; ix++)
614 for (
size_t iy = 0; iy < ny; iy++) {
615 const size_t idx =
ARRAY_2D(ix, iy, ny);
616 const double x[] = { lon[ix], lat[iy] };
618 cms_eval(cms_ptr[ip], cms_sol[ip], x, &val);
619 tmp_cms[idx] = (float) val;
620 tmp_org[idx] = array[
ARRAY_3D(ix, iy, ny, ip, np)];
624 t_eval_level[ip] = omp_get_wtime() - t0;
625 t_eval += t_eval_level[ip];
628 ratio[ip] = cms_compression_rate(cms_ptr[ip], cms_sol[ip]);
629 cr += 1.0 / ratio[ip];
634 ratio[ip], 32. / ratio[ip],
635 t_coars_level[ip], t_eval_level[ip], nxy,
636 nxy *
sizeof(
float), tmp_org, tmp_cms);
640 cms_save_zstd_sol(cms_sol[ip], inout, 3);
642 cms_save_sol(cms_sol[ip], inout);
645 cms_delete_sol(cms_sol[ip]);
646 cms_delete_module(cms_ptr[ip]);
653 LOG(2,
"Write 3-D variable: %s"
654 " (CMS, RATIO=%g, BPV=%g, T_COMP=%g s, V_COMP=%g MiB/s,"
655 " T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
656 varname, (
double) np / cr, 32. * cr / (
double) np, t_coars,
662 cms_delete_param(cms_param);
677 const double t_decomp,
683 static FILE *last_out = NULL;
684 static char last_var[
LEN] =
"";
687 double mean_err = 0.0, stddev_err = 0.0;
688 double nrmse = NAN, mean_orig = 0.0, orig_range = 0.0, rho = NAN;
690 double sum_err = 0.0, sumsq_err = 0.0;
691 double sum_orig = 0.0, sum_cmp = 0.0;
692 double sumsq_orig = 0.0, sumsq_cmp = 0.0, sum_org_cmp = 0.0;
694 double min_orig = 0.0, max_orig = 0.0;
695 double min_err = 0.0, max_err = 0.0;
698 for (
size_t i = 0; i < n; i++) {
699 const double o = (double) org[i];
700 const double c = (double) cmp[i];
701 const double e = c - o;
710 sum_org_cmp += o * c;
712 if (e < min_err || i == 0)
714 if (e > max_err || i == 0)
717 if (o < min_orig || i == 0)
719 if (o > max_orig || i == 0)
724 mean_err = sum_err / (double) n;
725 mean_orig = sum_orig / (double) n;
726 orig_range = max_orig - min_orig;
729 const double var_err =
730 (sumsq_err - (sum_err * sum_err) / (
double) n) / (
double) n;
731 stddev_err = sqrt(var_err > 0.0 ? var_err : 0.0);
734 nrmse = (orig_range > 0.0)
735 ? sqrt(sumsq_err / (
double) n) / orig_range : NAN;
738 const double nn = (double) n;
739 const double cov = sum_org_cmp - sum_orig * sum_cmp / nn;
740 const double var_orig = sumsq_orig - sum_orig * sum_orig / nn;
741 const double var_cmp = sumsq_cmp - sum_cmp * sum_cmp / nn;
742 const double denom = sqrt(var_orig * var_cmp);
743 rho = denom > 0.0 ? cov / denom : NAN;
746 if (out != last_out) {
752 if (last_var[0] !=
'\0' && strcmp(last_var, varname) != 0)
754 snprintf(last_var,
LEN,
"%s", varname);
758 "%s %s %lu %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g\n",
759 codec, varname, (
unsigned long) lev, plev, ratio, bpv, rho,
760 mean_err, stddev_err, min_err, max_err, mean_orig, orig_range,
772 const float *org_all,
773 const float *cmp_all,
779 const double t_decomp,
780 const size_t nbytes) {
786 float *tmp_org, *tmp_cmp;
787 ALLOC(tmp_org,
float,
789 ALLOC(tmp_cmp,
float,
792 for (
size_t lev = 0; lev < nz; lev++) {
795#pragma omp parallel for default(shared)
796 for (
size_t ixy = 0; ixy < nxy; ixy++) {
797 tmp_org[ixy] = org_all[ixy * nz + lev];
798 tmp_cmp[ixy] = cmp_all[ixy * nz + lev];
803 t_comp, t_decomp, nxy, nbytes, tmp_org, tmp_cmp);
821 for (
size_t iz = 0; iz < nz; iz++) {
827 for (
size_t ixy = 1; ixy < nxy; ixy++)
828 for (
size_t iz = 0; iz < nz; iz++) {
829 const double value = array[ixy * nz + iz];
837 for (
size_t iz = 0; iz < nz; iz++) {
838 const double range = scl[iz] - off[iz];
839 const double ref = fmax(1.0, fmax(fabs(off[iz]), fabs(scl[iz])));
840 scl[iz] = !(range > 1e-12 * ref) ? 0.0 : range;
844#pragma omp parallel for default(shared)
845 for (
size_t ixy = 0; ixy < nxy; ixy++)
846 for (
size_t iz = 0; iz < nz; iz++)
848 array[ixy * nz + iz] =
849 (float) ((array[ixy * nz + iz] - off[iz]) / scl[iz]);
851 array[ixy * nz + iz] = 0.0f;
864#pragma omp parallel for default(shared)
865 for (
size_t ixy = 0; ixy < nxy; ixy++)
866 for (
size_t iz = 0; iz < nz; iz++)
868 array[ixy * nz + iz] =
869 (float) (array[ixy * nz + iz] * scl[iz] + off[iz]);
871 array[ixy * nz + iz] = (float) off[iz];
890 if (enabled < 0 || enabled > 1)
891 ERRMSG(
"Invalid stored MET_LOSSY_SCALE flag!");
949ZSTD_CCtx *compress_zstd_create_cctx(
951 const int nworkers) {
954 ZSTD_CCtx *cctx = ZSTD_createCCtx();
956 ERRMSG(
"Cannot create ZSTD context!");
958 if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel,
960 ERRMSG(
"Cannot set ZSTD compression level!");
962 if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, nworkers)))
963 ERRMSG(
"Cannot set ZSTD worker count!");
972 const char *varname) {
974 static const char *
const names[] = {
975 "Z",
"T",
"U",
"V",
"W",
"PV",
"H2O",
"O3",
976 "LWC",
"RWC",
"IWC",
"SWC",
"CC"
979 for (
size_t i = 0; i <
sizeof(names) /
sizeof(names[0]); i++)
980 if (strcasecmp(varname, names[i]) == 0)
983 ERRMSG(
"Unknown meteorological variable name!");
993 const int decompress,
997 const size_t nxy = (size_t) met->
nx * (
size_t) met->
ny;
998 const size_t nz = (size_t) met->
np;
999 const size_t n = nxy * nz;
1000 const size_t nbytes = n *
sizeof(
float);
1001 const size_t pck_bytes = n *
sizeof(uint16_t);
1003 double vmin[
EP], vmax[
EP], off[
EP], scl[
EP];
1007 const size_t payload_len = 2 * nz *
sizeof(double) + pck_bytes;
1008 size_t stored_len = payload_len;
1009 const char *codec_info = ctl->
met_pck_zstd ?
"PCK+ZSTD" :
"PCK";
1012 ALLOC(sarray, uint16_t, n);
1016 double t_zstd = 0.0;
1021 uint64_t magic, pck_zstd_magic = UINT64_C(0x50434b5a53544431);
1022 unsigned char *compr = NULL, *payload = NULL;
1025 FREAD(&magic, uint64_t, 1, inout);
1026 if (magic != pck_zstd_magic)
1027 ERRMSG(
"PCK+ZSTD magic mismatch! Check MET_PCK_ZSTD and file type.");
1030 FREAD(&stored_len,
size_t,
1033 ALLOC(compr,
unsigned char,
1035 FREAD(compr,
unsigned char,
1038 ALLOC(payload,
unsigned char,
1040 const double t0_decomp = omp_get_wtime();
1041 const size_t out_len =
1042 ZSTD_decompress(payload, payload_len, compr, stored_len);
1043 t_zstd = omp_get_wtime() - t0_decomp;
1044 if (ZSTD_isError(out_len) || out_len != payload_len)
1045 ERRMSG(
"PCK ZSTD decompression failed or size mismatch!");
1048 memcpy(scl, payload, nz *
sizeof(
double));
1049 memcpy(off, payload + nz *
sizeof(
double), nz *
sizeof(
double));
1050 memcpy(sarray, payload + 2 * nz *
sizeof(
double), pck_bytes);
1056 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
1066 FREAD(sarray, uint16_t, n, inout);
1070 const double t0 = omp_get_wtime();
1073#pragma omp parallel for default(shared)
1074 for (
size_t ixy = 0; ixy < nxy; ixy++)
1075 for (
size_t iz = 0; iz < nz; iz++)
1076 array[ixy * nz + iz]
1077 = (
float) (sarray[ixy * nz + iz] * scl[iz] + off[iz]);
1080 const double t_decomp = t_zstd + omp_get_wtime() - t0;
1083 LOG(2,
"Read 3-D variable: %s"
1084 " (%s, RATIO=%g, BPV=%g, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1092 float *tmp_org, *tmp_pck;
1093 double t_comp_sum = 0, t_decomp_sum = 0, t_zstd = 0, t_zstd_decomp = 0;
1094 double t_comp_level[
EP], t_decomp_level[
EP];
1097 ALLOC(tmp_org,
float,
1099 ALLOC(tmp_pck,
float,
1103 for (
size_t iz = 0; iz < nz; iz++) {
1104 vmin[iz] = array[iz];
1105 vmax[iz] = array[iz];
1107 for (
size_t ixy = 1; ixy < nxy; ixy++)
1108 for (
size_t iz = 0; iz < nz; iz++) {
1109 if (array[ixy * nz + iz] < vmin[iz])
1110 vmin[iz] = array[ixy * nz + iz];
1111 if (array[ixy * nz + iz] > vmax[iz])
1112 vmax[iz] = array[ixy * nz + iz];
1116 for (
size_t iz = 0; iz < nz; iz++) {
1117 scl[iz] = (vmax[iz] - vmin[iz]) / 65533.;
1122 for (
size_t iz = 0; iz < nz; iz++) {
1123 const double t0 = omp_get_wtime();
1125#pragma omp parallel for default(shared)
1126 for (
size_t ixy = 0; ixy < nxy; ixy++)
1128 sarray[ixy * nz + iz] =
1129 (uint16_t) ((array[ixy * nz + iz] - off[iz]) / scl[iz] + .5);
1131 sarray[ixy * nz + iz] = 0;
1133 t_comp_level[iz] = omp_get_wtime() - t0;
1134 t_comp_sum += t_comp_level[iz];
1136 const double t1 = omp_get_wtime();
1138#pragma omp parallel for default(shared)
1139 for (
size_t ixy = 0; ixy < nxy; ixy++) {
1140 tmp_org[ixy] = array[ixy * nz + iz];
1141 tmp_pck[ixy] = (float) (sarray[ixy * nz + iz] * scl[iz] + off[iz]);
1144 t_decomp_level[iz] = omp_get_wtime() - t1;
1145 t_decomp_sum += t_decomp_level[iz];
1151 uint64_t pck_zstd_magic = UINT64_C(0x50434b5a53544431);
1152 unsigned char *payload = NULL, *payload_chk = NULL;
1153 void *stored_data = NULL;
1156 ALLOC(payload,
unsigned char,
1158 memcpy(payload, scl, nz *
sizeof(
double));
1159 memcpy(payload + nz *
sizeof(
double), off, nz *
sizeof(
double));
1160 memcpy(payload + 2 * nz *
sizeof(
double), sarray, pck_bytes);
1161 const size_t dst_cap = ZSTD_compressBound(payload_len);
1162 ALLOC(stored_data,
char,
1166 const double t0_comp = omp_get_wtime();
1168 ZSTD_compress2(cctx, stored_data, dst_cap, payload, payload_len);
1169 t_zstd = omp_get_wtime() - t0_comp;
1170 ZSTD_freeCCtx(cctx);
1171 if (ZSTD_isError(stored_len))
1172 ERRMSG(
"PCK ZSTD compression failed!");
1175 ALLOC(payload_chk,
unsigned char,
1177 const double t0_decomp2 = omp_get_wtime();
1178 const size_t out_len2 =
1179 ZSTD_decompress(payload_chk, payload_len, stored_data, stored_len);
1180 t_zstd_decomp = omp_get_wtime() - t0_decomp2;
1181 if (ZSTD_isError(out_len2) || out_len2 != payload_len)
1182 ERRMSG(
"PCK ZSTD decompression failed or size mismatch!");
1189 FWRITE(&pck_zstd_magic, uint64_t, 1, inout);
1190 FWRITE(&stored_len,
size_t,
1193 FWRITE(stored_data,
unsigned char,
1200 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
1211 FWRITE(sarray, uint16_t, n, inout);
1217 const double t_comp = t_comp_sum + t_zstd;
1218 const double t_decomp = t_decomp_sum + t_zstd_decomp;
1221 LOG(2,
"Write 3-D variable: %s"
1222 " (%s, RATIO=%g, BPV=%g, T_COMP=%g s, V_COMP=%g MiB/s,"
1223 " T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1224 varname, codec_info, ratio_out, bpv_out, t_comp,
1230 const double t_zstd_level = t_zstd / (double) nz;
1231 const double t_zstd_decomp_level = t_zstd_decomp / (double) nz;
1232 const char *codec = ctl->
met_pck_zstd ?
"PCKZSTD" :
"PCK";
1233 for (
size_t iz = 0; iz < nz; iz++) {
1234#pragma omp parallel for default(shared)
1237 for (
size_t ixy = 0; ixy < nxy; ixy++) {
1238 tmp_org[ixy] = array[ixy * nz + iz];
1239 tmp_pck[ixy] = (float) (sarray[ixy * nz + iz] * scl[iz] + off[iz]);
1245 t_comp_level[iz] + t_zstd_level,
1246 t_decomp_level[iz] + t_zstd_decomp_level,
1247 nxy, nxy *
sizeof(
float), tmp_org, tmp_pck);
1266 const char *varname,
1268 const int decompress,
1277 ERRMSG(
"Exactly one of precision or tolerance must be set for SZ3!");
1279 size_t r1 = (size_t) met->
np, r2 = (
size_t) met->
ny, r3 = (size_t) met->
nx,
1280 outSize = 0, total_elems = r1 * r2 * r3;
1282 unsigned char *bytes = NULL;
1283 double *scale_off = NULL, *scale_scl = NULL;
1284 float *orig_all = NULL;
1285 char codec_info[
LEN];
1291 const int stored_lossy_scale =
1297 FREAD(&sz3size,
size_t,
1302 FREAD(bytes,
unsigned char,
1307 const double t0 = omp_get_wtime();
1308 void *outData = SZ_decompress(SZ_FLOAT, bytes, sz3size, 0, 0, r3, r2, r1);
1310 ERRMSG(
"Decompression failed!");
1312 memcpy(array, outData, total_elems *
sizeof(
float));
1315 if (stored_lossy_scale > 0)
1317 const double t_decomp = omp_get_wtime() - t0;
1323 const double ratio =
COMPRESS_RATIO(total_elems *
sizeof(
float), sz3size);
1325 snprintf(codec_info,
LEN,
"SZ3, PREC=%d, TOL=%g, SCALE=%d",
1327 stored_lossy_scale);
1330 LOG(2,
"Read 3-D variable: %s"
1331 " (%s, RATIO=%g, BPV=%g, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1332 varname, codec_info, ratio, bpv, t_decomp,
1340 const int errBoundMode = (ctl->
met_sz3_prec[metvar] > 0) ? REL : ABS;
1341 const double absBound =
1342 (errBoundMode == ABS) ? ctl->
met_sz3_tol[metvar] : 0.0;
1343 const double relBound =
1344 (errBoundMode == REL) ? pow(2.0, -(
double) ctl->
met_sz3_prec[metvar])
1346 const size_t raw_size = total_elems *
sizeof(float);
1350 ALLOC(orig_all,
float,
1352 memcpy(orig_all, array, total_elems *
sizeof(
float));
1357 r2 * r3, r1, &scale_off, &scale_scl);
1360 const double t0 = omp_get_wtime();
1361 bytes = SZ_compress_args(SZ_FLOAT, array, &outSize,
1362 errBoundMode, absBound, relBound, 0.0,
1364 const double t_comp = omp_get_wtime() - t0;
1365 if (!bytes || outSize == 0)
1366 ERRMSG(
"Compression failed!");
1372 FWRITE(bytes,
unsigned char,
1376 snprintf(codec_info,
LEN,
"SZ3, PREC=%d, TOL=%g, SCALE=%d",
1381 double t_decomp = NAN;
1383 unsigned char *bytes_copy;
1385 const size_t nxy = r2 * r3;
1388 ALLOC(bytes_copy,
unsigned char,
1390 memcpy(bytes_copy, bytes, outSize);
1392 const double t1 = omp_get_wtime();
1393 void *decData = SZ_decompress(SZ_FLOAT, bytes_copy, outSize, 0, 0, r3,
1395 t_decomp = omp_get_wtime() - t1;
1397 ERRMSG(
"Decompression failed!");
1400 ALLOC(tmp_all,
float,
1402 memcpy(tmp_all, decData, total_elems *
sizeof(
float));
1410 (orig_all ? orig_all : array), tmp_all, nxy, r1,
1411 ratio, bpv, t_comp, t_decomp, raw_size);
1419 LOG(2,
"Write 3-D variable: %s"
1420 " (%s, RATIO=%g, BPV=%g, T_COMP=%g s, V_COMP=%g MiB/s,"
1421 " T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1422 varname, codec_info, ratio, bpv, t_comp,
1430 LOG(2,
"Write 3-D variable: %s"
1431 " (%s, RATIO=%g, BPV=%g, T_COMP=%g s, V_COMP=%g MiB/s)",
1432 varname, codec_info, ratio, bpv, t_comp,
1452 const char *varname,
1454 const int decompress,
1462 const size_t snx = (size_t) met->
np;
1463 const size_t sny = (
size_t) met->
ny;
1464 const size_t snz = (size_t) met->
nx;
1465 const size_t n = snx * sny * snz;
1466 const size_t raw_size = n *
sizeof(
float);
1467 const zfp_type type = zfp_type_float;
1468 zfp_field *field = zfp_field_3d(array, type, snx, sny, snz);
1471 zfp_stream *zfp = zfp_stream_open(NULL);
1473 ERRMSG(
"Failed to allocate zfp structures!");
1476 int actual_prec = 0;
1477 double actual_tol = 0;
1480 ERRMSG(
"Exactly one of precision or tolerance must be set for zfp!");
1482 actual_prec = (int) zfp_stream_set_precision(zfp, (
unsigned int)
1485 actual_tol = zfp_stream_set_accuracy(zfp, ctl->
met_zfp_tol[metvar]);
1488 const size_t bufsize = zfp_stream_maximum_size(zfp, field);
1494 bitstream *stream = stream_open(buffer, bufsize);
1495 zfp_stream_set_bit_stream(zfp, stream);
1496 zfp_stream_rewind(zfp);
1500 double *scale_off = NULL, *scale_scl = NULL;
1501 char codec_info[
LEN];
1505 const int stored_lossy_scale =
1508 FREAD(&zfpsize,
size_t,
1511 if (zfpsize > bufsize)
1512 ERRMSG(
"Compressed data size exceeds allocated buffer!");
1513 FREAD(buffer,
unsigned char,
1518 const double t0 = omp_get_wtime();
1519 if (!zfp_decompress(zfp, field))
1520 ERRMSG(
"Decompression failed!");
1523 if (stored_lossy_scale > 0)
1525 const double t_decomp = omp_get_wtime() - t0;
1528 snprintf(codec_info,
LEN,
"ZFP, PREC=%d, TOL=%g, SCALE=%d",
1529 actual_prec, actual_tol, stored_lossy_scale);
1532 LOG(2,
"Read 3-D variable: %s"
1533 " (%s, RATIO=%g, BPV=%g, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1534 varname, codec_info, ratio, bpv, t_decomp,
COMPRESS_SPEED(raw_size,
1540 float *tmp_all, *orig_all = NULL;
1541 const size_t nxy = sny * snz;
1545 ALLOC(orig_all,
float,
1547 memcpy(orig_all, array, raw_size);
1552 nxy, snx, &scale_off, &scale_scl);
1555 ALLOC(tmp_all,
float,
1559 const double t0 = omp_get_wtime();
1560 zfpsize = zfp_compress(zfp, field);
1561 const double t_comp = omp_get_wtime() - t0;
1563 ERRMSG(
"Compression failed!");
1569 FWRITE(buffer,
unsigned char,
1575 zfp_field *dec_field = zfp_field_3d(tmp_all, type, snx, sny, snz);
1577 ERRMSG(
"Failed to allocate zfp structures!");
1580 const double t1 = omp_get_wtime();
1581 zfp_stream_rewind(zfp);
1582 if (!zfp_decompress(zfp, dec_field))
1583 ERRMSG(
"Decompression failed!");
1586 const double t_decomp = omp_get_wtime() - t1;
1591 (orig_all ? orig_all : array), tmp_all, nxy, snx,
1592 ratio, bpv, t_comp, t_decomp, raw_size);
1594 snprintf(codec_info,
LEN,
"ZFP, PREC=%d, TOL=%g, SCALE=%d",
1598 LOG(2,
"Write 3-D variable: %s"
1599 " (%s, RATIO=%g, BPV=%g, T_COMP=%g s, V_COMP=%g MiB/s,"
1600 " T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1601 varname, codec_info, ratio, bpv, t_comp,
COMPRESS_SPEED(raw_size,
1608 zfp_field_free(dec_field);
1616 zfp_field_free(field);
1617 stream_close(stream);
1618 zfp_stream_close(zfp);
1629 const char *varname,
1631 const int decompress,
1636 const size_t nxy = (size_t) met->
nx * (
size_t) met->
ny;
1637 const size_t nz = (size_t) met->
np;
1638 const size_t n = nxy * nz, uncomprLen = n *
sizeof(
float);
1639 size_t compsize, comprLen = ZSTD_compressBound(uncomprLen);
1642 char *compr, *uncompr = (
char *) array;
1643 char codec_info[
LEN];
1651 FREAD(&comprLen,
size_t,
1654 FREAD(compr,
unsigned char,
1659 const double t0 = omp_get_wtime();
1660 compsize = ZSTD_decompress(uncompr, uncomprLen, compr, comprLen);
1661 const double t_decomp = omp_get_wtime() - t0;
1662 if (ZSTD_isError(compsize) || compsize != uncomprLen)
1663 ERRMSG(
"Decompression failed or size mismatch!");
1669 LOG(2,
"Read 3-D variable: %s"
1670 " (%s, RATIO=%g, BPV=%g, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1671 varname, codec_info, ratio, bpv, t_decomp,
COMPRESS_SPEED(uncomprLen,
1681 ALLOC(tmp_all,
float,
1688 const double t0 = omp_get_wtime();
1689 compsize = ZSTD_compress2(cctx, compr, comprLen, uncompr, uncomprLen);
1690 const double t_comp = omp_get_wtime() - t0;
1691 if (ZSTD_isError(compsize)) {
1692 ZSTD_freeCCtx(cctx);
1693 ERRMSG(
"Compression failed!");
1697 FWRITE(&compsize,
size_t,
1700 FWRITE(compr,
unsigned char,
1706 const double t1 = omp_get_wtime();
1707 const size_t decomp_size = ZSTD_decompress(tmp_all, uncomprLen, compr,
1709 const double t_decomp = omp_get_wtime() - t1;
1710 if (ZSTD_isError(decomp_size) || decomp_size != uncomprLen)
1711 ERRMSG(
"Decompression failed or size mismatch!");
1716 nxy, nz, ratio, bpv, t_comp, t_decomp, uncomprLen);
1718 snprintf(codec_info,
LEN,
"ZSTD, LEVEL=%d, NWORKERS=%d",
1722 LOG(2,
"Write 3-D variable: %s"
1723 " (%s, RATIO=%g, BPV=%g, T_COMP=%g s, V_COMP=%g MiB/s,"
1724 " T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1725 varname, codec_info, ratio, bpv, t_comp,
COMPRESS_SPEED(uncomprLen,
1730 ZSTD_freeCCtx(cctx);
1745 const char *varname,
1747 const int decompress,
1752 const size_t nxy = (size_t) met->
nx * (
size_t) met->
ny;
1753 const size_t nz = (size_t) met->
np;
1754 const size_t n = nxy * nz;
1755 const size_t uncomprLen = n *
sizeof(
float);
1756 if (uncomprLen > (
size_t) INT_MAX)
1757 ERRMSG(
"LZ4 input buffer exceeds INT_MAX!");
1758 const int uncomprLenInt = (int) uncomprLen;
1760 const int comprCapInt = LZ4_compressBound(uncomprLenInt);
1761 if (comprCapInt <= 0)
1762 ERRMSG(
"Cannot determine LZ4 compression bound!");
1763 size_t comprLen = (size_t) comprCapInt;
1766 char *compr, *uncompr = (
char *) array;
1767 char codec_info[
LEN];
1770 snprintf(codec_info,
LEN,
"LZ4, ACCEL=%d", accel);
1776 FREAD(&comprLen,
size_t,
1779 if (comprLen > (
size_t) INT_MAX)
1780 ERRMSG(
"LZ4 compressed buffer exceeds INT_MAX!");
1781 FREAD(compr,
unsigned char,
1786 const double t0 = omp_get_wtime();
1787 const int decomp_size =
1788 LZ4_decompress_safe(compr, uncompr, (
int) comprLen, uncomprLenInt);
1789 const double t_decomp = omp_get_wtime() - t0;
1790 if (decomp_size != uncomprLenInt)
1791 ERRMSG(
"Decompression failed or size mismatch!");
1796 LOG(2,
"Read 3-D variable: %s"
1797 " (%s, RATIO=%g, BPV=%g, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1798 varname, codec_info, ratio, bpv, t_decomp,
COMPRESS_SPEED(uncomprLen,
1807 ALLOC(tmp_all,
float,
1811 const double t0 = omp_get_wtime();
1812 const int compsizeInt =
1813 LZ4_compress_fast(uncompr, compr, uncomprLenInt, comprCapInt, accel);
1814 const double t_comp = omp_get_wtime() - t0;
1815 if (compsizeInt <= 0)
1816 ERRMSG(
"Compression failed!");
1817 const size_t compsize = (size_t) compsizeInt;
1820 FWRITE(&compsize,
size_t,
1823 FWRITE(compr,
unsigned char,
1828 const double t1 = omp_get_wtime();
1829 const int decomp_size =
1830 LZ4_decompress_safe(compr, (
char *) tmp_all, compsizeInt,
1832 const double t_decomp = omp_get_wtime() - t1;
1833 if (decomp_size != uncomprLenInt)
1834 ERRMSG(
"Decompression failed or size mismatch!");
1839 nxy, nz, ratio, bpv, t_comp, t_decomp, uncomprLen);
1842 LOG(2,
"Write 3-D variable: %s"
1843 " (%s, RATIO=%g, BPV=%g, T_COMP=%g s, V_COMP=%g MiB/s,"
1844 " T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1845 varname, codec_info, ratio, bpv, t_comp,
COMPRESS_SPEED(uncomprLen,
1865 const double D = sec / 86400 - 0.5;
1868 const double g =
DEG2RAD(357.529 + 0.98560028 * D);
1869 const double q = 280.459 + 0.98564736 * D;
1870 const double L =
DEG2RAD(q + 1.915 * sin(g) + 0.020 * sin(2 * g));
1873 const double e =
DEG2RAD(23.439 - 0.00000036 * D);
1876 const double sindec = sin(e) * sin(L);
1879 const double ra = atan2(cos(e) * sin(L), cos(L));
1882 const double GMST = 18.697374558 + 24.06570982441908 * D;
1885 const double LST = GMST + lon / 15;
1888 const double h = LST / 12 * M_PI - ra;
1891 const double lat_help =
DEG2RAD(lat);
1894 return sin(lat_help) * sindec + cos(lat_help) * sqrt(1 -
1895 SQR(sindec)) * cos(h);
1907 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
1908 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
1911 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
1912 *doy = d0l[mon - 1] + day - 1;
1914 *doy = d0[mon - 1] + day - 1;
1923static int dd_particle_bytes;
1924static unsigned long long dd_sent, dd_intra, dd_inter;
1938 MPI_Comm_rank(MPI_COMM_WORLD, &
rank);
1947 const int ix0 = zonal_rank * nx_block;
1948 const int iy0 = merid_rank * ny_block;
1950 const int ix1 = ix0 + nx_block
1954 const int iy1 = iy0 + ny_block
1960#pragma acc update device(dd->nx_glob, dd->ny_glob, \
1961 dd->lon_glob[:dd->nx_glob], \
1962 dd->lat_glob[:dd->ny_glob])
1963#pragma acc data present(atm, ctl, dd)
1964#pragma acc parallel loop independent gang vector
1966 for (
int ip = 0; ip < atm->
np; ip++) {
1973 double lon = atm->
lon[ip];
1974 double lat = atm->
lat[ip];
1980 const int inside = (ix >= ix0 && ix < ix1 && iy >= iy0 && iy < iy1);
2015 MPI_Comm_rank(MPI_COMM_WORLD, &
rank);
2019#pragma acc enter data create(npart, particles[:npart])
2020#pragma acc update device(npart, particles[:npart])
2021#pragma acc parallel loop present(atm, ctl, particles, cache, npart)
2023 for (
int ip = atm->
np; ip < atm->np + npart; ip++)
2028 particles[ip - atm->
np].
time = atm->
time[ip];
2029 particles[ip - atm->
np].
lon = atm->
lon[ip];
2030 particles[ip - atm->
np].
lat = atm->
lat[ip];
2031 particles[ip - atm->
np].
p = atm->
p[ip];
2032 for (
int iq = 0; iq < ctl->
nq; iq++)
2033 particles[ip - atm->
np].
q[iq] = atm->
q[iq][ip];
2034 for (
int i = 0; i < 3; i++)
2035 particles[ip - atm->
np].
uvwp[i] = cache->
uvwp[ip][i];
2041#pragma acc update host( particles[:npart])
2042#pragma acc exit data delete(npart, particles)
2063 MPI_Comm_rank(MPI_COMM_WORLD, &
rank);
2065 const int np = atm->
np;
2072#pragma acc enter data create(particles[0:npart])
2073#pragma acc parallel loop present(ctl, atm, cache, dd, particles)
2074 for (
int i = 0; i < npart; i++) {
2075 const int ip = dd->
perm[np - 1 - i];
2077 particles[i].
p = atm->
p[ip];
2078 particles[i].
lon = atm->
lon[ip];
2079 particles[i].
lat = atm->
lat[ip];
2080 for (
int iq = 0; iq < ctl->
nq; iq++)
2081 particles[i].q[iq] = atm->
q[iq][ip];
2082 for (
int j = 0; j < 3; j++)
2083 particles[i].uvwp[j] = cache->
uvwp[ip][j];
2086#pragma acc update self(particles[0:npart])
2087#pragma acc exit data delete(particles[0:npart])
2092 if (nkeep > 0 && nkeep != np) {
2098 for (
int iq = 0; iq < ctl->
nq; iq++)
2104 const int nlost = np - nkeep - npart;
2106 WARN(
"Rank %d: %d particles have invalid subdomain and will be lost",
2109#pragma acc update device(atm->np)
2115 int nkeep_cpu = 0, nsend = 0, nlost = 0;
2116 for (
int ip = 0; ip < np; ip++) {
2119 if (current < 0 || target < 0) {
2124 if (target !=
rank) {
2125 particles[nsend].
time = atm->
time[ip];
2126 particles[nsend].
p = atm->
p[ip];
2127 particles[nsend].
lon = atm->
lon[ip];
2128 particles[nsend].
lat = atm->
lat[ip];
2129 for (
int iq = 0; iq < ctl->
nq; iq++)
2130 particles[nsend].q[iq] = atm->
q[iq][ip];
2131 for (
int i = 0; i < 3; i++)
2132 particles[nsend].uvwp[i] = cache->
uvwp[ip][i];
2137 if (nkeep_cpu != ip) {
2138 atm->
time[nkeep_cpu] = atm->
time[ip];
2139 atm->
p[nkeep_cpu] = atm->
p[ip];
2140 atm->
lon[nkeep_cpu] = atm->
lon[ip];
2141 atm->
lat[nkeep_cpu] = atm->
lat[ip];
2142 for (
int iq = 0; iq < ctl->
nq; iq++)
2143 atm->
q[iq][nkeep_cpu] = atm->
q[iq][ip];
2144 cache->
dt[nkeep_cpu] = cache->
dt[ip];
2145 for (
int i = 0; i < 3; i++)
2146 cache->
uvwp[nkeep_cpu][i] = cache->
uvwp[ip][i];
2152 ERRMSG(
"Inconsistent number of outgoing particles!");
2154 WARN(
"Rank %d: %d particles have invalid subdomain and will be lost",
2156 atm->
np = nkeep_cpu;
2179 int zonal_rank = ix / nx_block;
2185 int merid_rank = iy / ny_block;
2208 MPI_Comm_rank(MPI_COMM_WORLD, &
rank);
2209 MPI_Comm_size(MPI_COMM_WORLD, &
size);
2211 int *send_counts, *recv_counts;
2212 int *send_displs, *recv_displs;
2218 ALLOC(send_counts,
int,
2220 ALLOC(recv_counts,
int,
2222 ALLOC(send_displs,
int,
2224 ALLOC(recv_displs,
int,
2230#pragma omp parallel for
2231 for (
int ip = 0; ip < *npart; ip++) {
2235 if (dest < 0 || dest >=
size)
2236 ERRMSG(
"Invalid destination rank!");
2238 send_counts[dest]++;
2243 for (
int i = 0; i <
size; i++) {
2244 send_displs[i] = nsend;
2245 nsend += send_counts[i];
2248 LOG(3,
"DD_SEND rank=%d particles=%d",
rank, nsend);
2253 if (dd_node != NULL) {
2254 dd_sent += (
unsigned long long) nsend;
2255 for (
int i = 0; i <
size; i++) {
2256 if (dd_node[i] == dd_node[
rank])
2257 dd_intra += (
unsigned long long) send_counts[i];
2259 dd_inter += (
unsigned long long) send_counts[i];
2265 MPI_Alltoall(send_counts, 1, MPI_INT,
2266 recv_counts, 1, MPI_INT, MPI_COMM_WORLD);
2270 for (
int i = 0; i <
size; i++) {
2271 recv_displs[i] = nrecv;
2272 nrecv += recv_counts[i];
2278 for (
int i = 0; i <
size; i++)
2279 offsets[i] = send_displs[i];
2282 for (
int ip = 0; ip < *npart; ip++) {
2286 memcpy(&sendbuf[offsets[dest]], &(*particles)[ip],
sizeof(
particle_t));
2291 MPI_Alltoallv(sendbuf,
2296 recv_counts, recv_displs, dd->
MPI_Particle, MPI_COMM_WORLD);
2299 if (nrecv > *capacity) {
2300 const int newcap = nrecv + nrecv / 2 + 1;
2302 realloc(*particles, (
size_t) newcap *
sizeof(
particle_t));
2304 ERRMSG(
"Out of memory!");
2310#pragma omp parallel for
2311 for (
int ip = 0; ip < nrecv; ip++) {
2312 (*particles)[ip] = recvbuf[ip];
2342 ERRMSG(
"Please provide zonal and meridional subdomain numbers!");
2344 ERRMSG(
"Activate control flag DD!");
2348 MPI_Comm_size(MPI_COMM_WORLD, &
size);
2350 ERRMSG(
"Number of tasks and subdomains is not identical!");
2353 const MPI_Datatype types[6] =
2354 { MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE,
2356 const int blocklengths[6] = { 1, 1, 1, 1,
NQ, 3 };
2357 const MPI_Aint displacements[6] =
2362 MPI_Datatype fields;
2363 MPI_Type_create_struct(6, blocklengths, displacements, types, &fields);
2366 MPI_Type_create_resized(fields, 0, (MPI_Aint)
sizeof(
particle_t),
2368 MPI_Type_free(&fields);
2370 MPI_Aint lower_bound, extent;
2371 MPI_Type_get_extent(dd->
MPI_Particle, &lower_bound, &extent);
2372 if (lower_bound != 0 || extent != (MPI_Aint)
sizeof(
particle_t))
2373 ERRMSG(
"Invalid MPI particle datatype extent!");
2375 LOG(1,
"DD: %d x %d subdomains | exchange mode %d | initial particles %d",
2382 int rank, local_rank, leader;
2384 MPI_Comm_rank(MPI_COMM_WORLD, &
rank);
2385 MPI_Comm_split_type(MPI_COMM_WORLD, MPI_COMM_TYPE_SHARED,
rank,
2386 MPI_INFO_NULL, &shared);
2387 MPI_Comm_rank(shared, &local_rank);
2388 leader = local_rank == 0 ?
rank : -1;
2389 MPI_Bcast(&leader, 1, MPI_INT, 0, shared);
2391 MPI_Allgather(&leader, 1, MPI_INT, dd_node, 1, MPI_INT,
2394 dd_sent = dd_intra = dd_inter = 0;
2395 char hostname[MPI_MAX_PROCESSOR_NAME];
2397 MPI_Get_processor_name(hostname, &hostname_len);
2398 const char *gpu = getenv(
"CUDA_VISIBLE_DEVICES");
2399 LOG(2,
"DD_NODE rank=%d leader=%d local_rank=%d host=%s gpu=%s",
2400 rank, leader, local_rank, hostname, gpu ? gpu :
"-");
2401 MPI_Comm_free(&shared);
2418 const double lon_min = (dd->
lon_glob[0] < 0) ? -180.0 : 0.0;
2421 *lon =
FMOD(*lon - lon_min, 360.0);
2428 *lat = 180.0 - *lat;
2430 }
else if (*lat < -90.0) {
2431 *lat = -180.0 - *lat;
2436 *lon =
FMOD(*lon - lon_min, 360.0);
2461 if (atm->
np + npart >
NP)
2462 ERRMSG(
"Too many particles. Increase NP!");
2465#pragma acc enter data create(npart, particles[:npart])
2466#pragma acc update device(particles[:npart], npart)
2467#pragma acc data present(atm, ctl, cache, particles, npart)
2468#pragma acc parallel loop
2470 for (
int ip = atm->
np; ip < atm->np + npart; ip++) {
2471 atm->
time[ip] = particles[ip - atm->
np].
time;
2472 atm->
lon[ip] = particles[ip - atm->
np].
lon;
2473 atm->
lat[ip] = particles[ip - atm->
np].
lat;
2474 atm->
p[ip] = particles[ip - atm->
np].
p;
2475 for (
int iq = 0; iq < ctl->
nq; iq++)
2476 atm->
q[iq][ip] = particles[ip - atm->
np].
q[iq];
2477 for (
int i = 0; i < 3; i++)
2478 cache->
uvwp[ip][i] = particles[ip - atm->
np].
uvwp[i];
2482#pragma acc exit data delete(npart, particles)
2488#pragma acc update device(atm->np)
2506#pragma acc data present(array[0:np],perm[0:np],tmp[0:np])
2513#pragma acc parallel loop independent gang vector
2515#pragma omp parallel for default(shared)
2517 for (
int ip = 0; ip < np; ip++)
2518 tmp[ip] = array[perm[ip]];
2522#pragma acc parallel loop independent gang vector
2524#pragma omp parallel for default(shared)
2526 for (
int ip = 0; ip < np; ip++)
2527 array[ip] = tmp[ip];
2544#pragma acc data present(cache,perm[0:np],tmp[0:np])
2550 for (
int j = 0; j < 3; j++) {
2553#pragma acc parallel loop
2555#pragma omp parallel for
2557 for (
int ip = 0; ip < np; ip++)
2558 tmp[ip] = cache->
uvwp[perm[ip]][j];
2562#pragma acc parallel loop
2564#pragma omp parallel
for
2566 for (
int ip = 0; ip < np; ip++)
2567 cache->
uvwp[ip][j] = (
float) tmp[ip];
2582 MPI_Comm_rank(MPI_COMM_WORLD, &
rank);
2587 int *counter_ptr = (
int *) acc_malloc(
sizeof(
int));
2588 if (counter_ptr == NULL) {
2589 ERRMSG(
"Failed to allocate device counter memory!");
2591 acc_memcpy_to_device(counter_ptr, &counter,
sizeof(
int));
2593 int *counter_ptr = &counter;
2598#pragma acc parallel loop present(atm, cache, ctl) deviceptr(counter_ptr)
2600#pragma omp parallel for
2602 for (
int ip = 0; ip < atm->
np; ip++) {
2607#pragma acc atomic capture
2609#pragma omp atomic capture
2612 local_idx = *counter_ptr;
2615 int global_index = atm->
np + local_idx;
2616 if (global_index >=
NP)
2619 atm->
time[global_index] = atm->
time[ip];
2620 atm->
p[global_index] = atm->
p[ip];
2621 atm->
lon[global_index] = atm->
lon[ip];
2622 atm->
lat[global_index] = atm->
lat[ip];
2624 for (
int iq = 0; iq < ctl->
nq; iq++) {
2625 atm->
q[iq][global_index] = atm->
q[iq][ip];
2631 cache->
dt[global_index] = cache->
dt[ip];
2633 for (
int i = 0; i < 3; i++)
2634 cache->
uvwp[global_index][i] = cache->
uvwp[ip][i];
2639 acc_memcpy_from_device(npart, counter_ptr,
sizeof(
int));
2640 acc_free(counter_ptr);
2645 if (atm->
np + *npart >
NP)
2646 ERRMSG(
"Too many particles during DD push. Increase NP!");
2665 MPI_Comm_rank(MPI_COMM_WORLD, &
rank);
2668 const int np = atm->
np;
2669 double amax = (met0->
nx * met0->
ny + met0->
ny) * met0->
np + met0->
np;
2671#pragma acc enter data create(amax)
2672#pragma acc update device(amax)
2673#pragma acc data present(ctl,met0,atm,dd,amax)
2678#pragma acc parallel loop independent gang vector
2680#pragma omp parallel for default(shared)
2682 for (
int ip = 0; ip < np; ip++) {
2700#pragma acc host_data use_device(dd->sort_key, dd->perm)
2704 size_t *perm_sz = (
size_t *) malloc((
size_t) np *
sizeof(size_t));
2705 if (perm_sz == NULL)
2706 ERRMSG(
"Out of memory!");
2708#pragma acc update self(dd->sort_key[0:np])
2710 gsl_sort_index(perm_sz, dd->
sort_key, 1, (
size_t) np);
2711 for (
int ip = 0; ip < np; ++ip)
2712 dd->
perm[ip] = (
int) perm_sz[ip];
2715#pragma acc update device(dd->perm[0:np])
2724 for (
int iq = 0; iq < ctl->
nq; iq++)
2730 int nkeep = 0, nsend = 0, nlost = 0;
2732#pragma acc parallel loop reduction(+:nkeep,nsend,nlost) present(atm, ctl)
2734 for (
int ip = 0; ip < np; ip++) {
2739 else if (target ==
rank)
2750 (
"Rank %d: %d particles have subdomain index -1 and will be lost (kept: %d, to_send: %d, total_before: %d)",
2751 rank, nlost, nkeep, nsend, np);
2755#pragma acc update device(atm->np)
2760#pragma acc exit data delete(amax)
2778 MPI_Comm_rank(MPI_COMM_WORLD, &
rank);
2779 const int np = atm->
np;
2781 int counts[2] = { 0, 0 };
2784#pragma acc data copy(counts[0:2]) present(ctl, atm, dd)
2786#pragma acc parallel loop
2787 for (
int ip = 0; ip < np; ip++) {
2791 if (current < 0 || target < 0)
2793 if (target ==
rank) {
2794#pragma acc atomic capture
2801#pragma acc atomic capture
2806 dd->
perm[np - 1 - i] = ip;
2817 for (
int ip = 0; ip < np; ip++) {
2841 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
2842 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
2847 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
2848 for (i = 11; i > 0; i--)
2852 *day = doy - d0l[i] + 1;
2854 for (i = 11; i > 0; i--)
2858 *day = doy - d0[i] + 1;
2869 double data[2 *
EX];
2873 ERRMSG(
"Too many data points!");
2876 gsl_fft_complex_wavetable *wavetable =
2877 gsl_fft_complex_wavetable_alloc((
size_t) n);
2878 gsl_fft_complex_workspace *workspace =
2879 gsl_fft_complex_workspace_alloc((
size_t) n);
2882 for (
int i = 0; i < n; i++) {
2883 data[2 * i] = fcReal[i];
2884 data[2 * i + 1] = fcImag[i];
2888 gsl_fft_complex_forward(data, 1, (
size_t) n, wavetable, workspace);
2891 for (
int i = 0; i < n; i++) {
2892 fcReal[i] = data[2 * i];
2893 fcImag[i] = data[2 * i + 1];
2897 gsl_fft_complex_wavetable_free(wavetable);
2898 gsl_fft_complex_workspace_free(workspace);
2909 const double radius = z +
RE;
2910 const double latrad =
DEG2RAD(lat);
2911 const double lonrad =
DEG2RAD(lon);
2912 const double coslat = cos(latrad);
2914 x[0] = radius * coslat * cos(lonrad);
2915 x[1] = radius * coslat * sin(lonrad);
2916 x[2] = radius * sin(latrad);
2925 const char *metbase,
2926 const double dt_met,
2933 int year, mon, day, hour, min, sec;
2937 t6 = floor(t / dt_met) * dt_met;
2939 t6 = ceil(t / dt_met) * dt_met;
2942 jsec2time(t6, &year, &mon, &day, &hour, &min, &sec, &r);
2947 sprintf(filename,
"%s_YYYY_MM_DD_HH.nc", metbase);
2949 sprintf(filename,
"%s_YYYY_MM_DD_HH.bin", metbase);
2951 sprintf(filename,
"%s_YYYY_MM_DD_HH.pck", metbase);
2953 sprintf(filename,
"%s_YYYY_MM_DD_HH.zfp", metbase);
2955 sprintf(filename,
"%s_YYYY_MM_DD_HH.zstd", metbase);
2957 sprintf(filename,
"%s_YYYY_MM_DD_HH.cms", metbase);
2959 sprintf(filename,
"%s_YYYY_MM_DD_HH.sz3", metbase);
2961 sprintf(filename,
"%s_YYYY_MM_DD_HH.lz4", metbase);
2962 sprintf(repl,
"%d", year);
2964 sprintf(repl,
"%02d", mon);
2966 sprintf(repl,
"%02d", day);
2968 sprintf(repl,
"%02d", hour);
2974 sprintf(filename,
"%s_YYMMDDHH.nc", metbase);
2975 sprintf(repl,
"%d", year);
2977 sprintf(repl,
"%02d", year % 100);
2979 sprintf(repl,
"%02d", mon);
2981 sprintf(repl,
"%02d", day);
2983 sprintf(repl,
"%02d", hour);
2998 for (
int i = 0; i < 3; i++) {
3002 if (!(ch = strstr(orig, search)))
3004 strncpy(buffer, orig, (
size_t) (ch - orig));
3005 buffer[ch - orig] = 0;
3006 sprintf(buffer + (ch - orig),
"%s%s", repl, ch + strlen(search));
3008 strcpy(orig, buffer);
3015 const int met_tropo,
3035#pragma omp parallel for default(shared) private(ci,cw)
3036 for (
int ix = 0; ix < nx; ix++)
3037 for (
int iy = 0; iy < ny; iy++) {
3039 &pt[iy * nx + ix], ci, cw, 1);
3041 &ps[iy * nx + ix], ci, cw, 0);
3043 &zs[iy * nx + ix], ci, cw, 0);
3045 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
3047 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
3049 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
3051 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
3068 *lon2 =
FMOD(lon, 360.);
3069 if (*lon2 < lons[0])
3071 else if (*lon2 > lons[nlon - 1])
3076 if (lats[0] < lats[nlat - 1])
3077 *lat2 =
MIN(
MAX(*lat2, lats[0]), lats[nlat - 1]);
3079 *lat2 =
MIN(
MAX(*lat2, lats[nlat - 1]), lats[0]);
3095 if (lons[0] < lons[nlon - 1])
3096 *lon2 =
MIN(
MAX(lon, lons[0]), lons[nlon - 1]);
3098 *lon2 =
MIN(
MAX(lon, lons[nlon - 1]), lons[0]);
3101 if (lats[0] < lats[nlat - 1])
3102 *lat2 =
MIN(
MAX(lat, lats[0]), lats[nlat - 1]);
3104 *lat2 =
MIN(
MAX(lat, lats[nlat - 1]), lats[0]);
3112 float heights0[
EX][
EY][
EP],
3113 float array0[
EX][
EY][
EP],
3115 float heights1[
EX][
EY][
EP],
3116 float array1[
EX][
EY][
EP],
3118 const double height,
3149 int k_max = ind[0][0];
3150 for (
int i = 0; i < 2; i++)
3151 for (
int j = 0; j < 4; j++) {
3152 if (ci[2] > ind[i][j])
3154 if (k_max < ind[i][j])
3160 cw[0] = (lon2 - met0->
lon[ci[0]]) /
3161 (met0->
lon[ci[0] + 1] - met0->
lon[ci[0]]);
3162 cw[1] = (lat2 - met0->
lat[ci[1]]) /
3163 (met0->
lat[ci[1] + 1] - met0->
lat[ci[1]]);
3166 double height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2]]
3167 - heights0[ci[0]][ci[1]][ci[2]])
3168 + heights0[ci[0]][ci[1]][ci[2]];
3169 double height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2]]
3170 - heights0[ci[0]][ci[1] + 1][ci[2]])
3171 + heights0[ci[0]][ci[1] + 1][ci[2]];
3172 double height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2]]
3173 - heights0[ci[0] + 1][ci[1]][ci[2]])
3174 + heights0[ci[0] + 1][ci[1]][ci[2]];
3175 double height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2]]
3176 - heights0[ci[0] + 1][ci[1] + 1][ci[2]])
3177 + heights0[ci[0] + 1][ci[1] + 1][ci[2]];
3180 double height0 = cw[1] * (height01 - height00) + height00;
3181 double height1 = cw[1] * (height11 - height10) + height10;
3184 double height_bot = cw[0] * (height1 - height0) + height0;
3187 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
3188 - heights0[ci[0]][ci[1]][ci[2] + 1])
3189 + heights0[ci[0]][ci[1]][ci[2] + 1];
3190 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
3191 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
3192 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
3193 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
3194 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
3195 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
3196 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
3197 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
3198 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
3201 height0 = cw[1] * (height01 - height00) + height00;
3202 height1 = cw[1] * (height11 - height10) + height10;
3205 double height_top = cw[0] * (height1 - height0) + height0;
3208 while (((heights0[0][0][0] > heights0[0][0][1]) &&
3209 ((height_bot <= height) || (height_top > height))
3210 && (height_bot >= height) && (ci[2] < k_max))
3212 ((heights0[0][0][0] < heights0[0][0][1]) &&
3213 ((height_bot >= height) || (height_top < height))
3214 && (height_bot <= height) && (ci[2] < k_max))
3218 height_bot = height_top;
3221 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
3222 - heights0[ci[0]][ci[1]][ci[2] + 1])
3223 + heights0[ci[0]][ci[1]][ci[2] + 1];
3224 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
3225 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
3226 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
3227 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
3228 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
3229 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
3230 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
3231 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
3232 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
3235 height0 = cw[1] * (height01 - height00) + height00;
3236 height1 = cw[1] * (height11 - height10) + height10;
3239 height_top = cw[0] * (height1 - height0) + height0;
3243 cw[2] = (height - height_bot)
3244 / (height_top - height_bot);
3248 const double array000 = cw[3] * (array1[ci[0]][ci[1]][ci[2]]
3249 - array0[ci[0]][ci[1]][ci[2]])
3250 + array0[ci[0]][ci[1]][ci[2]];
3251 const double array100 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2]]
3252 - array0[ci[0] + 1][ci[1]][ci[2]])
3253 + array0[ci[0] + 1][ci[1]][ci[2]];
3254 const double array010 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2]]
3255 - array0[ci[0]][ci[1] + 1][ci[2]])
3256 + array0[ci[0]][ci[1] + 1][ci[2]];
3257 const double array110 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2]]
3258 - array0[ci[0] + 1][ci[1] + 1][ci[2]])
3259 + array0[ci[0] + 1][ci[1] + 1][ci[2]];
3260 const double array001 = cw[3] * (array1[ci[0]][ci[1]][ci[2] + 1]
3261 - array0[ci[0]][ci[1]][ci[2] + 1])
3262 + array0[ci[0]][ci[1]][ci[2] + 1];
3263 const double array101 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2] + 1]
3264 - array0[ci[0] + 1][ci[1]][ci[2] + 1])
3265 + array0[ci[0] + 1][ci[1]][ci[2] + 1];
3266 const double array011 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2] + 1]
3267 - array0[ci[0]][ci[1] + 1][ci[2] + 1])
3268 + array0[ci[0]][ci[1] + 1][ci[2] + 1];
3269 const double array111 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
3270 - array0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
3271 + array0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
3273 const double array00 = cw[0] * (array100 - array000) + array000;
3274 const double array10 = cw[0] * (array110 - array010) + array010;
3275 const double array01 = cw[0] * (array101 - array001) + array001;
3276 const double array11 = cw[0] * (array111 - array011) + array011;
3278 const double aux0 = cw[1] * (array10 - array00) + array00;
3279 const double aux1 = cw[1] * (array11 - array01) + array01;
3282 *var = cw[2] * (aux1 - aux0) + aux0;
3317 cw[0] = (met->
p[ci[0] + 1] - p)
3318 / (met->
p[ci[0] + 1] - met->
p[ci[0]]);
3319 cw[1] = (met->
lon[ci[1] + 1] - lon2)
3320 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
3321 cw[2] = (met->
lat[ci[2] + 1] - lat2)
3322 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
3326 const double aux00 =
3327 cw[0] * (array[ci[1]][ci[2]][ci[0]] - array[ci[1]][ci[2]][ci[0] + 1])
3328 + array[ci[1]][ci[2]][ci[0] + 1];
3329 const double aux01 =
3330 cw[0] * (array[ci[1]][ci[2] + 1][ci[0]] -
3331 array[ci[1]][ci[2] + 1][ci[0] + 1])
3332 + array[ci[1]][ci[2] + 1][ci[0] + 1];
3333 const double aux10 =
3334 cw[0] * (array[ci[1] + 1][ci[2]][ci[0]] -
3335 array[ci[1] + 1][ci[2]][ci[0] + 1])
3336 + array[ci[1] + 1][ci[2]][ci[0] + 1];
3337 const double aux11 =
3338 cw[0] * (array[ci[1] + 1][ci[2] + 1][ci[0]] -
3339 array[ci[1] + 1][ci[2] + 1][ci[0] + 1])
3340 + array[ci[1] + 1][ci[2] + 1][ci[0] + 1];
3343 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
3344 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
3345 *var = cw[1] * (aux0 - aux1) + aux1;
3352 float array[
EX][
EY],
3379 cw[1] = (met->
lon[ci[1] + 1] - lon2)
3380 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
3381 cw[2] = (met->
lat[ci[2] + 1] - lat2)
3382 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
3386 const double aux00 = array[ci[1]][ci[2]];
3387 const double aux01 = array[ci[1]][ci[2] + 1];
3388 const double aux10 = array[ci[1] + 1][ci[2]];
3389 const double aux11 = array[ci[1] + 1][ci[2] + 1];
3392 if (isfinite(aux00) && isfinite(aux01)
3393 && isfinite(aux10) && isfinite(aux11)) {
3394 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
3395 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
3396 *var = cw[1] * (aux0 - aux1) + aux1;
3416 float array0[
EX][
EY][
EP],
3418 float array1[
EX][
EY][
EP],
3435 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
3438 *var = wt * (var0 - var1) + var1;
3445 float array0[
EX][
EY],
3447 float array1[
EX][
EY],
3463 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
3466 if (isfinite(var0) && isfinite(var1))
3467 *var = wt * (var0 - var1) + var1;
3478 float array0[
EX][
EY],
3480 float array1[
EX][
EY],
3481 const double lons[
EX],
3482 const double lats[
EY],
3501 const int ix =
locate_reg(lons, (
int) nlon, lon2);
3502 const int iy =
locate_irr(lats, (
int) nlat, lat2);
3506 for (
int dx = 0; dx < 2; dx++)
3507 for (
int dy = 0; dy < 2; dy++) {
3508 if (isfinite(array0[ix + dx][iy + dy])) {
3509 mean += array0[ix + dx][iy + dy];
3510 *sigma +=
SQR(array0[ix + dx][iy + dy]);
3513 if (isfinite(array1[ix + dx][iy + dy])) {
3514 mean += array1[ix + dx][iy + dy];
3515 *sigma +=
SQR(array1[ix + dx][iy + dy]);
3520 *sigma = sqrt(
MAX(*sigma / n -
SQR(mean / n), 0.0));
3523 if (method == 1 && isfinite(array0[ix][iy])
3524 && isfinite(array0[ix][iy + 1])
3525 && isfinite(array0[ix + 1][iy])
3526 && isfinite(array0[ix + 1][iy + 1])
3527 && isfinite(array1[ix][iy])
3528 && isfinite(array1[ix][iy + 1])
3529 && isfinite(array1[ix + 1][iy])
3530 && isfinite(array1[ix + 1][iy + 1])) {
3532 const double aux00 =
LIN(lons[ix], array0[ix][iy],
3533 lons[ix + 1], array0[ix + 1][iy], lon2);
3534 const double aux01 =
LIN(lons[ix], array0[ix][iy + 1],
3535 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
3536 const double aux0 =
LIN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
3538 const double aux10 =
LIN(lons[ix], array1[ix][iy],
3539 lons[ix + 1], array1[ix + 1][iy], lon2);
3540 const double aux11 =
LIN(lons[ix], array1[ix][iy + 1],
3541 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
3542 const double aux1 =
LIN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
3544 *var =
LIN(time0, aux0, time1, aux1, time);
3549 const double aux00 =
NN(lons[ix], array0[ix][iy],
3550 lons[ix + 1], array0[ix + 1][iy], lon2);
3551 const double aux01 =
NN(lons[ix], array0[ix][iy + 1],
3552 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
3553 const double aux0 =
NN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
3555 const double aux10 =
NN(lons[ix], array1[ix][iy],
3556 lons[ix + 1], array1[ix + 1][iy], lon2);
3557 const double aux11 =
NN(lons[ix], array1[ix][iy + 1],
3558 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
3559 const double aux1 =
NN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
3561 *var =
NN(time0, aux0, time1, aux1, time);
3586 const time_t jsec0 = (time_t) jsec + timegm(&t0);
3587 t1 = gmtime(&jsec0);
3589 *year = t1->tm_year + 1900;
3590 *mon = t1->tm_mon + 1;
3592 *hour = t1->tm_hour;
3595 *remain = jsec - floor(jsec);
3601 const double kz[
EP],
3602 const double kw[
EP],
3611 const double z =
Z(p);
3616 else if (z > kz[nk - 1])
3620 return LIN(kz[idx], kw[idx], kz[idx + 1], kw[idx + 1], z);
3637 const double a =
RA *
SQR(t), r =
SH(h2o) / (1. -
SH(h2o));
3650 (
"MET_PRESS_LEVEL_DEF=0 is disabled. Use 3 for the extended L137 set.");
3655 (
"MET_PRESS_LEVEL_DEF=1 is disabled. Use 4 for the extended L91 set.");
3660 (
"MET_PRESS_LEVEL_DEF=2 is disabled. Use 5 for the extended L60 set.");
3666 const double press[147] = {
3667 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
3668 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
3669 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
3670 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
3671 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
3672 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
3673 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
3674 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
3675 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
3676 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
3677 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
3678 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
3679 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
3680 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
3681 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
3682 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
3683 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
3684 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
3685 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73, 1028.85,
3687 1035.09, 1038.21, 1041.33, 1044.45
3690 for (
int ip = 0; ip < ctl->
met_np; ip++)
3697 const double press[101] = {
3698 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
3699 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
3700 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
3701 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
3702 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
3704 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
3705 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
3706 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
3707 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
3708 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
3709 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
3710 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
3711 1007.4431, 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73,
3713 1035.09, 1038.21, 1041.33, 1044.45
3716 for (
int ip = 0; ip < ctl->
met_np; ip++)
3723 const double press[62] = {
3724 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
3725 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
3726 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
3727 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
3728 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
3729 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
3730 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
3731 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1034.86, 1039.65,
3735 for (
int ip = 0; ip < ctl->
met_np; ip++)
3742 const double press[137] = {
3743 0.01, 0.02, 0.031, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861,
3744 0.2499, 0.3299, 0.4288, 0.5496, 0.6952, 0.869, 1.0742,
3745 1.3143, 1.5928, 1.9134, 2.2797, 2.6954, 3.1642, 3.6898,
3746 4.2759, 4.9262, 5.6441, 6.4334, 7.2974, 8.2397, 9.2634,
3747 10.372, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945, 18.9752,
3748 20.761, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
3749 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.199, 54.5299,
3750 57.9834, 61.5607, 65.2695, 69.1187, 73.1187, 77.281, 81.6182,
3751 86.145, 90.8774, 95.828, 101.005, 106.415, 112.068, 117.971,
3752 124.134, 130.564, 137.27, 144.262, 151.549, 159.14, 167.045,
3753 175.273, 183.834, 192.739, 201.997, 211.619, 221.615, 231.995,
3754 242.772, 253.955, 265.556, 277.585, 290.055, 302.976, 316.361,
3755 330.22, 344.566, 359.411, 374.767, 390.645, 407.058, 424.019,
3756 441.539, 459.632, 478.31, 497.584, 517.42, 537.72, 558.343,
3757 579.193, 600.167, 621.162, 642.076, 662.808, 683.262, 703.347,
3758 722.979, 742.086, 760.6, 778.466, 795.64, 812.085, 827.776,
3759 842.696, 856.838, 870.2, 882.791, 894.622, 905.712, 916.081,
3760 925.757, 934.767, 943.14, 950.908, 958.104, 965.299, 972.495,
3761 979.69, 986.886, 994.081, 1001.28, 1008.47, 1015.67, 1022.86,
3762 1030.06, 1037.25, 1044.45
3765 for (
int ip = 0; ip < ctl->
met_np; ip++)
3772 const double press[59] = {
3773 0.1, 0.2, 0.3843, 0.6365, 0.9564, 1.3448, 1.8058, 2.3478,
3774 2.985, 3.7397, 4.6462, 5.7565, 7.1322, 8.8366, 10.9483,
3775 13.5647, 16.8064, 20.8227, 25.7989, 31.9642, 39.6029, 49.0671,
3776 60.1802, 73.0663, 87.7274, 104.229, 122.614, 142.902, 165.089,
3777 189.147, 215.025, 242.652, 272.059, 303.217, 336.044, 370.407,
3778 406.133, 443.009, 480.791, 519.209, 557.973, 596.777, 635.306,
3779 673.24, 710.263, 746.063, 780.346, 812.83, 843.263, 871.42,
3780 897.112, 920.189, 940.551, 958.148, 975.744, 993.341, 1010.94,
3784 for (
int ip = 0; ip < ctl->
met_np; ip++)
3788 ERRMSG(
"Use values between 3 and 7.");
3792 ERRMSG(
"Recompile with larger EP to use this pressure level definition!");
3804 int i = (ihi + ilo) >> 1;
3806 if (xx[i] < xx[i + 1])
3807 while (ihi > ilo + 1) {
3808 i = (ihi + ilo) >> 1;
3814 while (ihi > ilo + 1) {
3815 i = (ihi + ilo) >> 1;
3835 int i = (ihi + ilo) >> 1;
3837 if ((xx[ig] <= x && x < xx[ig + 1]) || (xx[ig] >= x && x > xx[ig + 1]))
3840 if (xx[i] < xx[i + 1])
3841 while (ihi > ilo + 1) {
3842 i = (ihi + ilo) >> 1;
3848 while (ihi > ilo + 1) {
3849 i = (ihi + ilo) >> 1;
3867 const int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
3881 float profiles[
EX][
EY][
EP],
3883 const int lon_ap_ind,
3884 const int lat_ap_ind,
3885 const double height_ap,
3891 np, height_ap, ind[0]);
3893 np, height_ap, ind[1]);
3895 np, height_ap, ind[2]);
3914 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3918 double dts, u[4], um = 0, v[4], vm = 0, w[4], wm = 0,
3922 for (
int i = 0; i < ctl->
advect; i++) {
3927 x[0] = atm->
lon[ip];
3928 x[1] = atm->
lat[ip];
3931 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
3932 x[0] = atm->
lon[ip] +
DX2COORD(met0, dts * u[i - 1], atm->
lat[ip]);
3933 x[1] = atm->
lat[ip] +
DY2COORD(met0, dts * v[i - 1]);
3934 x[2] = atm->
p[ip] + dts * w[i - 1];
3936 const double tm = atm->
time[ip] + dts;
3941 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3943 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3945 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
3951 met1, met1->
pl, met1->
ul,
3952 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3954 met1, met1->
pl, met1->
vl,
3955 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3957 met1, met1->
pl, met1->
wl,
3958 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
3964 k = (i == 0 ? 0.0 : 1.0);
3965 else if (ctl->
advect == 4)
3966 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
3973 atm->
time[ip] += cache->
dt[ip];
3975 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
3977 atm->
p[ip] += cache->
dt[ip] * wm;
3990 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3996 atm->
time[ip], atm->
p[ip],
3997 atm->
lon[ip], atm->
lat[ip],
3998 &atm->
q[qnt][ip], ci, cw, 1);
4001 double dts, u[4], um = 0, v[4], vm = 0, wdot[4],
4002 wdotm = 0, x[3] = { 0, 0, 0 };
4005 for (
int i = 0; i < ctl->
advect; i++) {
4010 x[0] = atm->
lon[ip];
4011 x[1] = atm->
lat[ip];
4012 x[2] = atm->
q[qnt][ip];
4014 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
4015 x[0] = atm->
lon[ip] +
DX2COORD(met0, dts * u[i - 1], atm->
lat[ip]);
4016 x[1] = atm->
lat[ip] +
DY2COORD(met0, dts * v[i - 1]);
4017 x[2] = atm->
q[qnt][ip] + dts * wdot[i - 1];
4020 const double tm = atm->
time[ip] + dts;
4025 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
4028 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
4031 tm, x[2], x[0], x[1], &wdot[i], ci, cw, 0);
4036 k = (i == 0 ? 0.0 : 1.0);
4037 else if (ctl->
advect == 4)
4038 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
4042 wdotm += k * wdot[i];
4046 atm->
time[ip] += cache->
dt[ip];
4048 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
4050 atm->
q[qnt][ip] += cache->
dt[ip] * wdotm;
4056 atm->
q[qnt][ip], atm->
lon[ip], atm->
lat[ip],
4057 &atm->
p[ip], ci, cw, 1);
4085 atm->
lon[ip], atm->
lat[ip], &atm->
p[ip], ci, cw, 1);
4110 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4146 if (atm->
p[ip] < pbl)
4195 ERRMSG(
"Only lat/lon grid supported");
4201 ERRMSG(
"Molar mass is not defined!");
4207 const int ensemble_mode = (ctl->
nens > 0);
4208 const int np = atm->
np;
4212 const int ngrid = nx * ny * nz;
4213 const int nens = ensemble_mode ? ctl->
nens : 1;
4215 double *restrict
const z = (
double *) malloc((
size_t) nz *
sizeof(double));
4216 double *restrict
const press =
4217 (
double *) malloc((
size_t) nz *
sizeof(double));
4218 double *restrict
const mass =
4219 (
double *) calloc((
size_t) ngrid * (size_t) nens,
sizeof(
double));
4220 double *restrict
const area =
4221 (
double *) malloc((
size_t) ny *
sizeof(double));
4222 double *restrict
const lon =
4223 (
double *) malloc((
size_t) nx *
sizeof(double));
4224 double *restrict
const lat =
4225 (
double *) malloc((
size_t) ny *
sizeof(double));
4227 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
4228 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
4229 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
4238#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])
4239#pragma acc data present(ctl,met0,met1,atm,ixs,iys,izs,z,press,mass,area,lon,lat)
4240#pragma acc parallel loop independent gang vector
4242#pragma omp parallel for default(shared)
4244 for (
int iz = 0; iz < nz; iz++) {
4246 press[iz] =
P(z[iz]);
4251#pragma acc parallel loop independent gang vector
4253 for (
int i = 0; i < ngrid * nens; i++)
4257 const double t0 = tt - 0.5 * ctl->
dt_mod;
4258 const double t1 = tt + 0.5 * ctl->
dt_mod;
4262#pragma acc parallel loop independent gang vector
4264#pragma omp parallel for default(shared)
4266 for (
int ip = 0; ip < np; ip++) {
4267 const double zpart =
Z(atm->
p[ip]);
4268 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
4273 || zpart < ctl->chemgrid_z0 || zpart >= ctl->
chemgrid_z1) {
4279 izs[ip] = (int) ((zpart - ctl->
chemgrid_z0) / dz);
4280 if (ixs[ip] >= nx || iys[ip] >= ny || izs[ip] >= nz)
4286#pragma acc parallel loop independent gang vector
4288#pragma omp parallel for default(shared)
4290 for (
int ix = 0; ix < nx; ix++)
4294#pragma acc parallel loop independent gang vector
4296#pragma omp parallel for default(shared)
4298 for (
int iy = 0; iy < ny; iy++) {
4300 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
4305#pragma acc parallel loop independent gang vector
4307 for (
int ip = 0; ip < np; ip++) {
4309 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
4310 if (ensemble_mode) {
4311 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
4312 mass_idx += ens * ngrid;
4315#pragma acc atomic update
4317 mass[mass_idx] += atm->
q[ctl->
qnt_m][ip];
4323#pragma acc parallel loop independent gang vector
4325#pragma omp parallel for default(shared)
4327 for (
int ip = 0; ip < np; ip++)
4335 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
4338 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
4339 if (ensemble_mode) {
4340 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
4341 mass_idx += ens * ngrid;
4345 const double m = mass[mass_idx];
4347 / (
RHO(press[izs[ip]], temp) * area[iys[ip]] * dz * 1e9);
4352#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
4380 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4396 const double lat_ref =
4399 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
4401 lat_ref, atm->
p[ip]));
4403 lat_ref, atm->
p[ip]));
4405 lat_ref, atm->
p[ip]));
4425 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4433 double pbot = ps, ptop = ps;
4450 double cape, cin, pel;
4456 if (isfinite(cape) && cape >= ctl->
conv_cape
4458 ptop =
MIN(ptop, pel);
4462 if (ptop != pbot && atm->
p[ip] >= ptop) {
4467 pbot, atm->
lon[ip], atm->
lat[ip], &tbot, ci, cw, 1);
4469 atm->
lon[ip], atm->
lat[ip], &ttop, ci, cw, 1);
4470 const double rhobot = pbot / tbot;
4471 const double rhotop = ptop / ttop;
4474 const double rho = rhobot + (rhotop - rhobot) * cache->
rs[ip];
4477 atm->
p[ip] =
LIN(rhobot, pbot, rhotop, ptop, rho);
4494 int npart = 0, nkeep = 0, capacity = 0;
4503 dd_sort(ctl, *met, cache, atm, dd, &npart);
4505 dd_push(ctl, atm, cache, &npart);
4512 if (npart > capacity) {
4513 const int newcap = npart + npart / 2 + 1;
4515 realloc(particles, (
size_t) newcap *
sizeof(
particle_t));
4517 ERRMSG(
"Out of memory!");
4529 MPI_Barrier(MPI_COMM_WORLD);
4555 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4558 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,clim,atm)") {
4567 const double aux = exp(-cache->
dt[ip] / tdec);
4568 if (ctl->
qnt_m >= 0) {
4571 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
4572 atm->
q[ctl->
qnt_m][ip] *= aux;
4597 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4605 float umean = 0, usig = 0, vmean = 0, vsig = 0, wmean = 0, wsig = 0;
4606 for (
int i = 0; i < 2; i++)
4607 for (
int j = 0; j < 2; j++)
4608 for (
int k = 0; k < 2; k++) {
4609 umean += met0->
u[ix + i][iy + j][iz + k];
4610 usig +=
SQR(met0->
u[ix + i][iy + j][iz + k]);
4611 vmean += met0->
v[ix + i][iy + j][iz + k];
4612 vsig +=
SQR(met0->
v[ix + i][iy + j][iz + k]);
4613 wmean += met0->
w[ix + i][iy + j][iz + k];
4614 wsig +=
SQR(met0->
w[ix + i][iy + j][iz + k]);
4616 umean += met1->
u[ix + i][iy + j][iz + k];
4617 usig +=
SQR(met1->
u[ix + i][iy + j][iz + k]);
4618 vmean += met1->
v[ix + i][iy + j][iz + k];
4619 vsig +=
SQR(met1->
v[ix + i][iy + j][iz + k]);
4620 wmean += met1->
w[ix + i][iy + j][iz + k];
4621 wsig +=
SQR(met1->
w[ix + i][iy + j][iz + k]);
4623 usig = usig / 16.f -
SQR(umean / 16.f);
4624 usig = (usig > 0 ? sqrtf(usig) : 0);
4625 vsig = vsig / 16.f -
SQR(vmean / 16.f);
4626 vsig = (vsig > 0 ? sqrtf(vsig) : 0);
4627 wsig = wsig / 16.f -
SQR(wmean / 16.f);
4628 wsig = (wsig > 0 ? sqrtf(wsig) : 0);
4631 const double r = 1 - 2 * fabs(cache->
dt[ip]) / ctl->
dt_met;
4632 const double r2 = sqrt(1 - r * r);
4636 cache->
uvwp[ip][0] =
4637 (float) (r * cache->
uvwp[ip][0] +
4642 cache->
uvwp[ip][1] =
4643 (float) (r * cache->
uvwp[ip][1] +
4650 cache->
uvwp[ip][2] =
4651 (float) (r * cache->
uvwp[ip][2] +
4653 atm->
p[ip] += cache->
uvwp[ip][2] * cache->
dt[ip];
4674 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4676 double pbl, ps, dsigw_dz = 0.0, sig_u = 0.0, sig_v = 0.0, sig_w = 0.0;
4677 double tau_u = 0.0, tau_v = 0.0, tau_w = 0.0;
4684 if (atm->
p[ip] < pbl)
4691 if (!(ps > 0.0 && pbl > 0.0 && ps > pbl))
4696 const double p =
MIN(atm->
p[ip], ps);
4697 const double zs =
Z(ps);
4698 const double z_raw = 1e3 * (
Z(p) - zs);
4699 const double zi = 1e3 * (
Z(pbl) - zs);
4706 const double z =
CLAMP(z_raw, 0.0, zi);
4707 const double zeta =
CLAMP(z / zi, 1e-6, 1.0 - 1e-6);
4708 const double z_m =
MAX(z, 1.0);
4713 const double p_save = atm->
p[ip];
4717 double ess, nss, h2o, t;
4724 atm->
p[ip] = p_save;
4726 const double tv =
TVIRT(t, h2o);
4727 const double thetav =
THETAVIRT(p, t, h2o);
4728 const double rho =
RHO(p, tv);
4729 const double tau = sqrt(
SQR(ess) +
SQR(nss));
4734 const double ustar = sqrt(
MAX(tau / rho, 0.0));
4735 const double ust =
MAX(1e-4, ustar);
4746 if (fabs(shf) > 1e-6)
4750 if (zi / fabs(ol) < 1.0) {
4755 const double corr = z_m / ust;
4756 const double sigw0 = 1.3 * ust * exp(-2e-4 * corr);
4758 sig_u =
MAX(2.0 * ust * exp(-3e-4 * corr), 1e-5);
4759 sig_v =
MAX(sigw0, 1e-5);
4760 sig_w =
MAX(sigw0, 1e-5);
4761 dsigw_dz = -2e-4 * sigw0 / ust;
4763 tau_u = 0.5 * z_m / sig_w / (1.0 + 1.5e-3 * corr);
4769 else if (ol < 0.0) {
4772 const double wstar_arg = -
G0 / thetav * shf / (rho *
CPD) * zi;
4773 const double wstar = pow(
MAX(wstar_arg, 0.0), 1.0 / 3.0);
4774 double dsigw2_dz = 0.0;
4777 sig_u =
MAX(ust * pow(
MAX(12.0 - 0.5 * zi / ol, 0.0), 1.0 / 3.0), 1e-6);
4781 const double arg =
MAX(3.0 * zeta - ol / zi, 1e-12);
4782 sig_w = 0.96 * wstar * pow(arg, 1.0 / 3.0);
4783 dsigw2_dz = 1.8432 *
SQR(wstar) / zi * pow(arg, -1.0 / 3.0);
4784 }
else if (zeta < 0.4) {
4785 const double arg =
MAX(3.0 * zeta - ol / zi, 1e-12);
4786 const double s1 = 0.96 * pow(arg, 1.0 / 3.0);
4787 const double s2 = 0.763 * pow(zeta, 0.175);
4790 dsigw2_dz = 1.8432 *
SQR(wstar) / zi * pow(arg, -1.0 / 3.0);
4793 dsigw2_dz = 0.203759 *
SQR(wstar) / zi * pow(zeta, -0.65);
4795 }
else if (zeta < 0.96) {
4796 sig_w = 0.722 * wstar * pow(1.0 - zeta, 0.207);
4797 dsigw2_dz = -0.215812 *
SQR(wstar) / zi * pow(1.0 - zeta, -0.586);
4799 sig_w = 0.37 * wstar;
4803 sig_w =
MAX(sig_w, 1e-6);
4804 dsigw_dz = sig_w > 1e-12 ? 0.5 * dsigw2_dz / sig_w : 0.0;
4807 tau_u = 0.15 * zi /
MAX(sig_u, 1e-12);
4810 if (z_m < fabs(ol)) {
4811 const double denom = 0.55 - 0.38 * fabs(z_m / ol);
4812 tau_w = 0.1 * z_m / (sig_w *
MAX(denom, 0.05));
4813 }
else if (zeta < 0.1)
4814 tau_w = 0.59 * z_m / sig_w;
4816 tau_w = 0.15 * zi / sig_w * (1.0 - exp(-5.0 * zeta));
4822 sig_u =
MAX(2.0 * ust * (1.0 - zeta), 1e-6);
4823 sig_v =
MAX(1.3 * ust * (1.0 - zeta), 1e-6);
4824 sig_w =
MAX(1.3 * ust * (1.0 - zeta), 1e-6);
4825 dsigw_dz = -1.3 * ust / zi;
4827 tau_u = 0.15 * zi / sig_u * sqrt(zeta);
4828 tau_v = 0.467 * tau_u;
4829 tau_w = 0.1 * zi / sig_w * pow(zeta, 0.8);
4833 tau_u =
MAX(tau_u, 10.0);
4834 tau_v =
MAX(tau_v, 10.0);
4835 tau_w =
MAX(tau_w, 30.0);
4838 if (!(sig_u > 0.0 && sig_v > 0.0
4839 && sig_w > 0.0 && tau_u > 0.0 && tau_v > 0.0 && tau_w > 0.0))
4843 const double dt = cache->
dt[ip];
4844 const double dt_abs = fabs(dt);
4846 const double ru = exp(-dt_abs / tau_u);
4847 const double ru2 = sqrt(
MAX(0.0, 1.0 -
SQR(ru)));
4848 const double rv = exp(-dt_abs / tau_v);
4849 const double rv2 = sqrt(
MAX(0.0, 1.0 -
SQR(rv)));
4852 = (float) (cache->
uvwp[ip][0] * ru + sig_u * ru2 * cache->
rs[3 * ip]);
4855 = (float) (cache->
uvwp[ip][1] * rv
4856 + sig_v * rv2 * cache->
rs[3 * ip + 1]);
4861 const double rw = exp(-dt_abs / tau_w);
4862 const double rw2 = sqrt(
MAX(0.0, 1.0 -
SQR(rw)));
4863 const double rhoaux = -1.0 / (1e3 *
H0);
4866 = (float) (cache->
uvwp[ip][2] * rw + sig_w * rw2 * cache->
rs[3 * ip + 2]
4867 + tau_w * (1.0 - rw)
4868 * (2.0 * sig_w * dsigw_dz + rhoaux *
SQR(sig_w)));
4878 double znew = z + cache->
uvwp[ip][2] * dt;
4880 while (znew < 0.0 || znew > zi) {
4884 cache->
uvwp[ip][2] = -cache->
uvwp[ip][2];
4888 znew = 2.0 * zi - znew;
4889 cache->
uvwp[ip][2] = -cache->
uvwp[ip][2];
4896 atm->
p[ip] =
P(zs + znew / 1000.0);
4899 atm->
p[ip] =
CLAMP(atm->
p[ip], pbl, ps);
4921 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4937 const double ptop = met0->
p[met0->
np - 1];
4940 const double wpbl =
pbl_weight(ctl, atm, ip, pbl, ps);
4941 const double wtrop =
tropo_weight(ctl, clim, atm, ip) * (1.0 - wpbl);
4942 const double wstrat = 1.0 - wpbl - wtrop;
4954 const double dt_abs = fabs(cache->
dt[ip]);
4959 const double sigma_h = sqrt(2.0 * Kx * dt_abs);
4964 atm->
lat[ip] +=
DY2COORD(met0, cache->
rs[3 * ip + 1] * sigma_h);
4972 const double sigma_z = sqrt(2.0 * Kz * dt_abs) * 1e-3;
4976 const double p_save = atm->
p[ip];
4981 const double eps_km = 0.01;
4982 const double p_up = p_save +
DZ2DP(eps_km, p_save);
4983 const double p_dn = p_save +
DZ2DP(-eps_km, p_save);
4986 atm->
p[ip] =
MAX(ptop,
MIN(ps, p_up));
4987 const double wpbl_up =
pbl_weight(ctl, atm, ip, pbl, ps);
4988 const double wtrop_up =
4990 const double wstrat_up = 1.0 - wpbl_up - wtrop_up;
4992 const double Kz_up =
4997 atm->
p[ip] =
MAX(ptop,
MIN(ps, p_dn));
4998 const double wpbl_dn =
pbl_weight(ctl, atm, ip, pbl, ps);
4999 const double wtrop_dn =
5001 const double wstrat_dn = 1.0 - wpbl_dn - wtrop_dn;
5003 const double Kz_dn =
5008 atm->
p[ip] = p_save;
5022 const double dKz_dz = (Kz_up - Kz_dn) / (2.0 * eps_km * 1e3);
5023 const double dlnrho_dz = -1.0 / (1e3 *
H0);
5024 const double w_drift = dKz_dz + Kz * dlnrho_dz;
5025 const double dz_drift = w_drift * dt_abs * 1e-3;
5028 const double dz_tot = cache->
rs[3 * ip + 2] * sigma_z + dz_drift;
5031 double ptrial = p_save +
DZ2DP(dz_tot, p_save);
5038 for (
int iter = 0; iter < 10; iter++) {
5040 ptrial = ps * ps / ptrial;
5041 else if (ptrial < ptop)
5042 ptrial = ptop * ptop / ptrial;
5048 atm->
p[ip] =
MAX(ptop,
MIN(ps, ptrial));
5067 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
5070 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
5082 const double dz = 1000. * (
Z(ps - ctl->
dry_depo_dp) -
Z(ps));
5102 const double aux = exp(-cache->
dt[ip] * v_dep / dz);
5103 if (ctl->
qnt_m >= 0) {
5106 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
5107 atm->
q[ctl->
qnt_m][ip] *= aux;
5127 ERRMSG(
"Only lat/lon grid supported");
5134 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
5140 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
5147 if (!(lwc > 0 || rwc > 0))
5161 const double H_SO2 =
5167 const double H_h2o2 =
5175 cor = atm->
q[ctl->
qnt_Cx][ip] >
5178 const double h2o2 = H_h2o2
5180 * M * cor * 1000. /
AVO;
5183 const double rho_air = atm->
p[ip] / (
RI * t) *
MA / 10.;
5184 const double CWC = (lwc + rwc) * rho_air / 1e3;
5187 const double rate_coef = k * K_1S * h2o2 * H_SO2 * CWC;
5188 const double aux = exp(-cache->
dt[ip] * rate_coef);
5189 if (ctl->
qnt_m >= 0) {
5192 atm->
q[ctl->
qnt_m][ip] *= aux;
5244 LOG(1,
"Read balloon pressure data: %s", ctl->
balloon);
5248 if (!(in = fopen(ctl->
balloon,
"r")))
5249 ERRMSG(
"Cannot open file!");
5253 while (fgets(line,
LEN, in))
5254 if (sscanf(line,
"%lg %lg", &(cache->
iso_ts[cache->
iso_n]),
5257 ERRMSG(
"Too many data points!");
5260 if (cache->
iso_n < 1)
5261 ERRMSG(
"Could not read any data!");
5284 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,met1,atm)") {
5309 atm->
p[ip] = cache->
iso_ps[0];
5337 const int nvar = NVAR, nfix = NFIX, nreact = NREACT;
5338 double rtol[1] = { 1.0e-3 };
5339 double atol[1] = { 1.0 };
5343#pragma acc data copy(rtol,atol,nvar,nfix,nreact)
5346 "acc data present(ctl,cache,clim,met0,met1,atm) ") {
5349 double var[nvar], fix[nfix], rconst[nreact];
5350 for (
int i = 0; i < nvar; i++)
5352 for (
int i = 0; i < nfix; i++)
5354 for (
int i = 0; i < nreact; i++)
5356 kpp_chem_initialize(ctl, clim, met0, met1, atm, var, fix, rconst, ip);
5361 for (
int i = 0; i < 20; i++) {
5368 Rosenbrock(var, fix, rconst, 0, ctl->
dt_kpp,
5369 atol, rtol, &FunTemplate, &JacTemplate, rpar, ipar);
5372 kpp_chem_output2atm(atm, ctl, met0, met1, var, ip);
5393 ERRMSG(
"Need T_ice and T_NAT to calculate T_STS!");
5397 "acc data present(ctl,cache,clim,met0,met1,atm)") {
5399 double ps, ts, zs, us, vs, ess, nss, shf, lsm, sst, pbl, pt, pct, pcb,
5400 cl, plcl, plfc, pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot,
5401 o3, lwc, rwc, iwc, swc, cc, z, zt, eta_d = 0, wdot = 0;
5411 atm->
time[ip], atm->
p[ip], atm->
lon[ip],
5412 atm->
lat[ip], &eta_d, ci, cw, 1);
5419 atm->
time[ip], atm->
p[ip], atm->
lon[ip],
5420 atm->
lat[ip], &wdot, ci, cw, 1);
5461 const double lat_ref =
5466 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
5468 lat_ref, atm->
p[ip]));
5471 SET_ATM(qnt_vh, sqrt(u * u + v * v));
5497 atm->
lat[ip], atm->
p[ip])));
5515 const int np = atm->
np;
5516 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
5517 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
5518 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
5519 double *restrict
const mixparam =
5520 (
double *) malloc((
size_t) np *
sizeof(double));
5521 if (ixs == NULL || iys == NULL || izs == NULL || mixparam == NULL)
5522 ERRMSG(
"Out of memory!");
5530 const double t0 = t - 0.5 * ctl->
dt_mod;
5531 const double t1 = t + 0.5 * ctl->
dt_mod;
5536#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np],mixparam[0:np])
5537#pragma acc data present(ctl,clim,atm,ixs,iys,izs,mixparam)
5538#pragma acc parallel loop independent gang vector
5540#pragma omp parallel for default(shared)
5542 for (
int ip = 0; ip < np; ip++) {
5543 const double zpart =
Z(atm->
p[ip]);
5544 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
5549 || zpart < ctl->mixing_z0 || zpart >= ctl->
mixing_z1) {
5555 izs[ip] = (int) ((zpart - ctl->
mixing_z0) / dz);
5564 mixparam[ip] = -expm1(-dt_mix * rate);
5568 const int use_ensemble = (ctl->
nens > 0);
5570 const int quantities[] = {
5578 const int n_qnt =
sizeof(quantities) /
sizeof(quantities[0]);
5580 for (
int i = 0; i < n_qnt; i++)
5581 if (quantities[i] >= 0)
5587#pragma acc exit data delete(ixs,iys,izs,mixparam)
5603 const double *mixparam,
5605 const int use_ensemble) {
5607 const int np = atm->
np;
5609 const int nens = use_ensemble ? ctl->
nens : 1;
5610 const int total_grid = ngrid * nens;
5612 double *restrict
const cmean =
5613 (
double *) malloc((
size_t) total_grid *
sizeof(double));
5614 double *restrict
const cweight =
5615 (
double *) malloc((
size_t) total_grid *
sizeof(double));
5616 if (cmean == NULL || cweight == NULL)
5617 ERRMSG(
"Out of memory!");
5621#pragma acc enter data create(cmean[0:total_grid],cweight[0:total_grid])
5622#pragma acc data present(ctl,atm,ixs,iys,izs,mixparam,cmean,cweight)
5623#pragma acc parallel loop independent gang vector
5628#pragma omp parallel for
5630 for (
int i = 0; i < total_grid; i++) {
5637#pragma acc parallel loop independent gang vector
5639 for (
int ip = 0; ip < np; ip++)
5641 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
5642 if (ens < 0 || ens >= nens)
5648#pragma acc atomic update
5650 cmean[idx] += mixparam[ip] * atm->
q[qnt_idx][ip];
5652#pragma acc atomic update
5654 cweight[idx] += mixparam[ip];
5659#pragma acc parallel loop independent gang vector
5664#pragma omp parallel for
5666 for (
int i = 0; i < total_grid; i++)
5668 cmean[i] /= cweight[i];
5672#pragma acc parallel loop independent gang vector
5674#pragma omp parallel for
5676 for (
int ip = 0; ip < np; ip++) {
5678 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
5680 if (ens < 0 || ens >= nens)
5685 atm->
q[qnt_idx][ip] +=
5686 (cmean[idx] - atm->
q[qnt_idx][ip]) * mixparam[ip];
5692#pragma acc exit data delete(cmean,cweight)
5713 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
5716 const double a = 4.71572206e-08;
5717 const double b = -8.28782867e-01;
5718 const double low = pow(1. / a, 1. / b);
5722 "acc data present(ctl,cache,clim,met0,met1,atm)") {
5748 0 ? pow(298. / t, ctl->
oh_chem[1]) : 1.);
5751 0 ? pow(298. / t, ctl->
oh_chem[3]) : 1.);
5752 const double c = log10(k0 * M / ki);
5753 k = k0 * M / (1. + k0 * M / ki) * pow(0.6, 1. / (1. + c * c));
5762 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
5765 const double rate_coef =
5767 atm->
lat[ip], atm->
p[ip]) * M * cor;
5768 const double aux = exp(-cache->
dt[ip] * rate_coef);
5769 if (ctl->
qnt_m >= 0) {
5772 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
5773 atm->
q[ctl->
qnt_m][ip] *= aux;
5789 const int reflect) {
5795 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(cache,met0,met1,atm)") {
5807 while (atm->
lat[ip] < -90 || atm->
lat[ip] > 90) {
5808 if (atm->
lat[ip] > 90) {
5809 atm->
lat[ip] = 180 - atm->
lat[ip];
5810 atm->
lon[ip] += 180;
5812 if (atm->
lat[ip] < -90) {
5813 atm->
lat[ip] = -180 - atm->
lat[ip];
5814 atm->
lon[ip] += 180;
5819 while (atm->
lon[ip] < -180)
5820 atm->
lon[ip] += 360;
5821 while (atm->
lon[ip] >= 180)
5822 atm->
lon[ip] -= 360;
5825 atm->
lon[ip], atm->
lat[ip], &atm->
lon[ip],
5830 const double ptop = met0->
p[met0->
np - 1];
5831 if (atm->
p[ip] < ptop) {
5832 atm->
p[ip] = reflect ? ptop * ptop / atm->
p[ip] : ptop;
5833 }
else if (atm->
p[ip] > 300.) {
5835 if (atm->
p[ip] > ps)
5836 atm->
p[ip] = reflect ? ps * ps / atm->
p[ip] : ps;
5863 const double dt = cache->
dt[ip];
5867 atm->
q[ctl->
qnt_Apb210][ip] *= exp(-dt * lambda_pb210);
5872 const double aux = exp(-dt * lambda_rn222);
5873 const double lost = old * (1.0 - aux);
5878 atm->
q[ctl->
qnt_Apb210][ip] += lost * lambda_pb210 / lambda_rn222;
5883 atm->
q[ctl->
qnt_Abe7][ip] *= exp(-dt * lambda_be7);
5887 atm->
q[ctl->
qnt_Acs137][ip] *= exp(-dt * lambda_cs137);
5891 atm->
q[ctl->
qnt_Ai131][ip] *= exp(-dt * lambda_i131);
5895 atm->
q[ctl->
qnt_Axe133][ip] *= exp(-dt * lambda_xe133);
5924 "acc data present(ctl,cache,met0,met1,atm,depo)") {
5927 const double dt = cache->
dt[ip];
5937 double dry_pb210 = 0, dry_be7 = 0, dry_cs137 = 0, dry_i131 = 0;
5939 const double dz = 1000. * (
Z(ps - ctl->
dry_depo_dp) -
Z(ps));
5949 double wet_pb210 = 0, wet_be7 = 0, wet_cs137 = 0, wet_i131 = 0;
5952 if (isfinite(pct) && atm->
p[ip] > pct) {
5959 double lwc, rwc, iwc, swc, t;
5965 const int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
5990 const int ix = ingrid
5992 const int iy = ingrid
6000 const double aux = exp(-dt * (dry_pb210 + wet_pb210));
6001 const double lost = old * (1. - aux);
6002 const double deposited = lost
6003 * (ctl->
radio_decay ? exp(lambda_pb210 * tref) : 1.0);
6005 if (ingrid && lost > 0) {
6007#pragma acc atomic update
6009#pragma omp atomic update
6011 depo->
Apb210[idx] += deposited;
6017 const double old = atm->
q[ctl->
qnt_Abe7][ip];
6018 const double aux = exp(-dt * (dry_be7 + wet_be7));
6019 const double lost = old * (1. - aux);
6020 const double deposited = lost
6021 * (ctl->
radio_decay ? exp(lambda_be7 * tref) : 1.0);
6023 if (ingrid && lost > 0) {
6025#pragma acc atomic update
6027#pragma omp atomic update
6029 depo->
Abe7[idx] += deposited;
6036 const double aux = exp(-dt * (dry_cs137 + wet_cs137));
6037 const double lost = old * (1. - aux);
6038 const double deposited = lost
6039 * (ctl->
radio_decay ? exp(lambda_cs137 * tref) : 1.0);
6041 if (ingrid && lost > 0) {
6043#pragma acc atomic update
6045#pragma omp atomic update
6047 depo->
Acs137[idx] += deposited;
6053 const double old = atm->
q[ctl->
qnt_Ai131][ip];
6054 const double aux = exp(-dt * (dry_i131 + wet_i131));
6055 const double lost = old * (1. - aux);
6056 const double deposited = lost
6057 * (ctl->
radio_decay ? exp(lambda_i131 * tref) : 1.0);
6059 if (ingrid && lost > 0) {
6061#pragma acc atomic update
6063#pragma omp atomic update
6065 depo->
Ai131[idx] += deposited;
6077 gsl_rng_env_setup();
6078 if (omp_get_max_threads() >
NTHREADS)
6079 ERRMSG(
"Too many threads!");
6080 for (
int i = 0; i <
NTHREADS; i++) {
6081 rng[i] = gsl_rng_alloc(gsl_rng_default);
6082 gsl_rng_set(rng[i], gsl_rng_default_seed
6083 + (
long unsigned) (ntask *
NTHREADS + i));
6088 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
6089 CURAND_STATUS_SUCCESS)
6090 ERRMSG(
"Cannot create random number generator!");
6091 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
6092 CURAND_STATUS_SUCCESS)
6093 ERRMSG(
"Cannot set seed for random number generator!");
6096 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
6097 CURAND_STATUS_SUCCESS)
6098 ERRMSG(
"Cannot set stream for random number generator!");
6115#pragma omp parallel for default(shared)
6116 for (
size_t i = 0; i < n; ++i)
6117 rs[i] = gsl_rng_uniform(rng[omp_get_thread_num()]);
6121 else if (method == 1) {
6122#pragma omp parallel for default(shared)
6123 for (
size_t i = 0; i < n; ++i)
6124 rs[i] = gsl_ran_gaussian_ziggurat(rng[omp_get_thread_num()], 1.0);
6130#pragma acc update device(rs[:n])
6138 const uint64_t key = 0xc8e4fd154ce32f6d;
6142#pragma acc data present(rs)
6143#pragma acc parallel loop independent gang vector
6145#pragma omp parallel for default(shared)
6147 for (
size_t i = 0; i < n + 1; ++i) {
6148 uint64_t r, t, x, y, z;
6149 y = x = (rng_ctr + i) * key;
6152 x = (x >> 32) | (x << 32);
6154 x = (x >> 32) | (x << 32);
6156 x = (x >> 32) | (x << 32);
6158 x = (x >> 32) | (x << 32);
6159 r = t ^ ((x * x + y) >> 32);
6160 rs[i] = (double) r / (
double) UINT64_MAX;
6167#pragma acc parallel loop independent gang vector
6169#pragma omp parallel for default(shared)
6171 for (
size_t i = 0; i < n; i += 2) {
6172 const double r = sqrt(-2.0 * log(rs[i]));
6173 const double phi = 2.0 * M_PI * rs[i + 1];
6174 rs[i] = r * cosf((
float) phi);
6175 rs[i + 1] = r * sinf((
float) phi);
6183#pragma acc host_data use_device(rs)
6188 if (curandGenerateUniformDouble(rng_curand, rs, (n < 4 ? 4 : n)) !=
6189 CURAND_STATUS_SUCCESS)
6190 ERRMSG(
"Cannot create random numbers!");
6194 else if (method == 1) {
6195 if (curandGenerateNormalDouble
6196 (rng_curand, rs, (n < 4 ? 4 : n), 0.0,
6197 1.0) != CURAND_STATUS_SUCCESS)
6198 ERRMSG(
"Cannot create random numbers!");
6202 ERRMSG(
"MPTRAC was compiled without cuRAND!");
6219 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
6227 const double v_s =
sedi(atm->
p[ip], t, atm->
q[ctl->
qnt_rp][ip],
6231 atm->
p[ip] +=
DZ2DP(v_s * cache->
dt[ip] / 1000., atm->
p[ip]);
6247 const int np = atm->
np;
6248 double *restrict
const a = (
double *) malloc((
size_t) np *
sizeof(double));
6249 int *restrict
const p = (
int *) malloc((
size_t) np *
sizeof(int));
6250 if (a == NULL || p == NULL)
6251 ERRMSG(
"Out of memory!");
6254#pragma acc enter data create(a[0:np],p[0:np])
6255#pragma acc data present(ctl,met0,cache,atm,a,p)
6260#pragma acc parallel loop independent gang vector
6262#pragma omp parallel for default(shared)
6264 for (
int ip = 0; ip < np; ip++) {
6275#pragma acc host_data use_device(a,p)
6277 thrustSortWrapper(a, np, p);
6279 size_t *perm_sz = (
size_t *) malloc((
size_t) np *
sizeof(size_t));
6280 if (perm_sz == NULL)
6281 ERRMSG(
"Out of memory!");
6283#pragma acc update self(a[0:np])
6285 gsl_sort_index(perm_sz, a, 1, (
size_t) np);
6286 for (
int ip = 0; ip < np; ++ip)
6287 p[ip] = (
int) perm_sz[ip];
6290#pragma acc update device(p[0:np])
6299 for (
int iq = 0; iq < ctl->
nq; iq++)
6306#pragma acc exit data delete(a,p)
6324 const double latmin = gsl_stats_min(met0->
lat, 1, (
size_t) met0->
ny),
6325 latmax = gsl_stats_max(met0->
lat, 1, (
size_t) met0->
ny);
6328 (fabs(met0->
lon[met0->
nx - 1] - met0->
lon[0] - 360.0) >= 0.01);
6331 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,atm)") {
6337 cache->
dt[ip] = t - atm->
time[ip];
6339 cache->
dt[ip] = 0.0;
6345 int dd = (ctl->
dd) ? 0 : 1;
6351 || atm->
lon[ip] >= met0->
lon[met0->
nx - 1]
6352 || atm->
lat[ip] <= latmin || atm->
lat[ip] >= latmax))
6353 cache->
dt[ip] = 0.0;
6372 ctl->
t_start = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
6374 ctl->
t_stop = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
6376 ctl->
t_start = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
6378 ctl->
t_stop = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
6383 ERRMSG(
"Nothing to do! Check T_STOP and DIRECTION!");
6403 ERRMSG(
"Only lat/lon grid supported");
6410 "acc data present(ctl,cache,clim,met0,met1,atm)") {
6434 const double K_o1d =
6437 atm->
p[ip], sza, o3c);
6438 atm->
q[ctl->
qnt_Cccl4][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
6443 const double K_o1d =
6446 atm->
p[ip], sza, o3c);
6447 atm->
q[ctl->
qnt_Cccl3f][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
6452 const double K_o1d =
6455 atm->
p[ip], sza, o3c);
6456 atm->
q[ctl->
qnt_Cccl2f2][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
6461 const double K_o1d =
6464 atm->
p[ip], sza, o3c);
6465 atm->
q[ctl->
qnt_Cn2o][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
6484 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
6487 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
6493 if (!isfinite(pct) || atm->
p[ip] <= pct)
6509 double lwc, rwc, iwc, swc;
6514 const int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
6554 h *= (1. + K_1 / H_ion + K_1 * K_2 /
SQR(H_ion));
6558 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
6561 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
6587 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
6590 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
6595 const double aux = exp(-cache->
dt[ip] * lambda);
6596 if (ctl->
qnt_m >= 0) {
6599 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
6600 atm->
q[ctl->
qnt_m][ip] *= aux;
6623 if (ctl != NULL || cache != NULL || clim != NULL || met0 != NULL
6624 || met1 != NULL || atm != NULL || depo != NULL || dd != NULL) {
6626 if (acc_get_num_devices(acc_device_nvidia) <= 0)
6627 ERRMSG(
"Not running on a GPU device!");
6628 acc_device_t device_type = acc_get_device_type();
6629 acc_init(device_type);
6655 (*dd)->MPI_Particle = MPI_DATATYPE_NULL;
6663 ctl_t *ctlup = *ctl;
6664#pragma acc enter data create(ctlup[:1])
6666 if (cache != NULL) {
6668#pragma acc enter data create(cacheup[:1])
6672#pragma acc enter data create(climup[:1])
6675 met_t *met0up = *met0;
6676#pragma acc enter data create(met0up[:1])
6679 met_t *met1up = *met1;
6680#pragma acc enter data create(met1up[:1])
6683 atm_t *atmup = *atm;
6684#pragma acc enter data create(atmup[:1])
6688#pragma acc enter data create(depoup[:1])
6693#pragma acc enter data create(ddup[:1])
6713 if (dd_node != NULL) {
6715 MPI_Comm_rank(MPI_COMM_WORLD, &
rank);
6716 LOG(2,
"DD_COMM rank=%d sent=%llu intra=%llu inter=%llu "
6717 "intra_bytes=%llu inter_bytes=%llu particle_bytes=%d",
6718 rank, dd_sent, dd_intra, dd_inter,
6719 dd_intra * (
unsigned long long) dd_particle_bytes,
6720 dd_inter * (
unsigned long long) dd_particle_bytes,
6732#pragma acc exit data delete(ctl[:1])
6734 if (cache != NULL) {
6735#pragma acc exit data delete(cache[:1])
6738#pragma acc exit data delete(clim[:1])
6741#pragma acc exit data delete(met0[:1])
6744#pragma acc exit data delete(met1[:1])
6747#pragma acc exit data delete(atm[:1])
6750#pragma acc exit data delete(depo[:1])
6754#pragma acc exit data delete(dd[:1])
6771 if (dd != NULL && dd->
MPI_Particle != MPI_DATATYPE_NULL)
6791 char cachefile[
LEN], cmd[2 *
LEN], filename[
LEN];
6797 if (t == ctl->
t_start || !init) {
6804 ERRMSG(
"Cannot open file!");
6809 ERRMSG(
"Cannot open file!");
6819 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
6820 LOG(1,
"Caching: %s", cachefile);
6821 if (system(cmd) != 0)
6822 WARN(
"Caching command failed!");
6827 if (t > (*met1)->time) {
6837 ERRMSG(
"Cannot open file!");
6847 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
6848 LOG(1,
"Caching: %s", cachefile);
6849 if (system(cmd) != 0)
6850 WARN(
"Caching command failed!");
6855 if (t < (*met0)->time) {
6865 ERRMSG(
"Cannot open file!");
6875 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
6876 LOG(1,
"Caching: %s", cachefile);
6877 if (system(cmd) != 0)
6878 WARN(
"Caching command failed!");
6882 if ((*met0)->coord_type != (*met1)->coord_type)
6883 ERRMSG(
"Coordinate types do not match!");
6886 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
6887 if ((*met0)->nx != (*met1)->nx
6888 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
6889 ERRMSG(
"Meteo grid dimensions do not match!");
6890 for (
int ix = 0; ix < (*met0)->nx; ix++)
6891 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
6892 ERRMSG(
"Meteo grid longitudes do not match!");
6893 for (
int iy = 0; iy < (*met0)->ny; iy++)
6894 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
6895 ERRMSG(
"Meteo grid latitudes do not match!");
6896 for (
int ip = 0; ip < (*met0)->np; ip++)
6897 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
6898 ERRMSG(
"Meteo grid pressure levels do not match!");
6921#pragma acc update device(depo[:1])
6930 const char *filename,
6943 LOG(1,
"Read atmospheric data: %s", filename);
6963 ERRMSG(
"Atmospheric data type not supported!");
6971 ERRMSG(
"Can not read any data!");
6975 LOG(2,
"Number of particles: %d", atm->
np);
6976 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
6977 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
6978 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
6979 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
6980 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
6981 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
6982 LOG(2,
"%s range: %g ... %g %s",
6983 ctl->
met_coord_type == 0 ?
"Longitude" :
"X coordinate", mini, maxi,
6985 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
6986 LOG(2,
"%s range: %g ... %g %s",
6987 ctl->
met_coord_type == 0 ?
"Latitude" :
"Y coordinate", mini, maxi,
6989 for (
int iq = 0; iq < ctl->
nq; iq++) {
6991 sprintf(msg,
"Quantity %s range: %s ... %s %s",
6994 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
6995 LOG(2, msg, mini, maxi);
7065 const char *filename,
7074 LOG(1,
"\nMassive-Parallel Trajectory Calculations (MPTRAC)\n"
7075 "(executable: %s | version: %s | compiled: %s, %s)\n",
7076 argv[0], VERSION, __DATE__, __TIME__);
7185 ctl->
nq = (int)
scan_ctl(filename, argc, argv,
"NQ", -1,
"0", NULL);
7187 ERRMSG(
"Too many quantities!");
7188 for (
int iq = 0; iq < ctl->
nq; iq++) {
7194 scan_ctl(filename, argc, argv,
"QNT_FORMAT", iq,
"%g",
7196 if (strcasecmp(ctl->
qnt_name[iq],
"aoa") == 0)
7200 SET_QNT(qnt_idx,
"idx",
"particle index",
"-")
7201 SET_QNT(qnt_ens,
"ens",
"ensemble index",
"-")
7202 SET_QNT(qnt_stat,
"stat",
"station flag",
"-")
7203 SET_QNT(qnt_m,
"m",
"mass",
"kg")
7204 SET_QNT(qnt_vmr,
"vmr",
"volume mixing ratio",
"ppv")
7205 SET_QNT(qnt_rp,
"rp",
"particle radius",
"microns")
7206 SET_QNT(qnt_rhop,
"rhop",
"particle density",
"kg/m^3")
7207 SET_QNT(qnt_ps,
"ps",
"surface pressure",
"hPa")
7208 SET_QNT(qnt_ts,
"ts",
"surface temperature",
"K")
7209 SET_QNT(qnt_zs,
"zs",
"surface height",
"km")
7210 SET_QNT(qnt_us,
"us",
"surface zonal wind",
"m/s")
7211 SET_QNT(qnt_vs,
"vs",
"surface meridional wind",
"m/s")
7212 SET_QNT(qnt_ess,
"ess",
"eastward turbulent surface stress",
"N/m^2")
7213 SET_QNT(qnt_nss,
"nss",
"northward turbulent surface stress",
"N/m^2")
7214 SET_QNT(qnt_shf,
"shf",
"surface sensible heat flux",
"W/m^2")
7215 SET_QNT(qnt_lsm,
"lsm",
"land-sea mask",
"1")
7216 SET_QNT(qnt_sst,
"sst",
"sea surface temperature",
"K")
7217 SET_QNT(qnt_pbl,
"pbl",
"planetary boundary layer",
"hPa")
7218 SET_QNT(qnt_pt,
"pt",
"tropopause pressure",
"hPa")
7219 SET_QNT(qnt_tt,
"tt",
"tropopause temperature",
"K")
7220 SET_QNT(qnt_zt,
"zt",
"tropopause geopotential height",
"km")
7221 SET_QNT(qnt_h2ot,
"h2ot",
"tropopause water vapor",
"ppv")
7222 SET_QNT(qnt_zg,
"zg",
"geopotential height",
"km")
7223 SET_QNT(qnt_p,
"p",
"pressure",
"hPa")
7224 SET_QNT(qnt_t,
"t",
"temperature",
"K")
7225 SET_QNT(qnt_rho,
"rho",
"air density",
"kg/m^3")
7226 SET_QNT(qnt_u,
"u",
"zonal wind",
"m/s")
7227 SET_QNT(qnt_v,
"v",
"meridional wind",
"m/s")
7228 SET_QNT(qnt_w,
"w",
"vertical velocity",
"hPa/s")
7229 SET_QNT(qnt_h2o,
"h2o",
"water vapor",
"ppv")
7230 SET_QNT(qnt_o3,
"o3",
"ozone",
"ppv")
7231 SET_QNT(qnt_lwc,
"lwc",
"cloud liquid water content",
"kg/kg")
7232 SET_QNT(qnt_rwc,
"rwc",
"cloud rain water content",
"kg/kg")
7233 SET_QNT(qnt_iwc,
"iwc",
"cloud ice water content",
"kg/kg")
7234 SET_QNT(qnt_swc,
"swc",
"cloud snow water content",
"kg/kg")
7235 SET_QNT(qnt_cc,
"cc",
"cloud cover",
"1")
7236 SET_QNT(qnt_pct,
"pct",
"cloud top pressure",
"hPa")
7237 SET_QNT(qnt_pcb,
"pcb",
"cloud bottom pressure",
"hPa")
7238 SET_QNT(qnt_cl,
"cl",
"total column cloud water",
"kg/m^2")
7239 SET_QNT(qnt_plcl,
"plcl",
"lifted condensation level",
"hPa")
7240 SET_QNT(qnt_plfc,
"plfc",
"level of free convection",
"hPa")
7241 SET_QNT(qnt_pel,
"pel",
"equilibrium level",
"hPa")
7242 SET_QNT(qnt_cape,
"cape",
"convective available potential energy",
7244 SET_QNT(qnt_cin,
"cin",
"convective inhibition",
"J/kg")
7245 SET_QNT(qnt_o3c,
"o3c",
"total column ozone",
"DU")
7246 SET_QNT(qnt_hno3,
"hno3",
"nitric acid",
"ppv")
7247 SET_QNT(qnt_oh,
"oh",
"hydroxyl radical",
"ppv")
7248 SET_QNT(qnt_h2o2,
"h2o2",
"hydrogen peroxide",
"ppv")
7249 SET_QNT(qnt_ho2,
"ho2",
"hydroperoxyl radical",
"ppv")
7250 SET_QNT(qnt_o1d,
"o1d",
"atomic oxygen",
"ppv")
7251 SET_QNT(qnt_mloss_oh,
"mloss_oh",
"mass loss due to OH chemistry",
"kg")
7252 SET_QNT(qnt_mloss_h2o2,
"mloss_h2o2",
7253 "mass loss due to H2O2 chemistry",
"kg")
7254 SET_QNT(qnt_mloss_kpp,
"mloss_kpp",
"mass loss due to kpp chemistry",
7256 SET_QNT(qnt_mloss_wet,
"mloss_wet",
"mass loss due to wet deposition",
7258 SET_QNT(qnt_mloss_dry,
"mloss_dry",
"mass loss due to dry deposition",
7260 SET_QNT(qnt_mloss_decay,
"mloss_decay",
7261 "mass loss due to exponential decay",
"kg")
7262 SET_QNT(qnt_loss_rate,
"loss_rate",
"total loss rate",
"s^-1")
7263 SET_QNT(qnt_psat,
"psat",
"saturation pressure over water",
"hPa")
7264 SET_QNT(qnt_psice,
"psice",
"saturation pressure over ice",
"hPa")
7265 SET_QNT(qnt_pw,
"pw",
"partial water vapor pressure",
"hPa")
7266 SET_QNT(qnt_sh,
"sh",
"specific humidity",
"kg/kg")
7267 SET_QNT(qnt_rh,
"rh",
"relative humidity",
"%%")
7268 SET_QNT(qnt_rhice,
"rhice",
"relative humidity over ice",
"%%")
7269 SET_QNT(qnt_theta,
"theta",
"potential temperature",
"K")
7270 SET_QNT(qnt_iso_var,
"iso_var",
"isosurface reference value",
"varies")
7271 SET_QNT(qnt_zeta,
"zeta",
"zeta coordinate",
"K")
7272 SET_QNT(qnt_zeta_d,
"zeta_d",
"diagnosed zeta coordinate",
"K")
7273 SET_QNT(qnt_zeta_dot,
"zeta_dot",
"velocity of zeta coordinate",
7275 SET_QNT(qnt_eta,
"eta",
"eta coordinate",
"1")
7276 SET_QNT(qnt_eta_d,
"eta_d",
"diagnosed eta coordinate",
"1")
7277 SET_QNT(qnt_eta_dot,
"eta_dot",
"velocity of eta coordinate",
"1/s")
7278 SET_QNT(qnt_tvirt,
"tvirt",
"virtual temperature",
"K")
7279 SET_QNT(qnt_lapse,
"lapse",
"temperature lapse rate",
"K/km")
7280 SET_QNT(qnt_vh,
"vh",
"horizontal velocity",
"m/s")
7281 SET_QNT(qnt_vz,
"vz",
"vertical velocity",
"m/s")
7282 SET_QNT(qnt_pv,
"pv",
"potential vorticity",
"PVU")
7283 SET_QNT(qnt_tdew,
"tdew",
"dew point temperature",
"K")
7284 SET_QNT(qnt_tice,
"tice",
"frost point temperature",
"K")
7285 SET_QNT(qnt_tsts,
"tsts",
"STS existence temperature",
"K")
7286 SET_QNT(qnt_tnat,
"tnat",
"NAT existence temperature",
"K")
7287 SET_QNT(qnt_Cx,
"Cx",
"Trace species x volume mixing ratio",
"ppv")
7288 SET_QNT(qnt_Ch2o,
"Ch2o",
"H2O volume mixing ratio",
"ppv")
7289 SET_QNT(qnt_Co3,
"Co3",
"O3 volume mixing ratio",
"ppv")
7290 SET_QNT(qnt_Cco,
"Cco",
"CO volume mixing ratio",
"ppv")
7291 SET_QNT(qnt_Coh,
"Coh",
"HO volume mixing ratio",
"ppv")
7292 SET_QNT(qnt_Ch,
"Ch",
"H radical volume mixing ratio",
"ppv")
7293 SET_QNT(qnt_Cho2,
"Cho2",
"HO2 volume mixing ratio",
"ppv")
7294 SET_QNT(qnt_Ch2o2,
"Ch2o2",
"H2O2 volume mixing ratio",
"ppv")
7295 SET_QNT(qnt_Co1d,
"Co1d",
"O(1D) volume mixing ratio",
"ppv")
7296 SET_QNT(qnt_Co3p,
"Co3p",
"O(3P) radical volume mixing ratio",
"ppv")
7297 SET_QNT(qnt_Cccl4,
"Cccl4",
"CCl4 (CFC-10) volume mixing ratio",
"ppv")
7298 SET_QNT(qnt_Cccl3f,
"Cccl3f",
"CCl3F (CFC-11) volume mixing ratio",
7300 SET_QNT(qnt_Cccl2f2,
"Cccl2f2",
"CCl2F2 (CFC-12) volume mixing ratio",
7302 SET_QNT(qnt_Cn2o,
"Cn2o",
"N2O volume mixing ratio",
"ppv")
7303 SET_QNT(qnt_Csf6,
"Csf6",
"SF6 volume mixing ratio",
"ppv")
7304 SET_QNT(qnt_aoa,
"aoa",
"age of air",
"s")
7305 SET_QNT(qnt_Arn222,
"Arn222",
"Rn-222 activity",
"Bq")
7306 SET_QNT(qnt_Apb210,
"Apb210",
"Pb-210 activity",
"Bq")
7307 SET_QNT(qnt_Abe7,
"Abe7",
"Be-7 activity",
"Bq")
7308 SET_QNT(qnt_Acs137,
"Acs137",
"Cs-137 activity",
"Bq")
7309 SET_QNT(qnt_Ai131,
"Ai131",
"I-131 activity",
"Bq")
7310 SET_QNT(qnt_Axe133,
"Axe133",
"Xe-133 activity",
"Bq")
7311 SET_QNT(qnt_current_subdomain,
"current_subdomain",
7312 "current subdomain rank",
"-")
7313 SET_QNT(qnt_target_subdomain,
"target_subdomain",
7314 "target subdomain rank",
"-")
7319 (int)
scan_ctl(filename, argc, argv,
"MET_COORD_TYPE", -1,
"0", NULL);
7321 ERRMSG(
"MET_COORD_TYPE must be 0 or 1!");
7326 scan_ctl(filename, argc, argv,
"MET_UTM_REF_LAT", -1,
"", NULL);
7328 scan_ctl(filename, argc, argv,
"MET_UTM_REF_LON", -1,
"", NULL);
7333 (int)
scan_ctl(filename, argc, argv,
"ADVECT_VERT_COORD", -1,
"0", NULL);
7335 ERRMSG(
"ADVECT_VERT_COORD must be 0, 1, 2, or 3!");
7338 ERRMSG(
"Add quantity zeta for diabatic advection!");
7340 ERRMSG(
"Add quantity eta for etadot avection!");
7343 (int)
scan_ctl(filename, argc, argv,
"MET_VERT_COORD", -1,
"0", NULL);
7345 ERRMSG(
"MET_VERT_COORD must be 0, 1, 2, 3, or 4!");
7348 ERRMSG(
"Quantity eta_d requires full-level A and B coefficients!");
7352 (
"Using ADVECT_VERT_COORD = 2 requires meteo data on model levels!");
7355 (
"Using ADVECT_VERT_COORD = 3 requires A and B model level coefficients!");
7358 (int)
scan_ctl(filename, argc, argv,
"MET_GP2Z", -1,
"0", NULL);
7360 ERRMSG(
"Set MET_GP2Z to 0 or 1!");
7364 (int)
scan_ctl(filename, argc, argv,
"DIRECTION", -1,
"1", NULL);
7366 ERRMSG(
"Set DIRECTION to -1 or 1!");
7367 ctl->
t_stop =
scan_ctl(filename, argc, argv,
"T_STOP", -1,
"1e100", NULL);
7368 ctl->
dt_mod =
scan_ctl(filename, argc, argv,
"DT_MOD", -1,
"180", NULL);
7372 ctl->
dt_met =
scan_ctl(filename, argc, argv,
"DT_MET", -1,
"3600", NULL);
7374 ERRMSG(
"DT_MOD must not exceed DT_MET!");
7376 (int)
scan_ctl(filename, argc, argv,
"MET_CONVENTION", -1,
"0", NULL);
7378 (int)
scan_ctl(filename, argc, argv,
"MET_TYPE", -1,
"0", NULL);
7381 (
"Please use meteo files in netcdf format for diabatic calculations.");
7384 (
"Please use meteo files in netcdf format for etadot calculations.");
7386 (int)
scan_ctl(filename, argc, argv,
"MET_CLAMS", -1,
"0", NULL);
7388 (int)
scan_ctl(filename, argc, argv,
"MET_NC_SCALE", -1,
"1", NULL);
7390 (int)
scan_ctl(filename, argc, argv,
"MET_NC_READ_MODE", -1,
"0", NULL);
7392 ERRMSG(
"Set MET_NC_READ_MODE to 0 or 1!");
7394 (int)
scan_ctl(filename, argc, argv,
"MET_NC_LEVEL", -1,
"0", NULL);
7396 (int)
scan_ctl(filename, argc, argv,
"MET_NC_QUANT", -1,
"0", NULL);
7398 (int)
scan_ctl(filename, argc, argv,
"MET_ZSTD_LEVEL", -1,
"-3", NULL);
7400 (int)
scan_ctl(filename, argc, argv,
"MET_ZSTD_NWORKERS", -1,
"4", NULL);
7402 (int)
scan_ctl(filename, argc, argv,
"MET_LZ4_ACCEL", -1,
"8", NULL);
7404 (int)
scan_ctl(filename, argc, argv,
"MET_PCK_ZSTD", -1,
"0", NULL);
7406 ERRMSG(
"Set MET_PCK_ZSTD to 0 or 1!");
7409 ERRMSG(
"MET_PCK_ZSTD requires MPTRAC to be compiled with ZSTD support!");
7411 const int def_lossy_scale =
7412 (int)
scan_ctl(filename, argc, argv,
"MET_LOSSY_SCALE", -1,
"0", NULL);
7413 for (
int i = 0; i <
METVAR; i++) {
7414 char defprec_zfp[
LEN] =
"7", deftol_zfp[
LEN] =
"0.0";
7415 char defprec_sz3[
LEN] =
"6", deftol_sz3[
LEN] =
"0.0";
7417 sprintf(defprec_zfp,
"12");
7418 sprintf(defprec_sz3,
"11");
7419 }
else if (i == 1) {
7420 sprintf(defprec_zfp,
"11");
7421 sprintf(defprec_sz3,
"7");
7422 }
else if (i == 2 || i == 3) {
7423 sprintf(defprec_zfp,
"7");
7424 sprintf(defprec_sz3,
"7");
7425 }
else if (i == 4) {
7426 sprintf(defprec_zfp,
"6");
7427 sprintf(defprec_sz3,
"13");
7428 }
else if (i == 5) {
7429 sprintf(defprec_zfp,
"7");
7430 sprintf(defprec_sz3,
"20");
7431 }
else if (i == 6) {
7432 sprintf(defprec_zfp,
"10");
7433 sprintf(defprec_sz3,
"18");
7434 }
else if (i == 7) {
7435 sprintf(defprec_zfp,
"9");
7436 sprintf(defprec_sz3,
"10");
7437 }
else if (i >= 8 && i <= 11) {
7438 sprintf(defprec_zfp,
"6");
7439 sprintf(defprec_sz3,
"13");
7440 }
else if (i == 12) {
7441 sprintf(defprec_zfp,
"9");
7442 sprintf(defprec_sz3,
"6");
7445 (int)
scan_ctl(filename, argc, argv,
"MET_ZFP_PREC", i, defprec_zfp,
7448 scan_ctl(filename, argc, argv,
"MET_ZFP_TOL", i, deftol_zfp, NULL);
7450 (int)
scan_ctl(filename, argc, argv,
"MET_SZ3_PREC", i, defprec_sz3,
7453 scan_ctl(filename, argc, argv,
"MET_SZ3_TOL", i, deftol_sz3, NULL);
7455 snprintf(defscale,
LEN,
"%d", def_lossy_scale);
7457 (int)
scan_ctl(filename, argc, argv,
"MET_LOSSY_SCALE", i, defscale,
7460 ERRMSG(
"Set MET_LOSSY_SCALE to 0 or 1!");
7464 scan_ctl(filename, argc, argv,
"MET_COMP_LOGFILE", -1,
"-",
7467 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_BATCH", -1,
"-1", NULL);
7469 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ZSTD", -1,
"1", NULL);
7471 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ND0X", -1,
"48", NULL);
7473 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ND0Y", -1,
"24", NULL);
7475 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_MAXLEV", -1,
"6", NULL);
7476 for (
int i = 0; i <
METVAR; i++) {
7477 char defeps[
LEN] =
"1.0";
7478 if (i == 1 || i == 2 || i == 3)
7479 sprintf(defeps,
"0.05");
7481 scan_ctl(filename, argc, argv,
"MET_CMS_EPS", i, defeps, NULL);
7483 ctl->
met_dx = (int)
scan_ctl(filename, argc, argv,
"MET_DX", -1,
"1", NULL);
7484 ctl->
met_dy = (int)
scan_ctl(filename, argc, argv,
"MET_DY", -1,
"1", NULL);
7485 ctl->
met_dp = (int)
scan_ctl(filename, argc, argv,
"MET_DP", -1,
"1", NULL);
7487 ERRMSG(
"MET_DX, MET_DY, and MET_DP need to be greater than zero!");
7488 ctl->
met_sx = (int)
scan_ctl(filename, argc, argv,
"MET_SX", -1,
"1", NULL);
7489 ctl->
met_sy = (int)
scan_ctl(filename, argc, argv,
"MET_SY", -1,
"1", NULL);
7490 ctl->
met_sp = (int)
scan_ctl(filename, argc, argv,
"MET_SP", -1,
"1", NULL);
7492 ERRMSG(
"MET_SX, MET_SY, and MET_SP need to be greater than zero!");
7494 scan_ctl(filename, argc, argv,
"MET_DETREND", -1,
"-999", NULL);
7495 ctl->
met_np = (int)
scan_ctl(filename, argc, argv,
"MET_NP", -1,
"0", NULL);
7497 ERRMSG(
"Too many pressure levels!");
7499 (int)
scan_ctl(filename, argc, argv,
"MET_PRESS_LEVEL_DEF", -1,
"-1",
7505 for (
int ip = 0; ip < ctl->
met_np; ip++)
7507 scan_ctl(filename, argc, argv,
"MET_P", ip,
"", NULL);
7511 (int)
scan_ctl(filename, argc, argv,
"MET_NLEV", -1,
"0", NULL);
7513 ERRMSG(
"Too many model levels!");
7514 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
7516 scan_ctl(filename, argc, argv,
"MET_LEV_HYAM", ip,
"", NULL);
7517 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
7519 scan_ctl(filename, argc, argv,
"MET_LEV_HYBM", ip,
"", NULL);
7521 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SX", -1,
"-1", NULL);
7523 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SY", -1,
"-1", NULL);
7525 (int)
scan_ctl(filename, argc, argv,
"MET_RELHUM", -1,
"0", NULL);
7527 (int)
scan_ctl(filename, argc, argv,
"MET_CAPE", -1,
"1", NULL);
7529 ERRMSG(
"Set MET_CAPE to 0 or 1!");
7531 (int)
scan_ctl(filename, argc, argv,
"MET_PBL", -1,
"3", NULL);
7533 ERRMSG(
"Set MET_PBL to 0 ... 3!");
7535 scan_ctl(filename, argc, argv,
"MET_PBL_MIN", -1,
"0.1", NULL);
7537 scan_ctl(filename, argc, argv,
"MET_PBL_MAX", -1,
"5.0", NULL);
7539 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO", -1,
"3", NULL);
7541 ERRMSG(
"Set MET_TROPO to 0 ... 5!");
7543 scan_ctl(filename, argc, argv,
"MET_TROPO_PV", -1,
"3.5", NULL);
7545 scan_ctl(filename, argc, argv,
"MET_TROPO_THETA", -1,
"380", NULL);
7547 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO_SPLINE", -1,
"1", NULL);
7549 scan_ctl(filename, argc, argv,
"MET_DT_OUT", -1,
"0.1", NULL);
7551 (int)
scan_ctl(filename, argc, argv,
"MET_CACHE", -1,
"0", NULL);
7553 (int)
scan_ctl(filename, argc, argv,
"MET_MPI_SHARE", -1,
"0", NULL);
7556 ctl->
sort_dt =
scan_ctl(filename, argc, argv,
"SORT_DT", -1,
"-999", NULL);
7560 (int)
scan_ctl(filename, argc, argv,
"ISOSURF", -1,
"0", NULL);
7562 ERRMSG(
"Add quantity iso_var for ISOSURF=1, 2, or 3!");
7567 (int)
scan_ctl(filename, argc, argv,
"RNG_TYPE", -1,
"1", NULL);
7569 ERRMSG(
"Set RNG_TYPE to 0, 1, or 2!");
7572 ctl->
advect = (int)
scan_ctl(filename, argc, argv,
"ADVECT", -1,
"2", NULL);
7574 ERRMSG(
"Set ADVECT to 1, 2, or 4!");
7578 = (int)
scan_ctl(filename, argc, argv,
"DIFFUSION", -1,
"0", NULL);
7580 ERRMSG(
"Set DIFFUSION to 0 or 1!");
7582 (int)
scan_ctl(filename, argc, argv,
"TURB_PBL_SCHEME", -1,
"0", NULL);
7584 ERRMSG(
"Set TURB_PBL_SCHEME to 0 or 1!");
7586 scan_ctl(filename, argc, argv,
"TURB_DX_PBL", -1,
"50", NULL);
7588 scan_ctl(filename, argc, argv,
"TURB_DX_TROP", -1,
"50", NULL);
7590 scan_ctl(filename, argc, argv,
"TURB_DX_STRAT", -1,
"0", NULL);
7592 scan_ctl(filename, argc, argv,
"TURB_DZ_PBL", -1,
"0", NULL);
7594 scan_ctl(filename, argc, argv,
"TURB_DZ_TROP", -1,
"0", NULL);
7596 scan_ctl(filename, argc, argv,
"TURB_DZ_STRAT", -1,
"0.1", NULL);
7598 scan_ctl(filename, argc, argv,
"TURB_MESOX", -1,
"0.16", NULL);
7600 scan_ctl(filename, argc, argv,
"TURB_MESOZ", -1,
"0.16", NULL);
7602 scan_ctl(filename, argc, argv,
"TURB_PBL_TRANS", -1,
"0", NULL);
7604 ERRMSG(
"TURB_PBL_TRANS must be in the range [0, 1]!");
7608 = (int)
scan_ctl(filename, argc, argv,
"CONV_MIX_PBL", -1,
"0", NULL);
7610 =
scan_ctl(filename, argc, argv,
"CONV_PBL_TRANS", -1,
"0", NULL);
7612 ERRMSG(
"CONV_PBL_TRANS must be in the range [0, 1]!");
7614 =
scan_ctl(filename, argc, argv,
"CONV_CAPE", -1,
"-999", NULL);
7616 =
scan_ctl(filename, argc, argv,
"CONV_CIN", -1,
"-999", NULL);
7617 ctl->
conv_dt =
scan_ctl(filename, argc, argv,
"CONV_DT", -1,
"-999", NULL);
7621 scan_ctl(filename, argc, argv,
"BOUND_MASS", -1,
"-999", NULL);
7623 scan_ctl(filename, argc, argv,
"BOUND_MASS_TREND", -1,
"0", NULL);
7625 scan_ctl(filename, argc, argv,
"BOUND_VMR", -1,
"-999", NULL);
7627 scan_ctl(filename, argc, argv,
"BOUND_VMR_TREND", -1,
"0", NULL);
7629 scan_ctl(filename, argc, argv,
"BOUND_LAT0", -1,
"-999", NULL);
7631 scan_ctl(filename, argc, argv,
"BOUND_LAT1", -1,
"-999", NULL);
7633 scan_ctl(filename, argc, argv,
"BOUND_P0", -1,
"-999", NULL);
7635 scan_ctl(filename, argc, argv,
"BOUND_P1", -1,
"-999", NULL);
7637 scan_ctl(filename, argc, argv,
"BOUND_DPS", -1,
"-999", NULL);
7639 scan_ctl(filename, argc, argv,
"BOUND_DZS", -1,
"-999", NULL);
7641 scan_ctl(filename, argc, argv,
"BOUND_ZETAS", -1,
"-999", NULL);
7643 (int)
scan_ctl(filename, argc, argv,
"BOUND_PBL", -1,
"0", NULL);
7647 if (strcasecmp(ctl->
species,
"CF2Cl2") == 0) {
7651 }
else if (strcasecmp(ctl->
species,
"CFCl3") == 0) {
7655 }
else if (strcasecmp(ctl->
species,
"CH4") == 0) {
7662 }
else if (strcasecmp(ctl->
species,
"CO") == 0) {
7671 }
else if (strcasecmp(ctl->
species,
"CO2") == 0) {
7675 }
else if (strcasecmp(ctl->
species,
"H2O") == 0) {
7677 }
else if (strcasecmp(ctl->
species,
"N2O") == 0) {
7681 }
else if (strcasecmp(ctl->
species,
"NH3") == 0) {
7688 }
else if (strcasecmp(ctl->
species,
"HNO3") == 0) {
7692 }
else if (strcasecmp(ctl->
species,
"NO") == 0) {
7701 }
else if (strcasecmp(ctl->
species,
"NO2") == 0) {
7710 }
else if (strcasecmp(ctl->
species,
"O3") == 0) {
7717 }
else if (strcasecmp(ctl->
species,
"SF6") == 0) {
7721 }
else if (strcasecmp(ctl->
species,
"SO2") == 0) {
7734 sprintf(defstr,
"%g", ctl->
molmass);
7735 ctl->
molmass =
scan_ctl(filename, argc, argv,
"MOLMASS", -1, defstr, NULL);
7740 (int)
scan_ctl(filename, argc, argv,
"OH_CHEM_REACTION", -1, defstr,
7742 for (
int ip = 0; ip < 4; ip++) {
7743 sprintf(defstr,
"%g", ctl->
oh_chem[ip]);
7745 scan_ctl(filename, argc, argv,
"OH_CHEM", ip, defstr, NULL);
7748 scan_ctl(filename, argc, argv,
"OH_CHEM_BETA", -1,
"0", NULL);
7752 (int)
scan_ctl(filename, argc, argv,
"H2O2_CHEM_REACTION", -1,
"0", NULL);
7756 (int)
scan_ctl(filename, argc, argv,
"KPP_CHEM", -1,
"0", NULL);
7757 ctl->
dt_kpp =
scan_ctl(filename, argc, argv,
"DT_KPP", -1,
"1800", NULL);
7761 (int)
scan_ctl(filename, argc, argv,
"TRACER_CHEM", -1,
"0", NULL);
7765 (int)
scan_ctl(filename, argc, argv,
"RADIO_DECAY", -1,
"0", NULL);
7767 (int)
scan_ctl(filename, argc, argv,
"RADIO_DEPO", -1,
"0", NULL);
7769 ERRMSG(
"Radioactive deposition requires a lat/lon meteorological grid!");
7772 for (
int ip = 0; ip < 2; ip++) {
7775 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_H", ip, defstr, NULL);
7777 for (
int ip = 0; ip < 1; ip++) {
7780 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_H", ip, defstr, NULL);
7783 scan_ctl(filename, argc, argv,
"WET_DEPO_SO2_PH", -1,
"0", NULL);
7785 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_A", -1,
"0", NULL);
7787 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_B", -1,
"0", NULL);
7789 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_A", -1,
"0", NULL);
7791 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_B", -1,
"0", NULL);
7793 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 0,
"0.5", NULL);
7795 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 1,
"0.36", NULL);
7797 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_RET_RATIO", -1,
"1", NULL);
7799 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_RET_RATIO", -1,
"1", NULL);
7803 scan_ctl(filename, argc, argv,
"DRY_DEPO_VDEP", -1,
"0", NULL);
7805 scan_ctl(filename, argc, argv,
"DRY_DEPO_DP", -1,
"30", NULL);
7808 scan_ctl(filename, argc, argv,
"CLIM_PHOTO", -1,
7809 "../../data/clams_photolysis_rates.nc", ctl->
clim_photo);
7810 scan_ctl(filename, argc, argv,
"CLIM_HNO3_FILENAME", -1,
7812 scan_ctl(filename, argc, argv,
"CLIM_OH_FILENAME", -1,
7814 scan_ctl(filename, argc, argv,
"CLIM_H2O2_FILENAME", -1,
7816 scan_ctl(filename, argc, argv,
"CLIM_HO2_FILENAME", -1,
7818 scan_ctl(filename, argc, argv,
"CLIM_O1D_FILENAME", -1,
7820 scan_ctl(filename, argc, argv,
"CLIM_CCL4_TIMESERIES", -1,
7822 scan_ctl(filename, argc, argv,
"CLIM_CCL3F_TIMESERIES", -1,
7824 scan_ctl(filename, argc, argv,
"CLIM_CCL2F2_TIMESERIES", -1,
7826 scan_ctl(filename, argc, argv,
"CLIM_N2O_TIMESERIES", -1,
7828 scan_ctl(filename, argc, argv,
"CLIM_SF6_TIMESERIES", -1,
7833 scan_ctl(filename, argc, argv,
"MIXING_DT", -1,
"3600.", NULL);
7835 scan_ctl(filename, argc, argv,
"MIXING_TAU_TROP", -1,
"-999", NULL);
7837 scan_ctl(filename, argc, argv,
"MIXING_TAU_STRAT", -1,
"-999", NULL);
7839 scan_ctl(filename, argc, argv,
"MIXING_Z0", -1,
"-5", NULL);
7841 scan_ctl(filename, argc, argv,
"MIXING_Z1", -1,
"85", NULL);
7843 (int)
scan_ctl(filename, argc, argv,
"MIXING_NZ", -1,
"90", NULL);
7845 scan_ctl(filename, argc, argv,
"MIXING_LON0", -1,
"-180", NULL);
7847 scan_ctl(filename, argc, argv,
"MIXING_LON1", -1,
"180", NULL);
7849 (int)
scan_ctl(filename, argc, argv,
"MIXING_NX", -1,
"360", NULL);
7851 scan_ctl(filename, argc, argv,
"MIXING_LAT0", -1,
"-90", NULL);
7853 scan_ctl(filename, argc, argv,
"MIXING_LAT1", -1,
"90", NULL);
7855 (int)
scan_ctl(filename, argc, argv,
"MIXING_NY", -1,
"180", NULL);
7861 ERRMSG(
"Invalid mixing grid!");
7864 ERRMSG(
"Mixing times must either both be positive or both be disabled!");
7868 scan_ctl(filename, argc, argv,
"CHEMGRID_Z0", -1,
"-5", NULL);
7870 scan_ctl(filename, argc, argv,
"CHEMGRID_Z1", -1,
"85", NULL);
7872 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NZ", -1,
"90", NULL);
7874 scan_ctl(filename, argc, argv,
"CHEMGRID_LON0", -1,
"-180", NULL);
7876 scan_ctl(filename, argc, argv,
"CHEMGRID_LON1", -1,
"180", NULL);
7878 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NX", -1,
"360", NULL);
7880 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT0", -1,
"-90", NULL);
7882 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT1", -1,
"90", NULL);
7884 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NY", -1,
"180", NULL);
7890 ERRMSG(
"Invalid chemistry grid!");
7895 scan_ctl(filename, argc, argv,
"TDEC_STRAT", -1,
"0", NULL);
7898 ctl->
psc_h2o =
scan_ctl(filename, argc, argv,
"PSC_H2O", -1,
"4e-6", NULL);
7900 scan_ctl(filename, argc, argv,
"PSC_HNO3", -1,
"9e-9", NULL);
7906 scan_ctl(filename, argc, argv,
"ATM_DT_OUT", -1,
"86400", NULL);
7908 (int)
scan_ctl(filename, argc, argv,
"ATM_FILTER", -1,
"0", NULL);
7910 (int)
scan_ctl(filename, argc, argv,
"ATM_STRIDE", -1,
"1", NULL);
7912 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE", -1,
"0", NULL);
7914 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE_OUT", -1,
"-1", NULL);
7918 (int)
scan_ctl(filename, argc, argv,
"ATM_NC_LEVEL", -1,
"0", NULL);
7919 for (
int iq = 0; iq < ctl->
nq; iq++)
7921 (
int)
scan_ctl(filename, argc, argv,
"ATM_NC_QUANT", iq,
"0", NULL);
7923 (int)
scan_ctl(filename, argc, argv,
"OBS_TYPE", -1,
"0", NULL);
7926 scan_ctl(filename, argc, argv,
"BUDGET_BASENAME", -1,
"-",
7929 scan_ctl(filename, argc, argv,
"BUDGET_DT_OUT", -1,
"86400", NULL);
7931 ERRMSG(
"Invalid mass budget output settings!");
7934 scan_ctl(filename, argc, argv,
"DEPO_BASENAME", -1,
"-",
7937 scan_ctl(filename, argc, argv,
"DEPO_DT_OUT", -1,
"86400", NULL);
7939 (int)
scan_ctl(filename, argc, argv,
"DEPO_TYPE", -1,
"0", NULL);
7945 scan_ctl(filename, argc, argv,
"CSI_DT_OUT", -1,
"86400", NULL);
7948 scan_ctl(filename, argc, argv,
"CSI_OBSMIN", -1,
"0", NULL);
7950 scan_ctl(filename, argc, argv,
"CSI_MODMIN", -1,
"0", NULL);
7951 ctl->
csi_z0 =
scan_ctl(filename, argc, argv,
"CSI_Z0", -1,
"-5", NULL);
7952 ctl->
csi_z1 =
scan_ctl(filename, argc, argv,
"CSI_Z1", -1,
"85", NULL);
7953 ctl->
csi_nz = (int)
scan_ctl(filename, argc, argv,
"CSI_NZ", -1,
"1", NULL);
7955 scan_ctl(filename, argc, argv,
"CSI_LON0", -1,
"-180", NULL);
7956 ctl->
csi_lon1 =
scan_ctl(filename, argc, argv,
"CSI_LON1", -1,
"180", NULL);
7958 (int)
scan_ctl(filename, argc, argv,
"CSI_NX", -1,
"360", NULL);
7959 ctl->
csi_lat0 =
scan_ctl(filename, argc, argv,
"CSI_LAT0", -1,
"-90", NULL);
7960 ctl->
csi_lat1 =
scan_ctl(filename, argc, argv,
"CSI_LAT1", -1,
"90", NULL);
7962 (int)
scan_ctl(filename, argc, argv,
"CSI_NY", -1,
"180", NULL);
7967 ERRMSG(
"Invalid CSI grid!");
7970 ctl->
nens = (int)
scan_ctl(filename, argc, argv,
"NENS", -1,
"0", NULL);
7972 ERRMSG(
"NENS must not be negative!");
7974 ERRMSG(
"Add quantity ens for ensemble calculations!");
7977 scan_ctl(filename, argc, argv,
"ENS_DT_OUT", -1,
"86400", NULL);
7980 scan_ctl(filename, argc, argv,
"GRID_BASENAME", -1,
"-",
7985 scan_ctl(filename, argc, argv,
"GRID_DT_OUT", -1,
"86400", NULL);
7987 (int)
scan_ctl(filename, argc, argv,
"GRID_SPARSE", -1,
"0", NULL);
7989 (int)
scan_ctl(filename, argc, argv,
"GRID_NC_LEVEL", -1,
"0", NULL);
7990 for (
int iq = 0; iq < ctl->
nq; iq++)
7992 (
int)
scan_ctl(filename, argc, argv,
"GRID_NC_QUANT", iq,
"0", NULL);
7994 (int)
scan_ctl(filename, argc, argv,
"GRID_STDDEV", -1,
"0", NULL);
7995 ctl->
grid_z0 =
scan_ctl(filename, argc, argv,
"GRID_Z0", -1,
"-5", NULL);
7996 ctl->
grid_z1 =
scan_ctl(filename, argc, argv,
"GRID_Z1", -1,
"85", NULL);
7998 (int)
scan_ctl(filename, argc, argv,
"GRID_NZ", -1,
"1", NULL);
8000 scan_ctl(filename, argc, argv,
"GRID_LON0", -1,
"-180", NULL);
8002 scan_ctl(filename, argc, argv,
"GRID_LON1", -1,
"180", NULL);
8004 (int)
scan_ctl(filename, argc, argv,
"GRID_NX", -1,
"360", NULL);
8006 scan_ctl(filename, argc, argv,
"GRID_LAT0", -1,
"-90", NULL);
8008 scan_ctl(filename, argc, argv,
"GRID_LAT1", -1,
"90", NULL);
8010 (int)
scan_ctl(filename, argc, argv,
"GRID_NY", -1,
"180", NULL);
8012 (int)
scan_ctl(filename, argc, argv,
"GRID_TYPE", -1,
"0", NULL);
8015 ERRMSG(
"Invalid output grid dimensions!");
8019 ERRMSG(
"Invalid output grid boundaries!");
8022 ERRMSG(
"Invalid radioactive deposition output settings!");
8025 scan_ctl(filename, argc, argv,
"PROF_BASENAME", -1,
"-",
8028 ctl->
prof_z0 =
scan_ctl(filename, argc, argv,
"PROF_Z0", -1,
"0", NULL);
8029 ctl->
prof_z1 =
scan_ctl(filename, argc, argv,
"PROF_Z1", -1,
"60", NULL);
8031 (int)
scan_ctl(filename, argc, argv,
"PROF_NZ", -1,
"60", NULL);
8033 scan_ctl(filename, argc, argv,
"PROF_LON0", -1,
"-180", NULL);
8035 scan_ctl(filename, argc, argv,
"PROF_LON1", -1,
"180", NULL);
8037 (int)
scan_ctl(filename, argc, argv,
"PROF_NX", -1,
"360", NULL);
8039 scan_ctl(filename, argc, argv,
"PROF_LAT0", -1,
"-90", NULL);
8041 scan_ctl(filename, argc, argv,
"PROF_LAT1", -1,
"90", NULL);
8043 (int)
scan_ctl(filename, argc, argv,
"PROF_NY", -1,
"180", NULL);
8048 ERRMSG(
"Invalid profile grid!");
8051 scan_ctl(filename, argc, argv,
"SAMPLE_BASENAME", -1,
"-",
8053 scan_ctl(filename, argc, argv,
"SAMPLE_KERNEL", -1,
"-",
8055 scan_ctl(filename, argc, argv,
"SAMPLE_OBSFILE", -1,
"-",
8058 scan_ctl(filename, argc, argv,
"SAMPLE_DX", -1,
"50", NULL);
8060 scan_ctl(filename, argc, argv,
"SAMPLE_DZ", -1,
"-999", NULL);
8063 scan_ctl(filename, argc, argv,
"STAT_BASENAME", -1,
"-",
8067 ctl->
stat_r =
scan_ctl(filename, argc, argv,
"STAT_R", -1,
"50", NULL);
8069 scan_ctl(filename, argc, argv,
"STAT_T0", -1,
"-1e100", NULL);
8070 ctl->
stat_t1 =
scan_ctl(filename, argc, argv,
"STAT_T1", -1,
"1e100", NULL);
8075 scan_ctl(filename, argc, argv,
"VTK_DT_OUT", -1,
"86400", NULL);
8077 (int)
scan_ctl(filename, argc, argv,
"VTK_STRIDE", -1,
"1", NULL);
8079 scan_ctl(filename, argc, argv,
"VTK_SCALE", -1,
"1.0", NULL);
8081 scan_ctl(filename, argc, argv,
"VTK_OFFSET", -1,
"0.0", NULL);
8083 (int)
scan_ctl(filename, argc, argv,
"VTK_SPHERE", -1,
"0", NULL);
8094 int mpi_initialized = 0;
8096 MPI_Initialized(&mpi_initialized);
8097 if (mpi_initialized)
8098 MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
8100 (int)
scan_ctl(filename, argc, argv,
"DD", -1,
8101 (mpi_initialized && mpi_size > 1) ?
"1" :
"0", NULL);
8103 ctl->
dd = (int)
scan_ctl(filename, argc, argv,
"DD", -1,
"0", NULL);
8107 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_MERIDIONAL", -1,
8108 (ctl->
dd == 1) ?
"2" :
"1", NULL);
8110 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_ZONAL", -1,
8111 (ctl->
dd == 1) ?
"2" :
"1", NULL);
8113 (int)
scan_ctl(filename, argc, argv,
"DD_HALOS_SIZE", -1,
"1", NULL);
8115 (double)
scan_ctl(filename, argc, argv,
"DD_SORT_DT", -1,
"1800", NULL);
8117 (int)
scan_ctl(filename, argc, argv,
"DD_EXCHANGE_MODE", -1,
"0", NULL);
8119 ERRMSG(
"Set DD_EXCHANGE_MODE to 0 (sort/push) or 1 (no sort)!");
8122 ERRMSG(
"MET_NC_READ_MODE=1 requires MPI DD, NetCDF, and MET_CONVENTION=0!");
8125 ERRMSG(
"MET_NC_READ_MODE=1 requires a DD build!");
8131 if (!mpi_initialized)
8133 (
"Domain decomposition requires to start the executable with one task per subdomain!");
8135 ERRMSG(
"DD_HALOS_SIZE must be non-negative!");
8137 ERRMSG(
"The number of subdomains has to be positive!");
8139 ERRMSG(
"Please provide zonal and meridional subdomain numbers!");
8141 ERRMSG(
"Number of tasks and subdomains is not identical!");
8144 (
"Domain decomposition requires the quantities current_subdomain and target_subdomain!");
8146 ERRMSG(
"Domain decomposition requires a lat/lon meteorological grid!");
8149 (
"Radioactive deposition is not supported with domain decomposition!");
8157 const char *filename,
8164 LOG(1,
"Read meteo data: %s", filename);
8171 ERRMSG(
"The domain decomposition is only implemented by the trac tool!");
8183 int mpi_initialized = 0;
8184 MPI_Initialized(&mpi_initialized);
8185 if (share && !mpi_initialized) {
8186 WARN(
"Cannot share meteo data because MPI has not been initialized!");
8190 MPI_Comm_rank(MPI_COMM_WORLD, &
rank);
8194 if (!share ||
rank == 0) {
8218 ERRMSG(
"MET_TYPE not implemented!");
8278 LOG(2,
"Broadcast data on rank %d...",
rank);
8412 module_dd(t, ctl, cache, dd, atm, met0);
8426 ERRMSG(
"Code was compiled without KPP!");
8459#pragma acc update device(ctl[:1])
8463 if (cache != NULL) {
8466#pragma acc update device(cache[:1])
8473#pragma acc update device(clim[:1])
8480 met_t *met0up = *met0;
8481#pragma acc update device(met0up[:1])
8488 met_t *met1up = *met1;
8489#pragma acc update device(met1up[:1])
8496#pragma acc update device(atm[:1])
8515#pragma acc update host(ctl[:1])
8519 if (cache != NULL) {
8522#pragma acc update host(cache[:1])
8529#pragma acc update host(clim[:1])
8536 met_t *met0up = *met0;
8537#pragma acc update host(met0up[:1])
8544 met_t *met1up = *met1;
8545#pragma acc update host(met1up[:1])
8552#pragma acc update host(atm[:1])
8560 const char *filename,
8569 LOG(1,
"Write atmospheric data: %s", filename);
8593 ERRMSG(
"Atmospheric data type not supported!");
8597 LOG(2,
"Number of particles: %d", atm->
np);
8598 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
8599 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
8600 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
8601 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
8602 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
8603 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
8604 LOG(2,
"%s range: %g ... %g %s",
8605 ctl->
met_coord_type == 0 ?
"Longitude" :
"X coordinate", mini, maxi,
8607 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
8608 LOG(2,
"%s range: %g ... %g %s",
8609 ctl->
met_coord_type == 0 ?
"Latitude" :
"Y coordinate", mini, maxi,
8611 for (
int iq = 0; iq < ctl->
nq; iq++) {
8613 sprintf(msg,
"Quantity %s range: %s ... %s %s",
8616 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
8617 LOG(2, msg, mini, maxi);
8624 const char *filename,
8632 LOG(1,
"Write meteo data: %s", filename);
8637 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
8641 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
8645 ERRMSG(
"MPTRAC was compiled without LZ4 compression!");
8649 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
8653 ERRMSG(
"MPTRAC was compiled without SZ3 compression!");
8667 ERRMSG(
"MET_TYPE not implemented!");
8673 const char *dirname,
8681 char ext[10], filename[2 *
LEN];
8685 int year, mon, day, hour, min, sec;
8688 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
8691 const int final = (t == ctl->
t_stop);
8706 if (output_atm || output_grid || output_budget || output_ens || output_vtk
8714 sprintf(ext,
"tab");
8716 sprintf(ext,
"bin");
8719 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d_%02d.%s",
8720 dirname, ctl->
atm_basename, year, mon, day, hour, min, sec, ext);
8726 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d_%02d.%s",
8727 dirname, ctl->
grid_basename, year, mon, day, hour, min, sec,
8729 write_grid(filename, ctl, met0, met1, atm, t);
8733 if (output_budget) {
8741#pragma acc update host(depo[:1])
8743 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d_%02d.%s",
8744 dirname, ctl->
depo_basename, year, mon, day, hour, min, sec,
8751 sprintf(filename,
"%s/%s.tab", dirname, ctl->
csi_basename);
8757 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d_%02d.tab",
8758 dirname, ctl->
ens_basename, year, mon, day, hour, min, sec);
8764 sprintf(filename,
"%s/%s.tab", dirname, ctl->
prof_basename);
8765 write_prof(filename, ctl, met0, met1, atm, t);
8776 sprintf(filename,
"%s/%s.tab", dirname, ctl->
stat_basename);
8785 sprintf(filename,
"%s/%s_%05d.vtk", dirname, ctl->
vtk_basename, ++nvtk);
8795 const double hno3) {
8798 const double h2o_help =
MAX(h2o, 0.1e-6);
8801 const double p_hno3 = hno3 * p / 1.333224;
8802 const double p_h2o = h2o_help * p / 1.333224;
8803 const double a = 0.009179 - 0.00088 * log10(p_h2o);
8804 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
8805 const double c = -11397.0 / a;
8806 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
8807 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
8825 const double p0 = pbl;
8828 if (atm->
p[ip] > p0)
8830 else if (atm->
p[ip] < p1)
8833 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
8839 const char *filename,
8845 if (!(in = fopen(filename,
"r"))) {
8846 WARN(
"Cannot open file!");
8852 while (fgets(line,
LEN, in)) {
8856 TOK(line, tok,
"%lg", atm->
time[atm->
np]);
8857 TOK(NULL, tok,
"%lg", atm->
p[atm->
np]);
8858 TOK(NULL, tok,
"%lg", atm->
lon[atm->
np]);
8859 TOK(NULL, tok,
"%lg", atm->
lat[atm->
np]);
8860 for (
int iq = 0; iq < ctl->
nq; iq++)
8861 TOK(NULL, tok,
"%lg", atm->
q[iq][atm->
np]);
8864 atm->
p[atm->
np] =
P(atm->
p[atm->
np]);
8867 if ((++atm->
np) >
NP)
8868 ERRMSG(
"Too many data points!");
8881 const char *filename,
8887 if (!(in = fopen(filename,
"r")))
8892 FREAD(&version,
int,
8896 ERRMSG(
"Wrong version of binary data!");
8914 for (
int iq = 0; iq < ctl->
nq; iq++)
8915 FREAD(atm->
q[iq],
double,
8925 ERRMSG(
"Error while reading binary data!");
8937 const char *filename,
8942 ERRMSG(
"CLaMS atmospheric files support only lat/lon grids");
8947 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
8954 if (nc_inq_varid(ncid,
"TIME_INIT", &varid) == NC_NOERR) {
8955 NC(nc_get_var_double(ncid, varid, atm->
time));
8957 WARN(
"TIME_INIT not found use time instead!");
8960 for (
int ip = 0; ip < atm->
np; ip++) {
8961 atm->
time[ip] = time_init;
8973 if (nc_inq_varid(ncid,
"PRESS_INIT", &varid) == NC_NOERR) {
8974 NC(nc_get_var_double(ncid, varid, atm->
p));
8976 WARN(
"PRESS_INIT not found use PRESS instead!");
8977 nc_inq_varid(ncid,
"PRESS", &varid);
8978 NC(nc_get_var_double(ncid, varid, atm->
p));
8983 for (
int iq = 0; iq < ctl->
nq; iq++)
9000 const char *filename,
9007 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
9020 for (
int iq = 0; iq < ctl->
nq; iq++)
9033 const char *filename,
9039 LOG(1,
"Read photolysis rates: %s", filename);
9042 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
9043 WARN(
"Photolysis rate data are missing!");
9050 if (photo->
p[0] < photo->
p[1])
9051 ERRMSG(
"Pressure data are not descending!");
9056 if (photo->
o3c[0] > photo->
o3c[1])
9057 ERRMSG(
"Total column ozone data are not ascending!");
9062 if (photo->
sza[0] > photo->
sza[1])
9063 ERRMSG(
"Solar zenith angle data are not ascending!");
9080 LOG(2,
"Number of pressure levels: %d", photo->
np);
9081 LOG(2,
"Altitude levels: %g, %g ... %g km",
9082 Z(photo->
p[0]),
Z(photo->
p[1]),
Z(photo->
p[photo->
np - 1]));
9083 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
9084 photo->
p[0], photo->
p[1], photo->
p[photo->
np - 1]);
9085 LOG(2,
"Number of solar zenith angles: %d", photo->
nsza);
9086 LOG(2,
"Solar zenith angles: %g, %g ... %g deg",
9089 LOG(2,
"Number of total column ozone values: %d", photo->
no3c);
9090 LOG(2,
"Total column ozone: %g, %g ... %g DU",
9092 LOG(2,
"N2O photolysis rate: %g, %g ... %g s**-1",
9093 photo->
n2o[0][0][0], photo->
n2o[1][0][0],
9094 photo->
n2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
9095 LOG(2,
"CCl4 photolysis rate: %g, %g ... %g s**-1",
9096 photo->
ccl4[0][0][0], photo->
ccl4[1][0][0],
9098 LOG(2,
"CFC-11 photolysis rate: %g, %g ... %g s**-1",
9099 photo->
ccl3f[0][0][0], photo->
ccl3f[1][0][0],
9101 LOG(2,
"CFC-12 photolysis rate: %g, %g ... %g s**-1",
9104 LOG(2,
"O2 photolysis rate: %g, %g ... %g s**-1",
9105 photo->
o2[0][0][0], photo->
o2[1][0][0],
9106 photo->
o2[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
9107 LOG(2,
"O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
9108 photo->
o3_1[0][0][0], photo->
o3_1[1][0][0],
9110 LOG(2,
"O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
9111 photo->
o3_2[0][0][0], photo->
o3_2[1][0][0],
9113 LOG(2,
"H2O2 photolysis rate: %g, %g ... %g s**-1",
9114 photo->
h2o2[0][0][0], photo->
h2o2[1][0][0],
9116 LOG(2,
"H2O photolysis rate: %g, %g ... %g s**-1",
9117 photo->
h2o[0][0][0], photo->
h2o[1][0][0],
9118 photo->
h2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
9125 const char *varname,
9139 for (
int ip = 0; ip < photo->
np; ip++)
9140 for (
int is = 0; is < photo->
nsza; is++)
9141 for (
int io = 0; io < photo->
no3c; io++)
9152 const char *filename,
9156 LOG(1,
"Read climatological time series: %s", filename);
9160 if (!(in = fopen(filename,
"r"))) {
9161 WARN(
"Cannot open file!");
9168 while (fgets(line,
LEN, in))
9169 if (sscanf(line,
"%lg %lg", &ts->
time[nh], &ts->
vmr[nh]) == 2) {
9172 ts->
time[nh] = (ts->
time[nh] - 2000.0) * 365.25 * 86400.;
9175 if (nh > 0 && ts->
time[nh] <= ts->
time[nh - 1])
9176 ERRMSG(
"Time series must be ascending!");
9180 ERRMSG(
"Too many data points!");
9189 ERRMSG(
"Not enough data points!");
9192 LOG(2,
"Number of time steps: %d", ts->
ntime);
9193 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s", ts->
time[0], ts->
time[1],
9195 LOG(2,
"Volume mixing ratio range: %g ... %g ppv",
9196 gsl_stats_min(ts->
vmr, 1, (
size_t) nh), gsl_stats_max(ts->
vmr, 1,
9206 const char *filename,
9207 const char *varname,
9210 int ncid, varid, it, iy, iz, iz2, nt;
9212 double *help, varmin = 1e99, varmax = -1e99;
9215 LOG(1,
"Read %s data: %s", varname, filename);
9218 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
9219 WARN(
"%s climatology data are missing!", varname);
9226 if (zm->
p[0] < zm->
p[1])
9227 ERRMSG(
"Pressure data are not descending!");
9232 if (zm->
lat[0] > zm->
lat[1])
9233 ERRMSG(
"Latitude data are not ascending!");
9237 zm->
time[0] = 1209600.00;
9238 zm->
time[1] = 3888000.00;
9239 zm->
time[2] = 6393600.00;
9240 zm->
time[3] = 9072000.00;
9241 zm->
time[4] = 11664000.00;
9242 zm->
time[5] = 14342400.00;
9243 zm->
time[6] = 16934400.00;
9244 zm->
time[7] = 19612800.00;
9245 zm->
time[8] = 22291200.00;
9246 zm->
time[9] = 24883200.00;
9247 zm->
time[10] = 27561600.00;
9248 zm->
time[11] = 30153600.00;
9257 for (it = 0; it < zm->
ntime; it++)
9258 for (iz = 0; iz < zm->
np; iz++)
9259 for (iy = 0; iy < zm->
nlat; iy++)
9264 for (it = 0; it < zm->
ntime; it++)
9265 for (iy = 0; iy < zm->
nlat; iy++)
9266 for (iz = 0; iz < zm->
np; iz++) {
9267 if (zm->
vmr[it][iz][iy] < 0) {
9268 for (iz2 = 0; iz2 < zm->
np; iz2++)
9269 if (zm->
vmr[it][iz2][iy] >= 0) {
9270 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
9273 for (iz2 = zm->
np - 1; iz2 >= 0; iz2--)
9274 if (zm->
vmr[it][iz2][iy] >= 0) {
9275 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
9279 varmin =
MIN(varmin, zm->
vmr[it][iz][iy]);
9280 varmax =
MAX(varmax, zm->
vmr[it][iz][iy]);
9287 LOG(2,
"Number of time steps: %d", zm->
ntime);
9288 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
9290 LOG(2,
"Number of pressure levels: %d", zm->
np);
9291 LOG(2,
"Altitude levels: %g, %g ... %g km",
9292 Z(zm->
p[0]),
Z(zm->
p[1]),
Z(zm->
p[zm->
np - 1]));
9293 LOG(2,
"Pressure levels: %g, %g ... %g hPa", zm->
p[0],
9294 zm->
p[1], zm->
p[zm->
np - 1]);
9295 LOG(2,
"Number of latitudes: %d", zm->
nlat);
9296 LOG(2,
"Latitudes: %g, %g ... %g deg",
9298 LOG(2,
"%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
9305 const char *filename,
9311 LOG(1,
"Read kernel function: %s", filename);
9315 if (!(in = fopen(filename,
"r")))
9316 ERRMSG(
"Cannot open file!");
9321 while (fgets(line,
LEN, in))
9322 if (sscanf(line,
"%lg %lg", &kz[n], &kw[n]) == 2) {
9323 if (n > 0 && kz[n] < kz[n - 1])
9324 ERRMSG(
"Height levels must be ascending!");
9326 ERRMSG(
"Too many height levels!");
9335 ERRMSG(
"Not enough height levels!");
9338 const double kmax = gsl_stats_max(kw, 1, (
size_t) n);
9339 for (
int iz = 0; iz < n; iz++)
9346 const char *filename,
9354 int year, mon, day, hour, min, sec;
9360 if (!(in = fopen(filename,
"r"))) {
9361 WARN(
"Cannot open file!");
9367 FREAD(&met_type,
int,
9371 ERRMSG(
"Wrong MET_TYPE of binary data!");
9375 FREAD(&version,
int,
9379 ERRMSG(
"Wrong version of binary data!");
9385 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
9386 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
9387 met->
time, year, mon, day, hour, min);
9388 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
9389 || day < 1 || day > 31 || hour < 0 || hour > 23)
9390 ERRMSG(
"Error while reading time!");
9398 LOG(2,
"Number of %s: %d",
9399 (met->
coord_type == 0) ?
"longitudes" :
"x coordinates", met->
nx);
9400 if (met->
nx < 2 || met->
nx >
EX)
9402 ?
"Number of longitudes out of range!"
9403 :
"Number of x coordinates out of range!");
9408 LOG(2,
"Number of %s: %d",
9409 (met->
coord_type == 0) ?
"latitudes" :
"y coordinates", met->
ny);
9410 if (met->
ny < 2 || met->
ny >
EY)
9412 ?
"Number of latitudes out of range!"
9413 :
"Number of y coordinates out of range!");
9418 LOG(2,
"Number of levels: %d", met->
np);
9419 if (met->
np < 2 || met->
np >
EP)
9420 ERRMSG(
"Number of levels out of range!");
9426 LOG(2,
"%s: %g, %g ... %g %s",
9427 met->
coord_type == 0 ?
"Longitudes" :
"X coordinates",
9434 LOG(2,
"%s: %g, %g ... %g %s",
9435 met->
coord_type == 0 ?
"Latitudes" :
"Y coordinates",
9442 LOG(2,
"Altitude levels: %g, %g ... %g km",
9443 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
9444 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
9445 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
9494 ERRMSG(
"Error while reading binary data!");
9509 const char *varname) {
9518 LOG(2,
"Read 2-D variable: %s (uncompressed)", varname);
9520 (
size_t) (met->
nx * met->
ny),
9524 for (
int ix = 0; ix < met->
nx; ix++)
9525 for (
int iy = 0; iy < met->
ny; iy++)
9526 var[ix][iy] = help[
ARRAY_2D(ix, iy, met->
ny)];
9539 const char *varname,
9540 const float bound_min,
9541 const float bound_max) {
9551 LOG(2,
"Read 3-D variable: %s (uncompressed)", varname);
9553 (
size_t) (met->
nx * met->
ny * met->
np),
9565 FREAD(&precision,
int,
9570 FREAD(&tolerance,
double,
9576 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
9585 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
9594 ERRMSG(
"MPTRAC was compiled without LZ4 compression!");
9603 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
9611 FREAD(&precision,
int,
9616 FREAD(&tolerance,
double,
9622 ERRMSG(
"MPTRAC was compiled without sz3 compression!");
9627#pragma omp parallel for default(shared) collapse(2)
9628 for (
int ix = 0; ix < met->
nx; ix++)
9629 for (
int iy = 0; iy < met->
ny; iy++)
9630 for (
int ip = 0; ip < met->
np; ip++) {
9631 var[ix][iy][ip] = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9632 if (var[ix][iy][ip] < bound_min)
9633 var[ix][iy][ip] = bound_min;
9634 else if (var[ix][iy][ip] > bound_max)
9635 var[ix][iy][ip] = bound_max;
9654 ERRMSG(
"Only lat/lon grid supported");
9658 LOG(2,
"Calculate CAPE...");
9661 const double pfac = 1.01439, dz0 =
RI /
MA /
G0 * log(pfac);
9664#pragma omp parallel for default(shared) collapse(2)
9665 for (
int ix = 0; ix < met->
nx; ix++)
9666 for (
int iy = 0; iy < met->
ny; iy++) {
9670 double h2o = 0, t, theta = 0;
9671 double pbot =
MIN(met->
ps[ix][iy], met->
p[0]);
9672 double ptop = pbot - 50.;
9673 for (
int ip = 0; ip < met->
np; ip++) {
9674 if (met->
p[ip] <= pbot) {
9675 theta +=
THETA(met->
p[ip], met->
t[ix][iy][ip]);
9676 h2o += met->
h2o[ix][iy][ip];
9679 if (met->
p[ip] < ptop && n > 0)
9686 met->
plcl[ix][iy] = NAN;
9687 met->
plfc[ix][iy] = NAN;
9688 met->
pel[ix][iy] = NAN;
9689 met->
cape[ix][iy] = NAN;
9690 met->
cin[ix][iy] = NAN;
9696 pbot = met->
ps[ix][iy];
9698 met->
plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
9699 t = theta / pow(1000. / met->
plcl[ix][iy],
KAPPA);
9700 if (
RH(met->
plcl[ix][iy], t, h2o) > 100.)
9701 ptop = met->
plcl[ix][iy];
9703 pbot = met->
plcl[ix][iy];
9704 }
while (pbot - ptop > 0.1);
9708 double dcape, dz, h2o_env, t_env;
9709 double p = met->
ps[ix][iy];
9710 met->
cape[ix][iy] = met->
cin[ix][iy] = 0;
9712 dz = dz0 *
TVIRT(t, h2o);
9714 t = theta / pow(1000. / p,
KAPPA);
9718 &h2o_env, ci, cw, 0);
9719 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
9720 TVIRT(t_env, h2o_env) * dz;
9722 met->
cin[ix][iy] += fabsf((
float) dcape);
9723 }
while (p > met->
plcl[ix][iy]);
9728 p = met->
plcl[ix][iy];
9729 t = theta / pow(1000. / p,
KAPPA);
9734 dz = dz0 *
TVIRT(t, h2o);
9737 double psat =
PSAT(t);
9738 h2o = psat / (p - (1. -
EPS) * psat);
9742 &h2o_env, ci, cw, 0);
9743 double dcape_old = dcape;
9744 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
9745 TVIRT(t_env, h2o_env) * dz;
9747 met->
cape[ix][iy] += (float) dcape;
9748 if (!isfinite(met->
plfc[ix][iy]))
9749 met->
plfc[ix][iy] = (
float) p;
9750 }
else if (dcape_old > 0)
9751 met->
pel[ix][iy] = (float) p;
9752 if (dcape < 0 && !isfinite(met->
plfc[ix][iy]))
9753 met->
cin[ix][iy] += fabsf((
float) dcape);
9757 if (!isfinite(met->
plfc[ix][iy]))
9758 met->
cin[ix][iy] = NAN;
9769 LOG(2,
"Calculate cloud data...");
9772 const double ccmin = 0.01, cwmin = 1e-6;
9775#pragma omp parallel for default(shared) collapse(2)
9776 for (
int ix = 0; ix < met->
nx; ix++)
9777 for (
int iy = 0; iy < met->
ny; iy++) {
9780 met->
pct[ix][iy] = NAN;
9781 met->
pcb[ix][iy] = NAN;
9782 met->
cl[ix][iy] = 0;
9785 for (
int ip = 0; ip < met->
np - 1; ip++) {
9788 if (met->
p[ip] > met->
ps[ix][iy] || met->
p[ip] <
P(20.))
9792 if (met->
cc[ix][iy][ip] > ccmin
9793 && (met->
lwc[ix][iy][ip] > cwmin
9794 || met->
rwc[ix][iy][ip] > cwmin
9795 || met->
iwc[ix][iy][ip] > cwmin
9796 || met->
swc[ix][iy][ip] > cwmin)) {
9800 = (float) (0.5 * (met->
p[ip] + (
float) met->
p[ip + 1]));
9803 if (!isfinite(met->
pcb[ix][iy]))
9805 = (
float) (0.5 * (met->
p[ip] + met->
p[
MAX(ip - 1, 0)]));
9809 met->
cl[ix][iy] += (float)
9810 (0.5 * (met->
lwc[ix][iy][ip] + met->
lwc[ix][iy][ip + 1]
9811 + met->
rwc[ix][iy][ip] + met->
rwc[ix][iy][ip + 1]
9812 + met->
iwc[ix][iy][ip] + met->
iwc[ix][iy][ip + 1]
9813 + met->
swc[ix][iy][ip] + met->
swc[ix][iy][ip + 1])
9814 * 100. * (met->
p[ip] - met->
p[ip + 1]) /
G0);
9832 ERRMSG(
"Only lat/lon grid supported");
9836 LOG(2,
"Detrend meteo data...");
9843 const double tssq = 2. *
SQR(sigma);
9846 int sy = (int) (3. *
DY2DEG(sigma) / fabs(met->
lat[1] - met->
lat[0]));
9850#pragma omp parallel for default(shared) collapse(2)
9851 for (
int ix = 0; ix < met->
nx; ix++) {
9852 for (
int iy = 0; iy < met->
ny; iy++) {
9860 (int) (3. *
DX2DEG(sigma, met->
lat[iy]) /
9861 fabs(met->
lon[1] - met->
lon[0]));
9866 for (
int ip = 0; ip < met->
np; ip++) {
9867 help->
t[ix][iy][ip] = 0;
9868 help->
u[ix][iy][ip] = 0;
9869 help->
v[ix][iy][ip] = 0;
9870 help->
w[ix][iy][ip] = 0;
9874 for (
int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
9878 else if (ix3 >= met->
nx)
9880 for (
int iy2 =
MAX(iy - sy, 0);
9881 iy2 <=
MIN(iy + sy, met->
ny - 1); iy2++) {
9888 const float w = (float) exp(-
DIST2(x0, x1) / tssq);
9892 for (
int ip = 0; ip < met->
np; ip++) {
9893 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip];
9894 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip];
9895 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip];
9896 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip];
9902 for (
int ip = 0; ip < met->
np; ip++) {
9903 help->
t[ix][iy][ip] /= wsum;
9904 help->
u[ix][iy][ip] /= wsum;
9905 help->
v[ix][iy][ip] /= wsum;
9906 help->
w[ix][iy][ip] /= wsum;
9912#pragma omp parallel for default(shared) collapse(3)
9913 for (
int ix = 0; ix < met->
nx; ix++)
9914 for (
int iy = 0; iy < met->
ny; iy++)
9915 for (
int ip = 0; ip < met->
np; ip++) {
9916 met->
t[ix][iy][ip] -= help->
t[ix][iy][ip];
9917 met->
u[ix][iy][ip] -= help->
u[ix][iy][ip];
9918 met->
v[ix][iy][ip] -= help->
v[ix][iy][ip];
9919 met->
w[ix][iy][ip] -= help->
w[ix][iy][ip];
9933 LOG(2,
"Extrapolate meteo data...");
9936#pragma omp parallel for default(shared) collapse(2)
9937 for (
int ix = 0; ix < met->
nx; ix++)
9938 for (
int iy = 0; iy < met->
ny; iy++) {
9942 for (ip0 = met->
np - 1; ip0 >= 0; ip0--)
9943 if (!isfinite(met->
t[ix][iy][ip0])
9944 || !isfinite(met->
u[ix][iy][ip0])
9945 || !isfinite(met->
v[ix][iy][ip0])
9946 || !isfinite(met->
w[ix][iy][ip0]))
9950 for (
int ip = ip0; ip >= 0; ip--) {
9951 met->
t[ix][iy][ip] = met->
t[ix][iy][ip + 1];
9952 met->
u[ix][iy][ip] = met->
u[ix][iy][ip + 1];
9953 met->
v[ix][iy][ip] = met->
v[ix][iy][ip + 1];
9954 met->
w[ix][iy][ip] = met->
w[ix][iy][ip + 1];
9955 met->
h2o[ix][iy][ip] = met->
h2o[ix][iy][ip + 1];
9956 met->
o3[ix][iy][ip] = met->
o3[ix][iy][ip + 1];
9957 met->
lwc[ix][iy][ip] = met->
lwc[ix][iy][ip + 1];
9958 met->
rwc[ix][iy][ip] = met->
rwc[ix][iy][ip + 1];
9959 met->
iwc[ix][iy][ip] = met->
iwc[ix][iy][ip + 1];
9960 met->
swc[ix][iy][ip] = met->
swc[ix][iy][ip + 1];
9961 met->
cc[ix][iy][ip] = met->
cc[ix][iy][ip + 1];
9980 LOG(2,
"Calculate geopotential heights...");
9987#pragma omp parallel for default(shared)
9988 for (
int ip = 0; ip < met->
np; ip++)
9989 logp[ip] = log(met->
p[ip]);
9992#pragma omp parallel for default(shared) collapse(2)
9993 for (
int ix = 0; ix < met->
nx; ix++)
9994 for (
int iy = 0; iy < met->
ny; iy++) {
9997 const double zs = met->
zs[ix][iy];
9998 const double lnps = log(met->
ps[ix][iy]);
10002 const double ts =
LIN(met->
p[ip0], met->
t[ix][iy][ip0], met->
p[ip0 + 1],
10003 met->
t[ix][iy][ip0 + 1], met->
ps[ix][iy]);
10004 const double h2os =
10005 LIN(met->
p[ip0], met->
h2o[ix][iy][ip0], met->
p[ip0 + 1],
10006 met->
h2o[ix][iy][ip0 + 1], met->
ps[ix][iy]);
10009 met->
z[ix][iy][ip0 + 1]
10011 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
10012 met->
t[ix][iy][ip0 + 1], met->
h2o[ix][iy][ip0 + 1]));
10013 for (
int ip = ip0 + 2; ip < met->
np; ip++)
10015 = (
float) (met->
z[ix][iy][ip - 1] +
10016 ZDIFF(logp[ip - 1], met->
t[ix][iy][ip - 1],
10017 met->
h2o[ix][iy][ip - 1], logp[ip],
10018 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
10021 met->
z[ix][iy][ip0]
10023 ZDIFF(lnps, ts, h2os, logp[ip0],
10024 met->
t[ix][iy][ip0], met->
h2o[ix][iy][ip0]));
10025 for (
int ip = ip0 - 1; ip >= 0; ip--)
10027 = (
float) (met->
z[ix][iy][ip + 1] +
10028 ZDIFF(logp[ip + 1], met->
t[ix][iy][ip + 1],
10029 met->
h2o[ix][iy][ip + 1], logp[ip],
10030 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
10034 if (dx == 0 || dy == 0)
10038 if (dx < 0 || dy < 0) {
10039 if (fabs(met->
lon[1] - met->
lon[0]) < 0.5) {
10049 float ws[dx + 1][dy + 1];
10050#pragma omp parallel for default(shared) collapse(2)
10051 for (
int ix = 0; ix <= dx; ix++)
10052 for (
int iy = 0; iy < dy; iy++)
10053 ws[ix][iy] = (1.0f - (
float) ix / (float) dx)
10054 * (1.0f - (float) iy / (
float) dy);
10057#pragma omp parallel for default(shared) collapse(3)
10058 for (
int ix = 0; ix < met->
nx; ix++)
10059 for (
int iy = 0; iy < met->
ny; iy++)
10060 for (
int ip = 0; ip < met->
np; ip++)
10061 help[
ARRAY_3D(ip, ix, met->
nx, iy, met->
ny)] = met->
z[ix][iy][ip];
10064#pragma omp parallel for default(shared) collapse(3)
10065 for (
int ip = 0; ip < met->
np; ip++)
10066 for (
int ix = 0; ix < met->
nx; ix++)
10067 for (
int iy = 0; iy < met->
ny; iy++) {
10068 float res = 0, wsum = 0;
10069 int iy0 =
MAX(iy - dy + 1, 0);
10070 int iy1 =
MIN(iy + dy - 1, met->
ny - 1);
10071 for (
int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
10075 else if (ix3 >= met->
nx)
10077 for (
int iy2 = iy0; iy2 <= iy1; ++iy2)
10078 if (isfinite(help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)])) {
10079 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
10080 res += w * help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)];
10085 met->
z[ix][iy][ip] = res / wsum;
10087 met->
z[ix][iy][ip] = NAN;
10097 const char *filename,
10103 char levname[
LEN], tstr[10];
10105 double rtime = 0, r, r2;
10107 int varid, ndims, dimids[NC_MAX_DIMS], year2, mon2, day2, hour2, min2, sec2,
10108 year, mon, day, hour, min, sec;
10114 LOG(2,
"Read meteo grid information...");
10123 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
10124 if (nc_inq_varid(ncid,
"time", &varid) == NC_NOERR) {
10125 NC(nc_get_var_double(ncid, varid, &rtime));
10126 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
10127 WARN(
"Time information in meteo file does not match filename!");
10129 WARN(
"Time information in meteo file is missing!");
10140 sprintf(tstr,
"19%.2s", &filename[strlen(filename) - 11]);
10142 sprintf(tstr,
"20%.2s", &filename[strlen(filename) - 11]);
10144 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 9]);
10146 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 7]);
10148 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 5]);
10154 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
10155 || day < 1 || day > 31 || hour < 0 || hour > 23)
10156 ERRMSG(
"Cannot read time from filename!");
10157 jsec2time(met->
time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
10158 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
10159 met->
time, year2, mon2, day2, hour2, min2);
10162 if (nc_inq_varid(ncid,
"u", &varid) != NC_NOERR)
10163 if (nc_inq_varid(ncid,
"U", &varid) != NC_NOERR)
10165 (
"Variable 'u' or 'U' not found, cannot determine vertical dimension!");
10167 NC(nc_inq_varndims(ncid, varid, &ndims));
10168 NC(nc_inq_vardimid(ncid, varid, dimids));
10172 (ncid, dimids[ctl->
met_convention == 0 ? 1 : 3], levname, &dimlen));
10173 }
else if (ndims == 3) {
10175 (ncid, dimids[ctl->
met_convention == 0 ? 0 : 2], levname, &dimlen));
10177 ERRMSG(
"Cannot determine vertical dimension!")
10178 met->
np = (int) dimlen;
10180 LOG(2,
"Number of levels: %d", met->
np);
10181 if (met->
np < 2 || met->
np >
EP)
10182 ERRMSG(
"Number of levels out of range!");
10190 LOG(2,
"Number of longitudes: %d", met->
nx);
10193 LOG(2,
"Number of latitudes: %d", met->
ny);
10196 LOG(2,
"Longitudes: %g, %g ... %g deg",
10197 met->
lon[0], met->
lon[1], met->
lon[met->
nx - 1]);
10199 LOG(2,
"Latitudes: %g, %g ... %g deg",
10200 met->
lat[0], met->
lat[1], met->
lat[met->
ny - 1]);
10205 LOG(2,
"Number of x coordinates: %d", met->
nx);
10208 LOG(2,
"Number of y coordinates: %d", met->
ny);
10211 LOG(2,
"X coordinates: %g, %g ... %g m",
10212 met->
lon[0], met->
lon[1], met->
lon[met->
nx - 1]);
10214 LOG(2,
"Y coordinates: %g, %g ... %g m",
10215 met->
lat[0], met->
lat[1], met->
lat[met->
ny - 1]);
10221 ERRMSG(
"Domain decomposition is only supported for lat/lon grids!");
10231 for (
int ip = 0; ip < met->
np; ip++)
10232 met->
p[ip] /= 100.;
10233 LOG(2,
"Altitude levels: %g, %g ... %g km",
10234 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
10235 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
10236 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
10240 if (strcasecmp(levname,
"hybrid") == 0)
10252 ERRMSG(
"You need to specify MET_NLEV, MET_LEV_HYAM, and MET_LEV_HYBM!");
10253 for (
int ip = 0; ip < ctl->
met_nlev; ip++) {
10263 ERRMSG(
"Eta levels must be ascending!");
10267 for (
int ix = 2; ix < met->
nx; ix++)
10269 (fabs(met->
lon[ix] - met->
lon[ix - 1]) -
10270 fabs(met->
lon[1] - met->
lon[0])) > 0.001)
10271 ERRMSG(
"No regular grid spacing in longitudes!");
10272 for (
int iy = 2; iy < met->
ny; iy++)
10274 (fabs(met->
lat[iy] - met->
lat[iy - 1]) -
10275 fabs(met->
lat[1] - met->
lat[0])) > 0.001) {
10276 WARN(
"No regular grid spacing in latitudes!");
10291 LOG(2,
"Read surface data...");
10295 (ncid, (
const char *
const[]) {
"lnsp",
"LNSP" }, 2, ctl, met, dd,
10298 for (
int ix = 0; ix < met->
nx; ix++)
10299 for (
int iy = 0; iy < met->
ny; iy++)
10300 met->
ps[ix][iy] = (
float) (exp(met->
ps[ix][iy]) / 100.);
10303 (ncid, (
const char *
const[]) {
"ps",
"PS",
"sp",
"SP" }, 4, ctl, met,
10306 WARN(
"Cannot not read surface pressure data (use lowest level)!");
10307 for (
int ix = 0; ix < met->
nx; ix++)
10308 for (
int iy = 0; iy < met->
ny; iy++)
10310 = (ctl->
met_np > 0 ? (
float) ctl->
met_p[0] : (
float) met->
p[0]);
10318 (ncid, (
const char *
const[]) {
"z",
"Z" }, 2, ctl, met, dd, met->zs,
10319 (float) (1. / (1000. *
G0)), 1))
10321 (ncid, (
const char *
const[]) {
"zm",
"ZM" }, 2, ctl, met, dd,
10323 (ctl->
met_gp2z ? (float) (1e-3 /
G0) : (float) (1. / 1000.)), 1))
10324 WARN(
"Cannot read surface geopotential height!");
10335 memcpy(help, met->
pl,
sizeof(met->
pl));
10337 (ncid, (
const char *
const[]) {
"gph",
"GPH" }, 2, ctl, met, dd,
10339 (float) (1e-3 /
G0)))
10340 ERRMSG(
"Cannot read geopotential height!");
10343 for (
int ix = 0; ix < met->nx; ix++)
10344 for (
int iy = 0; iy < met->ny; iy++)
10345 met->zs[ix][iy] = met->pl[ix][iy][0];
10346 memcpy(met->pl, help,
sizeof(met->pl));
10352 (ncid, (
const char *
const[]) {
"t2m",
"T2M",
"2t",
"2T",
"t2",
"T2" },
10353 6, ctl, met, dd, met->
ts, 1.0,
10355 WARN(
"Cannot read surface temperature!");
10359 (ncid, (
const char *
const[]) {
"u10m",
"U10M",
"10u",
"10U",
"u10",
10361 }, 6, ctl, met, dd,
10363 WARN(
"Cannot read surface zonal wind!");
10367 (ncid, (
const char *
const[]) {
"v10m",
"V10M",
"10v",
"10V",
"v10",
10369 }, 6, ctl, met, dd,
10371 WARN(
"Cannot read surface meridional wind!");
10375 (ncid, (
const char *
const[]) {
"iews",
"IEWS" }, 2, ctl, met, dd,
10378 WARN(
"Cannot read eastward turbulent surface stress!");
10382 (ncid, (
const char *
const[]) {
"inss",
"INSS" }, 2, ctl, met, dd,
10385 WARN(
"Cannot read northward turbulent surface stress!");
10389 (ncid, (
const char *
const[]) {
"ishf",
"ISHF" }, 2, ctl, met, dd,
10392 WARN(
"Cannot read surface sensible heat flux!");
10396 (ncid, (
const char *
const[]) {
"lsm",
"LSM" }, 2, ctl, met, dd,
10399 WARN(
"Cannot read land-sea mask!");
10403 (ncid, (
const char *
const[]) {
"sstk",
"SSTK",
"sst",
"SST" }, 4, ctl,
10406 WARN(
"Cannot read sea surface temperature!");
10411 (ncid, (
const char *
const[]) {
"blp",
"BLP" }, 2, ctl, met, dd,
10414 WARN(
"Cannot read planetary boundary layer pressure!");
10417 (ncid, (
const char *
const[]) {
"blh",
"BLH" }, 2, ctl, met, dd,
10420 WARN(
"Cannot read planetary boundary layer height!");
10425 (ncid, (
const char *
const[]) {
"cape",
"CAPE" }, 2, ctl, met, dd,
10426 met->
cape, 1.0, 1))
10427 WARN(
"Cannot read CAPE!");
10432 (ncid, (
const char *
const[]) {
"cin",
"CIN" }, 2, ctl, met, dd,
10435 WARN(
"Cannot read convective inhibition!");
10448 LOG(2,
"Read level data...");
10452 (ncid, (
const char *
const[]) {
"t",
"T",
"temp",
"TEMP" }, 4, ctl, met,
10454 ERRMSG(
"Cannot read temperature!");
10458 (ncid, (
const char *
const[]) {
"u",
"U" }, 2, ctl, met, dd, met->
u,
10460 ERRMSG(
"Cannot read zonal wind!");
10462 (ncid, (
const char *
const[]) {
"v",
"V" }, 2, ctl, met, dd, met->
v,
10464 ERRMSG(
"Cannot read meridional wind!");
10466 (ncid, (
const char *
const[]) {
"w",
"W",
"omega",
"OMEGA" }, 4, ctl,
10467 met, dd, met->
w, 0.01f))
10468 WARN(
"Cannot read vertical velocity!");
10473 (ncid, (
const char *
const[]) {
"q",
"Q",
"sh",
"SH" }, 4, ctl, met,
10476 WARN(
"Cannot read specific humidity!");
10479 (ncid, (
const char *
const[]) {
"rh",
"RH" }, 2, ctl, met, dd,
10481 WARN(
"Cannot read relative humidity!");
10482#pragma omp parallel for default(shared) collapse(2)
10483 for (
int ix = 0; ix < met->nx; ix++)
10484 for (
int iy = 0; iy < met->ny; iy++)
10485 for (
int ip = 0; ip < met->np; ip++) {
10486 double pw = met->h2o[ix][iy][ip] *
PSAT(met->t[ix][iy][ip]);
10487 met->h2o[ix][iy][ip] =
10488 (float) (pw / (met->p[ip] - (1.0 -
EPS) * pw));
10494 (ncid, (
const char *
const[]) {
"o3",
"O3" }, 2, ctl, met, dd, met->
o3,
10495 (float) (
MA /
MO3)))
10496 WARN(
"Cannot read ozone data!");
10500 (ncid, (
const char *
const[]) {
"clwc",
"CLWC" }, 2, ctl, met, dd,
10502 WARN(
"Cannot read cloud liquid water content!");
10504 (ncid, (
const char *
const[]) {
"crwc",
"CRWC" }, 2, ctl, met, dd,
10506 WARN(
"Cannot read cloud rain water content!");
10508 (ncid, (
const char *
const[]) {
"ciwc",
"CIWC" }, 2, ctl, met, dd,
10510 WARN(
"Cannot read cloud ice water content!");
10512 (ncid, (
const char *
const[]) {
"cswc",
"CSWC" }, 2, ctl, met, dd,
10514 WARN(
"Cannot read cloud snow water content!");
10516 (ncid, (
const char *
const[]) {
"cc",
"CC" }, 2, ctl, met, dd, met->
cc,
10518 WARN(
"Cannot read cloud cover!");
10523 (ncid, (
const char *
const[]) {
"ZETA",
"zeta" }, 2, ctl, met, dd,
10525 WARN(
"Cannot read ZETA!");
10527 (ncid, (
const char *
const[]) {
"ZETA_DOT_TOT",
"ZETA_DOT_clr",
10529 }, 3, ctl, met, dd, met->zeta_dotl, 0.00001157407f))
10530 ERRMSG(
"Cannot read ZETA_DOT!");
10535#pragma omp parallel for default(shared)
10536 for (
int ix = 0; ix < met->
nx; ix++)
10537 for (
int iy = 0; iy < met->
ny; iy++)
10538 for (
int ip = 0; ip < met->
np; ip++)
10539 met->
zetal[ix][iy][ip] =
10540 (
float) (met->
hyam[ip] / (100.0 *
P0) + met->
hybm[ip]);
10546 (ncid, (
const char *
const[]) {
"etadot",
"ETADOT" }, 2, ctl, met, dd,
10549 ERRMSG(
"Cannot read eta vertical velocity!");
10553#pragma omp parallel for default(shared)
10554 for (
int ix = 0; ix < met->
nx; ix++)
10555 for (
int iy = 0; iy < met->
ny; iy++)
10556 for (
int ip = 0; ip < met->
np; ip++) {
10557 met->
ul[ix][iy][ip] = met->
u[ix][iy][ip];
10558 met->
vl[ix][iy][ip] = met->
v[ix][iy][ip];
10559 met->
wl[ix][iy][ip] = met->
w[ix][iy][ip];
10563 met->
npl = met->
np;
10572 (ncid, (
const char *
const[]) {
"pl",
"PL",
"pressure",
"PRESSURE" },
10573 4, ctl, met, dd, met->pl,
10576 (ncid, (
const char *
const[]) {
"press",
"PRESS" }, 2, ctl, met,
10578 ERRMSG(
"Cannot read pressure on model levels!");
10586 ERRMSG(
"Mismatch in number of model levels!");
10589 for (
int ix = 0; ix < met->
nx; ix++)
10590 for (
int iy = 0; iy < met->
ny; iy++)
10591 for (
int ip = 0; ip < met->
np; ip++)
10592 met->
pl[ix][iy][ip] =
10593 (
float) (met->
hyam[ip] / 100. +
10594 met->
hybm[ip] * met->
ps[ix][iy]);
10602 ERRMSG(
"Mismatch in number of model levels!");
10605#pragma omp parallel for default(shared) collapse(2)
10606 for (
int ix = 0; ix < met->
nx; ix++)
10607 for (
int iy = 0; iy < met->
ny; iy++)
10608 for (
int ip = 0; ip < met->
np; ip++) {
10610 met->
hyam[ip] / 100. + met->
hybm[ip] * met->
ps[ix][iy];
10612 met->
hyam[ip + 1] / 100. + met->
hybm[ip + 1] * met->
ps[ix][iy];
10613 met->
pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
10618 for (
int ix = 0; ix < met->
nx; ix++)
10619 for (
int iy = 0; iy < met->
ny; iy++)
10620 for (
int ip = 1; ip < met->
np; ip++)
10621 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
10622 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
10623 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
10624 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip]))
10625 ERRMSG(
"Pressure profiles are not monotonic!");
10646 for (
int ip = 0; ip < met->
np; ip++)
10647 met->
p[ip] = ctl->
met_p[ip];
10651 for (
int ip = 1; ip < met->
np; ip++)
10652 if (met->
p[ip - 1] < met->
p[ip])
10653 ERRMSG(
"Pressure levels must be descending!");
10669static void met_global_2d_init(
const dd_t *dd,
const met_t *met) {
10671 MPI_Comm_rank(MPI_COMM_WORLD, &met_global_2d.rank);
10672 MPI_Comm_size(MPI_COMM_WORLD, &met_global_2d.size);
10673 const unsigned long long own[8] = {
10680 ALLOC(met_global_2d.geometry,
unsigned long long,
10681 8 * (
size_t) met_global_2d.size);
10682 MPI_Allgather(own, 8, MPI_UNSIGNED_LONG_LONG, met_global_2d.geometry,
10683 8, MPI_UNSIGNED_LONG_LONG, MPI_COMM_WORLD);
10685 const size_t nx = (size_t) dd->
nx_glob, ny = (
size_t) dd->
ny_glob;
10686 if (nx > SIZE_MAX / ny || nx * ny > SIZE_MAX /
sizeof(
float))
10687 ERRMSG(
"Global 2-D meteorological field exceeds addressable memory!");
10688 met_global_2d.global_elements = nx * ny;
10689 met_global_2d.local_elements = (size_t) met->
nx * (
size_t) met->
ny;
10690 if (met_global_2d.local_elements > SIZE_MAX /
sizeof(
float))
10691 ERRMSG(
"Local 2-D meteorological field exceeds addressable memory!");
10692 ALLOC(met_global_2d.local,
float, met_global_2d.local_elements);
10694 for (
int rank = 0;
rank < met_global_2d.size;
rank++) {
10695 const unsigned long long *g = met_global_2d.geometry + 8 *
rank;
10696 if (g[3] > SIZE_MAX - g[5])
10697 ERRMSG(
"Invalid DD window width for global 2-D redistribution!");
10698 const size_t width = (size_t) g[3] + (
size_t) g[5];
10699 if (width == 0 || g[2] > SIZE_MAX / width)
10700 ERRMSG(
"Invalid DD window size for global 2-D redistribution!");
10701 const size_t count = (size_t) g[2] * width;
10702 if (g[6] > width || g[3] > width - g[6]
10703 || g[7] > width || g[5] > width - g[7]
10704 || count > SIZE_MAX /
sizeof(
float)
10705 || g[0] + g[2] > ny || g[1] + g[3] > nx
10706 || g[4] + g[5] > nx)
10707 ERRMSG(
"Invalid DD window for global 2-D redistribution!");
10708 if (count > met_global_2d.packed_elements)
10709 met_global_2d.packed_elements = count;
10711 ALLOC(met_global_2d.packed,
float, met_global_2d.packed_elements);
10715static void met_global_2d_free(
void) {
10717 free(met_global_2d.geometry);
10718 free(met_global_2d.global);
10719 free(met_global_2d.packed);
10720 free(met_global_2d.local);
10721 memset(&met_global_2d, 0,
sizeof(met_global_2d));
10725static void met_global_2d_pack(
10728 const unsigned long long *g,
10731 const size_t width = (size_t) g[3] + (
size_t) g[5];
10732 for (
size_t y = 0; y < (size_t) g[2]; y++) {
10733 float *row =
packed + y * width;
10734 const float *source =
global + ((size_t) g[0] + y) * nx;
10735 memcpy(row + (
size_t) g[6], source + (
size_t) g[1],
10736 (
size_t) g[3] *
sizeof(
float));
10738 memcpy(row + (
size_t) g[7], source + (
size_t) g[4],
10739 (
size_t) g[5] *
sizeof(
float));
10744static const float *met_global_2d_read(
10751 const int reader = level % met_global_2d.size;
10752 if (met_global_2d.rank == reader) {
10754 if (met_global_2d.global == NULL)
10755 ALLOC(met_global_2d.global,
float, met_global_2d.global_elements);
10757 const size_t start[4] = { 0, (size_t) level, 0, 0 };
10758 const size_t count[4] = { 1, 1, (size_t) dd->
ny_glob,
10760 NC(nc_get_vara_float(ncid, varid, start, count,
10761 met_global_2d.global));
10763 const size_t start[3] = { 0, 0, 0 };
10764 const size_t count[3] = { 1, (size_t) dd->
ny_glob,
10766 NC(nc_get_vara_float(ncid, varid, start, count,
10767 met_global_2d.global));
10771 for (
int rank = 0;
rank < met_global_2d.size;
rank++) {
10772 const unsigned long long *g = met_global_2d.geometry + 8 *
rank;
10773 const size_t elements = (size_t) g[2] * ((
size_t) g[3] + (size_t) g[5]);
10774 if (met_global_2d.rank == reader) {
10776 float *target =
rank == reader ? met_global_2d.local :
10777 met_global_2d.packed;
10778 met_global_2d_pack(met_global_2d.global, target, g,
10780 if (
rank != reader) {
10782 for (
size_t offset = 0; offset < elements;) {
10783 const int count = (int)
MIN(elements - offset, (
size_t) INT_MAX);
10784 if (MPI_Send(target + offset, count, MPI_FLOAT,
rank, 0,
10785 MPI_COMM_WORLD) != MPI_SUCCESS)
10786 ERRMSG(
"Failed to distribute meteorological field!");
10787 offset += (size_t) count;
10790 }
else if (met_global_2d.rank ==
rank) {
10792 for (
size_t offset = 0; offset < elements;) {
10793 const int count = (int)
MIN(elements - offset, (
size_t) INT_MAX);
10794 if (MPI_Recv(met_global_2d.local + offset, count, MPI_FLOAT, reader,
10795 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE) != MPI_SUCCESS)
10796 ERRMSG(
"Failed to receive meteorological field!");
10797 offset += (size_t) count;
10801 return met_global_2d.local;
10805static void met_global_2d_check_var(
10810 const int levels) {
10812 int actual, ids[NC_MAX_VAR_DIMS];
10813 char name[NC_MAX_NAME + 1];
10815 NC(nc_inq_varndims(ncid, varid, &actual));
10816 if (actual != ndims)
10817 ERRMSG(
"MET_NC_READ_MODE=1 requires time-first NetCDF variables!");
10818 NC(nc_inq_vardimid(ncid, varid, ids));
10819 NC(nc_inq_dimname(ncid, ids[0], name));
10820 if (strcmp(name,
"time") != 0)
10821 ERRMSG(
"MET_NC_READ_MODE=1 requires time as first dimension!");
10822 NC(nc_inq_dimlen(ncid, ids[0], &length));
10824 ERRMSG(
"MET_NC_READ_MODE=1 requires a nonempty time dimension!");
10825 NC(nc_inq_dimname(ncid, ids[ndims - 1], name));
10826 if (strcmp(name,
"lon") != 0)
10827 ERRMSG(
"MET_NC_READ_MODE=1 requires longitude as last dimension!");
10828 NC(nc_inq_dimlen(ncid, ids[ndims - 1], &length));
10829 if (length != (
size_t) dd->
nx_glob)
10830 ERRMSG(
"MET_NC_READ_MODE=1 requires longitude as fastest dimension!");
10831 NC(nc_inq_dimname(ncid, ids[ndims - 2], name));
10832 if (strcmp(name,
"lat") != 0)
10833 ERRMSG(
"MET_NC_READ_MODE=1 requires latitude before longitude!");
10834 NC(nc_inq_dimlen(ncid, ids[ndims - 2], &length));
10835 if (length != (
size_t) dd->
ny_glob)
10836 ERRMSG(
"MET_NC_READ_MODE=1 requires latitude before longitude!");
10838 NC(nc_inq_dimlen(ncid, ids[1], &length));
10839 if (length != (
size_t) levels)
10840 ERRMSG(
"MET_NC_READ_MODE=1 requires all vertical levels!");
10849 const char *
const varnames[],
10850 const size_t nvarnames,
10854 float dest[
EX][
EY],
10858 const char *varsel = NULL;
10860 float offset, scalfac;
10865 for (
size_t i = 0; i < nvarnames; i++)
10866 if (nc_inq_varid(ncid, varnames[i], &varid) == NC_NOERR) {
10867 varsel = varnames[i];
10870 if (varsel == NULL)
10875 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
10876 && nc_get_att_float(ncid, varid,
"scale_factor",
10877 &scalfac) == NC_NOERR) {
10885 short fillval, missval;
10886 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
10888 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
10892 LOG(2,
"Read 2-D variable: %s"
10893 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
10894 varsel, fillval, missval, scalfac, offset);
10897 NC(nc_get_var_short(ncid, varid, help));
10901 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
10904 omp_set_dynamic(1);
10905#pragma omp parallel for default(shared)
10906 for (
int ix = 0; ix < met->
nx; ix++)
10907 for (
int iy = 0; iy < met->
ny; iy++) {
10910 const short aux = help[
ARRAY_2D(iy, ix, met->
nx)];
10911 if ((fillval == 0 || aux != fillval)
10912 && (missval == 0 || aux != missval)
10913 && fabsf(aux * scalfac + offset) < 1e14f)
10914 dest[ix][iy] += scl * (aux * scalfac + offset);
10916 dest[ix][iy] = NAN;
10918 omp_set_dynamic(0);
10925 else if (!ctl->
dd) {
10933 float fillval, missval;
10934 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
10936 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
10940 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
10941 varsel, fillval, missval);
10944 NC(nc_get_var_float(ncid, varid, help));
10950 omp_set_dynamic(1);
10951#pragma omp parallel for default(shared)
10952 for (
int ix = 0; ix < met->
nx; ix++)
10953 for (
int iy = 0; iy < met->
ny; iy++) {
10956 const float aux = help[
ARRAY_2D(iy, ix, met->
nx)];
10957 if ((fillval == 0 || aux != fillval)
10958 && (missval == 0 || aux != missval)
10959 && fabsf(aux) < 1e14f)
10960 dest[ix][iy] += scl * aux;
10962 dest[ix][iy] = NAN;
10964 omp_set_dynamic(0);
10969 omp_set_dynamic(1);
10970#pragma omp parallel for default(shared)
10971 for (
int iy = 0; iy < met->
ny; iy++)
10972 for (
int ix = 0; ix < met->
nx; ix++) {
10975 const float aux = help[
ARRAY_2D(ix, iy, met->
ny)];
10976 if ((fillval == 0 || aux != fillval)
10977 && (missval == 0 || aux != missval)
10978 && fabsf(aux) < 1e14f)
10979 dest[ix][iy] += scl * aux;
10981 dest[ix][iy] = NAN;
10983 omp_set_dynamic(0);
10994 float fillval, missval;
10995 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
10997 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
11001 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
11002 varsel, fillval, missval);
11006 met_global_2d_check_var(ncid, varid, 3, dd, 0);
11007 NC(nc_var_par_access(ncid, varid, NC_INDEPENDENT));
11008 const float *help = met_global_2d_read(ncid, varid, 3, varid, dd);
11010 omp_set_dynamic(1);
11011#pragma omp parallel for default(shared)
11012 for (
int iy = 0; iy < met->
ny; iy++)
11013 for (
int ix = 0; ix < met->
nx; ix++) {
11014 const float aux = help[(size_t) iy * (
size_t) met->
nx + (size_t) ix];
11017 if ((fillval == 0 || aux != fillval)
11018 && (missval == 0 || aux != missval) && fabsf(aux) < 1e14f)
11019 dest[ix][iy] += scl * aux;
11021 dest[ix][iy] = NAN;
11023 omp_set_dynamic(0);
11032 size_t help_subdomain_start[3];
11033 size_t help_subdomain_count[3];
11035 help_subdomain_start[0] = 0;
11044 help_subdomain_count[0] = 1;
11059 nc_var_par_access(ncid, varid, NC_COLLECTIVE);
11061 NC(nc_get_vara_float
11062 (ncid, varid, help_subdomain_start, help_subdomain_count, help));
11065 size_t help_halo_bnd_start[3];
11066 size_t help_halo_bnd_count[3];
11068 help_halo_bnd_start[0] = 0;
11077 help_halo_bnd_count[0] = 1;
11087 ALLOC(help_halo,
float,
11088 help_halo_bnd_count[1] * help_halo_bnd_count[2]);
11091 nc_var_par_access(ncid, varid, NC_COLLECTIVE);
11093 NC(nc_get_vara_float
11094 (ncid, varid, help_halo_bnd_start, help_halo_bnd_count,
11103 omp_set_dynamic(1);
11104#pragma omp parallel for default(shared)
11105 for (
int ix = 0; ix < (int) help_subdomain_count[2]; ix++)
11106 for (
int iy = 0; iy < (int) help_subdomain_count[1]; iy++) {
11110 help[
ARRAY_2D(iy, ix, (
int) help_subdomain_count[2])];
11111 if ((fillval == 0 || aux != fillval)
11112 && (missval == 0 || aux != missval)
11113 && fabsf(aux) < 1e14f) {
11119#pragma omp parallel for default(shared)
11120 for (
int ix = 0; ix < (int) help_halo_bnd_count[2]; ix++)
11121 for (
int iy = 0; iy < (int) help_halo_bnd_count[1]; iy++) {
11125 help_halo[
ARRAY_2D(iy, ix, (
int) help_halo_bnd_count[2])];
11126 if ((fillval == 0 || aux != fillval)
11127 && (missval == 0 || aux != missval)
11128 && fabsf(aux) < 1e14f)
11134 omp_set_dynamic(0);
11139 omp_set_dynamic(1);
11140#pragma omp parallel for default(shared)
11141 for (
int ix = 0; ix < (int) help_subdomain_count[1]; ix++)
11142 for (
int iy = 0; iy < (int) help_subdomain_count[2]; iy++) {
11146 help[
ARRAY_2D(ix, iy, (
int) help_subdomain_count[1])];
11147 if ((fillval == 0 || aux != fillval)
11148 && (missval == 0 || aux != missval)
11149 && fabsf(aux) < 1e14f)
11155#pragma omp parallel for default(shared)
11156 for (
int ix = 0; ix < (int) help_halo_bnd_count[1]; ix++)
11157 for (
int iy = 0; iy < (int) help_halo_bnd_count[2]; iy++) {
11161 help_halo[
ARRAY_2D(ix, iy, (
int) help_halo_bnd_count[1])];
11162 if ((fillval == 0 || aux != fillval)
11163 && (missval == 0 || aux != missval)
11164 && fabsf(aux) < 1e14f)
11169 omp_set_dynamic(0);
11187 const char *
const varnames[],
11188 const size_t nvarnames,
11195 const char *varsel = NULL;
11197 float offset, scalfac;
11202 for (
size_t i = 0; i < nvarnames; i++)
11203 if (nc_inq_varid(ncid, varnames[i], &varid) == NC_NOERR) {
11204 varsel = varnames[i];
11207 if (varsel == NULL)
11212 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
11213 && nc_get_att_float(ncid, varid,
"scale_factor",
11214 &scalfac) == NC_NOERR) {
11222 short fillval, missval;
11223 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
11225 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
11229 LOG(2,
"Read 3-D variable: %s "
11230 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
11231 varsel, fillval, missval, scalfac, offset);
11234 NC(nc_get_var_short(ncid, varid, help));
11238 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
11241 omp_set_dynamic(1);
11242#pragma omp parallel for default(shared)
11243 for (
int ix = 0; ix < met->
nx; ix++)
11244 for (
int iy = 0; iy < met->
ny; iy++)
11245 for (
int ip = 0; ip < met->
np; ip++) {
11246 const short aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
11247 if ((fillval == 0 || aux != fillval)
11248 && (missval == 0 || aux != missval)
11249 && fabsf(aux * scalfac + offset) < 1e14f)
11250 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
11252 dest[ix][iy][ip] = NAN;
11254 omp_set_dynamic(0);
11261 else if (!ctl->
dd) {
11269 float fillval, missval;
11270 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
11272 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
11276 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
11277 varsel, fillval, missval);
11280 NC(nc_get_var_float(ncid, varid, help));
11286 omp_set_dynamic(1);
11287#pragma omp parallel for default(shared)
11288 for (
int ix = 0; ix < met->
nx; ix++)
11289 for (
int iy = 0; iy < met->
ny; iy++)
11290 for (
int ip = 0; ip < met->
np; ip++) {
11291 const float aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
11292 if ((fillval == 0 || aux != fillval)
11293 && (missval == 0 || aux != missval)
11294 && fabsf(aux) < 1e14f)
11295 dest[ix][iy][ip] = scl * aux;
11297 dest[ix][iy][ip] = NAN;
11299 omp_set_dynamic(0);
11304 omp_set_dynamic(1);
11305#pragma omp parallel for default(shared)
11306 for (
int ip = 0; ip < met->
np; ip++)
11307 for (
int iy = 0; iy < met->
ny; iy++)
11308 for (
int ix = 0; ix < met->
nx; ix++) {
11309 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
11310 if ((fillval == 0 || aux != fillval)
11311 && (missval == 0 || aux != missval)
11312 && fabsf(aux) < 1e14f)
11313 dest[ix][iy][ip] = scl * aux;
11315 dest[ix][iy][ip] = NAN;
11317 omp_set_dynamic(0);
11328 float fillval, missval;
11329 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
11331 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
11335 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
11336 varsel, fillval, missval);
11340 met_global_2d_check_var(ncid, varid, 4, dd, met->
np);
11341 NC(nc_var_par_access(ncid, varid, NC_INDEPENDENT));
11342 for (
int ip = 0; ip < met->
np; ip++) {
11343 const float *help = met_global_2d_read(ncid, varid, 4, ip, dd);
11345 omp_set_dynamic(1);
11346#pragma omp parallel for default(shared)
11347 for (
int iy = 0; iy < met->
ny; iy++)
11348 for (
int ix = 0; ix < met->
nx; ix++) {
11350 help[(size_t) iy * (
size_t) met->
nx + (size_t) ix];
11351 if ((fillval == 0 || aux != fillval)
11352 && (missval == 0 || aux != missval) && fabsf(aux) < 1e14f)
11353 dest[ix][iy][ip] = scl * aux;
11355 dest[ix][iy][ip] = NAN;
11357 omp_set_dynamic(0);
11366 size_t help_subdomain_start[4];
11367 size_t help_subdomain_count[4];
11368 size_t help_halo_bnd_start[4];
11369 size_t help_halo_bnd_count[4];
11372 for (
int i = 0; i < 4; i++) {
11409 NC(nc_var_par_access(ncid, varid, NC_INDEPENDENT));
11411 NC(nc_get_vara_float
11412 (ncid, varid, help_subdomain_start, help_subdomain_count, help));
11416 ALLOC(help_halo,
float,
11421 NC(nc_var_par_access(ncid, varid, NC_INDEPENDENT));
11425 NC(nc_get_vara_float
11426 (ncid, varid, help_halo_bnd_start, help_halo_bnd_count,
11436 omp_set_dynamic(1);
11437#pragma omp parallel for default(shared)
11440 for (
int ip = 0; ip < met->
np; ip++) {
11444 if ((fillval == 0 || aux != fillval)
11445 && (missval == 0 || aux != missval)
11446 && fabsf(aux) < 1e14f) {
11453#pragma omp parallel for default(shared)
11456 for (
int ip = 0; ip < met->
np; ip++) {
11460 if ((fillval == 0 || aux != fillval)
11461 && (missval == 0 || aux != missval)
11462 && fabsf(aux) < 1e14f)
11467 omp_set_dynamic(0);
11472 omp_set_dynamic(1);
11473#pragma omp parallel for default(shared)
11474 for (
int ip = 0; ip < met->
np; ip++)
11480 if ((fillval == 0 || aux != fillval)
11481 && (missval == 0 || aux != missval)
11482 && fabsf(aux) < 1e14f)
11488#pragma omp parallel for default(shared)
11489 for (
int ip = 0; ip < met->
np; ip++)
11495 if ((fillval == 0 || aux != fillval)
11496 && (missval == 0 || aux != missval)
11497 && fabsf(aux) < 1e14f)
11502 omp_set_dynamic(0);
11520 const char *filename,
11525 size_t filename_len = strlen(filename) + 1;
11526 char sf_filename[filename_len];
11527 char ml_filename[filename_len];
11528 strcpy(sf_filename, filename);
11529 strcpy(ml_filename, filename);
11534 FILE *ml_file = fopen(ml_filename,
"rb");
11535 FILE *sf_file = fopen(sf_filename,
"rb");
11536 if (ml_file == NULL || sf_file == NULL) {
11537 if (ml_file != NULL) {
11539 WARN(
"Cannot open file: %s", sf_filename);
11541 if (sf_file != NULL) {
11543 WARN(
"Cannot open file: %s", ml_filename);
11549 int ml_num_messages = 0, err = 0;
11550 ECC(codes_count_in_file(0, ml_file, &ml_num_messages));
11553 (size_t) ml_num_messages);
11554 for (
int i = 0; i < ml_num_messages; i++) {
11556 if ((h = codes_grib_handle_new_from_file(0, ml_file, &err)) != NULL)
11561 int sf_num_messages = 0;
11562 ECC(codes_count_in_file(0, sf_file, &sf_num_messages));
11565 (size_t) sf_num_messages);
11566 for (
int i = 0; i < sf_num_messages; i++) {
11568 if ((h = codes_grib_handle_new_from_file(0, sf_file, &err)) != NULL)
11581 for (
int i = 0; i < sf_num_messages; i++)
11582 codes_handle_delete(sf_handles[i]);
11586 size_t value_count = 0;
11587 ECC(codes_get_size(ml_handles[0],
"pv", &value_count));
11588 if (value_count % 2 != 0)
11589 ERRMSG(
"Unexpected pv array length!");
11590 size_t nlevels = value_count / 2 - 1;
11592 ALLOC(values,
double,
11594 ECC(codes_get_double_array(ml_handles[0],
"pv", values, &value_count));
11595 double *a_vals = values;
11596 double *b_vals = values + nlevels;
11597 if (met->
npl > (
int) nlevels)
11598 ERRMSG(
"met->npl exceeds number of pressure levels in GRIB!");
11599 for (
int nx = 0; nx < met->
nx; nx++)
11600 for (
int ny = 0; ny < met->
ny; ny++)
11601 for (
int level = 0; level <= met->
npl; level++) {
11602 const float p1 = (float) (a_vals[level] * 0.01f +
11603 met->
ps[nx][ny] * b_vals[level]);
11604 const float p2 = (float) (a_vals[level + 1] * 0.01f +
11605 met->
ps[nx][ny] * b_vals[level + 1]);
11606 met->
pl[nx][ny][level] = 0.5f * (p1 + p2);
11612 for (
int i = 0; i < ml_num_messages; i++)
11613 codes_handle_delete(ml_handles[i]);
11631 LOG(2,
"Read meteo grid information...");
11634 char datestr[
LEN], timestr[
LEN];
11635 size_t s_date =
sizeof(datestr);
11636 ECC(codes_get_string(handles[0],
"dataDate", datestr, &s_date));
11637 size_t s_time =
sizeof(timestr);
11638 ECC(codes_get_string(handles[0],
"dataTime", timestr, &s_time));
11639 int year, month, day, hour;
11640 if (sscanf(datestr,
"%4d%2d%2d", &year, &month, &day) != 3)
11641 ERRMSG(
"Failed to parse dataDate: %s", datestr);
11642 if (sscanf(timestr,
"%2d", &hour) != 1)
11643 ERRMSG(
"Failed to parse dataTime: %s", timestr);
11645 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)", met->
time, year, month,
11649 long count_lat = 0, count_lon = 0;
11650 ECC(codes_get_long(handles[0],
"Nj", &count_lat));
11651 ECC(codes_get_long(handles[0],
"Ni", &count_lon));
11652 met->
ny = (int) count_lat;
11653 met->
nx = (int) count_lon;
11656 LOG(2,
"Number of longitudes: %d", met->
nx);
11657 if (met->
nx < 2 || met->
nx >
EX)
11658 ERRMSG(
"Number of longitudes out of range!");
11659 LOG(2,
"Number of latitudes: %d", met->
ny);
11660 if (met->
ny < 2 || met->
ny >
EY)
11661 ERRMSG(
"Number of latitudes out of range!");
11663 double first_lon, last_lon, first_lat, last_lat, inc_lon, inc_lat;
11664 ECC(codes_get_double
11665 (handles[0],
"longitudeOfFirstGridPointInDegrees", &first_lon));
11666 ECC(codes_get_double
11667 (handles[0],
"latitudeOfFirstGridPointInDegrees", &first_lat));
11668 ECC(codes_get_double
11669 (handles[0],
"longitudeOfLastGridPointInDegrees", &last_lon));
11670 ECC(codes_get_double
11671 (handles[0],
"latitudeOfLastGridPointInDegrees", &last_lat));
11672 ECC(codes_get_double(handles[0],
"iDirectionIncrementInDegrees", &inc_lon));
11673 ECC(codes_get_double(handles[0],
"jDirectionIncrementInDegrees", &inc_lat));
11675 long jscanpos, iscanneg;
11676 ECC(codes_get_long(handles[0],
"iScansNegatively", &iscanneg));
11677 ECC(codes_get_long(handles[0],
"jScansPositively", &jscanpos));
11682 for (
double i = first_lon; i <= last_lon + 1e-6; i += inc_lon) {
11683 met->
lon[counter] = i;
11686 for (
double i = first_lon; i > last_lon - 1e-6; i -= inc_lon) {
11687 met->
lon[counter] = i;
11693 for (
double i = first_lat; i > last_lat - 1e-6; i -= inc_lat) {
11694 met->
lat[counter] = i;
11697 for (
double i = first_lat; i <= last_lat + 1e-6; i += inc_lat) {
11698 met->
lat[counter] = i;
11703 LOG(2,
"Longitudes: %g, %g ... %g deg",
11704 met->
lon[0], met->
lon[1], met->
lon[met->
nx - 1]);
11705 LOG(2,
"Latitudes: %g, %g ... %g deg",
11706 met->
lat[0], met->
lat[1], met->
lat[met->
ny - 1]);
11710 for (
int i = 0; i < count_handles; i++) {
11712 ECC(codes_get_long(handles[i],
"level", &level));
11713 if (level > max_level)
11714 max_level = (int) level;
11716 met->
npl = max_level;
11719 LOG(2,
"Number of levels: %d", met->
npl);
11720 if (met->
npl < 2 || met->
npl >
EP)
11721 ERRMSG(
"Number of levels out of range!");
11730 const int num_messages,
11736 LOG(2,
"Read level data...");
11739 int t_flag = 0, u_flag = 0, v_flag = 0, w_flag = 0, o3_flag = 0, h2o_flag =
11740 0, lwc_flag = 0, rwc_flag = 0, iwc_flag = 0, swc_flag = 0, cc_flag = 0;
11743 for (
int i = 0; i < num_messages; i++) {
11745 size_t max_size =
LEN;
11746 char short_name[max_size];
11747 size_t value_count;
11751 long current_level;
11752 ECC(codes_get_long(handles[i],
"level", ¤t_level));
11753 current_level -= 1;
11756 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
11757 ECC(codes_get_size(handles[i],
"values", &value_count));
11758 ALLOC(values,
double,
11760 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
11768 ECC_READ_3D(
"w", current_level, met->
w, 0.01f, w_flag);
11786 if (t_flag != met->
npl)
11787 ERRMSG(
"Cannot read temperature!");
11788 if (u_flag != met->
npl)
11789 ERRMSG(
"Cannot read zonal wind!");
11790 if (v_flag != met->
npl)
11791 ERRMSG(
"Cannot read meridional wind!");
11792 if (w_flag != met->
npl)
11793 WARN(
"Cannot read vertical velocity!");
11794 if (h2o_flag != met->
npl)
11795 WARN(
"Cannot read specific humidity!");
11796 if (o3_flag != met->
npl)
11797 WARN(
"Cannot read ozone data!");
11798 if (lwc_flag != met->
npl)
11799 WARN(
"Cannot read cloud liquid water content!");
11800 if (rwc_flag != met->
npl)
11801 WARN(
"Cannot read cloud rain water content!");
11802 if (iwc_flag != met->
npl)
11803 WARN(
"Cannot read cloud ice water content!");
11804 if (swc_flag != met->
npl)
11805 WARN(
"Cannot read cloud snow water content!");
11806 if (cc_flag != met->
npl)
11807 WARN(
"Cannot read cloud cover!");
11810 for (
int ix = 0; ix < met->
nx; ix++)
11811 for (
int iy = 0; iy < met->
ny; iy++)
11812 for (
int ip = 1; ip < met->
np; ip++)
11813 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
11814 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
11815 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
11816 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip])) {
11817 LOG(1,
"%f %f %f %f", met->
pl[ix][iy][0], met->
pl[ix][iy][1],
11818 met->
pl[ix][iy][ip - 1], met->
pl[ix][iy][ip]);
11819 ERRMSG(
"Pressure profiles are not monotonic!");
11840 for (
int ip = 0; ip < met->
np; ip++)
11841 met->
p[ip] = ctl->
met_p[ip];
11845 for (
int ip = 1; ip < met->
np; ip++)
11846 if (met->
p[ip - 1] < met->
p[ip])
11847 ERRMSG(
"Pressure levels must be descending!");
11856 const int num_messages,
11862 LOG(2,
"Read surface data...");
11865 int sp_flag = 0, z_flag = 0, t_flag = 0, u_flag = 0, v_flag = 0, ess_flag =
11866 0, nss_flag = 0, shf_flag = 0, lsm_flag = 0, sst_flag = 0, cape_flag = 0,
11867 cin_flag = 0, pbl_flag = 0;
11870 for (
int i = 0; i < num_messages; i++) {
11872 size_t max_size =
LEN, value_count;
11874 char short_name[max_size];
11877 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
11878 ECC(codes_get_size(handles[i],
"values", &value_count));
11879 double *values = (
double *) malloc(value_count *
sizeof(
double));
11880 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
11927 WARN(
"Cannot read surface pressure data!");
11929 WARN(
"Cannot read surface geopotential height!");
11931 WARN(
"Cannot read surface temperature!");
11933 WARN(
"Cannot read surface zonal wind!");
11935 WARN(
"Cannot read surface meridional wind!");
11937 WARN(
"Cannot read eastward turbulent surface stress!");
11939 WARN(
"Cannot read northward turbulent surface stress!");
11941 WARN(
"Cannot read surface sensible heat flux!");
11943 WARN(
"Cannot read land-sea mask!");
11945 WARN(
"Cannot read sea surface temperature!");
11947 if (cape_flag == 0)
11948 WARN(
"Cannot read CAPE!");
11950 WARN(
"Cannot read convective inhibition!");
11952 if (ctl->
met_pbl == 1 && pbl_flag == 0)
11953 WARN(
"Cannot read planetary boundary layer height!");
11963 const char *varname) {
11965 double aux[
EP], p[
EP];
11969 LOG(2,
"Interpolate meteo data to pressure levels: %s", varname);
11972#pragma omp parallel for default(shared) private(aux,p) collapse(2)
11973 for (
int ix = 0; ix < met->
nx; ix++)
11974 for (
int iy = 0; iy < met->
ny; iy++) {
11977 for (
int ip = 0; ip < met->
np; ip++)
11978 p[ip] = met->
pl[ix][iy][ip];
11981 for (
int ip = 0; ip < ctl->
met_np; ip++) {
11982 double pt = ctl->
met_p[ip];
11983 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
11985 else if ((pt > p[met->
np - 1] && p[1] > p[0])
11986 || (pt < p[met->
np - 1] && p[1] < p[0]))
11987 pt = p[met->
np - 1];
11989 aux[ip] =
LIN(p[ip2], var[ix][iy][ip2],
11990 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
11994 for (
int ip = 0; ip < ctl->
met_np; ip++)
11995 var[ix][iy][ip] = (
float) aux[ip];
12011 LOG(2,
"Make zeta profiles monotone...");
12014#pragma omp parallel for default(shared) collapse(2)
12015 for (
int i = 0; i < met->
nx; i++)
12016 for (
int j = 0; j < met->
ny; j++) {
12019 while (k < met->npl) {
12020 if ((met->
zetal[i][j][k - 1] >= met->
zetal[i][j][k])) {
12026 while ((met->
zetal[i][j][k - 1] >=
12027 met->
zetal[i][j][k + l]) & (k + l < met->npl));
12032 (float) (met->
zetal[i][j][k + l] - met->
zetal[i][j][k - 1])
12035 for (
int m = k; m < k + l; m++) {
12036 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
12037 met->
zetal[i][j][m] = s * d + met->
zetal[i][j][k - 1];
12049#pragma omp parallel for default(shared) collapse(2)
12050 for (
int i = 0; i < met->
nx; i++)
12051 for (
int j = 0; j < met->
ny; j++) {
12054 while (k < met->npl) {
12055 if ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k])) {
12062 while ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k + l]) & (k + l <
12067 float s = (float) (met->
pl[i][j][k + l] - met->
pl[i][j][k - 1])
12070 for (
int m = k; m < k + l; m++) {
12071 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
12072 met->
pl[i][j][m] = s * d + met->
pl[i][j][k - 1];
12087 const char *filename,
12100 (filename, NC_NOWRITE | NC_SHARE, MPI_COMM_WORLD, MPI_INFO_NULL,
12107 if (!have_ncid && nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
12108 WARN(
"Cannot open file!");
12122 met_global_2d_init(dd, met);
12136 met_global_2d_free();
12140 NC(nc_close(ncid));
12159 MPI_Comm_rank(MPI_COMM_WORLD, &
rank);
12160 MPI_Comm_size(MPI_COMM_WORLD, &
size);
12167 LOG(2,
"Number of longitudes: %d", dd->
nx_glob);
12168 LOG(2,
"Number of latitudes: %d", dd->
ny_glob);
12172 ERRMSG(
"Global grid is too large!");
12175 ERRMSG(
"Too many zonal subdomains for global x grid!");
12178 ERRMSG(
"Too many meridional subdomains for global y grid!");
12184 LOG(2,
"Longitudes: %g, %g ... %g deg",
12186 LOG(2,
"Latitudes: %g, %g ... %g deg",
12194 const int left = (zonal_rank == 0);
12196 const int top = (merid_rank == 0);
12203 const int ix0 = zonal_rank * nx_block;
12204 const int iy0 = merid_rank * ny_block;
12206 int nx_core = nx_block;
12207 int ny_core = ny_block;
12216 if ((!left && halo > ix0)
12217 || (!right && halo > dd->
nx_glob - ix0 - nx_core)
12218 || (!top && halo > iy0)
12219 || (!bottom && halo > dd->
ny_glob - iy0 - ny_core))
12220 ERRMSG(
"DD_HALOS_SIZE exceeds the available global grid!");
12222 const int nx_local = nx_core
12224 const int ny_local = ny_core + (!top ? halo : 0) + (!bottom ? halo : 0);
12225 if (nx_local >
EX || ny_local >
EY)
12226 ERRMSG(
"DD halo grid exceeds EX or EY. Increase the grid capacity!");
12227 if (nx_local < 2 || ny_local < 2)
12228 ERRMSG(
"DD halo grid needs at least two points in each direction!");
12246 if (!left && !right) {
12249 }
else if (left ^ right) {
12255 if (!top && !bottom) {
12258 }
else if (top ^ bottom) {
12265 double lon_shift = 0.0;
12267 if (left ^ right) {
12281 lon_shift = left ? -360.0 : 360.0;
12314 LOG(2,
"Define subdomain properties.");
12315 LOG(2,
"MPI information: Rank %d, Size %d",
rank,
size);
12316 LOG(2,
"Edge position: l=%d,r=%d,t=%d,b=%d", left, right, top, bottom);
12317 LOG(2,
"Total size for subdomain meteo data: nx %d ny %d np %d",
12318 met->
nx, met->
ny, met->
np);
12319 LOG(2,
"Hyperslab sizes for boundary halos: nx %d ny %d np %d",
12322 LOG(2,
"Hyperslab sizes for subdomain and inner halos: nx %d ny %d np %d",
12325 LOG(2,
"Subdomain start: nx %ld ny %ld np %ld",
12327 LOG(2,
"Boundary halo start: nx %ld ny %ld np %ld",
12330 LOG(2,
"%d Subdomain longitudes: %g, %g ... %g deg",
12332 LOG(2,
"%d Subdomain latitudes: %g, %g ... %g deg",
12344 LOG(2,
"Calculate planetary boundary layer...");
12350#pragma omp parallel for default(shared) collapse(2)
12351 for (
int ix = 0; ix < met->
nx; ix++)
12352 for (
int iy = 0; iy < met->
ny; iy++) {
12355 const float z = met->
zs[ix][iy] + met->
pbl[ix][iy];
12358 (float) (
LIN(met->
z[ix][iy][ip], met->
p[ip],
12359 met->
z[ix][iy][ip + 1], met->
p[ip + 1], z));
12364 else if (ctl->
met_pbl == 2) {
12368 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
12371#pragma omp parallel for default(shared) collapse(2)
12372 for (
int ix = 0; ix < met->
nx; ix++)
12373 for (
int iy = 0; iy < met->
ny; iy++) {
12376 const double pbl_bot = met->
ps[ix][iy] * exp(-dz /
H0);
12380 for (ip = 1; ip < met->
np; ip++)
12381 if (met->
p[ip] < pbl_bot)
12385 const double h2os =
LIN(met->
p[ip - 1], met->
h2o[ix][iy][ip - 1],
12386 met->
p[ip], met->
h2o[ix][iy][ip], pbl_bot);
12387 const double tvs =
THETAVIRT(pbl_bot, met->
ts[ix][iy], h2os);
12390 double rib_old = 0;
12393 for (; ip < met->
np; ip++) {
12396 double vh2 =
SQR(met->
u[ix][iy][ip] - met->
us[ix][iy])
12397 +
SQR(met->
v[ix][iy][ip] - met->
vs[ix][iy]);
12398 vh2 =
MAX(vh2,
SQR(umin));
12402 G0 * 1e3 * (met->
z[ix][iy][ip] - met->
zs[ix][iy]) / tvs
12404 met->
h2o[ix][iy][ip]) - tvs) / vh2;
12407 if (rib >= rib_crit) {
12408 met->
pbl[ix][iy] = (float) (
LIN(rib_old, met->
p[ip - 1],
12409 rib, met->
p[ip], rib_crit));
12410 if (met->
pbl[ix][iy] > pbl_bot)
12411 met->
pbl[ix][iy] = (float) pbl_bot;
12426 const double dtheta = 2.0, zmin = 0.1;
12429#pragma omp parallel for default(shared) collapse(2)
12430 for (
int ix = 0; ix < met->
nx; ix++)
12431 for (
int iy = 0; iy < met->
ny; iy++) {
12434 const double theta0 =
THETA(met->
ps[ix][iy], met->
ts[ix][iy]);
12438 for (ip = met->
np - 2; ip > 0; ip--)
12439 if (met->
p[ip] >= 300.)
12440 if (met->
p[ip] > met->
ps[ix][iy]
12441 ||
THETA(met->
p[ip], met->
t[ix][iy][ip]) <= theta0 + dtheta)
12446 = (float) (
LIN(
THETA(met->
p[ip + 1], met->
t[ix][iy][ip + 1]),
12448 THETA(met->
p[ip], met->
t[ix][iy][ip]),
12449 met->
p[ip], theta0 + dtheta));
12452 double pbl_min = met->
ps[ix][iy] * exp(-zmin /
H0);
12453 if (met->
pbl[ix][iy] > pbl_min || met->
p[ip] > met->
ps[ix][iy])
12454 met->
pbl[ix][iy] = (float) pbl_min;
12459#pragma omp parallel for default(shared) collapse(2)
12460 for (
int ix = 0; ix < met->
nx; ix++)
12461 for (
int iy = 0; iy < met->
ny; iy++) {
12465 met->
pbl[ix][iy] =
MIN(met->
pbl[ix][iy], (
float) pbl_min);
12469 met->
pbl[ix][iy] =
MAX(met->
pbl[ix][iy], (
float) pbl_max);
12480 LOG(2,
"Apply periodic boundary conditions...");
12483 if (!(fabs(met->
lon[met->
nx - 1] - met->
lon[0]
12484 + met->
lon[1] - met->
lon[0] - 360) < 0.01))
12488 if ((++met->
nx) >=
EX)
12489 ERRMSG(
"Cannot create periodic boundary conditions!");
12492 met->
lon[met->
nx - 1] = met->
lon[met->
nx - 2] + met->
lon[1] - met->
lon[0];
12495#pragma omp parallel for default(shared)
12496 for (
int iy = 0; iy < met->
ny; iy++) {
12497 met->
ps[met->
nx - 1][iy] = met->
ps[0][iy];
12498 met->
zs[met->
nx - 1][iy] = met->
zs[0][iy];
12499 met->
ts[met->
nx - 1][iy] = met->
ts[0][iy];
12500 met->
us[met->
nx - 1][iy] = met->
us[0][iy];
12501 met->
vs[met->
nx - 1][iy] = met->
vs[0][iy];
12502 met->
ess[met->
nx - 1][iy] = met->
ess[0][iy];
12503 met->
nss[met->
nx - 1][iy] = met->
nss[0][iy];
12504 met->
shf[met->
nx - 1][iy] = met->
shf[0][iy];
12505 met->
lsm[met->
nx - 1][iy] = met->
lsm[0][iy];
12506 met->
sst[met->
nx - 1][iy] = met->
sst[0][iy];
12507 met->
pbl[met->
nx - 1][iy] = met->
pbl[0][iy];
12508 met->
cape[met->
nx - 1][iy] = met->
cape[0][iy];
12509 met->
cin[met->
nx - 1][iy] = met->
cin[0][iy];
12510 for (
int ip = 0; ip < met->
np; ip++) {
12511 met->
t[met->
nx - 1][iy][ip] = met->
t[0][iy][ip];
12512 met->
u[met->
nx - 1][iy][ip] = met->
u[0][iy][ip];
12513 met->
v[met->
nx - 1][iy][ip] = met->
v[0][iy][ip];
12514 met->
w[met->
nx - 1][iy][ip] = met->
w[0][iy][ip];
12515 met->
h2o[met->
nx - 1][iy][ip] = met->
h2o[0][iy][ip];
12516 met->
o3[met->
nx - 1][iy][ip] = met->
o3[0][iy][ip];
12517 met->
lwc[met->
nx - 1][iy][ip] = met->
lwc[0][iy][ip];
12518 met->
rwc[met->
nx - 1][iy][ip] = met->
rwc[0][iy][ip];
12519 met->
iwc[met->
nx - 1][iy][ip] = met->
iwc[0][iy][ip];
12520 met->
swc[met->
nx - 1][iy][ip] = met->
swc[0][iy][ip];
12521 met->
cc[met->
nx - 1][iy][ip] = met->
cc[0][iy][ip];
12523 for (
int ip = 0; ip < met->
npl; ip++) {
12524 met->
ul[met->
nx - 1][iy][ip] = met->
ul[0][iy][ip];
12525 met->
vl[met->
nx - 1][iy][ip] = met->
vl[0][iy][ip];
12526 met->
wl[met->
nx - 1][iy][ip] = met->
wl[0][iy][ip];
12527 met->
pl[met->
nx - 1][iy][ip] = met->
pl[0][iy][ip];
12528 met->
zetal[met->
nx - 1][iy][ip] = met->
zetal[0][iy][ip];
12541 LOG(2,
"Apply fix for polar winds...");
12547 if (fabs(met->
lat[0]) < 89.999 || fabs(met->
lat[met->
ny - 1]) < 89.999)
12551 for (
int ihem = 0; ihem < 2; ihem++) {
12554 int i89 = 1, i90 = 0, sign = 1;
12559 if (met->
lat[i90] < 0)
12563 double clon[
EX], slon[
EX];
12564#pragma omp parallel for default(shared)
12565 for (
int ix = 0; ix < met->
nx; ix++) {
12566 clon[ix] = cos(sign *
DEG2RAD(met->
lon[ix]));
12567 slon[ix] = sin(sign *
DEG2RAD(met->
lon[ix]));
12571#pragma omp parallel for default(shared)
12572 for (
int ip = 0; ip < met->
np; ip++) {
12575 double vel89x = 0, vel89y = 0;
12576 for (
int ix = 0; ix < met->
nx; ix++) {
12578 (met->
u[ix][i89][ip] * clon[ix] -
12579 met->
v[ix][i89][ip] * slon[ix]) / met->
nx;
12581 (met->
u[ix][i89][ip] * slon[ix] +
12582 met->
v[ix][i89][ip] * clon[ix]) / met->
nx;
12586 for (
int ix = 0; ix < met->
nx; ix++) {
12587 met->
u[ix][i90][ip]
12588 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
12589 met->
v[ix][i90][ip]
12590 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
12605 LOG(2,
"Calculate potential vorticity...");
12608#pragma omp parallel for default(shared)
12609 for (
int ip = 0; ip < met->
np; ip++)
12610 pows[ip] = pow(1000. / met->
p[ip],
KAPPA);
12613#pragma omp parallel for default(shared)
12614 for (
int ix = 0; ix < met->
nx; ix++) {
12617 const int ix0 =
MAX(ix - 1, 0);
12618 const int ix1 =
MIN(ix + 1, met->
nx - 1);
12621 for (
int iy = 0; iy < met->
ny; iy++) {
12624 const int iy0 =
MAX(iy - 1, 0);
12625 const int iy1 =
MIN(iy + 1, met->
ny - 1);
12628 const double latr = 0.5 * (met->
lat[iy1] + met->
lat[iy0]);
12629 double dx, dy, c0, c1, cr, vort;
12633 dx = 1000. *
DEG2DX(met->
lon[ix1] - met->
lon[ix0], latr);
12640 dx = met->
lon[ix1] - met->
lon[ix0];
12641 dy = met->
lat[iy1] - met->
lat[iy0];
12651 for (
int ip = 0; ip < met->
np; ip++) {
12655 = (met->
t[ix1][iy][ip] - met->
t[ix0][iy][ip]) * pows[ip] / dx;
12656 const double dvdx = (met->
v[ix1][iy][ip] - met->
v[ix0][iy][ip]) / dx;
12660 = (met->
t[ix][iy1][ip] - met->
t[ix][iy0][ip]) * pows[ip] / dy;
12662 = (met->
u[ix][iy1][ip] * c1 - met->
u[ix][iy0][ip] * c0) / dy;
12665 const int ip0 =
MAX(ip - 1, 0);
12666 const int ip1 =
MIN(ip + 1, met->
np - 1);
12669 double dtdp, dudp, dvdp;
12670 const double dp0 = 100. * (met->
p[ip] - met->
p[ip0]);
12671 const double dp1 = 100. * (met->
p[ip1] - met->
p[ip]);
12672 if (ip != ip0 && ip != ip1) {
12673 double denom = dp0 * dp1 * (dp0 + dp1);
12674 dtdp = (dp0 * dp0 * met->
t[ix][iy][ip1] * pows[ip1]
12675 - dp1 * dp1 * met->
t[ix][iy][ip0] * pows[ip0]
12676 + (dp1 * dp1 - dp0 * dp0) * met->
t[ix][iy][ip] * pows[ip])
12678 dudp = (dp0 * dp0 * met->
u[ix][iy][ip1]
12679 - dp1 * dp1 * met->
u[ix][iy][ip0]
12680 + (dp1 * dp1 - dp0 * dp0) * met->
u[ix][iy][ip])
12682 dvdp = (dp0 * dp0 * met->
v[ix][iy][ip1]
12683 - dp1 * dp1 * met->
v[ix][iy][ip0]
12684 + (dp1 * dp1 - dp0 * dp0) * met->
v[ix][iy][ip])
12687 const double denom = dp0 + dp1;
12689 (met->
t[ix][iy][ip1] * pows[ip1] -
12690 met->
t[ix][iy][ip0] * pows[ip0]) / denom;
12691 dudp = (met->
u[ix][iy][ip1] - met->
u[ix][iy][ip0]) / denom;
12692 dvdp = (met->
v[ix][iy][ip1] - met->
v[ix][iy][ip0]) / denom;
12696 met->
pv[ix][iy][ip] = (float)
12698 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
12704#pragma omp parallel for default(shared)
12705 for (
int ix = 0; ix < met->
nx; ix++)
12706 for (
int ip = 0; ip < met->
np; ip++) {
12708 = met->
pv[ix][1][ip]
12709 = met->
pv[ix][2][ip];
12710 met->
pv[ix][met->
ny - 1][ip]
12711 = met->
pv[ix][met->
ny - 2][ip]
12712 = met->
pv[ix][met->
ny - 3][ip];
12723 LOG(2,
"Calculate total column ozone...");
12726#pragma omp parallel for default(shared) collapse(2)
12727 for (
int ix = 0; ix < met->
nx; ix++)
12728 for (
int iy = 0; iy < met->
ny; iy++) {
12732 for (
int ip = 1; ip < met->
np; ip++)
12733 if (met->
p[ip - 1] <= met->
ps[ix][iy]) {
12735 0.5 * (met->
o3[ix][iy][ip - 1] + met->
o3[ix][iy][ip]);
12736 const double dp = met->
p[ip - 1] - met->
p[ip];
12737 cd += vmr *
MO3 /
MA * dp * 1e2 /
G0;
12760 LOG(2,
"Downsampling of meteo data...");
12766 help->
nx = met->
nx;
12767 help->
ny = met->
ny;
12768 help->
np = met->
np;
12769 memcpy(help->
lon, met->
lon,
sizeof(met->
lon));
12770 memcpy(help->
lat, met->
lat,
sizeof(met->
lat));
12771 memcpy(help->
p, met->
p,
sizeof(met->
p));
12774 for (
int ix = 0; ix < met->
nx; ix += ctl->
met_dx) {
12775 for (
int iy = 0; iy < met->
ny; iy += ctl->
met_dy) {
12776 for (
int ip = 0; ip < met->
np; ip += ctl->
met_dp) {
12777 help->
ps[ix][iy] = 0;
12778 help->
zs[ix][iy] = 0;
12779 help->
ts[ix][iy] = 0;
12780 help->
us[ix][iy] = 0;
12781 help->
vs[ix][iy] = 0;
12782 help->
ess[ix][iy] = 0;
12783 help->
nss[ix][iy] = 0;
12784 help->
shf[ix][iy] = 0;
12785 help->
lsm[ix][iy] = 0;
12786 help->
sst[ix][iy] = 0;
12787 help->
pbl[ix][iy] = 0;
12788 help->
cape[ix][iy] = 0;
12789 help->
cin[ix][iy] = 0;
12790 help->
t[ix][iy][ip] = 0;
12791 help->
u[ix][iy][ip] = 0;
12792 help->
v[ix][iy][ip] = 0;
12793 help->
w[ix][iy][ip] = 0;
12794 help->
h2o[ix][iy][ip] = 0;
12795 help->
o3[ix][iy][ip] = 0;
12796 help->
lwc[ix][iy][ip] = 0;
12797 help->
rwc[ix][iy][ip] = 0;
12798 help->
iwc[ix][iy][ip] = 0;
12799 help->
swc[ix][iy][ip] = 0;
12800 help->
cc[ix][iy][ip] = 0;
12802 for (
int ix2 = ix - ctl->
met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
12807 else if (ix3 >= met->
nx)
12810 for (
int iy2 =
MAX(iy - ctl->
met_sy + 1, 0);
12811 iy2 <=
MIN(iy + ctl->
met_sy - 1, met->
ny - 1); iy2++)
12812 for (
int ip2 =
MAX(ip - ctl->
met_sp + 1, 0);
12813 ip2 <=
MIN(ip + ctl->
met_sp - 1, met->
np - 1); ip2++) {
12815 (1.0f - (float) abs(ix - ix2) / (float) ctl->
met_sx)
12816 * (1.0f - (float) abs(iy - iy2) / (float) ctl->
met_sy)
12817 * (1.0f - (float) abs(ip - ip2) / (float) ctl->
met_sp);
12818 help->
ps[ix][iy] += w * met->
ps[ix3][iy2];
12819 help->
zs[ix][iy] += w * met->
zs[ix3][iy2];
12820 help->
ts[ix][iy] += w * met->
ts[ix3][iy2];
12821 help->
us[ix][iy] += w * met->
us[ix3][iy2];
12822 help->
vs[ix][iy] += w * met->
vs[ix3][iy2];
12823 help->
ess[ix][iy] += w * met->
ess[ix3][iy2];
12824 help->
nss[ix][iy] += w * met->
nss[ix3][iy2];
12825 help->
shf[ix][iy] += w * met->
shf[ix3][iy2];
12826 help->
lsm[ix][iy] += w * met->
lsm[ix3][iy2];
12827 help->
sst[ix][iy] += w * met->
sst[ix3][iy2];
12828 help->
pbl[ix][iy] += w * met->
pbl[ix3][iy2];
12829 help->
cape[ix][iy] += w * met->
cape[ix3][iy2];
12830 help->
cin[ix][iy] += w * met->
cin[ix3][iy2];
12831 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip2];
12832 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip2];
12833 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip2];
12834 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip2];
12835 help->
h2o[ix][iy][ip] += w * met->
h2o[ix3][iy2][ip2];
12836 help->
o3[ix][iy][ip] += w * met->
o3[ix3][iy2][ip2];
12837 help->
lwc[ix][iy][ip] += w * met->
lwc[ix3][iy2][ip2];
12838 help->
rwc[ix][iy][ip] += w * met->
rwc[ix3][iy2][ip2];
12839 help->
iwc[ix][iy][ip] += w * met->
iwc[ix3][iy2][ip2];
12840 help->
swc[ix][iy][ip] += w * met->
swc[ix3][iy2][ip2];
12841 help->
cc[ix][iy][ip] += w * met->
cc[ix3][iy2][ip2];
12845 help->
ps[ix][iy] /= wsum;
12846 help->
zs[ix][iy] /= wsum;
12847 help->
ts[ix][iy] /= wsum;
12848 help->
us[ix][iy] /= wsum;
12849 help->
vs[ix][iy] /= wsum;
12850 help->
ess[ix][iy] /= wsum;
12851 help->
nss[ix][iy] /= wsum;
12852 help->
shf[ix][iy] /= wsum;
12853 help->
lsm[ix][iy] /= wsum;
12854 help->
sst[ix][iy] /= wsum;
12855 help->
pbl[ix][iy] /= wsum;
12856 help->
cape[ix][iy] /= wsum;
12857 help->
cin[ix][iy] /= wsum;
12858 help->
t[ix][iy][ip] /= wsum;
12859 help->
u[ix][iy][ip] /= wsum;
12860 help->
v[ix][iy][ip] /= wsum;
12861 help->
w[ix][iy][ip] /= wsum;
12862 help->
h2o[ix][iy][ip] /= wsum;
12863 help->
o3[ix][iy][ip] /= wsum;
12864 help->
lwc[ix][iy][ip] /= wsum;
12865 help->
rwc[ix][iy][ip] /= wsum;
12866 help->
iwc[ix][iy][ip] /= wsum;
12867 help->
swc[ix][iy][ip] /= wsum;
12868 help->
cc[ix][iy][ip] /= wsum;
12875 for (
int ix = 0; ix < help->
nx; ix += ctl->
met_dx) {
12876 met->
lon[met->
nx] = help->
lon[ix];
12878 for (
int iy = 0; iy < help->
ny; iy += ctl->
met_dy) {
12879 met->
lat[met->
ny] = help->
lat[iy];
12880 met->
ps[met->
nx][met->
ny] = help->
ps[ix][iy];
12881 met->
zs[met->
nx][met->
ny] = help->
zs[ix][iy];
12882 met->
ts[met->
nx][met->
ny] = help->
ts[ix][iy];
12883 met->
us[met->
nx][met->
ny] = help->
us[ix][iy];
12884 met->
vs[met->
nx][met->
ny] = help->
vs[ix][iy];
12885 met->
ess[met->
nx][met->
ny] = help->
ess[ix][iy];
12886 met->
nss[met->
nx][met->
ny] = help->
nss[ix][iy];
12887 met->
shf[met->
nx][met->
ny] = help->
shf[ix][iy];
12888 met->
lsm[met->
nx][met->
ny] = help->
lsm[ix][iy];
12889 met->
sst[met->
nx][met->
ny] = help->
sst[ix][iy];
12890 met->
pbl[met->
nx][met->
ny] = help->
pbl[ix][iy];
12892 met->
cin[met->
nx][met->
ny] = help->
cin[ix][iy];
12894 for (
int ip = 0; ip < help->
np; ip += ctl->
met_dp) {
12895 met->
p[met->
np] = help->
p[ip];
12896 met->
t[met->
nx][met->
ny][met->
np] = help->
t[ix][iy][ip];
12897 met->
u[met->
nx][met->
ny][met->
np] = help->
u[ix][iy][ip];
12898 met->
v[met->
nx][met->
ny][met->
np] = help->
v[ix][iy][ip];
12899 met->
w[met->
nx][met->
ny][met->
np] = help->
w[ix][iy][ip];
12900 met->
h2o[met->
nx][met->
ny][met->
np] = help->
h2o[ix][iy][ip];
12901 met->
o3[met->
nx][met->
ny][met->
np] = help->
o3[ix][iy][ip];
12902 met->
lwc[met->
nx][met->
ny][met->
np] = help->
lwc[ix][iy][ip];
12903 met->
rwc[met->
nx][met->
ny][met->
np] = help->
rwc[ix][iy][ip];
12904 met->
iwc[met->
nx][met->
ny][met->
np] = help->
iwc[ix][iy][ip];
12905 met->
swc[met->
nx][met->
ny][met->
np] = help->
swc[ix][iy][ip];
12906 met->
cc[met->
nx][met->
ny][met->
np] = help->
cc[ix][iy][ip];
12925 double p2[200], pv[
EP], pv2[200], t[
EP], t2[200], th[
EP],
12926 th2[200], z[
EP], z2[200];
12930 LOG(2,
"Calculate tropopause...");
12933#pragma omp parallel for default(shared)
12934 for (
int iz = 0; iz < met->
np; iz++)
12935 z[iz] =
Z(met->
p[iz]);
12936#pragma omp parallel for default(shared)
12937 for (
int iz = 0; iz <= 190; iz++) {
12938 z2[iz] = 4.5 + 0.1 * iz;
12939 p2[iz] =
P(z2[iz]);
12944#pragma omp parallel for default(shared) collapse(2)
12945 for (
int ix = 0; ix < met->
nx; ix++)
12946 for (
int iy = 0; iy < met->
ny; iy++)
12947 met->
pt[ix][iy] = NAN;
12952 ERRMSG(
"Only lat/lon grid supported");
12953#pragma omp parallel for default(shared) collapse(2)
12954 for (
int ix = 0; ix < met->
nx; ix++)
12955 for (
int iy = 0; iy < met->
ny; iy++)
12963#pragma omp parallel for default(shared) private(t,t2) collapse(2)
12964 for (
int ix = 0; ix < met->
nx; ix++)
12965 for (
int iy = 0; iy < met->
ny; iy++) {
12968 for (
int iz = 0; iz < met->
np; iz++)
12969 t[iz] = met->
t[ix][iy][iz];
12973 int iz = (int) gsl_stats_min_index(t2, 1, 171);
12974 if (iz > 0 && iz < 170)
12975 met->
pt[ix][iy] = (float) p2[iz];
12977 met->
pt[ix][iy] = NAN;
12985#pragma omp parallel for default(shared) private(t,t2) collapse(2)
12986 for (
int ix = 0; ix < met->
nx; ix++)
12987 for (
int iy = 0; iy < met->
ny; iy++) {
12991 for (iz = 0; iz < met->
np; iz++)
12992 t[iz] = met->
t[ix][iy][iz];
12996 met->
pt[ix][iy] = NAN;
12997 for (iz = 0; iz <= 170; iz++) {
12999 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
13000 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
13005 if (iz > 0 && iz < 170)
13006 met->
pt[ix][iy] = (float) p2[iz];
13012 if (ctl->
met_tropo == 4 && isfinite(met->
pt[ix][iy])) {
13013 met->
pt[ix][iy] = NAN;
13014 for (; iz <= 170; iz++) {
13016 for (
int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
13017 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
13024 for (; iz <= 170; iz++) {
13026 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
13027 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
13032 if (iz > 0 && iz < 170)
13033 met->
pt[ix][iy] = (float) p2[iz];
13045#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
13046 for (
int ix = 0; ix < met->
nx; ix++)
13047 for (
int iy = 0; iy < met->
ny; iy++) {
13050 for (
int iz = 0; iz < met->
np; iz++)
13051 pv[iz] = met->
pv[ix][iy][iz];
13055 for (
int iz = 0; iz < met->
np; iz++)
13056 th[iz] =
THETA(met->
p[iz], met->
t[ix][iy][iz]);
13060 met->
pt[ix][iy] = NAN;
13061 for (
int iz = 0; iz <= 170; iz++)
13064 if (iz > 0 && iz < 170)
13065 met->
pt[ix][iy] = (float) p2[iz];
13072 ERRMSG(
"Cannot calculate tropopause!");
13075#pragma omp parallel for default(shared) collapse(2)
13076 for (
int ix = 0; ix < met->
nx; ix++)
13077 for (
int iy = 0; iy < met->
ny; iy++) {
13078 double h2ot, tt, zt;
13081 met->
lat[iy], &tt, ci, cw, 1);
13083 met->
lat[iy], &zt, ci, cw, 0);
13085 met->
lat[iy], &h2ot, ci, cw, 0);
13086 met->
tt[ix][iy] = (float) tt;
13087 met->
zt[ix][iy] = (float) zt;
13088 met->
h2ot[ix][iy] = (float) h2ot;
13095 const char *filename,
13105 LOG(1,
"Read observation data: %s", filename);
13109 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
13111 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
13113 ERRMSG(
"Set OBS_TYPE to 0 or 1!");
13116 for (
int i = 1; i < *nobs; i++)
13117 if (rt[i] < rt[i - 1])
13118 ERRMSG(
"Time must be ascending!");
13123 LOG(2,
"Number of observations: %d", *nobs);
13124 gsl_stats_minmax(&mini, &maxi, rt, 1, (
size_t) n);
13125 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
13126 gsl_stats_minmax(&mini, &maxi, rz, 1, (
size_t) n);
13127 LOG(2,
"Altitude range: %g ... %g km", mini, maxi);
13128 gsl_stats_minmax(&mini, &maxi, rlon, 1, (
size_t) n);
13129 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
13130 gsl_stats_minmax(&mini, &maxi, rlat, 1, (
size_t) n);
13131 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
13132 gsl_stats_minmax(&mini, &maxi, robs, 1, (
size_t) n);
13133 LOG(2,
"Observation range: %g ... %g", mini, maxi);
13139 const char *filename,
13149 if (!(in = fopen(filename,
"r")))
13150 ERRMSG(
"Cannot open file!");
13154 while (fgets(line,
LEN, in))
13155 if (sscanf(line,
"%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
13156 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
13157 if ((++(*nobs)) >=
NOBS)
13158 ERRMSG(
"Too many observations!");
13167 const char *filename,
13178 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
13179 ERRMSG(
"Cannot open file!");
13190 NC(nc_close(ncid));
13196 const char *filename,
13199 const char *varname,
13201 const char *defvalue,
13206 char fullname1[
LEN], fullname2[
LEN], rval[
LEN];
13208 int contain = 0, i;
13211 if (filename[strlen(filename) - 1] !=
'-')
13212 if (!(in = fopen(filename,
"r")))
13213 ERRMSG(
"Cannot open file!");
13217 sprintf(fullname1,
"%s[%d]", varname, arridx);
13218 sprintf(fullname2,
"%s[*]", varname);
13220 sprintf(fullname1,
"%s", varname);
13221 sprintf(fullname2,
"%s", varname);
13226 char dummy[
LEN], line[
LEN], rvarname[
LEN];
13227 while (fgets(line,
LEN, in)) {
13228 if (sscanf(line,
"%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
13229 if (strcasecmp(rvarname, fullname1) == 0 ||
13230 strcasecmp(rvarname, fullname2) == 0) {
13236 for (i = 1; i < argc - 1; i++)
13237 if (strcasecmp(argv[i], fullname1) == 0 ||
13238 strcasecmp(argv[i], fullname2) == 0) {
13239 sprintf(rval,
"%s", argv[i + 1]);
13250 if (strlen(defvalue) > 0)
13251 sprintf(rval,
"%s", defvalue);
13253 ERRMSG(
"Missing variable %s!\n", fullname1);
13257 LOG(1,
"%s = %s", fullname1, rval);
13261 sprintf(value,
"%s", rval);
13271 const double rhop) {
13274 const double rp_help = rp * 1e-6;
13277 const double rho =
RHO(p, T);
13280 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
13286 const double lambda = 2. * eta / (rho * v);
13289 const double K = lambda / rp_help;
13292 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
13295 return 2. *
SQR(rp_help) * (rhop - rho) *
G0 / (9. * eta) * G;
13307 const int method) {
13313 gsl_interp_accel *acc = gsl_interp_accel_alloc();
13314 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (
size_t) n);
13317 gsl_spline_init(s, x, y, (
size_t) n);
13318 for (
int i = 0; i < n2; i++)
13321 else if (x2[i] >= x[n - 1])
13324 y2[i] = gsl_spline_eval(s, x2[i], acc);
13327 gsl_spline_free(s);
13328 gsl_interp_accel_free(acc);
13333 for (
int i = 0; i < n2; i++)
13336 else if (x2[i] >= x[n - 1])
13340 y2[i] =
LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
13354 float mean = 0, var = 0;
13356 for (
int i = 0; i < n; ++i) {
13358 var +=
SQR(data[i]);
13361 var = var / (float) n -
SQR(mean / (
float) n);
13363 return (var > 0 ? sqrtf(var) : 0);
13375 const double remain,
13387 t1.tm_year = year - 1900;
13388 t1.tm_mon = mon - 1;
13394 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
13402 const int output) {
13409 static int iname = -1, igroup = -1, nname, ngroup, ct_name[
NTIMER];
13412 t1 = omp_get_wtime();
13417 rt_name[iname] += dt;
13418 rt_min[iname] = (ct_name[iname] <= 0 ? dt :
MIN(rt_min[iname], dt));
13419 rt_max[iname] = (ct_name[iname] <= 0 ? dt :
MAX(rt_max[iname], dt));
13423 rt_group[igroup] += t1 - t0;
13427 for (
int i = 0; i < nname; i++)
13428 LOG(1,
"TIMER_%s = %.3f s (min= %g s, mean= %g s,"
13429 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
13430 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
13431 for (
int i = 0; i < ngroup; i++)
13432 LOG(1,
"TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
13433 double total = 0.0;
13434 for (
int i = 0; i < nname; i++)
13435 total += rt_name[i];
13436 LOG(1,
"TIMER_TOTAL = %.3f s", total);
13440 for (iname = 0; iname < nname; iname++)
13441 if (strcasecmp(name, names[iname]) == 0)
13443 for (igroup = 0; igroup < ngroup; igroup++)
13444 if (strcasecmp(group, groups[igroup]) == 0)
13448 if (iname >= nname) {
13449 sprintf(names[iname],
"%s", name);
13450 if ((++nname) >=
NTIMER)
13451 ERRMSG(
"Too many timers!");
13455 if (igroup >= ngroup) {
13456 sprintf(groups[igroup],
"%s", group);
13457 if ((++ngroup) >=
NTIMER)
13458 ERRMSG(
"Too many groups!");
13468 const char *filename,
13470 const int with_seconds) {
13477 int len = (int) strlen(filename);
13478 sprintf(tstr,
"%.4s", &filename[len - offset]);
13479 int year = atoi(tstr);
13480 sprintf(tstr,
"%.2s", &filename[len - offset + 5]);
13481 int mon = atoi(tstr);
13482 sprintf(tstr,
"%.2s", &filename[len - offset + 8]);
13483 int day = atoi(tstr);
13484 sprintf(tstr,
"%.2s", &filename[len - offset + 11]);
13485 int hour = atoi(tstr);
13486 sprintf(tstr,
"%.2s", &filename[len - offset + 14]);
13487 int min = atoi(tstr);
13490 if (with_seconds) {
13491 sprintf(tstr,
"%.2s", &filename[len - offset + 17]);
13496 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
13497 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
13498 ERRMSG(
"Cannot read time from filename!");
13501 time2jsec(year, mon, day, hour, min, sec, 0.0, &t);
13521 const double p1 = pt * 0.866877899;
13522 const double p0 = pt / 0.866877899;
13525 if (atm->
p[ip] > p0)
13527 else if (atm->
p[ip] < p1)
13530 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
13536 const char *filename,
13544 const double t0 = t - 0.5 * ctl->
dt_mod;
13545 const double t1 = t + 0.5 * ctl->
dt_mod;
13551 if (!(out = popen(
"gnuplot",
"w")))
13552 ERRMSG(
"Cannot create pipe to gnuplot!");
13555 fprintf(out,
"set out \"%s.png\"\n", filename);
13559 int year, mon, day, hour, min, sec;
13560 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
13561 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
13562 year, mon, day, hour, min);
13567 ERRMSG(
"Cannot open file!");
13569 while (fgets(line,
LEN, in))
13570 fprintf(out,
"%s", line);
13577 if (!(out = fopen(filename,
"w")))
13578 ERRMSG(
"Cannot create file!");
13585 "# $1 = time [s]\n"
13586 "# $2 = altitude [km]\n"
13587 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
13590 "# $1 = time [s]\n"
13591 "# $2 = altitude [km]\n" "# $3 = x [m]\n" "# $4 = y [m]\n");
13594 for (
int iq = 0; iq < ctl->
nq; iq++)
13595 fprintf(out,
"# $%i = %s [%s]\n", iq + 5, ctl->
qnt_name[iq],
13597 fprintf(out,
"\n");
13600 for (
int ip = 0; ip < atm->
np; ip += ctl->
atm_stride) {
13608 fprintf(out,
"%.2f %g %g %g",
13609 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]
13612 fprintf(out,
"%.2f %g %.2f %.2f",
13613 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]
13617 for (
int iq = 0; iq < ctl->
nq; iq++) {
13622 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
13624 fprintf(out,
"\n");
13634 const char *filename,
13636 const atm_t *atm) {
13641 if (!(out = fopen(filename,
"w")))
13642 ERRMSG(
"Cannot create file!");
13666 for (
int iq = 0; iq < ctl->
nq; iq++)
13684 const char *filename,
13686 const atm_t *atm) {
13689 ERRMSG(
"CLaMS atmospheric files support only lat/lon grids");
13691 int tid, pid, ncid, varid;
13692 size_t start[2], count[2];
13695 NC(nc_create(filename, NC_NETCDF4, &ncid));
13698 NC(nc_def_dim(ncid,
"time", 1, &tid));
13699 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
13702 int dim_ids[2] = { tid, pid };
13703 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
13704 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
13705 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
13707 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
13709 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
13712 for (
int iq = 0; iq < ctl->
nq; iq++)
13722 NC(nc_enddef(ncid));
13730 for (
int iq = 0; iq < ctl->
nq; iq++)
13734 NC(nc_close(ncid));
13740 const char *dirname,
13746 ERRMSG(
"CLaMS atmospheric files support only lat/lon grids");
13749 static size_t out_cnt = 0;
13751 double r, r_start, r_stop;
13752 int year, mon, day, hour, min, sec;
13753 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
13754 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
13755 char filename_out[2 *
LEN] =
"traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
13757 int ncid, varid, tid, pid, cid;
13765 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
13767 &min_start, &sec_start, &r_start);
13769 &min_stop, &sec_stop, &r_stop);
13771 sprintf(filename_out,
13772 "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc", dirname,
13773 year_start % 100, mon_start, day_start, hour_start,
13774 year_stop % 100, mon_stop, day_stop, hour_stop);
13775 LOG(1,
"Write traj file: %s", filename_out);
13778 start[0] = out_cnt;
13781 count[1] = (size_t) atm->
np;
13784 if (out_cnt == 0) {
13787 NC(nc_create(filename_out, NC_NETCDF4, &ncid));
13790 NC(nc_def_dim(ncid,
"time", NC_UNLIMITED, &tid));
13791 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
13792 NC(nc_def_dim(ncid,
"TMDT", 7, &cid));
13797 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
13798 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
13799 NC_DEF_VAR(
"LAT", NC_DOUBLE, 2, dim_ids,
"Latitude",
"deg",
13801 NC_DEF_VAR(
"LON", NC_DOUBLE, 2, dim_ids,
"Longitude",
"deg",
13803 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 2, dim_ids,
"Pressure",
"hPa",
13805 NC_DEF_VAR(
"ZETA", NC_DOUBLE, 2, dim_ids,
"Zeta",
"K",
13807 for (
int iq = 0; iq < ctl->
nq; iq++)
13817 NC(nc_enddef(ncid));
13818 NC(nc_close(ncid));
13825 NC(nc_open(filename_out, NC_WRITE, &ncid));
13837 for (
int iq = 0; iq < ctl->
nq; iq++)
13841 NC(nc_close(ncid));
13844 if ((year == year_stop) && (mon == mon_stop)
13845 && (day == day_stop) && (hour == hour_stop)) {
13848 char filename_init[2 *
LEN] =
"./init_fix_YYYYMMDDHH.nc";
13849 sprintf(filename_init,
"%s/init_fix_%02d%02d%02d%02d.nc",
13850 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
13851 LOG(1,
"Write init file: %s", filename_init);
13854 NC(nc_create(filename_init, NC_NETCDF4, &ncid));
13857 NC(nc_def_dim(ncid,
"time", 1, &tid));
13858 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
13863 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
13864 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
13865 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
13867 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
13869 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
13872 for (
int iq = 0; iq < ctl->
nq; iq++)
13882 NC(nc_enddef(ncid));
13890 for (
int iq = 0; iq < ctl->
nq; iq++)
13894 NC(nc_close(ncid));
13901 const char *filename,
13903 const atm_t *atm) {
13905 int ncid, obsid, varid;
13907 size_t start[2], count[2];
13910 NC(nc_create(filename, NC_NETCDF4, &ncid));
13913 NC(nc_def_dim(ncid,
"obs", (
size_t) atm->
np, &obsid));
13916 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &obsid,
"time",
13917 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
13918 NC_DEF_VAR(
"press", NC_DOUBLE, 1, &obsid,
"pressure",
"hPa",
13920 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &obsid,
"longitude",
"degrees_east",
13922 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &obsid,
"latitude",
"degrees_north",
13924 for (
int iq = 0; iq < ctl->
nq; iq++)
13933 NC(nc_enddef(ncid));
13940 for (
int iq = 0; iq < ctl->
nq; iq++)
13944 NC(nc_close(ncid));
13950 const char *filename,
13961 if (ctl->
qnt_m < 0)
13962 ERRMSG(
"Need quantity mass!");
13963 const int ensemble = (ctl->
nens > 0);
13964 if (ensemble && ctl->
qnt_ens < 0)
13965 ERRMSG(
"Missing ensemble IDs!");
13967 ERRMSG(
"Too many ensembles!");
13971 LOG(1,
"Write mass budget data: %s", filename);
13972 if (!(out = fopen(filename,
"w")))
13973 ERRMSG(
"Cannot create file!");
13975 "# $1 = time [s]\n"
13976 "# $2 = ensemble ID (-999=total)\n"
13977 "# $3 = number of active air parcels [1]\n"
13978 "# $4 = total mass [kg]\n"
13979 "# $5 = mass loss due to OH chemistry [kg]\n"
13980 "# $6 = mass loss due to H2O2 chemistry [kg]\n"
13981 "# $7 = mass loss due to KPP chemistry [kg]\n"
13982 "# $8 = mass loss due to wet deposition [kg]\n"
13983 "# $9 = mass loss due to dry deposition [kg]\n"
13984 "# $10 = mass loss due to exponential decay [kg]\n"
13985 "# $11 = total tracked mass loss [kg]\n"
13986 "# $12 = accounted mass [kg]\n\n");
13991 const int qnt[7] = {
13996 double sum[
NENS + 1][7] = { {0} };
13997 int np[
NENS + 1] = { 0 };
13998 const double t0 = t - 0.5 * ctl->
dt_mod;
13999 const double t1 = t + 0.5 * ctl->
dt_mod;
14002 for (
int ip = 0; ip < atm->
np; ip++) {
14003 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
14007 e = (int) atm->
q[ctl->
qnt_ens][ip];
14008 if (e < 0 || e >= ctl->
nens)
14009 ERRMSG(
"Ensemble ID out of range!");
14013 for (
int iq = 0; iq < nq; iq++)
14014 if (qnt[iq] >= 0) {
14015 sum[e][iq] += atm->
q[qnt[iq]][ip];
14016 sum[
NENS][iq] += atm->
q[qnt[iq]][ip];
14021 for (
int ie = -1; ie < (ensemble ? ctl->
nens : 0); ie++) {
14022 const int e = (ie < 0 ?
NENS : ie);
14024 for (
int iq = 1; iq < nq; iq++)
14026 mloss += sum[e][iq];
14027 fprintf(out,
"%.2f %d %d %g", t, ie < 0 ? -999 : ie, np[e], sum[e][0]);
14028 for (
int iq = 1; iq < nq; iq++)
14029 fprintf(out,
" %g", qnt[iq] >= 0 ? sum[e][iq] : NAN);
14030 fprintf(out,
" %g %g\n", mloss, sum[e][0] + mloss);
14044 const char *filename,
14050 ERRMSG(
"Only lat/lon grid supported");
14054 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
14057 static int *obscount, nobs, nk;
14061 const int ensemble = (ctl->
nens > 0);
14067 if (ctl->
qnt_m < 0)
14068 ERRMSG(
"Need quantity mass!");
14071 ERRMSG(
"Missing ensemble IDs!");
14073 ERRMSG(
"Too many ensembles!");
14080 ALLOC(area,
double,
14086 ALLOC(rlon,
double,
14088 ALLOC(rlat,
double,
14090 ALLOC(robs,
double,
14101 LOG(1,
"Write CSI%s data: %s", ensemble ?
" ensemble" :
"", filename);
14102 if (!(out = fopen(filename,
"w")))
14103 ERRMSG(
"Cannot create file!");
14107 "# $1 = time [s]\n"
14108 "# $2 = ensemble ID\n"
14109 "# $3 = number of hits (cx)\n"
14110 "# $4 = number of misses (cy)\n"
14111 "# $5 = number of false alarms (cz)\n"
14112 "# $6 = number of observations (cx + cy)\n"
14113 "# $7 = number of forecasts (cx + cz)\n"
14114 "# $8 = bias (%%)\n"
14115 "# $9 = POD (%%)\n"
14116 "# $10 = FAR (%%)\n"
14117 "# $11 = CSI (%%)\n"
14118 "# $12 = hits by random chance\n"
14119 "# $13 = ETS (%%)\n"
14120 "# $14 = Pearson R\n"
14121 "# $15 = Spearman R\n"
14122 "# $16 = mean error [kg/m²]\n"
14123 "# $17 = RMSE [kg/m²]\n"
14124 "# $18 = MAE [kg/m²]\n"
14125 "# $19 = log-likelihood\n" "# $20 = number of points\n\n");
14133 for (
int iy = 0; iy < ctl->
csi_ny; iy++) {
14134 const double lat = ctl->
csi_lat0 + dlat * (iy + 0.5);
14135 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.0) * cos(
DEG2RAD(lat));
14140 const double t0 = t - 0.5 * ctl->
dt_mod;
14141 const double t1 = t + 0.5 * ctl->
dt_mod;
14145 ALLOC(modmean,
double,
14146 (ensemble ? ctl->
nens : 1) * grid_size);
14147 ALLOC(obsmean,
double,
14149 ALLOC(obscount,
int,
14151 ALLOC(obsstd,
double,
14155 for (
int i = 0; i < (ensemble ? ctl->
nens : 1); i++)
14156 ct[i] = cx[i] = cy[i] = cz[i] = n[i] = 0;
14159 for (
int i = 0; i < nobs; i++) {
14160 if (rt[i] < t0 || rt[i] >= t1 || !isfinite(robs[i]))
14168 const int ix = (int) ((rlon[i] - ctl->
csi_lon0) / dlon);
14169 const int iy = (int) ((rlat[i] - ctl->
csi_lat0) / dlat);
14170 const int iz = (int) ((rz[i] - ctl->
csi_z0) / dz);
14176 obsmean[idx] += robs[i];
14177 obsstd[idx] +=
SQR(robs[i]);
14182 for (
int ip = 0; ip < atm->
np; ip++) {
14185 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
14189 int ens_id = ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
14190 if (ens_id < 0 || ens_id >= (ensemble ? ctl->
nens : 1))
14191 ERRMSG(
"Ensemble ID out of range!");
14194 const double zpart =
Z(atm->
p[ip]);
14199 || zpart < ctl->csi_z0 || zpart >= ctl->
csi_z1)
14201 const int ix = (int) ((atm->
lon[ip] - ctl->
csi_lon0) / dlon);
14202 const int iy = (int) ((atm->
lat[ip] - ctl->
csi_lat0) / dlat);
14203 const int iz = (int) ((zpart - ctl->
csi_z0) / dz);
14213 for (
int e = 0; e < (ensemble ? ctl->
nens : 1); e++) {
14215 for (
int ix = 0; ix < ctl->
csi_nx; ix++)
14216 for (
int iy = 0; iy < ctl->
csi_ny; iy++)
14217 for (
int iz = 0; iz < ctl->
csi_nz; iz++) {
14222 if (obscount[idx]) {
14223 obsmean[idx] /= obscount[idx];
14225 sqrt(obsstd[idx] / obscount[idx] -
SQR(obsmean[idx]));
14229 const int midx = e * grid_size + idx;
14230 if (modmean[midx] > 0)
14231 modmean[midx] /= (1e6 * area[iy]);
14234 if (obscount[idx]) {
14249 x[n[e]] = modmean[midx];
14250 y[n[e]] = obsmean[idx];
14252 obsstdn[n[e]] = obsstd[idx];
14253 if ((++n[e]) >=
NCSI)
14254 ERRMSG(
"Too many points for statistics!");
14266 static double work[2 *
NCSI], work2[2 *
NCSI];
14267 const int n_obs = cx[e] + cy[e];
14268 const int n_for = cx[e] + cz[e];
14269 const double cx_rd = (ct[e] > 0) ? (1. * n_obs * n_for) / ct[e] : NAN;
14270 const double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
14271 const double pod = (n_obs > 0) ? 100. * cx[e] / n_obs : NAN;
14272 const double far = (n_for > 0) ? 100. * cz[e] / n_for : NAN;
14274 (cx[e] + cy[e] + cz[e] >
14275 0) ? 100. * cx[e] / (cx[e] + cy[e] + cz[e]) : NAN;
14277 (cx[e] + cy[e] + cz[e] - cx_rd >
14278 0) ? 100. * (cx[e] - cx_rd) / (cx[e] + cy[e] + cz[e] - cx_rd) : NAN;
14279 const double rho_p = gsl_stats_correlation(x, 1, y, 1, (
size_t) n[e]);
14280 const double rho_s =
14281 gsl_stats_spearman(x, 1, y, 1, (
size_t) n[e], work);
14282 for (
int i = 0; i < n[e]; i++) {
14283 work[i] = x[i] - y[i];
14284 work2[i] = (obsstdn[i] != 0) ? work[i] / obsstdn[i] : 0;
14286 const double mean = gsl_stats_mean(work, 1, (
size_t) n[e]);
14287 const double rmse =
14288 gsl_stats_sd_with_fixed_mean(work, 1, (
size_t) n[e], 0.0);
14289 const double absdev = gsl_stats_absdev_m(work, 1, (
size_t) n[e], 0.0);
14290 const double loglikelihood =
14291 gsl_stats_tss_m(work2, 1, (
size_t) n[e], 0.0) * -0.5;
14295 "%.2f %d %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n",
14296 t, ensemble ? e : -999, cx[e], cy[e], cz[e], n_obs, n_for, bias,
14297 pod, far, csi, cx_rd, ets, rho_p, rho_s, mean, rmse, absdev,
14298 loglikelihood, n[e]);
14301 for (
int i = 0; i < n[e]; i++)
14302 work[i] = work2[i] = x[i] = y[i] = obsstdn[i] = 0;
14303 ct[e] = cx[e] = cy[e] = cz[e] = n[e] = 0;
14331 const char *filename,
14337 ERRMSG(
"Only lat/lon grid supported");
14344 static int n[
NENS];
14351 ERRMSG(
"Missing ensemble IDs!");
14354 const double t0 = t - 0.5 * ctl->
dt_mod;
14355 const double t1 = t + 0.5 * ctl->
dt_mod;
14358 for (
int i = 0; i <
NENS; i++) {
14359 for (
int iq = 0; iq < ctl->
nq; iq++)
14360 qm[iq][i] = qs[iq][i] = 0;
14361 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
14366 for (
int ip = 0; ip < atm->
np; ip++) {
14369 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
14374 ERRMSG(
"Ensemble ID is out of range!");
14378 for (
int iq = 0; iq < ctl->
nq; iq++) {
14379 qm[iq][ctl->
qnt_ens] += atm->
q[iq][ip];
14390 LOG(1,
"Write ensemble data: %s", filename);
14391 if (!(out = fopen(filename,
"w")))
14392 ERRMSG(
"Cannot create file!");
14396 "# $1 = time [s]\n"
14397 "# $2 = altitude [km]\n"
14398 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
14399 for (
int iq = 0; iq < ctl->
nq; iq++)
14400 fprintf(out,
"# $%d = %s (mean) [%s]\n", 5 + iq,
14402 for (
int iq = 0; iq < ctl->
nq; iq++)
14403 fprintf(out,
"# $%d = %s (sigma) [%s]\n", 5 + ctl->
nq + iq,
14405 fprintf(out,
"# $%d = number of members\n\n", 5 + 2 * ctl->
nq);
14408 for (
int i = 0; i <
NENS; i++)
14410 cart2geo(xm[i], &dummy, &lon, &lat);
14411 fprintf(out,
"%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
14412 for (
int iq = 0; iq < ctl->
nq; iq++) {
14414 fprintf(out, ctl->
qnt_format[iq], qm[iq][i] / n[i]);
14416 for (
int iq = 0; iq < ctl->
nq; iq++) {
14418 double var = qs[iq][i] / n[i] -
SQR(qm[iq][i] / n[i]);
14419 fprintf(out, ctl->
qnt_format[iq], (var > 0 ? sqrt(var) : 0));
14421 fprintf(out,
" %d\n", n[i]);
14431 const char *filename,
14436 double *area, *data, *lat, *lon;
14440 LOG(1,
"Write radioactive deposition data: %s", filename);
14444 ALLOC(area,
double,
14446 ALLOC(data,
double,
14456 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
14457 lon[ix] = ctl->
grid_lon0 + dlon * (ix + 0.5);
14458 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
14459 lat[iy] = ctl->
grid_lat0 + dlat * (iy + 0.5);
14460 area[iy] = 1e6 * dlat * dlon *
SQR(
RE * M_PI / 180.)
14465 const double lambda[4] = {
14471 const double *inventory[4] = {
14474 for (
int iq = 0; iq < 4; iq++) {
14476 ? exp(-lambda[iq] * (t - ctl->
t_start)) : 1.0;
14477 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
14478 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
14480 data[iq * nxy + idx] = inventory[iq][idx] * decay / area[iy];
14490 ERRMSG(
"Radioactive deposition output type unknown!");
14502 const char *filename,
14504 const double *data,
14508 const double *area) {
14511 if (!(out = fopen(filename,
"w")))
14512 ERRMSG(
"Cannot create file!");
14515 "# $1 = time [s]\n"
14516 "# $2 = longitude [deg]\n"
14517 "# $3 = latitude [deg]\n"
14518 "# $4 = area [m^2]\n"
14519 "# $5 = deposited Pb-210 activity [Bq/m^2]\n"
14520 "# $6 = deposited Be-7 activity [Bq/m^2]\n"
14521 "# $7 = deposited Cs-137 activity [Bq/m^2]\n"
14522 "# $8 = deposited I-131 activity [Bq/m^2]\n\n");
14525 for (
int ix = 0; ix < ctl->
grid_nx; ix++) {
14526 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
14528 fprintf(out,
"%.2f %g %g %g %g %g %g %g\n",
14529 t, lon[ix], lat[iy], area[iy],
14530 data[idx], data[nxy + idx],
14531 data[2 * nxy + idx], data[3 * nxy + idx]);
14533 fprintf(out,
"\n");
14542 const char *filename,
14544 const double *data,
14548 const double *area) {
14551 int ncid, dimid[3], varid;
14552 size_t start[2], count[2];
14555 ALLOC(help,
double,
14559 NC(nc_create(filename, NC_NETCDF4, &ncid));
14560 NC(nc_def_dim(ncid,
"time", 1, &dimid[0]));
14561 NC(nc_def_dim(ncid,
"lat", (
size_t) ctl->
grid_ny, &dimid[1]));
14562 NC(nc_def_dim(ncid,
"lon", (
size_t) ctl->
grid_nx, &dimid[2]));
14565 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &dimid[0],
"time",
14566 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
14567 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &dimid[1],
"latitude",
14568 "degrees_north", 0, 0);
14569 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &dimid[2],
"longitude",
14570 "degrees_east", 0, 0);
14571 NC_DEF_VAR(
"area", NC_DOUBLE, 1, &dimid[1],
"surface area",
"m**2", 0, 0);
14572 NC_DEF_VAR(
"depo_pb210", NC_DOUBLE, 3, dimid,
14573 "ground inventory of Pb-210",
"Bq m**-2", ctl->
grid_nc_level, 0);
14575 "ground inventory of Be-7",
"Bq m**-2", ctl->
grid_nc_level, 0);
14576 NC_DEF_VAR(
"depo_cs137", NC_DOUBLE, 3, dimid,
14577 "ground inventory of Cs-137",
"Bq m**-2", ctl->
grid_nc_level, 0);
14578 NC_DEF_VAR(
"depo_i131", NC_DOUBLE, 3, dimid,
14579 "ground inventory of aerosol-bound I-131",
"Bq m**-2",
14581 NC(nc_enddef(ncid));
14590 const char *varname[4] = {
14591 "depo_pb210",
"depo_be7",
"depo_cs137",
"depo_i131"
14593 for (
int iq = 0; iq < 4; iq++) {
14594 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
14595 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
14601 NC(nc_close(ncid));
14608 const char *filename,
14616 ERRMSG(
"Only lat/lon grid supported");
14618 static double kz[
EP], kw[
EP];
14622 double *cd, *mean[
NQ], *sigma[
NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
14624 int *ixs, *iys, *izs, *np;
14630 LOG(1,
"Write grid data: %s", filename);
14643 for (
int iq = 0; iq < ctl->
nq; iq++) {
14644 ALLOC(mean[iq],
double,
14646 ALLOC(sigma[iq],
double,
14649 ALLOC(vmr_impl,
double,
14657 ALLOC(area,
double,
14659 ALLOC(press,
double,
14676#pragma omp parallel
for default(shared)
14677 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
14678 z[iz] = ctl->
grid_z0 + dz * (iz + 0.5);
14679 press[iz] =
P(z[iz]);
14683 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
14684 lon[ix] = ctl->
grid_lon0 + dlon * (ix + 0.5);
14685#pragma omp parallel for default(shared)
14686 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
14687 lat[iy] = ctl->
grid_lat0 + dlat * (iy + 0.5);
14688 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
14692 const double t0 = t - 0.5 * ctl->
dt_mod;
14693 const double t1 = t + 0.5 * ctl->
dt_mod;
14696#pragma omp parallel for default(shared)
14697 for (
int ip = 0; ip < atm->
np; ip++) {
14698 const double zpart =
Z(atm->
p[ip]);
14699 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
14704 || zpart < ctl->grid_z0 || zpart >= ctl->
grid_z1) {
14708 ixs[ip] = (int) ((atm->
lon[ip] - ctl->
grid_lon0) / dlon);
14709 iys[ip] = (int) ((atm->
lat[ip] - ctl->
grid_lat0) / dlat);
14710 izs[ip] = (int) ((zpart - ctl->
grid_z0) / dz);
14717 for (
int ip = 0; ip < atm->
np; ip++)
14718 if (izs[ip] >= 0) {
14723 for (
int iq = 0; iq < ctl->
nq; iq++) {
14724 mean[iq][idx] += kernel * atm->
q[iq][ip];
14725 sigma[iq][idx] +=
SQR(kernel * atm->
q[iq][ip]);
14730#pragma omp parallel for default(shared)
14731 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
14732 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
14733 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
14740 if (ctl->
qnt_m >= 0)
14741 cd[idx] = mean[ctl->
qnt_m][idx] / (1e6 * area[iy]);
14744 vmr_impl[idx] = NAN;
14745 if (ctl->
qnt_m >= 0 && ctl->
molmass > 0 && met0 != NULL
14748 if (mean[ctl->
qnt_m][idx] > 0) {
14754 lon[ix], lat[iy], &temp, ci, cw, 1);
14758 MA / ctl->
molmass * cd[idx] / (
RHO(press[iz], temp) * dz * 1e3);
14764 for (
int iq = 0; iq < ctl->
nq; iq++) {
14765 mean[iq][idx] /= np[idx];
14766 const double var = sigma[iq][idx] / np[idx] -
SQR(mean[iq][idx]);
14767 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
14769 for (
int iq = 0; iq < ctl->
nq; iq++) {
14770 mean[iq][idx] = NAN;
14771 sigma[iq][idx] = NAN;
14778 t, z, lon, lat, area, dz, np);
14783 t, z, lon, lat, area, dz, np);
14787 ERRMSG(
"Grid data format GRID_TYPE unknown!");
14791 for (
int iq = 0; iq < ctl->
nq; iq++) {
14810 const char *filename,
14815 const double *vmr_impl,
14820 const double *area,
14830 if (!(out = popen(
"gnuplot",
"w")))
14831 ERRMSG(
"Cannot create pipe to gnuplot!");
14834 fprintf(out,
"set out \"%s.png\"\n", filename);
14838 int year, mon, day, hour, min, sec;
14839 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
14840 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
14841 year, mon, day, hour, min);
14847 ERRMSG(
"Cannot open file!");
14848 while (fgets(line,
LEN, in))
14849 fprintf(out,
"%s", line);
14856 if (!(out = fopen(filename,
"w")))
14857 ERRMSG(
"Cannot create file!");
14862 "# $1 = time [s]\n"
14863 "# $2 = altitude [km]\n"
14864 "# $3 = longitude [deg]\n"
14865 "# $4 = latitude [deg]\n"
14866 "# $5 = surface area [km^2]\n"
14867 "# $6 = layer depth [km]\n"
14868 "# $7 = column density (implicit) [kg/m^2]\n"
14869 "# $8 = volume mixing ratio (implicit) [ppv]\n"
14870 "# $9 = number of particles [1]\n");
14871 for (
int iq = 0; iq < ctl->
nq; iq++)
14872 fprintf(out,
"# $%i = %s (mean) [%s]\n", 10 + iq, ctl->
qnt_name[iq],
14875 for (
int iq = 0; iq < ctl->
nq; iq++)
14876 fprintf(out,
"# $%i = %s (stddev) [%s]\n", 10 + ctl->
nq + iq,
14878 fprintf(out,
"\n");
14881 for (
int ix = 0; ix < ctl->
grid_nx; ix++) {
14883 fprintf(out,
"\n");
14884 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
14886 fprintf(out,
"\n");
14887 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
14890 fprintf(out,
"%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
14891 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
14892 for (
int iq = 0; iq < ctl->
nq; iq++) {
14894 fprintf(out, ctl->
qnt_format[iq], mean[iq][idx]);
14897 for (
int iq = 0; iq < ctl->
nq; iq++) {
14899 fprintf(out, ctl->
qnt_format[iq], sigma[iq][idx]);
14901 fprintf(out,
"\n");
14914 const char *filename,
14919 const double *vmr_impl,
14924 const double *area,
14928 char longname[2 *
LEN], varname[2 *
LEN];
14932 int *help2, ncid, dimid[10], varid;
14934 size_t start[2], count[2];
14937 ALLOC(help,
double,
14943 NC(nc_create(filename, NC_NETCDF4, &ncid));
14946 NC(nc_def_dim(ncid,
"time", 1, &dimid[0]));
14947 NC(nc_def_dim(ncid,
"z", (
size_t) ctl->
grid_nz, &dimid[1]));
14948 NC(nc_def_dim(ncid,
"lat", (
size_t) ctl->
grid_ny, &dimid[2]));
14949 NC(nc_def_dim(ncid,
"lon", (
size_t) ctl->
grid_nx, &dimid[3]));
14950 NC(nc_def_dim(ncid,
"dz", 1, &dimid[4]));
14953 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &dimid[0],
"time",
14954 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
14955 NC_DEF_VAR(
"z", NC_DOUBLE, 1, &dimid[1],
"altitude",
"km", 0, 0);
14956 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &dimid[2],
"latitude",
"degrees_north", 0,
14958 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &dimid[3],
"longitude",
"degrees_east", 0,
14960 NC_DEF_VAR(
"dz", NC_DOUBLE, 1, &dimid[1],
"layer depth",
"km", 0, 0);
14961 NC_DEF_VAR(
"area", NC_DOUBLE, 1, &dimid[2],
"surface area",
"km**2", 0, 0);
14963 NC_DEF_VAR(
"cd", NC_FLOAT, 4, dimid,
"column density",
"kg m**-2",
14966 "volume mixing ratio (implicit)",
"ppv", ctl->
grid_nc_level, 0);
14967 NC_DEF_VAR(
"np", NC_INT, 4, dimid,
"number of particles",
"1", 0, 0);
14968 for (
int iq = 0; iq < ctl->
nq; iq++) {
14969 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
14970 sprintf(longname,
"%s (mean)", ctl->
qnt_longname[iq]);
14974 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
14975 sprintf(longname,
"%s (stddev)", ctl->
qnt_longname[iq]);
14981 NC(nc_enddef(ncid));
14991 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
14992 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
14993 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
14998 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
14999 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
15000 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
15005 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
15006 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
15007 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
15012 for (
int iq = 0; iq < ctl->
nq; iq++) {
15013 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
15014 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
15015 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
15016 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
15023 for (
int iq = 0; iq < ctl->
nq; iq++) {
15024 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
15025 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
15026 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
15027 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
15034 NC(nc_close(ncid));
15044 const char *filename,
15049 FILE *out, *level_log = NULL;
15050 if (!(out = fopen(filename,
"w")))
15051 ERRMSG(
"Cannot create file!");
15057 ERRMSG(
"Cannot create compression log file!");
15062 "# $1 = compression codec name [-]\n"
15063 "# $2 = variable name [-]\n"
15064 "# $3 = level index [-]\n"
15065 "# $4 = pressure level [hPa]\n"
15066 "# $5 = compression ratio [-]\n"
15067 "# $6 = bits per value [bit/value]\n"
15068 "# $7 = correlation coefficient [-]\n"
15069 "# $8 = mean compression error [-]\n"
15070 "# $9 = standard deviation of compression error [-]\n"
15071 "# $10 = minimum compression error [-]\n"
15072 "# $11 = maximum compression error [-]\n"
15073 "# $12 = mean value of original field [-]\n"
15074 "# $13 = value range of original field [-]\n"
15075 "# $14 = normalized root mean square error [-]\n"
15076 "# $15 = compression time [s]\n"
15077 "# $16 = compression speed [MiB/s]\n"
15078 "# $17 = decompression time [s]\n"
15079 "# $18 = decompression speed [MiB/s]\n\n");
15157 ERRMSG(
"Number of meteo variables doesn't match!");
15177 const char *varname) {
15186 for (
int ix = 0; ix < met->
nx; ix++)
15187 for (
int iy = 0; iy < met->
ny; iy++)
15188 help[
ARRAY_2D(ix, iy, met->
ny)] = var[ix][iy];
15191 LOG(2,
"Write 2-D variable: %s (uncompressed)", varname);
15193 (
size_t) (met->
nx * met->
ny),
15207 const char *varname,
15218#pragma omp parallel for default(shared) collapse(2)
15219 for (
int ix = 0; ix < met->
nx; ix++)
15220 for (
int iy = 0; iy < met->
ny; iy++)
15221 for (
int ip = 0; ip < met->
np; ip++)
15222 help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)] = var[ix][iy][ip];
15226 LOG(2,
"Write 3-D variable: %s (uncompressed)", varname);
15228 (
size_t) (met->
nx * met->
ny * met->
np),
15234 compress_pck(ctl, met, varname, help, 0, level_log, out);
15245 compress_zfp(ctl, met, varname, help, 0, level_log, out);
15258 compress_lz4(ctl, met, varname, help, 0, level_log, out);
15264 compress_cms(ctl, met, varname, help, 0, level_log, out);
15277 compress_sz3(ctl, met, varname, help, 0, level_log, out);
15283 ERRMSG(
"MET_TYPE not supported!");
15286 LOG(3,
"%d", metvar);
15296 const char *filename,
15302 size_t start[4], count[4];
15303 NC(nc_create(filename, NC_NETCDF4, &ncid));
15306 int tid, lonid, latid, levid;
15307 NC(nc_def_dim(ncid,
"time", 1, &tid));
15310 NC(nc_def_dim(ncid,
"lon", (
size_t) met->
nx, &lonid));
15311 NC(nc_def_dim(ncid,
"lat", (
size_t) met->
ny, &latid));
15312 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &lonid,
"longitude",
"degrees_east", 0,
15314 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &latid,
"latitude",
"degrees_north", 0,
15317 NC(nc_def_dim(ncid,
"x", (
size_t) met->
nx, &lonid));
15318 NC(nc_def_dim(ncid,
"y", (
size_t) met->
ny, &latid));
15319 NC_DEF_VAR(
"x", NC_DOUBLE, 1, &lonid,
"x",
"easting", 0, 0);
15320 NC_DEF_VAR(
"y", NC_DOUBLE, 1, &latid,
"y",
"northing", 0, 0);
15323 NC(nc_def_dim(ncid,
"lev", (
size_t) met->
np, &levid));
15326 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"time",
15327 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
15328 NC_DEF_VAR(
"lev", NC_DOUBLE, 1, &levid,
"pressure",
"Pa", 0, 0);
15331 int dimid2[3] = { tid, latid, lonid };
15332 NC_DEF_VAR(
"sp", NC_FLOAT, 3, dimid2,
"Surface pressure",
"Pa",
15334 NC_DEF_VAR(
"z", NC_FLOAT, 3, dimid2,
"Geopotential",
"m**2 s**-2",
15336 NC_DEF_VAR(
"t2m", NC_FLOAT, 3, dimid2,
"2 metre temperature",
"K",
15338 NC_DEF_VAR(
"u10m", NC_FLOAT, 3, dimid2,
"10 metre U wind component",
15340 NC_DEF_VAR(
"v10m", NC_FLOAT, 3, dimid2,
"10 metre V wind component",
15343 "Instantaneous eastward turbulent surface stress",
"N m**-2",
15346 "Instantaneous northward turbulent surface stress",
"N m**-2",
15349 "Instantaneous surface sensible heat flux",
"W m**-2",
15351 NC_DEF_VAR(
"lsm", NC_FLOAT, 3, dimid2,
"Land/sea mask",
"-",
15353 NC_DEF_VAR(
"sstk", NC_FLOAT, 3, dimid2,
"Sea surface temperature",
"K",
15355 NC_DEF_VAR(
"blp", NC_FLOAT, 3, dimid2,
"Boundary layer pressure",
"Pa",
15357 NC_DEF_VAR(
"pt", NC_FLOAT, 3, dimid2,
"Tropopause pressure",
"Pa",
15359 NC_DEF_VAR(
"tt", NC_FLOAT, 3, dimid2,
"Tropopause temperature",
"K",
15361 NC_DEF_VAR(
"zt", NC_FLOAT, 3, dimid2,
"Tropopause height",
"m",
15363 NC_DEF_VAR(
"h2ot", NC_FLOAT, 3, dimid2,
"Tropopause water vapor",
"ppv",
15365 NC_DEF_VAR(
"pct", NC_FLOAT, 3, dimid2,
"Cloud top pressure",
"Pa",
15367 NC_DEF_VAR(
"pcb", NC_FLOAT, 3, dimid2,
"Cloud bottom pressure",
"Pa",
15369 NC_DEF_VAR(
"cl", NC_FLOAT, 3, dimid2,
"Total column cloud water",
15372 "Pressure at lifted condensation level (LCL)",
"Pa",
15375 "Pressure at level of free convection (LFC)",
"Pa",
15378 "Pressure at equilibrium level (EL)",
"Pa", ctl->
met_nc_level,
15381 "Convective available potential energy",
"J kg**-1",
15383 NC_DEF_VAR(
"cin", NC_FLOAT, 3, dimid2,
"Convective inhibition",
15385 NC_DEF_VAR(
"o3c", NC_FLOAT, 3, dimid2,
"Total column ozone",
"DU",
15389 int dimid3[4] = { tid, levid, latid, lonid };
15390 NC_DEF_VAR(
"t", NC_FLOAT, 4, dimid3,
"Temperature",
"K",
15392 NC_DEF_VAR(
"u", NC_FLOAT, 4, dimid3,
"U velocity",
"m s**-1",
15394 NC_DEF_VAR(
"v", NC_FLOAT, 4, dimid3,
"V velocity",
"m s**-1",
15396 NC_DEF_VAR(
"w", NC_FLOAT, 4, dimid3,
"Vertical velocity",
"Pa s**-1",
15398 NC_DEF_VAR(
"q", NC_FLOAT, 4, dimid3,
"Specific humidity",
"kg kg**-1",
15400 NC_DEF_VAR(
"o3", NC_FLOAT, 4, dimid3,
"Ozone mass mixing ratio",
15402 NC_DEF_VAR(
"clwc", NC_FLOAT, 4, dimid3,
"Cloud liquid water content",
15404 NC_DEF_VAR(
"crwc", NC_FLOAT, 4, dimid3,
"Cloud rain water content",
15406 NC_DEF_VAR(
"ciwc", NC_FLOAT, 4, dimid3,
"Cloud ice water content",
15408 NC_DEF_VAR(
"cswc", NC_FLOAT, 4, dimid3,
"Cloud snow water content",
15410 NC_DEF_VAR(
"cc", NC_FLOAT, 4, dimid3,
"Cloud cover",
"-",
15414 NC(nc_enddef(ncid));
15428 for (
int ip = 0; ip < met->
np; ip++)
15429 phelp[ip] = 100. * met->
p[ip];
15472 NC(nc_close(ncid));
15479 const char *varname,
15485 size_t start[4], count[4];
15493 for (
int ix = 0; ix < met->
nx; ix++)
15494 for (
int iy = 0; iy < met->
ny; iy++)
15495 help[
ARRAY_2D(iy, ix, met->
nx)] = scl * var[ix][iy];
15498 LOG(2,
"Write 2-D variable: %s (netCDF)", varname);
15509 const char *varname,
15515 size_t start[4], count[4];
15523 for (
int ix = 0; ix < met->
nx; ix++)
15524 for (
int iy = 0; iy < met->
ny; iy++)
15525 for (
int ip = 0; ip < met->
np; ip++)
15526 help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)] = scl * var[ix][iy][ip];
15529 LOG(2,
"Write 3-D variable: %s (netCDF)", varname);
15539 const char *filename,
15547 ERRMSG(
"Only lat/lon grid supported");
15551 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
15552 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
15554 static int nobs, *obscount, ip, okay;
15563 if (ctl->
qnt_m < 0)
15564 ERRMSG(
"Need quantity mass!");
15568 ERRMSG(
"Specify molar mass!");
15575 ALLOC(area,
double,
15579 ALLOC(press,
double,
15585 ALLOC(rlon,
double,
15587 ALLOC(rlat,
double,
15589 ALLOC(robs,
double,
15596 LOG(1,
"Write profile data: %s", filename);
15597 if (!(out = fopen(filename,
"w")))
15598 ERRMSG(
"Cannot create file!");
15602 "# $1 = time [s]\n"
15603 "# $2 = altitude [km]\n"
15604 "# $3 = longitude [deg]\n"
15605 "# $4 = latitude [deg]\n"
15606 "# $5 = pressure [hPa]\n"
15607 "# $6 = temperature [K]\n"
15608 "# $7 = volume mixing ratio [ppv]\n"
15609 "# $8 = H2O volume mixing ratio [ppv]\n"
15610 "# $9 = O3 volume mixing ratio [ppv]\n"
15611 "# $10 = observed BT index [K]\n"
15612 "# $11 = number of observations\n");
15620 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
15621 z[iz] = ctl->
prof_z0 + dz * (iz + 0.5);
15622 press[iz] =
P(z[iz]);
15626 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
15627 lon[ix] = ctl->
prof_lon0 + dlon * (ix + 0.5);
15628 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
15629 lat[iy] = ctl->
prof_lat0 + dlat * (iy + 0.5);
15630 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
15635 const double t0 = t - 0.5 * ctl->
dt_mod;
15636 const double t1 = t + 0.5 * ctl->
dt_mod;
15639 ALLOC(mass,
double,
15641 ALLOC(obsmean,
double,
15643 ALLOC(obscount,
int,
15647 for (
int i = 0; i < nobs; i++) {
15652 else if (rt[i] >= t1)
15656 if (!isfinite(robs[i]))
15663 const int ix = (int) ((rlon[i] - ctl->
prof_lon0) / dlon);
15664 const int iy = (int) ((rlat[i] - ctl->
prof_lat0) / dlat);
15670 obsmean[idx] += robs[i];
15675 for (ip = 0; ip < atm->
np; ip++) {
15678 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
15682 const double zpart =
Z(atm->
p[ip]);
15687 || zpart < ctl->prof_z0 || zpart >= ctl->
prof_z1)
15689 const int ix = (int) ((atm->
lon[ip] - ctl->
prof_lon0) / dlon);
15690 const int iy = (int) ((atm->
lat[ip] - ctl->
prof_lat0) / dlat);
15691 const int iz = (int) ((zpart - ctl->
prof_z0) / dz);
15697 mass[idx] += atm->
q[ctl->
qnt_m][ip];
15701 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
15702 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
15704 if (obscount[idx2] > 0) {
15708 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
15710 if (mass[idx3] > 0) {
15719 fprintf(out,
"\n");
15722 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
15727 lon[ix], lat[iy], &temp, ci, cw, 1);
15729 lon[ix], lat[iy], &h2o, ci, cw, 0);
15731 lon[ix], lat[iy], &o3, ci, cw, 0);
15736 / (
RHO(press[iz], temp) * area[iy] * dz * 1e9);
15739 fprintf(out,
"%.2f %g %g %g %g %g %g %g %g %g %d\n",
15740 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
15741 obsmean[idx2] / obscount[idx2], obscount[idx2]);
15774 const char *filename,
15782 ERRMSG(
"Only lat/lon grid supported");
15786 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[
EP],
15789 static int nobs, nk;
15802 ALLOC(rlon,
double,
15804 ALLOC(rlat,
double,
15806 ALLOC(robs,
double,
15817 LOG(1,
"Write sample data: %s", filename);
15818 if (!(out = fopen(filename,
"w")))
15819 ERRMSG(
"Cannot create file!");
15823 "# $1 = time [s]\n"
15824 "# $2 = altitude [km]\n"
15825 "# $3 = longitude [deg]\n"
15826 "# $4 = latitude [deg]\n"
15827 "# $5 = surface area [km^2]\n"
15828 "# $6 = layer depth [km]\n"
15829 "# $7 = number of particles [1]\n"
15830 "# $8 = column density [kg/m^2]\n"
15831 "# $9 = volume mixing ratio [ppv]\n"
15832 "# $10 = observed BT index [K]\n\n");
15837 area = M_PI * rmax2;
15841 const double t0 = t - 0.5 * ctl->
dt_mod;
15842 const double t1 = t + 0.5 * ctl->
dt_mod;
15845 for (
int i = 0; i < nobs; i++) {
15850 else if (rt[i] >= t1)
15855 geo2cart(0, rlon[i], rlat[i], x0);
15858 const double rp =
P(rz[i]);
15859 const double ptop =
P(rz[i] + ctl->
sample_dz);
15860 const double pbot =
P(rz[i] - ctl->
sample_dz);
15868 for (
int ip = 0; ip < atm->
np; ip++) {
15871 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
15875 if (fabs(rlat[i] - atm->
lat[ip]) > dlat)
15881 if (
DIST2(x0, x1) > rmax2)
15886 if (atm->
p[ip] > pbot || atm->
p[ip] < ptop)
15890 if (ctl->
qnt_m >= 0)
15897 const double cd = mass / (1e6 * area);
15908 rlon[i], rlat[i], &temp, ci, cw, 1);
15917 fprintf(out,
"%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
15918 rlon[i], rlat[i], area, ctl->
sample_dz, np, cd, vmr, robs[i]);
15939 const char *filename,
15945 ERRMSG(
"Only lat/lon grid supported");
15949 static double rmax2, x0[3], x1[3];
15958 LOG(1,
"Write station data: %s", filename);
15961 if (!(out = fopen(filename,
"w")))
15962 ERRMSG(
"Cannot create file!");
15966 "# $1 = time [s]\n"
15967 "# $2 = altitude [km]\n"
15968 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
15969 for (
int iq = 0; iq < ctl->
nq; iq++)
15970 fprintf(out,
"# $%i = %s [%s]\n", (iq + 5),
15972 fprintf(out,
"\n");
15980 const double t0 = t - 0.5 * ctl->
dt_mod;
15981 const double t1 = t + 0.5 * ctl->
dt_mod;
15987 for (
int ip = 0; ip < atm->
np; ip++) {
15990 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
16006 if (
DIST2(x0, x1) > rmax2)
16016 fprintf(out,
"%.2f %g %g %g",
16017 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]);
16018 for (
int iq = 0; iq < ctl->
nq; iq++) {
16020 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
16022 fprintf(out,
"\n");
16031#pragma acc update device(atm->q[ctl->qnt_stat][0:atm->np])
16045 const char *filename,
16051 ERRMSG(
"Only lat/lon grid supported");
16059 LOG(1,
"Write VTK data: %s", filename);
16062 const double t0 = t - 0.5 * ctl->
dt_mod;
16063 const double t1 = t + 0.5 * ctl->
dt_mod;
16066 if (!(out = fopen(filename,
"w")))
16067 ERRMSG(
"Cannot create file!");
16071 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
16072 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
16079 "# vtk DataFile Version 3.0\n"
16080 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
16083 fprintf(out,
"POINTS %d float\n", np);
16085 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
16086 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
16090 const double coslat = cos(
DEG2RAD(atm->
lat[ip]));
16091 const double x = radius * coslat * cos(
DEG2RAD(atm->
lon[ip]));
16092 const double y = radius * coslat * sin(
DEG2RAD(atm->
lon[ip]));
16093 const double z = radius * sin(
DEG2RAD(atm->
lat[ip]));
16094 fprintf(out,
"%g %g %g\n", x, y, z);
16097 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
16098 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
16100 fprintf(out,
"%g %g %g\n", atm->
lon[ip], atm->
lat[ip],
16105 fprintf(out,
"POINT_DATA %d\n", np);
16106 for (
int iq = 0; iq < ctl->
nq; iq++) {
16107 fprintf(out,
"SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
16109 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
16110 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
16112 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 dd_init(const ctl_t *ctl, dd_t *dd, atm_t *atm)
Initialize the domain decomposition infrastructure.
void write_depo(const char *filename, const ctl_t *ctl, const depo_t *depo, const double t)
Convert cumulative ground inventories to Bq m^-2 and write them.
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.
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 dd_read_met_nc_grid(dd_t *dd, const ctl_t *ctl, met_t *met, const int ncid)
Read meteorological grid information and construct the domain-decomposed grid with halo regions.
void read_met_sample(const ctl_t *ctl, met_t *met)
Downsamples meteorological data based on specified parameters.
int read_met_nc_2d(const int ncid, const char *const varnames[], const size_t nvarnames, 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 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_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.
void compress_log_levels_3d(FILE *out, const char *codec, const char *varname, const met_t *met, const float *org_all, const float *cmp_all, const size_t nxy, const size_t nz, const double ratio, const double bpv, const double t_comp, const double t_decomp, const size_t nbytes)
Write per-level compression diagnostics for a full 3-D field.
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 write_depo_asc(const char *filename, const ctl_t *ctl, const double *data, const double t, const double *lon, const double *lat, const double *area)
Write radioactive deposition densities as a gnuplot-compatible table.
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 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 compress_pck(const ctl_t *ctl, const met_t *met, const char *varname, float *array, const int decompress, FILE *level_log, FILE *inout)
Compresses or decompresses a 3‑D float array using the PCK format.
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 intpol_check_cartesian(const double *lons, const int nlon, const double *lats, const int nlat, const double lon, const double lat, double *lon2, double *lat2)
Clamps UTM coordinates to the valid bounds.
void read_met_periodic(met_t *met)
Applies periodic boundary conditions to meteorological data along longitudinal axis.
int compress_metvar_index(const char *varname)
Maps a meteorological variable name to its internal MPTRAC variable index.
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 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 mptrac_free(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm, depo_t *depo, dd_t *dd)
Frees memory resources allocated for MPTRAC.
void dd_sort(const ctl_t *ctl, const met_t *met0, cache_t *cache, atm_t *atm, dd_t *dd, int *npart)
Sort local atmospheric particles and determine export counts for domain decomposition.
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 mptrac_write_output(const char *dirname, const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, depo_t *depo, const double t)
Writes various types of output data to files in a specified directory.
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 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 get_met_filename(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 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.
int compress_read_lossy_scale(FILE *in, const size_t nz, double **off, double **scl)
Read optional lossyscaling metadata for a 3-D field.
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 dd_pack_compact(const ctl_t *ctl, cache_t *cache, atm_t *atm, dd_t *dd, particle_t *particles, const int nkeep, const int npart)
Pack outgoing particles and compact local arrays without sorting.
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...
void dd_assign_subdomains(const ctl_t *ctl, const dd_t *dd, atm_t *atm, const int init)
Assign or update particle subdomain ownership.
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 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_mixing_help(const ctl_t *ctl, atm_t *atm, const int *ixs, const int *iys, const int *izs, const double *mixparam, const int qnt_idx, const int use_ensemble)
Perform subgrid-scale interparcel mixing of a given quantity.
int dd_calc_subdomain_from_coords(const ctl_t *ctl, const dd_t *dd, double lon, double lat)
Determine MPI subdomain from particle coordinates.
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 compress_scale_to_unit(float *array, const size_t nxy, const size_t nz, double *off, double *scl)
Scales each vertical level of a 3-D field independently to the interval [0,1].
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 dd_normalize_lon_lat(const dd_t *dd, double *lon, double *lat)
Normalize geographic coordinates to the global grid convention.
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_position(const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm, const int reflect)
Update the positions and pressure levels of atmospheric particles.
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 dd_particles2atm(const ctl_t *ctl, cache_t *cache, const particle_t *particles, const int npart, atm_t *atm)
Copy received particles from the communication buffer into the atmospheric state.
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.
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.
void module_diff_meso(const ctl_t *ctl, cache_t *cache, const met_t *met0, const met_t *met1, atm_t *atm)
Simulate mesoscale diffusion for atmospheric particles.
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.
void mptrac_init(ctl_t *ctl, cache_t *cache, clim_t *clim, atm_t *atm, depo_t *depo, const int ntask)
Initializes the MPTRAC model and its associated components.
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.
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 write_met_bin_3d(FILE *out, const ctl_t *ctl, met_t *met, float var[EX][EY][EP], const char *varname, const int metvar, FILE *level_log)
Writes a 3-dimensional meteorological variable to a binary file.
void read_met_ozone(met_t *met)
Calculates the total column ozone from meteorological ozone data.
void dd_count_outgoing(const ctl_t *ctl, const atm_t *atm, dd_t *dd, int *nkeep, int *npart)
Classify particles before direct packing and compaction.
void mptrac_alloc(ctl_t **ctl, cache_t **cache, clim_t **clim, met_t **met0, met_t **met1, atm_t **atm, depo_t **depo, dd_t **dd)
Allocates and initializes memory resources for MPTRAC.
void sort_array(double *array, const int *perm, double *tmp, const int np)
Reorder a double array according to particle source indices.
void broadcast_large_data(void *data, size_t N)
State variables of cuRAND random number generator.
void compress_write_lossy_scale(FILE *out, const int enabled, float *array, const size_t nxy, const size_t nz, double **off, double **scl)
Write optional lossyscaling metadata for a 3-D field.
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 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)
Converts Cartesian coordinates to geographic coordinates.
double time_from_filename(const char *filename, const int offset, const int with_seconds)
Extracts and converts a timestamp from a filename to Julian seconds.
void dd_atm2particles(const ctl_t *ctl, cache_t *cache, atm_t *atm, particle_t *particles, const int npart)
Copy migratable atmospheric particles from the ATM state into a particle buffer.
void module_sort(const ctl_t *ctl, const met_t *met0, cache_t *cache, atm_t *atm)
Sort particles according to box index.
void dd_communicate_particles(const ctl_t *ctl, const dd_t *dd, particle_t **particles, int *npart, int *capacity)
Exchange particles between MPI ranks according to their destination rank.
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.
int read_met_nc_3d(const int ncid, const char *const varnames[], const size_t nvarnames, 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.
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 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 write_budget(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes a time series of the atmospheric tracer mass budget.
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 sort_uvwp(cache_t *cache, const int *perm, double *tmp, const int np)
Reorder particle-specific wind perturbations.
void get_met_replace(char *orig, const char *search, const char *repl)
Replaces occurrences of a substring in a string with another substring.
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.
void write_depo_nc(const char *filename, const ctl_t *ctl, const double *data, const double t, const double *lon, const double *lat, const double *area)
Write radioactive deposition densities as a CF-style netCDF file.
void module_timesteps(const ctl_t *ctl, cache_t *cache, const met_t *met0, atm_t *atm, const double t)
Calculate time steps for air parcels based on specified conditions.
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 mptrac_run_timestep(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t **met0, met_t **met1, atm_t *atm, depo_t *depo, double t, dd_t *dd)
Executes a single timestep of the MPTRAC model simulation.
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.
unsigned long long * geometry
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.
void get_tropo(const int met_tropo, ctl_t *ctl, const 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.
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.
void module_dd(double t, const ctl_t *ctl, cache_t *cache, dd_t *dd, atm_t *atm, met_t **met)
Perform domain decomposition and exchange particles between MPI ranks.
void compress_log_level(FILE *out, const char *codec, const char *varname, const size_t lev, const double plev, const double ratio, const double bpv, const double t_comp, const double t_decomp, const size_t n, const size_t nbytes, const float *org, const float *cmp)
Write one row of per-level compression diagnostics.
void compress_unscale_from_unit(float *array, const size_t nxy, const size_t nz, const double *off, const double *scl)
Restores a levelwise [0,1]-scaled 3-D field to physical units.
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 tropo_weight(const ctl_t *ctl, const clim_t *clim, const atm_t *atm, const int ip)
Computes a weighting factor based on tropopause pressure.
void dd_push(const ctl_t *ctl, atm_t *atm, cache_t *cache, int *npart)
Compact and stage non-local particles for domain decomposition transfer.
double lapse_rate(const double t, const double h2o)
Calculates the moist adiabatic lapse rate in Kelvin per kilometer.
void module_radio_depo(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm, depo_t *depo)
Deposit supported radionuclides from air parcels onto the ground grid.
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.
#define LEN
Maximum length of ASCII data lines.
#define RE
Mean radius of Earth [km].
#define TVIRT(t, h2o)
Compute virtual temperature.
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 SO2_DISS_K2_TEMP
Temperature dependence of the second SO2 dissociation constant [K].
#define PARTICLE_LOOP(ip0, ip1, check_dt,...)
Loop over particle indices with OpenACC acceleration.
#define MA
Molar mass of dry air [g/mol].
#define RADIO_HALF_LIFE_CS137
Half-life of Cs-137 [s].
#define P0
Standard pressure [hPa].
#define AVO
Avogadro constant [1/mol].
#define KB
Boltzmann constant [kg m^2/(K s^2)].
#define SO2_CORR_B
Exponent of the high-SO2 correction [1].
#define COMPRESS_BPV(n, stored_size)
Calculate bits per value from stored size and element count.
#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.
#define LAPSE(p1, t1, p2, t2)
Calculate lapse rate.
#define NC(cmd)
Execute a NetCDF command and check for errors.
#define RADIO_DRY_VDEP_I131
Dry deposition velocity of aerosol-bound I-131 [m/s].
#define SELECT_TIMER(id, group)
Select and start a timer with specific attributes.
#define RADIO_DRY_VDEP_CS137
Dry deposition velocity of Cs-137 [m/s].
#define SO2_DISS_K1_REF
First SO2 dissociation constant at CHEM_REF_TEMP [mol/L].
#define ECC_READ_3D(variable, level, target, scaling_factor, found_flag)
Writes 3D data from a grib message into the meteo struct.
void compress_zfp(const ctl_t *ctl, const met_t *met, const char *varname, float *array, const int decompress, FILE *level_log, FILE *inout)
Compresses or decompresses a 3D array of floats using the ZFP library.
#define SO2_DISS_K1_TEMP
Temperature dependence of the first SO2 dissociation constant [K].
#define DOTP(a, b)
Calculate the dot product of two vectors.
#define RA
Specific gas constant of dry air [J/(kg K)].
#define DD_EY_GLOB
Maximum number of latitudes of global meteo data.
#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 O1D_RATE_CFC12_B
O(1D) reaction temperature parameter for CFC-12 [K].
#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.
#define O1D_RATE_N2O_A
O(1D) reaction pre-factor for N2O [cm^3/s].
#define EY
Maximum number of latitudes for meteo data.
#define RADIO_DRY_VDEP_PB210
Dry deposition velocity of Pb-210 [m/s].
#define SH(h2o)
Compute specific humidity from water vapor volume mixing ratio.
void compress_sz3(const ctl_t *ctl, const met_t *met, const char *varname, float *array, const int decompress, FILE *level_log, FILE *inout)
Compresses or decompresses a 3-D float array using the SZ3 library.
#define H2O2_HENRY_TEMP
Temperature dependence of the H2O2 Henry constant [K].
#define INTPOL_3D(var, init)
Perform 3D interpolation for a meteorological variable.
#define CLAMP(v, lo, hi)
Clamp a value to a specified range.
#define M_AIR_MOLECULE
Mean mass of an air molecule [kg].
#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.
void compress_zstd(const ctl_t *ctl, const met_t *met, const char *varname, float *array, const int decompress, FILE *level_log, FILE *inout)
Compresses or decompresses a float array using ZSTD.
#define SO2_CORR_A
Scale factor of the high-SO2 correction [1].
#define P(z)
Compute pressure at given altitude.
#define LV
Latent heat of vaporization of water [J/kg].
#define RADIO_HALF_LIFE_I131
Half-life of I-131 [s].
#define RADIO_HALF_LIFE_BE7
Half-life of Be-7 [s].
#define G0
Standard gravity [m/s^2].
void compress_cms(const ctl_t *ctl, const met_t *met, const char *varname, float *array, const int decompress, FILE *level_log, FILE *inout)
Compresses or decompresses a 3-D meteorological field using cmultiscale.
#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 H2O2_SO2_RATE_REF
Reference rate for aqueous H2O2-SO2 chemistry [L^2/(mol^2 s)].
#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 O1D_RATE_CFC12_A
O(1D) reaction pre-factor for CFC-12 [cm^3/s].
#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 O1D_RATE_N2O_B
O(1D) reaction temperature parameter for N2O [K].
#define DX2COORD(met, dx, lat)
Convert a distance in meters to a coordinate value based on grid type.
#define O1D_RATE_CCL4_B
O(1D) reaction temperature parameter for CCl4 [K].
#define COMPRESS_RATIO(raw_size, stored_size)
Calculate the compression ratio from raw and stored byte counts.
#define WET_DEPO_T_ICE
Lower temperature of the ice-cloud retention transition [K].
#define THETA(p, t)
Compute potential temperature.
#define RI
Ideal gas constant [J/(mol K)].
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 RADIO_WET_COEFF_BE7
Wet deposition coefficient of Be-7 [s^-1].
#define SET_QNT(qnt, name, longname, unit)
Set atmospheric quantity index.
#define TICE(p, h2o)
Calculate frost point temperature (WMO, 2018).
void compress_lz4(const ctl_t *ctl, const met_t *met, const char *varname, float *array, const int decompress, FILE *level_log, FILE *inout)
Compresses or decompresses a float array using LZ4.
#define O1D_RATE_CFC11_A
O(1D) reaction pre-factor for CFC-11 [cm^3/s].
#define RADIO_WET_COEFF_CS137
Wet deposition coefficient of Cs-137 [s^-1].
#define TOK(line, tok, format, var)
Get string tokens.
#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.
#define WARN(...)
Print a warning message with contextual information.
#define H2O2_SO2_RATE_TEMP
Temperature parameter for the aqueous H2O2-SO2 rate [K].
#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 O1D_RATE_CCL4_A
O(1D) reaction pre-factor for CCl4 [cm^3/s].
#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.
#define OMEGA_EARTH
Angular velocity of Earth [s^-1].
#define DEG2RAD(deg)
Converts degrees to radians.
#define MO3
Molar mass of ozone [g/mol].
#define SQR(x)
Compute the square of a value.
#define RADIO_WET_COEFF_I131
Wet deposition coefficient of aerosol-bound I-131 [s^-1].
#define RAD2DEG(rad)
Converts radians to degrees.
#define RADIO_DRY_VDEP_BE7
Dry deposition velocity of Be-7 [m/s].
#define NP
Maximum number of atmospheric data points.
#define NTIMER
Maximum number of timers.
#define COMPRESS_SPEED(nbytes, dt)
Calculate compression throughput in MiB/s.
#define INTPOL_2D(var, init)
Perform 2D interpolation for a meteorological variable.
#define RH(p, t, h2o)
Compute relative humidity over water.
#define H2O2_HENRY_REF
Henry constant of H2O2 at CHEM_REF_TEMP [mol/(L atm)].
#define CHEM_REF_TEMP
Reference temperature for chemical equilibrium constants [K].
#define NC_PUT_FLOAT(varname, ptr, hyperslab)
Write a float array to a NetCDF file.
#define DD_EX_GLOB
Maximum number of longitudes of global meteo data.
#define CY
Maximum number of latitudes for climatological data.
#define LOG(level,...)
Print a log message with a specified logging level.
#define RADIO_HALF_LIFE_RN222
Half-life of Rn-222 [s].
#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 KAPPA
Exponent used for potential-temperature calculations [1].
#define ARRHENIUS(a, b, t)
Calculate the Arrhenius rate constant.
#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 EP
Maximum number of pressure levels for meteo data.
#define PSAT(t)
Compute saturation pressure over water.
#define SO2_DISS_K2_REF
Second SO2 dissociation constant at CHEM_REF_TEMP [mol/L].
#define SO2_HENRY_REF
Henry constant of SO2 at CHEM_REF_TEMP [mol/(L atm)].
#define SO2_HENRY_TEMP
Temperature dependence of the SO2 Henry constant [K].
#define RHO(p, t)
Compute density of air.
#define RADIO_HALF_LIFE_PB210
Half-life of Pb-210 [s].
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.
#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 WET_DEPO_T_LIQUID
Upper temperature of the ice-cloud retention transition [K].
#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 DY2COORD(met, dy)
Convert a distance to coordinate value based on grid type.
#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 O1D_RATE_CFC11_B
O(1D) reaction temperature parameter for CFC-11 [K].
#define MAX(a, b)
Macro to determine the maximum of two values.
#define WET_DEPO_T_LIQUID_BC
Temperature threshold for below-cloud retention [K].
#define RADIO_HALF_LIFE_XE133
Half-life of Xe-133 [s].
#define RADIO_WET_COEFF_PB210
Wet deposition coefficient of Pb-210 [s^-1].
#define FMOD(x, y)
Calculate the floating-point remainder of dividing x by y.
#define DOBSON_UNIT
Ozone column mass corresponding to one Dobson unit [kg/m^2].
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]
Shared balloon times [s] for ISOSURF=4.
int iso_n
Isosurface balloon number of data points.
double iso_ps[NP]
Shared balloon pressure time series [hPa] for ISOSURF=4.
double rs[3 *NP+1]
Random numbers.
float uvwp[NP][3]
Wind perturbations [m/s].
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 met_utm_ref_lon
Reference longitude [deg] for UTM grid.
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 qnt_eta_d
Quantity array index for diagnosed eta vertical coordinate.
int qnt_target_subdomain
Quantity array index for destination subdomain in domain decomposition.
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 halo size in grid points.
char atm_gpfile[LEN]
Gnuplot file for atmospheric data.
int mixing_nx
Number of longitudes of mixing grid.
int met_zstd_nworkers
ZSTD number of worker threads (0=single-threaded, default=4).
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 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, default=-3).
double met_utm_ref_lat
Reference latitude [deg] for UTM grid.
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).
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).
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.
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 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 met_nc_read_mode
NetCDF DD input (0=local hyperslabs, 1=global 2-D slices via MPI).
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
RADIO_DECAY switch for airborne and deposited activity (0=off, 1=on, default: 0).
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 met_pck_zstd
Apply an additional ZSTD compression step to PCK payloads (0=off, 1=on).
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 depo_dt_out
DEPO_DT_OUT time interval for radioactive deposition output [s] (default: 86400).
double turb_mesox
Horizontal scaling factor for mesoscale wind fluctuations.
char grid_kernel[LEN]
Kernel data file for grid output.
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 dd_supported
Whether the executable implements the domain decomposition.
double dd_sort_dt
Sorting time interval for the compactification (DD_EXCHANGE_MODE=0).
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).
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 variability of OH.
int dd
Domain decomposition (0=no, 1=yes).
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).
char met_comp_logfile[LEN]
Filename for per-level compression diagnostics ("-" disables output).
int qnt_h2ot
Quantity array index for tropopause water vapor volume mixing ratio.
int qnt_rh
Quantity array index for relative humidity over water.
int met_gp2z
Convert surface geopotential to geopotential height (0=no, 1=yes).
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 mixing_ny
Number of latitudes of mixing grid.
int met_convention
Meteo data layout (0=[lev, lat, lon], 1=[lon, lat, lev]).
char depo_basename[LEN]
DEPO_BASENAME for radioactive deposition files (default: disabled with "-").
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 switch (0=off, 1=on).
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 turb_pbl_scheme
PBL turbulence scheme (0=none, 1=closure).
double budget_dt_out
Time step for mass budget output [s].
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].
double met_zfp_tol[METVAR]
ZFP compression tolerance.
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).
int met_sz3_prec[METVAR]
SZ3 compression precision.
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).
int qnt_us
Quantity array index for surface zonal wind.
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.
int depo_type
DEPO_TYPE of deposition files (0=ASCII, 1=netCDF, default: 0).
char budget_basename[LEN]
Basename of mass budget data file.
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 (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 pressure thickness).
int met_lz4_accel
LZ4 acceleration factor (>=1, default=8).
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.
double mixing_tau_trop
E-folding time for interparcel mixing in the troposphere [s].
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].
double met_cms_eps[METVAR]
cmultiscale compression epsilon.
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.
int met_lossy_scale[METVAR]
Apply levelwise [0,1] scaling before lossy compression (0=off, 1=on).
double prof_lat1
Upper latitude of gridded profile data [deg].
int qnt_current_subdomain
Quantity array index for current subdomain in domain decomposition.
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.
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 turb_pbl_trans
Depth of turbulent PBL transition layer (fraction of PBL pressure thickness).
double psc_hno3
HNO3 volume mixing ratio for PSC analysis.
double prof_lon1
Upper longitude of gridded profile data [deg].
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.
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).
double met_sz3_tol[METVAR]
SZ3 compression tolerance.
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].
double mixing_tau_strat
E-folding time for interparcel mixing in the stratosphere [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 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].
int dd_exchange_mode
Particle exchange: 0=sort/push (default), 1=direct pack/compact.
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 met_coord_type
Type of coordinates for meteo data (-1=detect, 0=lat/lon [deg], 1=UTM [m]).
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 radio_depo
RADIO_DEPO switch for radionuclide deposition (0=off, 1=on, default: 0).
int dd_subdomains_zonal
Domain decomposition zonal subdomain number (defaults to 2 if domain decomposition is used,...
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].
int met_zfp_prec[METVAR]
ZFP compression precision.
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 (defaults to 2 if domain decomposition is used,...
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_iso_var
Quantity array index for isosurface reference (units depend on ISOSURF).
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]
Extent of the periodic boundary halo hyperslab.
int halo_offset_end
Offset of the periodic halo block at the end of the local x-array.
int nx_glob
Number of global longitudes.
double sort_key[NP]
Auxiliary array for sorting.
size_t halo_bnd_start[4]
Start indices of the periodic boundary halo hyperslab.
double lon_glob[DD_EX_GLOB]
Longitudes of the global grid [deg].
double tmp[NP]
Auxiliary temporary array for sorting.
double lat_glob[DD_EY_GLOB]
Latitudes of the global grid [deg].
int halo_offset_start
Offset of the periodic halo block at the beginning of the local x-array.
MPI_Datatype MPI_Particle
MPI datatype for particle exchange.
size_t subdomain_count[4]
Extent of the local subdomain hyperslab (including inner halos).
int ny_glob
Number of global latitudes.
size_t subdomain_start[4]
Start indices of the local subdomain hyperslab (including inner halos).
int perm[NP]
Auxiliary permutation array for sorting.
Ground inventories of deposited radionuclides.
double Ai131[EX *EY]
Deposited I-131 activity [Bq].
double Abe7[EX *EY]
Deposited Be-7 activity [Bq].
double Acs137[EX *EY]
Deposited Cs-137 activity [Bq].
double Apb210[EX *EY]
Deposited Pb-210 activity [Bq].
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].
float uvwp[3]
Temporally correlated turbulent velocity perturbations [m/s].
double lon
Longitude [deg].
double q[NQ]
Quantity data (for various, user-defined attributes).