35static uint64_t rng_ctr;
39static curandGenerator_t rng_curand;
49#define CHUNK_SIZE 2147483647
52 MPI_Bcast(&N, 1, MPI_UINT64_T, 0, MPI_COMM_WORLD);
55 const size_t num_chunks = (N + CHUNK_SIZE - 1) / CHUNK_SIZE;
58 for (
size_t i = 0; i < num_chunks; i++) {
61 const size_t start = i * CHUNK_SIZE;
62 const size_t end = (start + CHUNK_SIZE > N) ? N : start + CHUNK_SIZE;
63 const size_t chunk_size = end - start;
66 MPI_Bcast((
char *) data + start, (
int) chunk_size, MPI_BYTE, 0,
80 const double radius = sqrt(
DOTP(x, x));
82 *lat =
RAD2DEG(asin(x[2] / radius));
83 *lon =
RAD2DEG(atan2(x[1], x[0]));
98 const double sza_thresh =
DEG2RAD(85.), csza_thresh = cos(sza_thresh);
101 const double lat_ref =
104 while (lon_ref < -180.0)
106 while (lon_ref >= 180.0)
110 const double oh =
clim_zm(&clim->
oh, t, lat_ref, p);
117 const double csza =
cos_sza(t, lon_ref, lat_ref);
118 const double denom = (csza >= csza_thresh) ? csza : csza_thresh;
129 const double sza_thresh =
DEG2RAD(85.), csza_thresh = cos(sza_thresh);
132 for (
int it = 0; it < clim->
oh.
ntime; it++)
133 for (
int iz = 0; iz < clim->
oh.
np; iz++)
134 for (
int iy = 0; iy < clim->
oh.
nlat; iy++) {
141 for (
double lon = -180; lon < 180; lon += 1.0) {
144 const double denom = (csza >= csza_thresh) ? csza : csza_thresh;
150 clim->
oh.
vmr[it][iz][iy] /= (sum / (double) n);
165 if (p < photo->p[photo->
np - 1])
166 p_help = photo->
p[photo->
np - 1];
167 else if (p > photo->
p[0])
168 p_help = photo->
p[0];
171 double sza_help = sza;
172 if (sza < photo->sza[0])
173 sza_help = photo->
sza[0];
174 else if (sza > photo->
sza[photo->
nsza - 1])
175 sza_help = photo->
sza[photo->
nsza - 1];
178 double o3c_help = o3c;
179 if (o3c < photo->o3c[0])
180 o3c_help = photo->
o3c[0];
181 else if (o3c > photo->
o3c[photo->
no3c - 1])
182 o3c_help = photo->
o3c[photo->
no3c - 1];
190 const double aux00 =
LIN(photo->
p[ip], rate[ip][isza][io3c],
191 photo->
p[ip + 1], rate[ip + 1][isza][io3c],
193 const double aux01 =
LIN(photo->
p[ip], rate[ip][isza][io3c + 1],
194 photo->
p[ip + 1], rate[ip + 1][isza][io3c + 1],
196 const double aux10 =
LIN(photo->
p[ip], rate[ip][isza + 1][io3c],
197 photo->
p[ip + 1], rate[ip + 1][isza + 1][io3c],
199 const double aux11 =
LIN(photo->
p[ip], rate[ip][isza + 1][io3c + 1],
200 photo->
p[ip + 1], rate[ip + 1][isza + 1][io3c + 1],
203 LIN(photo->
o3c[io3c], aux00, photo->
o3c[io3c + 1], aux01, o3c_help);
205 LIN(photo->
o3c[io3c], aux10, photo->
o3c[io3c + 1], aux11, o3c_help);
207 LIN(photo->
sza[isza], aux0, photo->
sza[isza + 1], aux1, sza_help);
208 return MAX(aux, 0.0);
219 double sec =
FMOD(t, 365.25 * 86400.);
221 sec += 365.25 * 86400.;
229 clim->
tropo[isec][ilat],
231 clim->
tropo[isec][ilat + 1], lat);
233 clim->
tropo[isec + 1][ilat],
235 clim->
tropo[isec + 1][ilat + 1], lat);
245 LOG(1,
"Initialize tropopause data...");
249 double tropo_time[12] = {
250 1209600.00, 3888000.00, 6393600.00,
251 9072000.00, 11664000.00, 14342400.00,
252 16934400.00, 19612800.00, 22291200.00,
253 24883200.00, 27561600.00, 30153600.00
259 const double tropo_lat[73] = {
260 -90, -87.5, -85, -82.5, -80, -77.5, -75, -72.5, -70, -67.5,
261 -65, -62.5, -60, -57.5, -55, -52.5, -50, -47.5, -45, -42.5,
262 -40, -37.5, -35, -32.5, -30, -27.5, -25, -22.5, -20, -17.5,
263 -15, -12.5, -10, -7.5, -5, -2.5, 0, 2.5, 5, 7.5, 10, 12.5,
264 15, 17.5, 20, 22.5, 25, 27.5, 30, 32.5, 35, 37.5, 40, 42.5,
265 45, 47.5, 50, 52.5, 55, 57.5, 60, 62.5, 65, 67.5, 70, 72.5,
266 75, 77.5, 80, 82.5, 85, 87.5, 90
271 const double tropo[12][73] = {
272 {324.1, 325.6, 325, 324.3, 322.5, 319.7, 314, 307.2, 301.8, 299.6,
273 297.1, 292.2, 285.6, 276.1, 264, 248.9, 231.9, 213.5, 194.4,
274 175.3, 157, 140.4, 126.7, 116.3, 109.5, 105.4, 103, 101.4, 100.4,
275 99.69, 99.19, 98.84, 98.56, 98.39, 98.39, 98.42, 98.44, 98.54,
276 98.68, 98.81, 98.89, 98.96, 99.12, 99.65, 101.4, 105.4, 113.5, 128,
277 152.1, 184.7, 214, 234.1, 247.3, 255.8, 262.6, 267.7, 271.7, 275,
278 277.2, 279, 280.1, 280.4, 280.6, 280.1, 279.3, 278.3, 276.8, 275.8,
279 275.3, 275.6, 275.4, 274.1, 273.5},
280 {337.3, 338.7, 337.8, 336.4, 333, 328.8, 321.1, 312.6, 306.6, 303.7,
281 300.2, 293.8, 285.4, 273.8, 259.6, 242.7, 224.4, 205.2, 186, 167.5,
282 150.3, 135, 122.8, 113.9, 108.2, 104.7, 102.5, 101.1, 100.2, 99.42,
283 98.88, 98.52, 98.25, 98.09, 98.07, 98.1, 98.12, 98.2, 98.25, 98.27,
284 98.26, 98.27, 98.36, 98.79, 100.2, 104.2, 113.7, 131.2, 159.5, 193,
285 220.4, 238.1, 250.2, 258.1, 264.7, 269.7, 273.7, 277.3, 280.2, 282.8,
286 284.9, 286.5, 288.1, 288.8, 289, 288.5, 287.2, 286.3, 286.1, 287.2,
287 287.5, 286.2, 285.8},
288 {335, 336, 335.7, 335.1, 332.3, 328.1, 320.6, 311.8, 305.1, 301.9,
289 297.6, 290, 280.4, 268.3, 254.6, 239.6, 223.9, 207.9, 192.2, 176.9,
290 161.7, 146.4, 132.2, 120.6, 112.3, 107.2, 104.3, 102.4, 101.3,
291 100.4, 99.86, 99.47, 99.16, 98.97, 98.94, 98.97, 99, 99.09, 99.2,
292 99.31, 99.35, 99.41, 99.51, 99.86, 101.1, 104.9, 114.3, 131, 156.8,
293 186.3, 209.3, 224.6, 236.8, 246.3, 254.9, 262.3, 268.8, 274.8,
294 279.9, 284.6, 288.6, 291.6, 294.9, 297.5, 299.8, 301.8, 303.1,
295 304.3, 304.9, 306, 306.6, 306.2, 306},
296 {306.2, 306.7, 305.7, 307.1, 307.3, 306.4, 301.8, 296.2, 292.4,
297 290.3, 287.1, 280.9, 273.4, 264.3, 254.1, 242.8, 231, 219, 207.2,
298 195.5, 183.3, 169.7, 154.7, 138.7, 124.1, 113.6, 107.8, 104.7,
299 102.8, 101.7, 100.9, 100.4, 100, 99.79, 99.7, 99.66, 99.68, 99.79,
300 99.94, 100.2, 100.5, 100.9, 101.4, 102.1, 103.4, 107, 115.2, 129.1,
301 148.7, 171, 190.8, 205.6, 218.4, 229.4, 239.6, 248.6, 256.5,
302 263.7, 270.3, 276.6, 282.6, 288.1, 294.5, 300.4, 306.3, 311.4,
303 315.1, 318.3, 320.3, 322.2, 322.8, 321.5, 321.1},
304 {266.5, 264.9, 260.8, 261, 262, 263, 261.3, 259.7, 259.2, 259.8,
305 260.1, 258.6, 256.7, 253.6, 249.5, 243.9, 237.4, 230, 222.1, 213.9,
306 205, 194.4, 180.4, 161.8, 140.7, 122.9, 112.1, 106.7, 104.1, 102.7,
307 101.8, 101.4, 101.1, 101, 101, 101, 101.1, 101.2, 101.5, 101.9,
308 102.4, 103, 103.8, 104.9, 106.8, 110.1, 115.6, 124, 135.2, 148.9,
309 165.2, 181.3, 198, 211.8, 223.5, 233.8, 242.9, 251.5, 259, 266.2,
310 273.1, 279.2, 286.2, 292.8, 299.6, 306, 311.1, 315.5, 318.8, 322.6,
311 325.3, 325.8, 325.8},
312 {220.1, 218.1, 210.8, 207.2, 207.6, 210.5, 211.4, 213.5, 217.3,
313 222.4, 227.9, 232.8, 237.4, 240.8, 242.8, 243, 241.5, 238.6, 234.2,
314 228.5, 221, 210.7, 195.1, 172.9, 147.8, 127.6, 115.6, 109.9, 107.1,
315 105.7, 105, 104.8, 104.8, 104.9, 105, 105.1, 105.3, 105.5, 105.8,
316 106.4, 107, 107.6, 108.1, 108.8, 110, 111.8, 114.2, 117.4, 121.6,
317 127.9, 137.3, 151.2, 169.5, 189, 205.8, 218.9, 229.1, 237.8, 245,
318 251.5, 257.1, 262.3, 268.2, 274, 280.4, 286.7, 292.4, 297.9, 302.9,
319 308.5, 312.2, 313.1, 313.3},
320 {187.4, 184.5, 173.3, 166.1, 165.4, 167.8, 169.6, 173.6, 179.6,
321 187.9, 198.9, 210, 220.5, 229.2, 235.7, 239.9, 241.8, 241.6, 239.6,
322 235.8, 229.4, 218.6, 200.9, 175.9, 149.4, 129.4, 118.3, 113.1,
323 110.8, 109.7, 109.3, 109.4, 109.7, 110, 110.2, 110.4, 110.5, 110.7,
324 111, 111.4, 111.8, 112.1, 112.3, 112.7, 113.2, 113.9, 115, 116.4,
325 117.9, 120.4, 124.1, 130.9, 142.2, 159.6, 179.6, 198.5, 212.9,
326 224.2, 232.7, 239.1, 243.8, 247.7, 252.4, 257.3, 263.2, 269.5,
327 275.4, 281.1, 286.3, 292, 296.3, 298.2, 298.8},
328 {166, 166.4, 155.7, 148.3, 147.1, 149, 152.1, 157, 163.6, 172.4,
329 185.3, 199.2, 212.6, 224, 233.2, 239.6, 243.3, 244.6, 243.6, 240.3,
330 233.9, 222.6, 203.7, 177, 149.5, 129.7, 119, 114, 111.7, 110.7,
331 110.3, 110.3, 110.6, 110.9, 111.1, 111.3, 111.5, 111.6, 111.9,
332 112.2, 112.5, 112.6, 112.8, 113, 113.4, 114, 115.1, 116.5, 118.3,
333 120.9, 124.4, 130.2, 139.4, 154.6, 173.8, 193.1, 208.1, 220.4,
334 230.1, 238.2, 244.7, 249.5, 254.5, 259.3, 264.5, 269.4, 273.7,
335 278.2, 282.6, 287.4, 290.9, 292.5, 293},
336 {171.9, 172.8, 166.2, 162.3, 161.4, 162.5, 165.2, 169.6, 175.3,
337 183.1, 193.8, 205.9, 218.3, 229.6, 238.5, 244.3, 246.9, 246.7,
338 243.8, 238.4, 230.2, 217.9, 199.6, 174.9, 148.9, 129.8, 119.5,
339 114.8, 112.3, 110.9, 110.3, 110.1, 110.2, 110.3, 110.4, 110.5,
340 110.6, 110.8, 111, 111.4, 111.8, 112, 112.2, 112.4, 112.9, 113.6,
341 114.7, 116.3, 118.4, 121.9, 127.1, 136.1, 149.8, 168.4, 186.9,
342 203.3, 217, 229.1, 238.7, 247, 254, 259.3, 264.3, 268.3, 272.5,
343 276.6, 280.4, 284.4, 288.4, 293.3, 297.2, 298.7, 299.1},
344 {191.6, 192.2, 189, 188.1, 190.2, 193.7, 197.8, 202.9, 208.5,
345 215.6, 224.2, 233.1, 241.2, 247.3, 250.8, 251.3, 248.9, 244.2,
346 237.3, 228.4, 217.2, 202.9, 184.5, 162.5, 140.7, 124.8, 116.2,
347 111.8, 109.4, 107.9, 107, 106.7, 106.6, 106.6, 106.7, 106.7,
348 106.8, 107, 107.4, 108, 108.7, 109.3, 109.8, 110.4, 111.2,
349 112.4, 114.2, 116.9, 121.1, 127.9, 139.3, 155.2, 173.6, 190.7,
350 206.1, 220.1, 232.3, 243, 251.8, 259.2, 265.7, 270.6, 275.3,
351 279.3, 283.3, 286.9, 289.7, 292.8, 296.1, 300.5, 303.9, 304.8,
353 {241.5, 239.6, 236.8, 237.4, 239.4, 242.3, 244.2, 246.4, 249.2,
354 253.6, 258.6, 262.7, 264.8, 264.2, 260.6, 254.1, 245.5, 235.3,
355 223.9, 211.7, 198.3, 183.1, 165.6, 147.1, 130.5, 118.7, 111.9,
356 108.1, 105.8, 104.3, 103.4, 102.8, 102.5, 102.4, 102.5, 102.5,
357 102.5, 102.7, 103.1, 103.8, 104.6, 105.4, 106.1, 107, 108.2,
358 109.9, 112.8, 117.5, 126, 140.4, 161, 181.9, 201.2, 216.8, 230.4,
359 241.8, 251.4, 259.9, 266.9, 272.8, 277.4, 280.4, 282.9, 284.6,
360 286.1, 287.4, 288.3, 289.5, 290.9, 294.2, 296.9, 297.5, 297.6},
361 {301.2, 300.3, 296.6, 295.4, 295, 294.3, 291.2, 287.4, 284.9, 284.7,
362 284.1, 281.5, 277.1, 270.4, 261.7, 250.6, 237.6, 223.1, 207.9, 192,
363 175.8, 158.8, 142.1, 127.6, 116.8, 109.9, 106, 103.6, 102.1, 101.1,
364 100.4, 99.96, 99.6, 99.37, 99.32, 99.32, 99.31, 99.46, 99.77, 100.2,
365 100.7, 101.3, 101.8, 102.7, 104.1, 106.8, 111.9, 121, 136.7, 160,
366 186.9, 209.9, 228.1, 241.2, 251.5, 259.5, 265.7, 270.9, 274.8, 278,
367 280.3, 281.8, 283, 283.3, 283.7, 283.8, 283, 282.2, 281.2, 281.4,
370 memcpy(clim->
tropo, tropo,
sizeof(clim->
tropo));
373 double tropomin = 1e99, tropomax = -1e99;
375 for (
int iy = 0; iy < clim->
tropo_nlat; iy++) {
376 tropomin =
MIN(tropomin, clim->
tropo[it][iy]);
377 tropomax =
MAX(tropomax, clim->
tropo[it][iy]);
382 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
386 LOG(2,
"Latitudes: %g, %g ... %g deg",
389 LOG(2,
"Tropopause altitude range: %g ... %g hPa",
Z(tropomax),
391 LOG(2,
"Tropopause pressure range: %g ... %g hPa", tropomin, tropomax);
401 if (t <= ts->time[0])
408 ts->
time[idx + 1], ts->
vmr[idx + 1], t);
421 double sec =
FMOD(t, 365.25 * 86400.);
423 sec += 365.25 * 86400.;
427 if (p < zm->p[zm->
np - 1])
428 p_help = zm->
p[zm->
np - 1];
429 else if (p > zm->
p[0])
433 double lat_help = lat;
434 if (lat < zm->lat[0])
435 lat_help = zm->
lat[0];
436 else if (lat > zm->
lat[zm->
nlat - 1])
437 lat_help = zm->
lat[zm->
nlat - 1];
445 const double aux00 =
LIN(zm->
p[ip], zm->
vmr[isec][ip][ilat],
446 zm->
p[ip + 1], zm->
vmr[isec][ip + 1][ilat],
448 const double aux01 =
LIN(zm->
p[ip], zm->
vmr[isec][ip][ilat + 1],
449 zm->
p[ip + 1], zm->
vmr[isec][ip + 1][ilat + 1],
451 const double aux10 =
LIN(zm->
p[ip], zm->
vmr[isec + 1][ip][ilat],
452 zm->
p[ip + 1], zm->
vmr[isec + 1][ip + 1][ilat],
454 const double aux11 =
LIN(zm->
p[ip], zm->
vmr[isec + 1][ip][ilat + 1],
455 zm->
p[ip + 1], zm->
vmr[isec + 1][ip + 1][ilat + 1],
458 LIN(zm->
lat[ilat], aux00, zm->
lat[ilat + 1], aux01, lat_help);
460 LIN(zm->
lat[ilat], aux10, zm->
lat[ilat + 1], aux11, lat_help);
461 const double aux =
LIN(zm->
time[isec], aux0, zm->
time[isec + 1], aux1, sec);
462 return MAX(aux, 0.0);
473 const int decompress,
477 const size_t nx = (size_t) met->
nx;
478 const size_t ny = (
size_t) met->
ny;
479 const size_t np = (size_t) met->
np;
485 const size_t nxy = nx * ny;
486 double lon[
EX], lat[
EY];
487 for (
size_t ix = 0; ix < nx; ix++)
488 lon[ix] = 360. * (
double) ix / ((double) nx - 1.);
489 for (
size_t iy = 0; iy < ny; iy++)
490 lat[iy] = 90. - 180. * (
double) iy / ((double) ny - 1.);
493 const char domain[] =
"[0.0, 360.0]x[-90.0, 90.0]";
497 cms_param_t *cms_param
498 = cms_set_parameters(nx, ny, max_level_grid, Nd0_x, Nd0_y, domain);
501 double cr = 0, t_coars = 0, t_eval = 0;
508 for (
size_t ip = 0; ip < np; ip++) {
511 cms_module_t *cms_ptr = cms_init(cms_param);
516 cms_sol = cms_read_zstd_sol(cms_ptr, inout);
518 cms_sol = cms_read_sol(cms_ptr, inout);
521 const double t0 = omp_get_wtime();
522#pragma omp parallel for collapse(2) default(shared)
523 for (
size_t ix = 0; ix < nx; ix++)
524 for (
size_t iy = 0; iy < ny; iy++) {
526 const double x[] = { lon[ix], lat[iy] };
527 cms_eval(cms_ptr, cms_sol, x, &val);
528 array[
ARRAY_3D(ix, iy, ny, ip, np)] = (float) val;
530 t_eval += omp_get_wtime() - t0;
533 cr += 1.0 / cms_compression_rate(cms_ptr, cms_sol);
536 cms_delete_sol(cms_sol);
537 cms_delete_module(cms_ptr);
541 LOG(2,
"Read 3-D variable: %s"
542 " (CMS, RATIO=%g, BPV=%g, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
543 varname, (
double) np / cr, 32. * cr / (
double) np, t_eval,
551 cms_module_t *cms_ptr[
EP];
552 cms_sol_t *cms_sol[
EP];
553 double rho[
EP], mean_err[
EP], stddev_err[
EP], min_err[
EP], max_err[
EP];
554 double mean_org[
EP], range_org[
EP], nrmse[
EP];
555 double ratio[
EP], bpv[
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++) {
572 ALLOC(tmp_arr,
float,
576 for (
size_t ix = 0; ix < nx; ++ix)
577 for (
size_t iy = 0; iy < ny; ++iy)
579 array[
ARRAY_3D(ix, iy, ny, ip, np)];
582 cms_ptr[ip] = cms_init(cms_param);
586 cms_read_arr_new(cms_ptr[ip], tmp_arr, lon, lat,
594 t_coars += (omp_get_wtime() - t0);
597 for (
size_t ip = ip0; ip <
MIN(ip0 + dip, np); ip++) {
600 float *tmp_cms, *tmp_org;
601 ALLOC(tmp_cms,
float,
603 ALLOC(tmp_org,
float,
607 t0 = omp_get_wtime();
610#pragma omp parallel for collapse(2) default(shared)
611 for (
size_t ix = 0; ix < nx; ix++)
612 for (
size_t iy = 0; iy < ny; iy++) {
613 const size_t idx =
ARRAY_2D(ix, iy, ny);
614 const double x[] = { lon[ix], lat[iy] };
616 cms_eval(cms_ptr[ip], cms_sol[ip], x, &val);
617 tmp_cms[idx] = (float) val;
618 tmp_org[idx] = array[
ARRAY_3D(ix, iy, ny, ip, np)];
622 t_eval += (omp_get_wtime() - t0);
626 ratio[ip] = cms_compression_rate(cms_ptr[ip], cms_sol[ip]);
627 bpv[ip] = 32. / ratio[ip];
629 &stddev_err[ip], &min_err[ip], &max_err[ip],
630 &nrmse[ip], &mean_org[ip], &range_org[ip]);
631 rho[ip] = gsl_stats_float_correlation(tmp_org, 1, tmp_cms, 1, nxy);
635 cr += 1.0 / cms_compression_rate(cms_ptr[ip], cms_sol[ip]);
639 cms_save_zstd_sol(cms_sol[ip], inout, 3);
641 cms_save_sol(cms_sol[ip], inout);
644 cms_delete_sol(cms_sol[ip]);
645 cms_delete_module(cms_ptr[ip]);
653 const size_t nbytes = nx * ny * np *
sizeof(float);
654 for (
size_t ip = 0; ip < np; ip++)
656 "%s %s %lu %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g\n",
657 "CMS", varname, (
unsigned long) ip, met->
p[ip], ratio[ip],
658 bpv[ip], rho[ip], mean_err[ip], stddev_err[ip], min_err[ip],
659 max_err[ip], mean_org[ip], range_org[ip], nrmse[ip], t_coars,
665 LOG(2,
"Write 3-D variable: %s"
666 " (CMS, RATIO=%g, BPV=%g, T_COMP=%g s, V_COMP=%g MiB/s,"
667 " T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
668 varname, (
double) np / cr, 32. * cr / (
double) np, t_coars,
674 cms_delete_param(cms_param);
692 double avg = 0, m2 = 0, err_min = 0, err_max = 0, rmse = 0;
693 double org_min = 0, org_max = 0;
696 for (
size_t i = 0; i < n; i++) {
697 const double err = (double) cmp[i] - (
double) org[i];
698 const double val = (double) org[i];
699 const double delta = err - avg;
701 avg += delta / ((double) i + 1.);
702 m2 += delta * (err - avg);
705 if (i == 0 || err < err_min)
707 if (i == 0 || err > err_max)
709 if (i == 0 || val < org_min)
711 if (i == 0 || val > org_max)
716 *
stddev = (n > 1 ? sqrt(m2 / ((
double) n - 1.)) : 0);
720 for (
size_t i = 0; i < n; i++)
721 *org_mean += (
double) org[i];
722 *org_mean /= (double) n;
723 *range = org_max - org_min;
724 *nrmse = ((org_max - org_min) > 0
725 ? sqrt(rmse / (
double) n) / (org_max - org_min)
736 "# $1 = compression codec name [-]\n"
737 "# $2 = variable name [-]\n"
738 "# $3 = level index [-]\n"
739 "# $4 = pressure level [hPa]\n"
740 "# $5 = compression ratio [-]\n"
741 "# $6 = bits per value [bit/value]\n"
742 "# $7 = correlation coefficient [-]\n"
743 "# $8 = mean compression error [-]\n"
744 "# $9 = standard deviation of compression error [-]\n"
745 "# $10 = minimum compression error [-]\n"
746 "# $11 = maximum compression error [-]\n"
747 "# $12 = mean value of original field [-]\n"
748 "# $13 = value range of original field [-]\n"
749 "# $14 = normalized root mean square error [-]\n"
750 "# $15 = compression time [s]\n"
751 "# $16 = compression speed [MiB/s]\n"
752 "# $17 = decompression time [s]\n"
753 "# $18 = decompression speed [MiB/s]\n\n");
768 const double t_decomp,
773 static FILE *last_out = NULL;
774 static char last_var[
LEN] =
"";
775 double mean_err, stddev_err, min_err, max_err;
776 double nrmse, mean_org, range_org, rho_out = rho;
780 &max_err, &nrmse, &mean_org, &range_org);
782 rho_out = gsl_stats_float_correlation(org, 1, cmp, 1, n);
785 if (out != last_out) {
789 if (last_var[0] !=
'\0' && strcmp(last_var, varname) != 0)
791 snprintf(last_var,
LEN,
"%s", varname);
793 "%s %s %lu %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g\n",
794 codec, varname, (
unsigned long) lev, plev, ratio, bpv, rho_out,
795 mean_err, stddev_err, min_err, max_err, mean_org, range_org, nrmse,
809 for (
size_t iz = 0; iz < nz; iz++) {
814 for (
size_t ixy = 1; ixy < nxy; ixy++)
815 for (
size_t iz = 0; iz < nz; iz++) {
816 const double value = array[ixy * nz + iz];
823 for (
size_t iz = 0; iz < nz; iz++) {
824 const double range = scl[iz] - off[iz];
825 const double ref = fmax(1.0, fmax(fabs(off[iz]), fabs(scl[iz])));
826 scl[iz] = !(range > 1e-12 * ref) ? 0.0 : range;
829#pragma omp parallel for default(shared)
830 for (
size_t ixy = 0; ixy < nxy; ixy++)
831 for (
size_t iz = 0; iz < nz; iz++)
833 array[ixy * nz + iz] =
834 (float) ((array[ixy * nz + iz] - off[iz]) / scl[iz]);
836 array[ixy * nz + iz] = 0.0f;
848#pragma omp parallel for default(shared)
849 for (
size_t ixy = 0; ixy < nxy; ixy++)
850 for (
size_t iz = 0; iz < nz; iz++)
852 array[ixy * nz + iz] =
853 (float) (array[ixy * nz + iz] * scl[iz] + off[iz]);
855 array[ixy * nz + iz] = (float) off[iz];
861 const char *varname) {
863 if (strcasecmp(varname,
"Z") == 0)
865 else if (strcasecmp(varname,
"T") == 0)
867 else if (strcasecmp(varname,
"U") == 0)
869 else if (strcasecmp(varname,
"V") == 0)
871 else if (strcasecmp(varname,
"W") == 0)
873 else if (strcasecmp(varname,
"PV") == 0)
875 else if (strcasecmp(varname,
"H2O") == 0)
877 else if (strcasecmp(varname,
"O3") == 0)
879 else if (strcasecmp(varname,
"LWC") == 0)
881 else if (strcasecmp(varname,
"RWC") == 0)
883 else if (strcasecmp(varname,
"IWC") == 0)
885 else if (strcasecmp(varname,
"SWC") == 0)
887 else if (strcasecmp(varname,
"CC") == 0)
890 ERRMSG(
"Unknown meteorological variable name!");
900 const int decompress,
904 const size_t nxy = (size_t) met->
nx * (
size_t) met->
ny;
905 const size_t nz = (size_t) met->
np;
907 double vmin[
EP], vmax[
EP], off[
EP], scl[
EP];
908 unsigned short *sarray;
909 const size_t payload_len = 2 * nz *
sizeof(
double)
910 + nxy * nz *
sizeof(
unsigned short);
911 size_t stored_len = payload_len;
914 ALLOC(sarray,
unsigned short,
924 uint64_t magic, pck_zstd_magic = UINT64_C(0x50434b5a53544431);
925 unsigned char *compr = NULL, *payload = NULL;
927 FREAD(&magic, uint64_t, 1, inout);
928 if (magic != pck_zstd_magic)
929 ERRMSG(
"PCK+ZSTD magic mismatch! Check MET_PCK_ZSTD and file type.");
930 FREAD(&stored_len,
size_t,
933 ALLOC(compr,
unsigned char,
935 FREAD(compr,
unsigned char,
938 ALLOC(payload,
unsigned char,
940 const double t0_decomp = omp_get_wtime();
941 const size_t out_len =
942 ZSTD_decompress(payload, payload_len, compr, stored_len);
943 t_zstd = omp_get_wtime() - t0_decomp;
944 if (ZSTD_isError(out_len) || out_len != payload_len)
945 ERRMSG(
"PCK ZSTD decompression failed or size mismatch!");
946 memcpy(scl, payload, nz *
sizeof(
double));
947 memcpy(off, payload + nz *
sizeof(
double), nz *
sizeof(
double));
948 memcpy(sarray, payload + 2 * nz *
sizeof(
double),
949 nxy * nz *
sizeof(
unsigned short));
953 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
962 FREAD(sarray,
unsigned short,
968 const double t0 = omp_get_wtime();
971#pragma omp parallel for default(shared)
972 for (
size_t ixy = 0; ixy < nxy; ixy++)
973 for (
size_t iz = 0; iz < nz; iz++)
975 = (
float) (sarray[ixy * nz + iz] * scl[iz] + off[iz]);
978 const double t_decomp = t_zstd + omp_get_wtime() - t0;
979 const double ratio_out =
980 (double) (nxy * nz *
sizeof(
float)) / (
double) stored_len;
981 const double bpv_out = (8. * (double) stored_len) / (double) (nxy * nz);
982 LOG(2,
"Read 3-D variable: %s"
983 " (PCK%s, RATIO=%g, BPV=%g, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
984 varname, ctl->
met_pck_zstd ?
"+ZSTD" :
"", ratio_out, bpv_out,
990 float *tmp_org, *tmp_pck;
991 double t_comp_sum = 0, t_decomp_sum = 0, t_zstd = 0, t_zstd_decomp = 0;
993 double org_mean[
EP], range[
EP];
996 ALLOC(tmp_org,
float,
998 ALLOC(tmp_pck,
float,
1002 for (
size_t iz = 0; iz < nz; iz++) {
1003 vmin[iz] = array[iz];
1004 vmax[iz] = array[iz];
1006 for (
size_t ixy = 1; ixy < nxy; ixy++)
1007 for (
size_t iz = 0; iz < nz; iz++) {
1008 if (array[ixy * nz + iz] < vmin[iz])
1009 vmin[iz] = array[ixy * nz + iz];
1010 if (array[ixy * nz + iz] > vmax[iz])
1011 vmax[iz] = array[ixy * nz + iz];
1015 for (
size_t iz = 0; iz < nz; iz++) {
1016 scl[iz] = (vmax[iz] - vmin[iz]) / 65533.;
1021 for (
size_t iz = 0; iz < nz; iz++) {
1022 const double t0 = omp_get_wtime();
1024#pragma omp parallel for default(shared)
1025 for (
size_t ixy = 0; ixy < nxy; ixy++)
1027 sarray[ixy * nz + iz] =
1028 (
unsigned short) ((array[ixy * nz + iz] - off[iz]) / scl[iz] +
1031 sarray[ixy * nz + iz] = 0;
1033 const double t_comp = omp_get_wtime() - t0;
1034 t_comp_sum += t_comp;
1036 const double t1 = omp_get_wtime();
1038#pragma omp parallel for default(shared)
1039 for (
size_t ixy = 0; ixy < nxy; ixy++) {
1040 tmp_org[ixy] = array[ixy * nz + iz];
1041 tmp_pck[ixy] = (float) (sarray[ixy * nz + iz] * scl[iz] + off[iz]);
1044 const double t_decomp = omp_get_wtime() - t1;
1045 t_decomp_sum += t_decomp;
1049 &min[iz], &max[iz], &nrmse[iz], &org_mean[iz],
1051 rho[iz] = gsl_stats_float_correlation(tmp_org, 1, tmp_pck, 1, nxy);
1058 uint64_t pck_zstd_magic = UINT64_C(0x50434b5a53544431);
1059 unsigned char *payload = NULL, *payload_chk = NULL;
1060 void *stored_data = NULL;
1061 ALLOC(payload,
unsigned char,
1063 memcpy(payload, scl, nz *
sizeof(
double));
1064 memcpy(payload + nz *
sizeof(
double), off, nz *
sizeof(
double));
1065 memcpy(payload + 2 * nz *
sizeof(
double), sarray,
1066 nxy * nz *
sizeof(
unsigned short));
1067 const size_t dst_cap = ZSTD_compressBound(payload_len);
1068 ALLOC(stored_data,
char,
1070 ZSTD_CCtx *cctx = ZSTD_createCCtx();
1072 ERRMSG(
"Cannot create ZSTD context!");
1074 (ZSTD_CCtx_setParameter
1076 ERRMSG(
"Cannot set ZSTD compression level!");
1078 (ZSTD_CCtx_setParameter
1080 ERRMSG(
"Cannot set ZSTD worker count!");
1081 const double t0_comp = omp_get_wtime();
1083 ZSTD_compress2(cctx, stored_data, dst_cap, payload, payload_len);
1084 t_zstd = omp_get_wtime() - t0_comp;
1085 ZSTD_freeCCtx(cctx);
1086 if (ZSTD_isError(stored_len))
1087 ERRMSG(
"PCK ZSTD compression failed!");
1088 ALLOC(payload_chk,
unsigned char,
1090 const double t0_decomp2 = omp_get_wtime();
1091 const size_t out_len2 =
1092 ZSTD_decompress(payload_chk, payload_len, stored_data, stored_len);
1093 t_zstd_decomp = omp_get_wtime() - t0_decomp2;
1094 if (ZSTD_isError(out_len2) || out_len2 != payload_len)
1095 ERRMSG(
"PCK ZSTD decompression failed or size mismatch!");
1098 FWRITE(&pck_zstd_magic, uint64_t, 1, inout);
1099 FWRITE(&stored_len,
size_t,
1102 FWRITE(stored_data,
unsigned char,
1107 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
1116 FWRITE(sarray,
unsigned short,
1122 const double ratio_out =
1123 (double) (nxy * nz *
sizeof(
float)) / (
double) stored_len;
1124 const double bpv_out = (8. * (double) stored_len) / (double) (nxy * nz);
1125 const double t_comp = t_comp_sum + t_zstd;
1126 const double t_decomp = t_decomp_sum + t_zstd_decomp;
1127 LOG(2,
"Write 3-D variable: %s"
1128 " (PCK%s, RATIO=%g, BPV=%g, T_COMP=%g s, V_COMP=%g MiB/s,"
1129 " T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1130 varname, ctl->
met_pck_zstd ?
"+ZSTD" :
"", ratio_out, bpv_out, t_comp,
1136 const double t_comp_level = t_comp / (double) nz;
1137 const double t_decomp_level = t_decomp / (double) nz;
1138 for (
size_t iz = 0; iz < nz; iz++)
1140 "%s %s %lu %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g\n",
1142 (
unsigned long) iz, met->
p[iz], ratio_out, bpv_out, rho[iz],
1143 mean[iz],
stddev[iz], min[iz], max[iz], org_mean[iz],
1144 range[iz], nrmse[iz], t_comp_level,
1165 const char *varname,
1167 const int decompress,
1176 ERRMSG(
"Exactly one of precision or tolerance must be set for SZ3!");
1178 size_t r1 = (size_t) met->
np, r2 = (
size_t) met->
ny, r3 = (size_t) met->
nx,
1179 outSize = 0, total_elems = r1 * r2 * r3;
1181 unsigned char *bytes = NULL;
1182 double *scale_off = NULL, *scale_scl = NULL;
1183 float *orig_all = NULL;
1188 int stored_lossy_scale;
1189 FREAD(&stored_lossy_scale,
int,
1192 if (stored_lossy_scale < 0 || stored_lossy_scale > 1)
1193 ERRMSG(
"Invalid stored MET_LOSSY_SCALE flag!");
1194 if (stored_lossy_scale > 0) {
1195 ALLOC(scale_off,
double,
1197 ALLOC(scale_scl,
double,
1199 FREAD(scale_off,
double,
1202 FREAD(scale_scl,
double,
1208 FREAD(&sz3size,
size_t,
1213 FREAD(bytes,
unsigned char,
1217 const double t0 = omp_get_wtime();
1218 void *outData = SZ_decompress(SZ_FLOAT, bytes, sz3size, 0, 0, r3, r2, r1);
1220 ERRMSG(
"Decompression failed!");
1222 memcpy(array, outData, total_elems *
sizeof(
float));
1223 if (stored_lossy_scale > 0)
1225 const double t_decomp = omp_get_wtime() - t0;
1230 LOG(2,
"Read 3-D variable: %s"
1231 " (SZ3, PREC=%d, TOL=%g, SCALE=%d, RATIO=%g, BPV=%g, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1234 (
double) (total_elems *
sizeof(
float)) / (
double) sz3size,
1235 (8. * (
double) sz3size) / (
double) total_elems, t_decomp,
1241 const int errBoundMode = (ctl->
met_sz3_prec[metvar] > 0) ? REL : ABS;
1246 ALLOC(scale_off,
double,
1248 ALLOC(scale_scl,
double,
1251 ALLOC(orig_all,
float,
1253 memcpy(orig_all, array, total_elems *
sizeof(
float));
1256 FWRITE(scale_off,
double,
1259 FWRITE(scale_scl,
double,
1263 const double absBound =
1264 (errBoundMode == ABS) ? ctl->
met_sz3_tol[metvar] : 0.0;
1265 const double relBound = (errBoundMode == REL) ? pow(2.0,
1271 const double t0 = omp_get_wtime();
1272 bytes = SZ_compress_args(SZ_FLOAT, array, &outSize,
1273 errBoundMode, absBound, relBound, 0.0,
1275 const double t_comp = omp_get_wtime() - t0;
1276 if (!bytes || outSize == 0)
1277 ERRMSG(
"Compression failed!");
1282 FWRITE(bytes,
unsigned char,
1286 double t_decomp = NAN;
1288 unsigned char *bytes_copy;
1291 ALLOC(bytes_copy,
unsigned char,
1293 memcpy(bytes_copy, bytes, outSize);
1295 const double t1 = omp_get_wtime();
1296 void *decData = SZ_decompress(SZ_FLOAT, bytes_copy, outSize, 0, 0, r3,
1298 t_decomp = omp_get_wtime() - t1;
1300 ERRMSG(
"Decompression failed!");
1302 float *tmp_all, *tmp_org, *tmp_sz3;
1303 const size_t nxy = r2 * r3;
1305 ALLOC(tmp_all,
float,
1307 ALLOC(tmp_org,
float,
1309 ALLOC(tmp_sz3,
float,
1311 memcpy(tmp_all, decData, total_elems *
sizeof(
float));
1316 for (
size_t lev = 0; lev < r1; lev++) {
1319#pragma omp parallel for default(shared)
1320 for (
size_t ixy = 0; ixy < nxy; ixy++) {
1321 tmp_org[ixy] = (orig_all ? orig_all : array)[ixy * r1 + lev];
1322 tmp_sz3[ixy] = tmp_all[ixy * r1 + lev];
1325 (
double) (total_elems *
sizeof(
float))
1327 (8. * (
double) outSize) / (
double) total_elems,
1328 NAN, t_comp, t_decomp, nxy,
1329 total_elems *
sizeof(
float), tmp_org, tmp_sz3);
1338 LOG(2,
"Write 3-D variable: %s"
1339 " (SZ3, PREC=%d, TOL=%g, SCALE=%d, RATIO=%g, BPV=%g, T_COMP=%g s, V_COMP=%g MiB/s,"
1340 " T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1343 (
double) (total_elems *
sizeof(
float)) / (
double) outSize,
1344 (8. * (
double) outSize) / (
double) total_elems, t_comp,
1348 LOG(2,
"Write 3-D variable: %s"
1349 " (SZ3, PREC=%d, TOL=%g, SCALE=%d, RATIO=%g, BPV=%g, T_COMP=%g s, V_COMP=%g MiB/s)",
1352 (
double) (total_elems *
sizeof(
float)) / (
double) outSize,
1353 (8. * (
double) outSize) / (
double) total_elems, t_comp,
1370 const char *varname,
1372 const int decompress,
1380 const size_t snx = (size_t) met->
np;
1381 const size_t sny = (
size_t) met->
ny;
1382 const size_t snz = (size_t) met->
nx;
1383 const zfp_type type = zfp_type_float;
1384 zfp_field *field = zfp_field_3d(array, type, snx, sny, snz);
1387 zfp_stream *zfp = zfp_stream_open(NULL);
1389 ERRMSG(
"Failed to allocate zfp structures!");
1392 int actual_prec = 0;
1393 double actual_tol = 0;
1396 ERRMSG(
"Exactly one of precision or tolerance must be set for zfp!");
1398 actual_prec = (int) zfp_stream_set_precision(zfp, (
unsigned int)
1401 actual_tol = zfp_stream_set_accuracy(zfp, ctl->
met_zfp_tol[metvar]);
1404 const size_t bufsize = zfp_stream_maximum_size(zfp, field);
1410 bitstream *stream = stream_open(buffer, bufsize);
1411 zfp_stream_set_bit_stream(zfp, stream);
1412 zfp_stream_rewind(zfp);
1416 double *scale_off = NULL, *scale_scl = NULL;
1418 int stored_lossy_scale;
1419 FREAD(&stored_lossy_scale,
int,
1422 if (stored_lossy_scale < 0 || stored_lossy_scale > 1)
1423 ERRMSG(
"Invalid stored MET_LOSSY_SCALE flag!");
1424 if (stored_lossy_scale > 0) {
1425 ALLOC(scale_off,
double,
1427 ALLOC(scale_scl,
double,
1429 FREAD(scale_off,
double,
1432 FREAD(scale_scl,
double,
1436 FREAD(&zfpsize,
size_t,
1439 if (zfpsize > bufsize)
1440 ERRMSG(
"Compressed data size exceeds allocated buffer!");
1441 FREAD(buffer,
unsigned char,
1444 const double t0 = omp_get_wtime();
1445 if (!zfp_decompress(zfp, field))
1446 ERRMSG(
"Decompression failed!");
1447 if (stored_lossy_scale > 0)
1449 const double t_decomp = omp_get_wtime() - t0;
1451 ((double) (snx * sny * snz *
sizeof(
float))) / (double) zfpsize;
1452 const double bpv = (8.0 * (double) zfpsize) / (double) (snx * sny * snz);
1454 "Read 3-D variable: %s"
1455 " (ZFP, PREC=%d, TOL=%g, SCALE=%d, RATIO=%g, BPV=%g, T_DECOMP=%g s,"
1456 " V_DECOMP=%g MiB/s)",
1457 varname, actual_prec, actual_tol, stored_lossy_scale, cr, bpv,
1458 t_decomp,
COMPRESS_SPEED(snx * sny * snz *
sizeof(
float), t_decomp));
1463 float *tmp_all, *tmp_org, *tmp_zfp, *orig_all = NULL;
1464 const size_t nxy = sny * snz;
1470 ALLOC(scale_off,
double,
1472 ALLOC(scale_scl,
double,
1475 ALLOC(orig_all,
float,
1477 memcpy(orig_all, array, snx * sny * snz *
sizeof(
float));
1480 FWRITE(scale_off,
double,
1483 FWRITE(scale_scl,
double,
1488 ALLOC(tmp_all,
float,
1490 ALLOC(tmp_org,
float,
1492 ALLOC(tmp_zfp,
float,
1495 const double t0 = omp_get_wtime();
1496 zfpsize = zfp_compress(zfp, field);
1497 const double t_comp = omp_get_wtime() - t0;
1499 ERRMSG(
"Compression failed!");
1504 FWRITE(buffer,
unsigned char,
1509 zfp_field *dec_field = zfp_field_3d(tmp_all, type, snx, sny, snz);
1511 ERRMSG(
"Failed to allocate zfp structures!");
1513 const double t1 = omp_get_wtime();
1514 zfp_stream_rewind(zfp);
1515 if (!zfp_decompress(zfp, dec_field))
1516 ERRMSG(
"Decompression failed!");
1519 const double t_decomp = omp_get_wtime() - t1;
1521 for (
size_t lev = 0; lev < snx; lev++) {
1524#pragma omp parallel for default(shared)
1525 for (
size_t ixy = 0; ixy < nxy; ixy++) {
1526 tmp_org[ixy] = (orig_all ? orig_all : array)[ixy * snx + lev];
1527 tmp_zfp[ixy] = tmp_all[ixy * snx + lev];
1531 ((
double) (snx * sny * snz *
sizeof(
float)))
1532 / (
double) zfpsize, (8.0 * (
double) zfpsize)
1533 / (
double) (snx * sny * snz),
1534 NAN, t_comp, t_decomp, nxy,
1535 snx * sny * snz *
sizeof(
float), tmp_org, tmp_zfp);
1539 ((double) (snx * sny * snz *
sizeof(
float))) / (double) zfpsize;
1540 const double bpv = (8.0 * (double) zfpsize) / (double) (snx * sny * snz);
1542 "Write 3-D variable: %s"
1543 " (ZFP, PREC=%d, TOL=%g, SCALE=%d, RATIO=%g, BPV=%g, T_COMP=%g s,"
1544 " V_COMP=%g MiB/s, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1546 bpv, t_comp,
COMPRESS_SPEED(snx * sny * snz *
sizeof(
float), t_comp),
1547 t_decomp,
COMPRESS_SPEED(snx * sny * snz *
sizeof(
float), t_decomp));
1553 zfp_field_free(dec_field);
1560 zfp_field_free(field);
1561 stream_close(stream);
1562 zfp_stream_close(zfp);
1573 const char *varname,
1575 const int decompress,
1580 const size_t nxy = (size_t) met->
nx * (
size_t) met->
ny;
1581 const size_t nz = (size_t) met->
np;
1582 const size_t n = nxy * nz, uncomprLen = n *
sizeof(
float);
1583 size_t compsize, comprLen = ZSTD_compressBound(uncomprLen);
1586 char *compr, *uncompr = (
char *) array;
1592 FREAD(&comprLen,
size_t,
1595 FREAD(compr,
unsigned char,
1598 const double t0 = omp_get_wtime();
1599 compsize = ZSTD_decompress(uncompr, uncomprLen, compr, comprLen);
1600 const double t_decomp = omp_get_wtime() - t0;
1601 if (ZSTD_isError(compsize) || compsize != uncomprLen)
1602 ERRMSG(
"Decompression failed or size mismatch!");
1603 LOG(2,
"Read 3-D variable: %s"
1604 " (ZSTD, LEVEL=%d, RATIO=%g, BPV=%g, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1606 ((
double) uncomprLen) / (
double) comprLen,
1607 (8. * (
double) comprLen) / (
double) n, t_decomp,
1613 float *tmp_org, *tmp_zstd, *tmp_all;
1616 ALLOC(tmp_org,
float,
1618 ALLOC(tmp_zstd,
float,
1620 ALLOC(tmp_all,
float,
1623 cctx = ZSTD_createCCtx();
1625 ERRMSG(
"Cannot create ZSTD context!");
1627 if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel,
1629 ERRMSG(
"Cannot set ZSTD compression level!");
1631 if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers,
1633 ERRMSG(
"Cannot set ZSTD worker count!");
1635 const double t0 = omp_get_wtime();
1636 compsize = ZSTD_compress2(cctx, compr, comprLen, uncompr, uncomprLen);
1637 const double t_comp = omp_get_wtime() - t0;
1638 if (ZSTD_isError(compsize)) {
1639 ZSTD_freeCCtx(cctx);
1640 ERRMSG(
"Compression failed!");
1642 FWRITE(&compsize,
size_t,
1645 FWRITE(compr,
unsigned char,
1650 const double t1 = omp_get_wtime();
1651 const size_t decomp_size = ZSTD_decompress(tmp_all, uncomprLen, compr,
1653 const double t_decomp = omp_get_wtime() - t1;
1654 if (ZSTD_isError(decomp_size) || decomp_size != uncomprLen)
1655 ERRMSG(
"Decompression failed or size mismatch!");
1657 for (
size_t lev = 0; lev < nz; lev++) {
1660#pragma omp parallel for default(shared)
1661 for (
size_t ixy = 0; ixy < nxy; ixy++) {
1662 tmp_org[ixy] = array[ixy * nz + lev];
1663 tmp_zstd[ixy] = tmp_all[ixy * nz + lev];
1667 ((
double) uncomprLen) / (
double) compsize,
1668 (8. * (
double) compsize) / (
double) n,
1669 NAN, t_comp, t_decomp, nxy, uncomprLen, tmp_org,
1673 LOG(2,
"Write 3-D variable: %s"
1674 " (ZSTD, LEVEL=%d, NWORKERS=%d, RATIO=%g, BPV=%g, T_COMP=%g s,"
1676 " T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1678 ((
double) uncomprLen) / (
double) compsize,
1679 (8. * (
double) compsize) / (
double) n, t_comp,
1683 ZSTD_freeCCtx(cctx);
1700 const char *varname,
1702 const int decompress,
1707 const size_t nxy = (size_t) met->
nx * (
size_t) met->
ny;
1708 const size_t nz = (size_t) met->
np;
1709 const size_t n = nxy * nz;
1710 const size_t uncomprLen = n *
sizeof(
float);
1711 if (uncomprLen > (
size_t) INT_MAX)
1712 ERRMSG(
"LZ4 input buffer exceeds INT_MAX!");
1713 const int uncomprLenInt = (int) uncomprLen;
1715 const int comprCapInt = LZ4_compressBound(uncomprLenInt);
1716 if (comprCapInt <= 0)
1717 ERRMSG(
"Cannot determine LZ4 compression bound!");
1718 size_t comprLen = (size_t) comprCapInt;
1721 char *compr, *uncompr = (
char *) array;
1727 FREAD(&comprLen,
size_t,
1730 if (comprLen > (
size_t) INT_MAX)
1731 ERRMSG(
"LZ4 compressed buffer exceeds INT_MAX!");
1732 FREAD(compr,
unsigned char,
1735 const double t0 = omp_get_wtime();
1736 const int decomp_size =
1737 LZ4_decompress_safe(compr, uncompr, (
int) comprLen, uncomprLenInt);
1738 const double t_decomp = omp_get_wtime() - t0;
1739 if (decomp_size != uncomprLenInt)
1740 ERRMSG(
"Decompression failed or size mismatch!");
1741 LOG(2,
"Read 3-D variable: %s"
1742 " (LZ4, ACCEL=%d, RATIO=%g, BPV=%g, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1743 varname, accel, ((
double) uncomprLen) / (
double) comprLen,
1744 (8. * (
double) comprLen) / (
double) n, t_decomp,
1750 float *tmp_org, *tmp_lz4, *tmp_all;
1752 ALLOC(tmp_org,
float,
1754 ALLOC(tmp_lz4,
float,
1756 ALLOC(tmp_all,
float,
1759 const double t0 = omp_get_wtime();
1760 const int compsizeInt =
1761 LZ4_compress_fast(uncompr, compr, uncomprLenInt, comprCapInt, accel);
1762 const double t_comp = omp_get_wtime() - t0;
1763 if (compsizeInt <= 0)
1764 ERRMSG(
"Compression failed!");
1765 const size_t compsize = (size_t) compsizeInt;
1766 FWRITE(&compsize,
size_t,
1769 FWRITE(compr,
unsigned char,
1773 const double t1 = omp_get_wtime();
1774 const int decomp_size =
1775 LZ4_decompress_safe(compr, (
char *) tmp_all, compsizeInt,
1777 const double t_decomp = omp_get_wtime() - t1;
1778 if (decomp_size != uncomprLenInt)
1779 ERRMSG(
"Decompression failed or size mismatch!");
1781 for (
size_t lev = 0; lev < nz; lev++) {
1784#pragma omp parallel for default(shared)
1785 for (
size_t ixy = 0; ixy < nxy; ixy++) {
1786 tmp_org[ixy] = array[ixy * nz + lev];
1787 tmp_lz4[ixy] = tmp_all[ixy * nz + lev];
1791 ((
double) uncomprLen) / (
double) compsize,
1792 (8. * (
double) compsize) / (
double) n,
1793 NAN, t_comp, t_decomp, nxy, uncomprLen, tmp_org,
1797 LOG(2,
"Write 3-D variable: %s"
1798 " (LZ4, ACCEL=%d, RATIO=%g, BPV=%g, T_COMP=%g s, V_COMP=%g MiB/s,"
1799 " T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1800 varname, accel, ((
double) uncomprLen) / (
double) compsize,
1801 (8. * (
double) compsize) / (
double) n, t_comp,
1823 const double D = sec / 86400 - 0.5;
1826 const double g =
DEG2RAD(357.529 + 0.98560028 * D);
1827 const double q = 280.459 + 0.98564736 * D;
1828 const double L =
DEG2RAD(q + 1.915 * sin(g) + 0.020 * sin(2 * g));
1831 const double e =
DEG2RAD(23.439 - 0.00000036 * D);
1834 const double sindec = sin(e) * sin(L);
1837 const double ra = atan2(cos(e) * sin(L), cos(L));
1840 const double GMST = 18.697374558 + 24.06570982441908 * D;
1843 const double LST = GMST + lon / 15;
1846 const double h = LST / 12 * M_PI - ra;
1849 const double lat_help =
DEG2RAD(lat);
1852 return sin(lat_help) * sindec + cos(lat_help) * sqrt(1 -
1853 SQR(sindec)) * cos(h);
1865 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
1866 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
1869 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
1870 *doy = d0l[mon - 1] + day - 1;
1872 *doy = d0[mon - 1] + day - 1;
1889 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
1898 const int ix0 = zonal_rank * nx_block;
1899 const int iy0 = merid_rank * ny_block;
1901 const int ix1 = ix0 + nx_block
1905 const int iy1 = iy0 + ny_block
1911#pragma acc update device(dd->nx_glob, dd->ny_glob, \
1912 dd->lon_glob[:dd->nx_glob], \
1913 dd->lat_glob[:dd->ny_glob])
1914#pragma acc data present(atm, ctl, dd)
1915#pragma acc parallel loop independent gang vector
1917 for (
int ip = 0; ip < atm->
np; ip++) {
1924 double lon = atm->
lon[ip];
1925 double lat = atm->
lat[ip];
1931 const int inside = (ix >= ix0 && ix < ix1 && iy >= iy0 && iy < iy1);
1966 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
1970#pragma acc enter data create(npart, particles[:npart])
1971#pragma acc update device(npart, particles[:npart])
1972#pragma acc parallel loop present(atm, ctl, particles, cache, npart)
1974 for (
int ip = atm->
np; ip < atm->np + npart; ip++)
1979 particles[ip - atm->
np].
time = atm->
time[ip];
1980 particles[ip - atm->
np].
lon = atm->
lon[ip];
1981 particles[ip - atm->
np].
lat = atm->
lat[ip];
1982 particles[ip - atm->
np].
p = atm->
p[ip];
1983 for (
int iq = 0; iq < ctl->
nq; iq++)
1984 particles[ip - atm->
np].q[iq] = atm->
q[iq][ip];
1990#pragma acc update host( particles[:npart])
1991#pragma acc exit data delete(npart, particles)
2014 int zonal_rank = ix / nx_block;
2020 int merid_rank = iy / ny_block;
2043 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
2044 MPI_Comm_size(MPI_COMM_WORLD, &size);
2046 int *send_counts, *recv_counts;
2047 int *send_displs, *recv_displs;
2053 ALLOC(send_counts,
int,
2055 ALLOC(recv_counts,
int,
2057 ALLOC(send_displs,
int,
2059 ALLOC(recv_displs,
int,
2065#pragma omp parallel for
2066 for (
int ip = 0; ip < *npart; ip++) {
2070 if (dest < 0 || dest >= size)
2071 ERRMSG(
"Invalid destination rank!");
2073 send_counts[dest]++;
2078 for (
int i = 0; i < size; i++) {
2079 send_displs[i] = nsend;
2080 nsend += send_counts[i];
2084 MPI_Alltoall(send_counts, 1, MPI_INT,
2085 recv_counts, 1, MPI_INT, MPI_COMM_WORLD);
2089 for (
int i = 0; i < size; i++) {
2090 recv_displs[i] = nrecv;
2091 nrecv += recv_counts[i];
2097 for (
int i = 0; i < size; i++)
2098 offsets[i] = send_displs[i];
2101 for (
int ip = 0; ip < *npart; ip++) {
2105 memcpy(&sendbuf[offsets[dest]], &(*particles)[ip],
sizeof(
particle_t));
2110 MPI_Alltoallv(sendbuf,
2115 recv_counts, recv_displs, dd->MPI_Particle, MPI_COMM_WORLD);
2118 if (nrecv > *capacity) {
2119 const int newcap = nrecv + nrecv / 2 + 1;
2121 realloc(*particles, (
size_t) newcap *
sizeof(
particle_t));
2123 ERRMSG(
"Out of memory!");
2129#pragma omp parallel for
2130 for (
int ip = 0; ip < nrecv; ip++) {
2131 (*particles)[ip] = recvbuf[ip];
2160 MPI_Comm_size(MPI_COMM_WORLD, &size);
2162 ERRMSG(
"Number of tasks and subdomains is not identical!");
2165 const MPI_Datatype types[5] =
2166 { MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE };
2167 const int blocklengths[5] = { 1, 1, 1, 1,
NQ };
2168 const MPI_Aint displacements[5] =
2173 MPI_Type_create_struct(5, blocklengths, displacements, types,
2175 MPI_Type_commit(&dd->MPI_Particle);
2190 const double lon_min = (dd->
lon_glob[0] < 0) ? -180.0 : 0.0;
2193 *lon =
FMOD(*lon - lon_min, 360.0);
2200 *lat = 180.0 - *lat;
2202 }
else if (*lat < -90.0) {
2203 *lat = -180.0 - *lat;
2208 *lon =
FMOD(*lon - lon_min, 360.0);
2233 if (atm->
np + npart >
NP)
2234 ERRMSG(
"Too many particles. Increase NP!");
2237#pragma acc enter data create(npart, particles[:npart])
2238#pragma acc update device(particles[:npart], npart)
2239#pragma acc data present(atm, ctl, cache, particles, npart)
2240#pragma acc parallel loop
2242 for (
int ip = atm->
np; ip < atm->np + npart; ip++) {
2243 atm->
time[ip] = particles[ip - atm->
np].
time;
2244 atm->
lon[ip] = particles[ip - atm->
np].
lon;
2245 atm->
lat[ip] = particles[ip - atm->
np].
lat;
2246 atm->
p[ip] = particles[ip - atm->
np].
p;
2247 for (
int iq = 0; iq < ctl->
nq; iq++)
2248 atm->
q[iq][ip] = particles[ip - atm->
np].q[iq];
2252#pragma acc exit data delete(npart, particles)
2258#pragma acc update device(atm->np)
2275 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
2278 int device_counter = 0;
2279 int *device_counter_ptr = (
int *) acc_malloc(
sizeof(
int));
2280 if (device_counter_ptr == NULL) {
2281 ERRMSG(
"Failed to allocate device counter memory!");
2283 acc_memcpy_to_device(device_counter_ptr, &device_counter,
sizeof(
int));
2286#pragma acc parallel loop present(atm, cache) deviceptr(device_counter_ptr)
2287 for (
int ip = 0; ip < atm->
np; ip++) {
2293#pragma acc atomic capture
2295 local_idx = *device_counter_ptr;
2296 (*device_counter_ptr)++;
2299 int global_index = atm->
np + local_idx;
2302 atm->
time[global_index] = atm->
time[ip];
2303 atm->
p[global_index] = atm->
p[ip];
2304 atm->
lon[global_index] = atm->
lon[ip];
2305 atm->
lat[global_index] = atm->
lat[ip];
2308 for (
int iq = 0; iq <
NQ; iq++) {
2309 atm->
q[iq][global_index] = atm->
q[iq][ip];
2317 cache->
dt[global_index] = cache->
dt[ip];
2323 acc_memcpy_from_device(npart, device_counter_ptr,
sizeof(
int));
2324 acc_free(device_counter_ptr);
2342 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
2345 const int np = atm->
np;
2346 double amax = (met0->
nx * met0->
ny + met0->
ny) * met0->
np + met0->
np;
2348#pragma acc enter data create(amax)
2349#pragma acc update device(amax)
2350#pragma acc data present(ctl,met0,atm,dd,amax)
2355#pragma acc parallel loop independent gang vector
2357#pragma omp parallel for default(shared)
2359 for (
int ip = 0; ip < np; ip++) {
2367 dd->sort_key[ip] = amax + 1;
2369 dd->sort_key[ip] = amax + 2;
2377#pragma acc host_data use_device(dd->sort_key, dd->perm)
2379 thrustSortWrapper(dd->sort_key, np, dd->perm);
2381 size_t *perm_sz = (
size_t *) malloc((
size_t) np *
sizeof(size_t));
2382 if (perm_sz == NULL)
2383 ERRMSG(
"Out of memory!");
2385#pragma acc update self(dd->sort_key[0:np])
2387 gsl_sort_index(perm_sz, dd->sort_key, 1, (
size_t) np);
2388 for (
int ip = 0; ip < np; ++ip)
2389 dd->perm[ip] = (
int) perm_sz[ip];
2392#pragma acc update device(dd->perm[0:np])
2401 for (
int iq = 0; iq < ctl->
nq; iq++)
2407#pragma acc parallel loop reduction(+:nkeep) present(atm, ctl)
2409 for (
int ip = 0; ip < np; ip++)
2417#pragma acc parallel loop reduction(+:nsend) present(atm, ctl)
2419 for (
int ip = nkeep; ip < np; ip++)
2429 for (
int ip = 0; ip < np; ip++)
2435 (
"Rank %d: %d particles have subdomain index -1 and will be lost (kept: %d, to_send: %d, total_before: %d)",
2436 rank, nlost, nkeep, nsend, np);
2440#pragma acc update device(atm->np)
2445#pragma acc exit data delete(amax)
2460#pragma acc data present(dd,a)
2461#pragma acc parallel loop independent gang vector
2463#pragma omp parallel for default(shared)
2465 for (
int ip = 0; ip < np; ip++)
2466 dd->tmp[ip] = a[dd->perm[ip]];
2468#pragma acc parallel loop independent gang vector
2470#pragma omp parallel
for default(shared)
2472 for (
int ip = 0; ip < np; ip++)
2473 a[ip] = dd->tmp[ip];
2486 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
2487 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
2492 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
2493 for (i = 11; i > 0; i--)
2497 *day = doy - d0l[i] + 1;
2499 for (i = 11; i > 0; i--)
2503 *day = doy - d0[i] + 1;
2514 double data[2 *
EX];
2518 ERRMSG(
"Too many data points!");
2521 gsl_fft_complex_wavetable *wavetable =
2522 gsl_fft_complex_wavetable_alloc((
size_t) n);
2523 gsl_fft_complex_workspace *workspace =
2524 gsl_fft_complex_workspace_alloc((
size_t) n);
2527 for (
int i = 0; i < n; i++) {
2528 data[2 * i] = fcReal[i];
2529 data[2 * i + 1] = fcImag[i];
2533 gsl_fft_complex_forward(data, 1, (
size_t) n, wavetable, workspace);
2536 for (
int i = 0; i < n; i++) {
2537 fcReal[i] = data[2 * i];
2538 fcImag[i] = data[2 * i + 1];
2542 gsl_fft_complex_wavetable_free(wavetable);
2543 gsl_fft_complex_workspace_free(workspace);
2554 const double radius = z +
RE;
2555 const double latrad =
DEG2RAD(lat);
2556 const double lonrad =
DEG2RAD(lon);
2557 const double coslat = cos(latrad);
2559 x[0] = radius * coslat * cos(lonrad);
2560 x[1] = radius * coslat * sin(lonrad);
2561 x[2] = radius * sin(latrad);
2570 const char *metbase,
2571 const double dt_met,
2578 int year, mon, day, hour, min, sec;
2582 t6 = floor(t / dt_met) * dt_met;
2584 t6 = ceil(t / dt_met) * dt_met;
2587 jsec2time(t6, &year, &mon, &day, &hour, &min, &sec, &r);
2592 sprintf(filename,
"%s_YYYY_MM_DD_HH.nc", metbase);
2594 sprintf(filename,
"%s_YYYY_MM_DD_HH.bin", metbase);
2596 sprintf(filename,
"%s_YYYY_MM_DD_HH.pck", metbase);
2598 sprintf(filename,
"%s_YYYY_MM_DD_HH.zfp", metbase);
2600 sprintf(filename,
"%s_YYYY_MM_DD_HH.zstd", metbase);
2602 sprintf(filename,
"%s_YYYY_MM_DD_HH.cms", metbase);
2604 sprintf(filename,
"%s_YYYY_MM_DD_HH.sz3", metbase);
2606 sprintf(filename,
"%s_YYYY_MM_DD_HH.lz4", metbase);
2607 sprintf(repl,
"%d", year);
2609 sprintf(repl,
"%02d", mon);
2611 sprintf(repl,
"%02d", day);
2613 sprintf(repl,
"%02d", hour);
2619 sprintf(filename,
"%s_YYMMDDHH.nc", metbase);
2620 sprintf(repl,
"%d", year);
2622 sprintf(repl,
"%02d", year % 100);
2624 sprintf(repl,
"%02d", mon);
2626 sprintf(repl,
"%02d", day);
2628 sprintf(repl,
"%02d", hour);
2643 for (
int i = 0; i < 3; i++) {
2647 if (!(ch = strstr(orig, search)))
2649 strncpy(buffer, orig, (
size_t) (ch - orig));
2650 buffer[ch - orig] = 0;
2651 sprintf(buffer + (ch - orig),
"%s%s", repl, ch + strlen(search));
2653 strcpy(orig, buffer);
2660 const int met_tropo,
2680#pragma omp parallel for default(shared) private(ci,cw)
2681 for (
int ix = 0; ix < nx; ix++)
2682 for (
int iy = 0; iy < ny; iy++) {
2684 &pt[iy * nx + ix], ci, cw, 1);
2686 &ps[iy * nx + ix], ci, cw, 0);
2688 &zs[iy * nx + ix], ci, cw, 0);
2690 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
2692 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
2694 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
2696 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
2713 *lon2 =
FMOD(lon, 360.);
2714 if (*lon2 < lons[0])
2716 else if (*lon2 > lons[nlon - 1])
2721 if (lats[0] < lats[nlat - 1])
2722 *lat2 =
MIN(
MAX(*lat2, lats[0]), lats[nlat - 1]);
2724 *lat2 =
MIN(
MAX(*lat2, lats[nlat - 1]), lats[0]);
2740 if (lons[0] < lons[nlon - 1])
2741 *lon2 =
MIN(
MAX(lon, lons[0]), lons[nlon - 1]);
2743 *lon2 =
MIN(
MAX(lon, lons[nlon - 1]), lons[0]);
2746 if (lats[0] < lats[nlat - 1])
2747 *lat2 =
MIN(
MAX(lat, lats[0]), lats[nlat - 1]);
2749 *lat2 =
MIN(
MAX(lat, lats[nlat - 1]), lats[0]);
2757 float heights0[
EX][
EY][
EP],
2758 float array0[
EX][
EY][
EP],
2760 float heights1[
EX][
EY][
EP],
2761 float array1[
EX][
EY][
EP],
2763 const double height,
2794 int k_max = ind[0][0];
2795 for (
int i = 0; i < 2; i++)
2796 for (
int j = 0; j < 4; j++) {
2797 if (ci[2] > ind[i][j])
2799 if (k_max < ind[i][j])
2805 cw[0] = (lon2 - met0->
lon[ci[0]]) /
2806 (met0->
lon[ci[0] + 1] - met0->
lon[ci[0]]);
2807 cw[1] = (lat2 - met0->
lat[ci[1]]) /
2808 (met0->
lat[ci[1] + 1] - met0->
lat[ci[1]]);
2811 double height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2]]
2812 - heights0[ci[0]][ci[1]][ci[2]])
2813 + heights0[ci[0]][ci[1]][ci[2]];
2814 double height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2]]
2815 - heights0[ci[0]][ci[1] + 1][ci[2]])
2816 + heights0[ci[0]][ci[1] + 1][ci[2]];
2817 double height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2]]
2818 - heights0[ci[0] + 1][ci[1]][ci[2]])
2819 + heights0[ci[0] + 1][ci[1]][ci[2]];
2820 double height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2]]
2821 - heights0[ci[0] + 1][ci[1] + 1][ci[2]])
2822 + heights0[ci[0] + 1][ci[1] + 1][ci[2]];
2825 double height0 = cw[1] * (height01 - height00) + height00;
2826 double height1 = cw[1] * (height11 - height10) + height10;
2829 double height_bot = cw[0] * (height1 - height0) + height0;
2832 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
2833 - heights0[ci[0]][ci[1]][ci[2] + 1])
2834 + heights0[ci[0]][ci[1]][ci[2] + 1];
2835 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
2836 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
2837 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
2838 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
2839 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
2840 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
2841 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2842 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2843 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2846 height0 = cw[1] * (height01 - height00) + height00;
2847 height1 = cw[1] * (height11 - height10) + height10;
2850 double height_top = cw[0] * (height1 - height0) + height0;
2853 while (((heights0[0][0][0] > heights0[0][0][1]) &&
2854 ((height_bot <= height) || (height_top > height))
2855 && (height_bot >= height) && (ci[2] < k_max))
2857 ((heights0[0][0][0] < heights0[0][0][1]) &&
2858 ((height_bot >= height) || (height_top < height))
2859 && (height_bot <= height) && (ci[2] < k_max))
2863 height_bot = height_top;
2866 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
2867 - heights0[ci[0]][ci[1]][ci[2] + 1])
2868 + heights0[ci[0]][ci[1]][ci[2] + 1];
2869 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
2870 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
2871 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
2872 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
2873 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
2874 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
2875 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2876 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2877 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2880 height0 = cw[1] * (height01 - height00) + height00;
2881 height1 = cw[1] * (height11 - height10) + height10;
2884 height_top = cw[0] * (height1 - height0) + height0;
2888 cw[2] = (height - height_bot)
2889 / (height_top - height_bot);
2893 const double array000 = cw[3] * (array1[ci[0]][ci[1]][ci[2]]
2894 - array0[ci[0]][ci[1]][ci[2]])
2895 + array0[ci[0]][ci[1]][ci[2]];
2896 const double array100 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2]]
2897 - array0[ci[0] + 1][ci[1]][ci[2]])
2898 + array0[ci[0] + 1][ci[1]][ci[2]];
2899 const double array010 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2]]
2900 - array0[ci[0]][ci[1] + 1][ci[2]])
2901 + array0[ci[0]][ci[1] + 1][ci[2]];
2902 const double array110 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2]]
2903 - array0[ci[0] + 1][ci[1] + 1][ci[2]])
2904 + array0[ci[0] + 1][ci[1] + 1][ci[2]];
2905 const double array001 = cw[3] * (array1[ci[0]][ci[1]][ci[2] + 1]
2906 - array0[ci[0]][ci[1]][ci[2] + 1])
2907 + array0[ci[0]][ci[1]][ci[2] + 1];
2908 const double array101 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2] + 1]
2909 - array0[ci[0] + 1][ci[1]][ci[2] + 1])
2910 + array0[ci[0] + 1][ci[1]][ci[2] + 1];
2911 const double array011 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2] + 1]
2912 - array0[ci[0]][ci[1] + 1][ci[2] + 1])
2913 + array0[ci[0]][ci[1] + 1][ci[2] + 1];
2914 const double array111 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2915 - array0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2916 + array0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2918 const double array00 = cw[0] * (array100 - array000) + array000;
2919 const double array10 = cw[0] * (array110 - array010) + array010;
2920 const double array01 = cw[0] * (array101 - array001) + array001;
2921 const double array11 = cw[0] * (array111 - array011) + array011;
2923 const double aux0 = cw[1] * (array10 - array00) + array00;
2924 const double aux1 = cw[1] * (array11 - array01) + array01;
2927 *var = cw[2] * (aux1 - aux0) + aux0;
2962 cw[0] = (met->
p[ci[0] + 1] - p)
2963 / (met->
p[ci[0] + 1] - met->
p[ci[0]]);
2964 cw[1] = (met->
lon[ci[1] + 1] - lon2)
2965 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
2966 cw[2] = (met->
lat[ci[2] + 1] - lat2)
2967 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
2971 const double aux00 =
2972 cw[0] * (array[ci[1]][ci[2]][ci[0]] - array[ci[1]][ci[2]][ci[0] + 1])
2973 + array[ci[1]][ci[2]][ci[0] + 1];
2974 const double aux01 =
2975 cw[0] * (array[ci[1]][ci[2] + 1][ci[0]] -
2976 array[ci[1]][ci[2] + 1][ci[0] + 1])
2977 + array[ci[1]][ci[2] + 1][ci[0] + 1];
2978 const double aux10 =
2979 cw[0] * (array[ci[1] + 1][ci[2]][ci[0]] -
2980 array[ci[1] + 1][ci[2]][ci[0] + 1])
2981 + array[ci[1] + 1][ci[2]][ci[0] + 1];
2982 const double aux11 =
2983 cw[0] * (array[ci[1] + 1][ci[2] + 1][ci[0]] -
2984 array[ci[1] + 1][ci[2] + 1][ci[0] + 1])
2985 + array[ci[1] + 1][ci[2] + 1][ci[0] + 1];
2988 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
2989 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
2990 *var = cw[1] * (aux0 - aux1) + aux1;
2997 float array[
EX][
EY],
3024 cw[1] = (met->
lon[ci[1] + 1] - lon2)
3025 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
3026 cw[2] = (met->
lat[ci[2] + 1] - lat2)
3027 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
3031 const double aux00 = array[ci[1]][ci[2]];
3032 const double aux01 = array[ci[1]][ci[2] + 1];
3033 const double aux10 = array[ci[1] + 1][ci[2]];
3034 const double aux11 = array[ci[1] + 1][ci[2] + 1];
3037 if (isfinite(aux00) && isfinite(aux01)
3038 && isfinite(aux10) && isfinite(aux11)) {
3039 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
3040 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
3041 *var = cw[1] * (aux0 - aux1) + aux1;
3061 float array0[
EX][
EY][
EP],
3063 float array1[
EX][
EY][
EP],
3080 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
3083 *var = wt * (var0 - var1) + var1;
3090 float array0[
EX][
EY],
3092 float array1[
EX][
EY],
3108 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
3111 if (isfinite(var0) && isfinite(var1))
3112 *var = wt * (var0 - var1) + var1;
3123 float array0[
EX][
EY],
3125 float array1[
EX][
EY],
3126 const double lons[
EX],
3127 const double lats[
EY],
3146 const int ix =
locate_reg(lons, (
int) nlon, lon2);
3147 const int iy =
locate_irr(lats, (
int) nlat, lat2);
3151 for (
int dx = 0; dx < 2; dx++)
3152 for (
int dy = 0; dy < 2; dy++) {
3153 if (isfinite(array0[ix + dx][iy + dy])) {
3154 mean += array0[ix + dx][iy + dy];
3155 *sigma +=
SQR(array0[ix + dx][iy + dy]);
3158 if (isfinite(array1[ix + dx][iy + dy])) {
3159 mean += array1[ix + dx][iy + dy];
3160 *sigma +=
SQR(array1[ix + dx][iy + dy]);
3165 *sigma = sqrt(
MAX(*sigma / n -
SQR(mean / n), 0.0));
3168 if (method == 1 && isfinite(array0[ix][iy])
3169 && isfinite(array0[ix][iy + 1])
3170 && isfinite(array0[ix + 1][iy])
3171 && isfinite(array0[ix + 1][iy + 1])
3172 && isfinite(array1[ix][iy])
3173 && isfinite(array1[ix][iy + 1])
3174 && isfinite(array1[ix + 1][iy])
3175 && isfinite(array1[ix + 1][iy + 1])) {
3177 const double aux00 =
LIN(lons[ix], array0[ix][iy],
3178 lons[ix + 1], array0[ix + 1][iy], lon2);
3179 const double aux01 =
LIN(lons[ix], array0[ix][iy + 1],
3180 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
3181 const double aux0 =
LIN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
3183 const double aux10 =
LIN(lons[ix], array1[ix][iy],
3184 lons[ix + 1], array1[ix + 1][iy], lon2);
3185 const double aux11 =
LIN(lons[ix], array1[ix][iy + 1],
3186 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
3187 const double aux1 =
LIN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
3189 *var =
LIN(time0, aux0, time1, aux1, time);
3194 const double aux00 =
NN(lons[ix], array0[ix][iy],
3195 lons[ix + 1], array0[ix + 1][iy], lon2);
3196 const double aux01 =
NN(lons[ix], array0[ix][iy + 1],
3197 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
3198 const double aux0 =
NN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
3200 const double aux10 =
NN(lons[ix], array1[ix][iy],
3201 lons[ix + 1], array1[ix + 1][iy], lon2);
3202 const double aux11 =
NN(lons[ix], array1[ix][iy + 1],
3203 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
3204 const double aux1 =
NN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
3206 *var =
NN(time0, aux0, time1, aux1, time);
3231 const time_t jsec0 = (time_t) jsec + timegm(&t0);
3232 t1 = gmtime(&jsec0);
3234 *year = t1->tm_year + 1900;
3235 *mon = t1->tm_mon + 1;
3237 *hour = t1->tm_hour;
3240 *remain = jsec - floor(jsec);
3246 const double kz[
EP],
3247 const double kw[
EP],
3256 const double z =
Z(p);
3261 else if (z > kz[nk - 1])
3265 return LIN(kz[idx], kw[idx], kz[idx + 1], kw[idx + 1], z);
3282 const double a =
RA *
SQR(t), r =
SH(h2o) / (1. -
SH(h2o));
3295 (
"MET_PRESS_LEVEL_DEF=0 is disabled. Use 3 for the extended L137 set.");
3300 (
"MET_PRESS_LEVEL_DEF=1 is disabled. Use 4 for the extended L91 set.");
3305 (
"MET_PRESS_LEVEL_DEF=2 is disabled. Use 5 for the extended L60 set.");
3311 const double press[147] = {
3312 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
3313 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
3314 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
3315 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
3316 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
3317 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
3318 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
3319 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
3320 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
3321 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
3322 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
3323 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
3324 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
3325 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
3326 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
3327 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
3328 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
3329 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
3330 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73, 1028.85,
3332 1035.09, 1038.21, 1041.33, 1044.45
3335 for (
int ip = 0; ip < ctl->
met_np; ip++)
3342 const double press[101] = {
3343 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
3344 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
3345 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
3346 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
3347 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
3349 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
3350 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
3351 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
3352 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
3353 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
3354 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
3355 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
3356 1007.4431, 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73,
3358 1035.09, 1038.21, 1041.33, 1044.45
3361 for (
int ip = 0; ip < ctl->
met_np; ip++)
3368 const double press[62] = {
3369 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
3370 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
3371 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
3372 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
3373 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
3374 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
3375 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
3376 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1034.86, 1039.65,
3380 for (
int ip = 0; ip < ctl->
met_np; ip++)
3387 const double press[137] = {
3388 0.01, 0.02, 0.031, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861,
3389 0.2499, 0.3299, 0.4288, 0.5496, 0.6952, 0.869, 1.0742,
3390 1.3143, 1.5928, 1.9134, 2.2797, 2.6954, 3.1642, 3.6898,
3391 4.2759, 4.9262, 5.6441, 6.4334, 7.2974, 8.2397, 9.2634,
3392 10.372, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945, 18.9752,
3393 20.761, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
3394 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.199, 54.5299,
3395 57.9834, 61.5607, 65.2695, 69.1187, 73.1187, 77.281, 81.6182,
3396 86.145, 90.8774, 95.828, 101.005, 106.415, 112.068, 117.971,
3397 124.134, 130.564, 137.27, 144.262, 151.549, 159.14, 167.045,
3398 175.273, 183.834, 192.739, 201.997, 211.619, 221.615, 231.995,
3399 242.772, 253.955, 265.556, 277.585, 290.055, 302.976, 316.361,
3400 330.22, 344.566, 359.411, 374.767, 390.645, 407.058, 424.019,
3401 441.539, 459.632, 478.31, 497.584, 517.42, 537.72, 558.343,
3402 579.193, 600.167, 621.162, 642.076, 662.808, 683.262, 703.347,
3403 722.979, 742.086, 760.6, 778.466, 795.64, 812.085, 827.776,
3404 842.696, 856.838, 870.2, 882.791, 894.622, 905.712, 916.081,
3405 925.757, 934.767, 943.14, 950.908, 958.104, 965.299, 972.495,
3406 979.69, 986.886, 994.081, 1001.28, 1008.47, 1015.67, 1022.86,
3407 1030.06, 1037.25, 1044.45
3410 for (
int ip = 0; ip < ctl->
met_np; ip++)
3417 const double press[59] = {
3418 0.1, 0.2, 0.3843, 0.6365, 0.9564, 1.3448, 1.8058, 2.3478,
3419 2.985, 3.7397, 4.6462, 5.7565, 7.1322, 8.8366, 10.9483,
3420 13.5647, 16.8064, 20.8227, 25.7989, 31.9642, 39.6029, 49.0671,
3421 60.1802, 73.0663, 87.7274, 104.229, 122.614, 142.902, 165.089,
3422 189.147, 215.025, 242.652, 272.059, 303.217, 336.044, 370.407,
3423 406.133, 443.009, 480.791, 519.209, 557.973, 596.777, 635.306,
3424 673.24, 710.263, 746.063, 780.346, 812.83, 843.263, 871.42,
3425 897.112, 920.189, 940.551, 958.148, 975.744, 993.341, 1010.94,
3429 for (
int ip = 0; ip < ctl->
met_np; ip++)
3433 ERRMSG(
"Use values between 3 and 7.");
3437 ERRMSG(
"Recompile with larger EP to use this pressure level definition!");
3449 int i = (ihi + ilo) >> 1;
3451 if (xx[i] < xx[i + 1])
3452 while (ihi > ilo + 1) {
3453 i = (ihi + ilo) >> 1;
3459 while (ihi > ilo + 1) {
3460 i = (ihi + ilo) >> 1;
3480 int i = (ihi + ilo) >> 1;
3482 if ((xx[ig] <= x && x < xx[ig + 1]) || (xx[ig] >= x && x > xx[ig + 1]))
3485 if (xx[i] < xx[i + 1])
3486 while (ihi > ilo + 1) {
3487 i = (ihi + ilo) >> 1;
3493 while (ihi > ilo + 1) {
3494 i = (ihi + ilo) >> 1;
3512 const int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
3526 float profiles[
EX][
EY][
EP],
3528 const int lon_ap_ind,
3529 const int lat_ap_ind,
3530 const double height_ap,
3536 np, height_ap, ind[0]);
3538 np, height_ap, ind[1]);
3540 np, height_ap, ind[2]);
3559 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3563 double dts, u[4], um = 0, v[4], vm = 0, w[4], wm = 0,
3567 for (
int i = 0; i < ctl->
advect; i++) {
3572 x[0] = atm->
lon[ip];
3573 x[1] = atm->
lat[ip];
3576 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
3577 x[0] = atm->
lon[ip] +
DX2COORD(met0, dts * u[i - 1], atm->
lat[ip]);
3578 x[1] = atm->
lat[ip] +
DY2COORD(met0, dts * v[i - 1]);
3579 x[2] = atm->
p[ip] + dts * w[i - 1];
3581 const double tm = atm->
time[ip] + dts;
3586 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3588 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3590 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
3596 met1, met1->
pl, met1->
ul,
3597 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3599 met1, met1->
pl, met1->
vl,
3600 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3602 met1, met1->
pl, met1->
wl,
3603 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
3609 k = (i == 0 ? 0.0 : 1.0);
3610 else if (ctl->
advect == 4)
3611 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
3618 atm->
time[ip] += cache->
dt[ip];
3620 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
3622 atm->
p[ip] += cache->
dt[ip] * wm;
3634 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3640 atm->
time[ip], atm->
p[ip],
3641 atm->
lon[ip], atm->
lat[ip],
3642 &atm->
q[qnt][ip], ci, cw, 1);
3645 double dts, u[4], um = 0, v[4], vm = 0, wdot[4],
3646 wdotm = 0, x[3] = { 0, 0, 0 };
3649 for (
int i = 0; i < ctl->
advect; i++) {
3654 x[0] = atm->
lon[ip];
3655 x[1] = atm->
lat[ip];
3656 x[2] = atm->
q[qnt][ip];
3658 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
3659 x[0] = atm->
lon[ip] +
DX2COORD(met0, dts * u[i - 1], atm->
lat[ip]);
3660 x[1] = atm->
lat[ip] +
DY2COORD(met0, dts * v[i - 1]);
3661 x[2] = atm->
q[qnt][ip] + dts * wdot[i - 1];
3664 const double tm = atm->
time[ip] + dts;
3669 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3672 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3675 tm, x[2], x[0], x[1], &wdot[i], ci, cw, 0);
3680 k = (i == 0 ? 0.0 : 1.0);
3681 else if (ctl->
advect == 4)
3682 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
3686 wdotm += k * wdot[i];
3690 atm->
time[ip] += cache->
dt[ip];
3692 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
3694 atm->
q[qnt][ip] += cache->
dt[ip] * wdotm;
3700 atm->
q[qnt][ip], atm->
lon[ip], atm->
lat[ip],
3701 &atm->
p[ip], ci, cw, 1);
3729 atm->
lon[ip], atm->
lat[ip], &atm->
p[ip], ci, cw, 1);
3754 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3790 if (atm->
p[ip] < pbl)
3839 ERRMSG(
"Only lat/lon grid supported");
3845 ERRMSG(
"Molar mass is not defined!");
3851 const int ensemble_mode = (ctl->
nens > 0);
3852 const int np = atm->
np;
3856 const int ngrid = nx * ny * nz;
3857 const int nens = ensemble_mode ? ctl->
nens : 1;
3859 double *restrict
const z = (
double *) malloc((
size_t) nz *
sizeof(double));
3860 double *restrict
const press =
3861 (
double *) malloc((
size_t) nz *
sizeof(double));
3862 double *restrict
const mass =
3863 (
double *) calloc((
size_t) ngrid * (size_t) nens,
sizeof(
double));
3864 double *restrict
const area =
3865 (
double *) malloc((
size_t) ny *
sizeof(double));
3866 double *restrict
const lon =
3867 (
double *) malloc((
size_t) nx *
sizeof(double));
3868 double *restrict
const lat =
3869 (
double *) malloc((
size_t) ny *
sizeof(double));
3871 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
3872 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
3873 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
3882#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])
3883#pragma acc data present(ctl,met0,met1,atm,ixs,iys,izs,z,press,mass,area,lon,lat)
3884#pragma acc parallel loop independent gang vector
3886#pragma omp parallel for default(shared)
3888 for (
int iz = 0; iz < nz; iz++) {
3890 press[iz] =
P(z[iz]);
3894 const double t0 = tt - 0.5 * ctl->
dt_mod;
3895 const double t1 = tt + 0.5 * ctl->
dt_mod;
3899#pragma acc parallel loop independent gang vector
3901#pragma omp parallel for default(shared)
3903 for (
int ip = 0; ip < np; ip++) {
3907 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
3908 || ixs[ip] < 0 || ixs[ip] >= nx
3909 || iys[ip] < 0 || iys[ip] >= ny || izs[ip] < 0 || izs[ip] >= nz)
3915#pragma acc parallel loop independent gang vector
3917#pragma omp parallel for default(shared)
3919 for (
int ix = 0; ix < nx; ix++)
3923#pragma acc parallel loop independent gang vector
3925#pragma omp parallel for default(shared)
3927 for (
int iy = 0; iy < ny; iy++) {
3929 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
3934#pragma acc parallel loop independent gang vector
3936 for (
int ip = 0; ip < np; ip++) {
3938 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
3939 if (ensemble_mode) {
3940 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
3941 mass_idx += ens * ngrid;
3944#pragma acc atomic update
3946 mass[mass_idx] += atm->
q[ctl->
qnt_m][ip];
3952#pragma acc parallel loop independent gang vector
3954#pragma omp parallel for default(shared)
3956 for (
int ip = 0; ip < np; ip++)
3964 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
3967 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
3968 if (ensemble_mode) {
3969 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
3970 mass_idx += ens * ngrid;
3974 const double m = mass[mass_idx];
3976 / (
RHO(press[izs[ip]], temp) * area[iys[ip]] * dz * 1e9);
3981#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
4009 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4025 const double lat_ref =
4028 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
4030 lat_ref, atm->
p[ip]));
4032 lat_ref, atm->
p[ip]));
4034 lat_ref, atm->
p[ip]));
4054 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4062 double pbot = ps, ptop = ps;
4079 double cape, cin, pel;
4085 if (isfinite(cape) && cape >= ctl->
conv_cape
4087 ptop = GSL_MIN(ptop, pel);
4091 if (ptop != pbot && atm->
p[ip] >= ptop) {
4096 pbot, atm->
lon[ip], atm->
lat[ip], &tbot, ci, cw, 1);
4098 atm->
lon[ip], atm->
lat[ip], &ttop, ci, cw, 1);
4099 const double rhobot = pbot / tbot;
4100 const double rhotop = ptop / ttop;
4103 const double rho = rhobot + (rhotop - rhobot) * cache->
rs[ip];
4106 atm->
p[ip] =
LIN(rhobot, pbot, rhotop, ptop, rho);
4122 int npart = 0, capacity = 0;
4129 if (fmod(t, ctl->dd_sort_dt) == 0)
4130 dd_sort(ctl, *met, atm, dd, &npart);
4132 dd_push(ctl, atm, cache, &npart);
4135 if (npart > capacity) {
4136 const int newcap = npart + npart / 2 + 1;
4138 realloc(particles, (
size_t) newcap *
sizeof(
particle_t));
4140 ERRMSG(
"Out of memory!");
4149 MPI_Barrier(MPI_COMM_WORLD);
4175 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4178 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,clim,atm)") {
4187 const double aux = exp(-cache->
dt[ip] / tdec);
4188 if (ctl->
qnt_m >= 0) {
4191 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
4192 atm->
q[ctl->
qnt_m][ip] *= aux;
4217 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4225 float umean = 0, usig = 0, vmean = 0, vsig = 0, wmean = 0, wsig = 0;
4226 for (
int i = 0; i < 2; i++)
4227 for (
int j = 0; j < 2; j++)
4228 for (
int k = 0; k < 2; k++) {
4229 umean += met0->
u[ix + i][iy + j][iz + k];
4230 usig +=
SQR(met0->
u[ix + i][iy + j][iz + k]);
4231 vmean += met0->
v[ix + i][iy + j][iz + k];
4232 vsig +=
SQR(met0->
v[ix + i][iy + j][iz + k]);
4233 wmean += met0->
w[ix + i][iy + j][iz + k];
4234 wsig +=
SQR(met0->
w[ix + i][iy + j][iz + k]);
4236 umean += met1->
u[ix + i][iy + j][iz + k];
4237 usig +=
SQR(met1->
u[ix + i][iy + j][iz + k]);
4238 vmean += met1->
v[ix + i][iy + j][iz + k];
4239 vsig +=
SQR(met1->
v[ix + i][iy + j][iz + k]);
4240 wmean += met1->
w[ix + i][iy + j][iz + k];
4241 wsig +=
SQR(met1->
w[ix + i][iy + j][iz + k]);
4243 usig = usig / 16.f -
SQR(umean / 16.f);
4244 usig = (usig > 0 ? sqrtf(usig) : 0);
4245 vsig = vsig / 16.f -
SQR(vmean / 16.f);
4246 vsig = (vsig > 0 ? sqrtf(vsig) : 0);
4247 wsig = wsig / 16.f -
SQR(wmean / 16.f);
4248 wsig = (wsig > 0 ? sqrtf(wsig) : 0);
4251 const double r = 1 - 2 * fabs(cache->
dt[ip]) / ctl->
dt_met;
4252 const double r2 = sqrt(1 - r * r);
4256 cache->
uvwp[ip][0] =
4257 (float) (r * cache->
uvwp[ip][0] +
4262 cache->
uvwp[ip][1] =
4263 (float) (r * cache->
uvwp[ip][1] +
4270 cache->
uvwp[ip][2] =
4271 (float) (r * cache->
uvwp[ip][2] +
4273 atm->
p[ip] += cache->
uvwp[ip][2] * cache->
dt[ip];
4294 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4296 double pbl, ps, dsigw_dz = 0.0, sig_u, sig_w, tau_u, tau_w;
4303 if (atm->
p[ip] < pbl)
4310 const double p =
MIN(atm->
p[ip], ps);
4311 const double zs =
Z(ps);
4312 const double z = 1e3 * (
Z(p) - zs);
4313 const double zi = 1e3 * (
Z(pbl) - zs);
4314 const double zratio = z / zi;
4317 double ess, nss, h2o, t;
4322 const double thetav =
THETAVIRT(p, t, h2o);
4323 const double rho =
RHO(p,
TVIRT(t, h2o));
4324 const double tau = sqrt(
SQR(ess) +
SQR(nss));
4325 const double ustar = sqrt(tau / rho);
4326 const double ust =
MAX(1e-4, ustar);
4327 const double zeta =
MAX(zratio, 1e-6);
4328 const double z_m =
MAX(z, 1.0);
4337 if (fabs(shf) > 1e-6 && ust > 0.0)
4338 ol = thetav * rho *
CPD * (ust * ust * ust) / (
KARMAN *
G0 * shf);
4341 if (zi / fabs(ol) < 1.0) {
4342 const double corr = z_m / ust;
4343 const double sigw0 = 1.3 * ust * exp(-2e-4 * corr);
4344 sig_u = 1e-2 + 2.0 * ust * exp(-3e-4 * corr);
4345 sig_w = 1e-2 + sigw0;
4346 dsigw_dz = -2e-4 * sigw0;
4347 tau_u = 0.5 * z_m / sig_w / (1.0 + 1.5e-3 * corr);
4352 else if (ol < 0.0) {
4355 const double wstar =
4356 pow(-
G0 / thetav * shf / (rho *
CPD) * zi, 1. / 3.);
4359 sig_u = 1e-2 + ust * pow(12.0 - 0.5 * zi / ol, 1.0 / 3.0);
4360 sig_w = 1e-2 + sqrt(1.2 *
SQR(wstar) * (1.0 - 0.9 * zeta)
4361 * pow(zeta, 2.0 / 3.0)
4362 + (1.8 - 1.4 * zeta) *
SQR(ust));
4365 dsigw_dz = 0.5 / sig_w / zi * (-1.4 *
SQR(ust)
4367 (0.8 * pow(
MAX(zeta, 1e-3), -1.0 / 3.0)
4368 - 1.8 * pow(zeta, 2.0 / 3.0)));
4371 tau_u = 0.15 * zi / sig_u;
4373 tau_w = 0.1 * z_m / (sig_w * (0.55 - 0.38 * fabs(z_m / ol)));
4374 else if (zeta < 0.1)
4375 tau_w = 0.59 * z_m / sig_w;
4377 tau_w = 0.15 * zi / sig_w * (1.0 - exp(-5.0 * zeta));
4382 sig_u = 1e-2 + 2.0 * ust * (1.0 - zeta);
4383 sig_w = 1e-2 + 1.3 * ust * (1.0 - zeta);
4384 dsigw_dz = -1.3 * ust / zi;
4385 tau_u = 0.15 * zi / sig_u * sqrt(zeta);
4386 tau_w = 0.1 * zi / sig_w * pow(zeta, 0.8);
4390 sig_u =
MAX(sig_u, 0.25);
4391 sig_w =
MAX(sig_w, 0.1);
4392 tau_u =
MAX(tau_u, 10.);
4393 tau_w =
MAX(tau_w, 30.);
4396 const double ru = exp(-fabs(cache->
dt[ip]) / tau_u);
4397 const double ru2 = sqrt(1.0 -
SQR(ru));
4399 = (float) (cache->
uvwp[ip][0] * ru + sig_u * ru2 * cache->
rs[3 * ip]);
4401 = (float) (cache->
uvwp[ip][1] * ru
4402 + sig_u * ru2 * cache->
rs[3 * ip + 1]);
4404 const double rw = exp(-fabs(cache->
dt[ip]) / tau_w);
4405 const double rw2 = sqrt(1.0 -
SQR(rw));
4406 const double dsigw2_dz = 2.0 * sig_w * dsigw_dz;
4407 const double rhoaux = -1.0 / (1e3 *
H0);
4409 = (float) (cache->
uvwp[ip][2] * rw + sig_w * rw2 * cache->
rs[3 * ip + 2]
4410 + tau_w * (1.0 - rw) * (dsigw2_dz + rhoaux *
SQR(sig_w)));
4418 double znew = z + cache->
uvwp[ip][2] * cache->
dt[ip];
4419 while (znew < 0.0 || znew > zi) {
4423 znew = 2.0 * zi - znew;
4425 atm->
p[ip] +=
DZ2DP((znew - z) / 1000., atm->
p[ip]);
4447 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4460 const double wpbl =
pbl_weight(ctl, atm, ip, pbl, ps);
4461 const double wtrop =
tropo_weight(ctl, clim, atm, ip) * (1.0 - wpbl);
4462 const double wstrat = 1.0 - wpbl - wtrop;
4472 const double sigma = sqrt(2.0 * dx * fabs(cache->
dt[ip]));
4474 atm->
lat[ip] +=
DY2COORD(met0, cache->
rs[3 * ip + 1] * sigma);
4479 const double sigma = sqrt(2.0 * dz * fabs(cache->
dt[ip])) / 1000.;
4480 atm->
p[ip] +=
DZ2DP(cache->
rs[3 * ip + 2] * sigma, atm->
p[ip]);
4499 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4502 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4514 const double dz = 1000. * (
Z(ps - ctl->
dry_depo_dp) -
Z(ps));
4534 const double aux = exp(-cache->
dt[ip] * v_dep / dz);
4535 if (ctl->
qnt_m >= 0) {
4538 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
4539 atm->
q[ctl->
qnt_m][ip] *= aux;
4559 ERRMSG(
"Only lat/lon grid supported");
4566 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4569 const double a = 3.12541941e-06;
4570 const double b = -5.72532259e-01;
4571 const double low = pow(1. / a, 1. / b);
4574 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4581 if (!(lwc > 0 || rwc > 0))
4592 const double k = 9.1e7 * exp(-29700. /
RI * (1. / t - 1. / 298.15));
4595 const double H_SO2 =
4596 1.3e-2 * exp(2900. * (1. / t - 1. / 298.15)) *
RI * t;
4597 const double K_1S = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
4600 const double H_h2o2 =
4601 8.3e2 * exp(7600. * (1. / t - 1. / 298.15)) *
RI * t;
4607 cor = atm->
q[ctl->
qnt_Cx][ip] >
4608 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
4610 const double h2o2 = H_h2o2
4612 * M * cor * 1000. /
AVO;
4615 const double rho_air = atm->
p[ip] / (
RI * t) *
MA / 10.;
4616 const double CWC = (lwc + rwc) * rho_air / 1e3;
4619 const double rate_coef = k * K_1S * h2o2 * H_SO2 * CWC;
4620 const double aux = exp(-cache->
dt[ip] * rate_coef);
4621 if (ctl->
qnt_m >= 0) {
4624 atm->
q[ctl->
qnt_m][ip] *= aux;
4656 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
4659 cache->
iso_var[ip] = atm->
p[ip] / t;
4665 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
4676 LOG(1,
"Read balloon pressure data: %s", ctl->
balloon);
4680 if (!(in = fopen(ctl->
balloon,
"r")))
4681 ERRMSG(
"Cannot open file!");
4685 while (fgets(line,
LEN, in))
4686 if (sscanf(line,
"%lg %lg", &(cache->
iso_ts[cache->
iso_n]),
4689 ERRMSG(
"Too many data points!");
4692 if (cache->
iso_n < 1)
4693 ERRMSG(
"Could not read any data!");
4716 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,met1,atm)") {
4729 atm->
p[ip] = cache->
iso_var[ip] * t;
4735 atm->
p[ip] = 1000. * pow(cache->
iso_var[ip] / t, -1. / 0.286);
4741 atm->
p[ip] = cache->
iso_ps[0];
4769 const int nvar = NVAR, nfix = NFIX, nreact = NREACT;
4770 double rtol[1] = { 1.0e-3 };
4771 double atol[1] = { 1.0 };
4775#pragma acc data copy(rtol,atol,nvar,nfix,nreact)
4778 "acc data present(ctl,cache,clim,met0,met1,atm) ") {
4781 double var[nvar], fix[nfix], rconst[nreact];
4782 for (
int i = 0; i < nvar; i++)
4784 for (
int i = 0; i < nfix; i++)
4786 for (
int i = 0; i < nreact; i++)
4788 kpp_chem_initialize(ctl, clim, met0, met1, atm, var, fix, rconst, ip);
4793 for (
int i = 0; i < 20; i++) {
4800 Rosenbrock(var, fix, rconst, 0, ctl->
dt_kpp,
4801 atol, rtol, &FunTemplate, &JacTemplate, rpar, ipar);
4804 kpp_chem_output2atm(atm, ctl, met0, met1, var, ip);
4825 ERRMSG(
"Need T_ice and T_NAT to calculate T_STS!");
4829 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4831 double ps, ts, zs, us, vs, ess, nss, shf, lsm, sst, pbl, pt, pct, pcb,
4832 cl, plcl, plfc, pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot,
4833 o3, lwc, rwc, iwc, swc, cc, z, zt;
4878 const double lat_ref =
4883 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
4885 lat_ref, atm->
p[ip]));
4888 SET_ATM(qnt_vh, sqrt(u * u + v * v));
4910 atm->
lat[ip], atm->
p[ip])));
4928 const int np = atm->
np;
4929 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
4930 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
4931 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
4939 const double t0 = t - 0.5 * ctl->
dt_mod;
4940 const double t1 = t + 0.5 * ctl->
dt_mod;
4944#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
4945#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
4946#pragma acc parallel loop independent gang vector
4948#pragma omp parallel for default(shared)
4950 for (
int ip = 0; ip < np; ip++) {
4953 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
mixing_z0) / dz);
4954 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
4955 || ixs[ip] < 0 || ixs[ip] >= ctl->
mixing_nx
4956 || iys[ip] < 0 || iys[ip] >= ctl->
mixing_ny
4957 || izs[ip] < 0 || izs[ip] >= ctl->
mixing_nz)
4962 const int use_ensemble = (ctl->
nens > 0);
4964 const int quantities[] = {
4972 const int n_qnt =
sizeof(quantities) /
sizeof(quantities[0]);
4974 for (
int i = 0; i < n_qnt; i++)
4975 if (quantities[i] >= 0)
4981#pragma acc exit data delete(ixs,iys,izs)
4998 const int use_ensemble) {
5000 const int np = atm->
np;
5002 const int nens = use_ensemble ? ctl->
nens : 1;
5003 const int total_grid = ngrid * nens;
5005 double *restrict
const cmean =
5006 (
double *) malloc((
size_t) total_grid *
sizeof(double));
5007 int *restrict
const count =
5008 (
int *) malloc((
size_t) total_grid *
sizeof(int));
5012#pragma acc enter data create(cmean[0:total_grid],count[0:total_grid])
5013#pragma acc data present(ctl,clim,atm,ixs,iys,izs,cmean,count)
5014#pragma acc parallel loop independent gang vector
5019#pragma omp parallel for
5021 for (
int i = 0; i < total_grid; i++) {
5028#pragma acc parallel loop independent gang vector
5030 for (
int ip = 0; ip < np; ip++)
5032 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
5037#pragma acc atomic update
5039 cmean[idx] += atm->
q[qnt_idx][ip];
5041#pragma acc atomic update
5048#pragma acc parallel loop independent gang vector
5053#pragma omp parallel for
5055 for (
int i = 0; i < total_grid; i++)
5057 cmean[i] /= count[i];
5061#pragma acc parallel loop independent gang vector
5063#pragma omp parallel for
5065 for (
int ip = 0; ip < np; ip++) {
5067 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
5069 double mixparam = 1.0;
5078 atm->
q[qnt_idx][ip] += (cmean[idx] - atm->
q[qnt_idx][ip]) * mixparam;
5084#pragma acc exit data delete(cmean,count)
5105 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
5108 const double a = 4.71572206e-08;
5109 const double b = -8.28782867e-01;
5110 const double low = pow(1. / a, 1. / b);
5114 "acc data present(ctl,cache,clim,met0,met1,atm)") {
5140 0 ? pow(298. / t, ctl->
oh_chem[1]) : 1.);
5143 0 ? pow(298. / t, ctl->
oh_chem[3]) : 1.);
5144 const double c = log10(k0 * M / ki);
5145 k = k0 * M / (1. + k0 * M / ki) * pow(0.6, 1. / (1. + c * c));
5154 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
5157 const double rate_coef =
5159 atm->
lat[ip], atm->
p[ip]) * M * cor;
5160 const double aux = exp(-cache->
dt[ip] * rate_coef);
5161 if (ctl->
qnt_m >= 0) {
5164 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
5165 atm->
q[ctl->
qnt_m][ip] *= aux;
5186 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(cache,met0,met1,atm)") {
5198 while (atm->
lat[ip] < -90 || atm->
lat[ip] > 90) {
5199 if (atm->
lat[ip] > 90) {
5200 atm->
lat[ip] = 180 - atm->
lat[ip];
5201 atm->
lon[ip] += 180;
5203 if (atm->
lat[ip] < -90) {
5204 atm->
lat[ip] = -180 - atm->
lat[ip];
5205 atm->
lon[ip] += 180;
5210 while (atm->
lon[ip] < -180)
5211 atm->
lon[ip] += 360;
5212 while (atm->
lon[ip] >= 180)
5213 atm->
lon[ip] -= 360;
5216 atm->
lon[ip], atm->
lat[ip], &atm->
lon[ip],
5222 if (atm->
p[ip] < met0->
p[met0->
np - 1]) {
5223 atm->
p[ip] = met0->
p[met0->
np - 1];
5224 }
else if (atm->
p[ip] > 300.) {
5226 if (atm->
p[ip] > ps)
5243 const double lambda_rn222 = log(2.0) / (3.8235 * 86400.0);
5244 const double lambda_pb210 = log(2.0) / (22.3 * 365.25 * 86400.0);
5245 const double lambda_be7 = log(2.0) / (53.22 * 86400.0);
5246 const double lambda_cs137 = log(2.0) / (30.05 * 365.25 * 86400.0);
5247 const double lambda_i131 = log(2.0) / (8.02 * 86400.0);
5248 const double lambda_xe133 = log(2.0) / (5.2474 * 86400.0);
5254 const double dt = cache->
dt[ip];
5258 atm->
q[ctl->
qnt_Apb210][ip] *= exp(-dt * lambda_pb210);
5263 const double aux = exp(-dt * lambda_rn222);
5264 const double lost = old * (1.0 - aux);
5269 atm->
q[ctl->
qnt_Apb210][ip] += lost * lambda_pb210 / lambda_rn222;
5274 atm->
q[ctl->
qnt_Abe7][ip] *= exp(-dt * lambda_be7);
5278 atm->
q[ctl->
qnt_Acs137][ip] *= exp(-dt * lambda_cs137);
5282 atm->
q[ctl->
qnt_Ai131][ip] *= exp(-dt * lambda_i131);
5286 atm->
q[ctl->
qnt_Axe133][ip] *= exp(-dt * lambda_xe133);
5296 gsl_rng_env_setup();
5297 if (omp_get_max_threads() >
NTHREADS)
5298 ERRMSG(
"Too many threads!");
5299 for (
int i = 0; i <
NTHREADS; i++) {
5300 rng[i] = gsl_rng_alloc(gsl_rng_default);
5301 gsl_rng_set(rng[i], gsl_rng_default_seed
5302 + (
long unsigned) (ntask *
NTHREADS + i));
5307 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
5308 CURAND_STATUS_SUCCESS)
5309 ERRMSG(
"Cannot create random number generator!");
5310 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
5311 CURAND_STATUS_SUCCESS)
5312 ERRMSG(
"Cannot set seed for random number generator!");
5315 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
5316 CURAND_STATUS_SUCCESS)
5317 ERRMSG(
"Cannot set stream for random number generator!");
5334#pragma omp parallel for default(shared)
5335 for (
size_t i = 0; i < n; ++i)
5336 rs[i] = gsl_rng_uniform(rng[omp_get_thread_num()]);
5340 else if (method == 1) {
5341#pragma omp parallel for default(shared)
5342 for (
size_t i = 0; i < n; ++i)
5343 rs[i] = gsl_ran_gaussian_ziggurat(rng[omp_get_thread_num()], 1.0);
5349#pragma acc update device(rs[:n])
5357 const uint64_t key = 0xc8e4fd154ce32f6d;
5361#pragma acc data present(rs)
5362#pragma acc parallel loop independent gang vector
5364#pragma omp parallel for default(shared)
5366 for (
size_t i = 0; i < n + 1; ++i) {
5367 uint64_t r, t, x, y, z;
5368 y = x = (rng_ctr + i) * key;
5371 x = (x >> 32) | (x << 32);
5373 x = (x >> 32) | (x << 32);
5375 x = (x >> 32) | (x << 32);
5377 x = (x >> 32) | (x << 32);
5378 r = t ^ ((x * x + y) >> 32);
5379 rs[i] = (double) r / (
double) UINT64_MAX;
5386#pragma acc parallel loop independent gang vector
5388#pragma omp parallel for default(shared)
5390 for (
size_t i = 0; i < n; i += 2) {
5391 const double r = sqrt(-2.0 * log(rs[i]));
5392 const double phi = 2.0 * M_PI * rs[i + 1];
5393 rs[i] = r * cosf((
float) phi);
5394 rs[i + 1] = r * sinf((
float) phi);
5402#pragma acc host_data use_device(rs)
5407 if (curandGenerateUniformDouble(rng_curand, rs, (n < 4 ? 4 : n)) !=
5408 CURAND_STATUS_SUCCESS)
5409 ERRMSG(
"Cannot create random numbers!");
5413 else if (method == 1) {
5414 if (curandGenerateNormalDouble
5415 (rng_curand, rs, (n < 4 ? 4 : n), 0.0,
5416 1.0) != CURAND_STATUS_SUCCESS)
5417 ERRMSG(
"Cannot create random numbers!");
5421 ERRMSG(
"MPTRAC was compiled without cuRAND!");
5438 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
5446 const double v_s =
sedi(atm->
p[ip], t, atm->
q[ctl->
qnt_rp][ip],
5450 atm->
p[ip] +=
DZ2DP(v_s * cache->
dt[ip] / 1000., atm->
p[ip]);
5465 const int np = atm->
np;
5466 double *restrict
const a = (
double *) malloc((
size_t) np *
sizeof(double));
5467 int *restrict
const p = (
int *) malloc((
size_t) np *
sizeof(int));
5468 if (a == NULL || p == NULL)
5469 ERRMSG(
"Out of memory!");
5472#pragma acc enter data create(a[0:np],p[0:np])
5473#pragma acc data present(ctl,met0,atm,a,p)
5478#pragma acc parallel loop independent gang vector
5480#pragma omp parallel for default(shared)
5482 for (
int ip = 0; ip < np; ip++) {
5493#pragma acc host_data use_device(a,p)
5495 thrustSortWrapper(a, np, p);
5497 size_t *perm_sz = (
size_t *) malloc((
size_t) np *
sizeof(size_t));
5498 if (perm_sz == NULL)
5499 ERRMSG(
"Out of memory!");
5501#pragma acc update self(a[0:np])
5503 gsl_sort_index(perm_sz, a, 1, (
size_t) np);
5504 for (
int ip = 0; ip < np; ++ip)
5505 p[ip] = (
int) perm_sz[ip];
5508#pragma acc update device(p[0:np])
5517 for (
int iq = 0; iq < ctl->
nq; iq++)
5522#pragma acc exit data delete(a,p)
5536 double *restrict
const help =
5537 (
double *) malloc((
size_t) np *
sizeof(double));
5539 ERRMSG(
"Out of memory!");
5543#pragma acc enter data create(help[0:np])
5544#pragma acc data present(a,p,help)
5545#pragma acc parallel loop independent gang vector
5547#pragma omp parallel for default(shared)
5549 for (
int ip = 0; ip < np; ip++)
5550 help[ip] = a[p[ip]];
5552#pragma acc parallel loop independent gang vector
5554#pragma omp parallel for default(shared)
5556 for (
int ip = 0; ip < np; ip++)
5561#pragma acc exit data delete(help)
5578 const double latmin = gsl_stats_min(met0->
lat, 1, (
size_t) met0->
ny),
5579 latmax = gsl_stats_max(met0->
lat, 1, (
size_t) met0->
ny);
5582 (fabs(met0->
lon[met0->
nx - 1] - met0->
lon[0] - 360.0) >= 0.01);
5585 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,atm)") {
5591 cache->
dt[ip] = t - atm->
time[ip];
5593 cache->
dt[ip] = 0.0;
5602 if (local && (atm->
lon[ip] <= met0->
lon[0]
5603 || atm->
lon[ip] >= met0->
lon[met0->
nx - 1]
5604 || atm->
lat[ip] <= latmin || atm->
lat[ip] >= latmax))
5605 cache->
dt[ip] = 0.0;
5624 ctl->
t_start = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
5626 ctl->
t_stop = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
5628 ctl->
t_start = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
5630 ctl->
t_stop = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
5635 ERRMSG(
"Nothing to do! Check T_STOP and DIRECTION!");
5655 ERRMSG(
"Only lat/lon grid supported");
5662 "acc data present(ctl,cache,clim,met0,met1,atm)") {
5686 const double K_o1d =
ARRHENIUS(3.30e-10, 0, t) * o1d * M;
5688 atm->
p[ip], sza, o3c);
5689 atm->
q[ctl->
qnt_Cccl4][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5694 const double K_o1d =
ARRHENIUS(2.30e-10, 0, t) * o1d * M;
5696 atm->
p[ip], sza, o3c);
5697 atm->
q[ctl->
qnt_Cccl3f][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5702 const double K_o1d =
ARRHENIUS(1.40e-10, -25, t) * o1d * M;
5704 atm->
p[ip], sza, o3c);
5705 atm->
q[ctl->
qnt_Cccl2f2][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5710 const double K_o1d =
ARRHENIUS(1.19e-10, -20, t) * o1d * M;
5712 atm->
p[ip], sza, o3c);
5713 atm->
q[ctl->
qnt_Cn2o][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5732 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
5735 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
5741 if (!isfinite(pct) || atm->
p[ip] <= pct)
5757 double lwc, rwc, iwc, swc;
5762 const int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
5776 else if (t <= 238.15)
5796 const double K_1 = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
5797 const double K_2 = 6e-8 * exp(1.12e3 * (1. / t - 1. / 298.15));
5798 h *= (1. + K_1 / H_ion + K_1 * K_2 /
SQR(H_ion));
5802 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
5805 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
5831 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
5834 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
5839 const double aux = exp(-cache->
dt[ip] * lambda);
5840 if (ctl->
qnt_m >= 0) {
5843 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
5844 atm->
q[ctl->
qnt_m][ip] *= aux;
5869 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
5871 if (acc_get_num_devices(acc_device_nvidia) <= 0)
5872 ERRMSG(
"Not running on a GPU device!");
5873 acc_set_device_num(rank % acc_get_num_devices(acc_device_nvidia),
5875 acc_device_t device_type = acc_get_device_type();
5876 acc_init(device_type);
5892 ctl_t *ctlup = *ctl;
5895 met_t *met0up = *met0;
5896 met_t *met1up = *met1;
5897 atm_t *atmup = *atm;
5898#pragma acc enter data create(ctlup[:1],cacheup[:1],climup[:1],met0up[:1],met1up[:1],atmup[:1])
5901#pragma acc enter data create(ddup[:1])
5920#pragma acc exit data delete(ctl,cache,clim,met0,met1,atm)
5922#pragma acc exit data delete(dd)
5937 MPI_Type_free(&dd->MPI_Particle);
5956 char cachefile[
LEN], cmd[2 *
LEN], filename[
LEN];
5962 if (t == ctl->
t_start || !init) {
5969 ERRMSG(
"Cannot open file!");
5974 ERRMSG(
"Cannot open file!");
5984 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5985 LOG(1,
"Caching: %s", cachefile);
5986 if (system(cmd) != 0)
5987 WARN(
"Caching command failed!");
5992 if (t > (*met1)->time) {
6002 ERRMSG(
"Cannot open file!");
6012 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
6013 LOG(1,
"Caching: %s", cachefile);
6014 if (system(cmd) != 0)
6015 WARN(
"Caching command failed!");
6020 if (t < (*met0)->time) {
6030 ERRMSG(
"Cannot open file!");
6040 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
6041 LOG(1,
"Caching: %s", cachefile);
6042 if (system(cmd) != 0)
6043 WARN(
"Caching command failed!");
6047 if ((*met0)->coord_type != (*met1)->coord_type)
6048 ERRMSG(
"Coordinate types do not match!");
6051 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
6052 if ((*met0)->nx != (*met1)->nx
6053 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
6054 ERRMSG(
"Meteo grid dimensions do not match!");
6055 for (
int ix = 0; ix < (*met0)->nx; ix++)
6056 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
6057 ERRMSG(
"Meteo grid longitudes do not match!");
6058 for (
int iy = 0; iy < (*met0)->ny; iy++)
6059 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
6060 ERRMSG(
"Meteo grid latitudes do not match!");
6061 for (
int ip = 0; ip < (*met0)->np; ip++)
6062 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
6063 ERRMSG(
"Meteo grid pressure levels do not match!");
6089 const char *filename,
6102 LOG(1,
"Read atmospheric data: %s", filename);
6122 ERRMSG(
"Atmospheric data type not supported!");
6130 ERRMSG(
"Can not read any data!");
6134 LOG(2,
"Number of particles: %d", atm->
np);
6135 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
6136 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
6137 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
6138 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
6139 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
6140 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
6141 LOG(2,
"%s range: %g ... %g %s",
6142 ctl->
met_coord_type == 0 ?
"Longitude" :
"X coordinate", mini, maxi,
6144 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
6145 LOG(2,
"%s range: %g ... %g %s",
6146 ctl->
met_coord_type == 0 ?
"Latitude" :
"Y coordinate", mini, maxi,
6148 for (
int iq = 0; iq < ctl->
nq; iq++) {
6150 sprintf(msg,
"Quantity %s range: %s ... %s %s",
6153 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
6154 LOG(2, msg, mini, maxi);
6224 const char *filename,
6233 LOG(1,
"\nMassive-Parallel Trajectory Calculations (MPTRAC)\n"
6234 "(executable: %s | version: %s | compiled: %s, %s)\n",
6235 argv[0], VERSION, __DATE__, __TIME__);
6342 ctl->
nq = (int)
scan_ctl(filename, argc, argv,
"NQ", -1,
"0", NULL);
6344 ERRMSG(
"Too many quantities!");
6345 for (
int iq = 0; iq < ctl->
nq; iq++) {
6351 scan_ctl(filename, argc, argv,
"QNT_FORMAT", iq,
"%g",
6353 if (strcasecmp(ctl->
qnt_name[iq],
"aoa") == 0)
6357 SET_QNT(qnt_idx,
"idx",
"particle index",
"-")
6358 SET_QNT(qnt_ens,
"ens",
"ensemble index",
"-")
6359 SET_QNT(qnt_stat,
"stat",
"station flag",
"-")
6360 SET_QNT(qnt_m,
"m",
"mass",
"kg")
6361 SET_QNT(qnt_vmr,
"vmr",
"volume mixing ratio",
"ppv")
6362 SET_QNT(qnt_rp,
"rp",
"particle radius",
"microns")
6363 SET_QNT(qnt_rhop,
"rhop",
"particle density",
"kg/m^3")
6364 SET_QNT(qnt_ps,
"ps",
"surface pressure",
"hPa")
6365 SET_QNT(qnt_ts,
"ts",
"surface temperature",
"K")
6366 SET_QNT(qnt_zs,
"zs",
"surface height",
"km")
6367 SET_QNT(qnt_us,
"us",
"surface zonal wind",
"m/s")
6368 SET_QNT(qnt_vs,
"vs",
"surface meridional wind",
"m/s")
6369 SET_QNT(qnt_ess,
"ess",
"eastward turbulent surface stress",
"N/m^2")
6370 SET_QNT(qnt_nss,
"nss",
"northward turbulent surface stress",
"N/m^2")
6371 SET_QNT(qnt_shf,
"shf",
"surface sensible heat flux",
"W/m^2")
6372 SET_QNT(qnt_lsm,
"lsm",
"land-sea mask",
"1")
6373 SET_QNT(qnt_sst,
"sst",
"sea surface temperature",
"K")
6374 SET_QNT(qnt_pbl,
"pbl",
"planetary boundary layer",
"hPa")
6375 SET_QNT(qnt_pt,
"pt",
"tropopause pressure",
"hPa")
6376 SET_QNT(qnt_tt,
"tt",
"tropopause temperature",
"K")
6377 SET_QNT(qnt_zt,
"zt",
"tropopause geopotential height",
"km")
6378 SET_QNT(qnt_h2ot,
"h2ot",
"tropopause water vapor",
"ppv")
6379 SET_QNT(qnt_zg,
"zg",
"geopotential height",
"km")
6380 SET_QNT(qnt_p,
"p",
"pressure",
"hPa")
6381 SET_QNT(qnt_t,
"t",
"temperature",
"K")
6382 SET_QNT(qnt_rho,
"rho",
"air density",
"kg/m^3")
6383 SET_QNT(qnt_u,
"u",
"zonal wind",
"m/s")
6384 SET_QNT(qnt_v,
"v",
"meridional wind",
"m/s")
6385 SET_QNT(qnt_w,
"w",
"vertical velocity",
"hPa/s")
6386 SET_QNT(qnt_h2o,
"h2o",
"water vapor",
"ppv")
6387 SET_QNT(qnt_o3,
"o3",
"ozone",
"ppv")
6388 SET_QNT(qnt_lwc,
"lwc",
"cloud liquid water content",
"kg/kg")
6389 SET_QNT(qnt_rwc,
"rwc",
"cloud rain water content",
"kg/kg")
6390 SET_QNT(qnt_iwc,
"iwc",
"cloud ice water content",
"kg/kg")
6391 SET_QNT(qnt_swc,
"swc",
"cloud snow water content",
"kg/kg")
6392 SET_QNT(qnt_cc,
"cc",
"cloud cover",
"1")
6393 SET_QNT(qnt_pct,
"pct",
"cloud top pressure",
"hPa")
6394 SET_QNT(qnt_pcb,
"pcb",
"cloud bottom pressure",
"hPa")
6395 SET_QNT(qnt_cl,
"cl",
"total column cloud water",
"kg/m^2")
6396 SET_QNT(qnt_plcl,
"plcl",
"lifted condensation level",
"hPa")
6397 SET_QNT(qnt_plfc,
"plfc",
"level of free convection",
"hPa")
6398 SET_QNT(qnt_pel,
"pel",
"equilibrium level",
"hPa")
6399 SET_QNT(qnt_cape,
"cape",
"convective available potential energy",
6401 SET_QNT(qnt_cin,
"cin",
"convective inhibition",
"J/kg")
6402 SET_QNT(qnt_o3c,
"o3c",
"total column ozone",
"DU")
6403 SET_QNT(qnt_hno3,
"hno3",
"nitric acid",
"ppv")
6404 SET_QNT(qnt_oh,
"oh",
"hydroxyl radical",
"ppv")
6405 SET_QNT(qnt_h2o2,
"h2o2",
"hydrogen peroxide",
"ppv")
6406 SET_QNT(qnt_ho2,
"ho2",
"hydroperoxyl radical",
"ppv")
6407 SET_QNT(qnt_o1d,
"o1d",
"atomic oxygen",
"ppv")
6408 SET_QNT(qnt_mloss_oh,
"mloss_oh",
"mass loss due to OH chemistry",
"kg")
6409 SET_QNT(qnt_mloss_h2o2,
"mloss_h2o2",
6410 "mass loss due to H2O2 chemistry",
"kg")
6411 SET_QNT(qnt_mloss_kpp,
"mloss_kpp",
"mass loss due to kpp chemistry",
6413 SET_QNT(qnt_mloss_wet,
"mloss_wet",
"mass loss due to wet deposition",
6415 SET_QNT(qnt_mloss_dry,
"mloss_dry",
"mass loss due to dry deposition",
6417 SET_QNT(qnt_mloss_decay,
"mloss_decay",
6418 "mass loss due to exponential decay",
"kg")
6419 SET_QNT(qnt_loss_rate,
"loss_rate",
"total loss rate",
"s^-1")
6420 SET_QNT(qnt_psat,
"psat",
"saturation pressure over water",
"hPa")
6421 SET_QNT(qnt_psice,
"psice",
"saturation pressure over ice",
"hPa")
6422 SET_QNT(qnt_pw,
"pw",
"partial water vapor pressure",
"hPa")
6423 SET_QNT(qnt_sh,
"sh",
"specific humidity",
"kg/kg")
6424 SET_QNT(qnt_rh,
"rh",
"relative humidity",
"%%")
6425 SET_QNT(qnt_rhice,
"rhice",
"relative humidity over ice",
"%%")
6426 SET_QNT(qnt_theta,
"theta",
"potential temperature",
"K")
6427 SET_QNT(qnt_zeta,
"zeta",
"zeta coordinate",
"K")
6428 SET_QNT(qnt_zeta_d,
"zeta_d",
"diagnosed zeta coordinate",
"K")
6429 SET_QNT(qnt_zeta_dot,
"zeta_dot",
"velocity of zeta coordinate",
6431 SET_QNT(qnt_eta,
"eta",
"eta coordinate",
"1")
6432 SET_QNT(qnt_eta_dot,
"eta_dot",
"velocity of eta coordinate",
"1/s")
6433 SET_QNT(qnt_tvirt,
"tvirt",
"virtual temperature",
"K")
6434 SET_QNT(qnt_lapse,
"lapse",
"temperature lapse rate",
"K/km")
6435 SET_QNT(qnt_vh,
"vh",
"horizontal velocity",
"m/s")
6436 SET_QNT(qnt_vz,
"vz",
"vertical velocity",
"m/s")
6437 SET_QNT(qnt_pv,
"pv",
"potential vorticity",
"PVU")
6438 SET_QNT(qnt_tdew,
"tdew",
"dew point temperature",
"K")
6439 SET_QNT(qnt_tice,
"tice",
"frost point temperature",
"K")
6440 SET_QNT(qnt_tsts,
"tsts",
"STS existence temperature",
"K")
6441 SET_QNT(qnt_tnat,
"tnat",
"NAT existence temperature",
"K")
6442 SET_QNT(qnt_Cx,
"Cx",
"Trace species x volume mixing ratio",
"ppv")
6443 SET_QNT(qnt_Ch2o,
"Ch2o",
"H2O volume mixing ratio",
"ppv")
6444 SET_QNT(qnt_Co3,
"Co3",
"O3 volume mixing ratio",
"ppv")
6445 SET_QNT(qnt_Cco,
"Cco",
"CO volume mixing ratio",
"ppv")
6446 SET_QNT(qnt_Coh,
"Coh",
"HO volume mixing ratio",
"ppv")
6447 SET_QNT(qnt_Ch,
"Ch",
"H radical volume mixing ratio",
"ppv")
6448 SET_QNT(qnt_Cho2,
"Cho2",
"HO2 volume mixing ratio",
"ppv")
6449 SET_QNT(qnt_Ch2o2,
"Ch2o2",
"H2O2 volume mixing ratio",
"ppv")
6450 SET_QNT(qnt_Co1d,
"Co1d",
"O(1D) volume mixing ratio",
"ppv")
6451 SET_QNT(qnt_Co3p,
"Co3p",
"O(3P) radical volume mixing ratio",
"ppv")
6452 SET_QNT(qnt_Cccl4,
"Cccl4",
"CCl4 (CFC-10) volume mixing ratio",
"ppv")
6453 SET_QNT(qnt_Cccl3f,
"Cccl3f",
"CCl3F (CFC-11) volume mixing ratio",
6455 SET_QNT(qnt_Cccl2f2,
"Cccl2f2",
"CCl2F2 (CFC-12) volume mixing ratio",
6457 SET_QNT(qnt_Cn2o,
"Cn2o",
"N2O volume mixing ratio",
"ppv")
6458 SET_QNT(qnt_Csf6,
"Csf6",
"SF6 volume mixing ratio",
"ppv")
6459 SET_QNT(qnt_aoa,
"aoa",
"age of air",
"s")
6460 SET_QNT(qnt_Arn222,
"Arn222",
"Rn-222 activity",
"Bq")
6461 SET_QNT(qnt_Apb210,
"Apb210",
"Pb-210 activity",
"Bq")
6462 SET_QNT(qnt_Abe7,
"Abe7",
"Be-7 activity",
"Bq")
6463 SET_QNT(qnt_Acs137,
"Acs137",
"Cs-137 activity",
"Bq")
6464 SET_QNT(qnt_Ai131,
"Ai131",
"I-131 activity",
"Bq")
6465 SET_QNT(qnt_Axe133,
"Axe133",
"Xe-133 activity",
"Bq")
6466 SET_QNT(qnt_subdomain,
"subdomain",
"current subdomain index",
"-")
6467 SET_QNT(qnt_destination,
"destination",
6468 "subdomain index of destination",
"-")
6473 (int)
scan_ctl(filename, argc, argv,
"MET_COORD_TYPE", -1,
"0", NULL);
6475 ERRMSG(
"MET_COORD_TYPE must be 0 or 1!");
6480 scan_ctl(filename, argc, argv,
"MET_UTM_REF_LAT", -1,
"", NULL);
6482 scan_ctl(filename, argc, argv,
"MET_UTM_REF_LON", -1,
"", NULL);
6487 (int)
scan_ctl(filename, argc, argv,
"ADVECT_VERT_COORD", -1,
"0", NULL);
6489 ERRMSG(
"ADVECT_VERT_COORD must be 0, 1, 2, or 3!");
6492 ERRMSG(
"Add quantity zeta for diabatic advection!");
6494 ERRMSG(
"Add quantity eta for etadot avection!");
6497 (int)
scan_ctl(filename, argc, argv,
"MET_VERT_COORD", -1,
"0", NULL);
6499 ERRMSG(
"MET_VERT_COORD must be 0, 1, 2, 3, or 4!");
6503 (
"Using ADVECT_VERT_COORD = 2 requires meteo data on model levels!");
6506 (
"Using ADVECT_VERT_COORD = 3 requires A and B model level coefficients!");
6510 (int)
scan_ctl(filename, argc, argv,
"DIRECTION", -1,
"1", NULL);
6512 ERRMSG(
"Set DIRECTION to -1 or 1!");
6513 ctl->
t_stop =
scan_ctl(filename, argc, argv,
"T_STOP", -1,
"1e100", NULL);
6514 ctl->
dt_mod =
scan_ctl(filename, argc, argv,
"DT_MOD", -1,
"180", NULL);
6518 ctl->
dt_met =
scan_ctl(filename, argc, argv,
"DT_MET", -1,
"3600", NULL);
6520 (int)
scan_ctl(filename, argc, argv,
"MET_CONVENTION", -1,
"0", NULL);
6522 (int)
scan_ctl(filename, argc, argv,
"MET_TYPE", -1,
"0", NULL);
6525 (
"Please use meteo files in netcdf format for diabatic calculations.");
6528 (
"Please use meteo files in netcdf format for etadot calculations.");
6530 (int)
scan_ctl(filename, argc, argv,
"MET_CLAMS", -1,
"0", NULL);
6532 (int)
scan_ctl(filename, argc, argv,
"MET_NC_SCALE", -1,
"1", NULL);
6534 (int)
scan_ctl(filename, argc, argv,
"MET_NC_LEVEL", -1,
"0", NULL);
6536 (int)
scan_ctl(filename, argc, argv,
"MET_NC_QUANT", -1,
"0", NULL);
6538 (int)
scan_ctl(filename, argc, argv,
"MET_ZSTD_LEVEL", -1,
"-3", NULL);
6540 (int)
scan_ctl(filename, argc, argv,
"MET_ZSTD_NWORKERS", -1,
"4", NULL);
6542 (int)
scan_ctl(filename, argc, argv,
"MET_LZ4_ACCEL", -1,
"8", NULL);
6544 (int)
scan_ctl(filename, argc, argv,
"MET_PCK_ZSTD", -1,
"0", NULL);
6546 ERRMSG(
"Set MET_PCK_ZSTD to 0 or 1!");
6549 ERRMSG(
"MET_PCK_ZSTD requires MPTRAC to be compiled with ZSTD support!");
6551 const int def_lossy_scale =
6552 (int)
scan_ctl(filename, argc, argv,
"MET_LOSSY_SCALE", -1,
"0", NULL);
6553 for (
int i = 0; i <
METVAR; i++) {
6554 char defprec_zfp[
LEN] =
"7", deftol_zfp[
LEN] =
"0.0";
6555 char defprec_sz3[
LEN] =
"6", deftol_sz3[
LEN] =
"0.0";
6557 sprintf(defprec_zfp,
"12");
6558 sprintf(defprec_sz3,
"11");
6559 }
else if (i == 1) {
6560 sprintf(defprec_zfp,
"11");
6561 sprintf(defprec_sz3,
"7");
6562 }
else if (i == 2 || i == 3) {
6563 sprintf(defprec_zfp,
"7");
6564 sprintf(defprec_sz3,
"7");
6565 }
else if (i == 4) {
6566 sprintf(defprec_zfp,
"6");
6567 sprintf(defprec_sz3,
"13");
6568 }
else if (i == 5) {
6569 sprintf(defprec_zfp,
"7");
6570 sprintf(defprec_sz3,
"20");
6571 }
else if (i == 6) {
6572 sprintf(defprec_zfp,
"10");
6573 sprintf(defprec_sz3,
"18");
6574 }
else if (i == 7) {
6575 sprintf(defprec_zfp,
"9");
6576 sprintf(defprec_sz3,
"10");
6577 }
else if (i >= 8 && i <= 11) {
6578 sprintf(defprec_zfp,
"6");
6579 sprintf(defprec_sz3,
"13");
6580 }
else if (i == 12) {
6581 sprintf(defprec_zfp,
"9");
6582 sprintf(defprec_sz3,
"6");
6585 (int)
scan_ctl(filename, argc, argv,
"MET_ZFP_PREC", i, defprec_zfp,
6588 scan_ctl(filename, argc, argv,
"MET_ZFP_TOL", i, deftol_zfp, NULL);
6590 (int)
scan_ctl(filename, argc, argv,
"MET_SZ3_PREC", i, defprec_sz3,
6593 scan_ctl(filename, argc, argv,
"MET_SZ3_TOL", i, deftol_sz3, NULL);
6595 snprintf(defscale,
LEN,
"%d", def_lossy_scale);
6597 (int)
scan_ctl(filename, argc, argv,
"MET_LOSSY_SCALE", i, defscale,
6600 ERRMSG(
"Set MET_LOSSY_SCALE to 0 or 1!");
6604 scan_ctl(filename, argc, argv,
"MET_COMP_LOGFILE", -1,
"-",
6607 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_BATCH", -1,
"-1", NULL);
6609 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ZSTD", -1,
"1", NULL);
6611 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ND0X", -1,
"48", NULL);
6613 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ND0Y", -1,
"24", NULL);
6615 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_MAXLEV", -1,
"6", NULL);
6616 for (
int i = 0; i <
METVAR; i++) {
6617 char defeps[
LEN] =
"1.0";
6618 if (i == 1 || i == 2 || i == 3)
6619 sprintf(defeps,
"0.05");
6621 scan_ctl(filename, argc, argv,
"MET_CMS_EPS", i, defeps, NULL);
6623 ctl->
met_dx = (int)
scan_ctl(filename, argc, argv,
"MET_DX", -1,
"1", NULL);
6624 ctl->
met_dy = (int)
scan_ctl(filename, argc, argv,
"MET_DY", -1,
"1", NULL);
6625 ctl->
met_dp = (int)
scan_ctl(filename, argc, argv,
"MET_DP", -1,
"1", NULL);
6627 ERRMSG(
"MET_DX, MET_DY, and MET_DP need to be greater than zero!");
6628 ctl->
met_sx = (int)
scan_ctl(filename, argc, argv,
"MET_SX", -1,
"1", NULL);
6629 ctl->
met_sy = (int)
scan_ctl(filename, argc, argv,
"MET_SY", -1,
"1", NULL);
6630 ctl->
met_sp = (int)
scan_ctl(filename, argc, argv,
"MET_SP", -1,
"1", NULL);
6632 ERRMSG(
"MET_SX, MET_SY, and MET_SP need to be greater than zero!");
6634 scan_ctl(filename, argc, argv,
"MET_DETREND", -1,
"-999", NULL);
6635 ctl->
met_np = (int)
scan_ctl(filename, argc, argv,
"MET_NP", -1,
"0", NULL);
6637 ERRMSG(
"Too many pressure levels!");
6639 (int)
scan_ctl(filename, argc, argv,
"MET_PRESS_LEVEL_DEF", -1,
"-1",
6645 for (
int ip = 0; ip < ctl->
met_np; ip++)
6647 scan_ctl(filename, argc, argv,
"MET_P", ip,
"", NULL);
6651 (int)
scan_ctl(filename, argc, argv,
"MET_NLEV", -1,
"0", NULL);
6653 ERRMSG(
"Too many model levels!");
6654 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
6656 scan_ctl(filename, argc, argv,
"MET_LEV_HYAM", ip,
"", NULL);
6657 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
6659 scan_ctl(filename, argc, argv,
"MET_LEV_HYBM", ip,
"", NULL);
6661 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SX", -1,
"-1", NULL);
6663 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SY", -1,
"-1", NULL);
6665 (int)
scan_ctl(filename, argc, argv,
"MET_RELHUM", -1,
"0", NULL);
6667 (int)
scan_ctl(filename, argc, argv,
"MET_CAPE", -1,
"1", NULL);
6669 ERRMSG(
"Set MET_CAPE to 0 or 1!");
6671 (int)
scan_ctl(filename, argc, argv,
"MET_PBL", -1,
"3", NULL);
6673 ERRMSG(
"Set MET_PBL to 0 ... 3!");
6675 scan_ctl(filename, argc, argv,
"MET_PBL_MIN", -1,
"0.1", NULL);
6677 scan_ctl(filename, argc, argv,
"MET_PBL_MAX", -1,
"5.0", NULL);
6679 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO", -1,
"3", NULL);
6681 ERRMSG(
"Set MET_TROPO to 0 ... 5!");
6683 scan_ctl(filename, argc, argv,
"MET_TROPO_PV", -1,
"3.5", NULL);
6685 scan_ctl(filename, argc, argv,
"MET_TROPO_THETA", -1,
"380", NULL);
6687 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO_SPLINE", -1,
"1", NULL);
6689 scan_ctl(filename, argc, argv,
"MET_DT_OUT", -1,
"0.1", NULL);
6691 (int)
scan_ctl(filename, argc, argv,
"MET_CACHE", -1,
"0", NULL);
6693 (int)
scan_ctl(filename, argc, argv,
"MET_MPI_SHARE", -1,
"0", NULL);
6696 ctl->
sort_dt =
scan_ctl(filename, argc, argv,
"SORT_DT", -1,
"-999", NULL);
6700 (int)
scan_ctl(filename, argc, argv,
"ISOSURF", -1,
"0", NULL);
6705 (int)
scan_ctl(filename, argc, argv,
"RNG_TYPE", -1,
"1", NULL);
6707 ERRMSG(
"Set RNG_TYPE to 0, 1, or 2!");
6710 ctl->
advect = (int)
scan_ctl(filename, argc, argv,
"ADVECT", -1,
"2", NULL);
6712 ERRMSG(
"Set ADVECT to 1, 2, or 4!");
6716 = (int)
scan_ctl(filename, argc, argv,
"DIFFUSION", -1,
"0", NULL);
6718 ERRMSG(
"Set DIFFUSION to 0 or 1!");
6720 (int)
scan_ctl(filename, argc, argv,
"TURB_PBL_SCHEME", -1,
"0", NULL);
6722 ERRMSG(
"Set TURB_PBL_SCHEME to 0 or 1!");
6724 scan_ctl(filename, argc, argv,
"TURB_DX_PBL", -1,
"50", NULL);
6726 scan_ctl(filename, argc, argv,
"TURB_DX_TROP", -1,
"50", NULL);
6728 scan_ctl(filename, argc, argv,
"TURB_DX_STRAT", -1,
"0", NULL);
6730 scan_ctl(filename, argc, argv,
"TURB_DZ_PBL", -1,
"0", NULL);
6732 scan_ctl(filename, argc, argv,
"TURB_DZ_TROP", -1,
"0", NULL);
6734 scan_ctl(filename, argc, argv,
"TURB_DZ_STRAT", -1,
"0.1", NULL);
6736 scan_ctl(filename, argc, argv,
"TURB_MESOX", -1,
"0.16", NULL);
6738 scan_ctl(filename, argc, argv,
"TURB_MESOZ", -1,
"0.16", NULL);
6740 scan_ctl(filename, argc, argv,
"TURB_PBL_TRANS", -1,
"0", NULL);
6744 = (int)
scan_ctl(filename, argc, argv,
"CONV_MIX_PBL", -1,
"0", NULL);
6746 =
scan_ctl(filename, argc, argv,
"CONV_PBL_TRANS", -1,
"0", NULL);
6748 =
scan_ctl(filename, argc, argv,
"CONV_CAPE", -1,
"-999", NULL);
6750 =
scan_ctl(filename, argc, argv,
"CONV_CIN", -1,
"-999", NULL);
6751 ctl->
conv_dt =
scan_ctl(filename, argc, argv,
"CONV_DT", -1,
"-999", NULL);
6755 scan_ctl(filename, argc, argv,
"BOUND_MASS", -1,
"-999", NULL);
6757 scan_ctl(filename, argc, argv,
"BOUND_MASS_TREND", -1,
"0", NULL);
6759 scan_ctl(filename, argc, argv,
"BOUND_VMR", -1,
"-999", NULL);
6761 scan_ctl(filename, argc, argv,
"BOUND_VMR_TREND", -1,
"0", NULL);
6763 scan_ctl(filename, argc, argv,
"BOUND_LAT0", -1,
"-999", NULL);
6765 scan_ctl(filename, argc, argv,
"BOUND_LAT1", -1,
"-999", NULL);
6767 scan_ctl(filename, argc, argv,
"BOUND_P0", -1,
"-999", NULL);
6769 scan_ctl(filename, argc, argv,
"BOUND_P1", -1,
"-999", NULL);
6771 scan_ctl(filename, argc, argv,
"BOUND_DPS", -1,
"-999", NULL);
6773 scan_ctl(filename, argc, argv,
"BOUND_DZS", -1,
"-999", NULL);
6775 scan_ctl(filename, argc, argv,
"BOUND_ZETAS", -1,
"-999", NULL);
6777 (int)
scan_ctl(filename, argc, argv,
"BOUND_PBL", -1,
"0", NULL);
6781 if (strcasecmp(ctl->
species,
"CF2Cl2") == 0) {
6785 }
else if (strcasecmp(ctl->
species,
"CFCl3") == 0) {
6789 }
else if (strcasecmp(ctl->
species,
"CH4") == 0) {
6796 }
else if (strcasecmp(ctl->
species,
"CO") == 0) {
6805 }
else if (strcasecmp(ctl->
species,
"CO2") == 0) {
6809 }
else if (strcasecmp(ctl->
species,
"H2O") == 0) {
6811 }
else if (strcasecmp(ctl->
species,
"N2O") == 0) {
6815 }
else if (strcasecmp(ctl->
species,
"NH3") == 0) {
6822 }
else if (strcasecmp(ctl->
species,
"HNO3") == 0) {
6826 }
else if (strcasecmp(ctl->
species,
"NO") == 0) {
6835 }
else if (strcasecmp(ctl->
species,
"NO2") == 0) {
6844 }
else if (strcasecmp(ctl->
species,
"O3") == 0) {
6851 }
else if (strcasecmp(ctl->
species,
"SF6") == 0) {
6855 }
else if (strcasecmp(ctl->
species,
"SO2") == 0) {
6868 sprintf(defstr,
"%g", ctl->
molmass);
6869 ctl->
molmass =
scan_ctl(filename, argc, argv,
"MOLMASS", -1, defstr, NULL);
6874 (int)
scan_ctl(filename, argc, argv,
"OH_CHEM_REACTION", -1, defstr,
6876 for (
int ip = 0; ip < 4; ip++) {
6877 sprintf(defstr,
"%g", ctl->
oh_chem[ip]);
6879 scan_ctl(filename, argc, argv,
"OH_CHEM", ip, defstr, NULL);
6882 scan_ctl(filename, argc, argv,
"OH_CHEM_BETA", -1,
"0", NULL);
6886 (int)
scan_ctl(filename, argc, argv,
"H2O2_CHEM_REACTION", -1,
"0", NULL);
6890 (int)
scan_ctl(filename, argc, argv,
"KPP_CHEM", -1,
"0", NULL);
6891 ctl->
dt_kpp =
scan_ctl(filename, argc, argv,
"DT_KPP", -1,
"1800", NULL);
6895 (int)
scan_ctl(filename, argc, argv,
"TRACER_CHEM", -1,
"0", NULL);
6899 (int)
scan_ctl(filename, argc, argv,
"RADIO_DECAY", -1,
"0", NULL);
6902 for (
int ip = 0; ip < 2; ip++) {
6905 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_H", ip, defstr, NULL);
6907 for (
int ip = 0; ip < 1; ip++) {
6910 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_H", ip, defstr, NULL);
6913 scan_ctl(filename, argc, argv,
"WET_DEPO_SO2_PH", -1,
"0", NULL);
6915 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_A", -1,
"0", NULL);
6917 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_B", -1,
"0", NULL);
6919 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_A", -1,
"0", NULL);
6921 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_B", -1,
"0", NULL);
6923 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 0,
"0.5", NULL);
6925 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 1,
"0.36", NULL);
6927 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_RET_RATIO", -1,
"1", NULL);
6929 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_RET_RATIO", -1,
"1", NULL);
6933 scan_ctl(filename, argc, argv,
"DRY_DEPO_VDEP", -1,
"0", NULL);
6935 scan_ctl(filename, argc, argv,
"DRY_DEPO_DP", -1,
"30", NULL);
6938 scan_ctl(filename, argc, argv,
"CLIM_PHOTO", -1,
6939 "../../data/clams_photolysis_rates.nc", ctl->
clim_photo);
6940 scan_ctl(filename, argc, argv,
"CLIM_HNO3_FILENAME", -1,
6942 scan_ctl(filename, argc, argv,
"CLIM_OH_FILENAME", -1,
6944 scan_ctl(filename, argc, argv,
"CLIM_H2O2_FILENAME", -1,
6946 scan_ctl(filename, argc, argv,
"CLIM_HO2_FILENAME", -1,
6948 scan_ctl(filename, argc, argv,
"CLIM_O1D_FILENAME", -1,
6950 scan_ctl(filename, argc, argv,
"CLIM_CCL4_TIMESERIES", -1,
6952 scan_ctl(filename, argc, argv,
"CLIM_CCL3F_TIMESERIES", -1,
6954 scan_ctl(filename, argc, argv,
"CLIM_CCL2F2_TIMESERIES", -1,
6956 scan_ctl(filename, argc, argv,
"CLIM_N2O_TIMESERIES", -1,
6958 scan_ctl(filename, argc, argv,
"CLIM_SF6_TIMESERIES", -1,
6963 scan_ctl(filename, argc, argv,
"MIXING_DT", -1,
"3600.", NULL);
6965 scan_ctl(filename, argc, argv,
"MIXING_TROP", -1,
"-999", NULL);
6967 scan_ctl(filename, argc, argv,
"MIXING_STRAT", -1,
"-999", NULL);
6969 scan_ctl(filename, argc, argv,
"MIXING_Z0", -1,
"-5", NULL);
6971 scan_ctl(filename, argc, argv,
"MIXING_Z1", -1,
"85", NULL);
6973 (int)
scan_ctl(filename, argc, argv,
"MIXING_NZ", -1,
"90", NULL);
6975 scan_ctl(filename, argc, argv,
"MIXING_LON0", -1,
"-180", NULL);
6977 scan_ctl(filename, argc, argv,
"MIXING_LON1", -1,
"180", NULL);
6979 (int)
scan_ctl(filename, argc, argv,
"MIXING_NX", -1,
"360", NULL);
6981 scan_ctl(filename, argc, argv,
"MIXING_LAT0", -1,
"-90", NULL);
6983 scan_ctl(filename, argc, argv,
"MIXING_LAT1", -1,
"90", NULL);
6985 (int)
scan_ctl(filename, argc, argv,
"MIXING_NY", -1,
"180", NULL);
6989 scan_ctl(filename, argc, argv,
"CHEMGRID_Z0", -1,
"-5", NULL);
6991 scan_ctl(filename, argc, argv,
"CHEMGRID_Z1", -1,
"85", NULL);
6993 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NZ", -1,
"90", NULL);
6995 scan_ctl(filename, argc, argv,
"CHEMGRID_LON0", -1,
"-180", NULL);
6997 scan_ctl(filename, argc, argv,
"CHEMGRID_LON1", -1,
"180", NULL);
6999 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NX", -1,
"360", NULL);
7001 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT0", -1,
"-90", NULL);
7003 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT1", -1,
"90", NULL);
7005 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NY", -1,
"180", NULL);
7010 scan_ctl(filename, argc, argv,
"TDEC_STRAT", -1,
"0", NULL);
7013 ctl->
psc_h2o =
scan_ctl(filename, argc, argv,
"PSC_H2O", -1,
"4e-6", NULL);
7015 scan_ctl(filename, argc, argv,
"PSC_HNO3", -1,
"9e-9", NULL);
7021 scan_ctl(filename, argc, argv,
"ATM_DT_OUT", -1,
"86400", NULL);
7023 (int)
scan_ctl(filename, argc, argv,
"ATM_FILTER", -1,
"0", NULL);
7025 (int)
scan_ctl(filename, argc, argv,
"ATM_STRIDE", -1,
"1", NULL);
7027 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE", -1,
"0", NULL);
7029 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE_OUT", -1,
"-1", NULL);
7033 (int)
scan_ctl(filename, argc, argv,
"ATM_NC_LEVEL", -1,
"0", NULL);
7034 for (
int iq = 0; iq < ctl->
nq; iq++)
7036 (
int)
scan_ctl(filename, argc, argv,
"ATM_NC_QUANT", iq,
"0", NULL);
7038 (int)
scan_ctl(filename, argc, argv,
"OBS_TYPE", -1,
"0", NULL);
7044 scan_ctl(filename, argc, argv,
"CSI_DT_OUT", -1,
"86400", NULL);
7047 scan_ctl(filename, argc, argv,
"CSI_OBSMIN", -1,
"0", NULL);
7049 scan_ctl(filename, argc, argv,
"CSI_MODMIN", -1,
"0", NULL);
7050 ctl->
csi_z0 =
scan_ctl(filename, argc, argv,
"CSI_Z0", -1,
"-5", NULL);
7051 ctl->
csi_z1 =
scan_ctl(filename, argc, argv,
"CSI_Z1", -1,
"85", NULL);
7052 ctl->
csi_nz = (int)
scan_ctl(filename, argc, argv,
"CSI_NZ", -1,
"1", NULL);
7054 scan_ctl(filename, argc, argv,
"CSI_LON0", -1,
"-180", NULL);
7055 ctl->
csi_lon1 =
scan_ctl(filename, argc, argv,
"CSI_LON1", -1,
"180", NULL);
7057 (int)
scan_ctl(filename, argc, argv,
"CSI_NX", -1,
"360", NULL);
7058 ctl->
csi_lat0 =
scan_ctl(filename, argc, argv,
"CSI_LAT0", -1,
"-90", NULL);
7059 ctl->
csi_lat1 =
scan_ctl(filename, argc, argv,
"CSI_LAT1", -1,
"90", NULL);
7061 (int)
scan_ctl(filename, argc, argv,
"CSI_NY", -1,
"180", NULL);
7064 ctl->
nens = (int)
scan_ctl(filename, argc, argv,
"NENS", -1,
"0", NULL);
7067 scan_ctl(filename, argc, argv,
"ENS_DT_OUT", -1,
"86400", NULL);
7070 scan_ctl(filename, argc, argv,
"GRID_BASENAME", -1,
"-",
7075 scan_ctl(filename, argc, argv,
"GRID_DT_OUT", -1,
"86400", NULL);
7077 (int)
scan_ctl(filename, argc, argv,
"GRID_SPARSE", -1,
"0", NULL);
7079 (int)
scan_ctl(filename, argc, argv,
"GRID_NC_LEVEL", -1,
"0", NULL);
7080 for (
int iq = 0; iq < ctl->
nq; iq++)
7082 (
int)
scan_ctl(filename, argc, argv,
"GRID_NC_QUANT", iq,
"0", NULL);
7084 (int)
scan_ctl(filename, argc, argv,
"GRID_STDDEV", -1,
"0", NULL);
7085 ctl->
grid_z0 =
scan_ctl(filename, argc, argv,
"GRID_Z0", -1,
"-5", NULL);
7086 ctl->
grid_z1 =
scan_ctl(filename, argc, argv,
"GRID_Z1", -1,
"85", NULL);
7088 (int)
scan_ctl(filename, argc, argv,
"GRID_NZ", -1,
"1", NULL);
7090 scan_ctl(filename, argc, argv,
"GRID_LON0", -1,
"-180", NULL);
7092 scan_ctl(filename, argc, argv,
"GRID_LON1", -1,
"180", NULL);
7094 (int)
scan_ctl(filename, argc, argv,
"GRID_NX", -1,
"360", NULL);
7096 scan_ctl(filename, argc, argv,
"GRID_LAT0", -1,
"-90", NULL);
7098 scan_ctl(filename, argc, argv,
"GRID_LAT1", -1,
"90", NULL);
7100 (int)
scan_ctl(filename, argc, argv,
"GRID_NY", -1,
"180", NULL);
7102 (int)
scan_ctl(filename, argc, argv,
"GRID_TYPE", -1,
"0", NULL);
7105 scan_ctl(filename, argc, argv,
"PROF_BASENAME", -1,
"-",
7108 ctl->
prof_z0 =
scan_ctl(filename, argc, argv,
"PROF_Z0", -1,
"0", NULL);
7109 ctl->
prof_z1 =
scan_ctl(filename, argc, argv,
"PROF_Z1", -1,
"60", NULL);
7111 (int)
scan_ctl(filename, argc, argv,
"PROF_NZ", -1,
"60", NULL);
7113 scan_ctl(filename, argc, argv,
"PROF_LON0", -1,
"-180", NULL);
7115 scan_ctl(filename, argc, argv,
"PROF_LON1", -1,
"180", NULL);
7117 (int)
scan_ctl(filename, argc, argv,
"PROF_NX", -1,
"360", NULL);
7119 scan_ctl(filename, argc, argv,
"PROF_LAT0", -1,
"-90", NULL);
7121 scan_ctl(filename, argc, argv,
"PROF_LAT1", -1,
"90", NULL);
7123 (int)
scan_ctl(filename, argc, argv,
"PROF_NY", -1,
"180", NULL);
7126 scan_ctl(filename, argc, argv,
"SAMPLE_BASENAME", -1,
"-",
7128 scan_ctl(filename, argc, argv,
"SAMPLE_KERNEL", -1,
"-",
7130 scan_ctl(filename, argc, argv,
"SAMPLE_OBSFILE", -1,
"-",
7133 scan_ctl(filename, argc, argv,
"SAMPLE_DX", -1,
"50", NULL);
7135 scan_ctl(filename, argc, argv,
"SAMPLE_DZ", -1,
"-999", NULL);
7138 scan_ctl(filename, argc, argv,
"STAT_BASENAME", -1,
"-",
7142 ctl->
stat_r =
scan_ctl(filename, argc, argv,
"STAT_R", -1,
"50", NULL);
7144 scan_ctl(filename, argc, argv,
"STAT_T0", -1,
"-1e100", NULL);
7145 ctl->
stat_t1 =
scan_ctl(filename, argc, argv,
"STAT_T1", -1,
"1e100", NULL);
7150 scan_ctl(filename, argc, argv,
"VTK_DT_OUT", -1,
"86400", NULL);
7152 (int)
scan_ctl(filename, argc, argv,
"VTK_STRIDE", -1,
"1", NULL);
7154 scan_ctl(filename, argc, argv,
"VTK_SCALE", -1,
"1.0", NULL);
7156 scan_ctl(filename, argc, argv,
"VTK_OFFSET", -1,
"0.0", NULL);
7158 (int)
scan_ctl(filename, argc, argv,
"VTK_SPHERE", -1,
"0", NULL);
7161 ctl->
dd = (int)
scan_ctl(filename, argc, argv,
"DD", -1,
"0", NULL);
7163 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_MERIDIONAL", -1,
7164 (ctl->
dd == 1) ?
"2" :
"1", NULL);
7166 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_ZONAL", -1,
7167 (ctl->
dd == 1) ?
"2" :
"1", NULL);
7170 else if (ctl->
dd == 1)
7171 ERRMSG(
"Please provide zonal and meridional subdomain numbers!");
7173 (int)
scan_ctl(filename, argc, argv,
"DD_HALOS_SIZE", -1,
"1", NULL);
7179 const char *filename,
7186 LOG(1,
"Read meteo data: %s", filename);
7192 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
7220 ERRMSG(
"MET_TYPE not implemented!");
7274 LOG(2,
"Broadcast data on rank %d...", rank);
7408 ERRMSG(
"Code was compiled without DD!");
7420 ERRMSG(
"Code was compiled without KPP!");
7453#pragma acc update device(ctl[:1])
7457 if (cache != NULL) {
7460#pragma acc update device(cache[:1])
7467#pragma acc update device(clim[:1])
7474 met_t *met0up = *met0;
7475#pragma acc update device(met0up[:1])
7482 met_t *met1up = *met1;
7483#pragma acc update device(met1up[:1])
7490#pragma acc update device(atm[:1])
7509#pragma acc update host(ctl[:1])
7513 if (cache != NULL) {
7516#pragma acc update host(cache[:1])
7523#pragma acc update host(clim[:1])
7530 met_t *met0up = *met0;
7531#pragma acc update host(met0up[:1])
7538 met_t *met1up = *met1;
7539#pragma acc update host(met1up[:1])
7546#pragma acc update host(atm[:1])
7554 const char *filename,
7563 LOG(1,
"Write atmospheric data: %s", filename);
7587 ERRMSG(
"Atmospheric data type not supported!");
7591 LOG(2,
"Number of particles: %d", atm->
np);
7592 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
7593 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
7594 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
7595 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
7596 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
7597 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
7598 LOG(2,
"%s range: %g ... %g %s",
7599 ctl->
met_coord_type == 0 ?
"Longitude" :
"X coordinate", mini, maxi,
7601 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
7602 LOG(2,
"%s range: %g ... %g %s",
7603 ctl->
met_coord_type == 0 ?
"Latitude" :
"Y coordinate", mini, maxi,
7605 for (
int iq = 0; iq < ctl->
nq; iq++) {
7607 sprintf(msg,
"Quantity %s range: %s ... %s %s",
7610 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
7611 LOG(2, msg, mini, maxi);
7618 const char *filename,
7626 LOG(1,
"Write meteo data: %s", filename);
7631 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
7635 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
7639 ERRMSG(
"MPTRAC was compiled without LZ4 compression!");
7643 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
7647 ERRMSG(
"MPTRAC was compiled without SZ3 compression!");
7661 ERRMSG(
"MET_TYPE not implemented!");
7667 const char *dirname,
7674 char ext[10], filename[2 *
LEN];
7678 int year, mon, day, hour, min, sec;
7681 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
7696 sprintf(ext,
"tab");
7698 sprintf(ext,
"bin");
7701 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d_%02d.%s",
7702 dirname, ctl->
atm_basename, year, mon, day, hour, min, sec, ext);
7708 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d_%02d.%s",
7709 dirname, ctl->
grid_basename, year, mon, day, hour, min, sec,
7711 write_grid(filename, ctl, met0, met1, atm, t);
7716 sprintf(filename,
"%s/%s.tab", dirname, ctl->
csi_basename);
7722 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d_%02d.tab",
7723 dirname, ctl->
ens_basename, year, mon, day, hour, min, sec);
7729 sprintf(filename,
"%s/%s.tab", dirname, ctl->
prof_basename);
7730 write_prof(filename, ctl, met0, met1, atm, t);
7741 sprintf(filename,
"%s/%s.tab", dirname, ctl->
stat_basename);
7750 sprintf(filename,
"%s/%s_%05d.vtk", dirname, ctl->
vtk_basename, ++nvtk);
7760 const double hno3) {
7763 const double h2o_help =
MAX(h2o, 0.1e-6);
7766 const double p_hno3 = hno3 * p / 1.333224;
7767 const double p_h2o = h2o_help * p / 1.333224;
7768 const double a = 0.009179 - 0.00088 * log10(p_h2o);
7769 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
7770 const double c = -11397.0 / a;
7771 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
7772 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
7790 const double p0 = pbl;
7793 if (atm->
p[ip] > p0)
7795 else if (atm->
p[ip] < p1)
7798 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
7804 const char *filename,
7810 if (!(in = fopen(filename,
"r"))) {
7811 WARN(
"Cannot open file!");
7817 while (fgets(line,
LEN, in)) {
7821 TOK(line, tok,
"%lg", atm->
time[atm->
np]);
7822 TOK(NULL, tok,
"%lg", atm->
p[atm->
np]);
7823 TOK(NULL, tok,
"%lg", atm->
lon[atm->
np]);
7824 TOK(NULL, tok,
"%lg", atm->
lat[atm->
np]);
7825 for (
int iq = 0; iq < ctl->
nq; iq++)
7826 TOK(NULL, tok,
"%lg", atm->
q[iq][atm->
np]);
7829 atm->
p[atm->
np] =
P(atm->
p[atm->
np]);
7832 if ((++atm->
np) >
NP)
7833 ERRMSG(
"Too many data points!");
7846 const char *filename,
7852 if (!(in = fopen(filename,
"r")))
7857 FREAD(&version,
int,
7861 ERRMSG(
"Wrong version of binary data!");
7879 for (
int iq = 0; iq < ctl->
nq; iq++)
7880 FREAD(atm->
q[iq],
double,
7890 ERRMSG(
"Error while reading binary data!");
7902 const char *filename,
7907 ERRMSG(
"CLaMS atmospheric files support only lat/lon grids");
7912 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
7919 if (nc_inq_varid(ncid,
"TIME_INIT", &varid) == NC_NOERR) {
7920 NC(nc_get_var_double(ncid, varid, atm->
time));
7922 WARN(
"TIME_INIT not found use time instead!");
7925 for (
int ip = 0; ip < atm->
np; ip++) {
7926 atm->
time[ip] = time_init;
7938 if (nc_inq_varid(ncid,
"PRESS_INIT", &varid) == NC_NOERR) {
7939 NC(nc_get_var_double(ncid, varid, atm->
p));
7941 WARN(
"PRESS_INIT not found use PRESS instead!");
7942 nc_inq_varid(ncid,
"PRESS", &varid);
7943 NC(nc_get_var_double(ncid, varid, atm->
p));
7948 for (
int iq = 0; iq < ctl->
nq; iq++)
7965 const char *filename,
7972 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
7985 for (
int iq = 0; iq < ctl->
nq; iq++)
7998 const char *filename,
8004 LOG(1,
"Read photolysis rates: %s", filename);
8007 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
8008 WARN(
"Photolysis rate data are missing!");
8015 if (photo->
p[0] < photo->
p[1])
8016 ERRMSG(
"Pressure data are not descending!");
8021 if (photo->
o3c[0] > photo->
o3c[1])
8022 ERRMSG(
"Total column ozone data are not ascending!");
8027 if (photo->
sza[0] > photo->
sza[1])
8028 ERRMSG(
"Solar zenith angle data are not ascending!");
8045 LOG(2,
"Number of pressure levels: %d", photo->
np);
8046 LOG(2,
"Altitude levels: %g, %g ... %g km",
8047 Z(photo->
p[0]),
Z(photo->
p[1]),
Z(photo->
p[photo->
np - 1]));
8048 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
8049 photo->
p[0], photo->
p[1], photo->
p[photo->
np - 1]);
8050 LOG(2,
"Number of solar zenith angles: %d", photo->
nsza);
8051 LOG(2,
"Solar zenith angles: %g, %g ... %g deg",
8054 LOG(2,
"Number of total column ozone values: %d", photo->
no3c);
8055 LOG(2,
"Total column ozone: %g, %g ... %g DU",
8057 LOG(2,
"N2O photolysis rate: %g, %g ... %g s**-1",
8058 photo->
n2o[0][0][0], photo->
n2o[1][0][0],
8059 photo->
n2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
8060 LOG(2,
"CCl4 photolysis rate: %g, %g ... %g s**-1",
8061 photo->
ccl4[0][0][0], photo->
ccl4[1][0][0],
8063 LOG(2,
"CFC-11 photolysis rate: %g, %g ... %g s**-1",
8064 photo->
ccl3f[0][0][0], photo->
ccl3f[1][0][0],
8066 LOG(2,
"CFC-12 photolysis rate: %g, %g ... %g s**-1",
8069 LOG(2,
"O2 photolysis rate: %g, %g ... %g s**-1",
8070 photo->
o2[0][0][0], photo->
o2[1][0][0],
8071 photo->
o2[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
8072 LOG(2,
"O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
8073 photo->
o3_1[0][0][0], photo->
o3_1[1][0][0],
8075 LOG(2,
"O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
8076 photo->
o3_2[0][0][0], photo->
o3_2[1][0][0],
8078 LOG(2,
"H2O2 photolysis rate: %g, %g ... %g s**-1",
8079 photo->
h2o2[0][0][0], photo->
h2o2[1][0][0],
8081 LOG(2,
"H2O photolysis rate: %g, %g ... %g s**-1",
8082 photo->
h2o[0][0][0], photo->
h2o[1][0][0],
8083 photo->
h2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
8090 const char *varname,
8104 for (
int ip = 0; ip < photo->
np; ip++)
8105 for (
int is = 0; is < photo->
nsza; is++)
8106 for (
int io = 0; io < photo->
no3c; io++)
8117 const char *filename,
8121 LOG(1,
"Read climatological time series: %s", filename);
8125 if (!(in = fopen(filename,
"r"))) {
8126 WARN(
"Cannot open file!");
8133 while (fgets(line,
LEN, in))
8134 if (sscanf(line,
"%lg %lg", &ts->
time[nh], &ts->
vmr[nh]) == 2) {
8137 ts->
time[nh] = (ts->
time[nh] - 2000.0) * 365.25 * 86400.;
8140 if (nh > 0 && ts->
time[nh] <= ts->
time[nh - 1])
8141 ERRMSG(
"Time series must be ascending!");
8145 ERRMSG(
"Too many data points!");
8154 ERRMSG(
"Not enough data points!");
8157 LOG(2,
"Number of time steps: %d", ts->
ntime);
8158 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s", ts->
time[0], ts->
time[1],
8160 LOG(2,
"Volume mixing ratio range: %g ... %g ppv",
8161 gsl_stats_min(ts->
vmr, 1, (
size_t) nh), gsl_stats_max(ts->
vmr, 1,
8171 const char *filename,
8172 const char *varname,
8175 int ncid, varid, it, iy, iz, iz2, nt;
8177 double *help, varmin = 1e99, varmax = -1e99;
8180 LOG(1,
"Read %s data: %s", varname, filename);
8183 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
8184 WARN(
"%s climatology data are missing!", varname);
8191 if (zm->
p[0] < zm->
p[1])
8192 ERRMSG(
"Pressure data are not descending!");
8197 if (zm->
lat[0] > zm->
lat[1])
8198 ERRMSG(
"Latitude data are not ascending!");
8202 zm->
time[0] = 1209600.00;
8203 zm->
time[1] = 3888000.00;
8204 zm->
time[2] = 6393600.00;
8205 zm->
time[3] = 9072000.00;
8206 zm->
time[4] = 11664000.00;
8207 zm->
time[5] = 14342400.00;
8208 zm->
time[6] = 16934400.00;
8209 zm->
time[7] = 19612800.00;
8210 zm->
time[8] = 22291200.00;
8211 zm->
time[9] = 24883200.00;
8212 zm->
time[10] = 27561600.00;
8213 zm->
time[11] = 30153600.00;
8222 for (it = 0; it < zm->
ntime; it++)
8223 for (iz = 0; iz < zm->
np; iz++)
8224 for (iy = 0; iy < zm->
nlat; iy++)
8229 for (it = 0; it < zm->
ntime; it++)
8230 for (iy = 0; iy < zm->
nlat; iy++)
8231 for (iz = 0; iz < zm->
np; iz++) {
8232 if (zm->
vmr[it][iz][iy] < 0) {
8233 for (iz2 = 0; iz2 < zm->
np; iz2++)
8234 if (zm->
vmr[it][iz2][iy] >= 0) {
8235 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
8238 for (iz2 = zm->
np - 1; iz2 >= 0; iz2--)
8239 if (zm->
vmr[it][iz2][iy] >= 0) {
8240 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
8244 varmin =
MIN(varmin, zm->
vmr[it][iz][iy]);
8245 varmax =
MAX(varmax, zm->
vmr[it][iz][iy]);
8252 LOG(2,
"Number of time steps: %d", zm->
ntime);
8253 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
8255 LOG(2,
"Number of pressure levels: %d", zm->
np);
8256 LOG(2,
"Altitude levels: %g, %g ... %g km",
8257 Z(zm->
p[0]),
Z(zm->
p[1]),
Z(zm->
p[zm->
np - 1]));
8258 LOG(2,
"Pressure levels: %g, %g ... %g hPa", zm->
p[0],
8259 zm->
p[1], zm->
p[zm->
np - 1]);
8260 LOG(2,
"Number of latitudes: %d", zm->
nlat);
8261 LOG(2,
"Latitudes: %g, %g ... %g deg",
8263 LOG(2,
"%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
8270 const char *filename,
8276 LOG(1,
"Read kernel function: %s", filename);
8280 if (!(in = fopen(filename,
"r")))
8281 ERRMSG(
"Cannot open file!");
8286 while (fgets(line,
LEN, in))
8287 if (sscanf(line,
"%lg %lg", &kz[n], &kw[n]) == 2) {
8288 if (n > 0 && kz[n] < kz[n - 1])
8289 ERRMSG(
"Height levels must be ascending!");
8291 ERRMSG(
"Too many height levels!");
8300 ERRMSG(
"Not enough height levels!");
8303 const double kmax = gsl_stats_max(kw, 1, (
size_t) n);
8304 for (
int iz = 0; iz < n; iz++)
8311 const char *filename,
8319 int year, mon, day, hour, min, sec;
8325 if (!(in = fopen(filename,
"r"))) {
8326 WARN(
"Cannot open file!");
8332 FREAD(&met_type,
int,
8336 ERRMSG(
"Wrong MET_TYPE of binary data!");
8340 FREAD(&version,
int,
8344 ERRMSG(
"Wrong version of binary data!");
8350 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
8351 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
8352 met->
time, year, mon, day, hour, min);
8353 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
8354 || day < 1 || day > 31 || hour < 0 || hour > 23)
8355 ERRMSG(
"Error while reading time!");
8363 LOG(2,
"Number of %s: %d",
8364 (met->
coord_type == 0) ?
"longitudes" :
"x coordinates", met->
nx);
8365 if (met->
nx < 2 || met->
nx >
EX)
8367 ?
"Number of longitudes out of range!"
8368 :
"Number of x coordinates out of range!");
8373 LOG(2,
"Number of %s: %d",
8374 (met->
coord_type == 0) ?
"latitudes" :
"y coordinates", met->
ny);
8375 if (met->
ny < 2 || met->
ny >
EY)
8377 ?
"Number of latitudes out of range!"
8378 :
"Number of y coordinates out of range!");
8383 LOG(2,
"Number of levels: %d", met->
np);
8384 if (met->
np < 2 || met->
np >
EP)
8385 ERRMSG(
"Number of levels out of range!");
8391 LOG(2,
"%s: %g, %g ... %g %s",
8392 met->
coord_type == 0 ?
"Longitudes" :
"X coordinates",
8399 LOG(2,
"%s: %g, %g ... %g %s",
8400 met->
coord_type == 0 ?
"Latitudes" :
"Y coordinates",
8407 LOG(2,
"Altitude levels: %g, %g ... %g km",
8408 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
8409 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
8410 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
8459 ERRMSG(
"Error while reading binary data!");
8474 const char *varname) {
8483 LOG(2,
"Read 2-D variable: %s (uncompressed)", varname);
8485 (
size_t) (met->
nx * met->
ny),
8489 for (
int ix = 0; ix < met->
nx; ix++)
8490 for (
int iy = 0; iy < met->
ny; iy++)
8491 var[ix][iy] = help[
ARRAY_2D(ix, iy, met->
ny)];
8504 const char *varname,
8505 const float bound_min,
8506 const float bound_max) {
8516 LOG(2,
"Read 3-D variable: %s (uncompressed)", varname);
8518 (
size_t) (met->
nx * met->
ny * met->
np),
8530 FREAD(&precision,
int,
8535 FREAD(&tolerance,
double,
8541 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
8550 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
8559 ERRMSG(
"MPTRAC was compiled without LZ4 compression!");
8568 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
8576 FREAD(&precision,
int,
8581 FREAD(&tolerance,
double,
8587 ERRMSG(
"MPTRAC was compiled without sz3 compression!");
8592#pragma omp parallel for default(shared) collapse(2)
8593 for (
int ix = 0; ix < met->
nx; ix++)
8594 for (
int iy = 0; iy < met->
ny; iy++)
8595 for (
int ip = 0; ip < met->
np; ip++) {
8596 var[ix][iy][ip] = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
8597 if (var[ix][iy][ip] < bound_min)
8598 var[ix][iy][ip] = bound_min;
8599 else if (var[ix][iy][ip] > bound_max)
8600 var[ix][iy][ip] = bound_max;
8619 ERRMSG(
"Only lat/lon grid supported");
8623 LOG(2,
"Calculate CAPE...");
8626 const double pfac = 1.01439, dz0 =
RI /
MA /
G0 * log(pfac);
8629#pragma omp parallel for default(shared) collapse(2)
8630 for (
int ix = 0; ix < met->
nx; ix++)
8631 for (
int iy = 0; iy < met->
ny; iy++) {
8635 double h2o = 0, t, theta = 0;
8636 double pbot =
MIN(met->
ps[ix][iy], met->
p[0]);
8637 double ptop = pbot - 50.;
8638 for (
int ip = 0; ip < met->
np; ip++) {
8639 if (met->
p[ip] <= pbot) {
8640 theta +=
THETA(met->
p[ip], met->
t[ix][iy][ip]);
8641 h2o += met->
h2o[ix][iy][ip];
8644 if (met->
p[ip] < ptop && n > 0)
8651 met->
plcl[ix][iy] = NAN;
8652 met->
plfc[ix][iy] = NAN;
8653 met->
pel[ix][iy] = NAN;
8654 met->
cape[ix][iy] = NAN;
8655 met->
cin[ix][iy] = NAN;
8661 pbot = met->
ps[ix][iy];
8663 met->
plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
8664 t = theta / pow(1000. / met->
plcl[ix][iy], 0.286);
8665 if (
RH(met->
plcl[ix][iy], t, h2o) > 100.)
8666 ptop = met->
plcl[ix][iy];
8668 pbot = met->
plcl[ix][iy];
8669 }
while (pbot - ptop > 0.1);
8673 double dcape, dz, h2o_env, t_env;
8674 double p = met->
ps[ix][iy];
8675 met->
cape[ix][iy] = met->
cin[ix][iy] = 0;
8677 dz = dz0 *
TVIRT(t, h2o);
8679 t = theta / pow(1000. / p, 0.286);
8683 &h2o_env, ci, cw, 0);
8684 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
8685 TVIRT(t_env, h2o_env) * dz;
8687 met->
cin[ix][iy] += fabsf((
float) dcape);
8688 }
while (p > met->
plcl[ix][iy]);
8693 p = met->
plcl[ix][iy];
8694 t = theta / pow(1000. / p, 0.286);
8699 dz = dz0 *
TVIRT(t, h2o);
8702 double psat =
PSAT(t);
8703 h2o = psat / (p - (1. -
EPS) * psat);
8707 &h2o_env, ci, cw, 0);
8708 double dcape_old = dcape;
8709 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
8710 TVIRT(t_env, h2o_env) * dz;
8712 met->
cape[ix][iy] += (float) dcape;
8713 if (!isfinite(met->
plfc[ix][iy]))
8714 met->
plfc[ix][iy] = (
float) p;
8715 }
else if (dcape_old > 0)
8716 met->
pel[ix][iy] = (float) p;
8717 if (dcape < 0 && !isfinite(met->
plfc[ix][iy]))
8718 met->
cin[ix][iy] += fabsf((
float) dcape);
8722 if (!isfinite(met->
plfc[ix][iy]))
8723 met->
cin[ix][iy] = NAN;
8734 LOG(2,
"Calculate cloud data...");
8737 const double ccmin = 0.01, cwmin = 1e-6;
8740#pragma omp parallel for default(shared) collapse(2)
8741 for (
int ix = 0; ix < met->
nx; ix++)
8742 for (
int iy = 0; iy < met->
ny; iy++) {
8745 met->
pct[ix][iy] = NAN;
8746 met->
pcb[ix][iy] = NAN;
8747 met->
cl[ix][iy] = 0;
8750 for (
int ip = 0; ip < met->
np - 1; ip++) {
8753 if (met->
p[ip] > met->
ps[ix][iy] || met->
p[ip] <
P(20.))
8757 if (met->
cc[ix][iy][ip] > ccmin
8758 && (met->
lwc[ix][iy][ip] > cwmin
8759 || met->
rwc[ix][iy][ip] > cwmin
8760 || met->
iwc[ix][iy][ip] > cwmin
8761 || met->
swc[ix][iy][ip] > cwmin)) {
8765 = (float) (0.5 * (met->
p[ip] + (
float) met->
p[ip + 1]));
8768 if (!isfinite(met->
pcb[ix][iy]))
8770 = (
float) (0.5 * (met->
p[ip] + met->
p[
MAX(ip - 1, 0)]));
8774 met->
cl[ix][iy] += (float)
8775 (0.5 * (met->
lwc[ix][iy][ip] + met->
lwc[ix][iy][ip + 1]
8776 + met->
rwc[ix][iy][ip] + met->
rwc[ix][iy][ip + 1]
8777 + met->
iwc[ix][iy][ip] + met->
iwc[ix][iy][ip + 1]
8778 + met->
swc[ix][iy][ip] + met->
swc[ix][iy][ip + 1])
8779 * 100. * (met->
p[ip] - met->
p[ip + 1]) /
G0);
8797 ERRMSG(
"Only lat/lon grid supported");
8801 LOG(2,
"Detrend meteo data...");
8808 const double tssq = 2. *
SQR(sigma);
8811 int sy = (int) (3. *
DY2DEG(sigma) / fabs(met->
lat[1] - met->
lat[0]));
8815#pragma omp parallel for default(shared) collapse(2)
8816 for (
int ix = 0; ix < met->
nx; ix++) {
8817 for (
int iy = 0; iy < met->
ny; iy++) {
8825 (int) (3. *
DX2DEG(sigma, met->
lat[iy]) /
8826 fabs(met->
lon[1] - met->
lon[0]));
8831 for (
int ip = 0; ip < met->
np; ip++) {
8832 help->
t[ix][iy][ip] = 0;
8833 help->
u[ix][iy][ip] = 0;
8834 help->
v[ix][iy][ip] = 0;
8835 help->
w[ix][iy][ip] = 0;
8839 for (
int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
8843 else if (ix3 >= met->
nx)
8845 for (
int iy2 =
MAX(iy - sy, 0);
8846 iy2 <=
MIN(iy + sy, met->
ny - 1); iy2++) {
8853 const float w = (float) exp(-
DIST2(x0, x1) / tssq);
8857 for (
int ip = 0; ip < met->
np; ip++) {
8858 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip];
8859 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip];
8860 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip];
8861 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip];
8867 for (
int ip = 0; ip < met->
np; ip++) {
8868 help->
t[ix][iy][ip] /= wsum;
8869 help->
u[ix][iy][ip] /= wsum;
8870 help->
v[ix][iy][ip] /= wsum;
8871 help->
w[ix][iy][ip] /= wsum;
8877#pragma omp parallel for default(shared) collapse(3)
8878 for (
int ix = 0; ix < met->
nx; ix++)
8879 for (
int iy = 0; iy < met->
ny; iy++)
8880 for (
int ip = 0; ip < met->
np; ip++) {
8881 met->
t[ix][iy][ip] -= help->
t[ix][iy][ip];
8882 met->
u[ix][iy][ip] -= help->
u[ix][iy][ip];
8883 met->
v[ix][iy][ip] -= help->
v[ix][iy][ip];
8884 met->
w[ix][iy][ip] -= help->
w[ix][iy][ip];
8898 LOG(2,
"Extrapolate meteo data...");
8901#pragma omp parallel for default(shared) collapse(2)
8902 for (
int ix = 0; ix < met->
nx; ix++)
8903 for (
int iy = 0; iy < met->
ny; iy++) {
8907 for (ip0 = met->
np - 1; ip0 >= 0; ip0--)
8908 if (!isfinite(met->
t[ix][iy][ip0])
8909 || !isfinite(met->
u[ix][iy][ip0])
8910 || !isfinite(met->
v[ix][iy][ip0])
8911 || !isfinite(met->
w[ix][iy][ip0]))
8915 for (
int ip = ip0; ip >= 0; ip--) {
8916 met->
t[ix][iy][ip] = met->
t[ix][iy][ip + 1];
8917 met->
u[ix][iy][ip] = met->
u[ix][iy][ip + 1];
8918 met->
v[ix][iy][ip] = met->
v[ix][iy][ip + 1];
8919 met->
w[ix][iy][ip] = met->
w[ix][iy][ip + 1];
8920 met->
h2o[ix][iy][ip] = met->
h2o[ix][iy][ip + 1];
8921 met->
o3[ix][iy][ip] = met->
o3[ix][iy][ip + 1];
8922 met->
lwc[ix][iy][ip] = met->
lwc[ix][iy][ip + 1];
8923 met->
rwc[ix][iy][ip] = met->
rwc[ix][iy][ip + 1];
8924 met->
iwc[ix][iy][ip] = met->
iwc[ix][iy][ip + 1];
8925 met->
swc[ix][iy][ip] = met->
swc[ix][iy][ip + 1];
8926 met->
cc[ix][iy][ip] = met->
cc[ix][iy][ip + 1];
8945 LOG(2,
"Calculate geopotential heights...");
8952#pragma omp parallel for default(shared)
8953 for (
int ip = 0; ip < met->
np; ip++)
8954 logp[ip] = log(met->
p[ip]);
8957#pragma omp parallel for default(shared) collapse(2)
8958 for (
int ix = 0; ix < met->
nx; ix++)
8959 for (
int iy = 0; iy < met->
ny; iy++) {
8962 const double zs = met->
zs[ix][iy];
8963 const double lnps = log(met->
ps[ix][iy]);
8967 const double ts =
LIN(met->
p[ip0], met->
t[ix][iy][ip0], met->
p[ip0 + 1],
8968 met->
t[ix][iy][ip0 + 1], met->
ps[ix][iy]);
8970 LIN(met->
p[ip0], met->
h2o[ix][iy][ip0], met->
p[ip0 + 1],
8971 met->
h2o[ix][iy][ip0 + 1], met->
ps[ix][iy]);
8974 met->
z[ix][iy][ip0 + 1]
8976 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
8977 met->
t[ix][iy][ip0 + 1], met->
h2o[ix][iy][ip0 + 1]));
8978 for (
int ip = ip0 + 2; ip < met->
np; ip++)
8980 = (
float) (met->
z[ix][iy][ip - 1] +
8981 ZDIFF(logp[ip - 1], met->
t[ix][iy][ip - 1],
8982 met->
h2o[ix][iy][ip - 1], logp[ip],
8983 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
8988 ZDIFF(lnps, ts, h2os, logp[ip0],
8989 met->
t[ix][iy][ip0], met->
h2o[ix][iy][ip0]));
8990 for (
int ip = ip0 - 1; ip >= 0; ip--)
8992 = (
float) (met->
z[ix][iy][ip + 1] +
8993 ZDIFF(logp[ip + 1], met->
t[ix][iy][ip + 1],
8994 met->
h2o[ix][iy][ip + 1], logp[ip],
8995 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
8999 if (dx == 0 || dy == 0)
9003 if (dx < 0 || dy < 0) {
9004 if (fabs(met->
lon[1] - met->
lon[0]) < 0.5) {
9014 float ws[dx + 1][dy + 1];
9015#pragma omp parallel for default(shared) collapse(2)
9016 for (
int ix = 0; ix <= dx; ix++)
9017 for (
int iy = 0; iy < dy; iy++)
9018 ws[ix][iy] = (1.0f - (
float) ix / (float) dx)
9019 * (1.0f - (float) iy / (
float) dy);
9022#pragma omp parallel for default(shared) collapse(3)
9023 for (
int ix = 0; ix < met->
nx; ix++)
9024 for (
int iy = 0; iy < met->
ny; iy++)
9025 for (
int ip = 0; ip < met->
np; ip++)
9026 help[
ARRAY_3D(ip, ix, met->
nx, iy, met->
ny)] = met->
z[ix][iy][ip];
9029#pragma omp parallel for default(shared) collapse(3)
9030 for (
int ip = 0; ip < met->
np; ip++)
9031 for (
int ix = 0; ix < met->
nx; ix++)
9032 for (
int iy = 0; iy < met->
ny; iy++) {
9033 float res = 0, wsum = 0;
9034 int iy0 =
MAX(iy - dy + 1, 0);
9035 int iy1 =
MIN(iy + dy - 1, met->
ny - 1);
9036 for (
int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
9040 else if (ix3 >= met->
nx)
9042 for (
int iy2 = iy0; iy2 <= iy1; ++iy2)
9043 if (isfinite(help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)])) {
9044 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
9045 res += w * help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)];
9050 met->
z[ix][iy][ip] = res / wsum;
9052 met->
z[ix][iy][ip] = NAN;
9062 const char *filename,
9068 char levname[
LEN], tstr[10];
9070 double rtime = 0, r, r2;
9072 int varid, ndims, dimids[NC_MAX_DIMS], year2, mon2, day2, hour2, min2, sec2,
9073 year, mon, day, hour, min, sec;
9079 LOG(2,
"Read meteo grid information...");
9088 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
9089 if (nc_inq_varid(ncid,
"time", &varid) == NC_NOERR) {
9090 NC(nc_get_var_double(ncid, varid, &rtime));
9091 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
9092 WARN(
"Time information in meteo file does not match filename!");
9094 WARN(
"Time information in meteo file is missing!");
9105 sprintf(tstr,
"19%.2s", &filename[strlen(filename) - 11]);
9107 sprintf(tstr,
"20%.2s", &filename[strlen(filename) - 11]);
9109 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 9]);
9111 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 7]);
9113 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 5]);
9119 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
9120 || day < 1 || day > 31 || hour < 0 || hour > 23)
9121 ERRMSG(
"Cannot read time from filename!");
9122 jsec2time(met->
time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
9123 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
9124 met->
time, year2, mon2, day2, hour2, min2);
9127 if (nc_inq_varid(ncid,
"u", &varid) != NC_NOERR)
9128 if (nc_inq_varid(ncid,
"U", &varid) != NC_NOERR)
9130 (
"Variable 'u' or 'U' not found, cannot determine vertical dimension!");
9132 NC(nc_inq_varndims(ncid, varid, &ndims));
9133 NC(nc_inq_vardimid(ncid, varid, dimids));
9137 (ncid, dimids[ctl->
met_convention == 0 ? 1 : 3], levname, &dimlen));
9138 }
else if (ndims == 3) {
9140 (ncid, dimids[ctl->
met_convention == 0 ? 0 : 2], levname, &dimlen));
9142 ERRMSG(
"Cannot determine vertical dimension!")
9143 met->
np = (int) dimlen;
9145 LOG(2,
"Number of levels: %d", met->
np);
9146 if (met->
np < 2 || met->
np >
EP)
9147 ERRMSG(
"Number of levels out of range!");
9155 LOG(2,
"Number of longitudes: %d", met->
nx);
9158 LOG(2,
"Number of latitudes: %d", met->
ny);
9161 LOG(2,
"Longitudes: %g, %g ... %g deg",
9164 LOG(2,
"Latitudes: %g, %g ... %g deg",
9170 LOG(2,
"Number of x coordinates: %d", met->
nx);
9173 LOG(2,
"Number of y coordinates: %d", met->
ny);
9176 LOG(2,
"X coordinates: %g, %g ... %g m",
9179 LOG(2,
"Y coordinates: %g, %g ... %g m",
9186 ERRMSG(
"Domain decomposition is only supported for lat/lon grids!");
9196 for (
int ip = 0; ip < met->
np; ip++)
9198 LOG(2,
"Altitude levels: %g, %g ... %g km",
9199 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
9200 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
9201 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
9205 if (strcasecmp(levname,
"hybrid") == 0)
9217 ERRMSG(
"You need to specify MET_NLEV, MET_LEV_HYAM, and MET_LEV_HYBM!");
9218 for (
int ip = 0; ip < ctl->
met_nlev; ip++) {
9226 met->
eta[k] = met->
hyam[k] / 100000.0 + met->
hybm[k];
9228 ERRMSG(
"Eta levels must be ascending!");
9232 for (
int ix = 2; ix < met->
nx; ix++)
9234 (fabs(met->
lon[ix] - met->
lon[ix - 1]) -
9235 fabs(met->
lon[1] - met->
lon[0])) > 0.001)
9236 ERRMSG(
"No regular grid spacing in longitudes!");
9237 for (
int iy = 2; iy < met->
ny; iy++)
9239 (fabs(met->
lat[iy] - met->
lat[iy - 1]) -
9240 fabs(met->
lat[1] - met->
lat[0])) > 0.001) {
9241 WARN(
"No regular grid spacing in latitudes!");
9256 LOG(2,
"Read surface data...");
9260 (ncid,
"lnsp",
"LNSP", NULL, NULL, NULL, NULL, ctl, met, dd, met->
ps,
9262 for (
int ix = 0; ix < met->
nx; ix++)
9263 for (
int iy = 0; iy < met->
ny; iy++)
9264 met->
ps[ix][iy] = (
float) (exp(met->
ps[ix][iy]) / 100.);
9267 (ncid,
"ps",
"PS",
"sp",
"SP", NULL, NULL, ctl, met, dd, met->
ps,
9269 WARN(
"Cannot not read surface pressure data (use lowest level)!");
9270 for (
int ix = 0; ix < met->
nx; ix++)
9271 for (
int iy = 0; iy < met->
ny; iy++)
9273 = (ctl->
met_np > 0 ? (
float) ctl->
met_p[0] : (
float) met->
p[0]);
9281 (ncid,
"z",
"Z", NULL, NULL, NULL, NULL, ctl, met, dd, met->
zs,
9282 (
float) (1. / (1000. *
G0)), 1))
9284 (ncid,
"zm",
"ZM", NULL, NULL, NULL, NULL, ctl, met, dd, met->
zs,
9285 (
float) (1. / 1000.), 1))
9286 WARN(
"Cannot read surface geopotential height!");
9297 memcpy(help, met->
pl,
sizeof(met->
pl));
9299 (ncid,
"gph",
"GPH", NULL, NULL, ctl, met, dd, met->
pl,
9300 (
float) (1e-3 /
G0)))
9301 ERRMSG(
"Cannot read geopotential height!");
9302 for (
int ix = 0; ix < met->
nx; ix++)
9303 for (
int iy = 0; iy < met->
ny; iy++)
9304 met->
zs[ix][iy] = met->
pl[ix][iy][0];
9305 memcpy(met->
pl, help,
sizeof(met->
pl));
9311 (ncid,
"t2m",
"T2M",
"2t",
"2T",
"t2",
"T2", ctl, met, dd, met->
ts, 1.0,
9313 WARN(
"Cannot read surface temperature!");
9317 (ncid,
"u10m",
"U10M",
"10u",
"10U",
"u10",
"U10", ctl, met, dd,
9319 WARN(
"Cannot read surface zonal wind!");
9323 (ncid,
"v10m",
"V10M",
"10v",
"10V",
"v10",
"V10", ctl, met, dd,
9325 WARN(
"Cannot read surface meridional wind!");
9329 (ncid,
"iews",
"IEWS", NULL, NULL, NULL, NULL, ctl, met, dd, met->
ess,
9331 WARN(
"Cannot read eastward turbulent surface stress!");
9335 (ncid,
"inss",
"INSS", NULL, NULL, NULL, NULL, ctl, met, dd, met->
nss,
9337 WARN(
"Cannot read nothward turbulent surface stress!");
9341 (ncid,
"ishf",
"ISHF", NULL, NULL, NULL, NULL, ctl, met, dd, met->
shf,
9343 WARN(
"Cannot read surface sensible heat flux!");
9347 (ncid,
"lsm",
"LSM", NULL, NULL, NULL, NULL, ctl, met, dd, met->
lsm,
9349 WARN(
"Cannot read land-sea mask!");
9353 (ncid,
"sstk",
"SSTK",
"sst",
"SST", NULL, NULL, ctl, met, dd, met->
sst,
9355 WARN(
"Cannot read sea surface temperature!");
9360 (ncid,
"blp",
"BLP", NULL, NULL, NULL, NULL, ctl, met, dd, met->
pbl,
9362 WARN(
"Cannot read planetary boundary layer pressure!");
9365 (ncid,
"blh",
"BLH", NULL, NULL, NULL, NULL, ctl, met, dd, met->
pbl,
9367 WARN(
"Cannot read planetary boundary layer height!");
9372 (ncid,
"cape",
"CAPE", NULL, NULL, NULL, NULL, ctl, met, dd,
9374 WARN(
"Cannot read CAPE!");
9379 (ncid,
"cin",
"CIN", NULL, NULL, NULL, NULL, ctl, met, dd, met->
cin,
9381 WARN(
"Cannot read convective inhibition!");
9394 LOG(2,
"Read level data...");
9398 (ncid,
"t",
"T",
"temp",
"TEMP", ctl, met, dd, met->
t, 1.0))
9399 ERRMSG(
"Cannot read temperature!");
9402 if (!
read_met_nc_3d(ncid,
"u",
"U", NULL, NULL, ctl, met, dd, met->
u, 1.0))
9403 ERRMSG(
"Cannot read zonal wind!");
9404 if (!
read_met_nc_3d(ncid,
"v",
"V", NULL, NULL, ctl, met, dd, met->
v, 1.0))
9405 ERRMSG(
"Cannot read meridional wind!");
9407 (ncid,
"w",
"W",
"omega",
"OMEGA", ctl, met, dd, met->
w, 0.01f))
9408 WARN(
"Cannot read vertical velocity!");
9413 (ncid,
"q",
"Q",
"sh",
"SH", ctl, met, dd, met->
h2o,
9415 WARN(
"Cannot read specific humidity!");
9418 (ncid,
"rh",
"RH", NULL, NULL, ctl, met, dd, met->
h2o, 0.01f))
9419 WARN(
"Cannot read relative humidity!");
9420#pragma omp parallel for default(shared) collapse(2)
9421 for (
int ix = 0; ix < met->
nx; ix++)
9422 for (
int iy = 0; iy < met->
ny; iy++)
9423 for (
int ip = 0; ip < met->
np; ip++) {
9424 double pw = met->
h2o[ix][iy][ip] *
PSAT(met->
t[ix][iy][ip]);
9425 met->
h2o[ix][iy][ip] =
9426 (float) (pw / (met->
p[ip] - (1.0 -
EPS) * pw));
9432 (ncid,
"o3",
"O3", NULL, NULL, ctl, met, dd, met->
o3,
9433 (
float) (
MA /
MO3)))
9434 WARN(
"Cannot read ozone data!");
9438 (ncid,
"clwc",
"CLWC", NULL, NULL, ctl, met, dd, met->
lwc, 1.0))
9439 WARN(
"Cannot read cloud liquid water content!");
9441 (ncid,
"crwc",
"CRWC", NULL, NULL, ctl, met, dd, met->
rwc, 1.0))
9442 WARN(
"Cannot read cloud rain water content!");
9444 (ncid,
"ciwc",
"CIWC", NULL, NULL, ctl, met, dd, met->
iwc, 1.0))
9445 WARN(
"Cannot read cloud ice water content!");
9447 (ncid,
"cswc",
"CSWC", NULL, NULL, ctl, met, dd, met->
swc, 1.0))
9448 WARN(
"Cannot read cloud snow water content!");
9450 (ncid,
"cc",
"CC", NULL, NULL, ctl, met, dd, met->
cc, 1.0))
9451 WARN(
"Cannot read cloud cover!");
9456 (ncid,
"ZETA",
"zeta", NULL, NULL, ctl, met, dd, met->
zetal, 1.0))
9457 WARN(
"Cannot read ZETA!");
9459 (ncid,
"ZETA_DOT_TOT",
"ZETA_DOT_clr",
"zeta_dot_clr",
9460 NULL, ctl, met, dd, met->
zeta_dotl, 0.00001157407f))
9461 WARN(
"Cannot read ZETA_DOT!");
9466#pragma omp parallel for default(shared)
9467 for (
int ix = 0; ix < met->
nx; ix++)
9468 for (
int iy = 0; iy < met->
ny; iy++)
9469 for (
int ip = 0; ip < met->
np; ip++)
9470 met->
zetal[ix][iy][ip] =
9471 (
float) (met->
hyam[ip] / 100000.0 + met->
hybm[ip]);
9473 (ncid,
"etadot",
"ETADOT", NULL, NULL, ctl, met, dd, met->
zeta_dotl,
9475 WARN(
"Cannot read eta vertical velocity!");
9480#pragma omp parallel for default(shared)
9481 for (
int ix = 0; ix < met->
nx; ix++)
9482 for (
int iy = 0; iy < met->
ny; iy++)
9483 for (
int ip = 0; ip < met->
np; ip++) {
9484 met->
ul[ix][iy][ip] = met->
u[ix][iy][ip];
9485 met->
vl[ix][iy][ip] = met->
v[ix][iy][ip];
9486 met->
wl[ix][iy][ip] = met->
w[ix][iy][ip];
9499 (ncid,
"pl",
"PL",
"pressure",
"PRESSURE", ctl, met, dd, met->
pl,
9502 (ncid,
"press",
"PRESS", NULL, NULL, ctl, met, dd, met->
pl, 1.0))
9503 ERRMSG(
"Cannot read pressure on model levels!");
9511 ERRMSG(
"Mismatch in number of model levels!");
9514 for (
int ix = 0; ix < met->
nx; ix++)
9515 for (
int iy = 0; iy < met->
ny; iy++)
9516 for (
int ip = 0; ip < met->
np; ip++)
9517 met->
pl[ix][iy][ip] =
9518 (
float) (met->
hyam[ip] / 100. +
9519 met->
hybm[ip] * met->
ps[ix][iy]);
9527 ERRMSG(
"Mismatch in number of model levels!");
9530#pragma omp parallel for default(shared) collapse(2)
9531 for (
int ix = 0; ix < met->
nx; ix++)
9532 for (
int iy = 0; iy < met->
ny; iy++)
9533 for (
int ip = 0; ip < met->
np; ip++) {
9535 met->
hyam[ip] / 100. + met->
hybm[ip] * met->
ps[ix][iy];
9537 met->
hyam[ip + 1] / 100. + met->
hybm[ip + 1] * met->
ps[ix][iy];
9538 met->
pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
9543 for (
int ix = 0; ix < met->
nx; ix++)
9544 for (
int iy = 0; iy < met->
ny; iy++)
9545 for (
int ip = 1; ip < met->
np; ip++)
9546 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
9547 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
9548 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
9549 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip]))
9550 ERRMSG(
"Pressure profiles are not monotonic!");
9571 for (
int ip = 0; ip < met->
np; ip++)
9572 met->
p[ip] = ctl->
met_p[ip];
9576 for (
int ip = 1; ip < met->
np; ip++)
9577 if (met->
p[ip - 1] < met->
p[ip])
9578 ERRMSG(
"Pressure levels must be descending!");
9585 const char *varname,
9586 const char *varname2,
9587 const char *varname3,
9588 const char *varname4,
9589 const char *varname5,
9590 const char *varname6,
9600 float offset, scalfac;
9605 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
9606 sprintf(varsel,
"%s", varname);
9607 else if (varname2 != NULL
9608 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
9609 sprintf(varsel,
"%s", varname2);
9610 else if (varname3 != NULL
9611 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
9612 sprintf(varsel,
"%s", varname3);
9613 else if (varname4 != NULL
9614 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
9615 sprintf(varsel,
"%s", varname4);
9616 else if (varname5 != NULL
9617 && nc_inq_varid(ncid, varname5, &varid) == NC_NOERR)
9618 sprintf(varsel,
"%s", varname5);
9619 else if (varname6 != NULL
9620 && nc_inq_varid(ncid, varname6, &varid) == NC_NOERR)
9621 sprintf(varsel,
"%s", varname6);
9627 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
9628 && nc_get_att_float(ncid, varid,
"scale_factor",
9629 &scalfac) == NC_NOERR) {
9637 short fillval, missval;
9638 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9640 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9644 LOG(2,
"Read 2-D variable: %s"
9645 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
9646 varsel, fillval, missval, scalfac, offset);
9649 NC(nc_get_var_short(ncid, varid, help));
9653 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
9657#pragma omp parallel for default(shared)
9658 for (
int ix = 0; ix < met->
nx; ix++)
9659 for (
int iy = 0; iy < met->
ny; iy++) {
9662 const short aux = help[
ARRAY_2D(iy, ix, met->
nx)];
9663 if ((fillval == 0 || aux != fillval)
9664 && (missval == 0 || aux != missval)
9665 && fabsf(aux * scalfac + offset) < 1e14f)
9666 dest[ix][iy] += scl * (aux * scalfac + offset);
9677 else if (!ctl->
dd) {
9685 float fillval, missval;
9686 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9688 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9692 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
9693 varsel, fillval, missval);
9696 NC(nc_get_var_float(ncid, varid, help));
9703#pragma omp parallel for default(shared)
9704 for (
int ix = 0; ix < met->
nx; ix++)
9705 for (
int iy = 0; iy < met->
ny; iy++) {
9708 const float aux = help[
ARRAY_2D(iy, ix, met->
nx)];
9709 if ((fillval == 0 || aux != fillval)
9710 && (missval == 0 || aux != missval)
9711 && fabsf(aux) < 1e14f)
9712 dest[ix][iy] += scl * aux;
9722#pragma omp parallel for default(shared)
9723 for (
int iy = 0; iy < met->
ny; iy++)
9724 for (
int ix = 0; ix < met->
nx; ix++) {
9727 const float aux = help[
ARRAY_2D(ix, iy, met->
ny)];
9728 if ((fillval == 0 || aux != fillval)
9729 && (missval == 0 || aux != missval)
9730 && fabsf(aux) < 1e14f)
9731 dest[ix][iy] += scl * aux;
9746 float fillval, missval;
9747 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9749 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9753 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
9754 varsel, fillval, missval);
9758 size_t help_subdomain_start[3];
9759 size_t help_subdomain_count[3];
9761 help_subdomain_start[0] = 0;
9770 help_subdomain_count[0] = 1;
9784 nc_var_par_access(ncid, varid, NC_COLLECTIVE);
9786 NC(nc_get_vara_float
9787 (ncid, varid, help_subdomain_start, help_subdomain_count, help));
9790 size_t help_halo_bnd_start[3];
9791 size_t help_halo_bnd_count[3];
9793 help_halo_bnd_start[0] = 0;
9802 help_halo_bnd_count[0] = 1;
9812 ALLOC(help_halo,
float,
9813 help_halo_bnd_count[1] * help_halo_bnd_count[2]);
9816 nc_var_par_access(ncid, varid, NC_COLLECTIVE);
9818 NC(nc_get_vara_float
9819 (ncid, varid, help_halo_bnd_start, help_halo_bnd_count, help_halo));
9826#pragma omp parallel for default(shared)
9827 for (
int ix = 0; ix < (int) help_subdomain_count[2]; ix++)
9828 for (
int iy = 0; iy < (int) help_subdomain_count[1]; iy++) {
9832 help[
ARRAY_2D(iy, ix, (
int) help_subdomain_count[2])];
9833 if ((fillval == 0 || aux != fillval)
9834 && (missval == 0 || aux != missval)
9835 && fabsf(aux) < 1e14f) {
9841#pragma omp parallel for default(shared)
9842 for (
int ix = 0; ix < (int) help_halo_bnd_count[2]; ix++)
9843 for (
int iy = 0; iy < (int) help_halo_bnd_count[1]; iy++) {
9847 help_halo[
ARRAY_2D(iy, ix, (
int) help_halo_bnd_count[2])];
9848 if ((fillval == 0 || aux != fillval)
9849 && (missval == 0 || aux != missval)
9850 && fabsf(aux) < 1e14f)
9862#pragma omp parallel for default(shared)
9863 for (
int ix = 0; ix < (int) help_subdomain_count[1]; ix++)
9864 for (
int iy = 0; iy < (int) help_subdomain_count[2]; iy++) {
9868 help[
ARRAY_2D(ix, iy, (
int) help_subdomain_count[1])];
9869 if ((fillval == 0 || aux != fillval)
9870 && (missval == 0 || aux != missval)
9871 && fabsf(aux) < 1e14f)
9877#pragma omp parallel for default(shared)
9878 for (
int ix = 0; ix < (int) help_halo_bnd_count[1]; ix++)
9879 for (
int iy = 0; iy < (int) help_halo_bnd_count[2]; iy++) {
9883 help_halo[
ARRAY_2D(ix, iy, (
int) help_halo_bnd_count[1])];
9884 if ((fillval == 0 || aux != fillval)
9885 && (missval == 0 || aux != missval)
9886 && fabsf(aux) < 1e14f)
9907 const char *varname,
9908 const char *varname2,
9909 const char *varname3,
9910 const char *varname4,
9919 float offset, scalfac;
9924 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
9925 sprintf(varsel,
"%s", varname);
9926 else if (varname2 != NULL
9927 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
9928 sprintf(varsel,
"%s", varname2);
9929 else if (varname3 != NULL
9930 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
9931 sprintf(varsel,
"%s", varname3);
9932 else if (varname4 != NULL
9933 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
9934 sprintf(varsel,
"%s", varname4);
9940 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
9941 && nc_get_att_float(ncid, varid,
"scale_factor",
9942 &scalfac) == NC_NOERR) {
9950 short fillval, missval;
9951 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9953 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9957 LOG(2,
"Read 3-D variable: %s "
9958 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
9959 varsel, fillval, missval, scalfac, offset);
9962 NC(nc_get_var_short(ncid, varid, help));
9966 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
9970#pragma omp parallel for default(shared)
9971 for (
int ix = 0; ix < met->
nx; ix++)
9972 for (
int iy = 0; iy < met->
ny; iy++)
9973 for (
int ip = 0; ip < met->
np; ip++) {
9974 const short aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
9975 if ((fillval == 0 || aux != fillval)
9976 && (missval == 0 || aux != missval)
9977 && fabsf(aux * scalfac + offset) < 1e14f)
9978 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
9980 dest[ix][iy][ip] = NAN;
9989 else if (!ctl->
dd) {
9997 float fillval, missval;
9998 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
10000 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
10004 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
10005 varsel, fillval, missval);
10008 NC(nc_get_var_float(ncid, varid, help));
10014 omp_set_dynamic(1);
10015#pragma omp parallel for default(shared)
10016 for (
int ix = 0; ix < met->
nx; ix++)
10017 for (
int iy = 0; iy < met->
ny; iy++)
10018 for (
int ip = 0; ip < met->
np; ip++) {
10019 const float aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
10020 if ((fillval == 0 || aux != fillval)
10021 && (missval == 0 || aux != missval)
10022 && fabsf(aux) < 1e14f)
10023 dest[ix][iy][ip] = scl * aux;
10025 dest[ix][iy][ip] = NAN;
10027 omp_set_dynamic(0);
10032 omp_set_dynamic(1);
10033#pragma omp parallel for default(shared)
10034 for (
int ip = 0; ip < met->
np; ip++)
10035 for (
int iy = 0; iy < met->
ny; iy++)
10036 for (
int ix = 0; ix < met->
nx; ix++) {
10037 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
10038 if ((fillval == 0 || aux != fillval)
10039 && (missval == 0 || aux != missval)
10040 && fabsf(aux) < 1e14f)
10041 dest[ix][iy][ip] = scl * aux;
10043 dest[ix][iy][ip] = NAN;
10045 omp_set_dynamic(0);
10056 float fillval, missval;
10057 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
10059 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
10063 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
10064 varsel, fillval, missval);
10067 size_t help_subdomain_start[4];
10068 size_t help_subdomain_count[4];
10069 size_t help_halo_bnd_start[4];
10070 size_t help_halo_bnd_count[4];
10073 for (
int i = 0; i < 4; i++) {
10109 nc_var_par_access(ncid, varid, NC_COLLECTIVE);
10111 NC(nc_get_vara_float
10112 (ncid, varid, help_subdomain_start, help_subdomain_count, help));
10116 ALLOC(help_halo,
float,
10122 nc_var_par_access(ncid, varid, NC_COLLECTIVE);
10124 NC(nc_get_vara_float(ncid,
10126 help_halo_bnd_start, help_halo_bnd_count,
10133 omp_set_dynamic(1);
10134#pragma omp parallel for default(shared)
10137 for (
int ip = 0; ip < met->
np; ip++) {
10141 if ((fillval == 0 || aux != fillval)
10142 && (missval == 0 || aux != missval)
10143 && fabsf(aux) < 1e14f)
10149#pragma omp parallel for default(shared)
10152 for (
int ip = 0; ip < met->
np; ip++) {
10156 if ((fillval == 0 || aux != fillval)
10157 && (missval == 0 || aux != missval)
10158 && fabsf(aux) < 1e14f)
10163 omp_set_dynamic(0);
10168 omp_set_dynamic(1);
10169#pragma omp parallel for default(shared)
10170 for (
int ip = 0; ip < met->
np; ip++)
10176 if ((fillval == 0 || aux != fillval)
10177 && (missval == 0 || aux != missval)
10178 && fabsf(aux) < 1e14f)
10184#pragma omp parallel for default(shared)
10185 for (
int ip = 0; ip < met->
np; ip++)
10191 if ((fillval == 0 || aux != fillval)
10192 && (missval == 0 || aux != missval)
10193 && fabsf(aux) < 1e14f)
10198 omp_set_dynamic(0);
10214 const char *filename,
10219 size_t filename_len = strlen(filename) + 1;
10220 char sf_filename[filename_len];
10221 char ml_filename[filename_len];
10222 strcpy(sf_filename, filename);
10223 strcpy(ml_filename, filename);
10228 FILE *ml_file = fopen(ml_filename,
"rb");
10229 FILE *sf_file = fopen(sf_filename,
"rb");
10230 if (ml_file == NULL || sf_file == NULL) {
10231 if (ml_file != NULL) {
10233 WARN(
"Cannot open file: %s", sf_filename);
10235 if (sf_file != NULL) {
10237 WARN(
"Cannot open file: %s", ml_filename);
10243 int ml_num_messages = 0, err = 0;
10244 ECC(codes_count_in_file(0, ml_file, &ml_num_messages));
10247 (size_t) ml_num_messages);
10248 for (
int i = 0; i < ml_num_messages; i++) {
10250 if ((h = codes_grib_handle_new_from_file(0, ml_file, &err)) != NULL)
10255 int sf_num_messages = 0;
10256 ECC(codes_count_in_file(0, sf_file, &sf_num_messages));
10259 (size_t) sf_num_messages);
10260 for (
int i = 0; i < sf_num_messages; i++) {
10262 if ((h = codes_grib_handle_new_from_file(0, sf_file, &err)) != NULL)
10275 for (
int i = 0; i < sf_num_messages; i++)
10276 codes_handle_delete(sf_handles[i]);
10280 size_t value_count = 0;
10281 ECC(codes_get_size(ml_handles[0],
"pv", &value_count));
10282 if (value_count % 2 != 0)
10283 ERRMSG(
"Unexpected pv array length!");
10284 size_t nlevels = value_count / 2 - 1;
10286 ALLOC(values,
double,
10288 ECC(codes_get_double_array(ml_handles[0],
"pv", values, &value_count));
10289 double *a_vals = values;
10290 double *b_vals = values + nlevels;
10291 if (met->
npl > (
int) nlevels)
10292 ERRMSG(
"met->npl exceeds number of pressure levels in GRIB!");
10293 for (
int nx = 0; nx < met->
nx; nx++)
10294 for (
int ny = 0; ny < met->
ny; ny++)
10295 for (
int level = 0; level <= met->
npl; level++) {
10296 const float p1 = (float) (a_vals[level] * 0.01f +
10297 met->
ps[nx][ny] * b_vals[level]);
10298 const float p2 = (float) (a_vals[level + 1] * 0.01f +
10299 met->
ps[nx][ny] * b_vals[level + 1]);
10300 met->
pl[nx][ny][level] = 0.5f * (p1 + p2);
10306 for (
int i = 0; i < ml_num_messages; i++)
10307 codes_handle_delete(ml_handles[i]);
10325 LOG(2,
"Read meteo grid information...");
10328 char datestr[
LEN], timestr[
LEN];
10329 size_t s_date =
sizeof(datestr);
10330 ECC(codes_get_string(handles[0],
"dataDate", datestr, &s_date));
10331 size_t s_time =
sizeof(timestr);
10332 ECC(codes_get_string(handles[0],
"dataTime", timestr, &s_time));
10333 int year, month, day, hour;
10334 if (sscanf(datestr,
"%4d%2d%2d", &year, &month, &day) != 3)
10335 ERRMSG(
"Failed to parse dataDate: %s", datestr);
10336 if (sscanf(timestr,
"%2d", &hour) != 1)
10337 ERRMSG(
"Failed to parse dataTime: %s", timestr);
10339 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)", met->
time, year, month,
10343 long count_lat = 0, count_lon = 0;
10344 ECC(codes_get_long(handles[0],
"Nj", &count_lat));
10345 ECC(codes_get_long(handles[0],
"Ni", &count_lon));
10346 met->
ny = (int) count_lat;
10347 met->
nx = (int) count_lon;
10350 LOG(2,
"Number of longitudes: %d", met->
nx);
10351 if (met->
nx < 2 || met->
nx >
EX)
10352 ERRMSG(
"Number of longitudes out of range!");
10353 LOG(2,
"Number of latitudes: %d", met->
ny);
10354 if (met->
ny < 2 || met->
ny >
EY)
10355 ERRMSG(
"Number of latitudes out of range!");
10357 double first_lon, last_lon, first_lat, last_lat, inc_lon, inc_lat;
10358 ECC(codes_get_double
10359 (handles[0],
"longitudeOfFirstGridPointInDegrees", &first_lon));
10360 ECC(codes_get_double
10361 (handles[0],
"latitudeOfFirstGridPointInDegrees", &first_lat));
10362 ECC(codes_get_double
10363 (handles[0],
"longitudeOfLastGridPointInDegrees", &last_lon));
10364 ECC(codes_get_double
10365 (handles[0],
"latitudeOfLastGridPointInDegrees", &last_lat));
10366 ECC(codes_get_double(handles[0],
"iDirectionIncrementInDegrees", &inc_lon));
10367 ECC(codes_get_double(handles[0],
"jDirectionIncrementInDegrees", &inc_lat));
10369 long jscanpos, iscanneg;
10370 ECC(codes_get_long(handles[0],
"iScansNegatively", &iscanneg));
10371 ECC(codes_get_long(handles[0],
"jScansPositively", &jscanpos));
10376 for (
double i = first_lon; i <= last_lon + 1e-6; i += inc_lon) {
10377 met->
lon[counter] = i;
10380 for (
double i = first_lon; i > last_lon - 1e-6; i -= inc_lon) {
10381 met->
lon[counter] = i;
10387 for (
double i = first_lat; i > last_lat - 1e-6; i -= inc_lat) {
10388 met->
lat[counter] = i;
10391 for (
double i = first_lat; i <= last_lat + 1e-6; i += inc_lat) {
10392 met->
lat[counter] = i;
10397 LOG(2,
"Longitudes: %g, %g ... %g deg",
10398 met->
lon[0], met->
lon[1], met->
lon[met->
nx - 1]);
10399 LOG(2,
"Latitudes: %g, %g ... %g deg",
10400 met->
lat[0], met->
lat[1], met->
lat[met->
ny - 1]);
10404 for (
int i = 0; i < count_handles; i++) {
10406 ECC(codes_get_long(handles[i],
"level", &level));
10407 if (level > max_level)
10408 max_level = (int) level;
10410 met->
npl = max_level;
10413 LOG(2,
"Number of levels: %d", met->
npl);
10414 if (met->
npl < 2 || met->
npl >
EP)
10415 ERRMSG(
"Number of levels out of range!");
10424 const int num_messages,
10430 LOG(2,
"Read level data...");
10433 int t_flag = 0, u_flag = 0, v_flag = 0, w_flag = 0, o3_flag = 0, h2o_flag =
10434 0, lwc_flag = 0, rwc_flag = 0, iwc_flag = 0, swc_flag = 0, cc_flag = 0;
10437 for (
int i = 0; i < num_messages; i++) {
10439 size_t max_size =
LEN;
10440 char short_name[max_size];
10441 size_t value_count;
10445 long current_level;
10446 ECC(codes_get_long(handles[i],
"level", ¤t_level));
10447 current_level -= 1;
10450 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
10451 ECC(codes_get_size(handles[i],
"values", &value_count));
10452 ALLOC(values,
double,
10454 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
10462 ECC_READ_3D(
"w", current_level, met->
w, 0.01f, w_flag);
10480 if (t_flag != met->
npl)
10481 ERRMSG(
"Cannot read temperature!");
10482 if (u_flag != met->
npl)
10483 ERRMSG(
"Cannot read zonal wind!");
10484 if (v_flag != met->
npl)
10485 ERRMSG(
"Cannot read meridional wind!");
10486 if (w_flag != met->
npl)
10487 WARN(
"Cannot read vertical velocity!");
10488 if (h2o_flag != met->
npl)
10489 WARN(
"Cannot read specific humidity!");
10490 if (o3_flag != met->
npl)
10491 WARN(
"Cannot read ozone data!");
10492 if (lwc_flag != met->
npl)
10493 WARN(
"Cannot read cloud liquid water content!");
10494 if (rwc_flag != met->
npl)
10495 WARN(
"Cannot read cloud rain water content!");
10496 if (iwc_flag != met->
npl)
10497 WARN(
"Cannot read cloud ice water content!");
10498 if (swc_flag != met->
npl)
10499 WARN(
"Cannot read cloud snow water content!");
10500 if (cc_flag != met->
npl)
10501 WARN(
"Cannot read cloud cover!");
10504 for (
int ix = 0; ix < met->
nx; ix++)
10505 for (
int iy = 0; iy < met->
ny; iy++)
10506 for (
int ip = 1; ip < met->
np; ip++)
10507 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
10508 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
10509 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
10510 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip])) {
10511 LOG(1,
"%f %f %f %f", met->
pl[ix][iy][0], met->
pl[ix][iy][1],
10512 met->
pl[ix][iy][ip - 1], met->
pl[ix][iy][ip]);
10513 ERRMSG(
"Pressure profiles are not monotonic!");
10534 for (
int ip = 0; ip < met->
np; ip++)
10535 met->
p[ip] = ctl->
met_p[ip];
10539 for (
int ip = 1; ip < met->
np; ip++)
10540 if (met->
p[ip - 1] < met->
p[ip])
10541 ERRMSG(
"Pressure levels must be descending!");
10550 const int num_messages,
10556 LOG(2,
"Read surface data...");
10559 int sp_flag = 0, z_flag = 0, t_flag = 0, u_flag = 0, v_flag = 0, ess_flag =
10560 0, nss_flag = 0, shf_flag = 0, lsm_flag = 0, sst_flag = 0, cape_flag = 0,
10561 cin_flag = 0, pbl_flag = 0;
10564 for (
int i = 0; i < num_messages; i++) {
10566 size_t max_size =
LEN, value_count;
10568 char short_name[max_size];
10571 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
10572 ECC(codes_get_size(handles[i],
"values", &value_count));
10573 double *values = (
double *) malloc(value_count *
sizeof(
double));
10574 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
10621 WARN(
"Cannot read surface pressure data!");
10623 WARN(
"Cannot read surface geopotential height!");
10625 WARN(
"Cannot read surface temperature!");
10627 WARN(
"Cannot read surface zonal wind!");
10629 WARN(
"Cannot read surface meridional wind!");
10631 WARN(
"Cannot read eastward turbulent surface stress!");
10633 WARN(
"Cannot read northward turbulent surface stress!");
10635 WARN(
"Cannot read surface sensible heat flux!");
10637 WARN(
"Cannot read land-sea mask!");
10639 WARN(
"Cannot read sea surface temperature!");
10641 if (cape_flag == 0)
10642 WARN(
"Cannot read CAPE!");
10644 WARN(
"Cannot read convective inhibition!");
10646 if (ctl->
met_pbl == 1 && pbl_flag == 0)
10647 WARN(
"Cannot read planetary boundary layer height!");
10657 const char *varname) {
10659 double aux[
EP], p[
EP];
10663 LOG(2,
"Interpolate meteo data to pressure levels: %s", varname);
10666#pragma omp parallel for default(shared) private(aux,p) collapse(2)
10667 for (
int ix = 0; ix < met->
nx; ix++)
10668 for (
int iy = 0; iy < met->
ny; iy++) {
10671 for (
int ip = 0; ip < met->
np; ip++)
10672 p[ip] = met->
pl[ix][iy][ip];
10675 for (
int ip = 0; ip < ctl->
met_np; ip++) {
10676 double pt = ctl->
met_p[ip];
10677 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
10679 else if ((pt > p[met->
np - 1] && p[1] > p[0])
10680 || (pt < p[met->
np - 1] && p[1] < p[0]))
10681 pt = p[met->
np - 1];
10683 aux[ip] =
LIN(p[ip2], var[ix][iy][ip2],
10684 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
10688 for (
int ip = 0; ip < ctl->
met_np; ip++)
10689 var[ix][iy][ip] = (
float) aux[ip];
10705 LOG(2,
"Make zeta profiles monotone...");
10708#pragma omp parallel for default(shared) collapse(2)
10709 for (
int i = 0; i < met->
nx; i++)
10710 for (
int j = 0; j < met->
ny; j++) {
10713 while (k < met->npl) {
10714 if ((met->
zetal[i][j][k - 1] >= met->
zetal[i][j][k])) {
10720 while ((met->
zetal[i][j][k - 1] >=
10721 met->
zetal[i][j][k + l]) & (k + l < met->npl));
10726 (float) (met->
zetal[i][j][k + l] - met->
zetal[i][j][k - 1])
10729 for (
int m = k; m < k + l; m++) {
10730 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
10731 met->
zetal[i][j][m] = s * d + met->
zetal[i][j][k - 1];
10743#pragma omp parallel for default(shared) collapse(2)
10744 for (
int i = 0; i < met->
nx; i++)
10745 for (
int j = 0; j < met->
ny; j++) {
10748 while (k < met->npl) {
10749 if ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k])) {
10756 while ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k + l]) & (k + l <
10761 float s = (float) (met->
pl[i][j][k + l] - met->
pl[i][j][k - 1])
10764 for (
int m = k; m < k + l; m++) {
10765 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
10766 met->
pl[i][j][m] = s * d + met->
pl[i][j][k - 1];
10781 const char *filename,
10792 (filename, NC_NOWRITE | NC_SHARE, MPI_COMM_WORLD, MPI_INFO_NULL,
10796 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
10797 WARN(
"Cannot open file!");
10815 NC(nc_close(ncid));
10832 int rank = 0, size = 1;
10834 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
10835 MPI_Comm_size(MPI_COMM_WORLD, &size);
10842 LOG(2,
"Number of longitudes: %d", dd->
nx_glob);
10843 LOG(2,
"Number of latitudes: %d", dd->
ny_glob);
10847 ERRMSG(
"Global grid is too large!");
10850 ERRMSG(
"Too many zonal subdomains for global x grid!");
10853 ERRMSG(
"Too many meridional subdomains for global y grid!");
10859 LOG(2,
"Longitudes: %g, %g ... %g deg",
10861 LOG(2,
"Latitudes: %g, %g ... %g deg",
10869 const int left = (zonal_rank == 0);
10871 const int top = (merid_rank == 0);
10878 const int ix0 = zonal_rank * nx_block;
10879 const int iy0 = merid_rank * ny_block;
10881 int nx_core = nx_block;
10882 int ny_core = ny_block;
10905 if (!left && !right) {
10908 }
else if (left ^ right) {
10914 if (!top && !bottom) {
10917 }
else if (top ^ bottom) {
10924 double lon_shift = 0.0;
10926 if (left ^ right) {
10942 lon_shift = left ? -360.0 : 360.0;
10975 LOG(2,
"Define subdomain properties.");
10976 LOG(2,
"MPI information: Rank %d, Size %d", rank, size);
10977 LOG(2,
"Edge position: l=%d,r=%d,t=%d,b=%d", left, right, top, bottom);
10978 LOG(2,
"Total size for subdomain meteo data: nx %d ny %d np %d",
10979 met->
nx, met->
ny, met->
np);
10980 LOG(2,
"Hyperslab sizes for boundary halos: nx %d ny %d np %d",
10983 LOG(2,
"Hyperslab sizes for subdomain and inner halos: nx %d ny %d np %d",
10986 LOG(2,
"Subdomain start: nx %ld ny %ld np %ld",
10988 LOG(2,
"Boundary halo start: nx %ld ny %ld np %ld",
10991 LOG(2,
"%d Subdomain longitudes: %g, %g ... %g deg",
10992 rank, met->
lon[0], met->
lon[1], met->
lon[met->
nx - 1]);
10993 LOG(2,
"%d Subdomain latitudes: %g, %g ... %g deg",
10994 rank, met->
lat[0], met->
lat[1], met->
lat[met->
ny - 1]);
11005 LOG(2,
"Calculate planetary boundary layer...");
11011#pragma omp parallel for default(shared) collapse(2)
11012 for (
int ix = 0; ix < met->
nx; ix++)
11013 for (
int iy = 0; iy < met->
ny; iy++) {
11016 const float z = met->
zs[ix][iy] + met->
pbl[ix][iy];
11019 (float) (
LIN(met->
z[ix][iy][ip], met->
p[ip],
11020 met->
z[ix][iy][ip + 1], met->
p[ip + 1], z));
11025 else if (ctl->
met_pbl == 2) {
11029 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
11032#pragma omp parallel for default(shared) collapse(2)
11033 for (
int ix = 0; ix < met->
nx; ix++)
11034 for (
int iy = 0; iy < met->
ny; iy++) {
11037 const double pbl_bot = met->
ps[ix][iy] * exp(-dz /
H0);
11041 for (ip = 1; ip < met->
np; ip++)
11042 if (met->
p[ip] < pbl_bot)
11046 const double h2os =
LIN(met->
p[ip - 1], met->
h2o[ix][iy][ip - 1],
11047 met->
p[ip], met->
h2o[ix][iy][ip], pbl_bot);
11048 const double tvs =
THETAVIRT(pbl_bot, met->
ts[ix][iy], h2os);
11051 double rib_old = 0;
11054 for (; ip < met->
np; ip++) {
11057 double vh2 =
SQR(met->
u[ix][iy][ip] - met->
us[ix][iy])
11058 +
SQR(met->
v[ix][iy][ip] - met->
vs[ix][iy]);
11059 vh2 =
MAX(vh2,
SQR(umin));
11063 G0 * 1e3 * (met->
z[ix][iy][ip] - met->
zs[ix][iy]) / tvs
11065 met->
h2o[ix][iy][ip]) - tvs) / vh2;
11068 if (rib >= rib_crit) {
11069 met->
pbl[ix][iy] = (float) (
LIN(rib_old, met->
p[ip - 1],
11070 rib, met->
p[ip], rib_crit));
11071 if (met->
pbl[ix][iy] > pbl_bot)
11072 met->
pbl[ix][iy] = (float) pbl_bot;
11087 const double dtheta = 2.0, zmin = 0.1;
11090#pragma omp parallel for default(shared) collapse(2)
11091 for (
int ix = 0; ix < met->
nx; ix++)
11092 for (
int iy = 0; iy < met->
ny; iy++) {
11095 const double theta0 =
THETA(met->
ps[ix][iy], met->
ts[ix][iy]);
11099 for (ip = met->
np - 2; ip > 0; ip--)
11100 if (met->
p[ip] >= 300.)
11101 if (met->
p[ip] > met->
ps[ix][iy]
11102 ||
THETA(met->
p[ip], met->
t[ix][iy][ip]) <= theta0 + dtheta)
11107 = (float) (
LIN(
THETA(met->
p[ip + 1], met->
t[ix][iy][ip + 1]),
11109 THETA(met->
p[ip], met->
t[ix][iy][ip]),
11110 met->
p[ip], theta0 + dtheta));
11113 double pbl_min = met->
ps[ix][iy] * exp(-zmin /
H0);
11114 if (met->
pbl[ix][iy] > pbl_min || met->
p[ip] > met->
ps[ix][iy])
11115 met->
pbl[ix][iy] = (float) pbl_min;
11120#pragma omp parallel for default(shared) collapse(2)
11121 for (
int ix = 0; ix < met->
nx; ix++)
11122 for (
int iy = 0; iy < met->
ny; iy++) {
11126 met->
pbl[ix][iy] =
MIN(met->
pbl[ix][iy], (
float) pbl_min);
11130 met->
pbl[ix][iy] =
MAX(met->
pbl[ix][iy], (
float) pbl_max);
11141 LOG(2,
"Apply periodic boundary conditions...");
11144 if (!(fabs(met->
lon[met->
nx - 1] - met->
lon[0]
11145 + met->
lon[1] - met->
lon[0] - 360) < 0.01))
11149 if ((++met->
nx) >=
EX)
11150 ERRMSG(
"Cannot create periodic boundary conditions!");
11153 met->
lon[met->
nx - 1] = met->
lon[met->
nx - 2] + met->
lon[1] - met->
lon[0];
11156#pragma omp parallel for default(shared)
11157 for (
int iy = 0; iy < met->
ny; iy++) {
11158 met->
ps[met->
nx - 1][iy] = met->
ps[0][iy];
11159 met->
zs[met->
nx - 1][iy] = met->
zs[0][iy];
11160 met->
ts[met->
nx - 1][iy] = met->
ts[0][iy];
11161 met->
us[met->
nx - 1][iy] = met->
us[0][iy];
11162 met->
vs[met->
nx - 1][iy] = met->
vs[0][iy];
11163 met->
ess[met->
nx - 1][iy] = met->
ess[0][iy];
11164 met->
nss[met->
nx - 1][iy] = met->
nss[0][iy];
11165 met->
shf[met->
nx - 1][iy] = met->
shf[0][iy];
11166 met->
lsm[met->
nx - 1][iy] = met->
lsm[0][iy];
11167 met->
sst[met->
nx - 1][iy] = met->
sst[0][iy];
11168 met->
pbl[met->
nx - 1][iy] = met->
pbl[0][iy];
11169 met->
cape[met->
nx - 1][iy] = met->
cape[0][iy];
11170 met->
cin[met->
nx - 1][iy] = met->
cin[0][iy];
11171 for (
int ip = 0; ip < met->
np; ip++) {
11172 met->
t[met->
nx - 1][iy][ip] = met->
t[0][iy][ip];
11173 met->
u[met->
nx - 1][iy][ip] = met->
u[0][iy][ip];
11174 met->
v[met->
nx - 1][iy][ip] = met->
v[0][iy][ip];
11175 met->
w[met->
nx - 1][iy][ip] = met->
w[0][iy][ip];
11176 met->
h2o[met->
nx - 1][iy][ip] = met->
h2o[0][iy][ip];
11177 met->
o3[met->
nx - 1][iy][ip] = met->
o3[0][iy][ip];
11178 met->
lwc[met->
nx - 1][iy][ip] = met->
lwc[0][iy][ip];
11179 met->
rwc[met->
nx - 1][iy][ip] = met->
rwc[0][iy][ip];
11180 met->
iwc[met->
nx - 1][iy][ip] = met->
iwc[0][iy][ip];
11181 met->
swc[met->
nx - 1][iy][ip] = met->
swc[0][iy][ip];
11182 met->
cc[met->
nx - 1][iy][ip] = met->
cc[0][iy][ip];
11184 for (
int ip = 0; ip < met->
npl; ip++) {
11185 met->
ul[met->
nx - 1][iy][ip] = met->
ul[0][iy][ip];
11186 met->
vl[met->
nx - 1][iy][ip] = met->
vl[0][iy][ip];
11187 met->
wl[met->
nx - 1][iy][ip] = met->
wl[0][iy][ip];
11188 met->
pl[met->
nx - 1][iy][ip] = met->
pl[0][iy][ip];
11189 met->
zetal[met->
nx - 1][iy][ip] = met->
zetal[0][iy][ip];
11202 LOG(2,
"Apply fix for polar winds...");
11208 if (fabs(met->
lat[0]) < 89.999 || fabs(met->
lat[met->
ny - 1]) < 89.999)
11212 for (
int ihem = 0; ihem < 2; ihem++) {
11215 int i89 = 1, i90 = 0, sign = 1;
11220 if (met->
lat[i90] < 0)
11224 double clon[
EX], slon[
EX];
11225#pragma omp parallel for default(shared)
11226 for (
int ix = 0; ix < met->
nx; ix++) {
11227 clon[ix] = cos(sign *
DEG2RAD(met->
lon[ix]));
11228 slon[ix] = sin(sign *
DEG2RAD(met->
lon[ix]));
11232#pragma omp parallel for default(shared)
11233 for (
int ip = 0; ip < met->
np; ip++) {
11236 double vel89x = 0, vel89y = 0;
11237 for (
int ix = 0; ix < met->
nx; ix++) {
11239 (met->
u[ix][i89][ip] * clon[ix] -
11240 met->
v[ix][i89][ip] * slon[ix]) / met->
nx;
11242 (met->
u[ix][i89][ip] * slon[ix] +
11243 met->
v[ix][i89][ip] * clon[ix]) / met->
nx;
11247 for (
int ix = 0; ix < met->
nx; ix++) {
11248 met->
u[ix][i90][ip]
11249 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
11250 met->
v[ix][i90][ip]
11251 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
11266 LOG(2,
"Calculate potential vorticity...");
11269#pragma omp parallel for default(shared)
11270 for (
int ip = 0; ip < met->
np; ip++)
11271 pows[ip] = pow(1000. / met->
p[ip], 0.286);
11274#pragma omp parallel for default(shared)
11275 for (
int ix = 0; ix < met->
nx; ix++) {
11278 const int ix0 =
MAX(ix - 1, 0);
11279 const int ix1 =
MIN(ix + 1, met->
nx - 1);
11282 for (
int iy = 0; iy < met->
ny; iy++) {
11285 const int iy0 =
MAX(iy - 1, 0);
11286 const int iy1 =
MIN(iy + 1, met->
ny - 1);
11289 const double latr = 0.5 * (met->
lat[iy1] + met->
lat[iy0]);
11290 double dx, dy, c0, c1, cr, vort;
11294 dx = 1000. *
DEG2DX(met->
lon[ix1] - met->
lon[ix0], latr);
11299 vort = 2 * 7.2921e-5 * sin(
DEG2RAD(latr));
11301 dx = met->
lon[ix1] - met->
lon[ix0];
11302 dy = met->
lat[iy1] - met->
lat[iy0];
11308 vort = 2 * 7.2921e-5 * sin(latr / (
RE * 1000));
11312 for (
int ip = 0; ip < met->
np; ip++) {
11316 = (met->
t[ix1][iy][ip] - met->
t[ix0][iy][ip]) * pows[ip] / dx;
11317 const double dvdx = (met->
v[ix1][iy][ip] - met->
v[ix0][iy][ip]) / dx;
11321 = (met->
t[ix][iy1][ip] - met->
t[ix][iy0][ip]) * pows[ip] / dy;
11323 = (met->
u[ix][iy1][ip] * c1 - met->
u[ix][iy0][ip] * c0) / dy;
11326 const int ip0 =
MAX(ip - 1, 0);
11327 const int ip1 =
MIN(ip + 1, met->
np - 1);
11330 double dtdp, dudp, dvdp;
11331 const double dp0 = 100. * (met->
p[ip] - met->
p[ip0]);
11332 const double dp1 = 100. * (met->
p[ip1] - met->
p[ip]);
11333 if (ip != ip0 && ip != ip1) {
11334 double denom = dp0 * dp1 * (dp0 + dp1);
11335 dtdp = (dp0 * dp0 * met->
t[ix][iy][ip1] * pows[ip1]
11336 - dp1 * dp1 * met->
t[ix][iy][ip0] * pows[ip0]
11337 + (dp1 * dp1 - dp0 * dp0) * met->
t[ix][iy][ip] * pows[ip])
11339 dudp = (dp0 * dp0 * met->
u[ix][iy][ip1]
11340 - dp1 * dp1 * met->
u[ix][iy][ip0]
11341 + (dp1 * dp1 - dp0 * dp0) * met->
u[ix][iy][ip])
11343 dvdp = (dp0 * dp0 * met->
v[ix][iy][ip1]
11344 - dp1 * dp1 * met->
v[ix][iy][ip0]
11345 + (dp1 * dp1 - dp0 * dp0) * met->
v[ix][iy][ip])
11348 const double denom = dp0 + dp1;
11350 (met->
t[ix][iy][ip1] * pows[ip1] -
11351 met->
t[ix][iy][ip0] * pows[ip0]) / denom;
11352 dudp = (met->
u[ix][iy][ip1] - met->
u[ix][iy][ip0]) / denom;
11353 dvdp = (met->
v[ix][iy][ip1] - met->
v[ix][iy][ip0]) / denom;
11357 met->
pv[ix][iy][ip] = (float)
11359 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
11365#pragma omp parallel for default(shared)
11366 for (
int ix = 0; ix < met->
nx; ix++)
11367 for (
int ip = 0; ip < met->
np; ip++) {
11369 = met->
pv[ix][1][ip]
11370 = met->
pv[ix][2][ip];
11371 met->
pv[ix][met->
ny - 1][ip]
11372 = met->
pv[ix][met->
ny - 2][ip]
11373 = met->
pv[ix][met->
ny - 3][ip];
11384 LOG(2,
"Calculate total column ozone...");
11387#pragma omp parallel for default(shared) collapse(2)
11388 for (
int ix = 0; ix < met->
nx; ix++)
11389 for (
int iy = 0; iy < met->
ny; iy++) {
11393 for (
int ip = 1; ip < met->
np; ip++)
11394 if (met->
p[ip - 1] <= met->
ps[ix][iy]) {
11396 0.5 * (met->
o3[ix][iy][ip - 1] + met->
o3[ix][iy][ip]);
11397 const double dp = met->
p[ip - 1] - met->
p[ip];
11398 cd += vmr *
MO3 /
MA * dp * 1e2 /
G0;
11402 met->
o3c[ix][iy] = (float) (cd / 2.1415e-5);
11421 LOG(2,
"Downsampling of meteo data...");
11427 help->
nx = met->
nx;
11428 help->
ny = met->
ny;
11429 help->
np = met->
np;
11430 memcpy(help->
lon, met->
lon,
sizeof(met->
lon));
11431 memcpy(help->
lat, met->
lat,
sizeof(met->
lat));
11432 memcpy(help->
p, met->
p,
sizeof(met->
p));
11435 for (
int ix = 0; ix < met->
nx; ix += ctl->
met_dx) {
11436 for (
int iy = 0; iy < met->
ny; iy += ctl->
met_dy) {
11437 for (
int ip = 0; ip < met->
np; ip += ctl->
met_dp) {
11438 help->
ps[ix][iy] = 0;
11439 help->
zs[ix][iy] = 0;
11440 help->
ts[ix][iy] = 0;
11441 help->
us[ix][iy] = 0;
11442 help->
vs[ix][iy] = 0;
11443 help->
ess[ix][iy] = 0;
11444 help->
nss[ix][iy] = 0;
11445 help->
shf[ix][iy] = 0;
11446 help->
lsm[ix][iy] = 0;
11447 help->
sst[ix][iy] = 0;
11448 help->
pbl[ix][iy] = 0;
11449 help->
cape[ix][iy] = 0;
11450 help->
cin[ix][iy] = 0;
11451 help->
t[ix][iy][ip] = 0;
11452 help->
u[ix][iy][ip] = 0;
11453 help->
v[ix][iy][ip] = 0;
11454 help->
w[ix][iy][ip] = 0;
11455 help->
h2o[ix][iy][ip] = 0;
11456 help->
o3[ix][iy][ip] = 0;
11457 help->
lwc[ix][iy][ip] = 0;
11458 help->
rwc[ix][iy][ip] = 0;
11459 help->
iwc[ix][iy][ip] = 0;
11460 help->
swc[ix][iy][ip] = 0;
11461 help->
cc[ix][iy][ip] = 0;
11463 for (
int ix2 = ix - ctl->
met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
11468 else if (ix3 >= met->
nx)
11471 for (
int iy2 =
MAX(iy - ctl->
met_sy + 1, 0);
11472 iy2 <=
MIN(iy + ctl->
met_sy - 1, met->
ny - 1); iy2++)
11473 for (
int ip2 =
MAX(ip - ctl->
met_sp + 1, 0);
11474 ip2 <=
MIN(ip + ctl->
met_sp - 1, met->
np - 1); ip2++) {
11476 (1.0f - (float) abs(ix - ix2) / (float) ctl->
met_sx)
11477 * (1.0f - (float) abs(iy - iy2) / (float) ctl->
met_sy)
11478 * (1.0f - (float) abs(ip - ip2) / (float) ctl->
met_sp);
11479 help->
ps[ix][iy] += w * met->
ps[ix3][iy2];
11480 help->
zs[ix][iy] += w * met->
zs[ix3][iy2];
11481 help->
ts[ix][iy] += w * met->
ts[ix3][iy2];
11482 help->
us[ix][iy] += w * met->
us[ix3][iy2];
11483 help->
vs[ix][iy] += w * met->
vs[ix3][iy2];
11484 help->
ess[ix][iy] += w * met->
ess[ix3][iy2];
11485 help->
nss[ix][iy] += w * met->
nss[ix3][iy2];
11486 help->
shf[ix][iy] += w * met->
shf[ix3][iy2];
11487 help->
lsm[ix][iy] += w * met->
lsm[ix3][iy2];
11488 help->
sst[ix][iy] += w * met->
sst[ix3][iy2];
11489 help->
pbl[ix][iy] += w * met->
pbl[ix3][iy2];
11490 help->
cape[ix][iy] += w * met->
cape[ix3][iy2];
11491 help->
cin[ix][iy] += w * met->
cin[ix3][iy2];
11492 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip2];
11493 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip2];
11494 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip2];
11495 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip2];
11496 help->
h2o[ix][iy][ip] += w * met->
h2o[ix3][iy2][ip2];
11497 help->
o3[ix][iy][ip] += w * met->
o3[ix3][iy2][ip2];
11498 help->
lwc[ix][iy][ip] += w * met->
lwc[ix3][iy2][ip2];
11499 help->
rwc[ix][iy][ip] += w * met->
rwc[ix3][iy2][ip2];
11500 help->
iwc[ix][iy][ip] += w * met->
iwc[ix3][iy2][ip2];
11501 help->
swc[ix][iy][ip] += w * met->
swc[ix3][iy2][ip2];
11502 help->
cc[ix][iy][ip] += w * met->
cc[ix3][iy2][ip2];
11506 help->
ps[ix][iy] /= wsum;
11507 help->
zs[ix][iy] /= wsum;
11508 help->
ts[ix][iy] /= wsum;
11509 help->
us[ix][iy] /= wsum;
11510 help->
vs[ix][iy] /= wsum;
11511 help->
ess[ix][iy] /= wsum;
11512 help->
nss[ix][iy] /= wsum;
11513 help->
shf[ix][iy] /= wsum;
11514 help->
lsm[ix][iy] /= wsum;
11515 help->
sst[ix][iy] /= wsum;
11516 help->
pbl[ix][iy] /= wsum;
11517 help->
cape[ix][iy] /= wsum;
11518 help->
cin[ix][iy] /= wsum;
11519 help->
t[ix][iy][ip] /= wsum;
11520 help->
u[ix][iy][ip] /= wsum;
11521 help->
v[ix][iy][ip] /= wsum;
11522 help->
w[ix][iy][ip] /= wsum;
11523 help->
h2o[ix][iy][ip] /= wsum;
11524 help->
o3[ix][iy][ip] /= wsum;
11525 help->
lwc[ix][iy][ip] /= wsum;
11526 help->
rwc[ix][iy][ip] /= wsum;
11527 help->
iwc[ix][iy][ip] /= wsum;
11528 help->
swc[ix][iy][ip] /= wsum;
11529 help->
cc[ix][iy][ip] /= wsum;
11536 for (
int ix = 0; ix < help->
nx; ix += ctl->
met_dx) {
11537 met->
lon[met->
nx] = help->
lon[ix];
11539 for (
int iy = 0; iy < help->
ny; iy += ctl->
met_dy) {
11540 met->
lat[met->
ny] = help->
lat[iy];
11541 met->
ps[met->
nx][met->
ny] = help->
ps[ix][iy];
11542 met->
zs[met->
nx][met->
ny] = help->
zs[ix][iy];
11543 met->
ts[met->
nx][met->
ny] = help->
ts[ix][iy];
11544 met->
us[met->
nx][met->
ny] = help->
us[ix][iy];
11545 met->
vs[met->
nx][met->
ny] = help->
vs[ix][iy];
11546 met->
ess[met->
nx][met->
ny] = help->
ess[ix][iy];
11547 met->
nss[met->
nx][met->
ny] = help->
nss[ix][iy];
11548 met->
shf[met->
nx][met->
ny] = help->
shf[ix][iy];
11549 met->
lsm[met->
nx][met->
ny] = help->
lsm[ix][iy];
11550 met->
sst[met->
nx][met->
ny] = help->
sst[ix][iy];
11551 met->
pbl[met->
nx][met->
ny] = help->
pbl[ix][iy];
11553 met->
cin[met->
nx][met->
ny] = help->
cin[ix][iy];
11555 for (
int ip = 0; ip < help->
np; ip += ctl->
met_dp) {
11556 met->
p[met->
np] = help->
p[ip];
11557 met->
t[met->
nx][met->
ny][met->
np] = help->
t[ix][iy][ip];
11558 met->
u[met->
nx][met->
ny][met->
np] = help->
u[ix][iy][ip];
11559 met->
v[met->
nx][met->
ny][met->
np] = help->
v[ix][iy][ip];
11560 met->
w[met->
nx][met->
ny][met->
np] = help->
w[ix][iy][ip];
11561 met->
h2o[met->
nx][met->
ny][met->
np] = help->
h2o[ix][iy][ip];
11562 met->
o3[met->
nx][met->
ny][met->
np] = help->
o3[ix][iy][ip];
11563 met->
lwc[met->
nx][met->
ny][met->
np] = help->
lwc[ix][iy][ip];
11564 met->
rwc[met->
nx][met->
ny][met->
np] = help->
rwc[ix][iy][ip];
11565 met->
iwc[met->
nx][met->
ny][met->
np] = help->
iwc[ix][iy][ip];
11566 met->
swc[met->
nx][met->
ny][met->
np] = help->
swc[ix][iy][ip];
11567 met->
cc[met->
nx][met->
ny][met->
np] = help->
cc[ix][iy][ip];
11586 double p2[200], pv[
EP], pv2[200], t[
EP], t2[200], th[
EP],
11587 th2[200], z[
EP], z2[200];
11591 LOG(2,
"Calculate tropopause...");
11594#pragma omp parallel for default(shared)
11595 for (
int iz = 0; iz < met->
np; iz++)
11596 z[iz] =
Z(met->
p[iz]);
11597#pragma omp parallel for default(shared)
11598 for (
int iz = 0; iz <= 190; iz++) {
11599 z2[iz] = 4.5 + 0.1 * iz;
11600 p2[iz] =
P(z2[iz]);
11605#pragma omp parallel for default(shared) collapse(2)
11606 for (
int ix = 0; ix < met->
nx; ix++)
11607 for (
int iy = 0; iy < met->
ny; iy++)
11608 met->
pt[ix][iy] = NAN;
11613 ERRMSG(
"Only lat/lon grid supported");
11614#pragma omp parallel for default(shared) collapse(2)
11615 for (
int ix = 0; ix < met->
nx; ix++)
11616 for (
int iy = 0; iy < met->
ny; iy++)
11624#pragma omp parallel for default(shared) private(t,t2) collapse(2)
11625 for (
int ix = 0; ix < met->
nx; ix++)
11626 for (
int iy = 0; iy < met->
ny; iy++) {
11629 for (
int iz = 0; iz < met->
np; iz++)
11630 t[iz] = met->
t[ix][iy][iz];
11634 int iz = (int) gsl_stats_min_index(t2, 1, 171);
11635 if (iz > 0 && iz < 170)
11636 met->
pt[ix][iy] = (float) p2[iz];
11638 met->
pt[ix][iy] = NAN;
11646#pragma omp parallel for default(shared) private(t,t2) collapse(2)
11647 for (
int ix = 0; ix < met->
nx; ix++)
11648 for (
int iy = 0; iy < met->
ny; iy++) {
11652 for (iz = 0; iz < met->
np; iz++)
11653 t[iz] = met->
t[ix][iy][iz];
11657 met->
pt[ix][iy] = NAN;
11658 for (iz = 0; iz <= 170; iz++) {
11660 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
11661 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
11666 if (iz > 0 && iz < 170)
11667 met->
pt[ix][iy] = (float) p2[iz];
11674 met->
pt[ix][iy] = NAN;
11675 for (; iz <= 170; iz++) {
11677 for (
int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
11678 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
11685 for (; iz <= 170; iz++) {
11687 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
11688 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
11693 if (iz > 0 && iz < 170)
11694 met->
pt[ix][iy] = (float) p2[iz];
11706#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
11707 for (
int ix = 0; ix < met->
nx; ix++)
11708 for (
int iy = 0; iy < met->
ny; iy++) {
11711 for (
int iz = 0; iz < met->
np; iz++)
11712 pv[iz] = met->
pv[ix][iy][iz];
11716 for (
int iz = 0; iz < met->
np; iz++)
11717 th[iz] =
THETA(met->
p[iz], met->
t[ix][iy][iz]);
11721 met->
pt[ix][iy] = NAN;
11722 for (
int iz = 0; iz <= 170; iz++)
11725 if (iz > 0 && iz < 170)
11726 met->
pt[ix][iy] = (float) p2[iz];
11733 ERRMSG(
"Cannot calculate tropopause!");
11736#pragma omp parallel for default(shared) collapse(2)
11737 for (
int ix = 0; ix < met->
nx; ix++)
11738 for (
int iy = 0; iy < met->
ny; iy++) {
11739 double h2ot, tt, zt;
11742 met->
lat[iy], &tt, ci, cw, 1);
11744 met->
lat[iy], &zt, ci, cw, 0);
11746 met->
lat[iy], &h2ot, ci, cw, 0);
11747 met->
tt[ix][iy] = (float) tt;
11748 met->
zt[ix][iy] = (float) zt;
11749 met->
h2ot[ix][iy] = (float) h2ot;
11756 const char *filename,
11766 LOG(1,
"Read observation data: %s", filename);
11770 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
11772 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
11774 ERRMSG(
"Set OBS_TYPE to 0 or 1!");
11777 for (
int i = 1; i < *nobs; i++)
11778 if (rt[i] < rt[i - 1])
11779 ERRMSG(
"Time must be ascending!");
11784 LOG(2,
"Number of observations: %d", *nobs);
11785 gsl_stats_minmax(&mini, &maxi, rt, 1, (
size_t) n);
11786 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
11787 gsl_stats_minmax(&mini, &maxi, rz, 1, (
size_t) n);
11788 LOG(2,
"Altitude range: %g ... %g km", mini, maxi);
11789 gsl_stats_minmax(&mini, &maxi, rlon, 1, (
size_t) n);
11790 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
11791 gsl_stats_minmax(&mini, &maxi, rlat, 1, (
size_t) n);
11792 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
11793 gsl_stats_minmax(&mini, &maxi, robs, 1, (
size_t) n);
11794 LOG(2,
"Observation range: %g ... %g", mini, maxi);
11800 const char *filename,
11810 if (!(in = fopen(filename,
"r")))
11811 ERRMSG(
"Cannot open file!");
11815 while (fgets(line,
LEN, in))
11816 if (sscanf(line,
"%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
11817 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
11818 if ((++(*nobs)) >=
NOBS)
11819 ERRMSG(
"Too many observations!");
11828 const char *filename,
11839 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
11840 ERRMSG(
"Cannot open file!");
11851 NC(nc_close(ncid));
11857 const char *filename,
11860 const char *varname,
11862 const char *defvalue,
11867 char fullname1[
LEN], fullname2[
LEN], rval[
LEN];
11869 int contain = 0, i;
11872 if (filename[strlen(filename) - 1] !=
'-')
11873 if (!(in = fopen(filename,
"r")))
11874 ERRMSG(
"Cannot open file!");
11878 sprintf(fullname1,
"%s[%d]", varname, arridx);
11879 sprintf(fullname2,
"%s[*]", varname);
11881 sprintf(fullname1,
"%s", varname);
11882 sprintf(fullname2,
"%s", varname);
11887 char dummy[
LEN], line[
LEN], rvarname[
LEN];
11888 while (fgets(line,
LEN, in)) {
11889 if (sscanf(line,
"%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
11890 if (strcasecmp(rvarname, fullname1) == 0 ||
11891 strcasecmp(rvarname, fullname2) == 0) {
11897 for (i = 1; i < argc - 1; i++)
11898 if (strcasecmp(argv[i], fullname1) == 0 ||
11899 strcasecmp(argv[i], fullname2) == 0) {
11900 sprintf(rval,
"%s", argv[i + 1]);
11911 if (strlen(defvalue) > 0)
11912 sprintf(rval,
"%s", defvalue);
11914 ERRMSG(
"Missing variable %s!\n", fullname1);
11918 LOG(1,
"%s = %s", fullname1, rval);
11922 sprintf(value,
"%s", rval);
11932 const double rhop) {
11935 const double rp_help = rp * 1e-6;
11938 const double rho =
RHO(p, T);
11941 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
11944 const double v = sqrt(8. *
KB * T / (M_PI * 4.8096e-26));
11947 const double lambda = 2. * eta / (rho * v);
11950 const double K = lambda / rp_help;
11953 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
11956 return 2. *
SQR(rp_help) * (rhop - rho) *
G0 / (9. * eta) * G;
11968 const int method) {
11974 gsl_interp_accel *acc = gsl_interp_accel_alloc();
11975 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (
size_t) n);
11978 gsl_spline_init(s, x, y, (
size_t) n);
11979 for (
int i = 0; i < n2; i++)
11982 else if (x2[i] >= x[n - 1])
11985 y2[i] = gsl_spline_eval(s, x2[i], acc);
11988 gsl_spline_free(s);
11989 gsl_interp_accel_free(acc);
11994 for (
int i = 0; i < n2; i++)
11997 else if (x2[i] >= x[n - 1])
12001 y2[i] =
LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
12015 float mean = 0, var = 0;
12017 for (
int i = 0; i < n; ++i) {
12019 var +=
SQR(data[i]);
12022 var = var / (float) n -
SQR(mean / (
float) n);
12024 return (var > 0 ? sqrtf(var) : 0);
12036 const double remain,
12048 t1.tm_year = year - 1900;
12049 t1.tm_mon = mon - 1;
12055 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
12063 const int output) {
12070 static int iname = -1, igroup = -1, nname, ngroup, ct_name[
NTIMER];
12073 t1 = omp_get_wtime();
12078 rt_name[iname] += dt;
12079 rt_min[iname] = (ct_name[iname] <= 0 ? dt :
MIN(rt_min[iname], dt));
12080 rt_max[iname] = (ct_name[iname] <= 0 ? dt :
MAX(rt_max[iname], dt));
12084 rt_group[igroup] += t1 - t0;
12088 for (
int i = 0; i < nname; i++)
12089 LOG(1,
"TIMER_%s = %.3f s (min= %g s, mean= %g s,"
12090 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
12091 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
12092 for (
int i = 0; i < ngroup; i++)
12093 LOG(1,
"TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
12094 double total = 0.0;
12095 for (
int i = 0; i < nname; i++)
12096 total += rt_name[i];
12097 LOG(1,
"TIMER_TOTAL = %.3f s", total);
12101 for (iname = 0; iname < nname; iname++)
12102 if (strcasecmp(name, names[iname]) == 0)
12104 for (igroup = 0; igroup < ngroup; igroup++)
12105 if (strcasecmp(group, groups[igroup]) == 0)
12109 if (iname >= nname) {
12110 sprintf(names[iname],
"%s", name);
12111 if ((++nname) >=
NTIMER)
12112 ERRMSG(
"Too many timers!");
12116 if (igroup >= ngroup) {
12117 sprintf(groups[igroup],
"%s", group);
12118 if ((++ngroup) >=
NTIMER)
12119 ERRMSG(
"Too many groups!");
12129 const char *filename,
12131 const int with_seconds) {
12138 int len = (int) strlen(filename);
12139 sprintf(tstr,
"%.4s", &filename[len - offset]);
12140 int year = atoi(tstr);
12141 sprintf(tstr,
"%.2s", &filename[len - offset + 5]);
12142 int mon = atoi(tstr);
12143 sprintf(tstr,
"%.2s", &filename[len - offset + 8]);
12144 int day = atoi(tstr);
12145 sprintf(tstr,
"%.2s", &filename[len - offset + 11]);
12146 int hour = atoi(tstr);
12147 sprintf(tstr,
"%.2s", &filename[len - offset + 14]);
12148 int min = atoi(tstr);
12151 if (with_seconds) {
12152 sprintf(tstr,
"%.2s", &filename[len - offset + 17]);
12157 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
12158 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
12159 ERRMSG(
"Cannot read time from filename!");
12162 time2jsec(year, mon, day, hour, min, sec, 0.0, &t);
12182 const double p1 = pt * 0.866877899;
12183 const double p0 = pt / 0.866877899;
12186 if (atm->
p[ip] > p0)
12188 else if (atm->
p[ip] < p1)
12191 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
12197 const char *filename,
12205 const double t0 = t - 0.5 * ctl->
dt_mod;
12206 const double t1 = t + 0.5 * ctl->
dt_mod;
12212 if (!(out = popen(
"gnuplot",
"w")))
12213 ERRMSG(
"Cannot create pipe to gnuplot!");
12216 fprintf(out,
"set out \"%s.png\"\n", filename);
12220 int year, mon, day, hour, min, sec;
12221 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
12222 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
12223 year, mon, day, hour, min);
12228 ERRMSG(
"Cannot open file!");
12230 while (fgets(line,
LEN, in))
12231 fprintf(out,
"%s", line);
12238 if (!(out = fopen(filename,
"w")))
12239 ERRMSG(
"Cannot create file!");
12246 "# $1 = time [s]\n"
12247 "# $2 = altitude [km]\n"
12248 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
12251 "# $1 = time [s]\n"
12252 "# $2 = altitude [km]\n" "# $3 = x [m]\n" "# $4 = y [m]\n");
12255 for (
int iq = 0; iq < ctl->
nq; iq++)
12256 fprintf(out,
"# $%i = %s [%s]\n", iq + 5, ctl->
qnt_name[iq],
12258 fprintf(out,
"\n");
12261 for (
int ip = 0; ip < atm->
np; ip += ctl->
atm_stride) {
12269 fprintf(out,
"%.2f %g %g %g",
12270 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]
12273 fprintf(out,
"%.2f %g %.2f %.2f",
12274 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]
12278 for (
int iq = 0; iq < ctl->
nq; iq++) {
12283 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
12285 fprintf(out,
"\n");
12295 const char *filename,
12297 const atm_t *atm) {
12302 if (!(out = fopen(filename,
"w")))
12303 ERRMSG(
"Cannot create file!");
12327 for (
int iq = 0; iq < ctl->
nq; iq++)
12345 const char *filename,
12347 const atm_t *atm) {
12350 ERRMSG(
"CLaMS atmospheric files support only lat/lon grids");
12352 int tid, pid, ncid, varid;
12353 size_t start[2], count[2];
12356 NC(nc_create(filename, NC_NETCDF4, &ncid));
12359 NC(nc_def_dim(ncid,
"time", 1, &tid));
12360 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
12363 int dim_ids[2] = { tid, pid };
12364 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
12365 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
12366 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
12368 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
12370 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
12373 for (
int iq = 0; iq < ctl->
nq; iq++)
12383 NC(nc_enddef(ncid));
12391 for (
int iq = 0; iq < ctl->
nq; iq++)
12395 NC(nc_close(ncid));
12401 const char *dirname,
12407 ERRMSG(
"CLaMS atmospheric files support only lat/lon grids");
12410 static size_t out_cnt = 0;
12412 double r, r_start, r_stop;
12413 int year, mon, day, hour, min, sec;
12414 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
12415 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
12416 char filename_out[2 *
LEN] =
"traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
12418 int ncid, varid, tid, pid, cid;
12426 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
12428 &min_start, &sec_start, &r_start);
12430 &min_stop, &sec_stop, &r_stop);
12432 sprintf(filename_out,
12433 "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc", dirname,
12434 year_start % 100, mon_start, day_start, hour_start,
12435 year_stop % 100, mon_stop, day_stop, hour_stop);
12436 LOG(1,
"Write traj file: %s", filename_out);
12439 start[0] = out_cnt;
12442 count[1] = (size_t) atm->
np;
12445 if (out_cnt == 0) {
12448 NC(nc_create(filename_out, NC_NETCDF4, &ncid));
12451 NC(nc_def_dim(ncid,
"time", NC_UNLIMITED, &tid));
12452 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
12453 NC(nc_def_dim(ncid,
"TMDT", 7, &cid));
12458 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
12459 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
12460 NC_DEF_VAR(
"LAT", NC_DOUBLE, 2, dim_ids,
"Latitude",
"deg",
12462 NC_DEF_VAR(
"LON", NC_DOUBLE, 2, dim_ids,
"Longitude",
"deg",
12464 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 2, dim_ids,
"Pressure",
"hPa",
12466 NC_DEF_VAR(
"ZETA", NC_DOUBLE, 2, dim_ids,
"Zeta",
"K",
12468 for (
int iq = 0; iq < ctl->
nq; iq++)
12478 NC(nc_enddef(ncid));
12479 NC(nc_close(ncid));
12486 NC(nc_open(filename_out, NC_WRITE, &ncid));
12498 for (
int iq = 0; iq < ctl->
nq; iq++)
12502 NC(nc_close(ncid));
12505 if ((year == year_stop) && (mon == mon_stop)
12506 && (day == day_stop) && (hour == hour_stop)) {
12509 char filename_init[2 *
LEN] =
"./init_fix_YYYYMMDDHH.nc";
12510 sprintf(filename_init,
"%s/init_fix_%02d%02d%02d%02d.nc",
12511 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
12512 LOG(1,
"Write init file: %s", filename_init);
12515 NC(nc_create(filename_init, NC_NETCDF4, &ncid));
12518 NC(nc_def_dim(ncid,
"time", 1, &tid));
12519 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
12524 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
12525 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
12526 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
12528 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
12530 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
12533 for (
int iq = 0; iq < ctl->
nq; iq++)
12543 NC(nc_enddef(ncid));
12551 for (
int iq = 0; iq < ctl->
nq; iq++)
12555 NC(nc_close(ncid));
12562 const char *filename,
12564 const atm_t *atm) {
12566 int ncid, obsid, varid;
12568 size_t start[2], count[2];
12571 NC(nc_create(filename, NC_NETCDF4, &ncid));
12574 NC(nc_def_dim(ncid,
"obs", (
size_t) atm->
np, &obsid));
12577 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &obsid,
"time",
12578 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
12579 NC_DEF_VAR(
"press", NC_DOUBLE, 1, &obsid,
"pressure",
"hPa",
12581 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &obsid,
"longitude",
"degrees_east",
12583 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &obsid,
"latitude",
"degrees_north",
12585 for (
int iq = 0; iq < ctl->
nq; iq++)
12594 NC(nc_enddef(ncid));
12601 for (
int iq = 0; iq < ctl->
nq; iq++)
12605 NC(nc_close(ncid));
12611 const char *filename,
12617 ERRMSG(
"Only lat/lon grid supported");
12621 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
12624 static int *obscount, nobs, nk;
12628 const int ensemble = (ctl->
nens > 0);
12634 if (ctl->
qnt_m < 0)
12635 ERRMSG(
"Need quantity mass!");
12638 ERRMSG(
"Missing ensemble IDs!");
12640 ERRMSG(
"Too many ensembles!");
12647 ALLOC(area,
double,
12653 ALLOC(rlon,
double,
12655 ALLOC(rlat,
double,
12657 ALLOC(robs,
double,
12668 LOG(1,
"Write CSI%s data: %s", ensemble ?
" ensemble" :
"", filename);
12669 if (!(out = fopen(filename,
"w")))
12670 ERRMSG(
"Cannot create file!");
12674 "# $1 = time [s]\n"
12675 "# $2 = ensemble ID\n"
12676 "# $3 = number of hits (cx)\n"
12677 "# $4 = number of misses (cy)\n"
12678 "# $5 = number of false alarms (cz)\n"
12679 "# $6 = number of observations (cx + cy)\n"
12680 "# $7 = number of forecasts (cx + cz)\n"
12681 "# $8 = bias (%%)\n"
12682 "# $9 = POD (%%)\n"
12683 "# $10 = FAR (%%)\n"
12684 "# $11 = CSI (%%)\n"
12685 "# $12 = hits by random chance\n"
12686 "# $13 = ETS (%%)\n"
12687 "# $14 = Pearson R\n"
12688 "# $15 = Spearman R\n"
12689 "# $16 = mean error [kg/m²]\n"
12690 "# $17 = RMSE [kg/m²]\n"
12691 "# $18 = MAE [kg/m²]\n"
12692 "# $19 = log-likelihood\n" "# $20 = number of points\n\n");
12700 for (
int iy = 0; iy < ctl->
csi_ny; iy++) {
12701 const double lat = ctl->
csi_lat0 + dlat * (iy + 0.5);
12702 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.0) * cos(
DEG2RAD(lat));
12707 const double t0 = t - 0.5 * ctl->
dt_mod;
12708 const double t1 = t + 0.5 * ctl->
dt_mod;
12712 ALLOC(modmean,
double,
12713 (ensemble ? ctl->
nens : 1) * grid_size);
12714 ALLOC(obsmean,
double,
12716 ALLOC(obscount,
int,
12718 ALLOC(obsstd,
double,
12722 for (
int i = 0; i < (ensemble ? ctl->
nens : 1); i++)
12723 ct[i] = cx[i] = cy[i] = cz[i] = n[i] = 0;
12726 for (
int i = 0; i < nobs; i++) {
12727 if (rt[i] < t0 || rt[i] >= t1 || !isfinite(robs[i]))
12731 const int ix = (int) ((rlon[i] - ctl->
csi_lon0) / dlon);
12732 const int iy = (int) ((rlat[i] - ctl->
csi_lat0) / dlat);
12733 const int iz = (int) ((rz[i] - ctl->
csi_z0) / dz);
12734 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
12740 obsmean[idx] += robs[i];
12741 obsstd[idx] +=
SQR(robs[i]);
12746 for (
int ip = 0; ip < atm->
np; ip++) {
12749 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
12753 int ens_id = ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
12754 if (ens_id < 0 || ens_id >= (ensemble ? ctl->
nens : 1))
12755 ERRMSG(
"Ensemble ID out of range!");
12758 const int ix = (int) ((atm->
lon[ip] - ctl->
csi_lon0) / dlon);
12759 const int iy = (int) ((atm->
lat[ip] - ctl->
csi_lat0) / dlat);
12760 const int iz = (int) ((
Z(atm->
p[ip]) - ctl->
csi_z0) / dz);
12761 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
12771 for (
int e = 0; e < (ensemble ? ctl->
nens : 1); e++) {
12773 for (
int ix = 0; ix < ctl->
csi_nx; ix++)
12774 for (
int iy = 0; iy < ctl->
csi_ny; iy++)
12775 for (
int iz = 0; iz < ctl->
csi_nz; iz++) {
12780 if (obscount[idx]) {
12781 obsmean[idx] /= obscount[idx];
12783 sqrt(obsstd[idx] / obscount[idx] -
SQR(obsmean[idx]));
12787 const int midx = e * grid_size + idx;
12788 if (modmean[midx] > 0)
12789 modmean[midx] /= (1e6 * area[iy]);
12792 if (obscount[idx]) {
12807 x[n[e]] = modmean[midx];
12808 y[n[e]] = obsmean[idx];
12810 obsstdn[n[e]] = obsstd[idx];
12811 if ((++n[e]) >=
NCSI)
12812 ERRMSG(
"Too many points for statistics!");
12824 static double work[2 *
NCSI], work2[2 *
NCSI];
12825 const int n_obs = cx[e] + cy[e];
12826 const int n_for = cx[e] + cz[e];
12827 const double cx_rd = (ct[e] > 0) ? (1. * n_obs * n_for) / ct[e] : NAN;
12828 const double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
12829 const double pod = (n_obs > 0) ? 100. * cx[e] / n_obs : NAN;
12830 const double far = (n_for > 0) ? 100. * cz[e] / n_for : NAN;
12832 (cx[e] + cy[e] + cz[e] >
12833 0) ? 100. * cx[e] / (cx[e] + cy[e] + cz[e]) : NAN;
12835 (cx[e] + cy[e] + cz[e] - cx_rd >
12836 0) ? 100. * (cx[e] - cx_rd) / (cx[e] + cy[e] + cz[e] - cx_rd) : NAN;
12837 const double rho_p = gsl_stats_correlation(x, 1, y, 1, (
size_t) n[e]);
12838 const double rho_s =
12839 gsl_stats_spearman(x, 1, y, 1, (
size_t) n[e], work);
12840 for (
int i = 0; i < n[e]; i++) {
12841 work[i] = x[i] - y[i];
12842 work2[i] = (obsstdn[i] != 0) ? work[i] / obsstdn[i] : 0;
12844 const double mean = gsl_stats_mean(work, 1, (
size_t) n[e]);
12845 const double rmse =
12846 gsl_stats_sd_with_fixed_mean(work, 1, (
size_t) n[e], 0.0);
12847 const double absdev = gsl_stats_absdev_m(work, 1, (
size_t) n[e], 0.0);
12848 const double loglikelihood =
12849 gsl_stats_tss_m(work2, 1, (
size_t) n[e], 0.0) * -0.5;
12853 "%.2f %d %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n",
12854 t, ensemble ? e : -999, cx[e], cy[e], cz[e], n_obs, n_for, bias,
12855 pod, far, csi, cx_rd, ets, rho_p, rho_s, mean, rmse, absdev,
12856 loglikelihood, n[e]);
12859 for (
int i = 0; i < n[e]; i++)
12860 work[i] = work2[i] = x[i] = y[i] = obsstdn[i] = 0;
12861 ct[e] = cx[e] = cy[e] = cz[e] = n[e] = 0;
12889 const char *filename,
12895 ERRMSG(
"Only lat/lon grid supported");
12902 static int n[
NENS];
12909 ERRMSG(
"Missing ensemble IDs!");
12912 const double t0 = t - 0.5 * ctl->
dt_mod;
12913 const double t1 = t + 0.5 * ctl->
dt_mod;
12916 for (
int i = 0; i <
NENS; i++) {
12917 for (
int iq = 0; iq < ctl->
nq; iq++)
12918 qm[iq][i] = qs[iq][i] = 0;
12919 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
12924 for (
int ip = 0; ip < atm->
np; ip++) {
12927 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
12932 ERRMSG(
"Ensemble ID is out of range!");
12936 for (
int iq = 0; iq < ctl->
nq; iq++) {
12937 qm[iq][ctl->
qnt_ens] += atm->
q[iq][ip];
12948 LOG(1,
"Write ensemble data: %s", filename);
12949 if (!(out = fopen(filename,
"w")))
12950 ERRMSG(
"Cannot create file!");
12954 "# $1 = time [s]\n"
12955 "# $2 = altitude [km]\n"
12956 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
12957 for (
int iq = 0; iq < ctl->
nq; iq++)
12958 fprintf(out,
"# $%d = %s (mean) [%s]\n", 5 + iq,
12960 for (
int iq = 0; iq < ctl->
nq; iq++)
12961 fprintf(out,
"# $%d = %s (sigma) [%s]\n", 5 + ctl->
nq + iq,
12963 fprintf(out,
"# $%d = number of members\n\n", 5 + 2 * ctl->
nq);
12966 for (
int i = 0; i <
NENS; i++)
12968 cart2geo(xm[i], &dummy, &lon, &lat);
12969 fprintf(out,
"%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
12970 for (
int iq = 0; iq < ctl->
nq; iq++) {
12972 fprintf(out, ctl->
qnt_format[iq], qm[iq][i] / n[i]);
12974 for (
int iq = 0; iq < ctl->
nq; iq++) {
12976 double var = qs[iq][i] / n[i] -
SQR(qm[iq][i] / n[i]);
12977 fprintf(out, ctl->
qnt_format[iq], (var > 0 ? sqrt(var) : 0));
12979 fprintf(out,
" %d\n", n[i]);
12989 const char *filename,
12997 ERRMSG(
"Only lat/lon grid supported");
12999 static double kz[
EP], kw[
EP];
13003 double *cd, *mean[
NQ], *sigma[
NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
13005 int *ixs, *iys, *izs, *np;
13011 LOG(1,
"Write grid data: %s", filename);
13024 for (
int iq = 0; iq < ctl->
nq; iq++) {
13025 ALLOC(mean[iq],
double,
13027 ALLOC(sigma[iq],
double,
13030 ALLOC(vmr_impl,
double,
13038 ALLOC(area,
double,
13040 ALLOC(press,
double,
13057#pragma omp parallel
for default(shared)
13058 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
13059 z[iz] = ctl->
grid_z0 + dz * (iz + 0.5);
13060 press[iz] =
P(z[iz]);
13064 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13065 lon[ix] = ctl->
grid_lon0 + dlon * (ix + 0.5);
13066#pragma omp parallel for default(shared)
13067 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
13068 lat[iy] = ctl->
grid_lat0 + dlat * (iy + 0.5);
13069 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
13073 const double t0 = t - 0.5 * ctl->
dt_mod;
13074 const double t1 = t + 0.5 * ctl->
dt_mod;
13077#pragma omp parallel for default(shared)
13078 for (
int ip = 0; ip < atm->
np; ip++) {
13079 ixs[ip] = (int) ((atm->
lon[ip] - ctl->
grid_lon0) / dlon);
13080 iys[ip] = (int) ((atm->
lat[ip] - ctl->
grid_lat0) / dlat);
13081 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
grid_z0) / dz);
13082 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
13083 || ixs[ip] < 0 || ixs[ip] >= ctl->
grid_nx
13084 || iys[ip] < 0 || iys[ip] >= ctl->
grid_ny
13085 || izs[ip] < 0 || izs[ip] >= ctl->
grid_nz)
13090 for (
int ip = 0; ip < atm->
np; ip++)
13091 if (izs[ip] >= 0) {
13096 for (
int iq = 0; iq < ctl->
nq; iq++) {
13097 mean[iq][idx] += kernel * atm->
q[iq][ip];
13098 sigma[iq][idx] +=
SQR(kernel * atm->
q[iq][ip]);
13103#pragma omp parallel for default(shared)
13104 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13105 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
13106 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
13113 if (ctl->
qnt_m >= 0)
13114 cd[idx] = mean[ctl->
qnt_m][idx] / (1e6 * area[iy]);
13117 vmr_impl[idx] = NAN;
13118 if (ctl->
qnt_m >= 0 && ctl->
molmass > 0 && met0 != NULL
13121 if (mean[ctl->
qnt_m][idx] > 0) {
13127 lon[ix], lat[iy], &temp, ci, cw, 1);
13131 MA / ctl->
molmass * cd[idx] / (
RHO(press[iz], temp) * dz * 1e3);
13137 for (
int iq = 0; iq < ctl->
nq; iq++) {
13138 mean[iq][idx] /= np[idx];
13139 const double var = sigma[iq][idx] / np[idx] -
SQR(mean[iq][idx]);
13140 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
13142 for (
int iq = 0; iq < ctl->
nq; iq++) {
13143 mean[iq][idx] = NAN;
13144 sigma[iq][idx] = NAN;
13151 t, z, lon, lat, area, dz, np);
13156 t, z, lon, lat, area, dz, np);
13160 ERRMSG(
"Grid data format GRID_TYPE unknown!");
13164 for (
int iq = 0; iq < ctl->
nq; iq++) {
13183 const char *filename,
13188 const double *vmr_impl,
13193 const double *area,
13203 if (!(out = popen(
"gnuplot",
"w")))
13204 ERRMSG(
"Cannot create pipe to gnuplot!");
13207 fprintf(out,
"set out \"%s.png\"\n", filename);
13211 int year, mon, day, hour, min, sec;
13212 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
13213 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
13214 year, mon, day, hour, min);
13220 ERRMSG(
"Cannot open file!");
13221 while (fgets(line,
LEN, in))
13222 fprintf(out,
"%s", line);
13229 if (!(out = fopen(filename,
"w")))
13230 ERRMSG(
"Cannot create file!");
13235 "# $1 = time [s]\n"
13236 "# $2 = altitude [km]\n"
13237 "# $3 = longitude [deg]\n"
13238 "# $4 = latitude [deg]\n"
13239 "# $5 = surface area [km^2]\n"
13240 "# $6 = layer depth [km]\n"
13241 "# $7 = column density (implicit) [kg/m^2]\n"
13242 "# $8 = volume mixing ratio (implicit) [ppv]\n"
13243 "# $9 = number of particles [1]\n");
13244 for (
int iq = 0; iq < ctl->
nq; iq++)
13245 fprintf(out,
"# $%i = %s (mean) [%s]\n", 10 + iq, ctl->
qnt_name[iq],
13248 for (
int iq = 0; iq < ctl->
nq; iq++)
13249 fprintf(out,
"# $%i = %s (stddev) [%s]\n", 10 + ctl->
nq + iq,
13251 fprintf(out,
"\n");
13254 for (
int ix = 0; ix < ctl->
grid_nx; ix++) {
13256 fprintf(out,
"\n");
13257 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
13259 fprintf(out,
"\n");
13260 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
13263 fprintf(out,
"%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
13264 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
13265 for (
int iq = 0; iq < ctl->
nq; iq++) {
13267 fprintf(out, ctl->
qnt_format[iq], mean[iq][idx]);
13270 for (
int iq = 0; iq < ctl->
nq; iq++) {
13272 fprintf(out, ctl->
qnt_format[iq], sigma[iq][idx]);
13274 fprintf(out,
"\n");
13287 const char *filename,
13292 const double *vmr_impl,
13297 const double *area,
13301 char longname[2 *
LEN], varname[2 *
LEN];
13305 int *help2, ncid, dimid[10], varid;
13307 size_t start[2], count[2];
13310 ALLOC(help,
double,
13316 NC(nc_create(filename, NC_NETCDF4, &ncid));
13319 NC(nc_def_dim(ncid,
"time", 1, &dimid[0]));
13320 NC(nc_def_dim(ncid,
"z", (
size_t) ctl->
grid_nz, &dimid[1]));
13321 NC(nc_def_dim(ncid,
"lat", (
size_t) ctl->
grid_ny, &dimid[2]));
13322 NC(nc_def_dim(ncid,
"lon", (
size_t) ctl->
grid_nx, &dimid[3]));
13323 NC(nc_def_dim(ncid,
"dz", 1, &dimid[4]));
13326 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &dimid[0],
"time",
13327 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
13328 NC_DEF_VAR(
"z", NC_DOUBLE, 1, &dimid[1],
"altitude",
"km", 0, 0);
13329 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &dimid[2],
"latitude",
"degrees_north", 0,
13331 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &dimid[3],
"longitude",
"degrees_east", 0,
13333 NC_DEF_VAR(
"dz", NC_DOUBLE, 1, &dimid[1],
"layer depth",
"km", 0, 0);
13334 NC_DEF_VAR(
"area", NC_DOUBLE, 1, &dimid[2],
"surface area",
"km**2", 0, 0);
13336 NC_DEF_VAR(
"cd", NC_FLOAT, 4, dimid,
"column density",
"kg m**-2",
13339 "volume mixing ratio (implicit)",
"ppv", ctl->
grid_nc_level, 0);
13340 NC_DEF_VAR(
"np", NC_INT, 4, dimid,
"number of particles",
"1", 0, 0);
13341 for (
int iq = 0; iq < ctl->
nq; iq++) {
13342 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
13343 sprintf(longname,
"%s (mean)", ctl->
qnt_longname[iq]);
13347 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
13348 sprintf(longname,
"%s (stddev)", ctl->
qnt_longname[iq]);
13354 NC(nc_enddef(ncid));
13364 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13365 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
13366 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
13371 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13372 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
13373 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
13378 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13379 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
13380 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
13385 for (
int iq = 0; iq < ctl->
nq; iq++) {
13386 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
13387 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13388 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
13389 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
13396 for (
int iq = 0; iq < ctl->
nq; iq++) {
13397 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
13398 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13399 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
13400 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
13407 NC(nc_close(ncid));
13417 const char *filename,
13422 FILE *out, *level_log = NULL;
13423 if (!(out = fopen(filename,
"w")))
13424 ERRMSG(
"Cannot create file!");
13428 ERRMSG(
"Cannot create compression log file!");
13508 ERRMSG(
"Number of meteo variables doesn't match!");
13528 const char *varname) {
13537 for (
int ix = 0; ix < met->
nx; ix++)
13538 for (
int iy = 0; iy < met->
ny; iy++)
13539 help[
ARRAY_2D(ix, iy, met->
ny)] = var[ix][iy];
13542 LOG(2,
"Write 2-D variable: %s (uncompressed)", varname);
13544 (
size_t) (met->
nx * met->
ny),
13558 const char *varname,
13569#pragma omp parallel for default(shared) collapse(2)
13570 for (
int ix = 0; ix < met->
nx; ix++)
13571 for (
int iy = 0; iy < met->
ny; iy++)
13572 for (
int ip = 0; ip < met->
np; ip++)
13573 help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)] = var[ix][iy][ip];
13577 LOG(2,
"Write 3-D variable: %s (uncompressed)", varname);
13579 (
size_t) (met->
nx * met->
ny * met->
np),
13585 compress_pck(ctl, met, varname, help, 0, level_log, out);
13596 compress_zfp(ctl, met, varname, help, 0, level_log, out);
13609 compress_lz4(ctl, met, varname, help, 0, level_log, out);
13615 compress_cms(ctl, met, varname, help, 0, level_log, out);
13628 compress_sz3(ctl, met, varname, help, 0, level_log, out);
13634 ERRMSG(
"MET_TYPE not supported!");
13637 LOG(3,
"%d", metvar);
13647 const char *filename,
13653 size_t start[4], count[4];
13654 NC(nc_create(filename, NC_NETCDF4, &ncid));
13657 int tid, lonid, latid, levid;
13658 NC(nc_def_dim(ncid,
"time", 1, &tid));
13661 NC(nc_def_dim(ncid,
"lon", (
size_t) met->
nx, &lonid));
13662 NC(nc_def_dim(ncid,
"lat", (
size_t) met->
ny, &latid));
13663 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &lonid,
"longitude",
"degrees_east", 0,
13665 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &latid,
"latitude",
"degrees_north", 0,
13668 NC(nc_def_dim(ncid,
"x", (
size_t) met->
nx, &lonid));
13669 NC(nc_def_dim(ncid,
"y", (
size_t) met->
ny, &latid));
13670 NC_DEF_VAR(
"x", NC_DOUBLE, 1, &lonid,
"x",
"easting", 0, 0);
13671 NC_DEF_VAR(
"y", NC_DOUBLE, 1, &latid,
"y",
"northing", 0, 0);
13674 NC(nc_def_dim(ncid,
"lev", (
size_t) met->
np, &levid));
13677 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"time",
13678 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
13679 NC_DEF_VAR(
"lev", NC_DOUBLE, 1, &levid,
"pressure",
"Pa", 0, 0);
13682 int dimid2[2] = { latid, lonid };
13683 NC_DEF_VAR(
"sp", NC_FLOAT, 2, dimid2,
"Surface pressure",
"Pa",
13685 NC_DEF_VAR(
"z", NC_FLOAT, 2, dimid2,
"Geopotential",
"m**2 s**-2",
13687 NC_DEF_VAR(
"t2m", NC_FLOAT, 2, dimid2,
"2 metre temperature",
"K",
13689 NC_DEF_VAR(
"u10m", NC_FLOAT, 2, dimid2,
"10 metre U wind component",
13691 NC_DEF_VAR(
"v10m", NC_FLOAT, 2, dimid2,
"10 metre V wind component",
13694 "Instantaneous eastward turbulent surface stress",
"N m**-2",
13697 "Instantaneous northward turbulent surface stress",
"N m**-2",
13700 "Instantaneous surface sensible heat flux",
"W m**-2",
13702 NC_DEF_VAR(
"lsm", NC_FLOAT, 2, dimid2,
"Land/sea mask",
"-",
13704 NC_DEF_VAR(
"sstk", NC_FLOAT, 2, dimid2,
"Sea surface temperature",
"K",
13706 NC_DEF_VAR(
"blp", NC_FLOAT, 2, dimid2,
"Boundary layer pressure",
"Pa",
13708 NC_DEF_VAR(
"pt", NC_FLOAT, 2, dimid2,
"Tropopause pressure",
"Pa",
13710 NC_DEF_VAR(
"tt", NC_FLOAT, 2, dimid2,
"Tropopause temperature",
"K",
13712 NC_DEF_VAR(
"zt", NC_FLOAT, 2, dimid2,
"Tropopause height",
"m",
13714 NC_DEF_VAR(
"h2ot", NC_FLOAT, 2, dimid2,
"Tropopause water vapor",
"ppv",
13716 NC_DEF_VAR(
"pct", NC_FLOAT, 2, dimid2,
"Cloud top pressure",
"Pa",
13718 NC_DEF_VAR(
"pcb", NC_FLOAT, 2, dimid2,
"Cloud bottom pressure",
"Pa",
13720 NC_DEF_VAR(
"cl", NC_FLOAT, 2, dimid2,
"Total column cloud water",
13723 "Pressure at lifted condensation level (LCL)",
"Pa",
13726 "Pressure at level of free convection (LFC)",
"Pa",
13729 "Pressure at equilibrium level (EL)",
"Pa", ctl->
met_nc_level,
13732 "Convective available potential energy",
"J kg**-1",
13734 NC_DEF_VAR(
"cin", NC_FLOAT, 2, dimid2,
"Convective inhibition",
13736 NC_DEF_VAR(
"o3c", NC_FLOAT, 2, dimid2,
"Total column ozone",
"DU",
13740 int dimid3[3] = { levid, latid, lonid };
13741 NC_DEF_VAR(
"t", NC_FLOAT, 3, dimid3,
"Temperature",
"K",
13743 NC_DEF_VAR(
"u", NC_FLOAT, 3, dimid3,
"U velocity",
"m s**-1",
13745 NC_DEF_VAR(
"v", NC_FLOAT, 3, dimid3,
"V velocity",
"m s**-1",
13747 NC_DEF_VAR(
"w", NC_FLOAT, 3, dimid3,
"Vertical velocity",
"Pa s**-1",
13749 NC_DEF_VAR(
"q", NC_FLOAT, 3, dimid3,
"Specific humidity",
"kg kg**-1",
13751 NC_DEF_VAR(
"o3", NC_FLOAT, 3, dimid3,
"Ozone mass mixing ratio",
13753 NC_DEF_VAR(
"clwc", NC_FLOAT, 3, dimid3,
"Cloud liquid water content",
13755 NC_DEF_VAR(
"crwc", NC_FLOAT, 3, dimid3,
"Cloud rain water content",
13757 NC_DEF_VAR(
"ciwc", NC_FLOAT, 3, dimid3,
"Cloud ice water content",
13759 NC_DEF_VAR(
"cswc", NC_FLOAT, 3, dimid3,
"Cloud snow water content",
13761 NC_DEF_VAR(
"cc", NC_FLOAT, 3, dimid3,
"Cloud cover",
"-",
13765 NC(nc_enddef(ncid));
13779 for (
int ip = 0; ip < met->
np; ip++)
13780 phelp[ip] = 100. * met->
p[ip];
13823 NC(nc_close(ncid));
13830 const char *varname,
13836 size_t start[4], count[4];
13844 for (
int ix = 0; ix < met->
nx; ix++)
13845 for (
int iy = 0; iy < met->
ny; iy++)
13846 help[
ARRAY_2D(iy, ix, met->
nx)] = scl * var[ix][iy];
13849 LOG(2,
"Write 2-D variable: %s (netCDF)", varname);
13860 const char *varname,
13866 size_t start[4], count[4];
13874 for (
int ix = 0; ix < met->
nx; ix++)
13875 for (
int iy = 0; iy < met->
ny; iy++)
13876 for (
int ip = 0; ip < met->
np; ip++)
13877 help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)] = scl * var[ix][iy][ip];
13880 LOG(2,
"Write 3-D variable: %s (netCDF)", varname);
13890 const char *filename,
13898 ERRMSG(
"Only lat/lon grid supported");
13902 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
13903 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
13905 static int nobs, *obscount, ip, okay;
13914 if (ctl->
qnt_m < 0)
13915 ERRMSG(
"Need quantity mass!");
13919 ERRMSG(
"Specify molar mass!");
13926 ALLOC(area,
double,
13930 ALLOC(press,
double,
13936 ALLOC(rlon,
double,
13938 ALLOC(rlat,
double,
13940 ALLOC(robs,
double,
13947 LOG(1,
"Write profile data: %s", filename);
13948 if (!(out = fopen(filename,
"w")))
13949 ERRMSG(
"Cannot create file!");
13953 "# $1 = time [s]\n"
13954 "# $2 = altitude [km]\n"
13955 "# $3 = longitude [deg]\n"
13956 "# $4 = latitude [deg]\n"
13957 "# $5 = pressure [hPa]\n"
13958 "# $6 = temperature [K]\n"
13959 "# $7 = volume mixing ratio [ppv]\n"
13960 "# $8 = H2O volume mixing ratio [ppv]\n"
13961 "# $9 = O3 volume mixing ratio [ppv]\n"
13962 "# $10 = observed BT index [K]\n"
13963 "# $11 = number of observations\n");
13971 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
13972 z[iz] = ctl->
prof_z0 + dz * (iz + 0.5);
13973 press[iz] =
P(z[iz]);
13977 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
13978 lon[ix] = ctl->
prof_lon0 + dlon * (ix + 0.5);
13979 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
13980 lat[iy] = ctl->
prof_lat0 + dlat * (iy + 0.5);
13981 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
13986 const double t0 = t - 0.5 * ctl->
dt_mod;
13987 const double t1 = t + 0.5 * ctl->
dt_mod;
13990 ALLOC(mass,
double,
13992 ALLOC(obsmean,
double,
13994 ALLOC(obscount,
int,
13998 for (
int i = 0; i < nobs; i++) {
14003 else if (rt[i] >= t1)
14007 if (!isfinite(robs[i]))
14011 const int ix = (int) ((rlon[i] - ctl->
prof_lon0) / dlon);
14012 const int iy = (int) ((rlat[i] - ctl->
prof_lat0) / dlat);
14015 if (ix < 0 || ix >= ctl->
prof_nx || iy < 0 || iy >= ctl->
prof_ny)
14020 obsmean[idx] += robs[i];
14025 for (ip = 0; ip < atm->
np; ip++) {
14028 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
14032 const int ix = (int) ((atm->
lon[ip] - ctl->
prof_lon0) / dlon);
14033 const int iy = (int) ((atm->
lat[ip] - ctl->
prof_lat0) / dlat);
14034 const int iz = (int) ((
Z(atm->
p[ip]) - ctl->
prof_z0) / dz);
14037 if (ix < 0 || ix >= ctl->
prof_nx ||
14043 mass[idx] += atm->
q[ctl->
qnt_m][ip];
14047 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
14048 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
14050 if (obscount[idx2] > 0) {
14054 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
14056 if (mass[idx3] > 0) {
14065 fprintf(out,
"\n");
14068 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
14073 lon[ix], lat[iy], &temp, ci, cw, 1);
14075 lon[ix], lat[iy], &h2o, ci, cw, 0);
14077 lon[ix], lat[iy], &o3, ci, cw, 0);
14082 / (
RHO(press[iz], temp) * area[iy] * dz * 1e9);
14085 fprintf(out,
"%.2f %g %g %g %g %g %g %g %g %g %d\n",
14086 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
14087 obsmean[idx2] / obscount[idx2], obscount[idx2]);
14120 const char *filename,
14128 ERRMSG(
"Only lat/lon grid supported");
14132 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[
EP],
14135 static int nobs, nk;
14148 ALLOC(rlon,
double,
14150 ALLOC(rlat,
double,
14152 ALLOC(robs,
double,
14163 LOG(1,
"Write sample data: %s", filename);
14164 if (!(out = fopen(filename,
"w")))
14165 ERRMSG(
"Cannot create file!");
14169 "# $1 = time [s]\n"
14170 "# $2 = altitude [km]\n"
14171 "# $3 = longitude [deg]\n"
14172 "# $4 = latitude [deg]\n"
14173 "# $5 = surface area [km^2]\n"
14174 "# $6 = layer depth [km]\n"
14175 "# $7 = number of particles [1]\n"
14176 "# $8 = column density [kg/m^2]\n"
14177 "# $9 = volume mixing ratio [ppv]\n"
14178 "# $10 = observed BT index [K]\n\n");
14183 area = M_PI * rmax2;
14187 const double t0 = t - 0.5 * ctl->
dt_mod;
14188 const double t1 = t + 0.5 * ctl->
dt_mod;
14191 for (
int i = 0; i < nobs; i++) {
14196 else if (rt[i] >= t1)
14201 geo2cart(0, rlon[i], rlat[i], x0);
14204 const double rp =
P(rz[i]);
14205 const double ptop =
P(rz[i] + ctl->
sample_dz);
14206 const double pbot =
P(rz[i] - ctl->
sample_dz);
14214 for (
int ip = 0; ip < atm->
np; ip++) {
14217 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
14221 if (fabs(rlat[i] - atm->
lat[ip]) > dlat)
14227 if (
DIST2(x0, x1) > rmax2)
14232 if (atm->
p[ip] > pbot || atm->
p[ip] < ptop)
14236 if (ctl->
qnt_m >= 0)
14243 const double cd = mass / (1e6 * area);
14254 rlon[i], rlat[i], &temp, ci, cw, 1);
14263 fprintf(out,
"%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
14264 rlon[i], rlat[i], area, ctl->
sample_dz, np, cd, vmr, robs[i]);
14285 const char *filename,
14291 ERRMSG(
"Only lat/lon grid supported");
14295 static double rmax2, x0[3], x1[3];
14304 LOG(1,
"Write station data: %s", filename);
14307 if (!(out = fopen(filename,
"w")))
14308 ERRMSG(
"Cannot create file!");
14312 "# $1 = time [s]\n"
14313 "# $2 = altitude [km]\n"
14314 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
14315 for (
int iq = 0; iq < ctl->
nq; iq++)
14316 fprintf(out,
"# $%i = %s [%s]\n", (iq + 5),
14318 fprintf(out,
"\n");
14326 const double t0 = t - 0.5 * ctl->
dt_mod;
14327 const double t1 = t + 0.5 * ctl->
dt_mod;
14330 for (
int ip = 0; ip < atm->
np; ip++) {
14333 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
14349 if (
DIST2(x0, x1) > rmax2)
14357 fprintf(out,
"%.2f %g %g %g",
14358 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]);
14359 for (
int iq = 0; iq < ctl->
nq; iq++) {
14361 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
14363 fprintf(out,
"\n");
14374 const char *filename,
14380 ERRMSG(
"Only lat/lon grid supported");
14388 LOG(1,
"Write VTK data: %s", filename);
14391 const double t0 = t - 0.5 * ctl->
dt_mod;
14392 const double t1 = t + 0.5 * ctl->
dt_mod;
14395 if (!(out = fopen(filename,
"w")))
14396 ERRMSG(
"Cannot create file!");
14400 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
14401 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
14408 "# vtk DataFile Version 3.0\n"
14409 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
14412 fprintf(out,
"POINTS %d float\n", np);
14414 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
14415 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
14419 const double coslat = cos(
DEG2RAD(atm->
lat[ip]));
14420 const double x = radius * coslat * cos(
DEG2RAD(atm->
lon[ip]));
14421 const double y = radius * coslat * sin(
DEG2RAD(atm->
lon[ip]));
14422 const double z = radius * sin(
DEG2RAD(atm->
lat[ip]));
14423 fprintf(out,
"%g %g %g\n", x, y, z);
14426 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
14427 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
14429 fprintf(out,
"%g %g %g\n", atm->
lon[ip], atm->
lat[ip],
14434 fprintf(out,
"POINT_DATA %d\n", np);
14435 for (
int iq = 0; iq < ctl->
nq; iq++) {
14436 fprintf(out,
"SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
14438 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
14439 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
14441 fprintf(out,
"%g\n", atm->
q[iq][ip]);
void read_met_geopot(const ctl_t *ctl, met_t *met)
Calculates geopotential heights from meteorological data.
void mptrac_alloc(ctl_t **ctl, cache_t **cache, clim_t **clim, met_t **met0, met_t **met1, atm_t **atm, dd_t **dd)
Allocates and initializes memory resources for MPTRAC.
void mptrac_write_atm(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes air parcel data to a file in various formats.
void day2doy(const int year, const int mon, const int day, int *doy)
Get day of year from date.
void read_met_extrapolate(met_t *met)
Extrapolates meteorological data.
void write_atm_clams_traj(const char *dirname, const ctl_t *ctl, const atm_t *atm, const double t)
Writes CLaMS trajectory data to a NetCDF file.
int read_met_nc_2d(const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const char *varname5, const char *varname6, const ctl_t *ctl, const met_t *met, dd_t *dd, float dest[EX][EY], const float scl, const int init)
Reads a 2-dimensional meteorological variable from a NetCDF file.
void write_met_nc_2d(const int ncid, const char *varname, met_t *met, float var[EX][EY], const float scl)
Writes a 2D meteorological variable to a NetCDF file.
void read_met_sample(const ctl_t *ctl, met_t *met)
Downsamples meteorological data based on specified parameters.
void read_obs(const char *filename, const ctl_t *ctl, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from a file and stores it in arrays.
void module_advect(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Advances particle positions using different advection schemes.
void module_timesteps(const ctl_t *ctl, cache_t *cache, met_t *met0, atm_t *atm, const double t)
Calculate time steps for air parcels based on specified conditions.
void module_meteo(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Update atmospheric properties using meteorological data.
void read_clim_photo(const char *filename, clim_photo_t *photo)
Reads photolysis rates from a NetCDF file and populates the given photolysis structure.
void read_met_cloud(met_t *met)
Calculates cloud-related variables for each grid point.
void module_decay(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, atm_t *atm)
Simulate exponential decay processes for atmospheric particles.
double sedi(const double p, const double T, const double rp, const double rhop)
Calculates the sedimentation velocity of a particle in air.
double cos_sza(const double sec, const double lon, const double lat)
Calculates the cosine of the solar zenith angle.
void intpol_met_space_2d(const met_t *met, float array[EX][EY], const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables in 2D space.
int read_met_nc_3d(const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const ctl_t *ctl, const met_t *met, dd_t *dd, float dest[EX][EY][EP], const float scl)
Reads a 3-dimensional meteorological variable from a NetCDF file.
int read_atm_nc(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a generic netCDF file and populates the given atmospheric structure.
void read_met_pbl(const ctl_t *ctl, met_t *met)
Computes the planetary boundary layer (PBL) pressure based on meteorological data.
void read_met_detrend(const ctl_t *ctl, met_t *met)
Detrends meteorological data.
void read_met_tropo(const ctl_t *ctl, const clim_t *clim, met_t *met)
Calculates the tropopause and related meteorological variables based on various methods and stores th...
void read_obs_asc(const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from an ASCII file.
void module_chem_init(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Initializes the chemistry modules by setting atmospheric composition.
int locate_reg(const double *xx, const int n, const double x)
Locate the index of the interval containing a given value in a regular grid.
void compress_log_header(FILE *out)
Write the ASCII header for per-level compression diagnostics.
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.
void mptrac_run_timestep(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t **met0, met_t **met1, atm_t *atm, double t, dd_t *dd)
Executes a single timestep of the MPTRAC model simulation.
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 module_mixing_help(const ctl_t *ctl, const clim_t *clim, atm_t *atm, const int *ixs, const int *iys, const int *izs, const int qnt_idx, const int use_ensemble)
Perform subgrid-scale interparcel mixing of a given quantity.
void read_clim_photo_help(const int ncid, const char *varname, const clim_photo_t *photo, double var[CP][CSZA][CO3])
Reads a 3D climatological photochemistry variable from a NetCDF file.
void read_met_ml2pl(const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname)
Interpolates meteorological data to specified pressure levels.
double clim_tropo(const clim_t *clim, const double t, const double lat)
Calculates the tropopause pressure based on climatological data.
void read_obs_nc(const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from a NetCDF file.
void read_met_bin_2d(FILE *in, const met_t *met, float var[EX][EY], const char *varname)
Reads a 2-dimensional meteorological variable from a binary file and stores it in the provided array.
int locate_irr(const double *xx, const int n, const double x)
Locate the index of the interval containing a given value in a sorted array.
void module_isosurf_init(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Initialize the isosurface module based on atmospheric data.
void level_definitions(ctl_t *ctl)
Defines pressure levels for meteorological data.
void write_grid_asc(const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
Writes grid data to an ASCII file.
void mptrac_update_device(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
Updates device memory for specified data structures.
void time2jsec(const int year, const int mon, const int day, const int hour, const int min, const int sec, const double remain, double *jsec)
Converts time components to seconds since January 1, 2000, 12:00:00 UTC.
void mptrac_init(ctl_t *ctl, cache_t *cache, clim_t *clim, atm_t *atm, const int ntask)
Initializes the MPTRAC model and its associated components.
void intpol_met_time_3d(const met_t *met0, float array0[EX][EY][EP], const met_t *met1, float array1[EX][EY][EP], const double ts, const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological data in 3D space and time.
void 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.
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 compress_error_stats(const float *org, const float *cmp, const size_t n, double *mean, double *stddev, double *min, double *max, double *nrmse, double *org_mean, double *range)
Compute error statistics between original and reconstructed data.
void module_chem_grid(const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double tt)
Computes gridded chemical tracer concentrations (volume mixing ratio) from individual air parcel mass...
double clim_photo(const double rate[CP][CSZA][CO3], const clim_photo_t *photo, const double p, const double sza, const double o3c)
Calculates the photolysis rate for a given set of atmospheric conditions.
void read_clim_zm(const char *filename, const char *varname, clim_zm_t *zm)
Reads zonally averaged climatological data from a netCDF file and populates the given structure.
void read_met_nc_grid_dd_naive(dd_t *dd, const ctl_t *ctl, met_t *met, const int ncid)
Read meteorological grid information and construct the domain-decomposed grid with halo regions.
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_sort(const ctl_t *ctl, const met_t *met0, atm_t *atm)
Sort particles according to box index.
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 module_advect_init(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Initializes the advection module by setting up pressure fields.
void module_radio_decay(const ctl_t *ctl, const cache_t *cache, atm_t *atm)
Apply radioactive decay to atmospheric tracer species.
void mptrac_get_met(ctl_t *ctl, clim_t *clim, const double t, met_t **met0, met_t **met1, dd_t *dd)
Retrieves meteorological data for the specified time.
void module_sort_help(double *a, const int *p, const int np)
Reorder an array based on a given permutation.
float stddev(const float *data, const int n)
Calculates the standard deviation of a set of data.
void intpol_tropo_3d(const double time0, float array0[EX][EY], const double time1, float array1[EX][EY], const double lons[EX], const double lats[EY], const int nlon, const int nlat, const double time, const double lon, const double lat, const int method, double *var, double *sigma)
Interpolates tropopause data in 3D (latitude, longitude, and time).
void read_met_bin_3d(FILE *in, const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname, const float bound_min, const float bound_max)
Reads 3D meteorological data from a binary file, potentially using different compression methods.
int locate_irr_float(const float *xx, const int n, const double x, const int ig)
Locate the index of the interval containing a given value in an irregularly spaced array.
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 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 rho, 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 write_met_nc(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a NetCDF file.
void module_rng_init(const int ntask)
Initialize random number generators for parallel tasks.
int mptrac_read_atm(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a specified file into the given atmospheric structure.
void mptrac_update_host(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
Updates host memory for specified data structures.
void mptrac_write_output(const char *dirname, const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double t)
Writes various types of output data to files in a specified directory.
double clim_oh(const ctl_t *ctl, const clim_t *clim, const double t, const double lon, const double lat, const double p)
Calculates the hydroxyl radical (OH) concentration from climatology data, with an optional diurnal co...
void 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 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)
State variables of cuRAND random number generator.
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 doy2day(const int year, const int doy, int *mon, int *day)
Converts a given day of the year (DOY) to a date (month and day).
void intpol_met_4d_zeta(const met_t *met0, float heights0[EX][EY][EP], float array0[EX][EY][EP], const met_t *met1, float heights1[EX][EY][EP], float array1[EX][EY][EP], const double ts, const double height, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables to a given position and time.
void intpol_met_time_2d(const met_t *met0, float array0[EX][EY], const met_t *met1, float array1[EX][EY], const double ts, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological data in 2D space and time.
void module_position(const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Update the positions and pressure levels of atmospheric particles.
void clim_oh_diurnal_correction(const ctl_t *ctl, clim_t *clim)
Applies a diurnal correction to the hydroxyl radical (OH) concentration in climatology data.
void locate_vert(float profiles[EX][EY][EP], const int np, const int lon_ap_ind, const int lat_ap_ind, const double height_ap, int *ind)
Locate the four vertical indizes of a box for a given height value.
void write_met_bin_2d(FILE *out, met_t *met, float var[EX][EY], const char *varname)
Writes a 2-dimensional meteorological variable to a binary file.
void read_met_pv(met_t *met)
Calculates potential vorticity (PV) from meteorological data.
int read_atm_bin(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a binary file and populates the given atmospheric structure.
void module_diff_meso(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate mesoscale diffusion for atmospheric particles.
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 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.
int mptrac_read_met(const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met, dd_t *dd)
Reads meteorological data from a file, supporting multiple formats and MPI broadcasting.
void write_vtk(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes VTK (Visualization Toolkit) data to a specified file.
void module_tracer_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Simulate chemical reactions involving long-lived atmospheric tracers.
void mptrac_read_ctl(const char *filename, int argc, char *argv[], ctl_t *ctl)
Reads control parameters from a configuration file and populates the given structure.
void mptrac_free(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm, dd_t *dd)
Frees memory resources allocated for MPTRAC.
void read_met_polar_winds(met_t *met)
Applies a fix for polar winds in meteorological data.
void module_h2o2_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Perform chemical reactions involving H2O2 within cloud particles.
void write_grid_nc(const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
Writes grid data to a NetCDF file.
double pbl_weight(const ctl_t *ctl, const atm_t *atm, const int ip, const double pbl, const double ps)
Computes a weighting factor based on planetary boundary layer pressure.
void module_diff_pbl(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Computes particle diffusion within the planetary boundary layer (PBL).
void write_met_nc_3d(const int ncid, const char *varname, met_t *met, float var[EX][EY][EP], const float scl)
Writes a 3D meteorological variable to a NetCDF file.
void module_isosurf(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Apply the isosurface module to adjust atmospheric properties.
void module_oh_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Perform hydroxyl chemistry calculations for atmospheric particles.
void geo2cart(const double z, const double lon, const double lat, double *x)
Converts geographic coordinates (longitude, latitude, altitude) to Cartesian coordinates.
void read_met_nc_grid(const char *filename, const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads meteorological grid data from NetCDF files with domain decomposition.
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 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.
double lapse_rate(const double t, const double h2o)
Calculates the moist adiabatic lapse rate in Kelvin per kilometer.
void write_csi(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes Critical Success Index (CSI) data to a file.
void write_atm_nc(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a NetCDF file.
MPTRAC library declarations.
#define NN(x0, y0, x1, y1, x)
Perform nearest-neighbor interpolation.
void dd_init(const ctl_t *ctl, dd_t *dd, atm_t *atm)
Initialize the domain decomposition infrastructure.
#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 PARTICLE_LOOP(ip0, ip1, check_dt,...)
Loop over particle indices with OpenACC acceleration.
#define MA
Molar mass of dry air [g/mol].
#define AVO
Avogadro constant [1/mol].
#define KB
Boltzmann constant [kg m^2/(K s^2)].
#define MH2O
Molar mass of water vapor [g/mol].
#define METVAR
Number of 3-D meteorological variables.
#define NENS
Maximum number of data points for ensemble analysis.
#define FWRITE(ptr, type, size, out)
Write data from memory to a file stream.
#define PW(p, h2o)
Calculate partial water vapor pressure.
#define H0
Scale height [km].
#define NC_PUT_ATT_GLOBAL(attname, text)
Add a global text attribute to a NetCDF file.
#define MOLEC_DENS(p, t)
Calculate the density of a gas molecule.
#define LAPSE(p1, t1, p2, t2)
Calculate lapse rate.
#define NC(cmd)
Execute a NetCDF command and check for errors.
#define SELECT_TIMER(id, group)
Select and start a timer with specific attributes.
#define ECC_READ_3D(variable, level, target, scaling_factor, found_flag)
Writes 3D data from a grib message into the meteo struct.
void compress_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 DOTP(a, b)
Calculate the dot product of two vectors.
#define RA
Specific gas constant of dry air [J/(kg K)].
int dd_calc_subdomain_from_coords(const ctl_t *ctl, const dd_t *dd, const double lon, const double lat)
Determine MPI subdomain from particle coordinates.
#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 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 EY
Maximum number of latitudes for meteo data.
#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 INTPOL_3D(var, init)
Perform 3D interpolation for a meteorological variable.
#define NOBS
Maximum number of observation data points.
#define NTHREADS
Maximum number of OpenMP threads.
#define ARRAY_2D(ix, iy, ny)
Macro for computing the linear index of a 2D array element.
#define Z(p)
Convert pressure to altitude.
#define codes_handle
Placeholder when ECCODES is not available.
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 P(z)
Compute pressure at given altitude.
#define LV
Latent heat of vaporization of water [J/kg].
#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.
void dd_assign_subdomains(const ctl_t *ctl, const dd_t *dd, atm_t *atm, const int init)
Assign or update particle subdomain ownership.
#define FREAD(ptr, type, size, in)
Read data from a file stream and store it in memory.
#define DX2DEG(dx, lat)
Convert a distance in kilometers to degrees longitude at a given latitude.
#define DEG2DY(dlat)
Convert a latitude difference to a distance in the y-direction (north-south).
#define EX
Maximum number of longitudes for meteo data.
#define EPS
Ratio of the specific gas constant of dry air and water vapor [1].
#define PSICE(t)
Compute saturation pressure over ice (WMO, 2018).
#define DX2COORD(met, dx, lat)
Convert a distance in meters to a coordinate value based on grid type.
#define THETA(p, t)
Compute potential temperature.
void dd_normalize_lon_lat(const dd_t *dd, double *lon, double *lat)
Normalize geographic coordinates to the global grid convention.
#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 SET_QNT(qnt, name, longname, unit)
Set atmospheric quantity index.
void dd_sort(const ctl_t *ctl, const met_t *met0, atm_t *atm, dd_t *dd, int *npart)
Sort local atmospheric particles and determine export counts for domain decomposition.
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.
#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 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 ZETA(ps, p, t)
Computes the value of the zeta vertical coordinate.
#define RHICE(p, t, h2o)
Compute relative humidity over ice.
#define INTPOL_TIME_ALL(time, p, lon, lat)
Interpolate multiple meteorological variables in time.
#define ALLOC(ptr, type, n)
Allocate memory for a pointer with error handling.
void read_met_grib_levels(codes_handle **handles, const int num_messages, const ctl_t *ctl, met_t *met)
Reads meteorological variables at different vertical levels from a grib file.
#define SET_ATM(qnt, val)
Set atmospheric quantity value.
#define CTS
Maximum number of data points of climatological time series.
#define ECC_READ_2D(variable, target, scaling_factor, found_flag)
Writes 2-D data from a grib message into the meteo struct.
#define DEG2RAD(deg)
Converts degrees to radians.
void broadcast_large_data(void *data, size_t N)
Broadcasts large data across all processes in an MPI communicator.
#define MO3
Molar mass of ozone [g/mol].
#define SQR(x)
Compute the square of a value.
#define RAD2DEG(rad)
Converts radians to degrees.
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.
#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.
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.
#define INTPOL_2D(var, init)
Perform 2D interpolation for a meteorological variable.
#define RH(p, t, h2o)
Compute relative humidity over water.
void module_dd(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.
#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.
void dd_sort_help(double *a, dd_t *dd, const int np)
Apply the sorting permutation to a particle data array.
#define LOG(level,...)
Print a log message with a specified logging level.
#define NC_DEF_VAR(varname, type, ndims, dims, long_name, units, level, quant)
Define a NetCDF variable with attributes.
#define TDEW(p, h2o)
Calculate dew point temperature.
#define ARRHENIUS(a, b, t)
Calculate the Arrhenius rate constant.
#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 RHO(p, t)
Compute density of air.
void module_kpp_chem(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
KPP chemistry module.
#define CO3
Maximum number of total column ozone data for climatological data.
void read_met_grib_grid(codes_handle **handles, int count_handles, met_t *met)
Reads global meteorological information from a grib file.
#define NC_PUT_DOUBLE(varname, ptr, hyperslab)
Write double precision data to a NetCDF variable.
#define ECC(cmd)
Execute an ECCODES command and check for errors.
#define LIN(x0, y0, x1, y1, x)
Linear interpolation.
#define DIST2(a, b)
Calculate the squared Euclidean distance between two points in Cartesian coordinates.
#define NC_INQ_DIM(dimname, ptr, min, max, check)
Inquire the length of a dimension in a NetCDF file.
#define DEG2DX(dlon, lat)
Convert a longitude difference to a distance in the x-direction (east-west) at a specific latitude.
#define 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.
void dd_push(const ctl_t *ctl, atm_t *atm, cache_t *cache, int *npart)
#define MAX(a, b)
Macro to determine the maximum of two values.
#define FMOD(x, y)
Calculate the floating-point remainder of dividing x by y.
double lat[NP]
Latitude [deg].
double lon[NP]
Longitude [deg].
int np
Number of air parcels.
double q[NQ][NP]
Quantity data (for various, user-defined attributes).
double p[NP]
Pressure [hPa].
double dt[NP]
Timesteps [s].
double iso_ts[NP]
Isosurface balloon time [s].
int iso_n
Isosurface balloon number of data points.
double iso_ps[NP]
Isosurface balloon pressure [hPa].
double rs[3 *NP+1]
Random numbers.
float uvwp[NP][3]
Wind perturbations [m/s].
double iso_var[NP]
Isosurface variables.
Climatological data in the form of photolysis rates.
int nsza
Number of solar zenith angles.
double sza[CSZA]
Solar zenith angle [rad].
double o3_1[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O1d + O2) [1/s].
double p[CP]
Pressure [hPa].
double ccl2f2[CP][CSZA][CO3]
CCl2F2 photolysis rate [1/s].
double o2[CP][CSZA][CO3]
O2 photolysis rate [1/s].
double ccl3f[CP][CSZA][CO3]
CCl3F photolysis rate [1/s].
double n2o[CP][CSZA][CO3]
N2O photolysis rate [1/s].
double h2o2[CP][CSZA][CO3]
H2O2 photolysis rate [1/s].
double h2o[CP][CSZA][CO3]
H2O photolysis rate [1/s].
double ccl4[CP][CSZA][CO3]
CCl4 photolysis rate [1/s].
double o3_2[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O3p + O2) [1/s].
double o3c[CO3]
Total column ozone [DU].
int np
Number of pressure levels.
int no3c
Number of total ozone columns.
clim_ts_t ccl2f2
CFC-12 time series.
clim_photo_t photo
Photolysis rates.
clim_zm_t ho2
HO2 zonal means.
clim_zm_t hno3
HNO3 zonal means.
int tropo_ntime
Number of tropopause timesteps.
clim_ts_t sf6
SF6 time series.
clim_ts_t ccl4
CFC-10 time series.
clim_ts_t ccl3f
CFC-11 time series.
clim_zm_t o1d
O(1D) zonal means.
double tropo_lat[73]
Tropopause latitudes [deg].
clim_zm_t h2o2
H2O2 zonal means.
int tropo_nlat
Number of tropopause latitudes.
clim_zm_t oh
OH zonal means.
double tropo[12][73]
Tropopause pressure values [hPa].
double tropo_time[12]
Tropopause time steps [s].
clim_ts_t n2o
N2O time series.
Climatological data in the form of time series.
double vmr[CTS]
Volume mixing ratio [ppv].
double time[CTS]
Time [s].
int ntime
Number of timesteps.
Climatological data in the form of zonal means.
int np
Number of pressure levels.
double p[CP]
Pressure [hPa].
double vmr[CT][CP][CY]
Volume mixing ratio [ppv].
int ntime
Number of timesteps.
int nlat
Number of latitudes.
double lat[CY]
Latitude [deg].
double 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 met_nc_scale
Check netCDF scaling factors (0=no, 1=yes).
int qnt_pel
Quantity array index for pressure at equilibrium level (EL).
int csi_nz
Number of altitudes of gridded CSI data.
double molmass
Molar mass [g/mol].
int qnt_p
Quantity array index for pressure.
int qnt_Cccl2f2
Quantity array index for CFC-12 volume mixing ratio (chemistry code).
int dd_halos_size
Domain decomposition size of halos given in grid-points.
char atm_gpfile[LEN]
Gnuplot file for atmospheric data.
int mixing_nx
Number of longitudes of mixing grid.
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 mixing_trop
Interparcel exchange parameter for mixing in the troposphere.
double sort_dt
Time step for sorting of particle data [s].
double mixing_z1
Upper altitude of mixing grid [km].
double stat_r
Search radius around station [km].
double wet_depo_bc_a
Coefficient A for wet deposition below cloud (exponential form).
int met_zstd_level
ZSTD compression level (from -5 to 22, 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 qnt_psice
Quantity array index for saturation pressure over ice.
double chemgrid_lon0
Lower longitude of chemistry grid [deg].
int bound_pbl
Boundary conditions planetary boundary layer (0=no, 1=yes).
int qnt_mloss_wet
Quantity array index for total mass loss due to wet deposition.
int radio_decay
Switch for radioactive decay module (0=off, 1=on).
int met_geopot_sx
Longitudinal smoothing of geopotential heights.
int met_sy
Smoothing for latitudes.
int qnt_ps
Quantity array index for surface pressure.
int rng_type
Random number generator (0=GSL, 1=Squares, 2=cuRAND).
char prof_obsfile[LEN]
Observation data file for profile output.
int 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 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 met_tropo
Tropopause definition (0=none, 1=clim, 2=cold point, 3=WMO_1st, 4=WMO_2nd, 5=dynamical).
int qnt_rp
Quantity array index for particle radius.
int met_mpi_share
Use MPI to share meteo (0=no, 1=yes).
double mixing_strat
Interparcel exchange parameter for mixing in the stratosphere.
int qnt_vz
Quantity array index for vertical velocity.
int qnt_ho2
Quantity array index for HO2 volume mixing ratio (climatology).
double csi_z1
Upper altitude of gridded CSI data [km].
double stat_t0
Start time for station output [s].
double oh_chem_beta
Beta parameter for diurnal variablity of OH.
int dd
Domain decomposition (0=no, 1=yes, with 2x2 if not specified).
char clim_o1d_filename[LEN]
Filename of O(1D) climatology.
int qnt_eta
Quantity array index for eta vertical coordinate.
char clim_photo[LEN]
Filename of photolysis rates climatology.
double wet_depo_so2_ph
pH value used to calculate effective Henry constant of SO2.
double mixing_z0
Lower altitude of mixing grid [km].
int qnt_mloss_decay
Quantity array index for total mass loss due to exponential decay.
int atm_type_out
Type of atmospheric data files for output (-1=same as ATM_TYPE, 0=ASCII, 1=binary,...
int met_cms_nd0x
cmultiscale number of cells of coarsest grid in x-direction.
int met_nlev
Number of meteo data model levels.
double dt_kpp
Time step for KPP chemistry [s].
char csi_basename[LEN]
Basename of CSI data files.
double dry_depo_dp
Dry deposition surface layer [hPa].
int qnt_shf
Quantity array index for surface sensible heat flux.
int qnt_vs
Quantity array index for surface meridional wind.
int qnt_Cco
Quantity array index for CO volume mixing ratio (chemistry code).
double vtk_dt_out
Time step for VTK data output [s].
double t_stop
Stop time of simulation [s].
double conv_dt
Time interval for convection module [s].
char sample_obsfile[LEN]
Observation data file for sample output.
int qnt_hno3
Quantity array index for HNO3 volume mixing ratio (climatology).
char grid_basename[LEN]
Basename of grid data files.
int met_clams
Read MPTRAC or CLaMS meteo data (0=MPTRAC, 1=CLaMS).
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.
double bound_lat0
Boundary conditions minimum longitude [deg].
double met_pbl_max
Maximum depth of planetary boundary layer [km].
int met_dx
Stride for longitudes.
int qnt_destination
Quantity array index for destination subdomain in domain decomposition.
int mixing_ny
Number of latitudes of mixing grid.
int met_convention
Meteo data layout (0=[lev, lat, lon], 1=[lon, lat, lev]).
int qnt_zeta_d
Quantity array index for diagnosed zeta vertical coordinate.
char clim_h2o2_filename[LEN]
Filename of H2O2 climatology.
int tracer_chem
Switch for first order tracer chemistry module (0=off, 1=on).
double dt_mod
Time step of simulation [s].
int diffusion
Diffusion 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).
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.
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 depth).
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.
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 met_cms_batch
cmultiscale batch size.
double psc_h2o
H2O volume mixing ratio for PSC analysis.
int met_sp
Smoothing for pressure levels.
double prof_lon0
Lower longitude of gridded profile data [deg].
int qnt_Axe133
Quantity array index for radioactive activity of Xe-133.
int chemgrid_nx
Number of longitudes of chemistry grid.
int qnt_pct
Quantity array index for cloud top pressure.
int qnt_mloss_kpp
Quantity array index for total mass loss due to KPP chemistry.
int qnt_psat
Quantity array index for saturation pressure over water.
int qnt_subdomain
Quantity array index for current subdomain in domain decomposition.
double met_lev_hybm[EP]
Meteo data model level b coefficients.
double prof_lat0
Lower latitude of gridded profile data [deg].
int qnt_cin
Quantity array index for convective inhibition (CIN).
double turb_pbl_trans
Depth of turbulent PBL transition layer (fraction of PBL depth).
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].
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].
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 dd_subdomains_zonal
Domain decomposition zonal subdomain number.
int qnt_idx
Quantity array index for air parcel IDs.
double met_tropo_theta
Dynamical tropopause potential temperature threshold [K].
int qnt_rwc
Quantity array index for cloud rain water content.
double t_start
Start time of simulation [s].
char qnt_longname[NQ][LEN]
Quantity long names.
double met_p[EP]
Target pressure levels [hPa].
int nq
Number of quantities.
double tdec_trop
Life time of particles in the troposphere [s].
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.
int qnt_zt
Quantity array index for tropopause geopotential height.
int met_type
Type of meteo data files (0=netCDF, 1=binary, 2=pck, 3=ZFP, 4=ZSTD, 5=cms, 6=grib,...
int qnt_cc
Quantity array index for cloud cover.
int qnt_plcl
Quantity array index for pressure at lifted condensation level (LCL).
double grid_dt_out
Time step for gridded data output [s].
int qnt_tdew
Quantity array index for dew point temperature.
Domain decomposition data structure.
size_t halo_bnd_count[4]
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.
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 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.
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).
float zt[EX][EY]
Tropopause geopotential height [km].
float sst[EX][EY]
Sea surface temperature [K].
float rwc[EX][EY][EP]
Cloud rain water content [kg/kg].
float o3c[EX][EY]
Total column ozone [DU].
float zeta_dotl[EX][EY][EP]
Vertical velocity on model levels [K/s].
float h2o[EX][EY][EP]
Water vapor volume mixing ratio [1].
float cape[EX][EY]
Convective available potential energy [J/kg].
float w[EX][EY][EP]
Vertical velocity [hPa/s].
float pct[EX][EY]
Cloud top pressure [hPa].
double hybrid[EP]
Model hybrid levels.
int nx
Number of longitudes.
int ny
Number of latitudes.
float shf[EX][EY]
Surface sensible heat flux [W/m^2].
float ps[EX][EY]
Surface pressure [hPa].
float lwc[EX][EY][EP]
Cloud liquid water content [kg/kg].
float us[EX][EY]
Surface zonal wind [m/s].
float wl[EX][EY][EP]
Vertical velocity on model levels [hPa/s].
float vl[EX][EY][EP]
Meridional wind on model levels [m/s].
float zs[EX][EY]
Surface geopotential height [km].
float o3[EX][EY][EP]
Ozone volume mixing ratio [1].
float cc[EX][EY][EP]
Cloud cover [1].
int np
Number of pressure levels.
float t[EX][EY][EP]
Temperature [K].
float ts[EX][EY]
Surface temperature [K].
float u[EX][EY][EP]
Zonal wind [m/s].
float ess[EX][EY]
Eastward turbulent surface stress [N/m^2].
float ul[EX][EY][EP]
Zonal wind on model levels [m/s].
float pcb[EX][EY]
Cloud bottom pressure [hPa].
float pel[EX][EY]
Pressure at equilibrium level (EL) [hPa].
float cin[EX][EY]
Convective inhibition [J/kg].
float plcl[EX][EY]
Pressure at lifted condensation level (LCL) [hPa].
double lon[EX]
Longitudes [deg].
float pt[EX][EY]
Tropopause pressure [hPa].
float tt[EX][EY]
Tropopause temperature [K].
float pbl[EX][EY]
Boundary layer pressure [hPa].
float vs[EX][EY]
Surface meridional wind [m/s].
float z[EX][EY][EP]
Geopotential height [km].
float v[EX][EY][EP]
Meridional wind [m/s].
int npl
Number of model levels.
float lsm[EX][EY]
Land-sea mask [1].
float iwc[EX][EY][EP]
Cloud ice water content [kg/kg].
float h2ot[EX][EY]
Tropopause water vapor volume mixing ratio [ppv].
float pv[EX][EY][EP]
Potential vorticity [PVU].
double eta[EP]
Model level eta values.
float cl[EX][EY]
Total column cloud water [kg/m^2].
float nss[EX][EY]
Northward turbulent surface stress [N/m^2].
float pl[EX][EY][EP]
Pressure on model levels [hPa].
float plfc[EX][EY]
Pressure at level of free convection (LFC) [hPa].
double hyam[EP]
Model level a coefficients [Pa].
double lat[EY]
Latitudes [deg].
float swc[EX][EY][EP]
Cloud snow water content [kg/kg].
double hybm[EP]
Model level b coefficients.
float zetal[EX][EY][EP]
Zeta on model levels [K].
double p[EP]
Pressure levels [hPa].
double lat
Latitude [deg].
double lon
Longitude [deg].
double q[NQ]
Quantity data (for various, user-defined attributes).