35static uint64_t rng_ctr;
39static curandGenerator_t rng_curand;
47#define CHUNK_SIZE 2147483647
50 MPI_Bcast(&N, 1, MPI_UINT64_T, 0, MPI_COMM_WORLD);
53 const size_t num_chunks = (N + CHUNK_SIZE - 1) / CHUNK_SIZE;
56 for (
size_t i = 0; i < num_chunks; i++) {
59 const size_t start = i * CHUNK_SIZE;
60 const size_t end = (start + CHUNK_SIZE > N) ? N : start + CHUNK_SIZE;
61 const size_t chunk_size = end - start;
64 MPI_Bcast((
char *) data + start, (
int) chunk_size, MPI_BYTE, 0,
78 const double radius = sqrt(
DOTP(x, x));
80 *lat =
RAD2DEG(asin(x[2] / radius));
81 *lon =
RAD2DEG(atan2(x[1], x[0]));
96 const double sza_thresh =
DEG2RAD(85.), csza_thresh = cos(sza_thresh);
99 const double oh =
clim_zm(&clim->
oh, t, lat, p);
106 const double csza =
cos_sza(t, lon, lat);
107 const double denom = (csza >= csza_thresh) ? csza : csza_thresh;
118 const double sza_thresh =
DEG2RAD(85.), csza_thresh = cos(sza_thresh);
121 for (
int it = 0; it < clim->
oh.
ntime; it++)
122 for (
int iz = 0; iz < clim->
oh.
np; iz++)
123 for (
int iy = 0; iy < clim->
oh.
nlat; iy++) {
130 for (
double lon = -180; lon < 180; lon += 1.0) {
133 const double denom = (csza >= csza_thresh) ? csza : csza_thresh;
139 clim->
oh.
vmr[it][iz][iy] /= (sum / (double) n);
154 if (p < photo->p[photo->
np - 1])
155 p_help = photo->
p[photo->
np - 1];
156 else if (p > photo->
p[0])
157 p_help = photo->
p[0];
160 double sza_help = sza;
161 if (sza < photo->sza[0])
162 sza_help = photo->
sza[0];
163 else if (sza > photo->
sza[photo->
nsza - 1])
164 sza_help = photo->
sza[photo->
nsza - 1];
167 double o3c_help = o3c;
168 if (o3c < photo->o3c[0])
169 o3c_help = photo->
o3c[0];
170 else if (o3c > photo->
o3c[photo->
no3c - 1])
171 o3c_help = photo->
o3c[photo->
no3c - 1];
179 const double aux00 =
LIN(photo->
p[ip], rate[ip][isza][io3c],
180 photo->
p[ip + 1], rate[ip + 1][isza][io3c],
182 const double aux01 =
LIN(photo->
p[ip], rate[ip][isza][io3c + 1],
183 photo->
p[ip + 1], rate[ip + 1][isza][io3c + 1],
185 const double aux10 =
LIN(photo->
p[ip], rate[ip][isza + 1][io3c],
186 photo->
p[ip + 1], rate[ip + 1][isza + 1][io3c],
188 const double aux11 =
LIN(photo->
p[ip], rate[ip][isza + 1][io3c + 1],
189 photo->
p[ip + 1], rate[ip + 1][isza + 1][io3c + 1],
192 LIN(photo->
o3c[io3c], aux00, photo->
o3c[io3c + 1], aux01, o3c_help);
194 LIN(photo->
o3c[io3c], aux10, photo->
o3c[io3c + 1], aux11, o3c_help);
196 LIN(photo->
sza[isza], aux0, photo->
sza[isza + 1], aux1, sza_help);
197 return MAX(aux, 0.0);
208 double sec =
FMOD(t, 365.25 * 86400.);
210 sec += 365.25 * 86400.;
218 clim->
tropo[isec][ilat],
220 clim->
tropo[isec][ilat + 1], lat);
222 clim->
tropo[isec + 1][ilat],
224 clim->
tropo[isec + 1][ilat + 1], lat);
234 LOG(1,
"Initialize tropopause data...");
238 double tropo_time[12] = {
239 1209600.00, 3888000.00, 6393600.00,
240 9072000.00, 11664000.00, 14342400.00,
241 16934400.00, 19612800.00, 22291200.00,
242 24883200.00, 27561600.00, 30153600.00
248 const double tropo_lat[73] = {
249 -90, -87.5, -85, -82.5, -80, -77.5, -75, -72.5, -70, -67.5,
250 -65, -62.5, -60, -57.5, -55, -52.5, -50, -47.5, -45, -42.5,
251 -40, -37.5, -35, -32.5, -30, -27.5, -25, -22.5, -20, -17.5,
252 -15, -12.5, -10, -7.5, -5, -2.5, 0, 2.5, 5, 7.5, 10, 12.5,
253 15, 17.5, 20, 22.5, 25, 27.5, 30, 32.5, 35, 37.5, 40, 42.5,
254 45, 47.5, 50, 52.5, 55, 57.5, 60, 62.5, 65, 67.5, 70, 72.5,
255 75, 77.5, 80, 82.5, 85, 87.5, 90
260 const double tropo[12][73] = {
261 {324.1, 325.6, 325, 324.3, 322.5, 319.7, 314, 307.2, 301.8, 299.6,
262 297.1, 292.2, 285.6, 276.1, 264, 248.9, 231.9, 213.5, 194.4,
263 175.3, 157, 140.4, 126.7, 116.3, 109.5, 105.4, 103, 101.4, 100.4,
264 99.69, 99.19, 98.84, 98.56, 98.39, 98.39, 98.42, 98.44, 98.54,
265 98.68, 98.81, 98.89, 98.96, 99.12, 99.65, 101.4, 105.4, 113.5, 128,
266 152.1, 184.7, 214, 234.1, 247.3, 255.8, 262.6, 267.7, 271.7, 275,
267 277.2, 279, 280.1, 280.4, 280.6, 280.1, 279.3, 278.3, 276.8, 275.8,
268 275.3, 275.6, 275.4, 274.1, 273.5},
269 {337.3, 338.7, 337.8, 336.4, 333, 328.8, 321.1, 312.6, 306.6, 303.7,
270 300.2, 293.8, 285.4, 273.8, 259.6, 242.7, 224.4, 205.2, 186, 167.5,
271 150.3, 135, 122.8, 113.9, 108.2, 104.7, 102.5, 101.1, 100.2, 99.42,
272 98.88, 98.52, 98.25, 98.09, 98.07, 98.1, 98.12, 98.2, 98.25, 98.27,
273 98.26, 98.27, 98.36, 98.79, 100.2, 104.2, 113.7, 131.2, 159.5, 193,
274 220.4, 238.1, 250.2, 258.1, 264.7, 269.7, 273.7, 277.3, 280.2, 282.8,
275 284.9, 286.5, 288.1, 288.8, 289, 288.5, 287.2, 286.3, 286.1, 287.2,
276 287.5, 286.2, 285.8},
277 {335, 336, 335.7, 335.1, 332.3, 328.1, 320.6, 311.8, 305.1, 301.9,
278 297.6, 290, 280.4, 268.3, 254.6, 239.6, 223.9, 207.9, 192.2, 176.9,
279 161.7, 146.4, 132.2, 120.6, 112.3, 107.2, 104.3, 102.4, 101.3,
280 100.4, 99.86, 99.47, 99.16, 98.97, 98.94, 98.97, 99, 99.09, 99.2,
281 99.31, 99.35, 99.41, 99.51, 99.86, 101.1, 104.9, 114.3, 131, 156.8,
282 186.3, 209.3, 224.6, 236.8, 246.3, 254.9, 262.3, 268.8, 274.8,
283 279.9, 284.6, 288.6, 291.6, 294.9, 297.5, 299.8, 301.8, 303.1,
284 304.3, 304.9, 306, 306.6, 306.2, 306},
285 {306.2, 306.7, 305.7, 307.1, 307.3, 306.4, 301.8, 296.2, 292.4,
286 290.3, 287.1, 280.9, 273.4, 264.3, 254.1, 242.8, 231, 219, 207.2,
287 195.5, 183.3, 169.7, 154.7, 138.7, 124.1, 113.6, 107.8, 104.7,
288 102.8, 101.7, 100.9, 100.4, 100, 99.79, 99.7, 99.66, 99.68, 99.79,
289 99.94, 100.2, 100.5, 100.9, 101.4, 102.1, 103.4, 107, 115.2, 129.1,
290 148.7, 171, 190.8, 205.6, 218.4, 229.4, 239.6, 248.6, 256.5,
291 263.7, 270.3, 276.6, 282.6, 288.1, 294.5, 300.4, 306.3, 311.4,
292 315.1, 318.3, 320.3, 322.2, 322.8, 321.5, 321.1},
293 {266.5, 264.9, 260.8, 261, 262, 263, 261.3, 259.7, 259.2, 259.8,
294 260.1, 258.6, 256.7, 253.6, 249.5, 243.9, 237.4, 230, 222.1, 213.9,
295 205, 194.4, 180.4, 161.8, 140.7, 122.9, 112.1, 106.7, 104.1, 102.7,
296 101.8, 101.4, 101.1, 101, 101, 101, 101.1, 101.2, 101.5, 101.9,
297 102.4, 103, 103.8, 104.9, 106.8, 110.1, 115.6, 124, 135.2, 148.9,
298 165.2, 181.3, 198, 211.8, 223.5, 233.8, 242.9, 251.5, 259, 266.2,
299 273.1, 279.2, 286.2, 292.8, 299.6, 306, 311.1, 315.5, 318.8, 322.6,
300 325.3, 325.8, 325.8},
301 {220.1, 218.1, 210.8, 207.2, 207.6, 210.5, 211.4, 213.5, 217.3,
302 222.4, 227.9, 232.8, 237.4, 240.8, 242.8, 243, 241.5, 238.6, 234.2,
303 228.5, 221, 210.7, 195.1, 172.9, 147.8, 127.6, 115.6, 109.9, 107.1,
304 105.7, 105, 104.8, 104.8, 104.9, 105, 105.1, 105.3, 105.5, 105.8,
305 106.4, 107, 107.6, 108.1, 108.8, 110, 111.8, 114.2, 117.4, 121.6,
306 127.9, 137.3, 151.2, 169.5, 189, 205.8, 218.9, 229.1, 237.8, 245,
307 251.5, 257.1, 262.3, 268.2, 274, 280.4, 286.7, 292.4, 297.9, 302.9,
308 308.5, 312.2, 313.1, 313.3},
309 {187.4, 184.5, 173.3, 166.1, 165.4, 167.8, 169.6, 173.6, 179.6,
310 187.9, 198.9, 210, 220.5, 229.2, 235.7, 239.9, 241.8, 241.6, 239.6,
311 235.8, 229.4, 218.6, 200.9, 175.9, 149.4, 129.4, 118.3, 113.1,
312 110.8, 109.7, 109.3, 109.4, 109.7, 110, 110.2, 110.4, 110.5, 110.7,
313 111, 111.4, 111.8, 112.1, 112.3, 112.7, 113.2, 113.9, 115, 116.4,
314 117.9, 120.4, 124.1, 130.9, 142.2, 159.6, 179.6, 198.5, 212.9,
315 224.2, 232.7, 239.1, 243.8, 247.7, 252.4, 257.3, 263.2, 269.5,
316 275.4, 281.1, 286.3, 292, 296.3, 298.2, 298.8},
317 {166, 166.4, 155.7, 148.3, 147.1, 149, 152.1, 157, 163.6, 172.4,
318 185.3, 199.2, 212.6, 224, 233.2, 239.6, 243.3, 244.6, 243.6, 240.3,
319 233.9, 222.6, 203.7, 177, 149.5, 129.7, 119, 114, 111.7, 110.7,
320 110.3, 110.3, 110.6, 110.9, 111.1, 111.3, 111.5, 111.6, 111.9,
321 112.2, 112.5, 112.6, 112.8, 113, 113.4, 114, 115.1, 116.5, 118.3,
322 120.9, 124.4, 130.2, 139.4, 154.6, 173.8, 193.1, 208.1, 220.4,
323 230.1, 238.2, 244.7, 249.5, 254.5, 259.3, 264.5, 269.4, 273.7,
324 278.2, 282.6, 287.4, 290.9, 292.5, 293},
325 {171.9, 172.8, 166.2, 162.3, 161.4, 162.5, 165.2, 169.6, 175.3,
326 183.1, 193.8, 205.9, 218.3, 229.6, 238.5, 244.3, 246.9, 246.7,
327 243.8, 238.4, 230.2, 217.9, 199.6, 174.9, 148.9, 129.8, 119.5,
328 114.8, 112.3, 110.9, 110.3, 110.1, 110.2, 110.3, 110.4, 110.5,
329 110.6, 110.8, 111, 111.4, 111.8, 112, 112.2, 112.4, 112.9, 113.6,
330 114.7, 116.3, 118.4, 121.9, 127.1, 136.1, 149.8, 168.4, 186.9,
331 203.3, 217, 229.1, 238.7, 247, 254, 259.3, 264.3, 268.3, 272.5,
332 276.6, 280.4, 284.4, 288.4, 293.3, 297.2, 298.7, 299.1},
333 {191.6, 192.2, 189, 188.1, 190.2, 193.7, 197.8, 202.9, 208.5,
334 215.6, 224.2, 233.1, 241.2, 247.3, 250.8, 251.3, 248.9, 244.2,
335 237.3, 228.4, 217.2, 202.9, 184.5, 162.5, 140.7, 124.8, 116.2,
336 111.8, 109.4, 107.9, 107, 106.7, 106.6, 106.6, 106.7, 106.7,
337 106.8, 107, 107.4, 108, 108.7, 109.3, 109.8, 110.4, 111.2,
338 112.4, 114.2, 116.9, 121.1, 127.9, 139.3, 155.2, 173.6, 190.7,
339 206.1, 220.1, 232.3, 243, 251.8, 259.2, 265.7, 270.6, 275.3,
340 279.3, 283.3, 286.9, 289.7, 292.8, 296.1, 300.5, 303.9, 304.8,
342 {241.5, 239.6, 236.8, 237.4, 239.4, 242.3, 244.2, 246.4, 249.2,
343 253.6, 258.6, 262.7, 264.8, 264.2, 260.6, 254.1, 245.5, 235.3,
344 223.9, 211.7, 198.3, 183.1, 165.6, 147.1, 130.5, 118.7, 111.9,
345 108.1, 105.8, 104.3, 103.4, 102.8, 102.5, 102.4, 102.5, 102.5,
346 102.5, 102.7, 103.1, 103.8, 104.6, 105.4, 106.1, 107, 108.2,
347 109.9, 112.8, 117.5, 126, 140.4, 161, 181.9, 201.2, 216.8, 230.4,
348 241.8, 251.4, 259.9, 266.9, 272.8, 277.4, 280.4, 282.9, 284.6,
349 286.1, 287.4, 288.3, 289.5, 290.9, 294.2, 296.9, 297.5, 297.6},
350 {301.2, 300.3, 296.6, 295.4, 295, 294.3, 291.2, 287.4, 284.9, 284.7,
351 284.1, 281.5, 277.1, 270.4, 261.7, 250.6, 237.6, 223.1, 207.9, 192,
352 175.8, 158.8, 142.1, 127.6, 116.8, 109.9, 106, 103.6, 102.1, 101.1,
353 100.4, 99.96, 99.6, 99.37, 99.32, 99.32, 99.31, 99.46, 99.77, 100.2,
354 100.7, 101.3, 101.8, 102.7, 104.1, 106.8, 111.9, 121, 136.7, 160,
355 186.9, 209.9, 228.1, 241.2, 251.5, 259.5, 265.7, 270.9, 274.8, 278,
356 280.3, 281.8, 283, 283.3, 283.7, 283.8, 283, 282.2, 281.2, 281.4,
359 memcpy(clim->
tropo, tropo,
sizeof(clim->
tropo));
362 double tropomin = 1e99, tropomax = -1e99;
364 for (
int iy = 0; iy < clim->
tropo_nlat; iy++) {
365 tropomin =
MIN(tropomin, clim->
tropo[it][iy]);
366 tropomax =
MAX(tropomax, clim->
tropo[it][iy]);
371 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
375 LOG(2,
"Latitudes: %g, %g ... %g deg",
378 LOG(2,
"Tropopause altitude range: %g ... %g hPa",
Z(tropomax),
380 LOG(2,
"Tropopause pressure range: %g ... %g hPa", tropomin, tropomax);
390 if (t <= ts->time[0])
397 ts->
time[idx + 1], ts->
vmr[idx + 1], t);
410 double sec =
FMOD(t, 365.25 * 86400.);
412 sec += 365.25 * 86400.;
416 if (p < zm->p[zm->
np - 1])
417 p_help = zm->
p[zm->
np - 1];
418 else if (p > zm->
p[0])
422 double lat_help = lat;
423 if (lat < zm->lat[0])
424 lat_help = zm->
lat[0];
425 else if (lat > zm->
lat[zm->
nlat - 1])
426 lat_help = zm->
lat[zm->
nlat - 1];
434 const double aux00 =
LIN(zm->
p[ip], zm->
vmr[isec][ip][ilat],
435 zm->
p[ip + 1], zm->
vmr[isec][ip + 1][ilat],
437 const double aux01 =
LIN(zm->
p[ip], zm->
vmr[isec][ip][ilat + 1],
438 zm->
p[ip + 1], zm->
vmr[isec][ip + 1][ilat + 1],
440 const double aux10 =
LIN(zm->
p[ip], zm->
vmr[isec + 1][ip][ilat],
441 zm->
p[ip + 1], zm->
vmr[isec + 1][ip + 1][ilat],
443 const double aux11 =
LIN(zm->
p[ip], zm->
vmr[isec + 1][ip][ilat + 1],
444 zm->
p[ip + 1], zm->
vmr[isec + 1][ip + 1][ilat + 1],
447 LIN(zm->
lat[ilat], aux00, zm->
lat[ilat + 1], aux01, lat_help);
449 LIN(zm->
lat[ilat], aux10, zm->
lat[ilat + 1], aux11, lat_help);
450 const double aux =
LIN(zm->
time[isec], aux0, zm->
time[isec + 1], aux1, sec);
451 return MAX(aux, 0.0);
465 const int decompress,
470 const size_t nxy = nx * ny;
471 double lon[
EX], lat[
EY];
472 for (
size_t ix = 0; ix < nx; ix++)
473 lon[ix] = 360. * (
double) ix / ((double) nx - 1.);
474 for (
size_t iy = 0; iy < ny; iy++)
475 lat[iy] = 90. - 180. * (
double) iy / ((double) ny - 1.);
478 const char domain[] =
"[0.0, 360.0]x[-90.0, 90.0]";
482 cms_param_t *cms_param
483 = cms_set_parameters(nx, ny, max_level_grid, Nd0_x, Nd0_y, domain);
486 double cr = 0, t_coars = 0, t_eval = 0;
493 for (
size_t ip = 0; ip < np; ip++) {
496 cms_module_t *cms_ptr = cms_init(cms_param);
501 cms_sol = cms_read_zstd_sol(cms_ptr, inout);
503 cms_sol = cms_read_sol(cms_ptr, inout);
506 const double t0 = omp_get_wtime();
507#pragma omp parallel for collapse(2) default(shared)
508 for (
size_t ix = 0; ix < nx; ix++)
509 for (
size_t iy = 0; iy < ny; iy++) {
511 const double x[] = { lon[ix], lat[iy] };
512 cms_eval(cms_ptr, cms_sol, x, &val);
513 array[
ARRAY_3D(ix, iy, ny, ip, np)] = (float) val;
515 t_eval += omp_get_wtime() - t0;
518 cr += 1.0 / cms_compression_rate(cms_ptr, cms_sol);
521 cms_delete_sol(cms_sol);
522 cms_delete_module(cms_ptr);
526 LOG(2,
"Read 3-D variable: %s"
527 " (CMS, RATIO=%g, BPV=%g, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
528 varname, (
double) np / cr, 32. * cr / (
double) np, t_eval,
536 cms_module_t *cms_ptr[
EP];
537 cms_sol_t *cms_sol[
EP];
538 double rho[
EP], mean_err[
EP], stddev_err[
EP], min_err[
EP], max_err[
EP];
539 double mean_org[
EP], range_org[
EP], nrmse[
EP];
540 double ratio[
EP], bpv[
EP];
544 ? (size_t) omp_get_max_threads()
546 for (
size_t ip0 = 0; ip0 < np; ip0 += dip) {
549 double t0 = omp_get_wtime();
552#pragma omp parallel for default(shared)
553 for (
size_t ip = ip0; ip <
MIN(ip0 + dip, np); ip++) {
557 ALLOC(tmp_arr,
float,
561 for (
size_t ix = 0; ix < nx; ++ix)
562 for (
size_t iy = 0; iy < ny; ++iy)
564 array[
ARRAY_3D(ix, iy, ny, ip, np)];
568 if (strcasecmp(varname,
"Z") == 0)
570 else if (strcasecmp(varname,
"T") == 0)
572 else if (strcasecmp(varname,
"U") == 0)
574 else if (strcasecmp(varname,
"V") == 0)
576 else if (strcasecmp(varname,
"W") == 0)
578 else if (strcasecmp(varname,
"PV") == 0)
580 else if (strcasecmp(varname,
"H2O") == 0)
582 else if (strcasecmp(varname,
"O3") == 0)
584 else if (strcasecmp(varname,
"LWC") == 0)
586 else if (strcasecmp(varname,
"RWC") == 0)
588 else if (strcasecmp(varname,
"IWC") == 0)
590 else if (strcasecmp(varname,
"SWC") == 0)
592 else if (strcasecmp(varname,
"CC") == 0)
595 ERRMSG(
"Variable name unknown!");
598 cms_ptr[ip] = cms_init(cms_param);
602 cms_read_arr_new(cms_ptr[ip], tmp_arr, lon, lat,
610 t_coars += (omp_get_wtime() - t0);
613 for (
size_t ip = ip0; ip <
MIN(ip0 + dip, np); ip++) {
616 float *tmp_cms, *tmp_org;
617 ALLOC(tmp_cms,
float,
619 ALLOC(tmp_org,
float,
623 t0 = omp_get_wtime();
626#pragma omp parallel for collapse(2) default(shared)
627 for (
size_t ix = 0; ix < nx; ix++)
628 for (
size_t iy = 0; iy < ny; iy++) {
629 const size_t idx =
ARRAY_2D(ix, iy, ny);
630 const double x[] = { lon[ix], lat[iy] };
632 cms_eval(cms_ptr[ip], cms_sol[ip], x, &val);
633 tmp_cms[idx] = (float) val;
634 tmp_org[idx] = array[
ARRAY_3D(ix, iy, ny, ip, np)];
638 t_eval += (omp_get_wtime() - t0);
642 ratio[ip] = cms_compression_rate(cms_ptr[ip], cms_sol[ip]);
643 bpv[ip] = 32. / ratio[ip];
645 &stddev_err[ip], &min_err[ip], &max_err[ip],
646 &nrmse[ip], &mean_org[ip], &range_org[ip]);
647 rho[ip] = gsl_stats_float_correlation(tmp_org, 1, tmp_cms, 1, nxy);
651 cr += 1.0 / cms_compression_rate(cms_ptr[ip], cms_sol[ip]);
655 cms_save_zstd_sol(cms_sol[ip], inout, 3);
657 cms_save_sol(cms_sol[ip], inout);
660 cms_delete_sol(cms_sol[ip]);
661 cms_delete_module(cms_ptr[ip]);
669 const size_t nbytes = nx * ny * np *
sizeof(float);
670 for (
size_t ip = 0; ip < np; ip++)
672 "%s %s %lu %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g\n",
673 "CMS", varname, (
unsigned long) ip, plev[ip], ratio[ip],
674 bpv[ip], rho[ip], mean_err[ip], stddev_err[ip], min_err[ip],
675 max_err[ip], mean_org[ip], range_org[ip], nrmse[ip], t_coars,
681 LOG(2,
"Write 3-D variable: %s"
682 " (CMS, RATIO=%g, BPV=%g, T_COMP=%g s, V_COMP=%g MiB/s,"
683 " T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
684 varname, (
double) np / cr, 32. * cr / (
double) np, t_coars,
690 cms_delete_param(cms_param);
701 return (dt > 0 ? ((
double) nbytes) / (dt * 1024. * 1024.) : NAN);
718 double avg = 0, m2 = 0, err_min = 0, err_max = 0, rmse = 0;
719 double org_min = 0, org_max = 0;
722 for (
size_t i = 0; i < n; i++) {
723 const double err = (double) cmp[i] - (
double) org[i];
724 const double val = (double) org[i];
725 const double delta = err - avg;
727 avg += delta / ((double) i + 1.);
728 m2 += delta * (err - avg);
731 if (i == 0 || err < err_min)
733 if (i == 0 || err > err_max)
735 if (i == 0 || val < org_min)
737 if (i == 0 || val > org_max)
742 *
stddev = (n > 1 ? sqrt(m2 / ((
double) n - 1.)) : 0);
746 for (
size_t i = 0; i < n; i++)
747 *org_mean += (
double) org[i];
748 *org_mean /= (double) n;
749 *range = org_max - org_min;
750 *nrmse = ((org_max - org_min) > 0
751 ? sqrt(rmse / (
double) n) / (org_max - org_min)
762 "# $1 = compression codec name [-]\n"
763 "# $2 = variable name [-]\n"
764 "# $3 = level index [-]\n"
765 "# $4 = pressure level [hPa]\n"
766 "# $5 = compression ratio [-]\n"
767 "# $6 = bits per value [bit/value]\n"
768 "# $7 = correlation coefficient [-]\n"
769 "# $8 = mean compression error [-]\n"
770 "# $9 = standard deviation of compression error [-]\n"
771 "# $10 = minimum compression error [-]\n"
772 "# $11 = maximum compression error [-]\n"
773 "# $12 = mean value of original field [-]\n"
774 "# $13 = value range of original field [-]\n"
775 "# $14 = normalized root mean square error [-]\n"
776 "# $15 = compression time [s]\n"
777 "# $16 = compression speed [MiB/s]\n"
778 "# $17 = decompression time [s]\n"
779 "# $18 = decompression speed [MiB/s]\n\n");
794 const double t_decomp,
799 static FILE *last_out = NULL;
800 static char last_var[
LEN] =
"";
801 double mean_err, stddev_err, min_err, max_err;
802 double nrmse, mean_org, range_org, rho_out = rho;
806 &max_err, &nrmse, &mean_org, &range_org);
808 rho_out = gsl_stats_float_correlation(org, 1, cmp, 1, n);
811 if (out != last_out) {
815 if (last_var[0] !=
'\0' && strcmp(last_var, varname) != 0)
817 snprintf(last_var,
LEN,
"%s", varname);
819 "%s %s %lu %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g\n",
820 codec, varname, (
unsigned long) lev, plev, ratio, bpv, rho_out,
821 mean_err, stddev_err, min_err, max_err, mean_org, range_org, nrmse,
830static const uint64_t pck_zstd_magic = UINT64_C(0x50434b5a53544431);
832static size_t compress_zstd_buffer(
834 const size_t src_len,
840 const size_t dst_cap = ZSTD_compressBound(src_len);
841 void *dst = calloc(dst_cap, 1);
845 ERRMSG(
"Memory allocation failed!");
847 cctx = ZSTD_createCCtx();
850 ERRMSG(
"Cannot create ZSTD context!");
853 if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel,
857 ERRMSG(
"Cannot set ZSTD compression level!");
860 if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, nworkers))) {
863 ERRMSG(
"Cannot set ZSTD worker count!");
866 const double t0 = omp_get_wtime();
867 const size_t dst_len = ZSTD_compress2(cctx, dst, dst_cap, src, src_len);
868 *t_comp = omp_get_wtime() - t0;
872 if (ZSTD_isError(dst_len)) {
874 ERRMSG(
"PCK ZSTD compression failed!");
881static void decompress_zstd_buffer(
883 const size_t src_len,
885 const size_t dst_len,
888 const double t0 = omp_get_wtime();
889 const size_t out_len = ZSTD_decompress(dst, dst_len, src, src_len);
890 *t_decomp = omp_get_wtime() - t0;
892 if (ZSTD_isError(out_len) || out_len != dst_len)
893 ERRMSG(
"PCK ZSTD decompression failed or size mismatch!");
906 for (
size_t iz = 0; iz < nz; iz++) {
911 for (
size_t ixy = 1; ixy < nxy; ixy++)
912 for (
size_t iz = 0; iz < nz; iz++) {
913 const double value = array[ixy * nz + iz];
920 for (
size_t iz = 0; iz < nz; iz++) {
921 const double range = scl[iz] - off[iz];
922 const double ref = fmax(1.0, fmax(fabs(off[iz]), fabs(scl[iz])));
923 scl[iz] = !(range > 1e-12 * ref) ? 0.0 : range;
926#pragma omp parallel for default(shared)
927 for (
size_t ixy = 0; ixy < nxy; ixy++)
928 for (
size_t iz = 0; iz < nz; iz++)
930 array[ixy * nz + iz] =
931 (float) ((array[ixy * nz + iz] - off[iz]) / scl[iz]);
933 array[ixy * nz + iz] = 0.0f;
945#pragma omp parallel for default(shared)
946 for (
size_t ixy = 0; ixy < nxy; ixy++)
947 for (
size_t iz = 0; iz < nz; iz++)
949 array[ixy * nz + iz] =
950 (float) (array[ixy * nz + iz] * scl[iz] + off[iz]);
952 array[ixy * nz + iz] = (float) off[iz];
958 const char *varname) {
960 if (strcasecmp(varname,
"Z") == 0)
962 if (strcasecmp(varname,
"T") == 0)
964 if (strcasecmp(varname,
"U") == 0)
966 if (strcasecmp(varname,
"V") == 0)
968 if (strcasecmp(varname,
"W") == 0)
970 if (strcasecmp(varname,
"PV") == 0)
972 if (strcasecmp(varname,
"H2O") == 0)
974 if (strcasecmp(varname,
"O3") == 0)
976 if (strcasecmp(varname,
"LWC") == 0)
978 if (strcasecmp(varname,
"RWC") == 0)
980 if (strcasecmp(varname,
"IWC") == 0)
982 if (strcasecmp(varname,
"SWC") == 0)
984 if (strcasecmp(varname,
"CC") == 0)
987 ERRMSG(
"Unknown meteorological variable name!");
999 const int decompress,
1001 const int zstd_level,
1002 const int zstd_nworkers,
1008 (void) zstd_nworkers;
1011 double vmin[
EP], vmax[
EP], off[
EP], scl[
EP];
1012 unsigned short *sarray;
1013 const size_t payload_len = 2 * nz *
sizeof(double)
1014 + nxy * nz *
sizeof(
unsigned short);
1015 size_t stored_len = payload_len;
1018 ALLOC(sarray,
unsigned short,
1023 double t_zstd = 0.0;
1029 unsigned char *compr = NULL, *payload = NULL;
1031 FREAD(&magic, uint64_t, 1, inout);
1032 if (magic != pck_zstd_magic)
1033 ERRMSG(
"PCK+ZSTD magic mismatch! Check MET_PCK_ZSTD and file type.");
1034 FREAD(&stored_len,
size_t,
1037 ALLOC(compr,
unsigned char,
1039 FREAD(compr,
unsigned char,
1042 ALLOC(payload,
unsigned char,
1044 decompress_zstd_buffer(compr, stored_len, payload, payload_len,
1046 memcpy(scl, payload, nz *
sizeof(
double));
1047 memcpy(off, payload + nz *
sizeof(
double), nz *
sizeof(
double));
1048 memcpy(sarray, payload + 2 * nz *
sizeof(
double),
1049 nxy * nz *
sizeof(
unsigned short));
1053 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
1062 FREAD(sarray,
unsigned short,
1068 const double t0 = omp_get_wtime();
1071#pragma omp parallel for default(shared)
1072 for (
size_t ixy = 0; ixy < nxy; ixy++)
1073 for (
size_t iz = 0; iz < nz; iz++)
1074 array[ixy * nz + iz]
1075 = (
float) (sarray[ixy * nz + iz] * scl[iz] + off[iz]);
1078 const double t_decomp = t_zstd + omp_get_wtime() - t0;
1079 const double ratio_out =
1080 (double) (nxy * nz *
sizeof(
float)) / (
double) stored_len;
1081 const double bpv_out = (8. * (double) stored_len) / (double) (nxy * nz);
1082 LOG(2,
"Read 3-D variable: %s"
1083 " (PCK%s, RATIO=%g, BPV=%g, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1084 varname, pck_zstd ?
"+ZSTD" :
"", ratio_out, bpv_out, t_decomp,
1090 float *tmp_org, *tmp_pck;
1091 double t_comp_sum = 0, t_decomp_sum = 0, t_zstd = 0, t_zstd_decomp = 0;
1093 double org_mean[
EP], range[
EP];
1096 ALLOC(tmp_org,
float,
1098 ALLOC(tmp_pck,
float,
1102 for (
size_t iz = 0; iz < nz; iz++) {
1103 vmin[iz] = array[iz];
1104 vmax[iz] = array[iz];
1106 for (
size_t ixy = 1; ixy < nxy; ixy++)
1107 for (
size_t iz = 0; iz < nz; iz++) {
1108 if (array[ixy * nz + iz] < vmin[iz])
1109 vmin[iz] = array[ixy * nz + iz];
1110 if (array[ixy * nz + iz] > vmax[iz])
1111 vmax[iz] = array[ixy * nz + iz];
1115 for (
size_t iz = 0; iz < nz; iz++) {
1116 scl[iz] = (vmax[iz] - vmin[iz]) / 65533.;
1121 for (
size_t iz = 0; iz < nz; iz++) {
1122 const double t0 = omp_get_wtime();
1124#pragma omp parallel for default(shared)
1125 for (
size_t ixy = 0; ixy < nxy; ixy++)
1127 sarray[ixy * nz + iz] =
1128 (
unsigned short) ((array[ixy * nz + iz] - off[iz]) / scl[iz] +
1131 sarray[ixy * nz + iz] = 0;
1133 const double t_comp = omp_get_wtime() - t0;
1134 t_comp_sum += t_comp;
1136 const double t1 = omp_get_wtime();
1138#pragma omp parallel for default(shared)
1139 for (
size_t ixy = 0; ixy < nxy; ixy++) {
1140 tmp_org[ixy] = array[ixy * nz + iz];
1141 tmp_pck[ixy] = (float) (sarray[ixy * nz + iz] * scl[iz] + off[iz]);
1144 const double t_decomp = omp_get_wtime() - t1;
1145 t_decomp_sum += t_decomp;
1149 &min[iz], &max[iz], &nrmse[iz], &org_mean[iz],
1151 rho[iz] = gsl_stats_float_correlation(tmp_org, 1, tmp_pck, 1, nxy);
1156 void *stored_data = NULL;
1160 unsigned char *payload = NULL, *payload_chk = NULL;
1161 ALLOC(payload,
unsigned char,
1163 memcpy(payload, scl, nz *
sizeof(
double));
1164 memcpy(payload + nz *
sizeof(
double), off, nz *
sizeof(
double));
1165 memcpy(payload + 2 * nz *
sizeof(
double), sarray,
1166 nxy * nz *
sizeof(
unsigned short));
1167 stored_len = compress_zstd_buffer(payload, payload_len, zstd_level,
1168 zstd_nworkers, &stored_data, &t_zstd);
1169 ALLOC(payload_chk,
unsigned char,
1171 decompress_zstd_buffer(stored_data, stored_len, payload_chk,
1172 payload_len, &t_zstd_decomp);
1175 FWRITE(&pck_zstd_magic, uint64_t, 1, inout);
1176 FWRITE(&stored_len,
size_t,
1179 FWRITE(stored_data,
unsigned char,
1183 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
1192 FWRITE(sarray,
unsigned short,
1198 const double ratio_out =
1199 (double) (nxy * nz *
sizeof(
float)) / (
double) stored_len;
1200 const double bpv_out = (8. * (double) stored_len) / (double) (nxy * nz);
1201 const double t_comp = t_comp_sum + t_zstd;
1202 const double t_decomp = t_decomp_sum + t_zstd_decomp;
1203 LOG(2,
"Write 3-D variable: %s"
1204 " (PCK%s, RATIO=%g, BPV=%g, T_COMP=%g s, V_COMP=%g MiB/s,"
1205 " T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1206 varname, pck_zstd ?
"+ZSTD" :
"", ratio_out, bpv_out, t_comp,
1212 const double ratio_level = ratio_out;
1213 const double bpv_level = bpv_out;
1214 const double t_comp_level = t_comp / (double) nz;
1215 const double t_decomp_level = t_decomp / (double) nz;
1216 for (
size_t iz = 0; iz < nz; iz++)
1218 "%s %s %lu %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g\n",
1219 pck_zstd ?
"PCKZSTD" :
"PCK", varname, (
unsigned long) iz,
1220 plev[iz], ratio_level, bpv_level,
1221 rho[iz], mean[iz],
stddev[iz], min[iz], max[iz], org_mean[iz],
1222 range[iz], nrmse[iz],
1243 const char *varname,
1255 if ((precision > 0) == (tolerance > 0.0))
1256 ERRMSG(
"Exactly one of precision or tolerance must be set for SZ3!");
1258 size_t r1 = (size_t) nx, r2 = (
size_t) ny, r3 = (size_t) nz,
1259 outSize = 0, total_elems = r1 * r2 * r3;
1261 unsigned char *bytes = NULL;
1262 double *scale_off = NULL, *scale_scl = NULL;
1263 float *orig_all = NULL;
1265 if (lossy_scale < 0 || lossy_scale > 1)
1266 ERRMSG(
"Set MET_LOSSY_SCALE to 0 or 1!");
1272 int stored_lossy_scale;
1273 FREAD(&stored_lossy_scale,
int,
1276 if (stored_lossy_scale < 0 || stored_lossy_scale > 1)
1277 ERRMSG(
"Invalid stored MET_LOSSY_SCALE flag!");
1278 if (stored_lossy_scale > 0) {
1279 ALLOC(scale_off,
double,
1281 ALLOC(scale_scl,
double,
1283 FREAD(scale_off,
double,
1286 FREAD(scale_scl,
double,
1292 FREAD(&sz3size,
size_t,
1297 FREAD(bytes,
unsigned char,
1301 const double t0 = omp_get_wtime();
1302 void *outData = SZ_decompress(SZ_FLOAT, bytes, sz3size, 0, 0, r3, r2, r1);
1304 ERRMSG(
"Decompression failed!");
1306 memcpy(array, outData, total_elems *
sizeof(
float));
1307 if (stored_lossy_scale > 0)
1309 const double t_decomp = omp_get_wtime() - t0;
1314 LOG(2,
"Read 3-D variable: %s"
1315 " (SZ3, PREC=%d, TOL=%g, SCALE=%d, RATIO=%g, BPV=%g, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1316 varname, precision, tolerance, stored_lossy_scale,
1317 (
double) (total_elems *
sizeof(
float)) / (
double) sz3size,
1318 (8. * (
double) sz3size) / (
double) total_elems, t_decomp,
1324 const int errBoundMode = (precision > 0) ? REL : ABS;
1325 FWRITE(&lossy_scale,
int,
1328 if (lossy_scale > 0) {
1329 ALLOC(scale_off,
double,
1331 ALLOC(scale_scl,
double,
1334 ALLOC(orig_all,
float,
1336 memcpy(orig_all, array, total_elems *
sizeof(
float));
1339 FWRITE(scale_off,
double,
1342 FWRITE(scale_scl,
double,
1346 const double absBound = (errBoundMode == ABS) ? tolerance : 0.0;
1347 const double relBound =
1348 (errBoundMode == REL) ? pow(2.0, -(
double) precision) : 0.0;
1350 const double t0 = omp_get_wtime();
1351 bytes = SZ_compress_args(SZ_FLOAT, array, &outSize,
1352 errBoundMode, absBound, relBound, 0.0,
1354 const double t_comp = omp_get_wtime() - t0;
1355 if (!bytes || outSize == 0)
1356 ERRMSG(
"Compression failed!");
1361 FWRITE(bytes,
unsigned char,
1365 double t_decomp = NAN;
1367 unsigned char *bytes_copy;
1370 ALLOC(bytes_copy,
unsigned char,
1372 memcpy(bytes_copy, bytes, outSize);
1374 const double t1 = omp_get_wtime();
1375 void *decData = SZ_decompress(SZ_FLOAT, bytes_copy, outSize, 0, 0, r3,
1377 t_decomp = omp_get_wtime() - t1;
1379 ERRMSG(
"Decompression failed!");
1381 float *tmp_all, *tmp_org, *tmp_sz3;
1382 const size_t nxy = r2 * r3;
1384 ALLOC(tmp_all,
float,
1386 ALLOC(tmp_org,
float,
1388 ALLOC(tmp_sz3,
float,
1390 memcpy(tmp_all, decData, total_elems *
sizeof(
float));
1391 if (lossy_scale > 0)
1395 for (
size_t lev = 0; lev < r1; lev++) {
1398#pragma omp parallel for default(shared)
1399 for (
size_t ixy = 0; ixy < nxy; ixy++) {
1400 tmp_org[ixy] = (orig_all ? orig_all : array)[ixy * r1 + lev];
1401 tmp_sz3[ixy] = tmp_all[ixy * r1 + lev];
1404 (
double) (total_elems *
sizeof(
float))
1406 (8. * (
double) outSize) / (
double) total_elems,
1407 NAN, t_comp, t_decomp, nxy,
1408 total_elems *
sizeof(
float), tmp_org, tmp_sz3);
1417 LOG(2,
"Write 3-D variable: %s"
1418 " (SZ3, PREC=%d, TOL=%g, SCALE=%d, RATIO=%g, BPV=%g, T_COMP=%g s, V_COMP=%g MiB/s,"
1419 " T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1420 varname, precision, tolerance, lossy_scale,
1421 (
double) (total_elems *
sizeof(
float)) / (
double) outSize,
1422 (8. * (
double) outSize) / (
double) total_elems, t_comp,
1426 LOG(2,
"Write 3-D variable: %s"
1427 " (SZ3, PREC=%d, TOL=%g, SCALE=%d, RATIO=%g, BPV=%g, T_COMP=%g s, V_COMP=%g MiB/s)",
1428 varname, precision, tolerance, lossy_scale,
1429 (
double) (total_elems *
sizeof(
float)) / (
double) outSize,
1430 (8. * (
double) outSize) / (
double) total_elems, t_comp,
1445 const char *varname,
1451 const int precision,
1452 const double tolerance,
1453 const int lossy_scale,
1454 const int decompress,
1458 if (lossy_scale < 0 || lossy_scale > 1)
1459 ERRMSG(
"Set MET_LOSSY_SCALE to 0 or 1!");
1462 const size_t snx = (size_t) nx;
1463 const size_t sny = (size_t) ny;
1464 const size_t snz = (size_t) nz;
1465 const zfp_type type = zfp_type_float;
1466 zfp_field *field = zfp_field_3d(array, type, snx, sny, snz);
1469 zfp_stream *zfp = zfp_stream_open(NULL);
1471 ERRMSG(
"Failed to allocate zfp structures!");
1474 int actual_prec = 0;
1475 double actual_tol = 0;
1476 if ((precision > 0 && tolerance > 0) || (precision <= 0 && tolerance <= 0)) {
1477 ERRMSG(
"Exactly one of precision or tolerance must be set for zfp!");
1478 }
else if (precision > 0)
1480 (int) zfp_stream_set_precision(zfp, (
unsigned int) precision);
1481 else if (tolerance > 0)
1482 actual_tol = zfp_stream_set_accuracy(zfp, tolerance);
1485 const size_t bufsize = zfp_stream_maximum_size(zfp, field);
1491 bitstream *stream = stream_open(buffer, bufsize);
1492 zfp_stream_set_bit_stream(zfp, stream);
1493 zfp_stream_rewind(zfp);
1497 double *scale_off = NULL, *scale_scl = NULL;
1499 int stored_lossy_scale;
1500 FREAD(&stored_lossy_scale,
int,
1503 if (stored_lossy_scale < 0 || stored_lossy_scale > 1)
1504 ERRMSG(
"Invalid stored MET_LOSSY_SCALE flag!");
1505 if (stored_lossy_scale > 0) {
1506 ALLOC(scale_off,
double,
1508 ALLOC(scale_scl,
double,
1510 FREAD(scale_off,
double,
1513 FREAD(scale_scl,
double,
1517 FREAD(&zfpsize,
size_t,
1520 if (zfpsize > bufsize)
1521 ERRMSG(
"Compressed data size exceeds allocated buffer!");
1522 FREAD(buffer,
unsigned char,
1525 const double t0 = omp_get_wtime();
1526 if (!zfp_decompress(zfp, field))
1527 ERRMSG(
"Decompression failed!");
1528 if (stored_lossy_scale > 0)
1530 const double t_decomp = omp_get_wtime() - t0;
1532 ((double) (snx * sny * snz *
sizeof(
float))) / (double) zfpsize;
1533 const double bpv = (8.0 * (double) zfpsize) / (double) (snx * sny * snz);
1535 "Read 3-D variable: %s"
1536 " (ZFP, PREC=%d, TOL=%g, SCALE=%d, RATIO=%g, BPV=%g, T_DECOMP=%g s,"
1537 " V_DECOMP=%g MiB/s)",
1538 varname, actual_prec, actual_tol, stored_lossy_scale, cr, bpv,
1545 float *tmp_all, *tmp_org, *tmp_zfp, *orig_all = NULL;
1546 const size_t nxy = sny * snz;
1548 FWRITE(&lossy_scale,
int,
1551 if (lossy_scale > 0) {
1552 ALLOC(scale_off,
double,
1554 ALLOC(scale_scl,
double,
1557 ALLOC(orig_all,
float,
1559 memcpy(orig_all, array, snx * sny * snz *
sizeof(
float));
1562 FWRITE(scale_off,
double,
1565 FWRITE(scale_scl,
double,
1570 ALLOC(tmp_all,
float,
1572 ALLOC(tmp_org,
float,
1574 ALLOC(tmp_zfp,
float,
1577 const double t0 = omp_get_wtime();
1578 zfpsize = zfp_compress(zfp, field);
1579 const double t_comp = omp_get_wtime() - t0;
1581 ERRMSG(
"Compression failed!");
1586 FWRITE(buffer,
unsigned char,
1591 zfp_field *dec_field = zfp_field_3d(tmp_all, type, snx, sny, snz);
1593 ERRMSG(
"Failed to allocate zfp structures!");
1595 const double t1 = omp_get_wtime();
1596 zfp_stream_rewind(zfp);
1597 if (!zfp_decompress(zfp, dec_field))
1598 ERRMSG(
"Decompression failed!");
1599 if (lossy_scale > 0)
1601 const double t_decomp = omp_get_wtime() - t1;
1603 for (
size_t lev = 0; lev < snx; lev++) {
1606#pragma omp parallel for default(shared)
1607 for (
size_t ixy = 0; ixy < nxy; ixy++) {
1608 tmp_org[ixy] = (orig_all ? orig_all : array)[ixy * snx + lev];
1609 tmp_zfp[ixy] = tmp_all[ixy * snx + lev];
1613 ((
double) (snx * sny * snz *
sizeof(
float)))
1614 / (
double) zfpsize, (8.0 * (
double) zfpsize)
1615 / (
double) (snx * sny * snz),
1616 NAN, t_comp, t_decomp, nxy,
1617 snx * sny * snz *
sizeof(
float), tmp_org, tmp_zfp);
1621 ((double) (snx * sny * snz *
sizeof(
float))) / (double) zfpsize;
1622 const double bpv = (8.0 * (double) zfpsize) / (double) (snx * sny * snz);
1624 "Write 3-D variable: %s"
1625 " (ZFP, PREC=%d, TOL=%g, SCALE=%d, RATIO=%g, BPV=%g, T_COMP=%g s,"
1626 " V_COMP=%g MiB/s, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1627 varname, actual_prec, actual_tol, lossy_scale, cr, bpv, t_comp,
1636 zfp_field_free(dec_field);
1643 zfp_field_free(field);
1644 stream_close(stream);
1645 zfp_stream_close(zfp);
1654 const char *varname,
1659 const int decompress,
1666 const size_t n = nxy * nz;
1667 const size_t uncomprLen = n *
sizeof(float);
1668 size_t compsize, comprLen = ZSTD_compressBound(uncomprLen);
1671 char *compr = calloc(comprLen, 1);
1673 ERRMSG(
"Memory allocation failed!");
1674 char *uncompr = (
char *) array;
1678 FREAD(&comprLen,
size_t,
1681 FREAD(compr,
unsigned char,
1684 const double t0 = omp_get_wtime();
1685 compsize = ZSTD_decompress(uncompr, uncomprLen, compr, comprLen);
1686 const double t_decomp = omp_get_wtime() - t0;
1687 if (ZSTD_isError(compsize) || compsize != uncomprLen)
1688 ERRMSG(
"Decompression failed or size mismatch!");
1689 LOG(2,
"Read 3-D variable: %s"
1690 " (ZSTD, LEVEL=%d, RATIO=%g, BPV=%g, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1691 varname, level, ((
double) uncomprLen) / (
double) comprLen,
1692 (8. * (
double) comprLen) / (
double) n, t_decomp,
1698 float *tmp_org, *tmp_zstd, *tmp_all;
1701 ALLOC(tmp_org,
float,
1703 ALLOC(tmp_zstd,
float,
1705 ALLOC(tmp_all,
float,
1708 cctx = ZSTD_createCCtx();
1710 ERRMSG(
"Cannot create ZSTD context!");
1712 if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel,
1714 ERRMSG(
"Cannot set ZSTD compression level!");
1716 if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers,
1718 ERRMSG(
"Cannot set ZSTD worker count!");
1720 const double t0 = omp_get_wtime();
1721 compsize = ZSTD_compress2(cctx, compr, comprLen, uncompr, uncomprLen);
1722 const double t_comp = omp_get_wtime() - t0;
1723 if (ZSTD_isError(compsize)) {
1724 ZSTD_freeCCtx(cctx);
1725 ERRMSG(
"Compression failed!");
1727 FWRITE(&compsize,
size_t,
1730 FWRITE(compr,
unsigned char,
1735 const double t1 = omp_get_wtime();
1736 const size_t decomp_size = ZSTD_decompress(tmp_all, uncomprLen, compr,
1738 const double t_decomp = omp_get_wtime() - t1;
1739 if (ZSTD_isError(decomp_size) || decomp_size != uncomprLen)
1740 ERRMSG(
"Decompression failed or size mismatch!");
1742 for (
size_t lev = 0; lev < nz; lev++) {
1745#pragma omp parallel for default(shared)
1746 for (
size_t ixy = 0; ixy < nxy; ixy++) {
1747 tmp_org[ixy] = array[ixy * nz + lev];
1748 tmp_zstd[ixy] = tmp_all[ixy * nz + lev];
1752 ((
double) uncomprLen) / (
double) compsize,
1753 (8. * (
double) compsize) / (
double) n,
1754 NAN, t_comp, t_decomp, nxy, uncomprLen, tmp_org,
1758 LOG(2,
"Write 3-D variable: %s"
1759 " (ZSTD, LEVEL=%d, NWORKERS=%d, RATIO=%g, BPV=%g, T_COMP=%g s,"
1761 " T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1762 varname, level, nworkers, ((
double) uncomprLen) / (
double) compsize,
1763 (8. * (
double) compsize) / (
double) n, t_comp,
1767 ZSTD_freeCCtx(cctx);
1782 const char *varname,
1787 const int decompress,
1788 const int acceleration,
1793 const size_t n = nxy * nz;
1794 const size_t uncomprLen = n *
sizeof(float);
1795 if (uncomprLen > (
size_t) INT_MAX)
1796 ERRMSG(
"LZ4 input buffer exceeds INT_MAX!");
1797 const int uncomprLenInt = (int) uncomprLen;
1798 const int accel = acceleration > 0 ? acceleration : 1;
1799 const int comprCapInt = LZ4_compressBound(uncomprLenInt);
1800 if (comprCapInt <= 0)
1801 ERRMSG(
"Cannot determine LZ4 compression bound!");
1802 size_t comprLen = (size_t) comprCapInt;
1805 char *compr = calloc(comprLen, 1);
1807 ERRMSG(
"Memory allocation failed!");
1808 char *uncompr = (
char *) array;
1812 FREAD(&comprLen,
size_t,
1815 if (comprLen > (
size_t) INT_MAX)
1816 ERRMSG(
"LZ4 compressed buffer exceeds INT_MAX!");
1817 FREAD(compr,
unsigned char,
1820 const double t0 = omp_get_wtime();
1821 const int decomp_size =
1822 LZ4_decompress_safe(compr, uncompr, (
int) comprLen, uncomprLenInt);
1823 const double t_decomp = omp_get_wtime() - t0;
1824 if (decomp_size != uncomprLenInt)
1825 ERRMSG(
"Decompression failed or size mismatch!");
1826 LOG(2,
"Read 3-D variable: %s"
1827 " (LZ4, ACCEL=%d, RATIO=%g, BPV=%g, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1828 varname, accel, ((
double) uncomprLen) / (
double) comprLen,
1829 (8. * (
double) comprLen) / (
double) n, t_decomp,
1835 float *tmp_org, *tmp_lz4, *tmp_all;
1837 ALLOC(tmp_org,
float,
1839 ALLOC(tmp_lz4,
float,
1841 ALLOC(tmp_all,
float,
1844 const double t0 = omp_get_wtime();
1845 const int compsizeInt =
1846 LZ4_compress_fast(uncompr, compr, uncomprLenInt, comprCapInt, accel);
1847 const double t_comp = omp_get_wtime() - t0;
1848 if (compsizeInt <= 0)
1849 ERRMSG(
"Compression failed!");
1850 const size_t compsize = (size_t) compsizeInt;
1851 FWRITE(&compsize,
size_t,
1854 FWRITE(compr,
unsigned char,
1858 const double t1 = omp_get_wtime();
1859 const int decomp_size =
1860 LZ4_decompress_safe(compr, (
char *) tmp_all, compsizeInt,
1862 const double t_decomp = omp_get_wtime() - t1;
1863 if (decomp_size != uncomprLenInt)
1864 ERRMSG(
"Decompression failed or size mismatch!");
1866 for (
size_t lev = 0; lev < nz; lev++) {
1869#pragma omp parallel for default(shared)
1870 for (
size_t ixy = 0; ixy < nxy; ixy++) {
1871 tmp_org[ixy] = array[ixy * nz + lev];
1872 tmp_lz4[ixy] = tmp_all[ixy * nz + lev];
1876 ((
double) uncomprLen) / (
double) compsize,
1877 (8. * (
double) compsize) / (
double) n,
1878 NAN, t_comp, t_decomp, nxy, uncomprLen, tmp_org,
1882 LOG(2,
"Write 3-D variable: %s"
1883 " (LZ4, ACCEL=%d, RATIO=%g, BPV=%g, T_COMP=%g s, V_COMP=%g MiB/s,"
1884 " T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1885 varname, accel, ((
double) uncomprLen) / (
double) compsize,
1886 (8. * (
double) compsize) / (
double) n, t_comp,
1908 const double D = sec / 86400 - 0.5;
1911 const double g =
DEG2RAD(357.529 + 0.98560028 * D);
1912 const double q = 280.459 + 0.98564736 * D;
1913 const double L =
DEG2RAD(q + 1.915 * sin(g) + 0.020 * sin(2 * g));
1916 const double e =
DEG2RAD(23.439 - 0.00000036 * D);
1919 const double sindec = sin(e) * sin(L);
1922 const double ra = atan2(cos(e) * sin(L), cos(L));
1925 const double GMST = 18.697374558 + 24.06570982441908 * D;
1928 const double LST = GMST + lon / 15;
1931 const double h = LST / 12 * M_PI - ra;
1934 const double lat_help =
DEG2RAD(lat);
1937 return sin(lat_help) * sindec + cos(lat_help) * sqrt(1 -
1938 SQR(sindec)) * cos(h);
1950 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
1951 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
1954 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
1955 *doy = d0l[mon - 1] + day - 1;
1957 *doy = d0[mon - 1] + day - 1;
1974 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
1983 const int ix0 = zonal_rank * nx_block;
1984 const int iy0 = merid_rank * ny_block;
1986 const int ix1 = ix0 + nx_block
1990 const int iy1 = iy0 + ny_block
1996#pragma acc update device(dd->nx_glob, dd->ny_glob, \
1997 dd->lon_glob[:dd->nx_glob], \
1998 dd->lat_glob[:dd->ny_glob])
1999#pragma acc data present(atm, ctl, dd)
2000#pragma acc parallel loop independent gang vector
2002 for (
int ip = 0; ip < atm->
np; ip++) {
2009 double lon = atm->
lon[ip];
2010 double lat = atm->
lat[ip];
2016 const int inside = (ix >= ix0 && ix < ix1 && iy >= iy0 && iy < iy1);
2051 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
2055#pragma acc enter data create(npart, particles[:npart])
2056#pragma acc update device(npart, particles[:npart])
2057#pragma acc parallel loop present(atm, ctl, particles, cache, npart)
2059 for (
int ip = atm->
np; ip < atm->np + npart; ip++)
2064 particles[ip - atm->
np].
time = atm->
time[ip];
2065 particles[ip - atm->
np].
lon = atm->
lon[ip];
2066 particles[ip - atm->
np].
lat = atm->
lat[ip];
2067 particles[ip - atm->
np].
p = atm->
p[ip];
2068 for (
int iq = 0; iq < ctl->
nq; iq++)
2069 particles[ip - atm->
np].q[iq] = atm->
q[iq][ip];
2075#pragma acc update host( particles[:npart])
2076#pragma acc exit data delete(npart, particles)
2099 int zonal_rank = ix / nx_block;
2105 int merid_rank = iy / ny_block;
2128 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
2129 MPI_Comm_size(MPI_COMM_WORLD, &size);
2131 int *send_counts, *recv_counts;
2132 int *send_displs, *recv_displs;
2138 ALLOC(send_counts,
int,
2140 ALLOC(recv_counts,
int,
2142 ALLOC(send_displs,
int,
2144 ALLOC(recv_displs,
int,
2150 for (
int ip = 0; ip < *npart; ip++) {
2154 if (dest < 0 || dest >= size)
2155 ERRMSG(
"Invalid destination rank!");
2156 send_counts[dest]++;
2161 for (
int i = 0; i < size; i++) {
2162 send_displs[i] = nsend;
2163 nsend += send_counts[i];
2167 MPI_Alltoall(send_counts, 1, MPI_INT,
2168 recv_counts, 1, MPI_INT, MPI_COMM_WORLD);
2172 for (
int i = 0; i < size; i++) {
2173 recv_displs[i] = nrecv;
2174 nrecv += recv_counts[i];
2180 for (
int i = 0; i < size; i++)
2181 offsets[i] = send_displs[i];
2184 for (
int ip = 0; ip < *npart; ip++) {
2188 memcpy(&sendbuf[offsets[dest]], &(*particles)[ip],
sizeof(
particle_t));
2193 MPI_Alltoallv(sendbuf,
2198 recv_counts, recv_displs, dd->MPI_Particle, MPI_COMM_WORLD);
2201 if (nrecv > *capacity) {
2202 const int newcap = nrecv + nrecv / 2 + 1;
2204 realloc(*particles, (
size_t) newcap *
sizeof(
particle_t));
2206 ERRMSG(
"Out of memory!");
2212 for (
int ip = 0; ip < nrecv; ip++) {
2213 (*particles)[ip] = recvbuf[ip];
2242 MPI_Comm_size(MPI_COMM_WORLD, &size);
2244 ERRMSG(
"Number of tasks and subdomains is not identical!");
2247 const MPI_Datatype types[5] =
2248 { MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE };
2249 const int blocklengths[5] = { 1, 1, 1, 1,
NQ };
2250 const MPI_Aint displacements[5] =
2255 MPI_Type_create_struct(5, blocklengths, displacements, types,
2257 MPI_Type_commit(&dd->MPI_Particle);
2272 const double lon_min = (dd->
lon_glob[0] < 0) ? -180.0 : 0.0;
2275 *lon =
FMOD(*lon - lon_min, 360.0);
2282 *lat = 180.0 - *lat;
2284 }
else if (*lat < -90.0) {
2285 *lat = -180.0 - *lat;
2290 *lon =
FMOD(*lon - lon_min, 360.0);
2315 if (atm->
np + npart >
NP)
2316 ERRMSG(
"Too many particles. Increase NP!");
2319#pragma acc enter data create(npart, particles[:npart])
2320#pragma acc update device(particles[:npart], npart)
2321#pragma acc data present(atm, ctl, cache, particles, npart)
2322#pragma acc parallel loop
2324 for (
int ip = atm->
np; ip < atm->np + npart; ip++) {
2325 atm->
time[ip] = particles[ip - atm->
np].
time;
2326 atm->
lon[ip] = particles[ip - atm->
np].
lon;
2327 atm->
lat[ip] = particles[ip - atm->
np].
lat;
2328 atm->
p[ip] = particles[ip - atm->
np].
p;
2329 for (
int iq = 0; iq < ctl->
nq; iq++)
2330 atm->
q[iq][ip] = particles[ip - atm->
np].q[iq];
2334#pragma acc exit data delete(npart, particles)
2340#pragma acc update device(atm->np)
2359 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
2362 const int np = atm->
np;
2363 double amax = (met0->
nx * met0->
ny + met0->
ny) * met0->
np + met0->
np;
2365#pragma acc enter data create(amax)
2366#pragma acc update device(amax)
2367#pragma acc data present(ctl,met0,atm,dd,amax)
2372#pragma acc parallel loop independent gang vector
2374#pragma omp parallel for default(shared)
2376 for (
int ip = 0; ip < np; ip++) {
2384 dd->sort_key[ip] = amax + 1;
2386 dd->sort_key[ip] = amax + 2;
2394#pragma acc host_data use_device(dd->sort_key, dd->perm)
2396 thrustSortWrapper(dd->sort_key, np, dd->perm);
2398 size_t *perm_sz = (
size_t *) malloc((
size_t) np *
sizeof(size_t));
2399 if (perm_sz == NULL)
2400 ERRMSG(
"Out of memory!");
2402#pragma acc update self(dd->sort_key[0:np])
2404 gsl_sort_index(perm_sz, dd->sort_key, 1, (
size_t) np);
2405 for (
int ip = 0; ip < np; ++ip)
2406 dd->perm[ip] = (
int) perm_sz[ip];
2409#pragma acc update device(dd->perm[0:np])
2418 for (
int iq = 0; iq < ctl->
nq; iq++)
2424#pragma acc parallel loop reduction(+:nkeep) present(atm, ctl)
2426 for (
int ip = 0; ip < np; ip++)
2434#pragma acc parallel loop reduction(+:nsend) present(atm, ctl)
2436 for (
int ip = nkeep; ip < np; ip++)
2446 for (
int ip = 0; ip < np; ip++)
2452 (
"Rank %d: %d particles have subdomain index -1 and will be lost (kept: %d, to_send: %d, total_before: %d)",
2453 rank, nlost, nkeep, nsend, np);
2457#pragma acc update device(atm->np)
2462#pragma acc exit data delete(amax)
2477#pragma acc data present(dd,a)
2478#pragma acc parallel loop independent gang vector
2480#pragma omp parallel for default(shared)
2482 for (
int ip = 0; ip < np; ip++)
2483 dd->tmp[ip] = a[dd->perm[ip]];
2485#pragma acc parallel loop independent gang vector
2487#pragma omp parallel
for default(shared)
2489 for (
int ip = 0; ip < np; ip++)
2490 a[ip] = dd->tmp[ip];
2503 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
2504 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
2509 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
2510 for (i = 11; i > 0; i--)
2514 *day = doy - d0l[i] + 1;
2516 for (i = 11; i > 0; i--)
2520 *day = doy - d0[i] + 1;
2531 double data[2 *
EX];
2535 ERRMSG(
"Too many data points!");
2538 gsl_fft_complex_wavetable *wavetable =
2539 gsl_fft_complex_wavetable_alloc((
size_t) n);
2540 gsl_fft_complex_workspace *workspace =
2541 gsl_fft_complex_workspace_alloc((
size_t) n);
2544 for (
int i = 0; i < n; i++) {
2545 data[2 * i] = fcReal[i];
2546 data[2 * i + 1] = fcImag[i];
2550 gsl_fft_complex_forward(data, 1, (
size_t) n, wavetable, workspace);
2553 for (
int i = 0; i < n; i++) {
2554 fcReal[i] = data[2 * i];
2555 fcImag[i] = data[2 * i + 1];
2559 gsl_fft_complex_wavetable_free(wavetable);
2560 gsl_fft_complex_workspace_free(workspace);
2571 const double radius = z +
RE;
2572 const double latrad =
DEG2RAD(lat);
2573 const double lonrad =
DEG2RAD(lon);
2574 const double coslat = cos(latrad);
2576 x[0] = radius * coslat * cos(lonrad);
2577 x[1] = radius * coslat * sin(lonrad);
2578 x[2] = radius * sin(latrad);
2587 const char *metbase,
2588 const double dt_met,
2595 int year, mon, day, hour, min, sec;
2599 t6 = floor(t / dt_met) * dt_met;
2601 t6 = ceil(t / dt_met) * dt_met;
2604 jsec2time(t6, &year, &mon, &day, &hour, &min, &sec, &r);
2609 sprintf(filename,
"%s_YYYY_MM_DD_HH.nc", metbase);
2611 sprintf(filename,
"%s_YYYY_MM_DD_HH.bin", metbase);
2613 sprintf(filename,
"%s_YYYY_MM_DD_HH.pck", metbase);
2615 sprintf(filename,
"%s_YYYY_MM_DD_HH.zfp", metbase);
2617 sprintf(filename,
"%s_YYYY_MM_DD_HH.zstd", metbase);
2619 sprintf(filename,
"%s_YYYY_MM_DD_HH.cms", metbase);
2621 sprintf(filename,
"%s_YYYY_MM_DD_HH.sz3", metbase);
2623 sprintf(filename,
"%s_YYYY_MM_DD_HH.lz4", metbase);
2624 sprintf(repl,
"%d", year);
2626 sprintf(repl,
"%02d", mon);
2628 sprintf(repl,
"%02d", day);
2630 sprintf(repl,
"%02d", hour);
2636 sprintf(filename,
"%s_YYMMDDHH.nc", metbase);
2637 sprintf(repl,
"%d", year);
2639 sprintf(repl,
"%02d", year % 100);
2641 sprintf(repl,
"%02d", mon);
2643 sprintf(repl,
"%02d", day);
2645 sprintf(repl,
"%02d", hour);
2660 for (
int i = 0; i < 3; i++) {
2664 if (!(ch = strstr(orig, search)))
2666 strncpy(buffer, orig, (
size_t) (ch - orig));
2667 buffer[ch - orig] = 0;
2668 sprintf(buffer + (ch - orig),
"%s%s", repl, ch + strlen(search));
2670 strcpy(orig, buffer);
2677 const int met_tropo,
2697#pragma omp parallel for default(shared) private(ci,cw)
2698 for (
int ix = 0; ix < nx; ix++)
2699 for (
int iy = 0; iy < ny; iy++) {
2701 &pt[iy * nx + ix], ci, cw, 1);
2703 &ps[iy * nx + ix], ci, cw, 0);
2705 &zs[iy * nx + ix], ci, cw, 0);
2707 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
2709 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
2711 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
2713 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
2730 *lon2 =
FMOD(lon, 360.);
2731 if (*lon2 < lons[0])
2733 else if (*lon2 > lons[nlon - 1])
2738 if (lats[0] < lats[nlat - 1])
2739 *lat2 =
MIN(
MAX(*lat2, lats[0]), lats[nlat - 1]);
2741 *lat2 =
MIN(
MAX(*lat2, lats[nlat - 1]), lats[0]);
2748 float heights0[
EX][
EY][
EP],
2749 float array0[
EX][
EY][
EP],
2751 float heights1[
EX][
EY][
EP],
2752 float array1[
EX][
EY][
EP],
2754 const double height,
2780 int k_max = ind[0][0];
2781 for (
int i = 0; i < 2; i++)
2782 for (
int j = 0; j < 4; j++) {
2783 if (ci[2] > ind[i][j])
2785 if (k_max < ind[i][j])
2791 cw[0] = (lon2 - met0->
lon[ci[0]]) /
2792 (met0->
lon[ci[0] + 1] - met0->
lon[ci[0]]);
2793 cw[1] = (lat2 - met0->
lat[ci[1]]) /
2794 (met0->
lat[ci[1] + 1] - met0->
lat[ci[1]]);
2797 double height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2]]
2798 - heights0[ci[0]][ci[1]][ci[2]])
2799 + heights0[ci[0]][ci[1]][ci[2]];
2800 double height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2]]
2801 - heights0[ci[0]][ci[1] + 1][ci[2]])
2802 + heights0[ci[0]][ci[1] + 1][ci[2]];
2803 double height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2]]
2804 - heights0[ci[0] + 1][ci[1]][ci[2]])
2805 + heights0[ci[0] + 1][ci[1]][ci[2]];
2806 double height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2]]
2807 - heights0[ci[0] + 1][ci[1] + 1][ci[2]])
2808 + heights0[ci[0] + 1][ci[1] + 1][ci[2]];
2811 double height0 = cw[1] * (height01 - height00) + height00;
2812 double height1 = cw[1] * (height11 - height10) + height10;
2815 double height_bot = cw[0] * (height1 - height0) + height0;
2818 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
2819 - heights0[ci[0]][ci[1]][ci[2] + 1])
2820 + heights0[ci[0]][ci[1]][ci[2] + 1];
2821 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
2822 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
2823 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
2824 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
2825 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
2826 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
2827 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2828 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2829 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2832 height0 = cw[1] * (height01 - height00) + height00;
2833 height1 = cw[1] * (height11 - height10) + height10;
2836 double height_top = cw[0] * (height1 - height0) + height0;
2839 while (((heights0[0][0][0] > heights0[0][0][1]) &&
2840 ((height_bot <= height) || (height_top > height))
2841 && (height_bot >= height) && (ci[2] < k_max))
2843 ((heights0[0][0][0] < heights0[0][0][1]) &&
2844 ((height_bot >= height) || (height_top < height))
2845 && (height_bot <= height) && (ci[2] < k_max))
2849 height_bot = height_top;
2852 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
2853 - heights0[ci[0]][ci[1]][ci[2] + 1])
2854 + heights0[ci[0]][ci[1]][ci[2] + 1];
2855 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
2856 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
2857 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
2858 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
2859 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
2860 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
2861 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2862 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2863 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2866 height0 = cw[1] * (height01 - height00) + height00;
2867 height1 = cw[1] * (height11 - height10) + height10;
2870 height_top = cw[0] * (height1 - height0) + height0;
2874 cw[2] = (height - height_bot)
2875 / (height_top - height_bot);
2879 const double array000 = cw[3] * (array1[ci[0]][ci[1]][ci[2]]
2880 - array0[ci[0]][ci[1]][ci[2]])
2881 + array0[ci[0]][ci[1]][ci[2]];
2882 const double array100 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2]]
2883 - array0[ci[0] + 1][ci[1]][ci[2]])
2884 + array0[ci[0] + 1][ci[1]][ci[2]];
2885 const double array010 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2]]
2886 - array0[ci[0]][ci[1] + 1][ci[2]])
2887 + array0[ci[0]][ci[1] + 1][ci[2]];
2888 const double array110 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2]]
2889 - array0[ci[0] + 1][ci[1] + 1][ci[2]])
2890 + array0[ci[0] + 1][ci[1] + 1][ci[2]];
2891 const double array001 = cw[3] * (array1[ci[0]][ci[1]][ci[2] + 1]
2892 - array0[ci[0]][ci[1]][ci[2] + 1])
2893 + array0[ci[0]][ci[1]][ci[2] + 1];
2894 const double array101 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2] + 1]
2895 - array0[ci[0] + 1][ci[1]][ci[2] + 1])
2896 + array0[ci[0] + 1][ci[1]][ci[2] + 1];
2897 const double array011 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2] + 1]
2898 - array0[ci[0]][ci[1] + 1][ci[2] + 1])
2899 + array0[ci[0]][ci[1] + 1][ci[2] + 1];
2900 const double array111 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2901 - array0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2902 + array0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2904 const double array00 = cw[0] * (array100 - array000) + array000;
2905 const double array10 = cw[0] * (array110 - array010) + array010;
2906 const double array01 = cw[0] * (array101 - array001) + array001;
2907 const double array11 = cw[0] * (array111 - array011) + array011;
2909 const double aux0 = cw[1] * (array10 - array00) + array00;
2910 const double aux1 = cw[1] * (array11 - array01) + array01;
2913 *var = cw[2] * (aux1 - aux0) + aux0;
2943 cw[0] = (met->
p[ci[0] + 1] - p)
2944 / (met->
p[ci[0] + 1] - met->
p[ci[0]]);
2945 cw[1] = (met->
lon[ci[1] + 1] - lon2)
2946 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
2947 cw[2] = (met->
lat[ci[2] + 1] - lat2)
2948 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
2952 const double aux00 =
2953 cw[0] * (array[ci[1]][ci[2]][ci[0]] - array[ci[1]][ci[2]][ci[0] + 1])
2954 + array[ci[1]][ci[2]][ci[0] + 1];
2955 const double aux01 =
2956 cw[0] * (array[ci[1]][ci[2] + 1][ci[0]] -
2957 array[ci[1]][ci[2] + 1][ci[0] + 1])
2958 + array[ci[1]][ci[2] + 1][ci[0] + 1];
2959 const double aux10 =
2960 cw[0] * (array[ci[1] + 1][ci[2]][ci[0]] -
2961 array[ci[1] + 1][ci[2]][ci[0] + 1])
2962 + array[ci[1] + 1][ci[2]][ci[0] + 1];
2963 const double aux11 =
2964 cw[0] * (array[ci[1] + 1][ci[2] + 1][ci[0]] -
2965 array[ci[1] + 1][ci[2] + 1][ci[0] + 1])
2966 + array[ci[1] + 1][ci[2] + 1][ci[0] + 1];
2969 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
2970 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
2971 *var = cw[1] * (aux0 - aux1) + aux1;
2978 float array[
EX][
EY],
2999 cw[1] = (met->
lon[ci[1] + 1] - lon2)
3000 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
3001 cw[2] = (met->
lat[ci[2] + 1] - lat2)
3002 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
3006 const double aux00 = array[ci[1]][ci[2]];
3007 const double aux01 = array[ci[1]][ci[2] + 1];
3008 const double aux10 = array[ci[1] + 1][ci[2]];
3009 const double aux11 = array[ci[1] + 1][ci[2] + 1];
3012 if (isfinite(aux00) && isfinite(aux01)
3013 && isfinite(aux10) && isfinite(aux11)) {
3014 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
3015 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
3016 *var = cw[1] * (aux0 - aux1) + aux1;
3036 float array0[
EX][
EY][
EP],
3038 float array1[
EX][
EY][
EP],
3055 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
3058 *var = wt * (var0 - var1) + var1;
3065 float array0[
EX][
EY],
3067 float array1[
EX][
EY],
3083 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
3086 if (isfinite(var0) && isfinite(var1))
3087 *var = wt * (var0 - var1) + var1;
3098 float array0[
EX][
EY],
3100 float array1[
EX][
EY],
3101 const double lons[
EX],
3102 const double lats[
EY],
3121 const int ix =
locate_reg(lons, (
int) nlon, lon2);
3122 const int iy =
locate_irr(lats, (
int) nlat, lat2);
3126 for (
int dx = 0; dx < 2; dx++)
3127 for (
int dy = 0; dy < 2; dy++) {
3128 if (isfinite(array0[ix + dx][iy + dy])) {
3129 mean += array0[ix + dx][iy + dy];
3130 *sigma +=
SQR(array0[ix + dx][iy + dy]);
3133 if (isfinite(array1[ix + dx][iy + dy])) {
3134 mean += array1[ix + dx][iy + dy];
3135 *sigma +=
SQR(array1[ix + dx][iy + dy]);
3140 *sigma = sqrt(
MAX(*sigma / n -
SQR(mean / n), 0.0));
3143 if (method == 1 && isfinite(array0[ix][iy])
3144 && isfinite(array0[ix][iy + 1])
3145 && isfinite(array0[ix + 1][iy])
3146 && isfinite(array0[ix + 1][iy + 1])
3147 && isfinite(array1[ix][iy])
3148 && isfinite(array1[ix][iy + 1])
3149 && isfinite(array1[ix + 1][iy])
3150 && isfinite(array1[ix + 1][iy + 1])) {
3152 const double aux00 =
LIN(lons[ix], array0[ix][iy],
3153 lons[ix + 1], array0[ix + 1][iy], lon2);
3154 const double aux01 =
LIN(lons[ix], array0[ix][iy + 1],
3155 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
3156 const double aux0 =
LIN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
3158 const double aux10 =
LIN(lons[ix], array1[ix][iy],
3159 lons[ix + 1], array1[ix + 1][iy], lon2);
3160 const double aux11 =
LIN(lons[ix], array1[ix][iy + 1],
3161 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
3162 const double aux1 =
LIN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
3164 *var =
LIN(time0, aux0, time1, aux1, time);
3169 const double aux00 =
NN(lons[ix], array0[ix][iy],
3170 lons[ix + 1], array0[ix + 1][iy], lon2);
3171 const double aux01 =
NN(lons[ix], array0[ix][iy + 1],
3172 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
3173 const double aux0 =
NN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
3175 const double aux10 =
NN(lons[ix], array1[ix][iy],
3176 lons[ix + 1], array1[ix + 1][iy], lon2);
3177 const double aux11 =
NN(lons[ix], array1[ix][iy + 1],
3178 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
3179 const double aux1 =
NN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
3181 *var =
NN(time0, aux0, time1, aux1, time);
3206 const time_t jsec0 = (time_t) jsec + timegm(&t0);
3207 t1 = gmtime(&jsec0);
3209 *year = t1->tm_year + 1900;
3210 *mon = t1->tm_mon + 1;
3212 *hour = t1->tm_hour;
3215 *remain = jsec - floor(jsec);
3221 const double kz[
EP],
3222 const double kw[
EP],
3231 const double z =
Z(p);
3236 else if (z > kz[nk - 1])
3240 return LIN(kz[idx], kw[idx], kz[idx + 1], kw[idx + 1], z);
3257 const double a =
RA *
SQR(t), r =
SH(h2o) / (1. -
SH(h2o));
3270 (
"MET_PRESS_LEVEL_DEF=0 is disabled. Use 3 for the extended L137 set.");
3275 (
"MET_PRESS_LEVEL_DEF=1 is disabled. Use 4 for the extended L91 set.");
3280 (
"MET_PRESS_LEVEL_DEF=2 is disabled. Use 5 for the extended L60 set.");
3286 const double press[147] = {
3287 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
3288 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
3289 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
3290 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
3291 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
3292 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
3293 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
3294 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
3295 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
3296 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
3297 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
3298 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
3299 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
3300 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
3301 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
3302 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
3303 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
3304 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
3305 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73, 1028.85,
3307 1035.09, 1038.21, 1041.33, 1044.45
3310 for (
int ip = 0; ip < ctl->
met_np; ip++)
3317 const double press[101] = {
3318 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
3319 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
3320 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
3321 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
3322 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
3324 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
3325 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
3326 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
3327 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
3328 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
3329 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
3330 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
3331 1007.4431, 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73,
3333 1035.09, 1038.21, 1041.33, 1044.45
3336 for (
int ip = 0; ip < ctl->
met_np; ip++)
3343 const double press[62] = {
3344 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
3345 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
3346 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
3347 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
3348 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
3349 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
3350 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
3351 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1034.86, 1039.65,
3355 for (
int ip = 0; ip < ctl->
met_np; ip++)
3362 const double press[137] = {
3363 0.01, 0.02, 0.031, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861,
3364 0.2499, 0.3299, 0.4288, 0.5496, 0.6952, 0.869, 1.0742,
3365 1.3143, 1.5928, 1.9134, 2.2797, 2.6954, 3.1642, 3.6898,
3366 4.2759, 4.9262, 5.6441, 6.4334, 7.2974, 8.2397, 9.2634,
3367 10.372, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945, 18.9752,
3368 20.761, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
3369 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.199, 54.5299,
3370 57.9834, 61.5607, 65.2695, 69.1187, 73.1187, 77.281, 81.6182,
3371 86.145, 90.8774, 95.828, 101.005, 106.415, 112.068, 117.971,
3372 124.134, 130.564, 137.27, 144.262, 151.549, 159.14, 167.045,
3373 175.273, 183.834, 192.739, 201.997, 211.619, 221.615, 231.995,
3374 242.772, 253.955, 265.556, 277.585, 290.055, 302.976, 316.361,
3375 330.22, 344.566, 359.411, 374.767, 390.645, 407.058, 424.019,
3376 441.539, 459.632, 478.31, 497.584, 517.42, 537.72, 558.343,
3377 579.193, 600.167, 621.162, 642.076, 662.808, 683.262, 703.347,
3378 722.979, 742.086, 760.6, 778.466, 795.64, 812.085, 827.776,
3379 842.696, 856.838, 870.2, 882.791, 894.622, 905.712, 916.081,
3380 925.757, 934.767, 943.14, 950.908, 958.104, 965.299, 972.495,
3381 979.69, 986.886, 994.081, 1001.28, 1008.47, 1015.67, 1022.86,
3382 1030.06, 1037.25, 1044.45
3385 for (
int ip = 0; ip < ctl->
met_np; ip++)
3392 const double press[59] = {
3393 0.1, 0.2, 0.3843, 0.6365, 0.9564, 1.3448, 1.8058, 2.3478,
3394 2.985, 3.7397, 4.6462, 5.7565, 7.1322, 8.8366, 10.9483,
3395 13.5647, 16.8064, 20.8227, 25.7989, 31.9642, 39.6029, 49.0671,
3396 60.1802, 73.0663, 87.7274, 104.229, 122.614, 142.902, 165.089,
3397 189.147, 215.025, 242.652, 272.059, 303.217, 336.044, 370.407,
3398 406.133, 443.009, 480.791, 519.209, 557.973, 596.777, 635.306,
3399 673.24, 710.263, 746.063, 780.346, 812.83, 843.263, 871.42,
3400 897.112, 920.189, 940.551, 958.148, 975.744, 993.341, 1010.94,
3404 for (
int ip = 0; ip < ctl->
met_np; ip++)
3408 ERRMSG(
"Use values between 3 and 7.");
3412 ERRMSG(
"Recompile with larger EP to use this pressure level definition!");
3424 int i = (ihi + ilo) >> 1;
3426 if (xx[i] < xx[i + 1])
3427 while (ihi > ilo + 1) {
3428 i = (ihi + ilo) >> 1;
3434 while (ihi > ilo + 1) {
3435 i = (ihi + ilo) >> 1;
3455 int i = (ihi + ilo) >> 1;
3457 if ((xx[ig] <= x && x < xx[ig + 1]) || (xx[ig] >= x && x > xx[ig + 1]))
3460 if (xx[i] < xx[i + 1])
3461 while (ihi > ilo + 1) {
3462 i = (ihi + ilo) >> 1;
3468 while (ihi > ilo + 1) {
3469 i = (ihi + ilo) >> 1;
3487 const int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
3501 float profiles[
EX][
EY][
EP],
3503 const int lon_ap_ind,
3504 const int lat_ap_ind,
3505 const double height_ap,
3511 np, height_ap, ind[0]);
3513 np, height_ap, ind[1]);
3515 np, height_ap, ind[2]);
3534 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3538 double dts, u[4], um = 0, v[4], vm = 0, w[4], wm = 0,
3542 for (
int i = 0; i < ctl->
advect; i++) {
3547 x[0] = atm->
lon[ip];
3548 x[1] = atm->
lat[ip];
3551 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
3552 x[0] = atm->
lon[ip] +
DX2DEG(dts * u[i - 1] / 1000., atm->
lat[ip]);
3553 x[1] = atm->
lat[ip] +
DY2DEG(dts * v[i - 1] / 1000.);
3554 x[2] = atm->
p[ip] + dts * w[i - 1];
3556 const double tm = atm->
time[ip] + dts;
3561 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3563 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3565 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
3571 met1, met1->
pl, met1->
ul,
3572 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3574 met1, met1->
pl, met1->
vl,
3575 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3577 met1, met1->
pl, met1->
wl,
3578 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
3584 k = (i == 0 ? 0.0 : 1.0);
3585 else if (ctl->
advect == 4)
3586 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
3593 atm->
time[ip] += cache->
dt[ip];
3594 atm->
lon[ip] +=
DX2DEG(cache->
dt[ip] * um / 1000.,
3595 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
3596 atm->
lat[ip] +=
DY2DEG(cache->
dt[ip] * vm / 1000.);
3597 atm->
p[ip] += cache->
dt[ip] * wm;
3609 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3615 atm->
time[ip], atm->
p[ip],
3616 atm->
lon[ip], atm->
lat[ip],
3617 &atm->
q[qnt][ip], ci, cw, 1);
3620 double dts, u[4], um = 0, v[4], vm = 0, wdot[4],
3621 wdotm = 0, x[3] = { 0, 0, 0 };
3624 for (
int i = 0; i < ctl->
advect; i++) {
3629 x[0] = atm->
lon[ip];
3630 x[1] = atm->
lat[ip];
3631 x[2] = atm->
q[qnt][ip];
3633 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
3634 x[0] = atm->
lon[ip] +
DX2DEG(dts * u[i - 1] / 1000., atm->
lat[ip]);
3635 x[1] = atm->
lat[ip] +
DY2DEG(dts * v[i - 1] / 1000.);
3636 x[2] = atm->
q[qnt][ip] + dts * wdot[i - 1];
3639 const double tm = atm->
time[ip] + dts;
3644 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3647 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3650 tm, x[2], x[0], x[1], &wdot[i], ci, cw, 0);
3655 k = (i == 0 ? 0.0 : 1.0);
3656 else if (ctl->
advect == 4)
3657 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
3661 wdotm += k * wdot[i];
3665 atm->
time[ip] += cache->
dt[ip];
3666 atm->
lon[ip] +=
DX2DEG(cache->
dt[ip] * um / 1000.,
3667 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
3668 atm->
lat[ip] +=
DY2DEG(cache->
dt[ip] * vm / 1000.);
3669 atm->
q[qnt][ip] += cache->
dt[ip] * wdotm;
3675 atm->
q[qnt][ip], atm->
lon[ip], atm->
lat[ip],
3676 &atm->
p[ip], ci, cw, 1);
3704 atm->
lon[ip], atm->
lat[ip], &atm->
p[ip], ci, cw, 1);
3729 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3765 if (atm->
p[ip] < pbl)
3817 ERRMSG(
"Molar mass is not defined!");
3823 const int ensemble_mode = (ctl->
nens > 0);
3824 const int np = atm->
np;
3828 const int ngrid = nx * ny * nz;
3829 const int nens = ensemble_mode ? ctl->
nens : 1;
3831 double *restrict
const z = (
double *) malloc((
size_t) nz *
sizeof(double));
3832 double *restrict
const press =
3833 (
double *) malloc((
size_t) nz *
sizeof(double));
3834 double *restrict
const mass =
3835 (
double *) calloc((
size_t) ngrid * (size_t) nens,
sizeof(
double));
3836 double *restrict
const area =
3837 (
double *) malloc((
size_t) ny *
sizeof(double));
3838 double *restrict
const lon =
3839 (
double *) malloc((
size_t) nx *
sizeof(double));
3840 double *restrict
const lat =
3841 (
double *) malloc((
size_t) ny *
sizeof(double));
3843 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
3844 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
3845 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
3854#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])
3855#pragma acc data present(ctl,met0,met1,atm,ixs,iys,izs,z,press,mass,area,lon,lat)
3856#pragma acc parallel loop independent gang vector
3858#pragma omp parallel for default(shared)
3860 for (
int iz = 0; iz < nz; iz++) {
3862 press[iz] =
P(z[iz]);
3866 const double t0 = tt - 0.5 * ctl->
dt_mod;
3867 const double t1 = tt + 0.5 * ctl->
dt_mod;
3871#pragma acc parallel loop independent gang vector
3873#pragma omp parallel for default(shared)
3875 for (
int ip = 0; ip < np; ip++) {
3879 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
3880 || ixs[ip] < 0 || ixs[ip] >= nx
3881 || iys[ip] < 0 || iys[ip] >= ny || izs[ip] < 0 || izs[ip] >= nz)
3887#pragma acc parallel loop independent gang vector
3889#pragma omp parallel for default(shared)
3891 for (
int ix = 0; ix < nx; ix++)
3895#pragma acc parallel loop independent gang vector
3897#pragma omp parallel for default(shared)
3899 for (
int iy = 0; iy < ny; iy++) {
3901 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
3906#pragma acc parallel loop independent gang vector
3908 for (
int ip = 0; ip < np; ip++) {
3910 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
3911 if (ensemble_mode) {
3912 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
3913 mass_idx += ens * ngrid;
3916#pragma acc atomic update
3918 mass[mass_idx] += atm->
q[ctl->
qnt_m][ip];
3924#pragma acc parallel loop independent gang vector
3926#pragma omp parallel for default(shared)
3928 for (
int ip = 0; ip < np; ip++)
3936 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
3939 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
3940 if (ensemble_mode) {
3941 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
3942 mass_idx += ens * ngrid;
3946 const double m = mass[mass_idx];
3948 / (
RHO(press[izs[ip]], temp) * area[iys[ip]] * dz * 1e9);
3953#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
3981 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3998 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
4000 atm->
lat[ip], atm->
p[ip]));
4002 atm->
lat[ip], atm->
p[ip]));
4004 atm->
lat[ip], atm->
p[ip]));
4024 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4032 double pbot = ps, ptop = ps;
4049 double cape, cin, pel;
4055 if (isfinite(cape) && cape >= ctl->
conv_cape
4057 ptop = GSL_MIN(ptop, pel);
4061 if (ptop != pbot && atm->
p[ip] >= ptop) {
4066 pbot, atm->
lon[ip], atm->
lat[ip], &tbot, ci, cw, 1);
4068 atm->
lon[ip], atm->
lat[ip], &ttop, ci, cw, 1);
4069 const double rhobot = pbot / tbot;
4070 const double rhotop = ptop / ttop;
4073 const double rho = rhobot + (rhotop - rhobot) * cache->
rs[ip];
4076 atm->
p[ip] =
LIN(rhobot, pbot, rhotop, ptop, rho);
4095 int npart = 0, capacity = 0;
4102 dd_sort(ctl, *met, atm, dd, &npart);
4105 if (npart > capacity) {
4106 const int newcap = npart + npart / 2 + 1;
4108 realloc(particles, (
size_t) newcap *
sizeof(
particle_t));
4110 ERRMSG(
"Out of memory!");
4142 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4145 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,clim,atm)") {
4154 const double aux = exp(-cache->
dt[ip] / tdec);
4155 if (ctl->
qnt_m >= 0) {
4158 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
4159 atm->
q[ctl->
qnt_m][ip] *= aux;
4184 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4192 float umean = 0, usig = 0, vmean = 0, vsig = 0, wmean = 0, wsig = 0;
4193 for (
int i = 0; i < 2; i++)
4194 for (
int j = 0; j < 2; j++)
4195 for (
int k = 0; k < 2; k++) {
4196 umean += met0->
u[ix + i][iy + j][iz + k];
4197 usig +=
SQR(met0->
u[ix + i][iy + j][iz + k]);
4198 vmean += met0->
v[ix + i][iy + j][iz + k];
4199 vsig +=
SQR(met0->
v[ix + i][iy + j][iz + k]);
4200 wmean += met0->
w[ix + i][iy + j][iz + k];
4201 wsig +=
SQR(met0->
w[ix + i][iy + j][iz + k]);
4203 umean += met1->
u[ix + i][iy + j][iz + k];
4204 usig +=
SQR(met1->
u[ix + i][iy + j][iz + k]);
4205 vmean += met1->
v[ix + i][iy + j][iz + k];
4206 vsig +=
SQR(met1->
v[ix + i][iy + j][iz + k]);
4207 wmean += met1->
w[ix + i][iy + j][iz + k];
4208 wsig +=
SQR(met1->
w[ix + i][iy + j][iz + k]);
4210 usig = usig / 16.f -
SQR(umean / 16.f);
4211 usig = (usig > 0 ? sqrtf(usig) : 0);
4212 vsig = vsig / 16.f -
SQR(vmean / 16.f);
4213 vsig = (vsig > 0 ? sqrtf(vsig) : 0);
4214 wsig = wsig / 16.f -
SQR(wmean / 16.f);
4215 wsig = (wsig > 0 ? sqrtf(wsig) : 0);
4218 const double r = 1 - 2 * fabs(cache->
dt[ip]) / ctl->
dt_met;
4219 const double r2 = sqrt(1 - r * r);
4223 cache->
uvwp[ip][0] =
4224 (float) (r * cache->
uvwp[ip][0] +
4229 cache->
uvwp[ip][1] =
4230 (float) (r * cache->
uvwp[ip][1] +
4237 cache->
uvwp[ip][2] =
4238 (float) (r * cache->
uvwp[ip][2] +
4240 atm->
p[ip] += cache->
uvwp[ip][2] * cache->
dt[ip];
4261 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4263 double dsigw_dz = 0.0, sig_u = 0.25, sig_w = 0.1,
4264 tau_u = 300., tau_w = 100.;
4273 if (atm->
p[ip] >= pbl) {
4276 const double p =
MIN(atm->
p[ip], ps);
4277 const double zs =
Z(ps);
4278 const double z = 1e3 * (
Z(p) - zs);
4279 const double zi = 1e3 * (
Z(pbl) - zs);
4280 const double zratio = z / zi;
4283 double ess, nss, h2o, t;
4288 const double rho =
RHO(p,
TVIRT(t, h2o));
4289 const double tau = sqrt(
SQR(ess) +
SQR(nss));
4290 const double ustar = sqrt(tau / rho);
4300 sig_u = 1e-2 + 2.0 * ustar * (1.0 - zratio);
4301 sig_w = 1e-2 + 1.3 * ustar * (1.0 - zratio);
4304 dsigw_dz = -1.3 * ustar / zi;
4307 tau_u = 0.07 * zi / sig_u * sqrt(zratio);
4308 tau_w = 0.1 * zi / sig_w * pow(zratio, 0.8);
4315 const double wstar =
4316 pow(
G0 /
THETAVIRT(p, t, h2o) * shf / (rho *
CPD) * zi, 1. / 3.);
4320 + sqrt(0.4 *
SQR(wstar) + (5.0 - 4.0 * zratio) *
SQR(ustar));
4321 sig_w = 1e-2 + sqrt(1.2 *
SQR(wstar) * (1.0 - 0.9 * zratio)
4322 * pow(zratio, 2.0 / 3.0)
4323 + (1.8 - 1.4 * zratio) *
SQR(ustar));
4326 dsigw_dz = 0.5 / sig_w / zi * (-1.4 *
SQR(ustar) +
SQR(wstar)
4328 pow(
MAX(zratio, 1e-3), -1.0 / 3.0)
4329 - 1.8 * pow(zratio, 2.0 / 3.0)));
4332 const double C0 = 3.0;
4334 (1.5 - 1.2 * pow(zratio, 1.0 / 3.0)) *
SQR(wstar) * wstar / zi
4335 +
SQR(ustar) * ustar * (1.0 - 0.8 * zratio) / (
KARMAN * z);
4336 tau_u = 2 *
SQR(sig_u) / (C0 * eps);
4337 tau_w = 2 *
SQR(sig_w) / (C0 * eps);
4342 sig_u =
MAX(sig_u, 0.25);
4343 sig_w =
MAX(sig_w, 0.1);
4344 tau_u =
MAX(tau_u, 300.);
4345 tau_w =
MAX(tau_w, 100.);
4348 const double ru = exp(-fabs(cache->
dt[ip]) / tau_u);
4349 const double ru2 = sqrt(1.0 -
SQR(ru));
4351 = (float) (cache->
uvwp[ip][0] * ru + ru2 * cache->
rs[3 * ip]);
4353 = (float) (cache->
uvwp[ip][1] * ru + ru2 * cache->
rs[3 * ip + 1]);
4355 const double rw = exp(-fabs(cache->
dt[ip]) / tau_w);
4356 const double rw2 = sqrt(1.0 -
SQR(rw));
4358 = (float) (cache->
uvwp[ip][2] * rw + rw2 * cache->
rs[3 * ip + 2]
4359 + sig_w * dsigw_dz * cache->
dt[ip]);
4366 DZ2DP(cache->
uvwp[ip][2] * cache->
dt[ip] / 1000., atm->
p[ip]);
4388 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4397 const double wpbl =
pbl_weight(ctl, atm, ip, pbl, ps);
4398 const double wtrop =
tropo_weight(clim, atm, ip) * (1.0 - wpbl);
4399 const double wstrat = 1.0 - wpbl - wtrop;
4409 const double sigma = sqrt(2.0 * dx * fabs(cache->
dt[ip])) / 1000.;
4411 atm->
lat[ip] +=
DY2DEG(cache->
rs[3 * ip + 1] * sigma);
4416 const double sigma = sqrt(2.0 * dz * fabs(cache->
dt[ip])) / 1000.;
4417 atm->
p[ip] +=
DZ2DP(cache->
rs[3 * ip + 2] * sigma, atm->
p[ip]);
4436 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4439 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4451 const double dz = 1000. * (
Z(ps - ctl->
dry_depo_dp) -
Z(ps));
4471 const double aux = exp(-cache->
dt[ip] * v_dep / dz);
4472 if (ctl->
qnt_m >= 0) {
4475 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
4476 atm->
q[ctl->
qnt_m][ip] *= aux;
4500 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4503 const double a = 3.12541941e-06;
4504 const double b = -5.72532259e-01;
4505 const double low = pow(1. / a, 1. / b);
4508 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4515 if (!(lwc > 0 || rwc > 0))
4526 const double k = 9.1e7 * exp(-29700. /
RI * (1. / t - 1. / 298.15));
4529 const double H_SO2 =
4530 1.3e-2 * exp(2900. * (1. / t - 1. / 298.15)) *
RI * t;
4531 const double K_1S = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
4534 const double H_h2o2 =
4535 8.3e2 * exp(7600. * (1. / t - 1. / 298.15)) *
RI * t;
4541 cor = atm->
q[ctl->
qnt_Cx][ip] >
4542 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
4544 const double h2o2 = H_h2o2
4546 * M * cor * 1000. /
AVO;
4549 const double rho_air = atm->
p[ip] / (
RI * t) *
MA / 10.;
4550 const double CWC = (lwc + rwc) * rho_air / 1e3;
4553 const double rate_coef = k * K_1S * h2o2 * H_SO2 * CWC;
4554 const double aux = exp(-cache->
dt[ip] * rate_coef);
4555 if (ctl->
qnt_m >= 0) {
4558 atm->
q[ctl->
qnt_m][ip] *= aux;
4590 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
4593 cache->
iso_var[ip] = atm->
p[ip] / t;
4599 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
4610 LOG(1,
"Read balloon pressure data: %s", ctl->
balloon);
4614 if (!(in = fopen(ctl->
balloon,
"r")))
4615 ERRMSG(
"Cannot open file!");
4619 while (fgets(line,
LEN, in))
4620 if (sscanf(line,
"%lg %lg", &(cache->
iso_ts[cache->
iso_n]),
4623 ERRMSG(
"Too many data points!");
4626 if (cache->
iso_n < 1)
4627 ERRMSG(
"Could not read any data!");
4650 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,met1,atm)") {
4663 atm->
p[ip] = cache->
iso_var[ip] * t;
4669 atm->
p[ip] = 1000. * pow(cache->
iso_var[ip] / t, -1. / 0.286);
4675 atm->
p[ip] = cache->
iso_ps[0];
4703 const int nvar = NVAR, nfix = NFIX, nreact = NREACT;
4704 double rtol[1] = { 1.0e-3 };
4705 double atol[1] = { 1.0 };
4709#pragma acc data copy(rtol,atol,nvar,nfix,nreact)
4712 "acc data present(ctl,cache,clim,met0,met1,atm) ") {
4715 double var[nvar], fix[nfix], rconst[nreact];
4716 for (
int i = 0; i < nvar; i++)
4718 for (
int i = 0; i < nfix; i++)
4720 for (
int i = 0; i < nreact; i++)
4722 kpp_chem_initialize(ctl, clim, met0, met1, atm, var, fix, rconst, ip);
4727 for (
int i = 0; i < 20; i++) {
4734 Rosenbrock(var, fix, rconst, 0, ctl->
dt_kpp,
4735 atol, rtol, &FunTemplate, &JacTemplate, rpar, ipar);
4738 kpp_chem_output2atm(atm, ctl, met0, met1, var, ip);
4759 ERRMSG(
"Need T_ice and T_NAT to calculate T_STS!");
4763 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4765 double ps, ts, zs, us, vs, ess, nss, shf, lsm, sst, pbl, pt, pct, pcb,
4766 cl, plcl, plfc, pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot,
4767 o3, lwc, rwc, iwc, swc, cc, z, zt;
4815 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
4817 atm->
lat[ip], atm->
p[ip]));
4819 atm->
lat[ip], atm->
p[ip]));
4821 atm->
lat[ip], atm->
p[ip]));
4822 SET_ATM(qnt_vh, sqrt(u * u + v * v));
4844 atm->
lat[ip], atm->
p[ip])));
4862 const int np = atm->
np;
4863 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
4864 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
4865 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
4873 const double t0 = t - 0.5 * ctl->
dt_mod;
4874 const double t1 = t + 0.5 * ctl->
dt_mod;
4878#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
4879#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
4880#pragma acc parallel loop independent gang vector
4882#pragma omp parallel for default(shared)
4884 for (
int ip = 0; ip < np; ip++) {
4887 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
mixing_z0) / dz);
4888 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
4889 || ixs[ip] < 0 || ixs[ip] >= ctl->
mixing_nx
4890 || iys[ip] < 0 || iys[ip] >= ctl->
mixing_ny
4891 || izs[ip] < 0 || izs[ip] >= ctl->
mixing_nz)
4896 const int use_ensemble = (ctl->
nens > 0);
4898 const int quantities[] = {
4906 const int n_qnt =
sizeof(quantities) /
sizeof(quantities[0]);
4908 for (
int i = 0; i < n_qnt; i++)
4909 if (quantities[i] >= 0)
4915#pragma acc exit data delete(ixs,iys,izs)
4932 const int use_ensemble) {
4934 const int np = atm->
np;
4936 const int nens = use_ensemble ? ctl->
nens : 1;
4937 const int total_grid = ngrid * nens;
4939 double *restrict
const cmean =
4940 (
double *) malloc((
size_t) total_grid *
sizeof(double));
4941 int *restrict
const count =
4942 (
int *) malloc((
size_t) total_grid *
sizeof(int));
4946#pragma acc enter data create(cmean[0:total_grid],count[0:total_grid])
4947#pragma acc data present(ctl,clim,atm,ixs,iys,izs,cmean,count)
4948#pragma acc parallel loop independent gang vector
4953#pragma omp parallel for
4955 for (
int i = 0; i < total_grid; i++) {
4962#pragma acc parallel loop independent gang vector
4964 for (
int ip = 0; ip < np; ip++)
4966 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
4971#pragma acc atomic update
4973 cmean[idx] += atm->
q[qnt_idx][ip];
4975#pragma acc atomic update
4982#pragma acc parallel loop independent gang vector
4987#pragma omp parallel for
4989 for (
int i = 0; i < total_grid; i++)
4991 cmean[i] /= count[i];
4995#pragma acc parallel loop independent gang vector
4997#pragma omp parallel for
4999 for (
int ip = 0; ip < np; ip++) {
5001 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
5003 double mixparam = 1.0;
5012 atm->
q[qnt_idx][ip] += (cmean[idx] - atm->
q[qnt_idx][ip]) * mixparam;
5018#pragma acc exit data delete(cmean,count)
5039 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
5042 const double a = 4.71572206e-08;
5043 const double b = -8.28782867e-01;
5044 const double low = pow(1. / a, 1. / b);
5048 "acc data present(ctl,cache,clim,met0,met1,atm)") {
5074 0 ? pow(298. / t, ctl->
oh_chem[1]) : 1.);
5077 0 ? pow(298. / t, ctl->
oh_chem[3]) : 1.);
5078 const double c = log10(k0 * M / ki);
5079 k = k0 * M / (1. + k0 * M / ki) * pow(0.6, 1. / (1. + c * c));
5088 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
5091 const double rate_coef =
5093 atm->
lat[ip], atm->
p[ip]) * M * cor;
5094 const double aux = exp(-cache->
dt[ip] * rate_coef);
5095 if (ctl->
qnt_m >= 0) {
5098 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
5099 atm->
q[ctl->
qnt_m][ip] *= aux;
5120 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(cache,met0,met1,atm)") {
5131 while (atm->
lat[ip] < -90 || atm->
lat[ip] > 90) {
5132 if (atm->
lat[ip] > 90) {
5133 atm->
lat[ip] = 180 - atm->
lat[ip];
5134 atm->
lon[ip] += 180;
5136 if (atm->
lat[ip] < -90) {
5137 atm->
lat[ip] = -180 - atm->
lat[ip];
5138 atm->
lon[ip] += 180;
5143 while (atm->
lon[ip] < -180)
5144 atm->
lon[ip] += 360;
5145 while (atm->
lon[ip] >= 180)
5146 atm->
lon[ip] -= 360;
5149 if (atm->
p[ip] < met0->
p[met0->
np - 1]) {
5150 atm->
p[ip] = met0->
p[met0->
np - 1];
5151 }
else if (atm->
p[ip] > 300.) {
5153 if (atm->
p[ip] > ps)
5170 const double lambda_rn222 = log(2.0) / (3.8235 * 86400.0);
5171 const double lambda_pb210 = log(2.0) / (22.3 * 365.25 * 86400.0);
5172 const double lambda_be7 = log(2.0) / (53.22 * 86400.0);
5173 const double lambda_cs137 = log(2.0) / (30.05 * 365.25 * 86400.0);
5174 const double lambda_i131 = log(2.0) / (8.02 * 86400.0);
5175 const double lambda_xe133 = log(2.0) / (5.2474 * 86400.0);
5181 const double dt = cache->
dt[ip];
5185 atm->
q[ctl->
qnt_Apb210][ip] *= exp(-dt * lambda_pb210);
5190 const double aux = exp(-dt * lambda_rn222);
5191 const double lost = old * (1.0 - aux);
5196 atm->
q[ctl->
qnt_Apb210][ip] += lost * lambda_pb210 / lambda_rn222;
5201 atm->
q[ctl->
qnt_Abe7][ip] *= exp(-dt * lambda_be7);
5205 atm->
q[ctl->
qnt_Acs137][ip] *= exp(-dt * lambda_cs137);
5209 atm->
q[ctl->
qnt_Ai131][ip] *= exp(-dt * lambda_i131);
5213 atm->
q[ctl->
qnt_Axe133][ip] *= exp(-dt * lambda_xe133);
5223 gsl_rng_env_setup();
5224 if (omp_get_max_threads() >
NTHREADS)
5225 ERRMSG(
"Too many threads!");
5226 for (
int i = 0; i <
NTHREADS; i++) {
5227 rng[i] = gsl_rng_alloc(gsl_rng_default);
5228 gsl_rng_set(rng[i], gsl_rng_default_seed
5229 + (
long unsigned) (ntask *
NTHREADS + i));
5234 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
5235 CURAND_STATUS_SUCCESS)
5236 ERRMSG(
"Cannot create random number generator!");
5237 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
5238 CURAND_STATUS_SUCCESS)
5239 ERRMSG(
"Cannot set seed for random number generator!");
5242 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
5243 CURAND_STATUS_SUCCESS)
5244 ERRMSG(
"Cannot set stream for random number generator!");
5261#pragma omp parallel for default(shared)
5262 for (
size_t i = 0; i < n; ++i)
5263 rs[i] = gsl_rng_uniform(rng[omp_get_thread_num()]);
5267 else if (method == 1) {
5268#pragma omp parallel for default(shared)
5269 for (
size_t i = 0; i < n; ++i)
5270 rs[i] = gsl_ran_gaussian_ziggurat(rng[omp_get_thread_num()], 1.0);
5276#pragma acc update device(rs[:n])
5284 const uint64_t key = 0xc8e4fd154ce32f6d;
5288#pragma acc data present(rs)
5289#pragma acc parallel loop independent gang vector
5291#pragma omp parallel for default(shared)
5293 for (
size_t i = 0; i < n + 1; ++i) {
5294 uint64_t r, t, x, y, z;
5295 y = x = (rng_ctr + i) * key;
5298 x = (x >> 32) | (x << 32);
5300 x = (x >> 32) | (x << 32);
5302 x = (x >> 32) | (x << 32);
5304 x = (x >> 32) | (x << 32);
5305 r = t ^ ((x * x + y) >> 32);
5306 rs[i] = (double) r / (
double) UINT64_MAX;
5313#pragma acc parallel loop independent gang vector
5315#pragma omp parallel for default(shared)
5317 for (
size_t i = 0; i < n; i += 2) {
5318 const double r = sqrt(-2.0 * log(rs[i]));
5319 const double phi = 2.0 * M_PI * rs[i + 1];
5320 rs[i] = r * cosf((
float) phi);
5321 rs[i + 1] = r * sinf((
float) phi);
5329#pragma acc host_data use_device(rs)
5334 if (curandGenerateUniformDouble(rng_curand, rs, (n < 4 ? 4 : n)) !=
5335 CURAND_STATUS_SUCCESS)
5336 ERRMSG(
"Cannot create random numbers!");
5340 else if (method == 1) {
5341 if (curandGenerateNormalDouble
5342 (rng_curand, rs, (n < 4 ? 4 : n), 0.0,
5343 1.0) != CURAND_STATUS_SUCCESS)
5344 ERRMSG(
"Cannot create random numbers!");
5348 ERRMSG(
"MPTRAC was compiled without cuRAND!");
5366 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
5374 const double v_s =
sedi(atm->
p[ip], t, atm->
q[ctl->
qnt_rp][ip],
5378 atm->
p[ip] +=
DZ2DP(v_s * cache->
dt[ip] / 1000., atm->
p[ip]);
5393 const int np = atm->
np;
5394 double *restrict
const a = (
double *) malloc((
size_t) np *
sizeof(double));
5395 int *restrict
const p = (
int *) malloc((
size_t) np *
sizeof(int));
5396 if (a == NULL || p == NULL)
5397 ERRMSG(
"Out of memory!");
5400#pragma acc enter data create(a[0:np],p[0:np])
5401#pragma acc data present(ctl,met0,atm,a,p)
5406#pragma acc parallel loop independent gang vector
5408#pragma omp parallel for default(shared)
5410 for (
int ip = 0; ip < np; ip++) {
5421#pragma acc host_data use_device(a,p)
5423 thrustSortWrapper(a, np, p);
5425 size_t *perm_sz = (
size_t *) malloc((
size_t) np *
sizeof(size_t));
5426 if (perm_sz == NULL)
5427 ERRMSG(
"Out of memory!");
5429#pragma acc update self(a[0:np])
5431 gsl_sort_index(perm_sz, a, 1, (
size_t) np);
5432 for (
int ip = 0; ip < np; ++ip)
5433 p[ip] = (
int) perm_sz[ip];
5436#pragma acc update device(p[0:np])
5445 for (
int iq = 0; iq < ctl->
nq; iq++)
5450#pragma acc exit data delete(a,p)
5464 double *restrict
const help =
5465 (
double *) malloc((
size_t) np *
sizeof(double));
5467 ERRMSG(
"Out of memory!");
5471#pragma acc enter data create(help[0:np])
5472#pragma acc data present(a,p,help)
5473#pragma acc parallel loop independent gang vector
5475#pragma omp parallel for default(shared)
5477 for (
int ip = 0; ip < np; ip++)
5478 help[ip] = a[p[ip]];
5480#pragma acc parallel loop independent gang vector
5482#pragma omp parallel for default(shared)
5484 for (
int ip = 0; ip < np; ip++)
5489#pragma acc exit data delete(help)
5506 const double latmin = gsl_stats_min(met0->
lat, 1, (
size_t) met0->
ny),
5507 latmax = gsl_stats_max(met0->
lat, 1, (
size_t) met0->
ny);
5510 (fabs(met0->
lon[met0->
nx - 1] - met0->
lon[0] - 360.0) >= 0.01);
5513 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,atm)") {
5519 cache->
dt[ip] = t - atm->
time[ip];
5521 cache->
dt[ip] = 0.0;
5530 if (local && (atm->
lon[ip] <= met0->
lon[0]
5531 || atm->
lon[ip] >= met0->
lon[met0->
nx - 1]
5532 || atm->
lat[ip] <= latmin || atm->
lat[ip] >= latmax))
5533 cache->
dt[ip] = 0.0;
5552 ctl->
t_start = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
5554 ctl->
t_stop = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
5556 ctl->
t_start = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
5558 ctl->
t_stop = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
5563 ERRMSG(
"Nothing to do! Check T_STOP and DIRECTION!");
5587 "acc data present(ctl,cache,clim,met0,met1,atm)") {
5611 const double K_o1d =
ARRHENIUS(3.30e-10, 0, t) * o1d * M;
5613 atm->
p[ip], sza, o3c);
5614 atm->
q[ctl->
qnt_Cccl4][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5619 const double K_o1d =
ARRHENIUS(2.30e-10, 0, t) * o1d * M;
5621 atm->
p[ip], sza, o3c);
5622 atm->
q[ctl->
qnt_Cccl3f][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5627 const double K_o1d =
ARRHENIUS(1.40e-10, -25, t) * o1d * M;
5629 atm->
p[ip], sza, o3c);
5630 atm->
q[ctl->
qnt_Cccl2f2][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5635 const double K_o1d =
ARRHENIUS(1.19e-10, -20, t) * o1d * M;
5637 atm->
p[ip], sza, o3c);
5638 atm->
q[ctl->
qnt_Cn2o][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5657 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
5660 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
5666 if (!isfinite(pct) || atm->
p[ip] <= pct)
5682 double lwc, rwc, iwc, swc;
5687 const int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
5701 else if (t <= 238.15)
5721 const double K_1 = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
5722 const double K_2 = 6e-8 * exp(1.12e3 * (1. / t - 1. / 298.15));
5723 h *= (1. + K_1 / H_ion + K_1 * K_2 /
SQR(H_ion));
5727 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
5730 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
5756 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
5759 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
5764 const double aux = exp(-cache->
dt[ip] * lambda);
5765 if (ctl->
qnt_m >= 0) {
5768 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
5769 atm->
q[ctl->
qnt_m][ip] *= aux;
5794 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
5796 if (acc_get_num_devices(acc_device_nvidia) <= 0)
5797 ERRMSG(
"Not running on a GPU device!");
5798 acc_set_device_num(rank % acc_get_num_devices(acc_device_nvidia),
5800 acc_device_t device_type = acc_get_device_type();
5801 acc_init(device_type);
5817 ctl_t *ctlup = *ctl;
5820 met_t *met0up = *met0;
5821 met_t *met1up = *met1;
5822 atm_t *atmup = *atm;
5823#pragma acc enter data create(ctlup[:1],cacheup[:1],climup[:1],met0up[:1],met1up[:1],atmup[:1])
5826#pragma acc enter data create(ddup[:1])
5845#pragma acc exit data delete(ctl,cache,clim,met0,met1,atm)
5847#pragma acc exit data delete(dd)
5862 MPI_Type_free(&dd->MPI_Particle);
5881 char cachefile[
LEN], cmd[2 *
LEN], filename[
LEN];
5887 if (t == ctl->
t_start || !init) {
5894 ERRMSG(
"Cannot open file!");
5899 ERRMSG(
"Cannot open file!");
5909 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5910 LOG(1,
"Caching: %s", cachefile);
5911 if (system(cmd) != 0)
5912 WARN(
"Caching command failed!");
5917 if (t > (*met1)->time) {
5927 ERRMSG(
"Cannot open file!");
5937 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5938 LOG(1,
"Caching: %s", cachefile);
5939 if (system(cmd) != 0)
5940 WARN(
"Caching command failed!");
5945 if (t < (*met0)->time) {
5955 ERRMSG(
"Cannot open file!");
5965 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5966 LOG(1,
"Caching: %s", cachefile);
5967 if (system(cmd) != 0)
5968 WARN(
"Caching command failed!");
5973 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
5974 if ((*met0)->nx != (*met1)->nx
5975 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
5976 ERRMSG(
"Meteo grid dimensions do not match!");
5977 for (
int ix = 0; ix < (*met0)->nx; ix++)
5978 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
5979 ERRMSG(
"Meteo grid longitudes do not match!");
5980 for (
int iy = 0; iy < (*met0)->ny; iy++)
5981 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
5982 ERRMSG(
"Meteo grid latitudes do not match!");
5983 for (
int ip = 0; ip < (*met0)->np; ip++)
5984 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
5985 ERRMSG(
"Meteo grid pressure levels do not match!");
6011 const char *filename,
6024 LOG(1,
"Read atmospheric data: %s", filename);
6044 ERRMSG(
"Atmospheric data type not supported!");
6052 ERRMSG(
"Can not read any data!");
6056 LOG(2,
"Number of particles: %d", atm->
np);
6057 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
6058 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
6059 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
6060 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
6061 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
6062 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
6063 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
6064 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
6065 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
6066 for (
int iq = 0; iq < ctl->
nq; iq++) {
6068 sprintf(msg,
"Quantity %s range: %s ... %s %s",
6071 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
6072 LOG(2, msg, mini, maxi);
6142 const char *filename,
6151 LOG(1,
"\nMassive-Parallel Trajectory Calculations (MPTRAC)\n"
6152 "(executable: %s | version: %s | compiled: %s, %s)\n",
6153 argv[0], VERSION, __DATE__, __TIME__);
6260 ctl->
nq = (int)
scan_ctl(filename, argc, argv,
"NQ", -1,
"0", NULL);
6262 ERRMSG(
"Too many quantities!");
6263 for (
int iq = 0; iq < ctl->
nq; iq++) {
6269 scan_ctl(filename, argc, argv,
"QNT_FORMAT", iq,
"%g",
6271 if (strcasecmp(ctl->
qnt_name[iq],
"aoa") == 0)
6275 SET_QNT(qnt_idx,
"idx",
"particle index",
"-")
6276 SET_QNT(qnt_ens,
"ens",
"ensemble index",
"-")
6277 SET_QNT(qnt_stat,
"stat",
"station flag",
"-")
6278 SET_QNT(qnt_m,
"m",
"mass",
"kg")
6279 SET_QNT(qnt_vmr,
"vmr",
"volume mixing ratio",
"ppv")
6280 SET_QNT(qnt_rp,
"rp",
"particle radius",
"microns")
6281 SET_QNT(qnt_rhop,
"rhop",
"particle density",
"kg/m^3")
6282 SET_QNT(qnt_ps,
"ps",
"surface pressure",
"hPa")
6283 SET_QNT(qnt_ts,
"ts",
"surface temperature",
"K")
6284 SET_QNT(qnt_zs,
"zs",
"surface height",
"km")
6285 SET_QNT(qnt_us,
"us",
"surface zonal wind",
"m/s")
6286 SET_QNT(qnt_vs,
"vs",
"surface meridional wind",
"m/s")
6287 SET_QNT(qnt_ess,
"ess",
"eastward turbulent surface stress",
"N/m^2")
6288 SET_QNT(qnt_nss,
"nss",
"northward turbulent surface stress",
"N/m^2")
6289 SET_QNT(qnt_shf,
"shf",
"surface sensible heat flux",
"W/m^2")
6290 SET_QNT(qnt_lsm,
"lsm",
"land-sea mask",
"1")
6291 SET_QNT(qnt_sst,
"sst",
"sea surface temperature",
"K")
6292 SET_QNT(qnt_pbl,
"pbl",
"planetary boundary layer",
"hPa")
6293 SET_QNT(qnt_pt,
"pt",
"tropopause pressure",
"hPa")
6294 SET_QNT(qnt_tt,
"tt",
"tropopause temperature",
"K")
6295 SET_QNT(qnt_zt,
"zt",
"tropopause geopotential height",
"km")
6296 SET_QNT(qnt_h2ot,
"h2ot",
"tropopause water vapor",
"ppv")
6297 SET_QNT(qnt_zg,
"zg",
"geopotential height",
"km")
6298 SET_QNT(qnt_p,
"p",
"pressure",
"hPa")
6299 SET_QNT(qnt_t,
"t",
"temperature",
"K")
6300 SET_QNT(qnt_rho,
"rho",
"air density",
"kg/m^3")
6301 SET_QNT(qnt_u,
"u",
"zonal wind",
"m/s")
6302 SET_QNT(qnt_v,
"v",
"meridional wind",
"m/s")
6303 SET_QNT(qnt_w,
"w",
"vertical velocity",
"hPa/s")
6304 SET_QNT(qnt_h2o,
"h2o",
"water vapor",
"ppv")
6305 SET_QNT(qnt_o3,
"o3",
"ozone",
"ppv")
6306 SET_QNT(qnt_lwc,
"lwc",
"cloud liquid water content",
"kg/kg")
6307 SET_QNT(qnt_rwc,
"rwc",
"cloud rain water content",
"kg/kg")
6308 SET_QNT(qnt_iwc,
"iwc",
"cloud ice water content",
"kg/kg")
6309 SET_QNT(qnt_swc,
"swc",
"cloud snow water content",
"kg/kg")
6310 SET_QNT(qnt_cc,
"cc",
"cloud cover",
"1")
6311 SET_QNT(qnt_pct,
"pct",
"cloud top pressure",
"hPa")
6312 SET_QNT(qnt_pcb,
"pcb",
"cloud bottom pressure",
"hPa")
6313 SET_QNT(qnt_cl,
"cl",
"total column cloud water",
"kg/m^2")
6314 SET_QNT(qnt_plcl,
"plcl",
"lifted condensation level",
"hPa")
6315 SET_QNT(qnt_plfc,
"plfc",
"level of free convection",
"hPa")
6316 SET_QNT(qnt_pel,
"pel",
"equilibrium level",
"hPa")
6317 SET_QNT(qnt_cape,
"cape",
"convective available potential energy",
6319 SET_QNT(qnt_cin,
"cin",
"convective inhibition",
"J/kg")
6320 SET_QNT(qnt_o3c,
"o3c",
"total column ozone",
"DU")
6321 SET_QNT(qnt_hno3,
"hno3",
"nitric acid",
"ppv")
6322 SET_QNT(qnt_oh,
"oh",
"hydroxyl radical",
"ppv")
6323 SET_QNT(qnt_h2o2,
"h2o2",
"hydrogen peroxide",
"ppv")
6324 SET_QNT(qnt_ho2,
"ho2",
"hydroperoxyl radical",
"ppv")
6325 SET_QNT(qnt_o1d,
"o1d",
"atomic oxygen",
"ppv")
6326 SET_QNT(qnt_mloss_oh,
"mloss_oh",
"mass loss due to OH chemistry",
"kg")
6327 SET_QNT(qnt_mloss_h2o2,
"mloss_h2o2",
6328 "mass loss due to H2O2 chemistry",
"kg")
6329 SET_QNT(qnt_mloss_kpp,
"mloss_kpp",
"mass loss due to kpp chemistry",
6331 SET_QNT(qnt_mloss_wet,
"mloss_wet",
"mass loss due to wet deposition",
6333 SET_QNT(qnt_mloss_dry,
"mloss_dry",
"mass loss due to dry deposition",
6335 SET_QNT(qnt_mloss_decay,
"mloss_decay",
6336 "mass loss due to exponential decay",
"kg")
6337 SET_QNT(qnt_loss_rate,
"loss_rate",
"total loss rate",
"s^-1")
6338 SET_QNT(qnt_psat,
"psat",
"saturation pressure over water",
"hPa")
6339 SET_QNT(qnt_psice,
"psice",
"saturation pressure over ice",
"hPa")
6340 SET_QNT(qnt_pw,
"pw",
"partial water vapor pressure",
"hPa")
6341 SET_QNT(qnt_sh,
"sh",
"specific humidity",
"kg/kg")
6342 SET_QNT(qnt_rh,
"rh",
"relative humidity",
"%%")
6343 SET_QNT(qnt_rhice,
"rhice",
"relative humidity over ice",
"%%")
6344 SET_QNT(qnt_theta,
"theta",
"potential temperature",
"K")
6345 SET_QNT(qnt_zeta,
"zeta",
"zeta coordinate",
"K")
6346 SET_QNT(qnt_zeta_d,
"zeta_d",
"diagnosed zeta coordinate",
"K")
6347 SET_QNT(qnt_zeta_dot,
"zeta_dot",
"velocity of zeta coordinate",
6349 SET_QNT(qnt_eta,
"eta",
"eta coordinate",
"1")
6350 SET_QNT(qnt_eta_dot,
"eta_dot",
"velocity of eta coordinate",
"1/s")
6351 SET_QNT(qnt_tvirt,
"tvirt",
"virtual temperature",
"K")
6352 SET_QNT(qnt_lapse,
"lapse",
"temperature lapse rate",
"K/km")
6353 SET_QNT(qnt_vh,
"vh",
"horizontal velocity",
"m/s")
6354 SET_QNT(qnt_vz,
"vz",
"vertical velocity",
"m/s")
6355 SET_QNT(qnt_pv,
"pv",
"potential vorticity",
"PVU")
6356 SET_QNT(qnt_tdew,
"tdew",
"dew point temperature",
"K")
6357 SET_QNT(qnt_tice,
"tice",
"frost point temperature",
"K")
6358 SET_QNT(qnt_tsts,
"tsts",
"STS existence temperature",
"K")
6359 SET_QNT(qnt_tnat,
"tnat",
"NAT existence temperature",
"K")
6360 SET_QNT(qnt_Cx,
"Cx",
"Trace species x volume mixing ratio",
"ppv")
6361 SET_QNT(qnt_Ch2o,
"Ch2o",
"H2O volume mixing ratio",
"ppv")
6362 SET_QNT(qnt_Co3,
"Co3",
"O3 volume mixing ratio",
"ppv")
6363 SET_QNT(qnt_Cco,
"Cco",
"CO volume mixing ratio",
"ppv")
6364 SET_QNT(qnt_Coh,
"Coh",
"HO volume mixing ratio",
"ppv")
6365 SET_QNT(qnt_Ch,
"Ch",
"H radical volume mixing ratio",
"ppv")
6366 SET_QNT(qnt_Cho2,
"Cho2",
"HO2 volume mixing ratio",
"ppv")
6367 SET_QNT(qnt_Ch2o2,
"Ch2o2",
"H2O2 volume mixing ratio",
"ppv")
6368 SET_QNT(qnt_Co1d,
"Co1d",
"O(1D) volume mixing ratio",
"ppv")
6369 SET_QNT(qnt_Co3p,
"Co3p",
"O(3P) radical volume mixing ratio",
"ppv")
6370 SET_QNT(qnt_Cccl4,
"Cccl4",
"CCl4 (CFC-10) volume mixing ratio",
"ppv")
6371 SET_QNT(qnt_Cccl3f,
"Cccl3f",
"CCl3F (CFC-11) volume mixing ratio",
6373 SET_QNT(qnt_Cccl2f2,
"Cccl2f2",
"CCl2F2 (CFC-12) volume mixing ratio",
6375 SET_QNT(qnt_Cn2o,
"Cn2o",
"N2O volume mixing ratio",
"ppv")
6376 SET_QNT(qnt_Csf6,
"Csf6",
"SF6 volume mixing ratio",
"ppv")
6377 SET_QNT(qnt_aoa,
"aoa",
"age of air",
"s")
6378 SET_QNT(qnt_Arn222,
"Arn222",
"Rn-222 activity",
"Bq")
6379 SET_QNT(qnt_Apb210,
"Apb210",
"Pb-210 activity",
"Bq")
6380 SET_QNT(qnt_Abe7,
"Abe7",
"Be-7 activity",
"Bq")
6381 SET_QNT(qnt_Acs137,
"Acs137",
"Cs-137 activity",
"Bq")
6382 SET_QNT(qnt_Ai131,
"Ai131",
"I-131 activity",
"Bq")
6383 SET_QNT(qnt_Axe133,
"Axe133",
"Xe-133 activity",
"Bq")
6384 SET_QNT(qnt_subdomain,
"subdomain",
"current subdomain index",
"-")
6385 SET_QNT(qnt_destination,
"destination",
6386 "subdomain index of destination",
"-")
6392 (int)
scan_ctl(filename, argc, argv,
"ADVECT_VERT_COORD", -1,
"0", NULL);
6394 ERRMSG(
"ADVECT_VERT_COORD must be 0, 1, 2, or 3!");
6397 ERRMSG(
"Add quantity zeta for diabatic advection!");
6399 ERRMSG(
"Add quantity eta for etadot avection!");
6402 (int)
scan_ctl(filename, argc, argv,
"MET_VERT_COORD", -1,
"0", NULL);
6404 ERRMSG(
"MET_VERT_COORD must be 0, 1, 2, 3, or 4!");
6408 (
"Using ADVECT_VERT_COORD = 2 requires meteo data on model levels!");
6411 (
"Using ADVECT_VERT_COORD = 3 requires A and B model level coefficients!");
6415 (int)
scan_ctl(filename, argc, argv,
"DIRECTION", -1,
"1", NULL);
6417 ERRMSG(
"Set DIRECTION to -1 or 1!");
6418 ctl->
t_stop =
scan_ctl(filename, argc, argv,
"T_STOP", -1,
"1e100", NULL);
6419 ctl->
dt_mod =
scan_ctl(filename, argc, argv,
"DT_MOD", -1,
"180", NULL);
6423 ctl->
dt_met =
scan_ctl(filename, argc, argv,
"DT_MET", -1,
"3600", NULL);
6425 (int)
scan_ctl(filename, argc, argv,
"MET_CONVENTION", -1,
"0", NULL);
6427 (int)
scan_ctl(filename, argc, argv,
"MET_TYPE", -1,
"0", NULL);
6430 (
"Please use meteo files in netcdf format for diabatic calculations.");
6433 (
"Please use meteo files in netcdf format for etadot calculations.");
6435 (int)
scan_ctl(filename, argc, argv,
"MET_CLAMS", -1,
"0", NULL);
6437 (int)
scan_ctl(filename, argc, argv,
"MET_NC_SCALE", -1,
"1", NULL);
6439 (int)
scan_ctl(filename, argc, argv,
"MET_NC_LEVEL", -1,
"0", NULL);
6441 (int)
scan_ctl(filename, argc, argv,
"MET_NC_QUANT", -1,
"0", NULL);
6443 (int)
scan_ctl(filename, argc, argv,
"MET_ZSTD_LEVEL", -1,
"-3", NULL);
6445 (int)
scan_ctl(filename, argc, argv,
"MET_ZSTD_NWORKERS", -1,
"4", NULL);
6447 (int)
scan_ctl(filename, argc, argv,
"MET_LZ4_ACCEL", -1,
"8", NULL);
6449 (int)
scan_ctl(filename, argc, argv,
"MET_PCK_ZSTD", -1,
"0", NULL);
6451 ERRMSG(
"Set MET_PCK_ZSTD to 0 or 1!");
6454 ERRMSG(
"MET_PCK_ZSTD requires MPTRAC to be compiled with ZSTD support!");
6456 const int def_lossy_scale =
6457 (int)
scan_ctl(filename, argc, argv,
"MET_LOSSY_SCALE", -1,
"0", NULL);
6458 for (
int i = 0; i <
METVAR; i++) {
6459 char defprec_zfp[
LEN] =
"7", deftol_zfp[
LEN] =
"0.0";
6460 char defprec_sz3[
LEN] =
"6", deftol_sz3[
LEN] =
"0.0";
6462 sprintf(defprec_zfp,
"12");
6463 sprintf(defprec_sz3,
"11");
6464 }
else if (i == 1) {
6465 sprintf(defprec_zfp,
"11");
6466 sprintf(defprec_sz3,
"7");
6467 }
else if (i == 2 || i == 3) {
6468 sprintf(defprec_zfp,
"7");
6469 sprintf(defprec_sz3,
"7");
6470 }
else if (i == 4) {
6471 sprintf(defprec_zfp,
"6");
6472 sprintf(defprec_sz3,
"13");
6473 }
else if (i == 5) {
6474 sprintf(defprec_zfp,
"7");
6475 sprintf(defprec_sz3,
"20");
6476 }
else if (i == 6) {
6477 sprintf(defprec_zfp,
"10");
6478 sprintf(defprec_sz3,
"18");
6479 }
else if (i == 7) {
6480 sprintf(defprec_zfp,
"9");
6481 sprintf(defprec_sz3,
"10");
6482 }
else if (i >= 8 && i <= 11) {
6483 sprintf(defprec_zfp,
"6");
6484 sprintf(defprec_sz3,
"13");
6485 }
else if (i == 12) {
6486 sprintf(defprec_zfp,
"9");
6487 sprintf(defprec_sz3,
"6");
6490 (int)
scan_ctl(filename, argc, argv,
"MET_ZFP_PREC", i, defprec_zfp,
6493 scan_ctl(filename, argc, argv,
"MET_ZFP_TOL", i, deftol_zfp, NULL);
6495 (int)
scan_ctl(filename, argc, argv,
"MET_SZ3_PREC", i, defprec_sz3,
6498 scan_ctl(filename, argc, argv,
"MET_SZ3_TOL", i, deftol_sz3, NULL);
6500 snprintf(defscale,
LEN,
"%d", def_lossy_scale);
6502 (int)
scan_ctl(filename, argc, argv,
"MET_LOSSY_SCALE", i, defscale,
6505 ERRMSG(
"Set MET_LOSSY_SCALE to 0 or 1!");
6508 scan_ctl(filename, argc, argv,
"MET_COMP_LOGFILE", -1,
"-",
6511 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_BATCH", -1,
"-1", NULL);
6513 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ZSTD", -1,
"1", NULL);
6515 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ND0X", -1,
"48", NULL);
6517 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ND0Y", -1,
"24", NULL);
6519 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_MAXLEV", -1,
"6", NULL);
6520 for (
int i = 0; i <
METVAR; i++) {
6521 char defeps[
LEN] =
"1.0";
6522 if (i == 1 || i == 2 || i == 3)
6523 sprintf(defeps,
"0.05");
6525 scan_ctl(filename, argc, argv,
"MET_CMS_EPS", i, defeps, NULL);
6527 ctl->
met_dx = (int)
scan_ctl(filename, argc, argv,
"MET_DX", -1,
"1", NULL);
6528 ctl->
met_dy = (int)
scan_ctl(filename, argc, argv,
"MET_DY", -1,
"1", NULL);
6529 ctl->
met_dp = (int)
scan_ctl(filename, argc, argv,
"MET_DP", -1,
"1", NULL);
6531 ERRMSG(
"MET_DX, MET_DY, and MET_DP need to be greater than zero!");
6532 ctl->
met_sx = (int)
scan_ctl(filename, argc, argv,
"MET_SX", -1,
"1", NULL);
6533 ctl->
met_sy = (int)
scan_ctl(filename, argc, argv,
"MET_SY", -1,
"1", NULL);
6534 ctl->
met_sp = (int)
scan_ctl(filename, argc, argv,
"MET_SP", -1,
"1", NULL);
6536 ERRMSG(
"MET_SX, MET_SY, and MET_SP need to be greater than zero!");
6538 scan_ctl(filename, argc, argv,
"MET_DETREND", -1,
"-999", NULL);
6539 ctl->
met_np = (int)
scan_ctl(filename, argc, argv,
"MET_NP", -1,
"0", NULL);
6541 ERRMSG(
"Too many pressure levels!");
6543 (int)
scan_ctl(filename, argc, argv,
"MET_PRESS_LEVEL_DEF", -1,
"-1",
6549 for (
int ip = 0; ip < ctl->
met_np; ip++)
6551 scan_ctl(filename, argc, argv,
"MET_P", ip,
"", NULL);
6555 (int)
scan_ctl(filename, argc, argv,
"MET_NLEV", -1,
"0", NULL);
6557 ERRMSG(
"Too many model levels!");
6558 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
6560 scan_ctl(filename, argc, argv,
"MET_LEV_HYAM", ip,
"", NULL);
6561 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
6563 scan_ctl(filename, argc, argv,
"MET_LEV_HYBM", ip,
"", NULL);
6565 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SX", -1,
"-1", NULL);
6567 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SY", -1,
"-1", NULL);
6569 (int)
scan_ctl(filename, argc, argv,
"MET_RELHUM", -1,
"0", NULL);
6571 (int)
scan_ctl(filename, argc, argv,
"MET_CAPE", -1,
"1", NULL);
6573 ERRMSG(
"Set MET_CAPE to 0 or 1!");
6575 (int)
scan_ctl(filename, argc, argv,
"MET_PBL", -1,
"3", NULL);
6577 ERRMSG(
"Set MET_PBL to 0 ... 3!");
6579 scan_ctl(filename, argc, argv,
"MET_PBL_MIN", -1,
"0.1", NULL);
6581 scan_ctl(filename, argc, argv,
"MET_PBL_MAX", -1,
"5.0", NULL);
6583 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO", -1,
"3", NULL);
6585 ERRMSG(
"Set MET_TROPO to 0 ... 5!");
6587 scan_ctl(filename, argc, argv,
"MET_TROPO_PV", -1,
"3.5", NULL);
6589 scan_ctl(filename, argc, argv,
"MET_TROPO_THETA", -1,
"380", NULL);
6591 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO_SPLINE", -1,
"1", NULL);
6593 scan_ctl(filename, argc, argv,
"MET_DT_OUT", -1,
"0.1", NULL);
6595 (int)
scan_ctl(filename, argc, argv,
"MET_CACHE", -1,
"0", NULL);
6597 (int)
scan_ctl(filename, argc, argv,
"MET_MPI_SHARE", -1,
"0", NULL);
6600 ctl->
sort_dt =
scan_ctl(filename, argc, argv,
"SORT_DT", -1,
"-999", NULL);
6604 (int)
scan_ctl(filename, argc, argv,
"ISOSURF", -1,
"0", NULL);
6609 (int)
scan_ctl(filename, argc, argv,
"RNG_TYPE", -1,
"1", NULL);
6611 ERRMSG(
"Set RNG_TYPE to 0, 1, or 2!");
6614 ctl->
advect = (int)
scan_ctl(filename, argc, argv,
"ADVECT", -1,
"2", NULL);
6618 ERRMSG(
"Set ADVECT to 0, 1, 2, or 4!");
6622 = (int)
scan_ctl(filename, argc, argv,
"DIFFUSION", -1,
"0", NULL);
6624 ERRMSG(
"Set DIFFUSION to 0, 1 or 2!");
6626 scan_ctl(filename, argc, argv,
"TURB_DX_PBL", -1,
"50", NULL);
6628 scan_ctl(filename, argc, argv,
"TURB_DX_TROP", -1,
"50", NULL);
6630 scan_ctl(filename, argc, argv,
"TURB_DX_STRAT", -1,
"0", NULL);
6632 scan_ctl(filename, argc, argv,
"TURB_DZ_PBL", -1,
"0", NULL);
6634 scan_ctl(filename, argc, argv,
"TURB_DZ_TROP", -1,
"0", NULL);
6636 scan_ctl(filename, argc, argv,
"TURB_DZ_STRAT", -1,
"0.1", NULL);
6638 scan_ctl(filename, argc, argv,
"TURB_MESOX", -1,
"0.16", NULL);
6640 scan_ctl(filename, argc, argv,
"TURB_MESOZ", -1,
"0.16", NULL);
6644 = (int)
scan_ctl(filename, argc, argv,
"CONV_MIX_PBL", -1,
"0", NULL);
6646 =
scan_ctl(filename, argc, argv,
"CONV_PBL_TRANS", -1,
"0", NULL);
6648 =
scan_ctl(filename, argc, argv,
"CONV_CAPE", -1,
"-999", NULL);
6650 =
scan_ctl(filename, argc, argv,
"CONV_CIN", -1,
"-999", NULL);
6651 ctl->
conv_dt =
scan_ctl(filename, argc, argv,
"CONV_DT", -1,
"-999", NULL);
6655 scan_ctl(filename, argc, argv,
"BOUND_MASS", -1,
"-999", NULL);
6657 scan_ctl(filename, argc, argv,
"BOUND_MASS_TREND", -1,
"0", NULL);
6659 scan_ctl(filename, argc, argv,
"BOUND_VMR", -1,
"-999", NULL);
6661 scan_ctl(filename, argc, argv,
"BOUND_VMR_TREND", -1,
"0", NULL);
6663 scan_ctl(filename, argc, argv,
"BOUND_LAT0", -1,
"-999", NULL);
6665 scan_ctl(filename, argc, argv,
"BOUND_LAT1", -1,
"-999", NULL);
6667 scan_ctl(filename, argc, argv,
"BOUND_P0", -1,
"-999", NULL);
6669 scan_ctl(filename, argc, argv,
"BOUND_P1", -1,
"-999", NULL);
6671 scan_ctl(filename, argc, argv,
"BOUND_DPS", -1,
"-999", NULL);
6673 scan_ctl(filename, argc, argv,
"BOUND_DZS", -1,
"-999", NULL);
6675 scan_ctl(filename, argc, argv,
"BOUND_ZETAS", -1,
"-999", NULL);
6677 (int)
scan_ctl(filename, argc, argv,
"BOUND_PBL", -1,
"0", NULL);
6681 if (strcasecmp(ctl->
species,
"CF2Cl2") == 0) {
6685 }
else if (strcasecmp(ctl->
species,
"CFCl3") == 0) {
6689 }
else if (strcasecmp(ctl->
species,
"CH4") == 0) {
6696 }
else if (strcasecmp(ctl->
species,
"CO") == 0) {
6705 }
else if (strcasecmp(ctl->
species,
"CO2") == 0) {
6709 }
else if (strcasecmp(ctl->
species,
"H2O") == 0) {
6711 }
else if (strcasecmp(ctl->
species,
"N2O") == 0) {
6715 }
else if (strcasecmp(ctl->
species,
"NH3") == 0) {
6722 }
else if (strcasecmp(ctl->
species,
"HNO3") == 0) {
6726 }
else if (strcasecmp(ctl->
species,
"NO") == 0) {
6735 }
else if (strcasecmp(ctl->
species,
"NO2") == 0) {
6744 }
else if (strcasecmp(ctl->
species,
"O3") == 0) {
6751 }
else if (strcasecmp(ctl->
species,
"SF6") == 0) {
6755 }
else if (strcasecmp(ctl->
species,
"SO2") == 0) {
6768 sprintf(defstr,
"%g", ctl->
molmass);
6769 ctl->
molmass =
scan_ctl(filename, argc, argv,
"MOLMASS", -1, defstr, NULL);
6774 (int)
scan_ctl(filename, argc, argv,
"OH_CHEM_REACTION", -1, defstr,
6776 for (
int ip = 0; ip < 4; ip++) {
6777 sprintf(defstr,
"%g", ctl->
oh_chem[ip]);
6779 scan_ctl(filename, argc, argv,
"OH_CHEM", ip, defstr, NULL);
6782 scan_ctl(filename, argc, argv,
"OH_CHEM_BETA", -1,
"0", NULL);
6786 (int)
scan_ctl(filename, argc, argv,
"H2O2_CHEM_REACTION", -1,
"0", NULL);
6790 (int)
scan_ctl(filename, argc, argv,
"KPP_CHEM", -1,
"0", NULL);
6791 ctl->
dt_kpp =
scan_ctl(filename, argc, argv,
"DT_KPP", -1,
"1800", NULL);
6795 (int)
scan_ctl(filename, argc, argv,
"TRACER_CHEM", -1,
"0", NULL);
6799 (int)
scan_ctl(filename, argc, argv,
"RADIO_DECAY", -1,
"0", NULL);
6802 for (
int ip = 0; ip < 2; ip++) {
6805 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_H", ip, defstr, NULL);
6807 for (
int ip = 0; ip < 1; ip++) {
6810 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_H", ip, defstr, NULL);
6813 scan_ctl(filename, argc, argv,
"WET_DEPO_SO2_PH", -1,
"0", NULL);
6815 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_A", -1,
"0", NULL);
6817 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_B", -1,
"0", NULL);
6819 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_A", -1,
"0", NULL);
6821 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_B", -1,
"0", NULL);
6823 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 0,
"0.5", NULL);
6825 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 1,
"0.36", NULL);
6827 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_RET_RATIO", -1,
"1", NULL);
6829 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_RET_RATIO", -1,
"1", NULL);
6833 scan_ctl(filename, argc, argv,
"DRY_DEPO_VDEP", -1,
"0", NULL);
6835 scan_ctl(filename, argc, argv,
"DRY_DEPO_DP", -1,
"30", NULL);
6838 scan_ctl(filename, argc, argv,
"CLIM_PHOTO", -1,
6839 "../../data/clams_photolysis_rates.nc", ctl->
clim_photo);
6840 scan_ctl(filename, argc, argv,
"CLIM_HNO3_FILENAME", -1,
6842 scan_ctl(filename, argc, argv,
"CLIM_OH_FILENAME", -1,
6844 scan_ctl(filename, argc, argv,
"CLIM_H2O2_FILENAME", -1,
6846 scan_ctl(filename, argc, argv,
"CLIM_HO2_FILENAME", -1,
6848 scan_ctl(filename, argc, argv,
"CLIM_O1D_FILENAME", -1,
6850 scan_ctl(filename, argc, argv,
"CLIM_CCL4_TIMESERIES", -1,
6852 scan_ctl(filename, argc, argv,
"CLIM_CCL3F_TIMESERIES", -1,
6854 scan_ctl(filename, argc, argv,
"CLIM_CCL2F2_TIMESERIES", -1,
6856 scan_ctl(filename, argc, argv,
"CLIM_N2O_TIMESERIES", -1,
6858 scan_ctl(filename, argc, argv,
"CLIM_SF6_TIMESERIES", -1,
6863 scan_ctl(filename, argc, argv,
"MIXING_DT", -1,
"3600.", NULL);
6865 scan_ctl(filename, argc, argv,
"MIXING_TROP", -1,
"-999", NULL);
6867 scan_ctl(filename, argc, argv,
"MIXING_STRAT", -1,
"-999", NULL);
6869 scan_ctl(filename, argc, argv,
"MIXING_Z0", -1,
"-5", NULL);
6871 scan_ctl(filename, argc, argv,
"MIXING_Z1", -1,
"85", NULL);
6873 (int)
scan_ctl(filename, argc, argv,
"MIXING_NZ", -1,
"90", NULL);
6875 scan_ctl(filename, argc, argv,
"MIXING_LON0", -1,
"-180", NULL);
6877 scan_ctl(filename, argc, argv,
"MIXING_LON1", -1,
"180", NULL);
6879 (int)
scan_ctl(filename, argc, argv,
"MIXING_NX", -1,
"360", NULL);
6881 scan_ctl(filename, argc, argv,
"MIXING_LAT0", -1,
"-90", NULL);
6883 scan_ctl(filename, argc, argv,
"MIXING_LAT1", -1,
"90", NULL);
6885 (int)
scan_ctl(filename, argc, argv,
"MIXING_NY", -1,
"180", NULL);
6889 scan_ctl(filename, argc, argv,
"CHEMGRID_Z0", -1,
"-5", NULL);
6891 scan_ctl(filename, argc, argv,
"CHEMGRID_Z1", -1,
"85", NULL);
6893 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NZ", -1,
"90", NULL);
6895 scan_ctl(filename, argc, argv,
"CHEMGRID_LON0", -1,
"-180", NULL);
6897 scan_ctl(filename, argc, argv,
"CHEMGRID_LON1", -1,
"180", NULL);
6899 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NX", -1,
"360", NULL);
6901 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT0", -1,
"-90", NULL);
6903 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT1", -1,
"90", NULL);
6905 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NY", -1,
"180", NULL);
6910 scan_ctl(filename, argc, argv,
"TDEC_STRAT", -1,
"0", NULL);
6913 ctl->
psc_h2o =
scan_ctl(filename, argc, argv,
"PSC_H2O", -1,
"4e-6", NULL);
6915 scan_ctl(filename, argc, argv,
"PSC_HNO3", -1,
"9e-9", NULL);
6921 scan_ctl(filename, argc, argv,
"ATM_DT_OUT", -1,
"86400", NULL);
6923 (int)
scan_ctl(filename, argc, argv,
"ATM_FILTER", -1,
"0", NULL);
6925 (int)
scan_ctl(filename, argc, argv,
"ATM_STRIDE", -1,
"1", NULL);
6927 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE", -1,
"0", NULL);
6929 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE_OUT", -1,
"-1", NULL);
6933 (int)
scan_ctl(filename, argc, argv,
"ATM_NC_LEVEL", -1,
"0", NULL);
6934 for (
int iq = 0; iq < ctl->
nq; iq++)
6936 (
int)
scan_ctl(filename, argc, argv,
"ATM_NC_QUANT", iq,
"0", NULL);
6938 (int)
scan_ctl(filename, argc, argv,
"OBS_TYPE", -1,
"0", NULL);
6944 scan_ctl(filename, argc, argv,
"CSI_DT_OUT", -1,
"86400", NULL);
6947 scan_ctl(filename, argc, argv,
"CSI_OBSMIN", -1,
"0", NULL);
6949 scan_ctl(filename, argc, argv,
"CSI_MODMIN", -1,
"0", NULL);
6950 ctl->
csi_z0 =
scan_ctl(filename, argc, argv,
"CSI_Z0", -1,
"-5", NULL);
6951 ctl->
csi_z1 =
scan_ctl(filename, argc, argv,
"CSI_Z1", -1,
"85", NULL);
6952 ctl->
csi_nz = (int)
scan_ctl(filename, argc, argv,
"CSI_NZ", -1,
"1", NULL);
6954 scan_ctl(filename, argc, argv,
"CSI_LON0", -1,
"-180", NULL);
6955 ctl->
csi_lon1 =
scan_ctl(filename, argc, argv,
"CSI_LON1", -1,
"180", NULL);
6957 (int)
scan_ctl(filename, argc, argv,
"CSI_NX", -1,
"360", NULL);
6958 ctl->
csi_lat0 =
scan_ctl(filename, argc, argv,
"CSI_LAT0", -1,
"-90", NULL);
6959 ctl->
csi_lat1 =
scan_ctl(filename, argc, argv,
"CSI_LAT1", -1,
"90", NULL);
6961 (int)
scan_ctl(filename, argc, argv,
"CSI_NY", -1,
"180", NULL);
6964 ctl->
nens = (int)
scan_ctl(filename, argc, argv,
"NENS", -1,
"0", NULL);
6967 scan_ctl(filename, argc, argv,
"ENS_DT_OUT", -1,
"86400", NULL);
6970 scan_ctl(filename, argc, argv,
"GRID_BASENAME", -1,
"-",
6975 scan_ctl(filename, argc, argv,
"GRID_DT_OUT", -1,
"86400", NULL);
6977 (int)
scan_ctl(filename, argc, argv,
"GRID_SPARSE", -1,
"0", NULL);
6979 (int)
scan_ctl(filename, argc, argv,
"GRID_NC_LEVEL", -1,
"0", NULL);
6980 for (
int iq = 0; iq < ctl->
nq; iq++)
6982 (
int)
scan_ctl(filename, argc, argv,
"GRID_NC_QUANT", iq,
"0", NULL);
6984 (int)
scan_ctl(filename, argc, argv,
"GRID_STDDEV", -1,
"0", NULL);
6985 ctl->
grid_z0 =
scan_ctl(filename, argc, argv,
"GRID_Z0", -1,
"-5", NULL);
6986 ctl->
grid_z1 =
scan_ctl(filename, argc, argv,
"GRID_Z1", -1,
"85", NULL);
6988 (int)
scan_ctl(filename, argc, argv,
"GRID_NZ", -1,
"1", NULL);
6990 scan_ctl(filename, argc, argv,
"GRID_LON0", -1,
"-180", NULL);
6992 scan_ctl(filename, argc, argv,
"GRID_LON1", -1,
"180", NULL);
6994 (int)
scan_ctl(filename, argc, argv,
"GRID_NX", -1,
"360", NULL);
6996 scan_ctl(filename, argc, argv,
"GRID_LAT0", -1,
"-90", NULL);
6998 scan_ctl(filename, argc, argv,
"GRID_LAT1", -1,
"90", NULL);
7000 (int)
scan_ctl(filename, argc, argv,
"GRID_NY", -1,
"180", NULL);
7002 (int)
scan_ctl(filename, argc, argv,
"GRID_TYPE", -1,
"0", NULL);
7005 scan_ctl(filename, argc, argv,
"PROF_BASENAME", -1,
"-",
7008 ctl->
prof_z0 =
scan_ctl(filename, argc, argv,
"PROF_Z0", -1,
"0", NULL);
7009 ctl->
prof_z1 =
scan_ctl(filename, argc, argv,
"PROF_Z1", -1,
"60", NULL);
7011 (int)
scan_ctl(filename, argc, argv,
"PROF_NZ", -1,
"60", NULL);
7013 scan_ctl(filename, argc, argv,
"PROF_LON0", -1,
"-180", NULL);
7015 scan_ctl(filename, argc, argv,
"PROF_LON1", -1,
"180", NULL);
7017 (int)
scan_ctl(filename, argc, argv,
"PROF_NX", -1,
"360", NULL);
7019 scan_ctl(filename, argc, argv,
"PROF_LAT0", -1,
"-90", NULL);
7021 scan_ctl(filename, argc, argv,
"PROF_LAT1", -1,
"90", NULL);
7023 (int)
scan_ctl(filename, argc, argv,
"PROF_NY", -1,
"180", NULL);
7026 scan_ctl(filename, argc, argv,
"SAMPLE_BASENAME", -1,
"-",
7028 scan_ctl(filename, argc, argv,
"SAMPLE_KERNEL", -1,
"-",
7030 scan_ctl(filename, argc, argv,
"SAMPLE_OBSFILE", -1,
"-",
7033 scan_ctl(filename, argc, argv,
"SAMPLE_DX", -1,
"50", NULL);
7035 scan_ctl(filename, argc, argv,
"SAMPLE_DZ", -1,
"-999", NULL);
7038 scan_ctl(filename, argc, argv,
"STAT_BASENAME", -1,
"-",
7042 ctl->
stat_r =
scan_ctl(filename, argc, argv,
"STAT_R", -1,
"50", NULL);
7044 scan_ctl(filename, argc, argv,
"STAT_T0", -1,
"-1e100", NULL);
7045 ctl->
stat_t1 =
scan_ctl(filename, argc, argv,
"STAT_T1", -1,
"1e100", NULL);
7050 scan_ctl(filename, argc, argv,
"VTK_DT_OUT", -1,
"86400", NULL);
7052 (int)
scan_ctl(filename, argc, argv,
"VTK_STRIDE", -1,
"1", NULL);
7054 scan_ctl(filename, argc, argv,
"VTK_SCALE", -1,
"1.0", NULL);
7056 scan_ctl(filename, argc, argv,
"VTK_OFFSET", -1,
"0.0", NULL);
7058 (int)
scan_ctl(filename, argc, argv,
"VTK_SPHERE", -1,
"0", NULL);
7061 ctl->
dd = (int)
scan_ctl(filename, argc, argv,
"DD", -1,
"0", NULL);
7063 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_MERIDIONAL", -1,
7064 (ctl->
dd == 1) ?
"2" :
"1", NULL);
7066 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_ZONAL", -1,
7067 (ctl->
dd == 1) ?
"2" :
"1", NULL);
7070 else if (ctl->
dd == 1)
7071 ERRMSG(
"Please provide zonal and meridional subdomain numbers!");
7073 (int)
scan_ctl(filename, argc, argv,
"DD_HALOS_SIZE", -1,
"1", NULL);
7079 const char *filename,
7086 LOG(1,
"Read meteo data: %s", filename);
7092 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
7120 ERRMSG(
"MET_TYPE not implemented!");
7174 LOG(2,
"Broadcast data on rank %d...", rank);
7308 ERRMSG(
"Code was compiled without DD!");
7320 ERRMSG(
"Code was compiled without KPP!");
7353#pragma acc update device(ctl[:1])
7357 if (cache != NULL) {
7360#pragma acc update device(cache[:1])
7367#pragma acc update device(clim[:1])
7374 met_t *met0up = *met0;
7375#pragma acc update device(met0up[:1])
7382 met_t *met1up = *met1;
7383#pragma acc update device(met1up[:1])
7390#pragma acc update device(atm[:1])
7409#pragma acc update host(ctl[:1])
7413 if (cache != NULL) {
7416#pragma acc update host(cache[:1])
7423#pragma acc update host(clim[:1])
7430 met_t *met0up = *met0;
7431#pragma acc update host(met0up[:1])
7438 met_t *met1up = *met1;
7439#pragma acc update host(met1up[:1])
7446#pragma acc update host(atm[:1])
7454 const char *filename,
7463 LOG(1,
"Write atmospheric data: %s", filename);
7487 ERRMSG(
"Atmospheric data type not supported!");
7491 LOG(2,
"Number of particles: %d", atm->
np);
7492 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
7493 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
7494 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
7495 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
7496 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
7497 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
7498 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
7499 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
7500 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
7501 for (
int iq = 0; iq < ctl->
nq; iq++) {
7503 sprintf(msg,
"Quantity %s range: %s ... %s %s",
7506 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
7507 LOG(2, msg, mini, maxi);
7514 const char *filename,
7522 LOG(1,
"Write meteo data: %s", filename);
7527 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
7531 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
7535 ERRMSG(
"MPTRAC was compiled without LZ4 compression!");
7539 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
7543 ERRMSG(
"MPTRAC was compiled without SZ3 compression!");
7557 ERRMSG(
"MET_TYPE not implemented!");
7563 const char *dirname,
7570 char ext[10], filename[2 *
LEN];
7574 int year, mon, day, hour, min, sec;
7577 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
7592 sprintf(ext,
"tab");
7594 sprintf(ext,
"bin");
7597 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
7598 dirname, ctl->
atm_basename, year, mon, day, hour, min, ext);
7604 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
7607 write_grid(filename, ctl, met0, met1, atm, t);
7612 sprintf(filename,
"%s/%s.tab", dirname, ctl->
csi_basename);
7618 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.tab",
7619 dirname, ctl->
ens_basename, year, mon, day, hour, min);
7625 sprintf(filename,
"%s/%s.tab", dirname, ctl->
prof_basename);
7626 write_prof(filename, ctl, met0, met1, atm, t);
7637 sprintf(filename,
"%s/%s.tab", dirname, ctl->
stat_basename);
7646 sprintf(filename,
"%s/%s_%05d.vtk", dirname, ctl->
vtk_basename, ++nvtk);
7656 const double hno3) {
7659 const double h2o_help =
MAX(h2o, 0.1e-6);
7662 const double p_hno3 = hno3 * p / 1.333224;
7663 const double p_h2o = h2o_help * p / 1.333224;
7664 const double a = 0.009179 - 0.00088 * log10(p_h2o);
7665 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
7666 const double c = -11397.0 / a;
7667 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
7668 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
7686 const double p0 = pbl;
7689 if (atm->
p[ip] > p0)
7691 else if (atm->
p[ip] < p1)
7694 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
7700 const char *filename,
7706 if (!(in = fopen(filename,
"r"))) {
7707 WARN(
"Cannot open file!");
7713 while (fgets(line,
LEN, in)) {
7717 TOK(line, tok,
"%lg", atm->
time[atm->
np]);
7718 TOK(NULL, tok,
"%lg", atm->
p[atm->
np]);
7719 TOK(NULL, tok,
"%lg", atm->
lon[atm->
np]);
7720 TOK(NULL, tok,
"%lg", atm->
lat[atm->
np]);
7721 for (
int iq = 0; iq < ctl->
nq; iq++)
7722 TOK(NULL, tok,
"%lg", atm->
q[iq][atm->
np]);
7725 atm->
p[atm->
np] =
P(atm->
p[atm->
np]);
7728 if ((++atm->
np) >
NP)
7729 ERRMSG(
"Too many data points!");
7742 const char *filename,
7748 if (!(in = fopen(filename,
"r")))
7753 FREAD(&version,
int,
7757 ERRMSG(
"Wrong version of binary data!");
7775 for (
int iq = 0; iq < ctl->
nq; iq++)
7776 FREAD(atm->
q[iq],
double,
7786 ERRMSG(
"Error while reading binary data!");
7798 const char *filename,
7805 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
7812 if (nc_inq_varid(ncid,
"TIME_INIT", &varid) == NC_NOERR) {
7813 NC(nc_get_var_double(ncid, varid, atm->
time));
7815 WARN(
"TIME_INIT not found use time instead!");
7818 for (
int ip = 0; ip < atm->
np; ip++) {
7819 atm->
time[ip] = time_init;
7831 if (nc_inq_varid(ncid,
"PRESS_INIT", &varid) == NC_NOERR) {
7832 NC(nc_get_var_double(ncid, varid, atm->
p));
7834 WARN(
"PRESS_INIT not found use PRESS instead!");
7835 nc_inq_varid(ncid,
"PRESS", &varid);
7836 NC(nc_get_var_double(ncid, varid, atm->
p));
7841 for (
int iq = 0; iq < ctl->
nq; iq++)
7858 const char *filename,
7865 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
7878 for (
int iq = 0; iq < ctl->
nq; iq++)
7891 const char *filename,
7897 LOG(1,
"Read photolysis rates: %s", filename);
7900 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
7901 WARN(
"Photolysis rate data are missing!");
7908 if (photo->
p[0] < photo->
p[1])
7909 ERRMSG(
"Pressure data are not descending!");
7914 if (photo->
o3c[0] > photo->
o3c[1])
7915 ERRMSG(
"Total column ozone data are not ascending!");
7920 if (photo->
sza[0] > photo->
sza[1])
7921 ERRMSG(
"Solar zenith angle data are not ascending!");
7938 LOG(2,
"Number of pressure levels: %d", photo->
np);
7939 LOG(2,
"Altitude levels: %g, %g ... %g km",
7940 Z(photo->
p[0]),
Z(photo->
p[1]),
Z(photo->
p[photo->
np - 1]));
7941 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
7942 photo->
p[0], photo->
p[1], photo->
p[photo->
np - 1]);
7943 LOG(2,
"Number of solar zenith angles: %d", photo->
nsza);
7944 LOG(2,
"Solar zenith angles: %g, %g ... %g deg",
7947 LOG(2,
"Number of total column ozone values: %d", photo->
no3c);
7948 LOG(2,
"Total column ozone: %g, %g ... %g DU",
7950 LOG(2,
"N2O photolysis rate: %g, %g ... %g s**-1",
7951 photo->
n2o[0][0][0], photo->
n2o[1][0][0],
7952 photo->
n2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7953 LOG(2,
"CCl4 photolysis rate: %g, %g ... %g s**-1",
7954 photo->
ccl4[0][0][0], photo->
ccl4[1][0][0],
7956 LOG(2,
"CFC-11 photolysis rate: %g, %g ... %g s**-1",
7957 photo->
ccl3f[0][0][0], photo->
ccl3f[1][0][0],
7959 LOG(2,
"CFC-12 photolysis rate: %g, %g ... %g s**-1",
7962 LOG(2,
"O2 photolysis rate: %g, %g ... %g s**-1",
7963 photo->
o2[0][0][0], photo->
o2[1][0][0],
7964 photo->
o2[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7965 LOG(2,
"O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
7966 photo->
o3_1[0][0][0], photo->
o3_1[1][0][0],
7968 LOG(2,
"O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
7969 photo->
o3_2[0][0][0], photo->
o3_2[1][0][0],
7971 LOG(2,
"H2O2 photolysis rate: %g, %g ... %g s**-1",
7972 photo->
h2o2[0][0][0], photo->
h2o2[1][0][0],
7974 LOG(2,
"H2O photolysis rate: %g, %g ... %g s**-1",
7975 photo->
h2o[0][0][0], photo->
h2o[1][0][0],
7976 photo->
h2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7983 const char *varname,
7997 for (
int ip = 0; ip < photo->
np; ip++)
7998 for (
int is = 0; is < photo->
nsza; is++)
7999 for (
int io = 0; io < photo->
no3c; io++)
8010 const char *filename,
8014 LOG(1,
"Read climatological time series: %s", filename);
8018 if (!(in = fopen(filename,
"r"))) {
8019 WARN(
"Cannot open file!");
8026 while (fgets(line,
LEN, in))
8027 if (sscanf(line,
"%lg %lg", &ts->
time[nh], &ts->
vmr[nh]) == 2) {
8030 ts->
time[nh] = (ts->
time[nh] - 2000.0) * 365.25 * 86400.;
8033 if (nh > 0 && ts->
time[nh] <= ts->
time[nh - 1])
8034 ERRMSG(
"Time series must be ascending!");
8038 ERRMSG(
"Too many data points!");
8047 ERRMSG(
"Not enough data points!");
8050 LOG(2,
"Number of time steps: %d", ts->
ntime);
8051 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s", ts->
time[0], ts->
time[1],
8053 LOG(2,
"Volume mixing ratio range: %g ... %g ppv",
8054 gsl_stats_min(ts->
vmr, 1, (
size_t) nh), gsl_stats_max(ts->
vmr, 1,
8064 const char *filename,
8065 const char *varname,
8068 int ncid, varid, it, iy, iz, iz2, nt;
8070 double *help, varmin = 1e99, varmax = -1e99;
8073 LOG(1,
"Read %s data: %s", varname, filename);
8076 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
8077 WARN(
"%s climatology data are missing!", varname);
8084 if (zm->
p[0] < zm->
p[1])
8085 ERRMSG(
"Pressure data are not descending!");
8090 if (zm->
lat[0] > zm->
lat[1])
8091 ERRMSG(
"Latitude data are not ascending!");
8095 zm->
time[0] = 1209600.00;
8096 zm->
time[1] = 3888000.00;
8097 zm->
time[2] = 6393600.00;
8098 zm->
time[3] = 9072000.00;
8099 zm->
time[4] = 11664000.00;
8100 zm->
time[5] = 14342400.00;
8101 zm->
time[6] = 16934400.00;
8102 zm->
time[7] = 19612800.00;
8103 zm->
time[8] = 22291200.00;
8104 zm->
time[9] = 24883200.00;
8105 zm->
time[10] = 27561600.00;
8106 zm->
time[11] = 30153600.00;
8115 for (it = 0; it < zm->
ntime; it++)
8116 for (iz = 0; iz < zm->
np; iz++)
8117 for (iy = 0; iy < zm->
nlat; iy++)
8122 for (it = 0; it < zm->
ntime; it++)
8123 for (iy = 0; iy < zm->
nlat; iy++)
8124 for (iz = 0; iz < zm->
np; iz++) {
8125 if (zm->
vmr[it][iz][iy] < 0) {
8126 for (iz2 = 0; iz2 < zm->
np; iz2++)
8127 if (zm->
vmr[it][iz2][iy] >= 0) {
8128 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
8131 for (iz2 = zm->
np - 1; iz2 >= 0; iz2--)
8132 if (zm->
vmr[it][iz2][iy] >= 0) {
8133 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
8137 varmin =
MIN(varmin, zm->
vmr[it][iz][iy]);
8138 varmax =
MAX(varmax, zm->
vmr[it][iz][iy]);
8145 LOG(2,
"Number of time steps: %d", zm->
ntime);
8146 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
8148 LOG(2,
"Number of pressure levels: %d", zm->
np);
8149 LOG(2,
"Altitude levels: %g, %g ... %g km",
8150 Z(zm->
p[0]),
Z(zm->
p[1]),
Z(zm->
p[zm->
np - 1]));
8151 LOG(2,
"Pressure levels: %g, %g ... %g hPa", zm->
p[0],
8152 zm->
p[1], zm->
p[zm->
np - 1]);
8153 LOG(2,
"Number of latitudes: %d", zm->
nlat);
8154 LOG(2,
"Latitudes: %g, %g ... %g deg",
8156 LOG(2,
"%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
8163 const char *filename,
8169 LOG(1,
"Read kernel function: %s", filename);
8173 if (!(in = fopen(filename,
"r")))
8174 ERRMSG(
"Cannot open file!");
8179 while (fgets(line,
LEN, in))
8180 if (sscanf(line,
"%lg %lg", &kz[n], &kw[n]) == 2) {
8181 if (n > 0 && kz[n] < kz[n - 1])
8182 ERRMSG(
"Height levels must be ascending!");
8184 ERRMSG(
"Too many height levels!");
8193 ERRMSG(
"Not enough height levels!");
8196 const double kmax = gsl_stats_max(kw, 1, (
size_t) n);
8197 for (
int iz = 0; iz < n; iz++)
8204 const char *filename,
8212 int year, mon, day, hour, min, sec;
8218 if (!(in = fopen(filename,
"r"))) {
8219 WARN(
"Cannot open file!");
8225 FREAD(&met_type,
int,
8229 ERRMSG(
"Wrong MET_TYPE of binary data!");
8233 FREAD(&version,
int,
8237 ERRMSG(
"Wrong version of binary data!");
8243 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
8244 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
8245 met->
time, year, mon, day, hour, min);
8246 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
8247 || day < 1 || day > 31 || hour < 0 || hour > 23)
8248 ERRMSG(
"Error while reading time!");
8254 LOG(2,
"Number of longitudes: %d", met->
nx);
8255 if (met->
nx < 2 || met->
nx >
EX)
8256 ERRMSG(
"Number of longitudes out of range!");
8261 LOG(2,
"Number of latitudes: %d", met->
ny);
8262 if (met->
ny < 2 || met->
ny >
EY)
8263 ERRMSG(
"Number of latitudes out of range!");
8268 LOG(2,
"Number of levels: %d", met->
np);
8269 if (met->
np < 2 || met->
np >
EP)
8270 ERRMSG(
"Number of levels out of range!");
8276 LOG(2,
"Longitudes: %g, %g ... %g deg",
8282 LOG(2,
"Latitudes: %g, %g ... %g deg",
8288 LOG(2,
"Altitude levels: %g, %g ... %g km",
8289 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
8290 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
8291 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
8340 ERRMSG(
"Error while reading binary data!");
8355 const char *varname) {
8364 LOG(2,
"Read 2-D variable: %s (uncompressed)", varname);
8366 (
size_t) (met->
nx * met->
ny),
8370 for (
int ix = 0; ix < met->
nx; ix++)
8371 for (
int iy = 0; iy < met->
ny; iy++)
8372 var[ix][iy] = help[
ARRAY_2D(ix, iy, met->
ny)];
8385 const char *varname,
8386 const float bound_min,
8387 const float bound_max) {
8399 LOG(2,
"Read 3-D variable: %s (uncompressed)", varname);
8401 (
size_t) (met->
nx * met->
ny * met->
np),
8415 FREAD(&precision,
int,
8420 FREAD(&tolerance,
double,
8428 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
8439 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
8449 ERRMSG(
"MPTRAC was compiled without LZ4 compression!");
8457 (
size_t) met->
np, met->
p, 1, NULL, in);
8459 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
8467 FREAD(&precision,
int,
8472 FREAD(&tolerance,
double,
8480 ERRMSG(
"MPTRAC was compiled without sz3 compression!");
8485#pragma omp parallel for default(shared) collapse(2)
8486 for (
int ix = 0; ix < met->
nx; ix++)
8487 for (
int iy = 0; iy < met->
ny; iy++)
8488 for (
int ip = 0; ip < met->
np; ip++) {
8489 var[ix][iy][ip] = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
8490 if (var[ix][iy][ip] < bound_min)
8491 var[ix][iy][ip] = bound_min;
8492 else if (var[ix][iy][ip] > bound_max)
8493 var[ix][iy][ip] = bound_max;
8513 LOG(2,
"Calculate CAPE...");
8516 const double pfac = 1.01439, dz0 =
RI /
MA /
G0 * log(pfac);
8519#pragma omp parallel for default(shared) collapse(2)
8520 for (
int ix = 0; ix < met->
nx; ix++)
8521 for (
int iy = 0; iy < met->
ny; iy++) {
8525 double h2o = 0, t, theta = 0;
8526 double pbot =
MIN(met->
ps[ix][iy], met->
p[0]);
8527 double ptop = pbot - 50.;
8528 for (
int ip = 0; ip < met->
np; ip++) {
8529 if (met->
p[ip] <= pbot) {
8530 theta +=
THETA(met->
p[ip], met->
t[ix][iy][ip]);
8531 h2o += met->
h2o[ix][iy][ip];
8534 if (met->
p[ip] < ptop && n > 0)
8541 met->
plcl[ix][iy] = NAN;
8542 met->
plfc[ix][iy] = NAN;
8543 met->
pel[ix][iy] = NAN;
8544 met->
cape[ix][iy] = NAN;
8545 met->
cin[ix][iy] = NAN;
8551 pbot = met->
ps[ix][iy];
8553 met->
plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
8554 t = theta / pow(1000. / met->
plcl[ix][iy], 0.286);
8555 if (
RH(met->
plcl[ix][iy], t, h2o) > 100.)
8556 ptop = met->
plcl[ix][iy];
8558 pbot = met->
plcl[ix][iy];
8559 }
while (pbot - ptop > 0.1);
8563 double dcape, dz, h2o_env, t_env;
8564 double p = met->
ps[ix][iy];
8565 met->
cape[ix][iy] = met->
cin[ix][iy] = 0;
8567 dz = dz0 *
TVIRT(t, h2o);
8569 t = theta / pow(1000. / p, 0.286);
8573 &h2o_env, ci, cw, 0);
8574 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
8575 TVIRT(t_env, h2o_env) * dz;
8577 met->
cin[ix][iy] += fabsf((
float) dcape);
8578 }
while (p > met->
plcl[ix][iy]);
8583 p = met->
plcl[ix][iy];
8584 t = theta / pow(1000. / p, 0.286);
8587 dz = dz0 *
TVIRT(t, h2o);
8590 double psat =
PSAT(t);
8591 h2o = psat / (p - (1. -
EPS) * psat);
8595 &h2o_env, ci, cw, 0);
8596 double dcape_old = dcape;
8597 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
8598 TVIRT(t_env, h2o_env) * dz;
8600 met->
cape[ix][iy] += (float) dcape;
8601 if (!isfinite(met->
plfc[ix][iy]))
8602 met->
plfc[ix][iy] = (
float) p;
8603 }
else if (dcape_old > 0)
8604 met->
pel[ix][iy] = (float) p;
8605 if (dcape < 0 && !isfinite(met->
plfc[ix][iy]))
8606 met->
cin[ix][iy] += fabsf((
float) dcape);
8610 if (!isfinite(met->
plfc[ix][iy]))
8611 met->
cin[ix][iy] = NAN;
8622 LOG(2,
"Calculate cloud data...");
8625 const double ccmin = 0.01, cwmin = 1e-6;
8628#pragma omp parallel for default(shared) collapse(2)
8629 for (
int ix = 0; ix < met->
nx; ix++)
8630 for (
int iy = 0; iy < met->
ny; iy++) {
8633 met->
pct[ix][iy] = NAN;
8634 met->
pcb[ix][iy] = NAN;
8635 met->
cl[ix][iy] = 0;
8638 for (
int ip = 0; ip < met->
np - 1; ip++) {
8641 if (met->
p[ip] > met->
ps[ix][iy] || met->
p[ip] <
P(20.))
8645 if (met->
cc[ix][iy][ip] > ccmin
8646 && (met->
lwc[ix][iy][ip] > cwmin
8647 || met->
rwc[ix][iy][ip] > cwmin
8648 || met->
iwc[ix][iy][ip] > cwmin
8649 || met->
swc[ix][iy][ip] > cwmin)) {
8653 = (float) (0.5 * (met->
p[ip] + (
float) met->
p[ip + 1]));
8656 if (!isfinite(met->
pcb[ix][iy]))
8658 = (
float) (0.5 * (met->
p[ip] + met->
p[
MAX(ip - 1, 0)]));
8662 met->
cl[ix][iy] += (float)
8663 (0.5 * (met->
lwc[ix][iy][ip] + met->
lwc[ix][iy][ip + 1]
8664 + met->
rwc[ix][iy][ip] + met->
rwc[ix][iy][ip + 1]
8665 + met->
iwc[ix][iy][ip] + met->
iwc[ix][iy][ip + 1]
8666 + met->
swc[ix][iy][ip] + met->
swc[ix][iy][ip + 1])
8667 * 100. * (met->
p[ip] - met->
p[ip + 1]) /
G0);
8686 LOG(2,
"Detrend meteo data...");
8693 const double tssq = 2. *
SQR(sigma);
8696 int sy = (int) (3. *
DY2DEG(sigma) / fabs(met->
lat[1] - met->
lat[0]));
8700#pragma omp parallel for default(shared) collapse(2)
8701 for (
int ix = 0; ix < met->
nx; ix++) {
8702 for (
int iy = 0; iy < met->
ny; iy++) {
8710 (int) (3. *
DX2DEG(sigma, met->
lat[iy]) /
8711 fabs(met->
lon[1] - met->
lon[0]));
8716 for (
int ip = 0; ip < met->
np; ip++) {
8717 help->
t[ix][iy][ip] = 0;
8718 help->
u[ix][iy][ip] = 0;
8719 help->
v[ix][iy][ip] = 0;
8720 help->
w[ix][iy][ip] = 0;
8724 for (
int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
8728 else if (ix3 >= met->
nx)
8730 for (
int iy2 =
MAX(iy - sy, 0);
8731 iy2 <=
MIN(iy + sy, met->
ny - 1); iy2++) {
8738 const float w = (float) exp(-
DIST2(x0, x1) / tssq);
8742 for (
int ip = 0; ip < met->
np; ip++) {
8743 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip];
8744 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip];
8745 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip];
8746 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip];
8752 for (
int ip = 0; ip < met->
np; ip++) {
8753 help->
t[ix][iy][ip] /= wsum;
8754 help->
u[ix][iy][ip] /= wsum;
8755 help->
v[ix][iy][ip] /= wsum;
8756 help->
w[ix][iy][ip] /= wsum;
8762#pragma omp parallel for default(shared) collapse(3)
8763 for (
int ix = 0; ix < met->
nx; ix++)
8764 for (
int iy = 0; iy < met->
ny; iy++)
8765 for (
int ip = 0; ip < met->
np; ip++) {
8766 met->
t[ix][iy][ip] -= help->
t[ix][iy][ip];
8767 met->
u[ix][iy][ip] -= help->
u[ix][iy][ip];
8768 met->
v[ix][iy][ip] -= help->
v[ix][iy][ip];
8769 met->
w[ix][iy][ip] -= help->
w[ix][iy][ip];
8783 LOG(2,
"Extrapolate meteo data...");
8786#pragma omp parallel for default(shared) collapse(2)
8787 for (
int ix = 0; ix < met->
nx; ix++)
8788 for (
int iy = 0; iy < met->
ny; iy++) {
8792 for (ip0 = met->
np - 1; ip0 >= 0; ip0--)
8793 if (!isfinite(met->
t[ix][iy][ip0])
8794 || !isfinite(met->
u[ix][iy][ip0])
8795 || !isfinite(met->
v[ix][iy][ip0])
8796 || !isfinite(met->
w[ix][iy][ip0]))
8800 for (
int ip = ip0; ip >= 0; ip--) {
8801 met->
t[ix][iy][ip] = met->
t[ix][iy][ip + 1];
8802 met->
u[ix][iy][ip] = met->
u[ix][iy][ip + 1];
8803 met->
v[ix][iy][ip] = met->
v[ix][iy][ip + 1];
8804 met->
w[ix][iy][ip] = met->
w[ix][iy][ip + 1];
8805 met->
h2o[ix][iy][ip] = met->
h2o[ix][iy][ip + 1];
8806 met->
o3[ix][iy][ip] = met->
o3[ix][iy][ip + 1];
8807 met->
lwc[ix][iy][ip] = met->
lwc[ix][iy][ip + 1];
8808 met->
rwc[ix][iy][ip] = met->
rwc[ix][iy][ip + 1];
8809 met->
iwc[ix][iy][ip] = met->
iwc[ix][iy][ip + 1];
8810 met->
swc[ix][iy][ip] = met->
swc[ix][iy][ip + 1];
8811 met->
cc[ix][iy][ip] = met->
cc[ix][iy][ip + 1];
8830 LOG(2,
"Calculate geopotential heights...");
8837#pragma omp parallel for default(shared)
8838 for (
int ip = 0; ip < met->
np; ip++)
8839 logp[ip] = log(met->
p[ip]);
8842#pragma omp parallel for default(shared) collapse(2)
8843 for (
int ix = 0; ix < met->
nx; ix++)
8844 for (
int iy = 0; iy < met->
ny; iy++) {
8847 const double zs = met->
zs[ix][iy];
8848 const double lnps = log(met->
ps[ix][iy]);
8852 const double ts =
LIN(met->
p[ip0], met->
t[ix][iy][ip0], met->
p[ip0 + 1],
8853 met->
t[ix][iy][ip0 + 1], met->
ps[ix][iy]);
8855 LIN(met->
p[ip0], met->
h2o[ix][iy][ip0], met->
p[ip0 + 1],
8856 met->
h2o[ix][iy][ip0 + 1], met->
ps[ix][iy]);
8859 met->
z[ix][iy][ip0 + 1]
8861 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
8862 met->
t[ix][iy][ip0 + 1], met->
h2o[ix][iy][ip0 + 1]));
8863 for (
int ip = ip0 + 2; ip < met->
np; ip++)
8865 = (
float) (met->
z[ix][iy][ip - 1] +
8866 ZDIFF(logp[ip - 1], met->
t[ix][iy][ip - 1],
8867 met->
h2o[ix][iy][ip - 1], logp[ip],
8868 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
8873 ZDIFF(lnps, ts, h2os, logp[ip0],
8874 met->
t[ix][iy][ip0], met->
h2o[ix][iy][ip0]));
8875 for (
int ip = ip0 - 1; ip >= 0; ip--)
8877 = (
float) (met->
z[ix][iy][ip + 1] +
8878 ZDIFF(logp[ip + 1], met->
t[ix][iy][ip + 1],
8879 met->
h2o[ix][iy][ip + 1], logp[ip],
8880 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
8884 if (dx == 0 || dy == 0)
8888 if (dx < 0 || dy < 0) {
8889 if (fabs(met->
lon[1] - met->
lon[0]) < 0.5) {
8899 float ws[dx + 1][dy + 1];
8900#pragma omp parallel for default(shared) collapse(2)
8901 for (
int ix = 0; ix <= dx; ix++)
8902 for (
int iy = 0; iy < dy; iy++)
8903 ws[ix][iy] = (1.0f - (
float) ix / (float) dx)
8904 * (1.0f - (float) iy / (
float) dy);
8907#pragma omp parallel for default(shared) collapse(3)
8908 for (
int ix = 0; ix < met->
nx; ix++)
8909 for (
int iy = 0; iy < met->
ny; iy++)
8910 for (
int ip = 0; ip < met->
np; ip++)
8911 help[
ARRAY_3D(ip, ix, met->
nx, iy, met->
ny)] = met->
z[ix][iy][ip];
8914#pragma omp parallel for default(shared) collapse(3)
8915 for (
int ip = 0; ip < met->
np; ip++)
8916 for (
int ix = 0; ix < met->
nx; ix++)
8917 for (
int iy = 0; iy < met->
ny; iy++) {
8918 float res = 0, wsum = 0;
8919 int iy0 =
MAX(iy - dy + 1, 0);
8920 int iy1 =
MIN(iy + dy - 1, met->
ny - 1);
8921 for (
int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
8925 else if (ix3 >= met->
nx)
8927 for (
int iy2 = iy0; iy2 <= iy1; ++iy2)
8928 if (isfinite(help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)])) {
8929 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
8930 res += w * help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)];
8935 met->
z[ix][iy][ip] = res / wsum;
8937 met->
z[ix][iy][ip] = NAN;
8947 const char *filename,
8953 char levname[
LEN], tstr[10];
8955 double rtime = 0, r, r2;
8957 int varid, ndims, dimids[NC_MAX_DIMS], year2, mon2, day2, hour2, min2, sec2,
8958 year, mon, day, hour, min, sec;
8964 LOG(2,
"Read meteo grid information...");
8973 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
8974 if (nc_inq_varid(ncid,
"time", &varid) == NC_NOERR) {
8975 NC(nc_get_var_double(ncid, varid, &rtime));
8976 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
8977 WARN(
"Time information in meteo file does not match filename!");
8979 WARN(
"Time information in meteo file is missing!");
8990 sprintf(tstr,
"19%.2s", &filename[strlen(filename) - 11]);
8992 sprintf(tstr,
"20%.2s", &filename[strlen(filename) - 11]);
8994 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 9]);
8996 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 7]);
8998 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 5]);
9004 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
9005 || day < 1 || day > 31 || hour < 0 || hour > 23)
9006 ERRMSG(
"Cannot read time from filename!");
9007 jsec2time(met->
time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
9008 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
9009 met->
time, year2, mon2, day2, hour2, min2);
9012 if (nc_inq_varid(ncid,
"u", &varid) != NC_NOERR)
9013 if (nc_inq_varid(ncid,
"U", &varid) != NC_NOERR)
9015 (
"Variable 'u' or 'U' not found, cannot determine vertical dimension!");
9017 NC(nc_inq_varndims(ncid, varid, &ndims));
9018 NC(nc_inq_vardimid(ncid, varid, dimids));
9022 (ncid, dimids[ctl->
met_convention == 0 ? 1 : 3], levname, &dimlen));
9023 }
else if (ndims == 3) {
9025 (ncid, dimids[ctl->
met_convention == 0 ? 0 : 2], levname, &dimlen));
9027 ERRMSG(
"Cannot determine vertical dimension!")
9028 met->
np = (int) dimlen;
9030 LOG(2,
"Number of levels: %d", met->
np);
9031 if (met->
np < 2 || met->
np >
EP)
9032 ERRMSG(
"Number of levels out of range!");
9038 LOG(2,
"Number of longitudes: %d", met->
nx);
9041 LOG(2,
"Number of latitudes: %d", met->
ny);
9045 LOG(2,
"Longitudes: %g, %g ... %g deg",
9048 LOG(2,
"Latitudes: %g, %g ... %g deg",
9061 for (
int ip = 0; ip < met->
np; ip++)
9063 LOG(2,
"Altitude levels: %g, %g ... %g km",
9064 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
9065 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
9066 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
9070 if (strcasecmp(levname,
"hybrid") == 0)
9082 ERRMSG(
"You need to specify MET_NLEV, MET_LEV_HYAM, and MET_LEV_HYBM!");
9083 for (
int ip = 0; ip < ctl->
met_nlev; ip++) {
9091 met->
eta[k] = met->
hyam[k] / 100000.0 + met->
hybm[k];
9093 ERRMSG(
"Eta levels must be ascending!");
9097 for (
int ix = 2; ix < met->
nx; ix++)
9099 (fabs(met->
lon[ix] - met->
lon[ix - 1]) -
9100 fabs(met->
lon[1] - met->
lon[0])) > 0.001)
9101 ERRMSG(
"No regular grid spacing in longitudes!");
9102 for (
int iy = 2; iy < met->
ny; iy++)
9104 (fabs(met->
lat[iy] - met->
lat[iy - 1]) -
9105 fabs(met->
lat[1] - met->
lat[0])) > 0.001) {
9106 WARN(
"No regular grid spacing in latitudes!");
9121 LOG(2,
"Read surface data...");
9125 (ncid,
"lnsp",
"LNSP", NULL, NULL, NULL, NULL, ctl, met, dd, met->
ps,
9127 for (
int ix = 0; ix < met->
nx; ix++)
9128 for (
int iy = 0; iy < met->
ny; iy++)
9129 met->
ps[ix][iy] = (
float) (exp(met->
ps[ix][iy]) / 100.);
9132 (ncid,
"ps",
"PS",
"sp",
"SP", NULL, NULL, ctl, met, dd, met->
ps,
9134 WARN(
"Cannot not read surface pressure data (use lowest level)!");
9135 for (
int ix = 0; ix < met->
nx; ix++)
9136 for (
int iy = 0; iy < met->
ny; iy++)
9138 = (ctl->
met_np > 0 ? (
float) ctl->
met_p[0] : (
float) met->
p[0]);
9146 (ncid,
"z",
"Z", NULL, NULL, NULL, NULL, ctl, met, dd, met->
zs,
9147 (
float) (1. / (1000. *
G0)), 1))
9149 (ncid,
"zm",
"ZM", NULL, NULL, NULL, NULL, ctl, met, dd, met->
zs,
9150 (
float) (1. / 1000.), 1))
9151 WARN(
"Cannot read surface geopotential height!");
9162 memcpy(help, met->
pl,
sizeof(met->
pl));
9164 (ncid,
"gph",
"GPH", NULL, NULL, ctl, met, dd, met->
pl,
9165 (
float) (1e-3 /
G0)))
9166 ERRMSG(
"Cannot read geopotential height!");
9167 for (
int ix = 0; ix < met->
nx; ix++)
9168 for (
int iy = 0; iy < met->
ny; iy++)
9169 met->
zs[ix][iy] = met->
pl[ix][iy][0];
9170 memcpy(met->
pl, help,
sizeof(met->
pl));
9176 (ncid,
"t2m",
"T2M",
"2t",
"2T",
"t2",
"T2", ctl, met, dd, met->
ts, 1.0,
9178 WARN(
"Cannot read surface temperature!");
9182 (ncid,
"u10m",
"U10M",
"10u",
"10U",
"u10",
"U10", ctl, met, dd,
9184 WARN(
"Cannot read surface zonal wind!");
9188 (ncid,
"v10m",
"V10M",
"10v",
"10V",
"v10",
"V10", ctl, met, dd,
9190 WARN(
"Cannot read surface meridional wind!");
9194 (ncid,
"iews",
"IEWS", NULL, NULL, NULL, NULL, ctl, met, dd, met->
ess,
9196 WARN(
"Cannot read eastward turbulent surface stress!");
9200 (ncid,
"inss",
"INSS", NULL, NULL, NULL, NULL, ctl, met, dd, met->
nss,
9202 WARN(
"Cannot read nothward turbulent surface stress!");
9206 (ncid,
"ishf",
"ISHF", NULL, NULL, NULL, NULL, ctl, met, dd, met->
shf,
9208 WARN(
"Cannot read surface sensible heat flux!");
9212 (ncid,
"lsm",
"LSM", NULL, NULL, NULL, NULL, ctl, met, dd, met->
lsm,
9214 WARN(
"Cannot read land-sea mask!");
9218 (ncid,
"sstk",
"SSTK",
"sst",
"SST", NULL, NULL, ctl, met, dd, met->
sst,
9220 WARN(
"Cannot read sea surface temperature!");
9225 (ncid,
"blp",
"BLP", NULL, NULL, NULL, NULL, ctl, met, dd, met->
pbl,
9227 WARN(
"Cannot read planetary boundary layer pressure!");
9230 (ncid,
"blh",
"BLH", NULL, NULL, NULL, NULL, ctl, met, dd, met->
pbl,
9232 WARN(
"Cannot read planetary boundary layer height!");
9237 (ncid,
"cape",
"CAPE", NULL, NULL, NULL, NULL, ctl, met, dd,
9239 WARN(
"Cannot read CAPE!");
9244 (ncid,
"cin",
"CIN", NULL, NULL, NULL, NULL, ctl, met, dd, met->
cin,
9246 WARN(
"Cannot read convective inhibition!");
9259 LOG(2,
"Read level data...");
9263 (ncid,
"t",
"T",
"temp",
"TEMP", ctl, met, dd, met->
t, 1.0))
9264 ERRMSG(
"Cannot read temperature!");
9267 if (!
read_met_nc_3d(ncid,
"u",
"U", NULL, NULL, ctl, met, dd, met->
u, 1.0))
9268 ERRMSG(
"Cannot read zonal wind!");
9269 if (!
read_met_nc_3d(ncid,
"v",
"V", NULL, NULL, ctl, met, dd, met->
v, 1.0))
9270 ERRMSG(
"Cannot read meridional wind!");
9272 (ncid,
"w",
"W",
"omega",
"OMEGA", ctl, met, dd, met->
w, 0.01f))
9273 WARN(
"Cannot read vertical velocity!");
9278 (ncid,
"q",
"Q",
"sh",
"SH", ctl, met, dd, met->
h2o,
9280 WARN(
"Cannot read specific humidity!");
9283 (ncid,
"rh",
"RH", NULL, NULL, ctl, met, dd, met->
h2o, 0.01f))
9284 WARN(
"Cannot read relative humidity!");
9285#pragma omp parallel for default(shared) collapse(2)
9286 for (
int ix = 0; ix < met->
nx; ix++)
9287 for (
int iy = 0; iy < met->
ny; iy++)
9288 for (
int ip = 0; ip < met->
np; ip++) {
9289 double pw = met->
h2o[ix][iy][ip] *
PSAT(met->
t[ix][iy][ip]);
9290 met->
h2o[ix][iy][ip] =
9291 (float) (pw / (met->
p[ip] - (1.0 -
EPS) * pw));
9297 (ncid,
"o3",
"O3", NULL, NULL, ctl, met, dd, met->
o3,
9298 (
float) (
MA /
MO3)))
9299 WARN(
"Cannot read ozone data!");
9303 (ncid,
"clwc",
"CLWC", NULL, NULL, ctl, met, dd, met->
lwc, 1.0))
9304 WARN(
"Cannot read cloud liquid water content!");
9306 (ncid,
"crwc",
"CRWC", NULL, NULL, ctl, met, dd, met->
rwc, 1.0))
9307 WARN(
"Cannot read cloud rain water content!");
9309 (ncid,
"ciwc",
"CIWC", NULL, NULL, ctl, met, dd, met->
iwc, 1.0))
9310 WARN(
"Cannot read cloud ice water content!");
9312 (ncid,
"cswc",
"CSWC", NULL, NULL, ctl, met, dd, met->
swc, 1.0))
9313 WARN(
"Cannot read cloud snow water content!");
9315 (ncid,
"cc",
"CC", NULL, NULL, ctl, met, dd, met->
cc, 1.0))
9316 WARN(
"Cannot read cloud cover!");
9321 (ncid,
"ZETA",
"zeta", NULL, NULL, ctl, met, dd, met->
zetal, 1.0))
9322 WARN(
"Cannot read ZETA!");
9324 (ncid,
"ZETA_DOT_TOT",
"ZETA_DOT_clr",
"zeta_dot_clr",
9325 NULL, ctl, met, dd, met->
zeta_dotl, 0.00001157407f))
9326 WARN(
"Cannot read ZETA_DOT!");
9331#pragma omp parallel for default(shared)
9332 for (
int ix = 0; ix < met->
nx; ix++)
9333 for (
int iy = 0; iy < met->
ny; iy++)
9334 for (
int ip = 0; ip < met->
np; ip++)
9335 met->
zetal[ix][iy][ip] =
9336 (
float) (met->
hyam[ip] / 100000.0 + met->
hybm[ip]);
9338 (ncid,
"etadot",
"ETADOT", NULL, NULL, ctl, met, dd, met->
zeta_dotl,
9340 WARN(
"Cannot read eta vertical velocity!");
9345#pragma omp parallel for default(shared)
9346 for (
int ix = 0; ix < met->
nx; ix++)
9347 for (
int iy = 0; iy < met->
ny; iy++)
9348 for (
int ip = 0; ip < met->
np; ip++) {
9349 met->
ul[ix][iy][ip] = met->
u[ix][iy][ip];
9350 met->
vl[ix][iy][ip] = met->
v[ix][iy][ip];
9351 met->
wl[ix][iy][ip] = met->
w[ix][iy][ip];
9364 (ncid,
"pl",
"PL",
"pressure",
"PRESSURE", ctl, met, dd, met->
pl,
9367 (ncid,
"press",
"PRESS", NULL, NULL, ctl, met, dd, met->
pl, 1.0))
9368 ERRMSG(
"Cannot read pressure on model levels!");
9376 ERRMSG(
"Mismatch in number of model levels!");
9379 for (
int ix = 0; ix < met->
nx; ix++)
9380 for (
int iy = 0; iy < met->
ny; iy++)
9381 for (
int ip = 0; ip < met->
np; ip++)
9382 met->
pl[ix][iy][ip] =
9383 (
float) (met->
hyam[ip] / 100. +
9384 met->
hybm[ip] * met->
ps[ix][iy]);
9392 ERRMSG(
"Mismatch in number of model levels!");
9395#pragma omp parallel for default(shared) collapse(2)
9396 for (
int ix = 0; ix < met->
nx; ix++)
9397 for (
int iy = 0; iy < met->
ny; iy++)
9398 for (
int ip = 0; ip < met->
np; ip++) {
9400 met->
hyam[ip] / 100. + met->
hybm[ip] * met->
ps[ix][iy];
9402 met->
hyam[ip + 1] / 100. + met->
hybm[ip + 1] * met->
ps[ix][iy];
9403 met->
pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
9408 for (
int ix = 0; ix < met->
nx; ix++)
9409 for (
int iy = 0; iy < met->
ny; iy++)
9410 for (
int ip = 1; ip < met->
np; ip++)
9411 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
9412 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
9413 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
9414 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip]))
9415 ERRMSG(
"Pressure profiles are not monotonic!");
9436 for (
int ip = 0; ip < met->
np; ip++)
9437 met->
p[ip] = ctl->
met_p[ip];
9441 for (
int ip = 1; ip < met->
np; ip++)
9442 if (met->
p[ip - 1] < met->
p[ip])
9443 ERRMSG(
"Pressure levels must be descending!");
9450 const char *varname,
9451 const char *varname2,
9452 const char *varname3,
9453 const char *varname4,
9454 const char *varname5,
9455 const char *varname6,
9465 float offset, scalfac;
9470 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
9471 sprintf(varsel,
"%s", varname);
9472 else if (varname2 != NULL
9473 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
9474 sprintf(varsel,
"%s", varname2);
9475 else if (varname3 != NULL
9476 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
9477 sprintf(varsel,
"%s", varname3);
9478 else if (varname4 != NULL
9479 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
9480 sprintf(varsel,
"%s", varname4);
9481 else if (varname5 != NULL
9482 && nc_inq_varid(ncid, varname5, &varid) == NC_NOERR)
9483 sprintf(varsel,
"%s", varname5);
9484 else if (varname6 != NULL
9485 && nc_inq_varid(ncid, varname6, &varid) == NC_NOERR)
9486 sprintf(varsel,
"%s", varname6);
9492 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
9493 && nc_get_att_float(ncid, varid,
"scale_factor",
9494 &scalfac) == NC_NOERR) {
9502 short fillval, missval;
9503 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9505 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9509 LOG(2,
"Read 2-D variable: %s"
9510 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
9511 varsel, fillval, missval, scalfac, offset);
9514 NC(nc_get_var_short(ncid, varid, help));
9518 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
9522#pragma omp parallel for default(shared)
9523 for (
int ix = 0; ix < met->
nx; ix++)
9524 for (
int iy = 0; iy < met->
ny; iy++) {
9527 const short aux = help[
ARRAY_2D(iy, ix, met->
nx)];
9528 if ((fillval == 0 || aux != fillval)
9529 && (missval == 0 || aux != missval)
9530 && fabsf(aux * scalfac + offset) < 1e14f)
9531 dest[ix][iy] += scl * (aux * scalfac + offset);
9542 else if (!ctl->
dd) {
9550 float fillval, missval;
9551 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9553 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9557 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
9558 varsel, fillval, missval);
9561 NC(nc_get_var_float(ncid, varid, help));
9568#pragma omp parallel for default(shared)
9569 for (
int ix = 0; ix < met->
nx; ix++)
9570 for (
int iy = 0; iy < met->
ny; iy++) {
9573 const float aux = help[
ARRAY_2D(iy, ix, met->
nx)];
9574 if ((fillval == 0 || aux != fillval)
9575 && (missval == 0 || aux != missval)
9576 && fabsf(aux) < 1e14f)
9577 dest[ix][iy] += scl * aux;
9587#pragma omp parallel for default(shared)
9588 for (
int iy = 0; iy < met->
ny; iy++)
9589 for (
int ix = 0; ix < met->
nx; ix++) {
9592 const float aux = help[
ARRAY_2D(ix, iy, met->
ny)];
9593 if ((fillval == 0 || aux != fillval)
9594 && (missval == 0 || aux != missval)
9595 && fabsf(aux) < 1e14f)
9596 dest[ix][iy] += scl * aux;
9611 float fillval, missval;
9612 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9614 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9618 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
9619 varsel, fillval, missval);
9623 size_t help_subdomain_start[3];
9624 size_t help_subdomain_count[3];
9626 help_subdomain_start[0] = 0;
9635 help_subdomain_count[0] = 1;
9649 nc_var_par_access(ncid, varid, NC_COLLECTIVE);
9651 NC(nc_get_vara_float
9652 (ncid, varid, help_subdomain_start, help_subdomain_count, help));
9655 size_t help_halo_bnd_start[3];
9656 size_t help_halo_bnd_count[3];
9658 help_halo_bnd_start[0] = 0;
9667 help_halo_bnd_count[0] = 1;
9677 ALLOC(help_halo,
float,
9678 help_halo_bnd_count[1] * help_halo_bnd_count[2]);
9681 nc_var_par_access(ncid, varid, NC_COLLECTIVE);
9683 NC(nc_get_vara_float
9684 (ncid, varid, help_halo_bnd_start, help_halo_bnd_count, help_halo));
9691#pragma omp parallel for default(shared)
9692 for (
int ix = 0; ix < (int) help_subdomain_count[2]; ix++)
9693 for (
int iy = 0; iy < (int) help_subdomain_count[1]; iy++) {
9697 help[
ARRAY_2D(iy, ix, (
int) help_subdomain_count[2])];
9698 if ((fillval == 0 || aux != fillval)
9699 && (missval == 0 || aux != missval)
9700 && fabsf(aux) < 1e14f) {
9706#pragma omp parallel for default(shared)
9707 for (
int ix = 0; ix < (int) help_halo_bnd_count[2]; ix++)
9708 for (
int iy = 0; iy < (int) help_halo_bnd_count[1]; iy++) {
9712 help_halo[
ARRAY_2D(iy, ix, (
int) help_halo_bnd_count[2])];
9713 if ((fillval == 0 || aux != fillval)
9714 && (missval == 0 || aux != missval)
9715 && fabsf(aux) < 1e14f)
9727#pragma omp parallel for default(shared)
9728 for (
int ix = 0; ix < (int) help_subdomain_count[1]; ix++)
9729 for (
int iy = 0; iy < (int) help_subdomain_count[2]; iy++) {
9733 help[
ARRAY_2D(ix, iy, (
int) help_subdomain_count[1])];
9734 if ((fillval == 0 || aux != fillval)
9735 && (missval == 0 || aux != missval)
9736 && fabsf(aux) < 1e14f)
9742#pragma omp parallel for default(shared)
9743 for (
int ix = 0; ix < (int) help_halo_bnd_count[1]; ix++)
9744 for (
int iy = 0; iy < (int) help_halo_bnd_count[2]; iy++) {
9748 help_halo[
ARRAY_2D(ix, iy, (
int) help_halo_bnd_count[1])];
9749 if ((fillval == 0 || aux != fillval)
9750 && (missval == 0 || aux != missval)
9751 && fabsf(aux) < 1e14f)
9772 const char *varname,
9773 const char *varname2,
9774 const char *varname3,
9775 const char *varname4,
9784 float offset, scalfac;
9789 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
9790 sprintf(varsel,
"%s", varname);
9791 else if (varname2 != NULL
9792 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
9793 sprintf(varsel,
"%s", varname2);
9794 else if (varname3 != NULL
9795 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
9796 sprintf(varsel,
"%s", varname3);
9797 else if (varname4 != NULL
9798 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
9799 sprintf(varsel,
"%s", varname4);
9805 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
9806 && nc_get_att_float(ncid, varid,
"scale_factor",
9807 &scalfac) == NC_NOERR) {
9815 short fillval, missval;
9816 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9818 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9822 LOG(2,
"Read 3-D variable: %s "
9823 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
9824 varsel, fillval, missval, scalfac, offset);
9827 NC(nc_get_var_short(ncid, varid, help));
9831 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
9835#pragma omp parallel for default(shared)
9836 for (
int ix = 0; ix < met->
nx; ix++)
9837 for (
int iy = 0; iy < met->
ny; iy++)
9838 for (
int ip = 0; ip < met->
np; ip++) {
9839 const short aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
9840 if ((fillval == 0 || aux != fillval)
9841 && (missval == 0 || aux != missval)
9842 && fabsf(aux * scalfac + offset) < 1e14f)
9843 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
9845 dest[ix][iy][ip] = NAN;
9854 else if (!ctl->
dd) {
9862 float fillval, missval;
9863 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9865 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9869 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
9870 varsel, fillval, missval);
9873 NC(nc_get_var_float(ncid, varid, help));
9880#pragma omp parallel for default(shared)
9881 for (
int ix = 0; ix < met->
nx; ix++)
9882 for (
int iy = 0; iy < met->
ny; iy++)
9883 for (
int ip = 0; ip < met->
np; ip++) {
9884 const float aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
9885 if ((fillval == 0 || aux != fillval)
9886 && (missval == 0 || aux != missval)
9887 && fabsf(aux) < 1e14f)
9888 dest[ix][iy][ip] = scl * aux;
9890 dest[ix][iy][ip] = NAN;
9898#pragma omp parallel for default(shared)
9899 for (
int ip = 0; ip < met->
np; ip++)
9900 for (
int iy = 0; iy < met->
ny; iy++)
9901 for (
int ix = 0; ix < met->
nx; ix++) {
9902 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9903 if ((fillval == 0 || aux != fillval)
9904 && (missval == 0 || aux != missval)
9905 && fabsf(aux) < 1e14f)
9906 dest[ix][iy][ip] = scl * aux;
9908 dest[ix][iy][ip] = NAN;
9921 float fillval, missval;
9922 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9924 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9928 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
9929 varsel, fillval, missval);
9932 size_t help_subdomain_start[4];
9933 size_t help_subdomain_count[4];
9934 size_t help_halo_bnd_start[4];
9935 size_t help_halo_bnd_count[4];
9938 for (
int i = 0; i < 4; i++) {
9974 nc_var_par_access(ncid, varid, NC_COLLECTIVE);
9976 NC(nc_get_vara_float
9977 (ncid, varid, help_subdomain_start, help_subdomain_count, help));
9981 ALLOC(help_halo,
float,
9987 nc_var_par_access(ncid, varid, NC_COLLECTIVE);
9989 NC(nc_get_vara_float(ncid,
9991 help_halo_bnd_start, help_halo_bnd_count,
9999#pragma omp parallel for default(shared)
10002 for (
int ip = 0; ip < met->
np; ip++) {
10006 if ((fillval == 0 || aux != fillval)
10007 && (missval == 0 || aux != missval)
10008 && fabsf(aux) < 1e14f)
10014#pragma omp parallel for default(shared)
10017 for (
int ip = 0; ip < met->
np; ip++) {
10021 if ((fillval == 0 || aux != fillval)
10022 && (missval == 0 || aux != missval)
10023 && fabsf(aux) < 1e14f)
10028 omp_set_dynamic(0);
10033 omp_set_dynamic(1);
10034#pragma omp parallel for default(shared)
10035 for (
int ip = 0; ip < met->
np; ip++)
10041 if ((fillval == 0 || aux != fillval)
10042 && (missval == 0 || aux != missval)
10043 && fabsf(aux) < 1e14f)
10049#pragma omp parallel for default(shared)
10050 for (
int ip = 0; ip < met->
np; ip++)
10056 if ((fillval == 0 || aux != fillval)
10057 && (missval == 0 || aux != missval)
10058 && fabsf(aux) < 1e14f)
10063 omp_set_dynamic(0);
10079 const char *filename,
10084 size_t filename_len = strlen(filename) + 1;
10085 char sf_filename[filename_len];
10086 char ml_filename[filename_len];
10087 strcpy(sf_filename, filename);
10088 strcpy(ml_filename, filename);
10093 FILE *ml_file = fopen(ml_filename,
"rb");
10094 FILE *sf_file = fopen(sf_filename,
"rb");
10095 if (ml_file == NULL || sf_file == NULL) {
10096 if (ml_file != NULL) {
10098 WARN(
"Cannot open file: %s", sf_filename);
10100 if (sf_file != NULL) {
10102 WARN(
"Cannot open file: %s", ml_filename);
10108 int ml_num_messages = 0, err = 0;
10109 ECC(codes_count_in_file(0, ml_file, &ml_num_messages));
10112 (size_t) ml_num_messages);
10113 for (
int i = 0; i < ml_num_messages; i++) {
10115 if ((h = codes_grib_handle_new_from_file(0, ml_file, &err)) != NULL)
10120 int sf_num_messages = 0;
10121 ECC(codes_count_in_file(0, sf_file, &sf_num_messages));
10124 (size_t) sf_num_messages);
10125 for (
int i = 0; i < sf_num_messages; i++) {
10127 if ((h = codes_grib_handle_new_from_file(0, sf_file, &err)) != NULL)
10140 for (
int i = 0; i < sf_num_messages; i++)
10141 codes_handle_delete(sf_handles[i]);
10145 size_t value_count = 0;
10146 ECC(codes_get_size(ml_handles[0],
"pv", &value_count));
10147 if (value_count % 2 != 0)
10148 ERRMSG(
"Unexpected pv array length!");
10149 size_t nlevels = value_count / 2 - 1;
10151 ALLOC(values,
double,
10153 ECC(codes_get_double_array(ml_handles[0],
"pv", values, &value_count));
10154 double *a_vals = values;
10155 double *b_vals = values + nlevels;
10156 if (met->
npl > (
int) nlevels)
10157 ERRMSG(
"met->npl exceeds number of pressure levels in GRIB!");
10158 for (
int nx = 0; nx < met->
nx; nx++)
10159 for (
int ny = 0; ny < met->
ny; ny++)
10160 for (
int level = 0; level <= met->
npl; level++) {
10161 const float p1 = (float) (a_vals[level] * 0.01f +
10162 met->
ps[nx][ny] * b_vals[level]);
10163 const float p2 = (float) (a_vals[level + 1] * 0.01f +
10164 met->
ps[nx][ny] * b_vals[level + 1]);
10165 met->
pl[nx][ny][level] = 0.5f * (p1 + p2);
10171 for (
int i = 0; i < ml_num_messages; i++)
10172 codes_handle_delete(ml_handles[i]);
10190 LOG(2,
"Read meteo grid information...");
10193 char datestr[
LEN], timestr[
LEN];
10194 size_t s_date =
sizeof(datestr);
10195 ECC(codes_get_string(handles[0],
"dataDate", datestr, &s_date));
10196 size_t s_time =
sizeof(timestr);
10197 ECC(codes_get_string(handles[0],
"dataTime", timestr, &s_time));
10198 int year, month, day, hour;
10199 if (sscanf(datestr,
"%4d%2d%2d", &year, &month, &day) != 3)
10200 ERRMSG(
"Failed to parse dataDate: %s", datestr);
10201 if (sscanf(timestr,
"%2d", &hour) != 1)
10202 ERRMSG(
"Failed to parse dataTime: %s", timestr);
10204 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)", met->
time, year, month,
10208 long count_lat = 0, count_lon = 0;
10209 ECC(codes_get_long(handles[0],
"Nj", &count_lat));
10210 ECC(codes_get_long(handles[0],
"Ni", &count_lon));
10211 met->
ny = (int) count_lat;
10212 met->
nx = (int) count_lon;
10215 LOG(2,
"Number of longitudes: %d", met->
nx);
10216 if (met->
nx < 2 || met->
nx >
EX)
10217 ERRMSG(
"Number of longitudes out of range!");
10218 LOG(2,
"Number of latitudes: %d", met->
ny);
10219 if (met->
ny < 2 || met->
ny >
EY)
10220 ERRMSG(
"Number of latitudes out of range!");
10222 double first_lon, last_lon, first_lat, last_lat, inc_lon, inc_lat;
10223 ECC(codes_get_double
10224 (handles[0],
"longitudeOfFirstGridPointInDegrees", &first_lon));
10225 ECC(codes_get_double
10226 (handles[0],
"latitudeOfFirstGridPointInDegrees", &first_lat));
10227 ECC(codes_get_double
10228 (handles[0],
"longitudeOfLastGridPointInDegrees", &last_lon));
10229 ECC(codes_get_double
10230 (handles[0],
"latitudeOfLastGridPointInDegrees", &last_lat));
10231 ECC(codes_get_double(handles[0],
"iDirectionIncrementInDegrees", &inc_lon));
10232 ECC(codes_get_double(handles[0],
"jDirectionIncrementInDegrees", &inc_lat));
10234 long jscanpos, iscanneg;
10235 ECC(codes_get_long(handles[0],
"iScansNegatively", &iscanneg));
10236 ECC(codes_get_long(handles[0],
"jScansPositively", &jscanpos));
10241 for (
double i = first_lon; i <= last_lon + 1e-6; i += inc_lon) {
10242 met->
lon[counter] = i;
10245 for (
double i = first_lon; i > last_lon - 1e-6; i -= inc_lon) {
10246 met->
lon[counter] = i;
10252 for (
double i = first_lat; i > last_lat - 1e-6; i -= inc_lat) {
10253 met->
lat[counter] = i;
10256 for (
double i = first_lat; i <= last_lat + 1e-6; i += inc_lat) {
10257 met->
lat[counter] = i;
10262 LOG(2,
"Longitudes: %g, %g ... %g deg",
10263 met->
lon[0], met->
lon[1], met->
lon[met->
nx - 1]);
10264 LOG(2,
"Latitudes: %g, %g ... %g deg",
10265 met->
lat[0], met->
lat[1], met->
lat[met->
ny - 1]);
10269 for (
int i = 0; i < count_handles; i++) {
10271 ECC(codes_get_long(handles[i],
"level", &level));
10272 if (level > max_level)
10273 max_level = (int) level;
10275 met->
npl = max_level;
10278 LOG(2,
"Number of levels: %d", met->
npl);
10279 if (met->
npl < 2 || met->
npl >
EP)
10280 ERRMSG(
"Number of levels out of range!");
10289 const int num_messages,
10295 LOG(2,
"Read level data...");
10298 int t_flag = 0, u_flag = 0, v_flag = 0, w_flag = 0, o3_flag = 0, h2o_flag =
10299 0, lwc_flag = 0, rwc_flag = 0, iwc_flag = 0, swc_flag = 0, cc_flag = 0;
10302 for (
int i = 0; i < num_messages; i++) {
10304 size_t max_size =
LEN;
10305 char short_name[max_size];
10306 size_t value_count;
10310 long current_level;
10311 ECC(codes_get_long(handles[i],
"level", ¤t_level));
10312 current_level -= 1;
10315 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
10316 ECC(codes_get_size(handles[i],
"values", &value_count));
10317 ALLOC(values,
double,
10319 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
10327 ECC_READ_3D(
"w", current_level, met->
w, 0.01f, w_flag);
10345 if (t_flag != met->
npl)
10346 ERRMSG(
"Cannot read temperature!");
10347 if (u_flag != met->
npl)
10348 ERRMSG(
"Cannot read zonal wind!");
10349 if (v_flag != met->
npl)
10350 ERRMSG(
"Cannot read meridional wind!");
10351 if (w_flag != met->
npl)
10352 WARN(
"Cannot read vertical velocity!");
10353 if (h2o_flag != met->
npl)
10354 WARN(
"Cannot read specific humidity!");
10355 if (o3_flag != met->
npl)
10356 WARN(
"Cannot read ozone data!");
10357 if (lwc_flag != met->
npl)
10358 WARN(
"Cannot read cloud liquid water content!");
10359 if (rwc_flag != met->
npl)
10360 WARN(
"Cannot read cloud rain water content!");
10361 if (iwc_flag != met->
npl)
10362 WARN(
"Cannot read cloud ice water content!");
10363 if (swc_flag != met->
npl)
10364 WARN(
"Cannot read cloud snow water content!");
10365 if (cc_flag != met->
npl)
10366 WARN(
"Cannot read cloud cover!");
10369 for (
int ix = 0; ix < met->
nx; ix++)
10370 for (
int iy = 0; iy < met->
ny; iy++)
10371 for (
int ip = 1; ip < met->
np; ip++)
10372 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
10373 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
10374 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
10375 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip])) {
10376 LOG(1,
"%f %f %f %f", met->
pl[ix][iy][0], met->
pl[ix][iy][1],
10377 met->
pl[ix][iy][ip - 1], met->
pl[ix][iy][ip]);
10378 ERRMSG(
"Pressure profiles are not monotonic!");
10399 for (
int ip = 0; ip < met->
np; ip++)
10400 met->
p[ip] = ctl->
met_p[ip];
10404 for (
int ip = 1; ip < met->
np; ip++)
10405 if (met->
p[ip - 1] < met->
p[ip])
10406 ERRMSG(
"Pressure levels must be descending!");
10415 const int num_messages,
10421 LOG(2,
"Read surface data...");
10424 int sp_flag = 0, z_flag = 0, t_flag = 0, u_flag = 0, v_flag = 0, lsm_flag =
10425 0, sst_flag = 0, cape_flag = 0, cin_flag = 0, pbl_flag = 0;
10428 for (
int i = 0; i < num_messages; i++) {
10430 size_t max_size =
LEN, value_count;
10432 char short_name[max_size];
10435 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
10436 ECC(codes_get_size(handles[i],
"values", &value_count));
10437 double *values = (
double *) malloc(value_count *
sizeof(
double));
10438 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
10476 WARN(
"Cannot read surface pressure data!");
10478 WARN(
"Cannot read surface geopotential height!");
10480 WARN(
"Cannot read surface temperature!");
10482 WARN(
"Cannot read surface zonal wind!");
10484 WARN(
"Cannot read surface meridional wind!");
10486 WARN(
"Cannot read land-sea mask!");
10488 WARN(
"Cannot read sea surface temperature!");
10490 if (cape_flag == 0)
10491 WARN(
"Cannot read CAPE!");
10493 WARN(
"Cannot read convective inhibition!");
10495 if (ctl->
met_pbl == 0 && pbl_flag == 0)
10496 WARN(
"Cannot read planetary boundary layer!");
10506 const char *varname) {
10508 double aux[
EP], p[
EP];
10512 LOG(2,
"Interpolate meteo data to pressure levels: %s", varname);
10515#pragma omp parallel for default(shared) private(aux,p) collapse(2)
10516 for (
int ix = 0; ix < met->
nx; ix++)
10517 for (
int iy = 0; iy < met->
ny; iy++) {
10520 for (
int ip = 0; ip < met->
np; ip++)
10521 p[ip] = met->
pl[ix][iy][ip];
10524 for (
int ip = 0; ip < ctl->
met_np; ip++) {
10525 double pt = ctl->
met_p[ip];
10526 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
10528 else if ((pt > p[met->
np - 1] && p[1] > p[0])
10529 || (pt < p[met->
np - 1] && p[1] < p[0]))
10530 pt = p[met->
np - 1];
10532 aux[ip] =
LIN(p[ip2], var[ix][iy][ip2],
10533 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
10537 for (
int ip = 0; ip < ctl->
met_np; ip++)
10538 var[ix][iy][ip] = (
float) aux[ip];
10554 LOG(2,
"Make zeta profiles monotone...");
10557#pragma omp parallel for default(shared) collapse(2)
10558 for (
int i = 0; i < met->
nx; i++)
10559 for (
int j = 0; j < met->
ny; j++) {
10562 while (k < met->npl) {
10563 if ((met->
zetal[i][j][k - 1] >= met->
zetal[i][j][k])) {
10569 while ((met->
zetal[i][j][k - 1] >=
10570 met->
zetal[i][j][k + l]) & (k + l < met->npl));
10575 (float) (met->
zetal[i][j][k + l] - met->
zetal[i][j][k - 1])
10578 for (
int m = k; m < k + l; m++) {
10579 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
10580 met->
zetal[i][j][m] = s * d + met->
zetal[i][j][k - 1];
10592#pragma omp parallel for default(shared) collapse(2)
10593 for (
int i = 0; i < met->
nx; i++)
10594 for (
int j = 0; j < met->
ny; j++) {
10597 while (k < met->npl) {
10598 if ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k])) {
10605 while ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k + l]) & (k + l <
10610 float s = (float) (met->
pl[i][j][k + l] - met->
pl[i][j][k - 1])
10613 for (
int m = k; m < k + l; m++) {
10614 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
10615 met->
pl[i][j][m] = s * d + met->
pl[i][j][k - 1];
10630 const char *filename,
10641 (filename, NC_NOWRITE | NC_SHARE, MPI_COMM_WORLD, MPI_INFO_NULL,
10645 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
10646 WARN(
"Cannot open file!");
10661 NC(nc_close(ncid));
10678 int rank = 0, size = 1;
10680 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
10681 MPI_Comm_size(MPI_COMM_WORLD, &size);
10688 LOG(2,
"Number of longitudes: %d", dd->
nx_glob);
10689 LOG(2,
"Number of latitudes: %d", dd->
ny_glob);
10693 ERRMSG(
"Global grid is too large!");
10696 ERRMSG(
"Too many zonal subdomains for global x grid!");
10699 ERRMSG(
"Too many meridional subdomains for global y grid!");
10705 LOG(2,
"Longitudes: %g, %g ... %g deg",
10707 LOG(2,
"Latitudes: %g, %g ... %g deg",
10715 const int left = (zonal_rank == 0);
10717 const int top = (merid_rank == 0);
10724 const int ix0 = zonal_rank * nx_block;
10725 const int iy0 = merid_rank * ny_block;
10727 int nx_core = nx_block;
10728 int ny_core = ny_block;
10751 if (!left && !right) {
10754 }
else if (left ^ right) {
10760 if (!top && !bottom) {
10763 }
else if (top ^ bottom) {
10770 double lon_shift = 0.0;
10772 if (left ^ right) {
10788 lon_shift = left ? -360.0 : 360.0;
10821 LOG(2,
"Define subdomain properties.");
10822 LOG(2,
"MPI information: Rank %d, Size %d", rank, size);
10823 LOG(2,
"Edge position: l=%d,r=%d,t=%d,b=%d", left, right, top, bottom);
10824 LOG(2,
"Total size for subdomain meteo data: nx %d ny %d np %d",
10825 met->
nx, met->
ny, met->
np);
10826 LOG(2,
"Hyperslab sizes for boundary halos: nx %d ny %d np %d",
10829 LOG(2,
"Hyperslab sizes for subdomain and inner halos: nx %d ny %d np %d",
10832 LOG(2,
"Subdomain start: nx %ld ny %ld np %ld",
10834 LOG(2,
"Boundary halo start: nx %ld ny %ld np %ld",
10837 LOG(2,
"%d Subdomain longitudes: %g, %g ... %g deg",
10838 rank, met->
lon[0], met->
lon[1], met->
lon[met->
nx - 1]);
10839 LOG(2,
"%d Subdomain latitudes: %g, %g ... %g deg",
10840 rank, met->
lat[0], met->
lat[1], met->
lat[met->
ny - 1]);
10851 LOG(2,
"Calculate planetary boundary layer...");
10857#pragma omp parallel for default(shared) collapse(2)
10858 for (
int ix = 0; ix < met->
nx; ix++)
10859 for (
int iy = 0; iy < met->
ny; iy++) {
10862 const float z = met->
zs[ix][iy] + met->
pbl[ix][iy];
10865 (float) (
LIN(met->
z[ix][iy][ip], met->
p[ip],
10866 met->
z[ix][iy][ip + 1], met->
p[ip + 1], z));
10871 else if (ctl->
met_pbl == 2) {
10875 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
10878#pragma omp parallel for default(shared) collapse(2)
10879 for (
int ix = 0; ix < met->
nx; ix++)
10880 for (
int iy = 0; iy < met->
ny; iy++) {
10883 const double pbl_bot = met->
ps[ix][iy] * exp(-dz /
H0);
10887 for (ip = 1; ip < met->
np; ip++)
10888 if (met->
p[ip] < pbl_bot)
10892 const double h2os =
LIN(met->
p[ip - 1], met->
h2o[ix][iy][ip - 1],
10893 met->
p[ip], met->
h2o[ix][iy][ip], pbl_bot);
10894 const double tvs =
THETAVIRT(pbl_bot, met->
ts[ix][iy], h2os);
10897 double rib_old = 0;
10900 for (; ip < met->
np; ip++) {
10903 double vh2 =
SQR(met->
u[ix][iy][ip] - met->
us[ix][iy])
10904 +
SQR(met->
v[ix][iy][ip] - met->
vs[ix][iy]);
10905 vh2 =
MAX(vh2,
SQR(umin));
10909 G0 * 1e3 * (met->
z[ix][iy][ip] - met->
zs[ix][iy]) / tvs
10911 met->
h2o[ix][iy][ip]) - tvs) / vh2;
10914 if (rib >= rib_crit) {
10915 met->
pbl[ix][iy] = (float) (
LIN(rib_old, met->
p[ip - 1],
10916 rib, met->
p[ip], rib_crit));
10917 if (met->
pbl[ix][iy] > pbl_bot)
10918 met->
pbl[ix][iy] = (float) pbl_bot;
10933 const double dtheta = 2.0, zmin = 0.1;
10936#pragma omp parallel for default(shared) collapse(2)
10937 for (
int ix = 0; ix < met->
nx; ix++)
10938 for (
int iy = 0; iy < met->
ny; iy++) {
10941 const double theta0 =
THETA(met->
ps[ix][iy], met->
ts[ix][iy]);
10945 for (ip = met->
np - 2; ip > 0; ip--)
10946 if (met->
p[ip] >= 300.)
10947 if (met->
p[ip] > met->
ps[ix][iy]
10948 ||
THETA(met->
p[ip], met->
t[ix][iy][ip]) <= theta0 + dtheta)
10953 = (float) (
LIN(
THETA(met->
p[ip + 1], met->
t[ix][iy][ip + 1]),
10955 THETA(met->
p[ip], met->
t[ix][iy][ip]),
10956 met->
p[ip], theta0 + dtheta));
10959 double pbl_min = met->
ps[ix][iy] * exp(-zmin /
H0);
10960 if (met->
pbl[ix][iy] > pbl_min || met->
p[ip] > met->
ps[ix][iy])
10961 met->
pbl[ix][iy] = (float) pbl_min;
10966#pragma omp parallel for default(shared) collapse(2)
10967 for (
int ix = 0; ix < met->
nx; ix++)
10968 for (
int iy = 0; iy < met->
ny; iy++) {
10972 met->
pbl[ix][iy] =
MIN(met->
pbl[ix][iy], (
float) pbl_min);
10976 met->
pbl[ix][iy] =
MAX(met->
pbl[ix][iy], (
float) pbl_max);
10987 LOG(2,
"Apply periodic boundary conditions...");
10990 if (!(fabs(met->
lon[met->
nx - 1] - met->
lon[0]
10991 + met->
lon[1] - met->
lon[0] - 360) < 0.01))
10995 if ((++met->
nx) >=
EX)
10996 ERRMSG(
"Cannot create periodic boundary conditions!");
10999 met->
lon[met->
nx - 1] = met->
lon[met->
nx - 2] + met->
lon[1] - met->
lon[0];
11002#pragma omp parallel for default(shared)
11003 for (
int iy = 0; iy < met->
ny; iy++) {
11004 met->
ps[met->
nx - 1][iy] = met->
ps[0][iy];
11005 met->
zs[met->
nx - 1][iy] = met->
zs[0][iy];
11006 met->
ts[met->
nx - 1][iy] = met->
ts[0][iy];
11007 met->
us[met->
nx - 1][iy] = met->
us[0][iy];
11008 met->
vs[met->
nx - 1][iy] = met->
vs[0][iy];
11009 met->
ess[met->
nx - 1][iy] = met->
ess[0][iy];
11010 met->
nss[met->
nx - 1][iy] = met->
nss[0][iy];
11011 met->
shf[met->
nx - 1][iy] = met->
shf[0][iy];
11012 met->
lsm[met->
nx - 1][iy] = met->
lsm[0][iy];
11013 met->
sst[met->
nx - 1][iy] = met->
sst[0][iy];
11014 met->
pbl[met->
nx - 1][iy] = met->
pbl[0][iy];
11015 met->
cape[met->
nx - 1][iy] = met->
cape[0][iy];
11016 met->
cin[met->
nx - 1][iy] = met->
cin[0][iy];
11017 for (
int ip = 0; ip < met->
np; ip++) {
11018 met->
t[met->
nx - 1][iy][ip] = met->
t[0][iy][ip];
11019 met->
u[met->
nx - 1][iy][ip] = met->
u[0][iy][ip];
11020 met->
v[met->
nx - 1][iy][ip] = met->
v[0][iy][ip];
11021 met->
w[met->
nx - 1][iy][ip] = met->
w[0][iy][ip];
11022 met->
h2o[met->
nx - 1][iy][ip] = met->
h2o[0][iy][ip];
11023 met->
o3[met->
nx - 1][iy][ip] = met->
o3[0][iy][ip];
11024 met->
lwc[met->
nx - 1][iy][ip] = met->
lwc[0][iy][ip];
11025 met->
rwc[met->
nx - 1][iy][ip] = met->
rwc[0][iy][ip];
11026 met->
iwc[met->
nx - 1][iy][ip] = met->
iwc[0][iy][ip];
11027 met->
swc[met->
nx - 1][iy][ip] = met->
swc[0][iy][ip];
11028 met->
cc[met->
nx - 1][iy][ip] = met->
cc[0][iy][ip];
11030 for (
int ip = 0; ip < met->
npl; ip++) {
11031 met->
ul[met->
nx - 1][iy][ip] = met->
ul[0][iy][ip];
11032 met->
vl[met->
nx - 1][iy][ip] = met->
vl[0][iy][ip];
11033 met->
wl[met->
nx - 1][iy][ip] = met->
wl[0][iy][ip];
11034 met->
pl[met->
nx - 1][iy][ip] = met->
pl[0][iy][ip];
11035 met->
zetal[met->
nx - 1][iy][ip] = met->
zetal[0][iy][ip];
11048 LOG(2,
"Apply fix for polar winds...");
11051 if (fabs(met->
lat[0]) < 89.999 || fabs(met->
lat[met->
ny - 1]) < 89.999)
11055 for (
int ihem = 0; ihem < 2; ihem++) {
11058 int i89 = 1, i90 = 0, sign = 1;
11063 if (met->
lat[i90] < 0)
11067 double clon[
EX], slon[
EX];
11068#pragma omp parallel for default(shared)
11069 for (
int ix = 0; ix < met->
nx; ix++) {
11070 clon[ix] = cos(sign *
DEG2RAD(met->
lon[ix]));
11071 slon[ix] = sin(sign *
DEG2RAD(met->
lon[ix]));
11075#pragma omp parallel for default(shared)
11076 for (
int ip = 0; ip < met->
np; ip++) {
11079 double vel89x = 0, vel89y = 0;
11080 for (
int ix = 0; ix < met->
nx; ix++) {
11082 (met->
u[ix][i89][ip] * clon[ix] -
11083 met->
v[ix][i89][ip] * slon[ix]) / met->
nx;
11085 (met->
u[ix][i89][ip] * slon[ix] +
11086 met->
v[ix][i89][ip] * clon[ix]) / met->
nx;
11090 for (
int ix = 0; ix < met->
nx; ix++) {
11091 met->
u[ix][i90][ip]
11092 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
11093 met->
v[ix][i90][ip]
11094 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
11109 LOG(2,
"Calculate potential vorticity...");
11112#pragma omp parallel for default(shared)
11113 for (
int ip = 0; ip < met->
np; ip++)
11114 pows[ip] = pow(1000. / met->
p[ip], 0.286);
11117#pragma omp parallel for default(shared)
11118 for (
int ix = 0; ix < met->
nx; ix++) {
11121 const int ix0 =
MAX(ix - 1, 0);
11122 const int ix1 =
MIN(ix + 1, met->
nx - 1);
11125 for (
int iy = 0; iy < met->
ny; iy++) {
11128 const int iy0 =
MAX(iy - 1, 0);
11129 const int iy1 =
MIN(iy + 1, met->
ny - 1);
11132 const double latr = 0.5 * (met->
lat[iy1] + met->
lat[iy0]);
11133 const double dx = 1000. *
DEG2DX(met->
lon[ix1] - met->
lon[ix0], latr);
11134 const double dy = 1000. *
DEG2DY(met->
lat[iy1] - met->
lat[iy0]);
11135 const double c0 = cos(
DEG2RAD(met->
lat[iy0]));
11136 const double c1 = cos(
DEG2RAD(met->
lat[iy1]));
11137 const double cr = cos(
DEG2RAD(latr));
11138 const double vort = 2 * 7.2921e-5 * sin(
DEG2RAD(latr));
11141 for (
int ip = 0; ip < met->
np; ip++) {
11145 = (met->
t[ix1][iy][ip] - met->
t[ix0][iy][ip]) * pows[ip] / dx;
11146 const double dvdx = (met->
v[ix1][iy][ip] - met->
v[ix0][iy][ip]) / dx;
11150 = (met->
t[ix][iy1][ip] - met->
t[ix][iy0][ip]) * pows[ip] / dy;
11152 = (met->
u[ix][iy1][ip] * c1 - met->
u[ix][iy0][ip] * c0) / dy;
11155 const int ip0 =
MAX(ip - 1, 0);
11156 const int ip1 =
MIN(ip + 1, met->
np - 1);
11159 double dtdp, dudp, dvdp;
11160 const double dp0 = 100. * (met->
p[ip] - met->
p[ip0]);
11161 const double dp1 = 100. * (met->
p[ip1] - met->
p[ip]);
11162 if (ip != ip0 && ip != ip1) {
11163 double denom = dp0 * dp1 * (dp0 + dp1);
11164 dtdp = (dp0 * dp0 * met->
t[ix][iy][ip1] * pows[ip1]
11165 - dp1 * dp1 * met->
t[ix][iy][ip0] * pows[ip0]
11166 + (dp1 * dp1 - dp0 * dp0) * met->
t[ix][iy][ip] * pows[ip])
11168 dudp = (dp0 * dp0 * met->
u[ix][iy][ip1]
11169 - dp1 * dp1 * met->
u[ix][iy][ip0]
11170 + (dp1 * dp1 - dp0 * dp0) * met->
u[ix][iy][ip])
11172 dvdp = (dp0 * dp0 * met->
v[ix][iy][ip1]
11173 - dp1 * dp1 * met->
v[ix][iy][ip0]
11174 + (dp1 * dp1 - dp0 * dp0) * met->
v[ix][iy][ip])
11177 const double denom = dp0 + dp1;
11179 (met->
t[ix][iy][ip1] * pows[ip1] -
11180 met->
t[ix][iy][ip0] * pows[ip0]) / denom;
11181 dudp = (met->
u[ix][iy][ip1] - met->
u[ix][iy][ip0]) / denom;
11182 dvdp = (met->
v[ix][iy][ip1] - met->
v[ix][iy][ip0]) / denom;
11186 met->
pv[ix][iy][ip] = (float)
11188 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
11194#pragma omp parallel for default(shared)
11195 for (
int ix = 0; ix < met->
nx; ix++)
11196 for (
int ip = 0; ip < met->
np; ip++) {
11198 = met->
pv[ix][1][ip]
11199 = met->
pv[ix][2][ip];
11200 met->
pv[ix][met->
ny - 1][ip]
11201 = met->
pv[ix][met->
ny - 2][ip]
11202 = met->
pv[ix][met->
ny - 3][ip];
11213 LOG(2,
"Calculate total column ozone...");
11216#pragma omp parallel for default(shared) collapse(2)
11217 for (
int ix = 0; ix < met->
nx; ix++)
11218 for (
int iy = 0; iy < met->
ny; iy++) {
11222 for (
int ip = 1; ip < met->
np; ip++)
11223 if (met->
p[ip - 1] <= met->
ps[ix][iy]) {
11225 0.5 * (met->
o3[ix][iy][ip - 1] + met->
o3[ix][iy][ip]);
11226 const double dp = met->
p[ip - 1] - met->
p[ip];
11227 cd += vmr *
MO3 /
MA * dp * 1e2 /
G0;
11231 met->
o3c[ix][iy] = (float) (cd / 2.1415e-5);
11250 LOG(2,
"Downsampling of meteo data...");
11256 help->
nx = met->
nx;
11257 help->
ny = met->
ny;
11258 help->
np = met->
np;
11259 memcpy(help->
lon, met->
lon,
sizeof(met->
lon));
11260 memcpy(help->
lat, met->
lat,
sizeof(met->
lat));
11261 memcpy(help->
p, met->
p,
sizeof(met->
p));
11264 for (
int ix = 0; ix < met->
nx; ix += ctl->
met_dx) {
11265 for (
int iy = 0; iy < met->
ny; iy += ctl->
met_dy) {
11266 for (
int ip = 0; ip < met->
np; ip += ctl->
met_dp) {
11267 help->
ps[ix][iy] = 0;
11268 help->
zs[ix][iy] = 0;
11269 help->
ts[ix][iy] = 0;
11270 help->
us[ix][iy] = 0;
11271 help->
vs[ix][iy] = 0;
11272 help->
ess[ix][iy] = 0;
11273 help->
nss[ix][iy] = 0;
11274 help->
shf[ix][iy] = 0;
11275 help->
lsm[ix][iy] = 0;
11276 help->
sst[ix][iy] = 0;
11277 help->
pbl[ix][iy] = 0;
11278 help->
cape[ix][iy] = 0;
11279 help->
cin[ix][iy] = 0;
11280 help->
t[ix][iy][ip] = 0;
11281 help->
u[ix][iy][ip] = 0;
11282 help->
v[ix][iy][ip] = 0;
11283 help->
w[ix][iy][ip] = 0;
11284 help->
h2o[ix][iy][ip] = 0;
11285 help->
o3[ix][iy][ip] = 0;
11286 help->
lwc[ix][iy][ip] = 0;
11287 help->
rwc[ix][iy][ip] = 0;
11288 help->
iwc[ix][iy][ip] = 0;
11289 help->
swc[ix][iy][ip] = 0;
11290 help->
cc[ix][iy][ip] = 0;
11292 for (
int ix2 = ix - ctl->
met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
11297 else if (ix3 >= met->
nx)
11300 for (
int iy2 =
MAX(iy - ctl->
met_sy + 1, 0);
11301 iy2 <=
MIN(iy + ctl->
met_sy - 1, met->
ny - 1); iy2++)
11302 for (
int ip2 =
MAX(ip - ctl->
met_sp + 1, 0);
11303 ip2 <=
MIN(ip + ctl->
met_sp - 1, met->
np - 1); ip2++) {
11305 (1.0f - (float) abs(ix - ix2) / (float) ctl->
met_sx)
11306 * (1.0f - (float) abs(iy - iy2) / (float) ctl->
met_sy)
11307 * (1.0f - (float) abs(ip - ip2) / (float) ctl->
met_sp);
11308 help->
ps[ix][iy] += w * met->
ps[ix3][iy2];
11309 help->
zs[ix][iy] += w * met->
zs[ix3][iy2];
11310 help->
ts[ix][iy] += w * met->
ts[ix3][iy2];
11311 help->
us[ix][iy] += w * met->
us[ix3][iy2];
11312 help->
vs[ix][iy] += w * met->
vs[ix3][iy2];
11313 help->
ess[ix][iy] += w * met->
ess[ix3][iy2];
11314 help->
nss[ix][iy] += w * met->
nss[ix3][iy2];
11315 help->
shf[ix][iy] += w * met->
shf[ix3][iy2];
11316 help->
lsm[ix][iy] += w * met->
lsm[ix3][iy2];
11317 help->
sst[ix][iy] += w * met->
sst[ix3][iy2];
11318 help->
pbl[ix][iy] += w * met->
pbl[ix3][iy2];
11319 help->
cape[ix][iy] += w * met->
cape[ix3][iy2];
11320 help->
cin[ix][iy] += w * met->
cin[ix3][iy2];
11321 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip2];
11322 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip2];
11323 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip2];
11324 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip2];
11325 help->
h2o[ix][iy][ip] += w * met->
h2o[ix3][iy2][ip2];
11326 help->
o3[ix][iy][ip] += w * met->
o3[ix3][iy2][ip2];
11327 help->
lwc[ix][iy][ip] += w * met->
lwc[ix3][iy2][ip2];
11328 help->
rwc[ix][iy][ip] += w * met->
rwc[ix3][iy2][ip2];
11329 help->
iwc[ix][iy][ip] += w * met->
iwc[ix3][iy2][ip2];
11330 help->
swc[ix][iy][ip] += w * met->
swc[ix3][iy2][ip2];
11331 help->
cc[ix][iy][ip] += w * met->
cc[ix3][iy2][ip2];
11335 help->
ps[ix][iy] /= wsum;
11336 help->
zs[ix][iy] /= wsum;
11337 help->
ts[ix][iy] /= wsum;
11338 help->
us[ix][iy] /= wsum;
11339 help->
vs[ix][iy] /= wsum;
11340 help->
ess[ix][iy] /= wsum;
11341 help->
nss[ix][iy] /= wsum;
11342 help->
shf[ix][iy] /= wsum;
11343 help->
lsm[ix][iy] /= wsum;
11344 help->
sst[ix][iy] /= wsum;
11345 help->
pbl[ix][iy] /= wsum;
11346 help->
cape[ix][iy] /= wsum;
11347 help->
cin[ix][iy] /= wsum;
11348 help->
t[ix][iy][ip] /= wsum;
11349 help->
u[ix][iy][ip] /= wsum;
11350 help->
v[ix][iy][ip] /= wsum;
11351 help->
w[ix][iy][ip] /= wsum;
11352 help->
h2o[ix][iy][ip] /= wsum;
11353 help->
o3[ix][iy][ip] /= wsum;
11354 help->
lwc[ix][iy][ip] /= wsum;
11355 help->
rwc[ix][iy][ip] /= wsum;
11356 help->
iwc[ix][iy][ip] /= wsum;
11357 help->
swc[ix][iy][ip] /= wsum;
11358 help->
cc[ix][iy][ip] /= wsum;
11365 for (
int ix = 0; ix < help->
nx; ix += ctl->
met_dx) {
11366 met->
lon[met->
nx] = help->
lon[ix];
11368 for (
int iy = 0; iy < help->
ny; iy += ctl->
met_dy) {
11369 met->
lat[met->
ny] = help->
lat[iy];
11370 met->
ps[met->
nx][met->
ny] = help->
ps[ix][iy];
11371 met->
zs[met->
nx][met->
ny] = help->
zs[ix][iy];
11372 met->
ts[met->
nx][met->
ny] = help->
ts[ix][iy];
11373 met->
us[met->
nx][met->
ny] = help->
us[ix][iy];
11374 met->
vs[met->
nx][met->
ny] = help->
vs[ix][iy];
11375 met->
ess[met->
nx][met->
ny] = help->
ess[ix][iy];
11376 met->
nss[met->
nx][met->
ny] = help->
nss[ix][iy];
11377 met->
shf[met->
nx][met->
ny] = help->
shf[ix][iy];
11378 met->
lsm[met->
nx][met->
ny] = help->
lsm[ix][iy];
11379 met->
sst[met->
nx][met->
ny] = help->
sst[ix][iy];
11380 met->
pbl[met->
nx][met->
ny] = help->
pbl[ix][iy];
11382 met->
cin[met->
nx][met->
ny] = help->
cin[ix][iy];
11384 for (
int ip = 0; ip < help->
np; ip += ctl->
met_dp) {
11385 met->
p[met->
np] = help->
p[ip];
11386 met->
t[met->
nx][met->
ny][met->
np] = help->
t[ix][iy][ip];
11387 met->
u[met->
nx][met->
ny][met->
np] = help->
u[ix][iy][ip];
11388 met->
v[met->
nx][met->
ny][met->
np] = help->
v[ix][iy][ip];
11389 met->
w[met->
nx][met->
ny][met->
np] = help->
w[ix][iy][ip];
11390 met->
h2o[met->
nx][met->
ny][met->
np] = help->
h2o[ix][iy][ip];
11391 met->
o3[met->
nx][met->
ny][met->
np] = help->
o3[ix][iy][ip];
11392 met->
lwc[met->
nx][met->
ny][met->
np] = help->
lwc[ix][iy][ip];
11393 met->
rwc[met->
nx][met->
ny][met->
np] = help->
rwc[ix][iy][ip];
11394 met->
iwc[met->
nx][met->
ny][met->
np] = help->
iwc[ix][iy][ip];
11395 met->
swc[met->
nx][met->
ny][met->
np] = help->
swc[ix][iy][ip];
11396 met->
cc[met->
nx][met->
ny][met->
np] = help->
cc[ix][iy][ip];
11415 double p2[200], pv[
EP], pv2[200], t[
EP], t2[200], th[
EP],
11416 th2[200], z[
EP], z2[200];
11420 LOG(2,
"Calculate tropopause...");
11423#pragma omp parallel for default(shared)
11424 for (
int iz = 0; iz < met->
np; iz++)
11425 z[iz] =
Z(met->
p[iz]);
11426#pragma omp parallel for default(shared)
11427 for (
int iz = 0; iz <= 190; iz++) {
11428 z2[iz] = 4.5 + 0.1 * iz;
11429 p2[iz] =
P(z2[iz]);
11434#pragma omp parallel for default(shared) collapse(2)
11435 for (
int ix = 0; ix < met->
nx; ix++)
11436 for (
int iy = 0; iy < met->
ny; iy++)
11437 met->
pt[ix][iy] = NAN;
11441#pragma omp parallel for default(shared) collapse(2)
11442 for (
int ix = 0; ix < met->
nx; ix++)
11443 for (
int iy = 0; iy < met->
ny; iy++)
11451#pragma omp parallel for default(shared) private(t,t2) collapse(2)
11452 for (
int ix = 0; ix < met->
nx; ix++)
11453 for (
int iy = 0; iy < met->
ny; iy++) {
11456 for (
int iz = 0; iz < met->
np; iz++)
11457 t[iz] = met->
t[ix][iy][iz];
11461 int iz = (int) gsl_stats_min_index(t2, 1, 171);
11462 if (iz > 0 && iz < 170)
11463 met->
pt[ix][iy] = (float) p2[iz];
11465 met->
pt[ix][iy] = NAN;
11473#pragma omp parallel for default(shared) private(t,t2) collapse(2)
11474 for (
int ix = 0; ix < met->
nx; ix++)
11475 for (
int iy = 0; iy < met->
ny; iy++) {
11479 for (iz = 0; iz < met->
np; iz++)
11480 t[iz] = met->
t[ix][iy][iz];
11484 met->
pt[ix][iy] = NAN;
11485 for (iz = 0; iz <= 170; iz++) {
11487 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
11488 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
11493 if (iz > 0 && iz < 170)
11494 met->
pt[ix][iy] = (float) p2[iz];
11501 met->
pt[ix][iy] = NAN;
11502 for (; iz <= 170; iz++) {
11504 for (
int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
11505 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
11512 for (; iz <= 170; iz++) {
11514 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
11515 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
11520 if (iz > 0 && iz < 170)
11521 met->
pt[ix][iy] = (float) p2[iz];
11533#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
11534 for (
int ix = 0; ix < met->
nx; ix++)
11535 for (
int iy = 0; iy < met->
ny; iy++) {
11538 for (
int iz = 0; iz < met->
np; iz++)
11539 pv[iz] = met->
pv[ix][iy][iz];
11543 for (
int iz = 0; iz < met->
np; iz++)
11544 th[iz] =
THETA(met->
p[iz], met->
t[ix][iy][iz]);
11548 met->
pt[ix][iy] = NAN;
11549 for (
int iz = 0; iz <= 170; iz++)
11552 if (iz > 0 && iz < 170)
11553 met->
pt[ix][iy] = (float) p2[iz];
11560 ERRMSG(
"Cannot calculate tropopause!");
11563#pragma omp parallel for default(shared) collapse(2)
11564 for (
int ix = 0; ix < met->
nx; ix++)
11565 for (
int iy = 0; iy < met->
ny; iy++) {
11566 double h2ot, tt, zt;
11569 met->
lat[iy], &tt, ci, cw, 1);
11571 met->
lat[iy], &zt, ci, cw, 0);
11573 met->
lat[iy], &h2ot, ci, cw, 0);
11574 met->
tt[ix][iy] = (float) tt;
11575 met->
zt[ix][iy] = (float) zt;
11576 met->
h2ot[ix][iy] = (float) h2ot;
11583 const char *filename,
11593 LOG(1,
"Read observation data: %s", filename);
11597 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
11599 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
11601 ERRMSG(
"Set OBS_TYPE to 0 or 1!");
11604 for (
int i = 1; i < *nobs; i++)
11605 if (rt[i] < rt[i - 1])
11606 ERRMSG(
"Time must be ascending!");
11611 LOG(2,
"Number of observations: %d", *nobs);
11612 gsl_stats_minmax(&mini, &maxi, rt, 1, (
size_t) n);
11613 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
11614 gsl_stats_minmax(&mini, &maxi, rz, 1, (
size_t) n);
11615 LOG(2,
"Altitude range: %g ... %g km", mini, maxi);
11616 gsl_stats_minmax(&mini, &maxi, rlon, 1, (
size_t) n);
11617 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
11618 gsl_stats_minmax(&mini, &maxi, rlat, 1, (
size_t) n);
11619 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
11620 gsl_stats_minmax(&mini, &maxi, robs, 1, (
size_t) n);
11621 LOG(2,
"Observation range: %g ... %g", mini, maxi);
11627 const char *filename,
11637 if (!(in = fopen(filename,
"r")))
11638 ERRMSG(
"Cannot open file!");
11642 while (fgets(line,
LEN, in))
11643 if (sscanf(line,
"%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
11644 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
11645 if ((++(*nobs)) >=
NOBS)
11646 ERRMSG(
"Too many observations!");
11655 const char *filename,
11666 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
11667 ERRMSG(
"Cannot open file!");
11678 NC(nc_close(ncid));
11684 const char *filename,
11687 const char *varname,
11689 const char *defvalue,
11694 char fullname1[
LEN], fullname2[
LEN], rval[
LEN];
11696 int contain = 0, i;
11699 if (filename[strlen(filename) - 1] !=
'-')
11700 if (!(in = fopen(filename,
"r")))
11701 ERRMSG(
"Cannot open file!");
11705 sprintf(fullname1,
"%s[%d]", varname, arridx);
11706 sprintf(fullname2,
"%s[*]", varname);
11708 sprintf(fullname1,
"%s", varname);
11709 sprintf(fullname2,
"%s", varname);
11714 char dummy[
LEN], line[
LEN], rvarname[
LEN];
11715 while (fgets(line,
LEN, in)) {
11716 if (sscanf(line,
"%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
11717 if (strcasecmp(rvarname, fullname1) == 0 ||
11718 strcasecmp(rvarname, fullname2) == 0) {
11724 for (i = 1; i < argc - 1; i++)
11725 if (strcasecmp(argv[i], fullname1) == 0 ||
11726 strcasecmp(argv[i], fullname2) == 0) {
11727 sprintf(rval,
"%s", argv[i + 1]);
11738 if (strlen(defvalue) > 0)
11739 sprintf(rval,
"%s", defvalue);
11741 ERRMSG(
"Missing variable %s!\n", fullname1);
11745 LOG(1,
"%s = %s", fullname1, rval);
11749 sprintf(value,
"%s", rval);
11759 const double rhop) {
11762 const double rp_help = rp * 1e-6;
11765 const double rho =
RHO(p, T);
11768 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
11771 const double v = sqrt(8. *
KB * T / (M_PI * 4.8096e-26));
11774 const double lambda = 2. * eta / (rho * v);
11777 const double K = lambda / rp_help;
11780 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
11783 return 2. *
SQR(rp_help) * (rhop - rho) *
G0 / (9. * eta) * G;
11795 const int method) {
11801 gsl_interp_accel *acc = gsl_interp_accel_alloc();
11802 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (
size_t) n);
11805 gsl_spline_init(s, x, y, (
size_t) n);
11806 for (
int i = 0; i < n2; i++)
11809 else if (x2[i] >= x[n - 1])
11812 y2[i] = gsl_spline_eval(s, x2[i], acc);
11815 gsl_spline_free(s);
11816 gsl_interp_accel_free(acc);
11821 for (
int i = 0; i < n2; i++)
11824 else if (x2[i] >= x[n - 1])
11828 y2[i] =
LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
11842 float mean = 0, var = 0;
11844 for (
int i = 0; i < n; ++i) {
11846 var +=
SQR(data[i]);
11849 var = var / (float) n -
SQR(mean / (
float) n);
11851 return (var > 0 ? sqrtf(var) : 0);
11863 const double remain,
11875 t1.tm_year = year - 1900;
11876 t1.tm_mon = mon - 1;
11882 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
11890 const int output) {
11897 static int iname = -1, igroup = -1, nname, ngroup, ct_name[
NTIMER];
11900 t1 = omp_get_wtime();
11905 rt_name[iname] += dt;
11906 rt_min[iname] = (ct_name[iname] <= 0 ? dt :
MIN(rt_min[iname], dt));
11907 rt_max[iname] = (ct_name[iname] <= 0 ? dt :
MAX(rt_max[iname], dt));
11911 rt_group[igroup] += t1 - t0;
11915 for (
int i = 0; i < nname; i++)
11916 LOG(1,
"TIMER_%s = %.3f s (min= %g s, mean= %g s,"
11917 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
11918 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
11919 for (
int i = 0; i < ngroup; i++)
11920 LOG(1,
"TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
11921 double total = 0.0;
11922 for (
int i = 0; i < nname; i++)
11923 total += rt_name[i];
11924 LOG(1,
"TIMER_TOTAL = %.3f s", total);
11928 for (iname = 0; iname < nname; iname++)
11929 if (strcasecmp(name, names[iname]) == 0)
11931 for (igroup = 0; igroup < ngroup; igroup++)
11932 if (strcasecmp(group, groups[igroup]) == 0)
11936 if (iname >= nname) {
11937 sprintf(names[iname],
"%s", name);
11938 if ((++nname) >=
NTIMER)
11939 ERRMSG(
"Too many timers!");
11943 if (igroup >= ngroup) {
11944 sprintf(groups[igroup],
"%s", group);
11945 if ((++ngroup) >=
NTIMER)
11946 ERRMSG(
"Too many groups!");
11956 const char *filename,
11957 const int offset) {
11964 int len = (int) strlen(filename);
11965 sprintf(tstr,
"%.4s", &filename[len - offset]);
11966 int year = atoi(tstr);
11967 sprintf(tstr,
"%.2s", &filename[len - offset + 5]);
11968 int mon = atoi(tstr);
11969 sprintf(tstr,
"%.2s", &filename[len - offset + 8]);
11970 int day = atoi(tstr);
11971 sprintf(tstr,
"%.2s", &filename[len - offset + 11]);
11972 int hour = atoi(tstr);
11973 sprintf(tstr,
"%.2s", &filename[len - offset + 14]);
11974 int min = atoi(tstr);
11977 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
11978 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
11979 ERRMSG(
"Cannot read time from filename!");
11982 time2jsec(year, mon, day, hour, min, 0, 0.0, &t);
11999 const double p1 = pt * 0.866877899;
12000 const double p0 = pt / 0.866877899;
12003 if (atm->
p[ip] > p0)
12005 else if (atm->
p[ip] < p1)
12008 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
12014 const char *filename,
12022 const double t0 = t - 0.5 * ctl->
dt_mod;
12023 const double t1 = t + 0.5 * ctl->
dt_mod;
12029 if (!(out = popen(
"gnuplot",
"w")))
12030 ERRMSG(
"Cannot create pipe to gnuplot!");
12033 fprintf(out,
"set out \"%s.png\"\n", filename);
12037 int year, mon, day, hour, min, sec;
12038 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
12039 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
12040 year, mon, day, hour, min);
12045 ERRMSG(
"Cannot open file!");
12047 while (fgets(line,
LEN, in))
12048 fprintf(out,
"%s", line);
12055 if (!(out = fopen(filename,
"w")))
12056 ERRMSG(
"Cannot create file!");
12061 "# $1 = time [s]\n"
12062 "# $2 = altitude [km]\n"
12063 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
12064 for (
int iq = 0; iq < ctl->
nq; iq++)
12065 fprintf(out,
"# $%i = %s [%s]\n", iq + 5, ctl->
qnt_name[iq],
12067 fprintf(out,
"\n");
12070 for (
int ip = 0; ip < atm->
np; ip += ctl->
atm_stride) {
12077 fprintf(out,
"%.2f %g %g %g", atm->
time[ip],
Z(atm->
p[ip]),
12078 atm->
lon[ip], atm->
lat[ip]);
12079 for (
int iq = 0; iq < ctl->
nq; iq++) {
12084 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
12086 fprintf(out,
"\n");
12096 const char *filename,
12098 const atm_t *atm) {
12103 if (!(out = fopen(filename,
"w")))
12104 ERRMSG(
"Cannot create file!");
12128 for (
int iq = 0; iq < ctl->
nq; iq++)
12146 const char *filename,
12148 const atm_t *atm) {
12150 int tid, pid, ncid, varid;
12151 size_t start[2], count[2];
12154 NC(nc_create(filename, NC_NETCDF4, &ncid));
12157 NC(nc_def_dim(ncid,
"time", 1, &tid));
12158 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
12161 int dim_ids[2] = { tid, pid };
12162 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
12163 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
12164 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
12166 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
12168 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
12171 for (
int iq = 0; iq < ctl->
nq; iq++)
12181 NC(nc_enddef(ncid));
12189 for (
int iq = 0; iq < ctl->
nq; iq++)
12193 NC(nc_close(ncid));
12199 const char *dirname,
12205 static size_t out_cnt = 0;
12207 double r, r_start, r_stop;
12208 int year, mon, day, hour, min, sec;
12209 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
12210 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
12211 char filename_out[2 *
LEN] =
"traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
12213 int ncid, varid, tid, pid, cid;
12221 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
12223 &min_start, &sec_start, &r_start);
12225 &min_stop, &sec_stop, &r_stop);
12227 sprintf(filename_out,
12228 "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc", dirname,
12229 year_start % 100, mon_start, day_start, hour_start,
12230 year_stop % 100, mon_stop, day_stop, hour_stop);
12231 LOG(1,
"Write traj file: %s", filename_out);
12234 start[0] = out_cnt;
12237 count[1] = (size_t) atm->
np;
12240 if (out_cnt == 0) {
12243 NC(nc_create(filename_out, NC_NETCDF4, &ncid));
12246 NC(nc_def_dim(ncid,
"time", NC_UNLIMITED, &tid));
12247 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
12248 NC(nc_def_dim(ncid,
"TMDT", 7, &cid));
12253 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
12254 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
12255 NC_DEF_VAR(
"LAT", NC_DOUBLE, 2, dim_ids,
"Latitude",
"deg",
12257 NC_DEF_VAR(
"LON", NC_DOUBLE, 2, dim_ids,
"Longitude",
"deg",
12259 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 2, dim_ids,
"Pressure",
"hPa",
12261 NC_DEF_VAR(
"ZETA", NC_DOUBLE, 2, dim_ids,
"Zeta",
"K",
12263 for (
int iq = 0; iq < ctl->
nq; iq++)
12273 NC(nc_enddef(ncid));
12274 NC(nc_close(ncid));
12281 NC(nc_open(filename_out, NC_WRITE, &ncid));
12293 for (
int iq = 0; iq < ctl->
nq; iq++)
12297 NC(nc_close(ncid));
12300 if ((year == year_stop) && (mon == mon_stop)
12301 && (day == day_stop) && (hour == hour_stop)) {
12304 char filename_init[2 *
LEN] =
"./init_fix_YYYYMMDDHH.nc";
12305 sprintf(filename_init,
"%s/init_fix_%02d%02d%02d%02d.nc",
12306 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
12307 LOG(1,
"Write init file: %s", filename_init);
12310 NC(nc_create(filename_init, NC_NETCDF4, &ncid));
12313 NC(nc_def_dim(ncid,
"time", 1, &tid));
12314 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
12319 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
12320 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
12321 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
12323 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
12325 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
12328 for (
int iq = 0; iq < ctl->
nq; iq++)
12338 NC(nc_enddef(ncid));
12346 for (
int iq = 0; iq < ctl->
nq; iq++)
12350 NC(nc_close(ncid));
12357 const char *filename,
12359 const atm_t *atm) {
12361 int ncid, obsid, varid;
12363 size_t start[2], count[2];
12366 NC(nc_create(filename, NC_NETCDF4, &ncid));
12369 NC(nc_def_dim(ncid,
"obs", (
size_t) atm->
np, &obsid));
12372 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &obsid,
"time",
12373 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
12374 NC_DEF_VAR(
"press", NC_DOUBLE, 1, &obsid,
"pressure",
"hPa",
12376 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &obsid,
"longitude",
"degrees_east",
12378 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &obsid,
"latitude",
"degrees_north",
12380 for (
int iq = 0; iq < ctl->
nq; iq++)
12389 NC(nc_enddef(ncid));
12396 for (
int iq = 0; iq < ctl->
nq; iq++)
12400 NC(nc_close(ncid));
12406 const char *filename,
12413 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
12416 static int *obscount, nobs, nk;
12420 const int ensemble = (ctl->
nens > 0);
12426 if (ctl->
qnt_m < 0)
12427 ERRMSG(
"Need quantity mass!");
12430 ERRMSG(
"Missing ensemble IDs!");
12432 ERRMSG(
"Too many ensembles!");
12439 ALLOC(area,
double,
12445 ALLOC(rlon,
double,
12447 ALLOC(rlat,
double,
12449 ALLOC(robs,
double,
12460 LOG(1,
"Write CSI%s data: %s", ensemble ?
" ensemble" :
"", filename);
12461 if (!(out = fopen(filename,
"w")))
12462 ERRMSG(
"Cannot create file!");
12466 "# $1 = time [s]\n"
12467 "# $2 = ensemble ID\n"
12468 "# $3 = number of hits (cx)\n"
12469 "# $4 = number of misses (cy)\n"
12470 "# $5 = number of false alarms (cz)\n"
12471 "# $6 = number of observations (cx + cy)\n"
12472 "# $7 = number of forecasts (cx + cz)\n"
12473 "# $8 = bias (%%)\n"
12474 "# $9 = POD (%%)\n"
12475 "# $10 = FAR (%%)\n"
12476 "# $11 = CSI (%%)\n"
12477 "# $12 = hits by random chance\n"
12478 "# $13 = ETS (%%)\n"
12479 "# $14 = Pearson R\n"
12480 "# $15 = Spearman R\n"
12481 "# $16 = mean error [kg/m²]\n"
12482 "# $17 = RMSE [kg/m²]\n"
12483 "# $18 = MAE [kg/m²]\n"
12484 "# $19 = log-likelihood\n" "# $20 = number of points\n\n");
12492 for (
int iy = 0; iy < ctl->
csi_ny; iy++) {
12493 const double lat = ctl->
csi_lat0 + dlat * (iy + 0.5);
12494 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.0) * cos(
DEG2RAD(lat));
12499 const double t0 = t - 0.5 * ctl->
dt_mod;
12500 const double t1 = t + 0.5 * ctl->
dt_mod;
12504 ALLOC(modmean,
double,
12505 (ensemble ? ctl->
nens : 1) * grid_size);
12506 ALLOC(obsmean,
double,
12508 ALLOC(obscount,
int,
12510 ALLOC(obsstd,
double,
12514 for (
int i = 0; i < (ensemble ? ctl->
nens : 1); i++)
12515 ct[i] = cx[i] = cy[i] = cz[i] = n[i] = 0;
12518 for (
int i = 0; i < nobs; i++) {
12519 if (rt[i] < t0 || rt[i] >= t1 || !isfinite(robs[i]))
12523 const int ix = (int) ((rlon[i] - ctl->
csi_lon0) / dlon);
12524 const int iy = (int) ((rlat[i] - ctl->
csi_lat0) / dlat);
12525 const int iz = (int) ((rz[i] - ctl->
csi_z0) / dz);
12526 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
12532 obsmean[idx] += robs[i];
12533 obsstd[idx] +=
SQR(robs[i]);
12538 for (
int ip = 0; ip < atm->
np; ip++) {
12541 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
12545 int ens_id = ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
12546 if (ens_id < 0 || ens_id >= (ensemble ? ctl->
nens : 1))
12547 ERRMSG(
"Ensemble ID out of range!");
12550 const int ix = (int) ((atm->
lon[ip] - ctl->
csi_lon0) / dlon);
12551 const int iy = (int) ((atm->
lat[ip] - ctl->
csi_lat0) / dlat);
12552 const int iz = (int) ((
Z(atm->
p[ip]) - ctl->
csi_z0) / dz);
12553 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
12563 for (
int e = 0; e < (ensemble ? ctl->
nens : 1); e++) {
12565 for (
int ix = 0; ix < ctl->
csi_nx; ix++)
12566 for (
int iy = 0; iy < ctl->
csi_ny; iy++)
12567 for (
int iz = 0; iz < ctl->
csi_nz; iz++) {
12572 if (obscount[idx]) {
12573 obsmean[idx] /= obscount[idx];
12575 sqrt(obsstd[idx] / obscount[idx] -
SQR(obsmean[idx]));
12579 const int midx = e * grid_size + idx;
12580 if (modmean[midx] > 0)
12581 modmean[midx] /= (1e6 * area[iy]);
12584 if (obscount[idx]) {
12599 x[n[e]] = modmean[midx];
12600 y[n[e]] = obsmean[idx];
12602 obsstdn[n[e]] = obsstd[idx];
12603 if ((++n[e]) >=
NCSI)
12604 ERRMSG(
"Too many points for statistics!");
12616 static double work[2 *
NCSI], work2[2 *
NCSI];
12617 const int n_obs = cx[e] + cy[e];
12618 const int n_for = cx[e] + cz[e];
12619 const double cx_rd = (ct[e] > 0) ? (1. * n_obs * n_for) / ct[e] : NAN;
12620 const double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
12621 const double pod = (n_obs > 0) ? 100. * cx[e] / n_obs : NAN;
12622 const double far = (n_for > 0) ? 100. * cz[e] / n_for : NAN;
12624 (cx[e] + cy[e] + cz[e] >
12625 0) ? 100. * cx[e] / (cx[e] + cy[e] + cz[e]) : NAN;
12627 (cx[e] + cy[e] + cz[e] - cx_rd >
12628 0) ? 100. * (cx[e] - cx_rd) / (cx[e] + cy[e] + cz[e] - cx_rd) : NAN;
12629 const double rho_p = gsl_stats_correlation(x, 1, y, 1, (
size_t) n[e]);
12630 const double rho_s =
12631 gsl_stats_spearman(x, 1, y, 1, (
size_t) n[e], work);
12632 for (
int i = 0; i < n[e]; i++) {
12633 work[i] = x[i] - y[i];
12634 work2[i] = (obsstdn[i] != 0) ? work[i] / obsstdn[i] : 0;
12636 const double mean = gsl_stats_mean(work, 1, (
size_t) n[e]);
12637 const double rmse =
12638 gsl_stats_sd_with_fixed_mean(work, 1, (
size_t) n[e], 0.0);
12639 const double absdev = gsl_stats_absdev_m(work, 1, (
size_t) n[e], 0.0);
12640 const double loglikelihood =
12641 gsl_stats_tss_m(work2, 1, (
size_t) n[e], 0.0) * -0.5;
12645 "%.2f %d %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n",
12646 t, ensemble ? e : -999, cx[e], cy[e], cz[e], n_obs, n_for, bias,
12647 pod, far, csi, cx_rd, ets, rho_p, rho_s, mean, rmse, absdev,
12648 loglikelihood, n[e]);
12651 for (
int i = 0; i < n[e]; i++)
12652 work[i] = work2[i] = x[i] = y[i] = obsstdn[i] = 0;
12653 ct[e] = cx[e] = cy[e] = cz[e] = n[e] = 0;
12681 const char *filename,
12691 static int n[
NENS];
12698 ERRMSG(
"Missing ensemble IDs!");
12701 const double t0 = t - 0.5 * ctl->
dt_mod;
12702 const double t1 = t + 0.5 * ctl->
dt_mod;
12705 for (
int i = 0; i <
NENS; i++) {
12706 for (
int iq = 0; iq < ctl->
nq; iq++)
12707 qm[iq][i] = qs[iq][i] = 0;
12708 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
12713 for (
int ip = 0; ip < atm->
np; ip++) {
12716 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
12721 ERRMSG(
"Ensemble ID is out of range!");
12725 for (
int iq = 0; iq < ctl->
nq; iq++) {
12726 qm[iq][ctl->
qnt_ens] += atm->
q[iq][ip];
12737 LOG(1,
"Write ensemble data: %s", filename);
12738 if (!(out = fopen(filename,
"w")))
12739 ERRMSG(
"Cannot create file!");
12743 "# $1 = time [s]\n"
12744 "# $2 = altitude [km]\n"
12745 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
12746 for (
int iq = 0; iq < ctl->
nq; iq++)
12747 fprintf(out,
"# $%d = %s (mean) [%s]\n", 5 + iq,
12749 for (
int iq = 0; iq < ctl->
nq; iq++)
12750 fprintf(out,
"# $%d = %s (sigma) [%s]\n", 5 + ctl->
nq + iq,
12752 fprintf(out,
"# $%d = number of members\n\n", 5 + 2 * ctl->
nq);
12755 for (
int i = 0; i <
NENS; i++)
12757 cart2geo(xm[i], &dummy, &lon, &lat);
12758 fprintf(out,
"%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
12759 for (
int iq = 0; iq < ctl->
nq; iq++) {
12761 fprintf(out, ctl->
qnt_format[iq], qm[iq][i] / n[i]);
12763 for (
int iq = 0; iq < ctl->
nq; iq++) {
12765 double var = qs[iq][i] / n[i] -
SQR(qm[iq][i] / n[i]);
12766 fprintf(out, ctl->
qnt_format[iq], (var > 0 ? sqrt(var) : 0));
12768 fprintf(out,
" %d\n", n[i]);
12778 const char *filename,
12785 static double kz[
EP], kw[
EP];
12789 double *cd, *mean[
NQ], *sigma[
NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
12791 int *ixs, *iys, *izs, *np;
12797 LOG(1,
"Write grid data: %s", filename);
12810 for (
int iq = 0; iq < ctl->
nq; iq++) {
12811 ALLOC(mean[iq],
double,
12813 ALLOC(sigma[iq],
double,
12816 ALLOC(vmr_impl,
double,
12824 ALLOC(area,
double,
12826 ALLOC(press,
double,
12843#pragma omp parallel
for default(shared)
12844 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
12845 z[iz] = ctl->
grid_z0 + dz * (iz + 0.5);
12846 press[iz] =
P(z[iz]);
12850 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12851 lon[ix] = ctl->
grid_lon0 + dlon * (ix + 0.5);
12852#pragma omp parallel for default(shared)
12853 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
12854 lat[iy] = ctl->
grid_lat0 + dlat * (iy + 0.5);
12855 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
12859 const double t0 = t - 0.5 * ctl->
dt_mod;
12860 const double t1 = t + 0.5 * ctl->
dt_mod;
12863#pragma omp parallel for default(shared)
12864 for (
int ip = 0; ip < atm->
np; ip++) {
12865 ixs[ip] = (int) ((atm->
lon[ip] - ctl->
grid_lon0) / dlon);
12866 iys[ip] = (int) ((atm->
lat[ip] - ctl->
grid_lat0) / dlat);
12867 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
grid_z0) / dz);
12868 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
12869 || ixs[ip] < 0 || ixs[ip] >= ctl->
grid_nx
12870 || iys[ip] < 0 || iys[ip] >= ctl->
grid_ny
12871 || izs[ip] < 0 || izs[ip] >= ctl->
grid_nz)
12876 for (
int ip = 0; ip < atm->
np; ip++)
12877 if (izs[ip] >= 0) {
12882 for (
int iq = 0; iq < ctl->
nq; iq++) {
12883 mean[iq][idx] += kernel * atm->
q[iq][ip];
12884 sigma[iq][idx] +=
SQR(kernel * atm->
q[iq][ip]);
12889#pragma omp parallel for default(shared)
12890 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12891 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12892 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
12899 if (ctl->
qnt_m >= 0)
12900 cd[idx] = mean[ctl->
qnt_m][idx] / (1e6 * area[iy]);
12903 vmr_impl[idx] = NAN;
12904 if (ctl->
qnt_m >= 0 && ctl->
molmass > 0 && met0 != NULL
12907 if (mean[ctl->
qnt_m][idx] > 0) {
12913 lon[ix], lat[iy], &temp, ci, cw, 1);
12917 MA / ctl->
molmass * cd[idx] / (
RHO(press[iz], temp) * dz * 1e3);
12923 for (
int iq = 0; iq < ctl->
nq; iq++) {
12924 mean[iq][idx] /= np[idx];
12925 const double var = sigma[iq][idx] / np[idx] -
SQR(mean[iq][idx]);
12926 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
12928 for (
int iq = 0; iq < ctl->
nq; iq++) {
12929 mean[iq][idx] = NAN;
12930 sigma[iq][idx] = NAN;
12937 t, z, lon, lat, area, dz, np);
12942 t, z, lon, lat, area, dz, np);
12946 ERRMSG(
"Grid data format GRID_TYPE unknown!");
12950 for (
int iq = 0; iq < ctl->
nq; iq++) {
12969 const char *filename,
12974 const double *vmr_impl,
12979 const double *area,
12989 if (!(out = popen(
"gnuplot",
"w")))
12990 ERRMSG(
"Cannot create pipe to gnuplot!");
12993 fprintf(out,
"set out \"%s.png\"\n", filename);
12997 int year, mon, day, hour, min, sec;
12998 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
12999 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
13000 year, mon, day, hour, min);
13006 ERRMSG(
"Cannot open file!");
13007 while (fgets(line,
LEN, in))
13008 fprintf(out,
"%s", line);
13015 if (!(out = fopen(filename,
"w")))
13016 ERRMSG(
"Cannot create file!");
13021 "# $1 = time [s]\n"
13022 "# $2 = altitude [km]\n"
13023 "# $3 = longitude [deg]\n"
13024 "# $4 = latitude [deg]\n"
13025 "# $5 = surface area [km^2]\n"
13026 "# $6 = layer depth [km]\n"
13027 "# $7 = column density (implicit) [kg/m^2]\n"
13028 "# $8 = volume mixing ratio (implicit) [ppv]\n"
13029 "# $9 = number of particles [1]\n");
13030 for (
int iq = 0; iq < ctl->
nq; iq++)
13031 fprintf(out,
"# $%i = %s (mean) [%s]\n", 10 + iq, ctl->
qnt_name[iq],
13034 for (
int iq = 0; iq < ctl->
nq; iq++)
13035 fprintf(out,
"# $%i = %s (stddev) [%s]\n", 10 + ctl->
nq + iq,
13037 fprintf(out,
"\n");
13040 for (
int ix = 0; ix < ctl->
grid_nx; ix++) {
13042 fprintf(out,
"\n");
13043 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
13045 fprintf(out,
"\n");
13046 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
13049 fprintf(out,
"%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
13050 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
13051 for (
int iq = 0; iq < ctl->
nq; iq++) {
13053 fprintf(out, ctl->
qnt_format[iq], mean[iq][idx]);
13056 for (
int iq = 0; iq < ctl->
nq; iq++) {
13058 fprintf(out, ctl->
qnt_format[iq], sigma[iq][idx]);
13060 fprintf(out,
"\n");
13073 const char *filename,
13078 const double *vmr_impl,
13083 const double *area,
13087 char longname[2 *
LEN], varname[2 *
LEN];
13091 int *help2, ncid, dimid[10], varid;
13093 size_t start[2], count[2];
13096 ALLOC(help,
double,
13102 NC(nc_create(filename, NC_NETCDF4, &ncid));
13105 NC(nc_def_dim(ncid,
"time", 1, &dimid[0]));
13106 NC(nc_def_dim(ncid,
"z", (
size_t) ctl->
grid_nz, &dimid[1]));
13107 NC(nc_def_dim(ncid,
"lat", (
size_t) ctl->
grid_ny, &dimid[2]));
13108 NC(nc_def_dim(ncid,
"lon", (
size_t) ctl->
grid_nx, &dimid[3]));
13109 NC(nc_def_dim(ncid,
"dz", 1, &dimid[4]));
13112 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &dimid[0],
"time",
13113 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
13114 NC_DEF_VAR(
"z", NC_DOUBLE, 1, &dimid[1],
"altitude",
"km", 0, 0);
13115 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &dimid[2],
"latitude",
"degrees_north", 0,
13117 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &dimid[3],
"longitude",
"degrees_east", 0,
13119 NC_DEF_VAR(
"dz", NC_DOUBLE, 1, &dimid[1],
"layer depth",
"km", 0, 0);
13120 NC_DEF_VAR(
"area", NC_DOUBLE, 1, &dimid[2],
"surface area",
"km**2", 0, 0);
13122 NC_DEF_VAR(
"cd", NC_FLOAT, 4, dimid,
"column density",
"kg m**-2",
13125 "volume mixing ratio (implicit)",
"ppv", ctl->
grid_nc_level, 0);
13126 NC_DEF_VAR(
"np", NC_INT, 4, dimid,
"number of particles",
"1", 0, 0);
13127 for (
int iq = 0; iq < ctl->
nq; iq++) {
13128 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
13129 sprintf(longname,
"%s (mean)", ctl->
qnt_longname[iq]);
13133 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
13134 sprintf(longname,
"%s (stddev)", ctl->
qnt_longname[iq]);
13140 NC(nc_enddef(ncid));
13150 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13151 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
13152 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
13157 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13158 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
13159 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
13164 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13165 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
13166 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
13171 for (
int iq = 0; iq < ctl->
nq; iq++) {
13172 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
13173 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13174 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
13175 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
13182 for (
int iq = 0; iq < ctl->
nq; iq++) {
13183 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
13184 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13185 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
13186 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
13193 NC(nc_close(ncid));
13203 const char *filename,
13208 FILE *out, *level_log = NULL;
13209 if (!(out = fopen(filename,
"w")))
13210 ERRMSG(
"Cannot create file!");
13214 ERRMSG(
"Cannot create compression log file!");
13294 ERRMSG(
"Number of meteo variables doesn't match!");
13314 const char *varname) {
13323 for (
int ix = 0; ix < met->
nx; ix++)
13324 for (
int iy = 0; iy < met->
ny; iy++)
13325 help[
ARRAY_2D(ix, iy, met->
ny)] = var[ix][iy];
13328 LOG(2,
"Write 2-D variable: %s (uncompressed)", varname);
13330 (
size_t) (met->
nx * met->
ny),
13344 const char *varname,
13355#pragma omp parallel for default(shared) collapse(2)
13356 for (
int ix = 0; ix < met->
nx; ix++)
13357 for (
int iy = 0; iy < met->
ny; iy++)
13358 for (
int ip = 0; ip < met->
np; ip++)
13359 help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)] = var[ix][iy][ip];
13363 LOG(2,
"Write 3-D variable: %s (uncompressed)", varname);
13365 (
size_t) (met->
nx * met->
ny * met->
np),
13379 const double tolerance = ctl->
met_zfp_tol[metvar];
13383 FWRITE(&tolerance,
double,
13412 (
size_t) met->
np, met->
p, 0, level_log, out);
13420 const double tolerance = ctl->
met_sz3_tol[metvar];
13424 FWRITE(&tolerance,
double,
13435 ERRMSG(
"MET_TYPE not supported!");
13438 LOG(3,
"%d", metvar);
13448 const char *filename,
13454 size_t start[4], count[4];
13455 NC(nc_create(filename, NC_NETCDF4, &ncid));
13458 int tid, lonid, latid, levid;
13459 NC(nc_def_dim(ncid,
"time", 1, &tid));
13460 NC(nc_def_dim(ncid,
"lon", (
size_t) met->
nx, &lonid));
13461 NC(nc_def_dim(ncid,
"lat", (
size_t) met->
ny, &latid));
13462 NC(nc_def_dim(ncid,
"lev", (
size_t) met->
np, &levid));
13465 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"time",
13466 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
13467 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &lonid,
"longitude",
"degrees_east", 0, 0);
13468 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &latid,
"latitude",
"degrees_north", 0, 0);
13469 NC_DEF_VAR(
"lev", NC_DOUBLE, 1, &levid,
"pressure",
"Pa", 0, 0);
13472 int dimid2[2] = { latid, lonid };
13473 NC_DEF_VAR(
"sp", NC_FLOAT, 2, dimid2,
"Surface pressure",
"Pa",
13475 NC_DEF_VAR(
"z", NC_FLOAT, 2, dimid2,
"Geopotential",
"m**2 s**-2",
13477 NC_DEF_VAR(
"t2m", NC_FLOAT, 2, dimid2,
"2 metre temperature",
"K",
13479 NC_DEF_VAR(
"u10m", NC_FLOAT, 2, dimid2,
"10 metre U wind component",
13481 NC_DEF_VAR(
"v10m", NC_FLOAT, 2, dimid2,
"10 metre V wind component",
13484 "Instantaneous eastward turbulent surface stress",
"N m**-2",
13487 "Instantaneous northward turbulent surface stress",
"N m**-2",
13490 "Instantaneous surface sensible heat flux",
"W m**-1",
13492 NC_DEF_VAR(
"lsm", NC_FLOAT, 2, dimid2,
"Land/sea mask",
"-",
13494 NC_DEF_VAR(
"sstk", NC_FLOAT, 2, dimid2,
"Sea surface temperature",
"K",
13496 NC_DEF_VAR(
"blp", NC_FLOAT, 2, dimid2,
"Boundary layer pressure",
"Pa",
13498 NC_DEF_VAR(
"pt", NC_FLOAT, 2, dimid2,
"Tropopause pressure",
"Pa",
13500 NC_DEF_VAR(
"tt", NC_FLOAT, 2, dimid2,
"Tropopause temperature",
"K",
13502 NC_DEF_VAR(
"zt", NC_FLOAT, 2, dimid2,
"Tropopause height",
"m",
13504 NC_DEF_VAR(
"h2ot", NC_FLOAT, 2, dimid2,
"Tropopause water vapor",
"ppv",
13506 NC_DEF_VAR(
"pct", NC_FLOAT, 2, dimid2,
"Cloud top pressure",
"Pa",
13508 NC_DEF_VAR(
"pcb", NC_FLOAT, 2, dimid2,
"Cloud bottom pressure",
"Pa",
13510 NC_DEF_VAR(
"cl", NC_FLOAT, 2, dimid2,
"Total column cloud water",
13513 "Pressure at lifted condensation level (LCL)",
"Pa",
13516 "Pressure at level of free convection (LFC)",
"Pa",
13519 "Pressure at equilibrium level (EL)",
"Pa", ctl->
met_nc_level,
13522 "Convective available potential energy",
"J kg**-1",
13524 NC_DEF_VAR(
"cin", NC_FLOAT, 2, dimid2,
"Convective inhibition",
13526 NC_DEF_VAR(
"o3c", NC_FLOAT, 2, dimid2,
"Total column ozone",
"DU",
13530 int dimid3[3] = { levid, latid, lonid };
13531 NC_DEF_VAR(
"t", NC_FLOAT, 3, dimid3,
"Temperature",
"K",
13533 NC_DEF_VAR(
"u", NC_FLOAT, 3, dimid3,
"U velocity",
"m s**-1",
13535 NC_DEF_VAR(
"v", NC_FLOAT, 3, dimid3,
"V velocity",
"m s**-1",
13537 NC_DEF_VAR(
"w", NC_FLOAT, 3, dimid3,
"Vertical velocity",
"Pa s**-1",
13539 NC_DEF_VAR(
"q", NC_FLOAT, 3, dimid3,
"Specific humidity",
"kg kg**-1",
13541 NC_DEF_VAR(
"o3", NC_FLOAT, 3, dimid3,
"Ozone mass mixing ratio",
13543 NC_DEF_VAR(
"clwc", NC_FLOAT, 3, dimid3,
"Cloud liquid water content",
13545 NC_DEF_VAR(
"crwc", NC_FLOAT, 3, dimid3,
"Cloud rain water content",
13547 NC_DEF_VAR(
"ciwc", NC_FLOAT, 3, dimid3,
"Cloud ice water content",
13549 NC_DEF_VAR(
"cswc", NC_FLOAT, 3, dimid3,
"Cloud snow water content",
13551 NC_DEF_VAR(
"cc", NC_FLOAT, 3, dimid3,
"Cloud cover",
"-",
13555 NC(nc_enddef(ncid));
13562 for (
int ip = 0; ip < met->
np; ip++)
13563 phelp[ip] = 100. * met->
p[ip];
13606 NC(nc_close(ncid));
13613 const char *varname,
13619 size_t start[4], count[4];
13627 for (
int ix = 0; ix < met->
nx; ix++)
13628 for (
int iy = 0; iy < met->
ny; iy++)
13629 help[
ARRAY_2D(iy, ix, met->
nx)] = scl * var[ix][iy];
13632 LOG(2,
"Write 2-D variable: %s (netCDF)", varname);
13643 const char *varname,
13649 size_t start[4], count[4];
13657 for (
int ix = 0; ix < met->
nx; ix++)
13658 for (
int iy = 0; iy < met->
ny; iy++)
13659 for (
int ip = 0; ip < met->
np; ip++)
13660 help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)] = scl * var[ix][iy][ip];
13663 LOG(2,
"Write 3-D variable: %s (netCDF)", varname);
13673 const char *filename,
13682 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
13683 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
13685 static int nobs, *obscount, ip, okay;
13694 if (ctl->
qnt_m < 0)
13695 ERRMSG(
"Need quantity mass!");
13699 ERRMSG(
"Specify molar mass!");
13706 ALLOC(area,
double,
13710 ALLOC(press,
double,
13716 ALLOC(rlon,
double,
13718 ALLOC(rlat,
double,
13720 ALLOC(robs,
double,
13727 LOG(1,
"Write profile data: %s", filename);
13728 if (!(out = fopen(filename,
"w")))
13729 ERRMSG(
"Cannot create file!");
13733 "# $1 = time [s]\n"
13734 "# $2 = altitude [km]\n"
13735 "# $3 = longitude [deg]\n"
13736 "# $4 = latitude [deg]\n"
13737 "# $5 = pressure [hPa]\n"
13738 "# $6 = temperature [K]\n"
13739 "# $7 = volume mixing ratio [ppv]\n"
13740 "# $8 = H2O volume mixing ratio [ppv]\n"
13741 "# $9 = O3 volume mixing ratio [ppv]\n"
13742 "# $10 = observed BT index [K]\n"
13743 "# $11 = number of observations\n");
13751 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
13752 z[iz] = ctl->
prof_z0 + dz * (iz + 0.5);
13753 press[iz] =
P(z[iz]);
13757 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
13758 lon[ix] = ctl->
prof_lon0 + dlon * (ix + 0.5);
13759 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
13760 lat[iy] = ctl->
prof_lat0 + dlat * (iy + 0.5);
13761 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
13766 const double t0 = t - 0.5 * ctl->
dt_mod;
13767 const double t1 = t + 0.5 * ctl->
dt_mod;
13770 ALLOC(mass,
double,
13772 ALLOC(obsmean,
double,
13774 ALLOC(obscount,
int,
13778 for (
int i = 0; i < nobs; i++) {
13783 else if (rt[i] >= t1)
13787 if (!isfinite(robs[i]))
13791 const int ix = (int) ((rlon[i] - ctl->
prof_lon0) / dlon);
13792 const int iy = (int) ((rlat[i] - ctl->
prof_lat0) / dlat);
13795 if (ix < 0 || ix >= ctl->
prof_nx || iy < 0 || iy >= ctl->
prof_ny)
13800 obsmean[idx] += robs[i];
13805 for (ip = 0; ip < atm->
np; ip++) {
13808 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13812 const int ix = (int) ((atm->
lon[ip] - ctl->
prof_lon0) / dlon);
13813 const int iy = (int) ((atm->
lat[ip] - ctl->
prof_lat0) / dlat);
13814 const int iz = (int) ((
Z(atm->
p[ip]) - ctl->
prof_z0) / dz);
13817 if (ix < 0 || ix >= ctl->
prof_nx ||
13823 mass[idx] += atm->
q[ctl->
qnt_m][ip];
13827 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
13828 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
13830 if (obscount[idx2] > 0) {
13834 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
13836 if (mass[idx3] > 0) {
13845 fprintf(out,
"\n");
13848 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
13853 lon[ix], lat[iy], &temp, ci, cw, 1);
13855 lon[ix], lat[iy], &h2o, ci, cw, 0);
13857 lon[ix], lat[iy], &o3, ci, cw, 0);
13862 / (
RHO(press[iz], temp) * area[iy] * dz * 1e9);
13865 fprintf(out,
"%.2f %g %g %g %g %g %g %g %g %g %d\n",
13866 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
13867 obsmean[idx2] / obscount[idx2], obscount[idx2]);
13900 const char *filename,
13909 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[
EP],
13912 static int nobs, nk;
13925 ALLOC(rlon,
double,
13927 ALLOC(rlat,
double,
13929 ALLOC(robs,
double,
13940 LOG(1,
"Write sample data: %s", filename);
13941 if (!(out = fopen(filename,
"w")))
13942 ERRMSG(
"Cannot create file!");
13946 "# $1 = time [s]\n"
13947 "# $2 = altitude [km]\n"
13948 "# $3 = longitude [deg]\n"
13949 "# $4 = latitude [deg]\n"
13950 "# $5 = surface area [km^2]\n"
13951 "# $6 = layer depth [km]\n"
13952 "# $7 = number of particles [1]\n"
13953 "# $8 = column density [kg/m^2]\n"
13954 "# $9 = volume mixing ratio [ppv]\n"
13955 "# $10 = observed BT index [K]\n\n");
13960 area = M_PI * rmax2;
13964 const double t0 = t - 0.5 * ctl->
dt_mod;
13965 const double t1 = t + 0.5 * ctl->
dt_mod;
13968 for (
int i = 0; i < nobs; i++) {
13973 else if (rt[i] >= t1)
13978 geo2cart(0, rlon[i], rlat[i], x0);
13981 const double rp =
P(rz[i]);
13982 const double ptop =
P(rz[i] + ctl->
sample_dz);
13983 const double pbot =
P(rz[i] - ctl->
sample_dz);
13991 for (
int ip = 0; ip < atm->
np; ip++) {
13994 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13998 if (fabs(rlat[i] - atm->
lat[ip]) > dlat)
14004 if (
DIST2(x0, x1) > rmax2)
14009 if (atm->
p[ip] > pbot || atm->
p[ip] < ptop)
14013 if (ctl->
qnt_m >= 0)
14020 const double cd = mass / (1e6 * area);
14031 rlon[i], rlat[i], &temp, ci, cw, 1);
14040 fprintf(out,
"%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
14041 rlon[i], rlat[i], area, ctl->
sample_dz, np, cd, vmr, robs[i]);
14062 const char *filename,
14069 static double rmax2, x0[3], x1[3];
14078 LOG(1,
"Write station data: %s", filename);
14081 if (!(out = fopen(filename,
"w")))
14082 ERRMSG(
"Cannot create file!");
14086 "# $1 = time [s]\n"
14087 "# $2 = altitude [km]\n"
14088 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
14089 for (
int iq = 0; iq < ctl->
nq; iq++)
14090 fprintf(out,
"# $%i = %s [%s]\n", (iq + 5),
14092 fprintf(out,
"\n");
14100 const double t0 = t - 0.5 * ctl->
dt_mod;
14101 const double t1 = t + 0.5 * ctl->
dt_mod;
14104 for (
int ip = 0; ip < atm->
np; ip++) {
14107 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
14123 if (
DIST2(x0, x1) > rmax2)
14131 fprintf(out,
"%.2f %g %g %g",
14132 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]);
14133 for (
int iq = 0; iq < ctl->
nq; iq++) {
14135 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
14137 fprintf(out,
"\n");
14148 const char *filename,
14159 LOG(1,
"Write VTK data: %s", filename);
14162 const double t0 = t - 0.5 * ctl->
dt_mod;
14163 const double t1 = t + 0.5 * ctl->
dt_mod;
14166 if (!(out = fopen(filename,
"w")))
14167 ERRMSG(
"Cannot create file!");
14171 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
14172 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
14179 "# vtk DataFile Version 3.0\n"
14180 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
14183 fprintf(out,
"POINTS %d float\n", np);
14185 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
14186 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
14190 const double coslat = cos(
DEG2RAD(atm->
lat[ip]));
14191 const double x = radius * coslat * cos(
DEG2RAD(atm->
lon[ip]));
14192 const double y = radius * coslat * sin(
DEG2RAD(atm->
lon[ip]));
14193 const double z = radius * sin(
DEG2RAD(atm->
lat[ip]));
14194 fprintf(out,
"%g %g %g\n", x, y, z);
14197 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
14198 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
14200 fprintf(out,
"%g %g %g\n", atm->
lon[ip], atm->
lat[ip],
14205 fprintf(out,
"POINT_DATA %d\n", np);
14206 for (
int iq = 0; iq < ctl->
nq; iq++) {
14207 fprintf(out,
"SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
14209 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
14210 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
14212 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.
void compress_pck(const char *varname, float *array, const size_t nxy, const size_t nz, const double *plev, const int decompress, const int pck_zstd, const int zstd_level, const int zstd_nworkers, FILE *level_log, FILE *inout)
Compresses or decompresses a 3D array of floats.
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 read_met_monotonize(const ctl_t *ctl, met_t *met)
Makes zeta and pressure profiles monotone.
int read_clim_ts(const char *filename, clim_ts_t *ts)
Reads a climatological time series from a file and populates the given time series structure.
void read_met_periodic(met_t *met)
Applies periodic boundary conditions to meteorological data along longitudinal axis.
void mptrac_run_timestep(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t **met0, met_t **met1, atm_t *atm, double t, dd_t *dd)
Executes a single timestep of the MPTRAC model simulation.
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.
double compress_speed_mib(const size_t nbytes, const double dt)
Calculate compression throughput in MiB/s.
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.
double time_from_filename(const char *filename, const int offset)
Extracts and converts a timestamp from a filename to Julian seconds.
void write_prof(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes profile data to a specified file.
void mptrac_read_clim(const ctl_t *ctl, clim_t *clim)
Reads various climatological data and populates the given climatology structure.
double tropo_weight(const clim_t *clim, const atm_t *atm, const int ip)
Computes a weighting factor based on tropopause pressure.
void 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.
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 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.
void compress_cms(const ctl_t *ctl, const char *varname, float *array, const size_t nx, const size_t ny, const size_t np, const double *plev, const int decompress, FILE *level_log, FILE *inout)
Compresses or decompresses a 3-D meteorological field using cmultiscale.
#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.
void compress_sz3(const char *varname, float *array, const int nx, const int ny, const int nz, const double *plev, const int precision, const double tolerance, const int lossy_scale, const int decompress, FILE *level_log, FILE *inout)
Compresses or decompresses a 3-D float array using the SZ3 library.
#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.
void compress_zstd(const char *varname, float *array, const size_t nxy, const size_t nz, const double *plev, const int decompress, const int level, const int nworkers, FILE *level_log, FILE *inout)
Compresses or decompresses a float array using Zstandard (ZSTD).
#define ECC_READ_3D(variable, level, target, scaling_factor, found_flag)
Writes 3D data from a grib message into the meteo struct.
#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.
#define INTPOL_3D(var, init)
Perform 3D interpolation for a meteorological variable.
#define NOBS
Maximum number of observation data points.
#define NTHREADS
Maximum number of OpenMP threads.
#define ARRAY_2D(ix, iy, ny)
Macro for computing the linear index of a 2D array element.
#define Z(p)
Convert pressure to altitude.
#define codes_handle
Placeholder when ECCODES is not available.
#define P(z)
Compute pressure at given altitude.
#define LV
Latent heat of vaporization of water [J/kg].
#define G0
Standard gravity [m/s^2].
#define CP
Maximum number of pressure levels for climatological data.
#define NQ
Maximum number of quantities per data point.
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 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).
#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.
void compress_lz4(const char *varname, float *array, const size_t nxy, const size_t nz, const double *plev, const int decompress, const int acceleration, FILE *level_log, FILE *inout)
Compresses or decompresses a float array using LZ4.
#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.
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.
void compress_zfp(const char *varname, float *array, const int nx, const int ny, const int nz, const double *plev, const int precision, const double tolerance, const int lossy_scale, const int decompress, FILE *level_log, FILE *inout)
Compresses or decompresses a 3D array of floats using the ZFP library.
#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 CPD
Specific heat of dry air at constant pressure [J/(kg K)].
#define CSZA
Maximum number of solar zenith angles for climatological data.
#define DY2DEG(dy)
Convert a distance in kilometers to degrees latitude.
#define MAX(a, b)
Macro to determine the maximum of two values.
#define FMOD(x, y)
Calculate the floating-point remainder of dividing x by y.
double lat[NP]
Latitude [deg].
double lon[NP]
Longitude [deg].
int np
Number of air parcels.
double q[NQ][NP]
Quantity data (for various, user-defined attributes).
double p[NP]
Pressure [hPa].
double dt[NP]
Timesteps [s].
double iso_ts[NP]
Isosurface balloon time [s].
int iso_n
Isosurface balloon number of data points.
double iso_ps[NP]
Isosurface balloon pressure [hPa].
double rs[3 *NP+1]
Random numbers.
float uvwp[NP][3]
Wind perturbations [m/s].
double iso_var[NP]
Isosurface variables.
Climatological data in the form of photolysis rates.
int nsza
Number of solar zenith angles.
double sza[CSZA]
Solar zenith angle [rad].
double o3_1[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O1d + O2) [1/s].
double p[CP]
Pressure [hPa].
double ccl2f2[CP][CSZA][CO3]
CCl2F2 photolysis rate [1/s].
double o2[CP][CSZA][CO3]
O2 photolysis rate [1/s].
double ccl3f[CP][CSZA][CO3]
CCl3F photolysis rate [1/s].
double n2o[CP][CSZA][CO3]
N2O photolysis rate [1/s].
double h2o2[CP][CSZA][CO3]
H2O2 photolysis rate [1/s].
double h2o[CP][CSZA][CO3]
H2O photolysis rate [1/s].
double ccl4[CP][CSZA][CO3]
CCl4 photolysis rate [1/s].
double o3_2[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O3p + O2) [1/s].
double o3c[CO3]
Total column ozone [DU].
int np
Number of pressure levels.
int no3c
Number of total ozone columns.
clim_ts_t ccl2f2
CFC-12 time series.
clim_photo_t photo
Photolysis rates.
clim_zm_t ho2
HO2 zonal means.
clim_zm_t hno3
HNO3 zonal means.
int tropo_ntime
Number of tropopause timesteps.
clim_ts_t sf6
SF6 time series.
clim_ts_t ccl4
CFC-10 time series.
clim_ts_t ccl3f
CFC-11 time series.
clim_zm_t o1d
O(1D) zonal means.
double tropo_lat[73]
Tropopause latitudes [deg].
clim_zm_t h2o2
H2O2 zonal means.
int tropo_nlat
Number of tropopause latitudes.
clim_zm_t oh
OH zonal means.
double tropo[12][73]
Tropopause pressure values [hPa].
double tropo_time[12]
Tropopause time steps [s].
clim_ts_t n2o
N2O time series.
Climatological data in the form of time series.
double vmr[CTS]
Volume mixing ratio [ppv].
double time[CTS]
Time [s].
int ntime
Number of timesteps.
Climatological data in the form of zonal means.
int np
Number of pressure levels.
double p[CP]
Pressure [hPa].
double vmr[CT][CP][CY]
Volume mixing ratio [ppv].
int ntime
Number of timesteps.
int nlat
Number of latitudes.
double lat[CY]
Latitude [deg].
double grid_z0
Lower altitude of gridded data [km].
int qnt_o3
Quantity array index for ozone volume mixing ratio.
double csi_lat1
Upper latitude of gridded CSI data [deg].
char csi_obsfile[LEN]
Observation data file for CSI analysis.
int qnt_Coh
Quantity array index for OH volume mixing ratio (chemistry code).
double wet_depo_ic_a
Coefficient A for wet deposition in cloud (exponential form).
int met_nc_scale
Check netCDF scaling factors (0=no, 1=yes).
int qnt_pel
Quantity array index for pressure at equilibrium level (EL).
int csi_nz
Number of altitudes of gridded CSI data.
double molmass
Molar mass [g/mol].
int qnt_p
Quantity array index for pressure.
int qnt_Cccl2f2
Quantity array index for CFC-12 volume mixing ratio (chemistry code).
int dd_halos_size
Domain decomposition size of halos given in grid-points.
char atm_gpfile[LEN]
Gnuplot file for atmospheric data.
int mixing_nx
Number of longitudes of mixing grid.
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).
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 scheme (0=off, 1=fixed-K, 2=PBL).
int qnt_tnat
Quantity array index for T_NAT.
int qnt_eta_dot
Quantity array index for velocity of eta vertical coordinate.
int qnt_tice
Quantity array index for T_ice.
int qnt_zg
Quantity array index for geopotential height.
double vtk_offset
Vertical offset for VTK data [km].
int qnt_v
Quantity array index for meridional wind.
int qnt_mloss_dry
Quantity array index for total mass loss due to dry deposition.
double bound_vmr_trend
Boundary conditions volume mixing ratio trend [ppv/s].
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 (0=off, 1=Euler, 2=midpoint, 4=Runge-Kutta).
double prof_z1
Upper altitude of gridded profile data [km].
double met_lev_hyam[EP]
Meteo data model level a coefficients.
int qnt_t
Quantity array index for temperature.
int atm_filter
Time filter for atmospheric data output (0=none, 1=missval, 2=remove).
int kpp_chem
Switch for KPP chemistry module (0=off, 1=on).
int qnt_zeta
Quantity array index for zeta vertical coordinate.
double conv_pbl_trans
Depth of PBL transition layer (fraction of PBL depth).
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 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 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).