35static uint64_t rng_ctr;
39static curandGenerator_t rng_curand;
49#define CHUNK_SIZE 2147483647
52 MPI_Bcast(&N, 1, MPI_UINT64_T, 0, MPI_COMM_WORLD);
55 const size_t num_chunks = (N + CHUNK_SIZE - 1) / CHUNK_SIZE;
58 for (
size_t i = 0; i < num_chunks; i++) {
61 const size_t start = i * CHUNK_SIZE;
62 const size_t end = (start + CHUNK_SIZE > N) ? N : start + CHUNK_SIZE;
63 const size_t chunk_size = end - start;
66 MPI_Bcast((
char *) data + start, (
int) chunk_size, MPI_BYTE, 0,
80 const double radius = sqrt(
DOTP(x, x));
82 *lat =
RAD2DEG(asin(x[2] / radius));
83 *lon =
RAD2DEG(atan2(x[1], x[0]));
98 const double sza_thresh =
DEG2RAD(85.), csza_thresh = cos(sza_thresh);
101 const double lat_ref =
104 while (lon_ref < -180.0)
106 while (lon_ref >= 180.0)
110 const double oh =
clim_zm(&clim->
oh, t, lat_ref, p);
117 const double csza =
cos_sza(t, lon_ref, lat_ref);
118 const double denom = (csza >= csza_thresh) ? csza : csza_thresh;
129 const double sza_thresh =
DEG2RAD(85.), csza_thresh = cos(sza_thresh);
132 for (
int it = 0; it < clim->
oh.
ntime; it++)
133 for (
int iz = 0; iz < clim->
oh.
np; iz++)
134 for (
int iy = 0; iy < clim->
oh.
nlat; iy++) {
141 for (
double lon = -180; lon < 180; lon += 1.0) {
144 const double denom = (csza >= csza_thresh) ? csza : csza_thresh;
150 clim->
oh.
vmr[it][iz][iy] /= (sum / (double) n);
165 if (p < photo->p[photo->
np - 1])
166 p_help = photo->
p[photo->
np - 1];
167 else if (p > photo->
p[0])
168 p_help = photo->
p[0];
171 double sza_help = sza;
172 if (sza < photo->sza[0])
173 sza_help = photo->
sza[0];
174 else if (sza > photo->
sza[photo->
nsza - 1])
175 sza_help = photo->
sza[photo->
nsza - 1];
178 double o3c_help = o3c;
179 if (o3c < photo->o3c[0])
180 o3c_help = photo->
o3c[0];
181 else if (o3c > photo->
o3c[photo->
no3c - 1])
182 o3c_help = photo->
o3c[photo->
no3c - 1];
190 const double aux00 =
LIN(photo->
p[ip], rate[ip][isza][io3c],
191 photo->
p[ip + 1], rate[ip + 1][isza][io3c],
193 const double aux01 =
LIN(photo->
p[ip], rate[ip][isza][io3c + 1],
194 photo->
p[ip + 1], rate[ip + 1][isza][io3c + 1],
196 const double aux10 =
LIN(photo->
p[ip], rate[ip][isza + 1][io3c],
197 photo->
p[ip + 1], rate[ip + 1][isza + 1][io3c],
199 const double aux11 =
LIN(photo->
p[ip], rate[ip][isza + 1][io3c + 1],
200 photo->
p[ip + 1], rate[ip + 1][isza + 1][io3c + 1],
203 LIN(photo->
o3c[io3c], aux00, photo->
o3c[io3c + 1], aux01, o3c_help);
205 LIN(photo->
o3c[io3c], aux10, photo->
o3c[io3c + 1], aux11, o3c_help);
207 LIN(photo->
sza[isza], aux0, photo->
sza[isza + 1], aux1, sza_help);
208 return MAX(aux, 0.0);
219 double sec =
FMOD(t, 365.25 * 86400.);
221 sec += 365.25 * 86400.;
229 clim->
tropo[isec][ilat],
231 clim->
tropo[isec][ilat + 1], lat);
233 clim->
tropo[isec + 1][ilat],
235 clim->
tropo[isec + 1][ilat + 1], lat);
245 LOG(1,
"Initialize tropopause data...");
249 double tropo_time[12] = {
250 1209600.00, 3888000.00, 6393600.00,
251 9072000.00, 11664000.00, 14342400.00,
252 16934400.00, 19612800.00, 22291200.00,
253 24883200.00, 27561600.00, 30153600.00
259 const double tropo_lat[73] = {
260 -90, -87.5, -85, -82.5, -80, -77.5, -75, -72.5, -70, -67.5,
261 -65, -62.5, -60, -57.5, -55, -52.5, -50, -47.5, -45, -42.5,
262 -40, -37.5, -35, -32.5, -30, -27.5, -25, -22.5, -20, -17.5,
263 -15, -12.5, -10, -7.5, -5, -2.5, 0, 2.5, 5, 7.5, 10, 12.5,
264 15, 17.5, 20, 22.5, 25, 27.5, 30, 32.5, 35, 37.5, 40, 42.5,
265 45, 47.5, 50, 52.5, 55, 57.5, 60, 62.5, 65, 67.5, 70, 72.5,
266 75, 77.5, 80, 82.5, 85, 87.5, 90
271 const double tropo[12][73] = {
272 {324.1, 325.6, 325, 324.3, 322.5, 319.7, 314, 307.2, 301.8, 299.6,
273 297.1, 292.2, 285.6, 276.1, 264, 248.9, 231.9, 213.5, 194.4,
274 175.3, 157, 140.4, 126.7, 116.3, 109.5, 105.4, 103, 101.4, 100.4,
275 99.69, 99.19, 98.84, 98.56, 98.39, 98.39, 98.42, 98.44, 98.54,
276 98.68, 98.81, 98.89, 98.96, 99.12, 99.65, 101.4, 105.4, 113.5, 128,
277 152.1, 184.7, 214, 234.1, 247.3, 255.8, 262.6, 267.7, 271.7, 275,
278 277.2, 279, 280.1, 280.4, 280.6, 280.1, 279.3, 278.3, 276.8, 275.8,
279 275.3, 275.6, 275.4, 274.1, 273.5},
280 {337.3, 338.7, 337.8, 336.4, 333, 328.8, 321.1, 312.6, 306.6, 303.7,
281 300.2, 293.8, 285.4, 273.8, 259.6, 242.7, 224.4, 205.2, 186, 167.5,
282 150.3, 135, 122.8, 113.9, 108.2, 104.7, 102.5, 101.1, 100.2, 99.42,
283 98.88, 98.52, 98.25, 98.09, 98.07, 98.1, 98.12, 98.2, 98.25, 98.27,
284 98.26, 98.27, 98.36, 98.79, 100.2, 104.2, 113.7, 131.2, 159.5, 193,
285 220.4, 238.1, 250.2, 258.1, 264.7, 269.7, 273.7, 277.3, 280.2, 282.8,
286 284.9, 286.5, 288.1, 288.8, 289, 288.5, 287.2, 286.3, 286.1, 287.2,
287 287.5, 286.2, 285.8},
288 {335, 336, 335.7, 335.1, 332.3, 328.1, 320.6, 311.8, 305.1, 301.9,
289 297.6, 290, 280.4, 268.3, 254.6, 239.6, 223.9, 207.9, 192.2, 176.9,
290 161.7, 146.4, 132.2, 120.6, 112.3, 107.2, 104.3, 102.4, 101.3,
291 100.4, 99.86, 99.47, 99.16, 98.97, 98.94, 98.97, 99, 99.09, 99.2,
292 99.31, 99.35, 99.41, 99.51, 99.86, 101.1, 104.9, 114.3, 131, 156.8,
293 186.3, 209.3, 224.6, 236.8, 246.3, 254.9, 262.3, 268.8, 274.8,
294 279.9, 284.6, 288.6, 291.6, 294.9, 297.5, 299.8, 301.8, 303.1,
295 304.3, 304.9, 306, 306.6, 306.2, 306},
296 {306.2, 306.7, 305.7, 307.1, 307.3, 306.4, 301.8, 296.2, 292.4,
297 290.3, 287.1, 280.9, 273.4, 264.3, 254.1, 242.8, 231, 219, 207.2,
298 195.5, 183.3, 169.7, 154.7, 138.7, 124.1, 113.6, 107.8, 104.7,
299 102.8, 101.7, 100.9, 100.4, 100, 99.79, 99.7, 99.66, 99.68, 99.79,
300 99.94, 100.2, 100.5, 100.9, 101.4, 102.1, 103.4, 107, 115.2, 129.1,
301 148.7, 171, 190.8, 205.6, 218.4, 229.4, 239.6, 248.6, 256.5,
302 263.7, 270.3, 276.6, 282.6, 288.1, 294.5, 300.4, 306.3, 311.4,
303 315.1, 318.3, 320.3, 322.2, 322.8, 321.5, 321.1},
304 {266.5, 264.9, 260.8, 261, 262, 263, 261.3, 259.7, 259.2, 259.8,
305 260.1, 258.6, 256.7, 253.6, 249.5, 243.9, 237.4, 230, 222.1, 213.9,
306 205, 194.4, 180.4, 161.8, 140.7, 122.9, 112.1, 106.7, 104.1, 102.7,
307 101.8, 101.4, 101.1, 101, 101, 101, 101.1, 101.2, 101.5, 101.9,
308 102.4, 103, 103.8, 104.9, 106.8, 110.1, 115.6, 124, 135.2, 148.9,
309 165.2, 181.3, 198, 211.8, 223.5, 233.8, 242.9, 251.5, 259, 266.2,
310 273.1, 279.2, 286.2, 292.8, 299.6, 306, 311.1, 315.5, 318.8, 322.6,
311 325.3, 325.8, 325.8},
312 {220.1, 218.1, 210.8, 207.2, 207.6, 210.5, 211.4, 213.5, 217.3,
313 222.4, 227.9, 232.8, 237.4, 240.8, 242.8, 243, 241.5, 238.6, 234.2,
314 228.5, 221, 210.7, 195.1, 172.9, 147.8, 127.6, 115.6, 109.9, 107.1,
315 105.7, 105, 104.8, 104.8, 104.9, 105, 105.1, 105.3, 105.5, 105.8,
316 106.4, 107, 107.6, 108.1, 108.8, 110, 111.8, 114.2, 117.4, 121.6,
317 127.9, 137.3, 151.2, 169.5, 189, 205.8, 218.9, 229.1, 237.8, 245,
318 251.5, 257.1, 262.3, 268.2, 274, 280.4, 286.7, 292.4, 297.9, 302.9,
319 308.5, 312.2, 313.1, 313.3},
320 {187.4, 184.5, 173.3, 166.1, 165.4, 167.8, 169.6, 173.6, 179.6,
321 187.9, 198.9, 210, 220.5, 229.2, 235.7, 239.9, 241.8, 241.6, 239.6,
322 235.8, 229.4, 218.6, 200.9, 175.9, 149.4, 129.4, 118.3, 113.1,
323 110.8, 109.7, 109.3, 109.4, 109.7, 110, 110.2, 110.4, 110.5, 110.7,
324 111, 111.4, 111.8, 112.1, 112.3, 112.7, 113.2, 113.9, 115, 116.4,
325 117.9, 120.4, 124.1, 130.9, 142.2, 159.6, 179.6, 198.5, 212.9,
326 224.2, 232.7, 239.1, 243.8, 247.7, 252.4, 257.3, 263.2, 269.5,
327 275.4, 281.1, 286.3, 292, 296.3, 298.2, 298.8},
328 {166, 166.4, 155.7, 148.3, 147.1, 149, 152.1, 157, 163.6, 172.4,
329 185.3, 199.2, 212.6, 224, 233.2, 239.6, 243.3, 244.6, 243.6, 240.3,
330 233.9, 222.6, 203.7, 177, 149.5, 129.7, 119, 114, 111.7, 110.7,
331 110.3, 110.3, 110.6, 110.9, 111.1, 111.3, 111.5, 111.6, 111.9,
332 112.2, 112.5, 112.6, 112.8, 113, 113.4, 114, 115.1, 116.5, 118.3,
333 120.9, 124.4, 130.2, 139.4, 154.6, 173.8, 193.1, 208.1, 220.4,
334 230.1, 238.2, 244.7, 249.5, 254.5, 259.3, 264.5, 269.4, 273.7,
335 278.2, 282.6, 287.4, 290.9, 292.5, 293},
336 {171.9, 172.8, 166.2, 162.3, 161.4, 162.5, 165.2, 169.6, 175.3,
337 183.1, 193.8, 205.9, 218.3, 229.6, 238.5, 244.3, 246.9, 246.7,
338 243.8, 238.4, 230.2, 217.9, 199.6, 174.9, 148.9, 129.8, 119.5,
339 114.8, 112.3, 110.9, 110.3, 110.1, 110.2, 110.3, 110.4, 110.5,
340 110.6, 110.8, 111, 111.4, 111.8, 112, 112.2, 112.4, 112.9, 113.6,
341 114.7, 116.3, 118.4, 121.9, 127.1, 136.1, 149.8, 168.4, 186.9,
342 203.3, 217, 229.1, 238.7, 247, 254, 259.3, 264.3, 268.3, 272.5,
343 276.6, 280.4, 284.4, 288.4, 293.3, 297.2, 298.7, 299.1},
344 {191.6, 192.2, 189, 188.1, 190.2, 193.7, 197.8, 202.9, 208.5,
345 215.6, 224.2, 233.1, 241.2, 247.3, 250.8, 251.3, 248.9, 244.2,
346 237.3, 228.4, 217.2, 202.9, 184.5, 162.5, 140.7, 124.8, 116.2,
347 111.8, 109.4, 107.9, 107, 106.7, 106.6, 106.6, 106.7, 106.7,
348 106.8, 107, 107.4, 108, 108.7, 109.3, 109.8, 110.4, 111.2,
349 112.4, 114.2, 116.9, 121.1, 127.9, 139.3, 155.2, 173.6, 190.7,
350 206.1, 220.1, 232.3, 243, 251.8, 259.2, 265.7, 270.6, 275.3,
351 279.3, 283.3, 286.9, 289.7, 292.8, 296.1, 300.5, 303.9, 304.8,
353 {241.5, 239.6, 236.8, 237.4, 239.4, 242.3, 244.2, 246.4, 249.2,
354 253.6, 258.6, 262.7, 264.8, 264.2, 260.6, 254.1, 245.5, 235.3,
355 223.9, 211.7, 198.3, 183.1, 165.6, 147.1, 130.5, 118.7, 111.9,
356 108.1, 105.8, 104.3, 103.4, 102.8, 102.5, 102.4, 102.5, 102.5,
357 102.5, 102.7, 103.1, 103.8, 104.6, 105.4, 106.1, 107, 108.2,
358 109.9, 112.8, 117.5, 126, 140.4, 161, 181.9, 201.2, 216.8, 230.4,
359 241.8, 251.4, 259.9, 266.9, 272.8, 277.4, 280.4, 282.9, 284.6,
360 286.1, 287.4, 288.3, 289.5, 290.9, 294.2, 296.9, 297.5, 297.6},
361 {301.2, 300.3, 296.6, 295.4, 295, 294.3, 291.2, 287.4, 284.9, 284.7,
362 284.1, 281.5, 277.1, 270.4, 261.7, 250.6, 237.6, 223.1, 207.9, 192,
363 175.8, 158.8, 142.1, 127.6, 116.8, 109.9, 106, 103.6, 102.1, 101.1,
364 100.4, 99.96, 99.6, 99.37, 99.32, 99.32, 99.31, 99.46, 99.77, 100.2,
365 100.7, 101.3, 101.8, 102.7, 104.1, 106.8, 111.9, 121, 136.7, 160,
366 186.9, 209.9, 228.1, 241.2, 251.5, 259.5, 265.7, 270.9, 274.8, 278,
367 280.3, 281.8, 283, 283.3, 283.7, 283.8, 283, 282.2, 281.2, 281.4,
370 memcpy(clim->
tropo, tropo,
sizeof(clim->
tropo));
373 double tropomin = 1e99, tropomax = -1e99;
375 for (
int iy = 0; iy < clim->
tropo_nlat; iy++) {
376 tropomin =
MIN(tropomin, clim->
tropo[it][iy]);
377 tropomax =
MAX(tropomax, clim->
tropo[it][iy]);
382 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
386 LOG(2,
"Latitudes: %g, %g ... %g deg",
389 LOG(2,
"Tropopause altitude range: %g ... %g hPa",
Z(tropomax),
391 LOG(2,
"Tropopause pressure range: %g ... %g hPa", tropomin, tropomax);
401 if (t <= ts->time[0])
408 ts->
time[idx + 1], ts->
vmr[idx + 1], t);
421 double sec =
FMOD(t, 365.25 * 86400.);
423 sec += 365.25 * 86400.;
427 if (p < zm->p[zm->
np - 1])
428 p_help = zm->
p[zm->
np - 1];
429 else if (p > zm->
p[0])
433 double lat_help = lat;
434 if (lat < zm->lat[0])
435 lat_help = zm->
lat[0];
436 else if (lat > zm->
lat[zm->
nlat - 1])
437 lat_help = zm->
lat[zm->
nlat - 1];
445 const double aux00 =
LIN(zm->
p[ip], zm->
vmr[isec][ip][ilat],
446 zm->
p[ip + 1], zm->
vmr[isec][ip + 1][ilat],
448 const double aux01 =
LIN(zm->
p[ip], zm->
vmr[isec][ip][ilat + 1],
449 zm->
p[ip + 1], zm->
vmr[isec][ip + 1][ilat + 1],
451 const double aux10 =
LIN(zm->
p[ip], zm->
vmr[isec + 1][ip][ilat],
452 zm->
p[ip + 1], zm->
vmr[isec + 1][ip + 1][ilat],
454 const double aux11 =
LIN(zm->
p[ip], zm->
vmr[isec + 1][ip][ilat + 1],
455 zm->
p[ip + 1], zm->
vmr[isec + 1][ip + 1][ilat + 1],
458 LIN(zm->
lat[ilat], aux00, zm->
lat[ilat + 1], aux01, lat_help);
460 LIN(zm->
lat[ilat], aux10, zm->
lat[ilat + 1], aux11, lat_help);
461 const double aux =
LIN(zm->
time[isec], aux0, zm->
time[isec + 1], aux1, sec);
462 return MAX(aux, 0.0);
473 const int decompress,
477 const size_t nx = (size_t) met->
nx;
478 const size_t ny = (
size_t) met->
ny;
479 const size_t np = (size_t) met->
np;
480 const size_t nxy = nx * ny;
486 double lon[
EX], lat[
EY];
487 for (
size_t ix = 0; ix < nx; ix++)
488 lon[ix] = 360. * (
double) ix / ((double) nx - 1.);
489 for (
size_t iy = 0; iy < ny; iy++)
490 lat[iy] = 90. - 180. * (
double) iy / ((double) ny - 1.);
493 const char domain[] =
"[0.0, 360.0]x[-90.0, 90.0]";
497 cms_param_t *cms_param
498 = cms_set_parameters(nx, ny, max_level_grid, Nd0_x, Nd0_y, domain);
501 double cr = 0, t_coars = 0, t_eval = 0;
508 for (
size_t ip = 0; ip < np; ip++) {
511 cms_module_t *cms_ptr = cms_init(cms_param);
516 cms_sol = cms_read_zstd_sol(cms_ptr, inout);
518 cms_sol = cms_read_sol(cms_ptr, inout);
521 const double t0 = omp_get_wtime();
522#pragma omp parallel for collapse(2) default(shared)
523 for (
size_t ix = 0; ix < nx; ix++)
524 for (
size_t iy = 0; iy < ny; iy++) {
526 const double x[] = { lon[ix], lat[iy] };
527 cms_eval(cms_ptr, cms_sol, x, &val);
528 array[
ARRAY_3D(ix, iy, ny, ip, np)] = (float) val;
530 t_eval += omp_get_wtime() - t0;
533 cr += 1.0 / cms_compression_rate(cms_ptr, cms_sol);
536 cms_delete_sol(cms_sol);
537 cms_delete_module(cms_ptr);
541 LOG(2,
"Read 3-D variable: %s"
542 " (CMS, RATIO=%g, BPV=%g, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
543 varname, (
double) np / cr, 32. * cr / (
double) np, t_eval,
551 cms_module_t *cms_ptr[
EP];
552 cms_sol_t *cms_sol[
EP];
553 double ratio[
EP], t_coars_level[
EP], t_eval_level[
EP];
557 ? (size_t) omp_get_max_threads()
559 for (
size_t ip0 = 0; ip0 < np; ip0 += dip) {
562 double t0 = omp_get_wtime();
565#pragma omp parallel for default(shared)
566 for (
size_t ip = ip0; ip <
MIN(ip0 + dip, np); ip++) {
567 const double t1 = omp_get_wtime();
571 ALLOC(tmp_arr,
float,
575 for (
size_t ix = 0; ix < nx; ++ix)
576 for (
size_t iy = 0; iy < ny; ++iy)
578 array[
ARRAY_3D(ix, iy, ny, ip, np)];
581 cms_ptr[ip] = cms_init(cms_param);
585 cms_read_arr_new(cms_ptr[ip], tmp_arr, lon, lat,
587 t_coars_level[ip] = omp_get_wtime() - t1;
594 t_coars += (omp_get_wtime() - t0);
597 for (
size_t ip = ip0; ip <
MIN(ip0 + dip, np); ip++) {
600 float *tmp_cms, *tmp_org;
601 ALLOC(tmp_cms,
float,
603 ALLOC(tmp_org,
float,
607 t0 = omp_get_wtime();
610#pragma omp parallel for collapse(2) default(shared)
611 for (
size_t ix = 0; ix < nx; ix++)
612 for (
size_t iy = 0; iy < ny; iy++) {
613 const size_t idx =
ARRAY_2D(ix, iy, ny);
614 const double x[] = { lon[ix], lat[iy] };
616 cms_eval(cms_ptr[ip], cms_sol[ip], x, &val);
617 tmp_cms[idx] = (float) val;
618 tmp_org[idx] = array[
ARRAY_3D(ix, iy, ny, ip, np)];
622 t_eval_level[ip] = omp_get_wtime() - t0;
623 t_eval += t_eval_level[ip];
626 ratio[ip] = cms_compression_rate(cms_ptr[ip], cms_sol[ip]);
627 cr += 1.0 / ratio[ip];
632 ratio[ip], 32. / ratio[ip],
633 t_coars_level[ip], t_eval_level[ip], nxy,
634 nxy *
sizeof(
float), tmp_org, tmp_cms);
638 cms_save_zstd_sol(cms_sol[ip], inout, 3);
640 cms_save_sol(cms_sol[ip], inout);
643 cms_delete_sol(cms_sol[ip]);
644 cms_delete_module(cms_ptr[ip]);
651 LOG(2,
"Write 3-D variable: %s"
652 " (CMS, RATIO=%g, BPV=%g, T_COMP=%g s, V_COMP=%g MiB/s,"
653 " T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
654 varname, (
double) np / cr, 32. * cr / (
double) np, t_coars,
660 cms_delete_param(cms_param);
675 const double t_decomp,
681 static FILE *last_out = NULL;
682 static char last_var[
LEN] =
"";
685 double mean_err = 0.0, stddev_err = 0.0;
686 double nrmse = NAN, mean_orig = 0.0, orig_range = 0.0, rho = NAN;
688 double sum_err = 0.0, sumsq_err = 0.0;
689 double sum_orig = 0.0, sum_cmp = 0.0;
690 double sumsq_orig = 0.0, sumsq_cmp = 0.0, sum_org_cmp = 0.0;
692 double min_orig = 0.0, max_orig = 0.0;
693 double min_err = 0.0, max_err = 0.0;
696 for (
size_t i = 0; i < n; i++) {
697 const double o = (double) org[i];
698 const double c = (double) cmp[i];
699 const double e = c - o;
708 sum_org_cmp += o * c;
710 if (e < min_err || i == 0)
712 if (e > max_err || i == 0)
715 if (o < min_orig || i == 0)
717 if (o > max_orig || i == 0)
722 mean_err = sum_err / (double) n;
723 mean_orig = sum_orig / (double) n;
724 orig_range = max_orig - min_orig;
727 const double var_err =
728 (sumsq_err - (sum_err * sum_err) / (
double) n) / (
double) n;
729 stddev_err = sqrt(var_err > 0.0 ? var_err : 0.0);
732 nrmse = (orig_range > 0.0)
733 ? sqrt(sumsq_err / (
double) n) / orig_range : NAN;
736 const double nn = (double) n;
737 const double cov = sum_org_cmp - sum_orig * sum_cmp / nn;
738 const double var_orig = sumsq_orig - sum_orig * sum_orig / nn;
739 const double var_cmp = sumsq_cmp - sum_cmp * sum_cmp / nn;
740 const double denom = sqrt(var_orig * var_cmp);
741 rho = denom > 0.0 ? cov / denom : NAN;
744 if (out != last_out) {
750 if (last_var[0] !=
'\0' && strcmp(last_var, varname) != 0)
752 snprintf(last_var,
LEN,
"%s", varname);
756 "%s %s %lu %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g\n",
757 codec, varname, (
unsigned long) lev, plev, ratio, bpv, rho,
758 mean_err, stddev_err, min_err, max_err, mean_orig, orig_range,
770 const float *org_all,
771 const float *cmp_all,
777 const double t_decomp,
778 const size_t nbytes) {
784 float *tmp_org, *tmp_cmp;
785 ALLOC(tmp_org,
float,
787 ALLOC(tmp_cmp,
float,
790 for (
size_t lev = 0; lev < nz; lev++) {
793#pragma omp parallel for default(shared)
794 for (
size_t ixy = 0; ixy < nxy; ixy++) {
795 tmp_org[ixy] = org_all[ixy * nz + lev];
796 tmp_cmp[ixy] = cmp_all[ixy * nz + lev];
801 t_comp, t_decomp, nxy, nbytes, tmp_org, tmp_cmp);
819 for (
size_t iz = 0; iz < nz; iz++) {
825 for (
size_t ixy = 1; ixy < nxy; ixy++)
826 for (
size_t iz = 0; iz < nz; iz++) {
827 const double value = array[ixy * nz + iz];
835 for (
size_t iz = 0; iz < nz; iz++) {
836 const double range = scl[iz] - off[iz];
837 const double ref = fmax(1.0, fmax(fabs(off[iz]), fabs(scl[iz])));
838 scl[iz] = !(range > 1e-12 * ref) ? 0.0 : range;
842#pragma omp parallel for default(shared)
843 for (
size_t ixy = 0; ixy < nxy; ixy++)
844 for (
size_t iz = 0; iz < nz; iz++)
846 array[ixy * nz + iz] =
847 (float) ((array[ixy * nz + iz] - off[iz]) / scl[iz]);
849 array[ixy * nz + iz] = 0.0f;
862#pragma omp parallel for default(shared)
863 for (
size_t ixy = 0; ixy < nxy; ixy++)
864 for (
size_t iz = 0; iz < nz; iz++)
866 array[ixy * nz + iz] =
867 (float) (array[ixy * nz + iz] * scl[iz] + off[iz]);
869 array[ixy * nz + iz] = (float) off[iz];
888 if (enabled < 0 || enabled > 1)
889 ERRMSG(
"Invalid stored MET_LOSSY_SCALE flag!");
947ZSTD_CCtx *compress_zstd_create_cctx(
949 const int nworkers) {
952 ZSTD_CCtx *cctx = ZSTD_createCCtx();
954 ERRMSG(
"Cannot create ZSTD context!");
956 if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel,
958 ERRMSG(
"Cannot set ZSTD compression level!");
960 if (ZSTD_isError(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, nworkers)))
961 ERRMSG(
"Cannot set ZSTD worker count!");
970 const char *varname) {
972 static const char *
const names[] = {
973 "Z",
"T",
"U",
"V",
"W",
"PV",
"H2O",
"O3",
974 "LWC",
"RWC",
"IWC",
"SWC",
"CC"
977 for (
size_t i = 0; i <
sizeof(names) /
sizeof(names[0]); i++)
978 if (strcasecmp(varname, names[i]) == 0)
981 ERRMSG(
"Unknown meteorological variable name!");
991 const int decompress,
995 const size_t nxy = (size_t) met->
nx * (
size_t) met->
ny;
996 const size_t nz = (size_t) met->
np;
997 const size_t n = nxy * nz;
998 const size_t nbytes = n *
sizeof(
float);
999 const size_t pck_bytes = n *
sizeof(uint16_t);
1001 double vmin[
EP], vmax[
EP], off[
EP], scl[
EP];
1005 const size_t payload_len = 2 * nz *
sizeof(double) + pck_bytes;
1006 size_t stored_len = payload_len;
1007 const char *codec_info = ctl->
met_pck_zstd ?
"PCK+ZSTD" :
"PCK";
1010 ALLOC(sarray, uint16_t, n);
1014 double t_zstd = 0.0;
1019 uint64_t magic, pck_zstd_magic = UINT64_C(0x50434b5a53544431);
1020 unsigned char *compr = NULL, *payload = NULL;
1023 FREAD(&magic, uint64_t, 1, inout);
1024 if (magic != pck_zstd_magic)
1025 ERRMSG(
"PCK+ZSTD magic mismatch! Check MET_PCK_ZSTD and file type.");
1028 FREAD(&stored_len,
size_t,
1031 ALLOC(compr,
unsigned char,
1033 FREAD(compr,
unsigned char,
1036 ALLOC(payload,
unsigned char,
1038 const double t0_decomp = omp_get_wtime();
1039 const size_t out_len =
1040 ZSTD_decompress(payload, payload_len, compr, stored_len);
1041 t_zstd = omp_get_wtime() - t0_decomp;
1042 if (ZSTD_isError(out_len) || out_len != payload_len)
1043 ERRMSG(
"PCK ZSTD decompression failed or size mismatch!");
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), pck_bytes);
1054 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
1064 FREAD(sarray, uint16_t, n, inout);
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;
1081 LOG(2,
"Read 3-D variable: %s"
1082 " (%s, RATIO=%g, BPV=%g, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1090 float *tmp_org, *tmp_pck;
1091 double t_comp_sum = 0, t_decomp_sum = 0, t_zstd = 0, t_zstd_decomp = 0;
1092 double t_comp_level[
EP], t_decomp_level[
EP];
1095 ALLOC(tmp_org,
float,
1097 ALLOC(tmp_pck,
float,
1101 for (
size_t iz = 0; iz < nz; iz++) {
1102 vmin[iz] = array[iz];
1103 vmax[iz] = array[iz];
1105 for (
size_t ixy = 1; ixy < nxy; ixy++)
1106 for (
size_t iz = 0; iz < nz; iz++) {
1107 if (array[ixy * nz + iz] < vmin[iz])
1108 vmin[iz] = array[ixy * nz + iz];
1109 if (array[ixy * nz + iz] > vmax[iz])
1110 vmax[iz] = array[ixy * nz + iz];
1114 for (
size_t iz = 0; iz < nz; iz++) {
1115 scl[iz] = (vmax[iz] - vmin[iz]) / 65533.;
1120 for (
size_t iz = 0; iz < nz; iz++) {
1121 const double t0 = omp_get_wtime();
1123#pragma omp parallel for default(shared)
1124 for (
size_t ixy = 0; ixy < nxy; ixy++)
1126 sarray[ixy * nz + iz] =
1127 (uint16_t) ((array[ixy * nz + iz] - off[iz]) / scl[iz] + .5);
1129 sarray[ixy * nz + iz] = 0;
1131 t_comp_level[iz] = omp_get_wtime() - t0;
1132 t_comp_sum += t_comp_level[iz];
1134 const double t1 = omp_get_wtime();
1136#pragma omp parallel for default(shared)
1137 for (
size_t ixy = 0; ixy < nxy; ixy++) {
1138 tmp_org[ixy] = array[ixy * nz + iz];
1139 tmp_pck[ixy] = (float) (sarray[ixy * nz + iz] * scl[iz] + off[iz]);
1142 t_decomp_level[iz] = omp_get_wtime() - t1;
1143 t_decomp_sum += t_decomp_level[iz];
1149 uint64_t pck_zstd_magic = UINT64_C(0x50434b5a53544431);
1150 unsigned char *payload = NULL, *payload_chk = NULL;
1151 void *stored_data = NULL;
1154 ALLOC(payload,
unsigned char,
1156 memcpy(payload, scl, nz *
sizeof(
double));
1157 memcpy(payload + nz *
sizeof(
double), off, nz *
sizeof(
double));
1158 memcpy(payload + 2 * nz *
sizeof(
double), sarray, pck_bytes);
1159 const size_t dst_cap = ZSTD_compressBound(payload_len);
1160 ALLOC(stored_data,
char,
1164 const double t0_comp = omp_get_wtime();
1166 ZSTD_compress2(cctx, stored_data, dst_cap, payload, payload_len);
1167 t_zstd = omp_get_wtime() - t0_comp;
1168 ZSTD_freeCCtx(cctx);
1169 if (ZSTD_isError(stored_len))
1170 ERRMSG(
"PCK ZSTD compression failed!");
1173 ALLOC(payload_chk,
unsigned char,
1175 const double t0_decomp2 = omp_get_wtime();
1176 const size_t out_len2 =
1177 ZSTD_decompress(payload_chk, payload_len, stored_data, stored_len);
1178 t_zstd_decomp = omp_get_wtime() - t0_decomp2;
1179 if (ZSTD_isError(out_len2) || out_len2 != payload_len)
1180 ERRMSG(
"PCK ZSTD decompression failed or size mismatch!");
1187 FWRITE(&pck_zstd_magic, uint64_t, 1, inout);
1188 FWRITE(&stored_len,
size_t,
1191 FWRITE(stored_data,
unsigned char,
1198 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
1209 FWRITE(sarray, uint16_t, n, inout);
1215 const double t_comp = t_comp_sum + t_zstd;
1216 const double t_decomp = t_decomp_sum + t_zstd_decomp;
1219 LOG(2,
"Write 3-D variable: %s"
1220 " (%s, RATIO=%g, BPV=%g, T_COMP=%g s, V_COMP=%g MiB/s,"
1221 " T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1222 varname, codec_info, ratio_out, bpv_out, t_comp,
1228 const double t_zstd_level = t_zstd / (double) nz;
1229 const double t_zstd_decomp_level = t_zstd_decomp / (double) nz;
1230 const char *codec = ctl->
met_pck_zstd ?
"PCKZSTD" :
"PCK";
1231 for (
size_t iz = 0; iz < nz; iz++) {
1232#pragma omp parallel for default(shared)
1235 for (
size_t ixy = 0; ixy < nxy; ixy++) {
1236 tmp_org[ixy] = array[ixy * nz + iz];
1237 tmp_pck[ixy] = (float) (sarray[ixy * nz + iz] * scl[iz] + off[iz]);
1243 t_comp_level[iz] + t_zstd_level,
1244 t_decomp_level[iz] + t_zstd_decomp_level,
1245 nxy, nxy *
sizeof(
float), tmp_org, tmp_pck);
1264 const char *varname,
1266 const int decompress,
1275 ERRMSG(
"Exactly one of precision or tolerance must be set for SZ3!");
1277 size_t r1 = (size_t) met->
np, r2 = (
size_t) met->
ny, r3 = (size_t) met->
nx,
1278 outSize = 0, total_elems = r1 * r2 * r3;
1280 unsigned char *bytes = NULL;
1281 double *scale_off = NULL, *scale_scl = NULL;
1282 float *orig_all = NULL;
1283 char codec_info[
LEN];
1289 const int stored_lossy_scale =
1295 FREAD(&sz3size,
size_t,
1300 FREAD(bytes,
unsigned char,
1305 const double t0 = omp_get_wtime();
1306 void *outData = SZ_decompress(SZ_FLOAT, bytes, sz3size, 0, 0, r3, r2, r1);
1308 ERRMSG(
"Decompression failed!");
1310 memcpy(array, outData, total_elems *
sizeof(
float));
1313 if (stored_lossy_scale > 0)
1315 const double t_decomp = omp_get_wtime() - t0;
1321 const double ratio =
COMPRESS_RATIO(total_elems *
sizeof(
float), sz3size);
1323 snprintf(codec_info,
LEN,
"SZ3, PREC=%d, TOL=%g, SCALE=%d",
1325 stored_lossy_scale);
1328 LOG(2,
"Read 3-D variable: %s"
1329 " (%s, RATIO=%g, BPV=%g, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1330 varname, codec_info, ratio, bpv, t_decomp,
1338 const int errBoundMode = (ctl->
met_sz3_prec[metvar] > 0) ? REL : ABS;
1339 const double absBound =
1340 (errBoundMode == ABS) ? ctl->
met_sz3_tol[metvar] : 0.0;
1341 const double relBound =
1342 (errBoundMode == REL) ? pow(2.0, -(
double) ctl->
met_sz3_prec[metvar])
1344 const size_t raw_size = total_elems *
sizeof(float);
1348 ALLOC(orig_all,
float,
1350 memcpy(orig_all, array, total_elems *
sizeof(
float));
1355 r2 * r3, r1, &scale_off, &scale_scl);
1358 const double t0 = omp_get_wtime();
1359 bytes = SZ_compress_args(SZ_FLOAT, array, &outSize,
1360 errBoundMode, absBound, relBound, 0.0,
1362 const double t_comp = omp_get_wtime() - t0;
1363 if (!bytes || outSize == 0)
1364 ERRMSG(
"Compression failed!");
1370 FWRITE(bytes,
unsigned char,
1374 snprintf(codec_info,
LEN,
"SZ3, PREC=%d, TOL=%g, SCALE=%d",
1379 double t_decomp = NAN;
1381 unsigned char *bytes_copy;
1383 const size_t nxy = r2 * r3;
1386 ALLOC(bytes_copy,
unsigned char,
1388 memcpy(bytes_copy, bytes, outSize);
1390 const double t1 = omp_get_wtime();
1391 void *decData = SZ_decompress(SZ_FLOAT, bytes_copy, outSize, 0, 0, r3,
1393 t_decomp = omp_get_wtime() - t1;
1395 ERRMSG(
"Decompression failed!");
1398 ALLOC(tmp_all,
float,
1400 memcpy(tmp_all, decData, total_elems *
sizeof(
float));
1408 (orig_all ? orig_all : array), tmp_all, nxy, r1,
1409 ratio, bpv, t_comp, t_decomp, raw_size);
1417 LOG(2,
"Write 3-D variable: %s"
1418 " (%s, 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, codec_info, ratio, bpv, t_comp,
1428 LOG(2,
"Write 3-D variable: %s"
1429 " (%s, RATIO=%g, BPV=%g, T_COMP=%g s, V_COMP=%g MiB/s)",
1430 varname, codec_info, ratio, bpv, t_comp,
1450 const char *varname,
1452 const int decompress,
1460 const size_t snx = (size_t) met->
np;
1461 const size_t sny = (
size_t) met->
ny;
1462 const size_t snz = (size_t) met->
nx;
1463 const size_t n = snx * sny * snz;
1464 const size_t raw_size = n *
sizeof(
float);
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;
1478 ERRMSG(
"Exactly one of precision or tolerance must be set for zfp!");
1480 actual_prec = (int) zfp_stream_set_precision(zfp, (
unsigned int)
1483 actual_tol = zfp_stream_set_accuracy(zfp, ctl->
met_zfp_tol[metvar]);
1486 const size_t bufsize = zfp_stream_maximum_size(zfp, field);
1492 bitstream *stream = stream_open(buffer, bufsize);
1493 zfp_stream_set_bit_stream(zfp, stream);
1494 zfp_stream_rewind(zfp);
1498 double *scale_off = NULL, *scale_scl = NULL;
1499 char codec_info[
LEN];
1503 const int stored_lossy_scale =
1506 FREAD(&zfpsize,
size_t,
1509 if (zfpsize > bufsize)
1510 ERRMSG(
"Compressed data size exceeds allocated buffer!");
1511 FREAD(buffer,
unsigned char,
1516 const double t0 = omp_get_wtime();
1517 if (!zfp_decompress(zfp, field))
1518 ERRMSG(
"Decompression failed!");
1521 if (stored_lossy_scale > 0)
1523 const double t_decomp = omp_get_wtime() - t0;
1526 snprintf(codec_info,
LEN,
"ZFP, PREC=%d, TOL=%g, SCALE=%d",
1527 actual_prec, actual_tol, stored_lossy_scale);
1530 LOG(2,
"Read 3-D variable: %s"
1531 " (%s, RATIO=%g, BPV=%g, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1532 varname, codec_info, ratio, bpv, t_decomp,
COMPRESS_SPEED(raw_size,
1538 float *tmp_all, *orig_all = NULL;
1539 const size_t nxy = sny * snz;
1543 ALLOC(orig_all,
float,
1545 memcpy(orig_all, array, raw_size);
1550 nxy, snx, &scale_off, &scale_scl);
1553 ALLOC(tmp_all,
float,
1557 const double t0 = omp_get_wtime();
1558 zfpsize = zfp_compress(zfp, field);
1559 const double t_comp = omp_get_wtime() - t0;
1561 ERRMSG(
"Compression failed!");
1567 FWRITE(buffer,
unsigned char,
1573 zfp_field *dec_field = zfp_field_3d(tmp_all, type, snx, sny, snz);
1575 ERRMSG(
"Failed to allocate zfp structures!");
1578 const double t1 = omp_get_wtime();
1579 zfp_stream_rewind(zfp);
1580 if (!zfp_decompress(zfp, dec_field))
1581 ERRMSG(
"Decompression failed!");
1584 const double t_decomp = omp_get_wtime() - t1;
1589 (orig_all ? orig_all : array), tmp_all, nxy, snx,
1590 ratio, bpv, t_comp, t_decomp, raw_size);
1592 snprintf(codec_info,
LEN,
"ZFP, PREC=%d, TOL=%g, SCALE=%d",
1596 LOG(2,
"Write 3-D variable: %s"
1597 " (%s, RATIO=%g, BPV=%g, T_COMP=%g s, V_COMP=%g MiB/s,"
1598 " T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1599 varname, codec_info, ratio, bpv, t_comp,
COMPRESS_SPEED(raw_size,
1606 zfp_field_free(dec_field);
1614 zfp_field_free(field);
1615 stream_close(stream);
1616 zfp_stream_close(zfp);
1627 const char *varname,
1629 const int decompress,
1634 const size_t nxy = (size_t) met->
nx * (
size_t) met->
ny;
1635 const size_t nz = (size_t) met->
np;
1636 const size_t n = nxy * nz, uncomprLen = n *
sizeof(
float);
1637 size_t compsize, comprLen = ZSTD_compressBound(uncomprLen);
1640 char *compr, *uncompr = (
char *) array;
1641 char codec_info[
LEN];
1649 FREAD(&comprLen,
size_t,
1652 FREAD(compr,
unsigned char,
1657 const double t0 = omp_get_wtime();
1658 compsize = ZSTD_decompress(uncompr, uncomprLen, compr, comprLen);
1659 const double t_decomp = omp_get_wtime() - t0;
1660 if (ZSTD_isError(compsize) || compsize != uncomprLen)
1661 ERRMSG(
"Decompression failed or size mismatch!");
1667 LOG(2,
"Read 3-D variable: %s"
1668 " (%s, RATIO=%g, BPV=%g, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1669 varname, codec_info, ratio, bpv, t_decomp,
COMPRESS_SPEED(uncomprLen,
1679 ALLOC(tmp_all,
float,
1686 const double t0 = omp_get_wtime();
1687 compsize = ZSTD_compress2(cctx, compr, comprLen, uncompr, uncomprLen);
1688 const double t_comp = omp_get_wtime() - t0;
1689 if (ZSTD_isError(compsize)) {
1690 ZSTD_freeCCtx(cctx);
1691 ERRMSG(
"Compression failed!");
1695 FWRITE(&compsize,
size_t,
1698 FWRITE(compr,
unsigned char,
1704 const double t1 = omp_get_wtime();
1705 const size_t decomp_size = ZSTD_decompress(tmp_all, uncomprLen, compr,
1707 const double t_decomp = omp_get_wtime() - t1;
1708 if (ZSTD_isError(decomp_size) || decomp_size != uncomprLen)
1709 ERRMSG(
"Decompression failed or size mismatch!");
1714 nxy, nz, ratio, bpv, t_comp, t_decomp, uncomprLen);
1716 snprintf(codec_info,
LEN,
"ZSTD, LEVEL=%d, NWORKERS=%d",
1720 LOG(2,
"Write 3-D variable: %s"
1721 " (%s, RATIO=%g, BPV=%g, T_COMP=%g s, V_COMP=%g MiB/s,"
1722 " T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1723 varname, codec_info, ratio, bpv, t_comp,
COMPRESS_SPEED(uncomprLen,
1728 ZSTD_freeCCtx(cctx);
1743 const char *varname,
1745 const int decompress,
1750 const size_t nxy = (size_t) met->
nx * (
size_t) met->
ny;
1751 const size_t nz = (size_t) met->
np;
1752 const size_t n = nxy * nz;
1753 const size_t uncomprLen = n *
sizeof(
float);
1754 if (uncomprLen > (
size_t) INT_MAX)
1755 ERRMSG(
"LZ4 input buffer exceeds INT_MAX!");
1756 const int uncomprLenInt = (int) uncomprLen;
1758 const int comprCapInt = LZ4_compressBound(uncomprLenInt);
1759 if (comprCapInt <= 0)
1760 ERRMSG(
"Cannot determine LZ4 compression bound!");
1761 size_t comprLen = (size_t) comprCapInt;
1764 char *compr, *uncompr = (
char *) array;
1765 char codec_info[
LEN];
1768 snprintf(codec_info,
LEN,
"LZ4, ACCEL=%d", accel);
1774 FREAD(&comprLen,
size_t,
1777 if (comprLen > (
size_t) INT_MAX)
1778 ERRMSG(
"LZ4 compressed buffer exceeds INT_MAX!");
1779 FREAD(compr,
unsigned char,
1784 const double t0 = omp_get_wtime();
1785 const int decomp_size =
1786 LZ4_decompress_safe(compr, uncompr, (
int) comprLen, uncomprLenInt);
1787 const double t_decomp = omp_get_wtime() - t0;
1788 if (decomp_size != uncomprLenInt)
1789 ERRMSG(
"Decompression failed or size mismatch!");
1794 LOG(2,
"Read 3-D variable: %s"
1795 " (%s, RATIO=%g, BPV=%g, T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1796 varname, codec_info, ratio, bpv, t_decomp,
COMPRESS_SPEED(uncomprLen,
1805 ALLOC(tmp_all,
float,
1809 const double t0 = omp_get_wtime();
1810 const int compsizeInt =
1811 LZ4_compress_fast(uncompr, compr, uncomprLenInt, comprCapInt, accel);
1812 const double t_comp = omp_get_wtime() - t0;
1813 if (compsizeInt <= 0)
1814 ERRMSG(
"Compression failed!");
1815 const size_t compsize = (size_t) compsizeInt;
1818 FWRITE(&compsize,
size_t,
1821 FWRITE(compr,
unsigned char,
1826 const double t1 = omp_get_wtime();
1827 const int decomp_size =
1828 LZ4_decompress_safe(compr, (
char *) tmp_all, compsizeInt,
1830 const double t_decomp = omp_get_wtime() - t1;
1831 if (decomp_size != uncomprLenInt)
1832 ERRMSG(
"Decompression failed or size mismatch!");
1837 nxy, nz, ratio, bpv, t_comp, t_decomp, uncomprLen);
1840 LOG(2,
"Write 3-D variable: %s"
1841 " (%s, RATIO=%g, BPV=%g, T_COMP=%g s, V_COMP=%g MiB/s,"
1842 " T_DECOMP=%g s, V_DECOMP=%g MiB/s)",
1843 varname, codec_info, ratio, bpv, t_comp,
COMPRESS_SPEED(uncomprLen,
1863 const double D = sec / 86400 - 0.5;
1866 const double g =
DEG2RAD(357.529 + 0.98560028 * D);
1867 const double q = 280.459 + 0.98564736 * D;
1868 const double L =
DEG2RAD(q + 1.915 * sin(g) + 0.020 * sin(2 * g));
1871 const double e =
DEG2RAD(23.439 - 0.00000036 * D);
1874 const double sindec = sin(e) * sin(L);
1877 const double ra = atan2(cos(e) * sin(L), cos(L));
1880 const double GMST = 18.697374558 + 24.06570982441908 * D;
1883 const double LST = GMST + lon / 15;
1886 const double h = LST / 12 * M_PI - ra;
1889 const double lat_help =
DEG2RAD(lat);
1892 return sin(lat_help) * sindec + cos(lat_help) * sqrt(1 -
1893 SQR(sindec)) * cos(h);
1905 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
1906 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
1909 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
1910 *doy = d0l[mon - 1] + day - 1;
1912 *doy = d0[mon - 1] + day - 1;
1929 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
1938 const int ix0 = zonal_rank * nx_block;
1939 const int iy0 = merid_rank * ny_block;
1941 const int ix1 = ix0 + nx_block
1945 const int iy1 = iy0 + ny_block
1951#pragma acc update device(dd->nx_glob, dd->ny_glob, \
1952 dd->lon_glob[:dd->nx_glob], \
1953 dd->lat_glob[:dd->ny_glob])
1954#pragma acc data present(atm, ctl, dd)
1955#pragma acc parallel loop independent gang vector
1957 for (
int ip = 0; ip < atm->
np; ip++) {
1964 double lon = atm->
lon[ip];
1965 double lat = atm->
lat[ip];
1971 const int inside = (ix >= ix0 && ix < ix1 && iy >= iy0 && iy < iy1);
2006 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
2010#pragma acc enter data create(npart, particles[:npart])
2011#pragma acc update device(npart, particles[:npart])
2012#pragma acc parallel loop present(atm, ctl, particles, cache, npart)
2014 for (
int ip = atm->
np; ip < atm->np + npart; ip++)
2019 particles[ip - atm->
np].
time = atm->
time[ip];
2020 particles[ip - atm->
np].
lon = atm->
lon[ip];
2021 particles[ip - atm->
np].
lat = atm->
lat[ip];
2022 particles[ip - atm->
np].
p = atm->
p[ip];
2023 for (
int iq = 0; iq < ctl->
nq; iq++)
2024 particles[ip - atm->
np].q[iq] = atm->
q[iq][ip];
2030#pragma acc update host( particles[:npart])
2031#pragma acc exit data delete(npart, particles)
2054 int zonal_rank = ix / nx_block;
2060 int merid_rank = iy / ny_block;
2083 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
2084 MPI_Comm_size(MPI_COMM_WORLD, &size);
2086 int *send_counts, *recv_counts;
2087 int *send_displs, *recv_displs;
2093 ALLOC(send_counts,
int,
2095 ALLOC(recv_counts,
int,
2097 ALLOC(send_displs,
int,
2099 ALLOC(recv_displs,
int,
2105#pragma omp parallel for
2106 for (
int ip = 0; ip < *npart; ip++) {
2110 if (dest < 0 || dest >= size)
2111 ERRMSG(
"Invalid destination rank!");
2113 send_counts[dest]++;
2118 for (
int i = 0; i < size; i++) {
2119 send_displs[i] = nsend;
2120 nsend += send_counts[i];
2124 MPI_Alltoall(send_counts, 1, MPI_INT,
2125 recv_counts, 1, MPI_INT, MPI_COMM_WORLD);
2129 for (
int i = 0; i < size; i++) {
2130 recv_displs[i] = nrecv;
2131 nrecv += recv_counts[i];
2137 for (
int i = 0; i < size; i++)
2138 offsets[i] = send_displs[i];
2141 for (
int ip = 0; ip < *npart; ip++) {
2145 memcpy(&sendbuf[offsets[dest]], &(*particles)[ip],
sizeof(
particle_t));
2150 MPI_Alltoallv(sendbuf,
2155 recv_counts, recv_displs, dd->MPI_Particle, MPI_COMM_WORLD);
2158 if (nrecv > *capacity) {
2159 const int newcap = nrecv + nrecv / 2 + 1;
2161 realloc(*particles, (
size_t) newcap *
sizeof(
particle_t));
2163 ERRMSG(
"Out of memory!");
2169#pragma omp parallel for
2170 for (
int ip = 0; ip < nrecv; ip++) {
2171 (*particles)[ip] = recvbuf[ip];
2201 ERRMSG(
"Please provide zonal and meridional subdomain numbers!");
2203 ERRMSG(
"Activate controle flag DD!");
2207 MPI_Comm_size(MPI_COMM_WORLD, &size);
2209 ERRMSG(
"Number of tasks and subdomains is not identical!");
2212 const MPI_Datatype types[5] =
2213 { MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE };
2214 const int blocklengths[5] = { 1, 1, 1, 1,
NQ };
2215 const MPI_Aint displacements[5] =
2220 MPI_Type_create_struct(5, blocklengths, displacements, types,
2222 MPI_Type_commit(&dd->MPI_Particle);
2237 const double lon_min = (dd->
lon_glob[0] < 0) ? -180.0 : 0.0;
2240 *lon =
FMOD(*lon - lon_min, 360.0);
2247 *lat = 180.0 - *lat;
2249 }
else if (*lat < -90.0) {
2250 *lat = -180.0 - *lat;
2255 *lon =
FMOD(*lon - lon_min, 360.0);
2280 if (atm->
np + npart >
NP)
2281 ERRMSG(
"Too many particles. Increase NP!");
2284#pragma acc enter data create(npart, particles[:npart])
2285#pragma acc update device(particles[:npart], npart)
2286#pragma acc data present(atm, ctl, cache, particles, npart)
2287#pragma acc parallel loop
2289 for (
int ip = atm->
np; ip < atm->np + npart; ip++) {
2290 atm->
time[ip] = particles[ip - atm->
np].
time;
2291 atm->
lon[ip] = particles[ip - atm->
np].
lon;
2292 atm->
lat[ip] = particles[ip - atm->
np].
lat;
2293 atm->
p[ip] = particles[ip - atm->
np].
p;
2294 for (
int iq = 0; iq < ctl->
nq; iq++)
2295 atm->
q[iq][ip] = particles[ip - atm->
np].q[iq];
2299#pragma acc exit data delete(npart, particles)
2305#pragma acc update device(atm->np)
2320 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
2325 int *counter_ptr = (
int *) acc_malloc(
sizeof(
int));
2326 if (counter_ptr == NULL) {
2327 ERRMSG(
"Failed to allocate device counter memory!");
2329 acc_memcpy_to_device(counter_ptr, &counter,
sizeof(
int));
2331 int *counter_ptr = &counter;
2336#pragma acc parallel loop present(atm, cache) deviceptr(counter_ptr)
2338#pragma omp parallel for
2340 for (
int ip = 0; ip < atm->
np; ip++) {
2345#pragma acc atomic capture
2347#pragma omp atomic capture
2350 local_idx = *counter_ptr;
2353 int global_index = atm->
np + local_idx;
2355 atm->
time[global_index] = atm->
time[ip];
2356 atm->
p[global_index] = atm->
p[ip];
2357 atm->
lon[global_index] = atm->
lon[ip];
2358 atm->
lat[global_index] = atm->
lat[ip];
2360 for (
int iq = 0; iq < ctl->
nq; iq++) {
2361 atm->
q[iq][global_index] = atm->
q[iq][ip];
2367 cache->
dt[global_index] = cache->
dt[ip];
2373 acc_memcpy_from_device(npart, counter_ptr,
sizeof(
int));
2374 acc_free(counter_ptr);
2395 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
2398 const int np = atm->
np;
2399 double amax = (met0->
nx * met0->
ny + met0->
ny) * met0->
np + met0->
np;
2401#pragma acc enter data create(amax)
2402#pragma acc update device(amax)
2403#pragma acc data present(ctl,met0,atm,dd,amax)
2408#pragma acc parallel loop independent gang vector
2410#pragma omp parallel for default(shared)
2412 for (
int ip = 0; ip < np; ip++) {
2420 dd->sort_key[ip] = amax + 1;
2422 dd->sort_key[ip] = amax + 2;
2430#pragma acc host_data use_device(dd->sort_key, dd->perm)
2432 thrustSortWrapper(dd->sort_key, np, dd->perm);
2434 size_t *perm_sz = (
size_t *) malloc((
size_t) np *
sizeof(size_t));
2435 if (perm_sz == NULL)
2436 ERRMSG(
"Out of memory!");
2438#pragma acc update self(dd->sort_key[0:np])
2440 gsl_sort_index(perm_sz, dd->sort_key, 1, (
size_t) np);
2441 for (
int ip = 0; ip < np; ++ip)
2442 dd->perm[ip] = (
int) perm_sz[ip];
2445#pragma acc update device(dd->perm[0:np])
2454 for (
int iq = 0; iq < ctl->
nq; iq++)
2460#pragma acc parallel loop reduction(+:nkeep) present(atm, ctl)
2462 for (
int ip = 0; ip < np; ip++)
2470#pragma acc parallel loop reduction(+:nsend) present(atm, ctl)
2472 for (
int ip = nkeep; ip < np; ip++)
2482 for (
int ip = 0; ip < np; ip++)
2488 (
"Rank %d: %d particles have subdomain index -1 and will be lost (kept: %d, to_send: %d, total_before: %d)",
2489 rank, nlost, nkeep, nsend, np);
2493#pragma acc update device(atm->np)
2498#pragma acc exit data delete(amax)
2513#pragma acc data present(dd,a)
2514#pragma acc parallel loop independent gang vector
2516#pragma omp parallel for default(shared)
2518 for (
int ip = 0; ip < np; ip++)
2519 dd->tmp[ip] = a[dd->perm[ip]];
2521#pragma acc parallel loop independent gang vector
2523#pragma omp parallel
for default(shared)
2525 for (
int ip = 0; ip < np; ip++)
2526 a[ip] = dd->tmp[ip];
2539 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
2540 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
2545 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
2546 for (i = 11; i > 0; i--)
2550 *day = doy - d0l[i] + 1;
2552 for (i = 11; i > 0; i--)
2556 *day = doy - d0[i] + 1;
2567 double data[2 *
EX];
2571 ERRMSG(
"Too many data points!");
2574 gsl_fft_complex_wavetable *wavetable =
2575 gsl_fft_complex_wavetable_alloc((
size_t) n);
2576 gsl_fft_complex_workspace *workspace =
2577 gsl_fft_complex_workspace_alloc((
size_t) n);
2580 for (
int i = 0; i < n; i++) {
2581 data[2 * i] = fcReal[i];
2582 data[2 * i + 1] = fcImag[i];
2586 gsl_fft_complex_forward(data, 1, (
size_t) n, wavetable, workspace);
2589 for (
int i = 0; i < n; i++) {
2590 fcReal[i] = data[2 * i];
2591 fcImag[i] = data[2 * i + 1];
2595 gsl_fft_complex_wavetable_free(wavetable);
2596 gsl_fft_complex_workspace_free(workspace);
2607 const double radius = z +
RE;
2608 const double latrad =
DEG2RAD(lat);
2609 const double lonrad =
DEG2RAD(lon);
2610 const double coslat = cos(latrad);
2612 x[0] = radius * coslat * cos(lonrad);
2613 x[1] = radius * coslat * sin(lonrad);
2614 x[2] = radius * sin(latrad);
2623 const char *metbase,
2624 const double dt_met,
2631 int year, mon, day, hour, min, sec;
2635 t6 = floor(t / dt_met) * dt_met;
2637 t6 = ceil(t / dt_met) * dt_met;
2640 jsec2time(t6, &year, &mon, &day, &hour, &min, &sec, &r);
2645 sprintf(filename,
"%s_YYYY_MM_DD_HH.nc", metbase);
2647 sprintf(filename,
"%s_YYYY_MM_DD_HH.bin", metbase);
2649 sprintf(filename,
"%s_YYYY_MM_DD_HH.pck", metbase);
2651 sprintf(filename,
"%s_YYYY_MM_DD_HH.zfp", metbase);
2653 sprintf(filename,
"%s_YYYY_MM_DD_HH.zstd", metbase);
2655 sprintf(filename,
"%s_YYYY_MM_DD_HH.cms", metbase);
2657 sprintf(filename,
"%s_YYYY_MM_DD_HH.sz3", metbase);
2659 sprintf(filename,
"%s_YYYY_MM_DD_HH.lz4", metbase);
2660 sprintf(repl,
"%d", year);
2662 sprintf(repl,
"%02d", mon);
2664 sprintf(repl,
"%02d", day);
2666 sprintf(repl,
"%02d", hour);
2672 sprintf(filename,
"%s_YYMMDDHH.nc", metbase);
2673 sprintf(repl,
"%d", year);
2675 sprintf(repl,
"%02d", year % 100);
2677 sprintf(repl,
"%02d", mon);
2679 sprintf(repl,
"%02d", day);
2681 sprintf(repl,
"%02d", hour);
2696 for (
int i = 0; i < 3; i++) {
2700 if (!(ch = strstr(orig, search)))
2702 strncpy(buffer, orig, (
size_t) (ch - orig));
2703 buffer[ch - orig] = 0;
2704 sprintf(buffer + (ch - orig),
"%s%s", repl, ch + strlen(search));
2706 strcpy(orig, buffer);
2713 const int met_tropo,
2733#pragma omp parallel for default(shared) private(ci,cw)
2734 for (
int ix = 0; ix < nx; ix++)
2735 for (
int iy = 0; iy < ny; iy++) {
2737 &pt[iy * nx + ix], ci, cw, 1);
2739 &ps[iy * nx + ix], ci, cw, 0);
2741 &zs[iy * nx + ix], ci, cw, 0);
2743 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
2745 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
2747 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
2749 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
2766 *lon2 =
FMOD(lon, 360.);
2767 if (*lon2 < lons[0])
2769 else if (*lon2 > lons[nlon - 1])
2774 if (lats[0] < lats[nlat - 1])
2775 *lat2 =
MIN(
MAX(*lat2, lats[0]), lats[nlat - 1]);
2777 *lat2 =
MIN(
MAX(*lat2, lats[nlat - 1]), lats[0]);
2793 if (lons[0] < lons[nlon - 1])
2794 *lon2 =
MIN(
MAX(lon, lons[0]), lons[nlon - 1]);
2796 *lon2 =
MIN(
MAX(lon, lons[nlon - 1]), lons[0]);
2799 if (lats[0] < lats[nlat - 1])
2800 *lat2 =
MIN(
MAX(lat, lats[0]), lats[nlat - 1]);
2802 *lat2 =
MIN(
MAX(lat, lats[nlat - 1]), lats[0]);
2810 float heights0[
EX][
EY][
EP],
2811 float array0[
EX][
EY][
EP],
2813 float heights1[
EX][
EY][
EP],
2814 float array1[
EX][
EY][
EP],
2816 const double height,
2847 int k_max = ind[0][0];
2848 for (
int i = 0; i < 2; i++)
2849 for (
int j = 0; j < 4; j++) {
2850 if (ci[2] > ind[i][j])
2852 if (k_max < ind[i][j])
2858 cw[0] = (lon2 - met0->
lon[ci[0]]) /
2859 (met0->
lon[ci[0] + 1] - met0->
lon[ci[0]]);
2860 cw[1] = (lat2 - met0->
lat[ci[1]]) /
2861 (met0->
lat[ci[1] + 1] - met0->
lat[ci[1]]);
2864 double height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2]]
2865 - heights0[ci[0]][ci[1]][ci[2]])
2866 + heights0[ci[0]][ci[1]][ci[2]];
2867 double height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2]]
2868 - heights0[ci[0]][ci[1] + 1][ci[2]])
2869 + heights0[ci[0]][ci[1] + 1][ci[2]];
2870 double height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2]]
2871 - heights0[ci[0] + 1][ci[1]][ci[2]])
2872 + heights0[ci[0] + 1][ci[1]][ci[2]];
2873 double height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2]]
2874 - heights0[ci[0] + 1][ci[1] + 1][ci[2]])
2875 + heights0[ci[0] + 1][ci[1] + 1][ci[2]];
2878 double height0 = cw[1] * (height01 - height00) + height00;
2879 double height1 = cw[1] * (height11 - height10) + height10;
2882 double height_bot = cw[0] * (height1 - height0) + height0;
2885 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
2886 - heights0[ci[0]][ci[1]][ci[2] + 1])
2887 + heights0[ci[0]][ci[1]][ci[2] + 1];
2888 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
2889 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
2890 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
2891 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
2892 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
2893 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
2894 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2895 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2896 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2899 height0 = cw[1] * (height01 - height00) + height00;
2900 height1 = cw[1] * (height11 - height10) + height10;
2903 double height_top = cw[0] * (height1 - height0) + height0;
2906 while (((heights0[0][0][0] > heights0[0][0][1]) &&
2907 ((height_bot <= height) || (height_top > height))
2908 && (height_bot >= height) && (ci[2] < k_max))
2910 ((heights0[0][0][0] < heights0[0][0][1]) &&
2911 ((height_bot >= height) || (height_top < height))
2912 && (height_bot <= height) && (ci[2] < k_max))
2916 height_bot = height_top;
2919 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
2920 - heights0[ci[0]][ci[1]][ci[2] + 1])
2921 + heights0[ci[0]][ci[1]][ci[2] + 1];
2922 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
2923 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
2924 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
2925 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
2926 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
2927 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
2928 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2929 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2930 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2933 height0 = cw[1] * (height01 - height00) + height00;
2934 height1 = cw[1] * (height11 - height10) + height10;
2937 height_top = cw[0] * (height1 - height0) + height0;
2941 cw[2] = (height - height_bot)
2942 / (height_top - height_bot);
2946 const double array000 = cw[3] * (array1[ci[0]][ci[1]][ci[2]]
2947 - array0[ci[0]][ci[1]][ci[2]])
2948 + array0[ci[0]][ci[1]][ci[2]];
2949 const double array100 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2]]
2950 - array0[ci[0] + 1][ci[1]][ci[2]])
2951 + array0[ci[0] + 1][ci[1]][ci[2]];
2952 const double array010 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2]]
2953 - array0[ci[0]][ci[1] + 1][ci[2]])
2954 + array0[ci[0]][ci[1] + 1][ci[2]];
2955 const double array110 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2]]
2956 - array0[ci[0] + 1][ci[1] + 1][ci[2]])
2957 + array0[ci[0] + 1][ci[1] + 1][ci[2]];
2958 const double array001 = cw[3] * (array1[ci[0]][ci[1]][ci[2] + 1]
2959 - array0[ci[0]][ci[1]][ci[2] + 1])
2960 + array0[ci[0]][ci[1]][ci[2] + 1];
2961 const double array101 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2] + 1]
2962 - array0[ci[0] + 1][ci[1]][ci[2] + 1])
2963 + array0[ci[0] + 1][ci[1]][ci[2] + 1];
2964 const double array011 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2] + 1]
2965 - array0[ci[0]][ci[1] + 1][ci[2] + 1])
2966 + array0[ci[0]][ci[1] + 1][ci[2] + 1];
2967 const double array111 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2968 - array0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2969 + array0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2971 const double array00 = cw[0] * (array100 - array000) + array000;
2972 const double array10 = cw[0] * (array110 - array010) + array010;
2973 const double array01 = cw[0] * (array101 - array001) + array001;
2974 const double array11 = cw[0] * (array111 - array011) + array011;
2976 const double aux0 = cw[1] * (array10 - array00) + array00;
2977 const double aux1 = cw[1] * (array11 - array01) + array01;
2980 *var = cw[2] * (aux1 - aux0) + aux0;
3015 cw[0] = (met->
p[ci[0] + 1] - p)
3016 / (met->
p[ci[0] + 1] - met->
p[ci[0]]);
3017 cw[1] = (met->
lon[ci[1] + 1] - lon2)
3018 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
3019 cw[2] = (met->
lat[ci[2] + 1] - lat2)
3020 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
3024 const double aux00 =
3025 cw[0] * (array[ci[1]][ci[2]][ci[0]] - array[ci[1]][ci[2]][ci[0] + 1])
3026 + array[ci[1]][ci[2]][ci[0] + 1];
3027 const double aux01 =
3028 cw[0] * (array[ci[1]][ci[2] + 1][ci[0]] -
3029 array[ci[1]][ci[2] + 1][ci[0] + 1])
3030 + array[ci[1]][ci[2] + 1][ci[0] + 1];
3031 const double aux10 =
3032 cw[0] * (array[ci[1] + 1][ci[2]][ci[0]] -
3033 array[ci[1] + 1][ci[2]][ci[0] + 1])
3034 + array[ci[1] + 1][ci[2]][ci[0] + 1];
3035 const double aux11 =
3036 cw[0] * (array[ci[1] + 1][ci[2] + 1][ci[0]] -
3037 array[ci[1] + 1][ci[2] + 1][ci[0] + 1])
3038 + array[ci[1] + 1][ci[2] + 1][ci[0] + 1];
3041 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
3042 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
3043 *var = cw[1] * (aux0 - aux1) + aux1;
3050 float array[
EX][
EY],
3077 cw[1] = (met->
lon[ci[1] + 1] - lon2)
3078 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
3079 cw[2] = (met->
lat[ci[2] + 1] - lat2)
3080 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
3084 const double aux00 = array[ci[1]][ci[2]];
3085 const double aux01 = array[ci[1]][ci[2] + 1];
3086 const double aux10 = array[ci[1] + 1][ci[2]];
3087 const double aux11 = array[ci[1] + 1][ci[2] + 1];
3090 if (isfinite(aux00) && isfinite(aux01)
3091 && isfinite(aux10) && isfinite(aux11)) {
3092 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
3093 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
3094 *var = cw[1] * (aux0 - aux1) + aux1;
3114 float array0[
EX][
EY][
EP],
3116 float array1[
EX][
EY][
EP],
3133 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
3136 *var = wt * (var0 - var1) + var1;
3143 float array0[
EX][
EY],
3145 float array1[
EX][
EY],
3161 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
3164 if (isfinite(var0) && isfinite(var1))
3165 *var = wt * (var0 - var1) + var1;
3176 float array0[
EX][
EY],
3178 float array1[
EX][
EY],
3179 const double lons[
EX],
3180 const double lats[
EY],
3199 const int ix =
locate_reg(lons, (
int) nlon, lon2);
3200 const int iy =
locate_irr(lats, (
int) nlat, lat2);
3204 for (
int dx = 0; dx < 2; dx++)
3205 for (
int dy = 0; dy < 2; dy++) {
3206 if (isfinite(array0[ix + dx][iy + dy])) {
3207 mean += array0[ix + dx][iy + dy];
3208 *sigma +=
SQR(array0[ix + dx][iy + dy]);
3211 if (isfinite(array1[ix + dx][iy + dy])) {
3212 mean += array1[ix + dx][iy + dy];
3213 *sigma +=
SQR(array1[ix + dx][iy + dy]);
3218 *sigma = sqrt(
MAX(*sigma / n -
SQR(mean / n), 0.0));
3221 if (method == 1 && isfinite(array0[ix][iy])
3222 && isfinite(array0[ix][iy + 1])
3223 && isfinite(array0[ix + 1][iy])
3224 && isfinite(array0[ix + 1][iy + 1])
3225 && isfinite(array1[ix][iy])
3226 && isfinite(array1[ix][iy + 1])
3227 && isfinite(array1[ix + 1][iy])
3228 && isfinite(array1[ix + 1][iy + 1])) {
3230 const double aux00 =
LIN(lons[ix], array0[ix][iy],
3231 lons[ix + 1], array0[ix + 1][iy], lon2);
3232 const double aux01 =
LIN(lons[ix], array0[ix][iy + 1],
3233 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
3234 const double aux0 =
LIN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
3236 const double aux10 =
LIN(lons[ix], array1[ix][iy],
3237 lons[ix + 1], array1[ix + 1][iy], lon2);
3238 const double aux11 =
LIN(lons[ix], array1[ix][iy + 1],
3239 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
3240 const double aux1 =
LIN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
3242 *var =
LIN(time0, aux0, time1, aux1, time);
3247 const double aux00 =
NN(lons[ix], array0[ix][iy],
3248 lons[ix + 1], array0[ix + 1][iy], lon2);
3249 const double aux01 =
NN(lons[ix], array0[ix][iy + 1],
3250 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
3251 const double aux0 =
NN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
3253 const double aux10 =
NN(lons[ix], array1[ix][iy],
3254 lons[ix + 1], array1[ix + 1][iy], lon2);
3255 const double aux11 =
NN(lons[ix], array1[ix][iy + 1],
3256 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
3257 const double aux1 =
NN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
3259 *var =
NN(time0, aux0, time1, aux1, time);
3284 const time_t jsec0 = (time_t) jsec + timegm(&t0);
3285 t1 = gmtime(&jsec0);
3287 *year = t1->tm_year + 1900;
3288 *mon = t1->tm_mon + 1;
3290 *hour = t1->tm_hour;
3293 *remain = jsec - floor(jsec);
3299 const double kz[
EP],
3300 const double kw[
EP],
3309 const double z =
Z(p);
3314 else if (z > kz[nk - 1])
3318 return LIN(kz[idx], kw[idx], kz[idx + 1], kw[idx + 1], z);
3335 const double a =
RA *
SQR(t), r =
SH(h2o) / (1. -
SH(h2o));
3348 (
"MET_PRESS_LEVEL_DEF=0 is disabled. Use 3 for the extended L137 set.");
3353 (
"MET_PRESS_LEVEL_DEF=1 is disabled. Use 4 for the extended L91 set.");
3358 (
"MET_PRESS_LEVEL_DEF=2 is disabled. Use 5 for the extended L60 set.");
3364 const double press[147] = {
3365 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
3366 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
3367 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
3368 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
3369 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
3370 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
3371 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
3372 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
3373 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
3374 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
3375 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
3376 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
3377 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
3378 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
3379 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
3380 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
3381 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
3382 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
3383 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73, 1028.85,
3385 1035.09, 1038.21, 1041.33, 1044.45
3388 for (
int ip = 0; ip < ctl->
met_np; ip++)
3395 const double press[101] = {
3396 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
3397 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
3398 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
3399 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
3400 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
3402 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
3403 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
3404 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
3405 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
3406 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
3407 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
3408 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
3409 1007.4431, 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73,
3411 1035.09, 1038.21, 1041.33, 1044.45
3414 for (
int ip = 0; ip < ctl->
met_np; ip++)
3421 const double press[62] = {
3422 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
3423 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
3424 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
3425 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
3426 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
3427 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
3428 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
3429 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1034.86, 1039.65,
3433 for (
int ip = 0; ip < ctl->
met_np; ip++)
3440 const double press[137] = {
3441 0.01, 0.02, 0.031, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861,
3442 0.2499, 0.3299, 0.4288, 0.5496, 0.6952, 0.869, 1.0742,
3443 1.3143, 1.5928, 1.9134, 2.2797, 2.6954, 3.1642, 3.6898,
3444 4.2759, 4.9262, 5.6441, 6.4334, 7.2974, 8.2397, 9.2634,
3445 10.372, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945, 18.9752,
3446 20.761, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
3447 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.199, 54.5299,
3448 57.9834, 61.5607, 65.2695, 69.1187, 73.1187, 77.281, 81.6182,
3449 86.145, 90.8774, 95.828, 101.005, 106.415, 112.068, 117.971,
3450 124.134, 130.564, 137.27, 144.262, 151.549, 159.14, 167.045,
3451 175.273, 183.834, 192.739, 201.997, 211.619, 221.615, 231.995,
3452 242.772, 253.955, 265.556, 277.585, 290.055, 302.976, 316.361,
3453 330.22, 344.566, 359.411, 374.767, 390.645, 407.058, 424.019,
3454 441.539, 459.632, 478.31, 497.584, 517.42, 537.72, 558.343,
3455 579.193, 600.167, 621.162, 642.076, 662.808, 683.262, 703.347,
3456 722.979, 742.086, 760.6, 778.466, 795.64, 812.085, 827.776,
3457 842.696, 856.838, 870.2, 882.791, 894.622, 905.712, 916.081,
3458 925.757, 934.767, 943.14, 950.908, 958.104, 965.299, 972.495,
3459 979.69, 986.886, 994.081, 1001.28, 1008.47, 1015.67, 1022.86,
3460 1030.06, 1037.25, 1044.45
3463 for (
int ip = 0; ip < ctl->
met_np; ip++)
3470 const double press[59] = {
3471 0.1, 0.2, 0.3843, 0.6365, 0.9564, 1.3448, 1.8058, 2.3478,
3472 2.985, 3.7397, 4.6462, 5.7565, 7.1322, 8.8366, 10.9483,
3473 13.5647, 16.8064, 20.8227, 25.7989, 31.9642, 39.6029, 49.0671,
3474 60.1802, 73.0663, 87.7274, 104.229, 122.614, 142.902, 165.089,
3475 189.147, 215.025, 242.652, 272.059, 303.217, 336.044, 370.407,
3476 406.133, 443.009, 480.791, 519.209, 557.973, 596.777, 635.306,
3477 673.24, 710.263, 746.063, 780.346, 812.83, 843.263, 871.42,
3478 897.112, 920.189, 940.551, 958.148, 975.744, 993.341, 1010.94,
3482 for (
int ip = 0; ip < ctl->
met_np; ip++)
3486 ERRMSG(
"Use values between 3 and 7.");
3490 ERRMSG(
"Recompile with larger EP to use this pressure level definition!");
3502 int i = (ihi + ilo) >> 1;
3504 if (xx[i] < xx[i + 1])
3505 while (ihi > ilo + 1) {
3506 i = (ihi + ilo) >> 1;
3512 while (ihi > ilo + 1) {
3513 i = (ihi + ilo) >> 1;
3533 int i = (ihi + ilo) >> 1;
3535 if ((xx[ig] <= x && x < xx[ig + 1]) || (xx[ig] >= x && x > xx[ig + 1]))
3538 if (xx[i] < xx[i + 1])
3539 while (ihi > ilo + 1) {
3540 i = (ihi + ilo) >> 1;
3546 while (ihi > ilo + 1) {
3547 i = (ihi + ilo) >> 1;
3565 const int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
3579 float profiles[
EX][
EY][
EP],
3581 const int lon_ap_ind,
3582 const int lat_ap_ind,
3583 const double height_ap,
3589 np, height_ap, ind[0]);
3591 np, height_ap, ind[1]);
3593 np, height_ap, ind[2]);
3612 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3616 double dts, u[4], um = 0, v[4], vm = 0, w[4], wm = 0,
3620 for (
int i = 0; i < ctl->
advect; i++) {
3625 x[0] = atm->
lon[ip];
3626 x[1] = atm->
lat[ip];
3629 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
3630 x[0] = atm->
lon[ip] +
DX2COORD(met0, dts * u[i - 1], atm->
lat[ip]);
3631 x[1] = atm->
lat[ip] +
DY2COORD(met0, dts * v[i - 1]);
3632 x[2] = atm->
p[ip] + dts * w[i - 1];
3634 const double tm = atm->
time[ip] + dts;
3639 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3641 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3643 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
3649 met1, met1->
pl, met1->
ul,
3650 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3652 met1, met1->
pl, met1->
vl,
3653 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3655 met1, met1->
pl, met1->
wl,
3656 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
3662 k = (i == 0 ? 0.0 : 1.0);
3663 else if (ctl->
advect == 4)
3664 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
3671 atm->
time[ip] += cache->
dt[ip];
3673 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
3675 atm->
p[ip] += cache->
dt[ip] * wm;
3688 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3694 atm->
time[ip], atm->
p[ip],
3695 atm->
lon[ip], atm->
lat[ip],
3696 &atm->
q[qnt][ip], ci, cw, 1);
3699 double dts, u[4], um = 0, v[4], vm = 0, wdot[4],
3700 wdotm = 0, x[3] = { 0, 0, 0 };
3703 for (
int i = 0; i < ctl->
advect; i++) {
3708 x[0] = atm->
lon[ip];
3709 x[1] = atm->
lat[ip];
3710 x[2] = atm->
q[qnt][ip];
3712 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
3713 x[0] = atm->
lon[ip] +
DX2COORD(met0, dts * u[i - 1], atm->
lat[ip]);
3714 x[1] = atm->
lat[ip] +
DY2COORD(met0, dts * v[i - 1]);
3715 x[2] = atm->
q[qnt][ip] + dts * wdot[i - 1];
3718 const double tm = atm->
time[ip] + dts;
3723 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3726 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3729 tm, x[2], x[0], x[1], &wdot[i], ci, cw, 0);
3734 k = (i == 0 ? 0.0 : 1.0);
3735 else if (ctl->
advect == 4)
3736 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
3740 wdotm += k * wdot[i];
3744 atm->
time[ip] += cache->
dt[ip];
3746 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
3748 atm->
q[qnt][ip] += cache->
dt[ip] * wdotm;
3754 atm->
q[qnt][ip], atm->
lon[ip], atm->
lat[ip],
3755 &atm->
p[ip], ci, cw, 1);
3783 atm->
lon[ip], atm->
lat[ip], &atm->
p[ip], ci, cw, 1);
3808 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3844 if (atm->
p[ip] < pbl)
3893 ERRMSG(
"Only lat/lon grid supported");
3899 ERRMSG(
"Molar mass is not defined!");
3905 const int ensemble_mode = (ctl->
nens > 0);
3906 const int np = atm->
np;
3910 const int ngrid = nx * ny * nz;
3911 const int nens = ensemble_mode ? ctl->
nens : 1;
3913 double *restrict
const z = (
double *) malloc((
size_t) nz *
sizeof(double));
3914 double *restrict
const press =
3915 (
double *) malloc((
size_t) nz *
sizeof(double));
3916 double *restrict
const mass =
3917 (
double *) calloc((
size_t) ngrid * (size_t) nens,
sizeof(
double));
3918 double *restrict
const area =
3919 (
double *) malloc((
size_t) ny *
sizeof(double));
3920 double *restrict
const lon =
3921 (
double *) malloc((
size_t) nx *
sizeof(double));
3922 double *restrict
const lat =
3923 (
double *) malloc((
size_t) ny *
sizeof(double));
3925 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
3926 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
3927 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
3936#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])
3937#pragma acc data present(ctl,met0,met1,atm,ixs,iys,izs,z,press,mass,area,lon,lat)
3938#pragma acc parallel loop independent gang vector
3940#pragma omp parallel for default(shared)
3942 for (
int iz = 0; iz < nz; iz++) {
3944 press[iz] =
P(z[iz]);
3948 const double t0 = tt - 0.5 * ctl->
dt_mod;
3949 const double t1 = tt + 0.5 * ctl->
dt_mod;
3953#pragma acc parallel loop independent gang vector
3955#pragma omp parallel for default(shared)
3957 for (
int ip = 0; ip < np; ip++) {
3961 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
3962 || ixs[ip] < 0 || ixs[ip] >= nx
3963 || iys[ip] < 0 || iys[ip] >= ny || izs[ip] < 0 || izs[ip] >= nz)
3969#pragma acc parallel loop independent gang vector
3971#pragma omp parallel for default(shared)
3973 for (
int ix = 0; ix < nx; ix++)
3977#pragma acc parallel loop independent gang vector
3979#pragma omp parallel for default(shared)
3981 for (
int iy = 0; iy < ny; iy++) {
3983 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
3988#pragma acc parallel loop independent gang vector
3990 for (
int ip = 0; ip < np; ip++) {
3992 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
3993 if (ensemble_mode) {
3994 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
3995 mass_idx += ens * ngrid;
3998#pragma acc atomic update
4000 mass[mass_idx] += atm->
q[ctl->
qnt_m][ip];
4006#pragma acc parallel loop independent gang vector
4008#pragma omp parallel for default(shared)
4010 for (
int ip = 0; ip < np; ip++)
4018 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
4021 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
4022 if (ensemble_mode) {
4023 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
4024 mass_idx += ens * ngrid;
4028 const double m = mass[mass_idx];
4030 / (
RHO(press[izs[ip]], temp) * area[iys[ip]] * dz * 1e9);
4035#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
4063 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4079 const double lat_ref =
4082 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
4084 lat_ref, atm->
p[ip]));
4086 lat_ref, atm->
p[ip]));
4088 lat_ref, atm->
p[ip]));
4108 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4116 double pbot = ps, ptop = ps;
4133 double cape, cin, pel;
4139 if (isfinite(cape) && cape >= ctl->
conv_cape
4141 ptop = GSL_MIN(ptop, pel);
4145 if (ptop != pbot && atm->
p[ip] >= ptop) {
4150 pbot, atm->
lon[ip], atm->
lat[ip], &tbot, ci, cw, 1);
4152 atm->
lon[ip], atm->
lat[ip], &ttop, ci, cw, 1);
4153 const double rhobot = pbot / tbot;
4154 const double rhotop = ptop / ttop;
4157 const double rho = rhobot + (rhotop - rhobot) * cache->
rs[ip];
4160 atm->
p[ip] =
LIN(rhobot, pbot, rhotop, ptop, rho);
4177 int npart = 0, capacity = 0;
4185 dd_sort(ctl, *met, atm, dd, &npart);
4187 dd_push(ctl, atm, cache, &npart);
4190 if (npart > capacity) {
4191 const int newcap = npart + npart / 2 + 1;
4193 realloc(particles, (
size_t) newcap *
sizeof(
particle_t));
4195 ERRMSG(
"Out of memory!");
4204 MPI_Barrier(MPI_COMM_WORLD);
4230 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4233 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,clim,atm)") {
4242 const double aux = exp(-cache->
dt[ip] / tdec);
4243 if (ctl->
qnt_m >= 0) {
4246 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
4247 atm->
q[ctl->
qnt_m][ip] *= aux;
4272 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4280 float umean = 0, usig = 0, vmean = 0, vsig = 0, wmean = 0, wsig = 0;
4281 for (
int i = 0; i < 2; i++)
4282 for (
int j = 0; j < 2; j++)
4283 for (
int k = 0; k < 2; k++) {
4284 umean += met0->
u[ix + i][iy + j][iz + k];
4285 usig +=
SQR(met0->
u[ix + i][iy + j][iz + k]);
4286 vmean += met0->
v[ix + i][iy + j][iz + k];
4287 vsig +=
SQR(met0->
v[ix + i][iy + j][iz + k]);
4288 wmean += met0->
w[ix + i][iy + j][iz + k];
4289 wsig +=
SQR(met0->
w[ix + i][iy + j][iz + k]);
4291 umean += met1->
u[ix + i][iy + j][iz + k];
4292 usig +=
SQR(met1->
u[ix + i][iy + j][iz + k]);
4293 vmean += met1->
v[ix + i][iy + j][iz + k];
4294 vsig +=
SQR(met1->
v[ix + i][iy + j][iz + k]);
4295 wmean += met1->
w[ix + i][iy + j][iz + k];
4296 wsig +=
SQR(met1->
w[ix + i][iy + j][iz + k]);
4298 usig = usig / 16.f -
SQR(umean / 16.f);
4299 usig = (usig > 0 ? sqrtf(usig) : 0);
4300 vsig = vsig / 16.f -
SQR(vmean / 16.f);
4301 vsig = (vsig > 0 ? sqrtf(vsig) : 0);
4302 wsig = wsig / 16.f -
SQR(wmean / 16.f);
4303 wsig = (wsig > 0 ? sqrtf(wsig) : 0);
4306 const double r = 1 - 2 * fabs(cache->
dt[ip]) / ctl->
dt_met;
4307 const double r2 = sqrt(1 - r * r);
4311 cache->
uvwp[ip][0] =
4312 (float) (r * cache->
uvwp[ip][0] +
4317 cache->
uvwp[ip][1] =
4318 (float) (r * cache->
uvwp[ip][1] +
4325 cache->
uvwp[ip][2] =
4326 (float) (r * cache->
uvwp[ip][2] +
4328 atm->
p[ip] += cache->
uvwp[ip][2] * cache->
dt[ip];
4349 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4351 double pbl, ps, dsigw_dz = 0.0, sig_u = 0.0, sig_v = 0.0, sig_w = 0.0;
4352 double tau_u = 0.0, tau_v = 0.0, tau_w = 0.0;
4359 if (atm->
p[ip] < pbl)
4366 if (!(ps > 0.0 && pbl > 0.0 && ps > pbl))
4371 const double p =
MIN(atm->
p[ip], ps);
4372 const double zs =
Z(ps);
4373 const double z_raw = 1e3 * (
Z(p) - zs);
4374 const double zi = 1e3 * (
Z(pbl) - zs);
4381 const double z =
CLAMP(z_raw, 0.0, zi);
4382 const double zeta =
CLAMP(z / zi, 1e-6, 1.0 - 1e-6);
4383 const double z_m =
MAX(z, 1.0);
4388 const double p_save = atm->
p[ip];
4392 double ess, nss, h2o, t;
4399 atm->
p[ip] = p_save;
4401 const double tv =
TVIRT(t, h2o);
4402 const double thetav =
THETAVIRT(p, t, h2o);
4403 const double rho =
RHO(p, tv);
4404 const double tau = sqrt(
SQR(ess) +
SQR(nss));
4409 const double ustar = sqrt(
MAX(tau / rho, 0.0));
4410 const double ust =
MAX(1e-4, ustar);
4421 if (fabs(shf) > 1e-6)
4425 if (zi / fabs(ol) < 1.0) {
4430 const double corr = z_m / ust;
4431 const double sigw0 = 1.3 * ust * exp(-2e-4 * corr);
4433 sig_u =
MAX(2.0 * ust * exp(-3e-4 * corr), 1e-5);
4434 sig_v =
MAX(sigw0, 1e-5);
4435 sig_w =
MAX(sigw0, 1e-5);
4436 dsigw_dz = -2e-4 * sigw0 / ust;
4438 tau_u = 0.5 * z_m / sig_w / (1.0 + 1.5e-3 * corr);
4444 else if (ol < 0.0) {
4447 const double wstar_arg = -
G0 / thetav * shf / (rho *
CPD) * zi;
4448 const double wstar = pow(
MAX(wstar_arg, 0.0), 1.0 / 3.0);
4449 double dsigw2_dz = 0.0;
4452 sig_u =
MAX(ust * pow(
MAX(12.0 - 0.5 * zi / ol, 0.0), 1.0 / 3.0), 1e-6);
4456 const double arg =
MAX(3.0 * zeta - ol / zi, 1e-12);
4457 sig_w = 0.96 * wstar * pow(arg, 1.0 / 3.0);
4458 dsigw2_dz = 1.8432 *
SQR(wstar) / zi * pow(arg, -1.0 / 3.0);
4459 }
else if (zeta < 0.4) {
4460 const double arg =
MAX(3.0 * zeta - ol / zi, 1e-12);
4461 const double s1 = 0.96 * pow(arg, 1.0 / 3.0);
4462 const double s2 = 0.763 * pow(zeta, 0.175);
4465 dsigw2_dz = 1.8432 *
SQR(wstar) / zi * pow(arg, -1.0 / 3.0);
4468 dsigw2_dz = 0.203759 *
SQR(wstar) / zi * pow(zeta, -0.65);
4470 }
else if (zeta < 0.96) {
4471 sig_w = 0.722 * wstar * pow(1.0 - zeta, 0.207);
4472 dsigw2_dz = -0.215812 *
SQR(wstar) / zi * pow(1.0 - zeta, -0.586);
4474 sig_w = 0.37 * wstar;
4478 sig_w =
MAX(sig_w, 1e-6);
4479 dsigw_dz = sig_w > 1e-12 ? 0.5 * dsigw2_dz / sig_w : 0.0;
4482 tau_u = 0.15 * zi /
MAX(sig_u, 1e-12);
4485 if (z_m < fabs(ol)) {
4486 const double denom = 0.55 - 0.38 * fabs(z_m / ol);
4487 tau_w = 0.1 * z_m / (sig_w *
MAX(denom, 0.05));
4488 }
else if (zeta < 0.1)
4489 tau_w = 0.59 * z_m / sig_w;
4491 tau_w = 0.15 * zi / sig_w * (1.0 - exp(-5.0 * zeta));
4497 sig_u =
MAX(2.0 * ust * (1.0 - zeta), 1e-6);
4498 sig_v =
MAX(1.3 * ust * (1.0 - zeta), 1e-6);
4499 sig_w =
MAX(1.3 * ust * (1.0 - zeta), 1e-6);
4500 dsigw_dz = -1.3 * ust / zi;
4502 tau_u = 0.15 * zi / sig_u * sqrt(zeta);
4503 tau_v = 0.467 * tau_u;
4504 tau_w = 0.1 * zi / sig_w * pow(zeta, 0.8);
4508 tau_u =
MAX(tau_u, 10.0);
4509 tau_v =
MAX(tau_v, 10.0);
4510 tau_w =
MAX(tau_w, 30.0);
4513 if (!(sig_u > 0.0 && sig_v > 0.0
4514 && sig_w > 0.0 && tau_u > 0.0 && tau_v > 0.0 && tau_w > 0.0))
4518 const double dt = cache->
dt[ip];
4519 const double dt_abs = fabs(dt);
4521 const double ru = exp(-dt_abs / tau_u);
4522 const double ru2 = sqrt(
MAX(0.0, 1.0 -
SQR(ru)));
4523 const double rv = exp(-dt_abs / tau_v);
4524 const double rv2 = sqrt(
MAX(0.0, 1.0 -
SQR(rv)));
4527 = (float) (cache->
uvwp[ip][0] * ru + sig_u * ru2 * cache->
rs[3 * ip]);
4530 = (float) (cache->
uvwp[ip][1] * rv
4531 + sig_v * rv2 * cache->
rs[3 * ip + 1]);
4536 const double rw = exp(-dt_abs / tau_w);
4537 const double rw2 = sqrt(
MAX(0.0, 1.0 -
SQR(rw)));
4538 const double rhoaux = -1.0 / (1e3 *
H0);
4541 = (float) (cache->
uvwp[ip][2] * rw + sig_w * rw2 * cache->
rs[3 * ip + 2]
4542 + tau_w * (1.0 - rw)
4543 * (2.0 * sig_w * dsigw_dz + rhoaux *
SQR(sig_w)));
4553 double znew = z + cache->
uvwp[ip][2] * dt;
4555 while (znew < 0.0 || znew > zi) {
4559 cache->
uvwp[ip][2] = -cache->
uvwp[ip][2];
4563 znew = 2.0 * zi - znew;
4564 cache->
uvwp[ip][2] = -cache->
uvwp[ip][2];
4571 atm->
p[ip] =
P(zs + znew / 1000.0);
4574 atm->
p[ip] =
CLAMP(atm->
p[ip], pbl, ps);
4596 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4612 const double ptop = met0->
p[met0->
np - 1];
4615 const double wpbl =
pbl_weight(ctl, atm, ip, pbl, ps);
4616 const double wtrop =
tropo_weight(ctl, clim, atm, ip) * (1.0 - wpbl);
4617 const double wstrat = 1.0 - wpbl - wtrop;
4629 const double dt_abs = fabs(cache->
dt[ip]);
4634 const double sigma_h = sqrt(2.0 * Kx * dt_abs);
4639 atm->
lat[ip] +=
DY2COORD(met0, cache->
rs[3 * ip + 1] * sigma_h);
4647 const double sigma_z = sqrt(2.0 * Kz * dt_abs) * 1e-3;
4651 const double p_save = atm->
p[ip];
4656 const double eps_km = 0.01;
4657 const double p_up = p_save +
DZ2DP(eps_km, p_save);
4658 const double p_dn = p_save +
DZ2DP(-eps_km, p_save);
4661 atm->
p[ip] =
MAX(ptop,
MIN(ps, p_up));
4662 const double wpbl_up =
pbl_weight(ctl, atm, ip, pbl, ps);
4663 const double wtrop_up =
4665 const double wstrat_up = 1.0 - wpbl_up - wtrop_up;
4667 const double Kz_up =
4672 atm->
p[ip] =
MAX(ptop,
MIN(ps, p_dn));
4673 const double wpbl_dn =
pbl_weight(ctl, atm, ip, pbl, ps);
4674 const double wtrop_dn =
4676 const double wstrat_dn = 1.0 - wpbl_dn - wtrop_dn;
4678 const double Kz_dn =
4683 atm->
p[ip] = p_save;
4697 const double dKz_dz = (Kz_up - Kz_dn) / (2.0 * eps_km * 1e3);
4698 const double dlnrho_dz = -1.0 / (1e3 *
H0);
4699 const double w_drift = dKz_dz + Kz * dlnrho_dz;
4700 const double dz_drift = w_drift * dt_abs * 1e-3;
4703 const double dz_tot = cache->
rs[3 * ip + 2] * sigma_z + dz_drift;
4706 double ptrial = p_save +
DZ2DP(dz_tot, p_save);
4713 for (
int iter = 0; iter < 10; iter++) {
4715 ptrial = ps * ps / ptrial;
4716 else if (ptrial < ptop)
4717 ptrial = ptop * ptop / ptrial;
4723 atm->
p[ip] =
MAX(ptop,
MIN(ps, ptrial));
4742 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4745 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4757 const double dz = 1000. * (
Z(ps - ctl->
dry_depo_dp) -
Z(ps));
4777 const double aux = exp(-cache->
dt[ip] * v_dep / dz);
4778 if (ctl->
qnt_m >= 0) {
4781 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
4782 atm->
q[ctl->
qnt_m][ip] *= aux;
4802 ERRMSG(
"Only lat/lon grid supported");
4809 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4812 const double a = 3.12541941e-06;
4813 const double b = -5.72532259e-01;
4814 const double low = pow(1. / a, 1. / b);
4817 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4824 if (!(lwc > 0 || rwc > 0))
4835 const double k = 9.1e7 * exp(-29700. /
RI * (1. / t - 1. / 298.15));
4838 const double H_SO2 =
4839 1.3e-2 * exp(2900. * (1. / t - 1. / 298.15)) *
RI * t;
4840 const double K_1S = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
4843 const double H_h2o2 =
4844 8.3e2 * exp(7600. * (1. / t - 1. / 298.15)) *
RI * t;
4850 cor = atm->
q[ctl->
qnt_Cx][ip] >
4851 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
4853 const double h2o2 = H_h2o2
4855 * M * cor * 1000. /
AVO;
4858 const double rho_air = atm->
p[ip] / (
RI * t) *
MA / 10.;
4859 const double CWC = (lwc + rwc) * rho_air / 1e3;
4862 const double rate_coef = k * K_1S * h2o2 * H_SO2 * CWC;
4863 const double aux = exp(-cache->
dt[ip] * rate_coef);
4864 if (ctl->
qnt_m >= 0) {
4867 atm->
q[ctl->
qnt_m][ip] *= aux;
4899 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
4902 cache->
iso_var[ip] = atm->
p[ip] / t;
4908 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
4919 LOG(1,
"Read balloon pressure data: %s", ctl->
balloon);
4923 if (!(in = fopen(ctl->
balloon,
"r")))
4924 ERRMSG(
"Cannot open file!");
4928 while (fgets(line,
LEN, in))
4929 if (sscanf(line,
"%lg %lg", &(cache->
iso_ts[cache->
iso_n]),
4932 ERRMSG(
"Too many data points!");
4935 if (cache->
iso_n < 1)
4936 ERRMSG(
"Could not read any data!");
4959 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,met1,atm)") {
4972 atm->
p[ip] = cache->
iso_var[ip] * t;
4978 atm->
p[ip] = 1000. * pow(cache->
iso_var[ip] / t, -1. / 0.286);
4984 atm->
p[ip] = cache->
iso_ps[0];
5012 const int nvar = NVAR, nfix = NFIX, nreact = NREACT;
5013 double rtol[1] = { 1.0e-3 };
5014 double atol[1] = { 1.0 };
5018#pragma acc data copy(rtol,atol,nvar,nfix,nreact)
5021 "acc data present(ctl,cache,clim,met0,met1,atm) ") {
5024 double var[nvar], fix[nfix], rconst[nreact];
5025 for (
int i = 0; i < nvar; i++)
5027 for (
int i = 0; i < nfix; i++)
5029 for (
int i = 0; i < nreact; i++)
5031 kpp_chem_initialize(ctl, clim, met0, met1, atm, var, fix, rconst, ip);
5036 for (
int i = 0; i < 20; i++) {
5043 Rosenbrock(var, fix, rconst, 0, ctl->
dt_kpp,
5044 atol, rtol, &FunTemplate, &JacTemplate, rpar, ipar);
5047 kpp_chem_output2atm(atm, ctl, met0, met1, var, ip);
5068 ERRMSG(
"Need T_ice and T_NAT to calculate T_STS!");
5072 "acc data present(ctl,cache,clim,met0,met1,atm)") {
5074 double ps, ts, zs, us, vs, ess, nss, shf, lsm, sst, pbl, pt, pct, pcb,
5075 cl, plcl, plfc, pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot,
5076 o3, lwc, rwc, iwc, swc, cc, z, zt;
5121 const double lat_ref =
5126 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
5128 lat_ref, atm->
p[ip]));
5131 SET_ATM(qnt_vh, sqrt(u * u + v * v));
5153 atm->
lat[ip], atm->
p[ip])));
5171 const int np = atm->
np;
5172 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
5173 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
5174 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
5182 const double t0 = t - 0.5 * ctl->
dt_mod;
5183 const double t1 = t + 0.5 * ctl->
dt_mod;
5187#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
5188#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
5189#pragma acc parallel loop independent gang vector
5191#pragma omp parallel for default(shared)
5193 for (
int ip = 0; ip < np; ip++) {
5196 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
mixing_z0) / dz);
5197 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
5198 || ixs[ip] < 0 || ixs[ip] >= ctl->
mixing_nx
5199 || iys[ip] < 0 || iys[ip] >= ctl->
mixing_ny
5200 || izs[ip] < 0 || izs[ip] >= ctl->
mixing_nz)
5205 const int use_ensemble = (ctl->
nens > 0);
5207 const int quantities[] = {
5215 const int n_qnt =
sizeof(quantities) /
sizeof(quantities[0]);
5217 for (
int i = 0; i < n_qnt; i++)
5218 if (quantities[i] >= 0)
5224#pragma acc exit data delete(ixs,iys,izs)
5241 const int use_ensemble) {
5243 const int np = atm->
np;
5245 const int nens = use_ensemble ? ctl->
nens : 1;
5246 const int total_grid = ngrid * nens;
5248 double *restrict
const cmean =
5249 (
double *) malloc((
size_t) total_grid *
sizeof(double));
5250 int *restrict
const count =
5251 (
int *) malloc((
size_t) total_grid *
sizeof(int));
5255#pragma acc enter data create(cmean[0:total_grid],count[0:total_grid])
5256#pragma acc data present(ctl,clim,atm,ixs,iys,izs,cmean,count)
5257#pragma acc parallel loop independent gang vector
5262#pragma omp parallel for
5264 for (
int i = 0; i < total_grid; i++) {
5271#pragma acc parallel loop independent gang vector
5273 for (
int ip = 0; ip < np; ip++)
5275 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
5280#pragma acc atomic update
5282 cmean[idx] += atm->
q[qnt_idx][ip];
5284#pragma acc atomic update
5291#pragma acc parallel loop independent gang vector
5296#pragma omp parallel for
5298 for (
int i = 0; i < total_grid; i++)
5300 cmean[i] /= count[i];
5304#pragma acc parallel loop independent gang vector
5306#pragma omp parallel for
5308 for (
int ip = 0; ip < np; ip++) {
5310 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
5312 double mixparam = 1.0;
5321 atm->
q[qnt_idx][ip] += (cmean[idx] - atm->
q[qnt_idx][ip]) * mixparam;
5327#pragma acc exit data delete(cmean,count)
5348 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
5351 const double a = 4.71572206e-08;
5352 const double b = -8.28782867e-01;
5353 const double low = pow(1. / a, 1. / b);
5357 "acc data present(ctl,cache,clim,met0,met1,atm)") {
5383 0 ? pow(298. / t, ctl->
oh_chem[1]) : 1.);
5386 0 ? pow(298. / t, ctl->
oh_chem[3]) : 1.);
5387 const double c = log10(k0 * M / ki);
5388 k = k0 * M / (1. + k0 * M / ki) * pow(0.6, 1. / (1. + c * c));
5397 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
5400 const double rate_coef =
5402 atm->
lat[ip], atm->
p[ip]) * M * cor;
5403 const double aux = exp(-cache->
dt[ip] * rate_coef);
5404 if (ctl->
qnt_m >= 0) {
5407 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
5408 atm->
q[ctl->
qnt_m][ip] *= aux;
5429 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(cache,met0,met1,atm)") {
5441 while (atm->
lat[ip] < -90 || atm->
lat[ip] > 90) {
5442 if (atm->
lat[ip] > 90) {
5443 atm->
lat[ip] = 180 - atm->
lat[ip];
5444 atm->
lon[ip] += 180;
5446 if (atm->
lat[ip] < -90) {
5447 atm->
lat[ip] = -180 - atm->
lat[ip];
5448 atm->
lon[ip] += 180;
5453 while (atm->
lon[ip] < -180)
5454 atm->
lon[ip] += 360;
5455 while (atm->
lon[ip] >= 180)
5456 atm->
lon[ip] -= 360;
5459 atm->
lon[ip], atm->
lat[ip], &atm->
lon[ip],
5464 const double ptop = met0->
p[met0->
np - 1];
5465 if (atm->
p[ip] < ptop) {
5466 atm->
p[ip] = ptop * ptop / atm->
p[ip];
5467 }
else if (atm->
p[ip] > 300.) {
5469 if (atm->
p[ip] > ps)
5470 atm->
p[ip] = ps * ps / atm->
p[ip];
5486 const double lambda_rn222 = log(2.0) / (3.8235 * 86400.0);
5487 const double lambda_pb210 = log(2.0) / (22.3 * 365.25 * 86400.0);
5488 const double lambda_be7 = log(2.0) / (53.22 * 86400.0);
5489 const double lambda_cs137 = log(2.0) / (30.05 * 365.25 * 86400.0);
5490 const double lambda_i131 = log(2.0) / (8.02 * 86400.0);
5491 const double lambda_xe133 = log(2.0) / (5.2474 * 86400.0);
5497 const double dt = cache->
dt[ip];
5501 atm->
q[ctl->
qnt_Apb210][ip] *= exp(-dt * lambda_pb210);
5506 const double aux = exp(-dt * lambda_rn222);
5507 const double lost = old * (1.0 - aux);
5512 atm->
q[ctl->
qnt_Apb210][ip] += lost * lambda_pb210 / lambda_rn222;
5517 atm->
q[ctl->
qnt_Abe7][ip] *= exp(-dt * lambda_be7);
5521 atm->
q[ctl->
qnt_Acs137][ip] *= exp(-dt * lambda_cs137);
5525 atm->
q[ctl->
qnt_Ai131][ip] *= exp(-dt * lambda_i131);
5529 atm->
q[ctl->
qnt_Axe133][ip] *= exp(-dt * lambda_xe133);
5539 gsl_rng_env_setup();
5540 if (omp_get_max_threads() >
NTHREADS)
5541 ERRMSG(
"Too many threads!");
5542 for (
int i = 0; i <
NTHREADS; i++) {
5543 rng[i] = gsl_rng_alloc(gsl_rng_default);
5544 gsl_rng_set(rng[i], gsl_rng_default_seed
5545 + (
long unsigned) (ntask *
NTHREADS + i));
5550 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
5551 CURAND_STATUS_SUCCESS)
5552 ERRMSG(
"Cannot create random number generator!");
5553 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
5554 CURAND_STATUS_SUCCESS)
5555 ERRMSG(
"Cannot set seed for random number generator!");
5558 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
5559 CURAND_STATUS_SUCCESS)
5560 ERRMSG(
"Cannot set stream for random number generator!");
5577#pragma omp parallel for default(shared)
5578 for (
size_t i = 0; i < n; ++i)
5579 rs[i] = gsl_rng_uniform(rng[omp_get_thread_num()]);
5583 else if (method == 1) {
5584#pragma omp parallel for default(shared)
5585 for (
size_t i = 0; i < n; ++i)
5586 rs[i] = gsl_ran_gaussian_ziggurat(rng[omp_get_thread_num()], 1.0);
5592#pragma acc update device(rs[:n])
5600 const uint64_t key = 0xc8e4fd154ce32f6d;
5604#pragma acc data present(rs)
5605#pragma acc parallel loop independent gang vector
5607#pragma omp parallel for default(shared)
5609 for (
size_t i = 0; i < n + 1; ++i) {
5610 uint64_t r, t, x, y, z;
5611 y = x = (rng_ctr + i) * key;
5614 x = (x >> 32) | (x << 32);
5616 x = (x >> 32) | (x << 32);
5618 x = (x >> 32) | (x << 32);
5620 x = (x >> 32) | (x << 32);
5621 r = t ^ ((x * x + y) >> 32);
5622 rs[i] = (double) r / (
double) UINT64_MAX;
5629#pragma acc parallel loop independent gang vector
5631#pragma omp parallel for default(shared)
5633 for (
size_t i = 0; i < n; i += 2) {
5634 const double r = sqrt(-2.0 * log(rs[i]));
5635 const double phi = 2.0 * M_PI * rs[i + 1];
5636 rs[i] = r * cosf((
float) phi);
5637 rs[i + 1] = r * sinf((
float) phi);
5645#pragma acc host_data use_device(rs)
5650 if (curandGenerateUniformDouble(rng_curand, rs, (n < 4 ? 4 : n)) !=
5651 CURAND_STATUS_SUCCESS)
5652 ERRMSG(
"Cannot create random numbers!");
5656 else if (method == 1) {
5657 if (curandGenerateNormalDouble
5658 (rng_curand, rs, (n < 4 ? 4 : n), 0.0,
5659 1.0) != CURAND_STATUS_SUCCESS)
5660 ERRMSG(
"Cannot create random numbers!");
5664 ERRMSG(
"MPTRAC was compiled without cuRAND!");
5681 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
5689 const double v_s =
sedi(atm->
p[ip], t, atm->
q[ctl->
qnt_rp][ip],
5693 atm->
p[ip] +=
DZ2DP(v_s * cache->
dt[ip] / 1000., atm->
p[ip]);
5708 const int np = atm->
np;
5709 double *restrict
const a = (
double *) malloc((
size_t) np *
sizeof(double));
5710 int *restrict
const p = (
int *) malloc((
size_t) np *
sizeof(int));
5711 if (a == NULL || p == NULL)
5712 ERRMSG(
"Out of memory!");
5715#pragma acc enter data create(a[0:np],p[0:np])
5716#pragma acc data present(ctl,met0,atm,a,p)
5721#pragma acc parallel loop independent gang vector
5723#pragma omp parallel for default(shared)
5725 for (
int ip = 0; ip < np; ip++) {
5736#pragma acc host_data use_device(a,p)
5738 thrustSortWrapper(a, np, p);
5740 size_t *perm_sz = (
size_t *) malloc((
size_t) np *
sizeof(size_t));
5741 if (perm_sz == NULL)
5742 ERRMSG(
"Out of memory!");
5744#pragma acc update self(a[0:np])
5746 gsl_sort_index(perm_sz, a, 1, (
size_t) np);
5747 for (
int ip = 0; ip < np; ++ip)
5748 p[ip] = (
int) perm_sz[ip];
5751#pragma acc update device(p[0:np])
5760 for (
int iq = 0; iq < ctl->
nq; iq++)
5765#pragma acc exit data delete(a,p)
5779 double *restrict
const help =
5780 (
double *) malloc((
size_t) np *
sizeof(double));
5782 ERRMSG(
"Out of memory!");
5786#pragma acc enter data create(help[0:np])
5787#pragma acc data present(a,p,help)
5788#pragma acc parallel loop independent gang vector
5790#pragma omp parallel for default(shared)
5792 for (
int ip = 0; ip < np; ip++)
5793 help[ip] = a[p[ip]];
5795#pragma acc parallel loop independent gang vector
5797#pragma omp parallel for default(shared)
5799 for (
int ip = 0; ip < np; ip++)
5804#pragma acc exit data delete(help)
5821 const double latmin = gsl_stats_min(met0->
lat, 1, (
size_t) met0->
ny),
5822 latmax = gsl_stats_max(met0->
lat, 1, (
size_t) met0->
ny);
5825 (fabs(met0->
lon[met0->
nx - 1] - met0->
lon[0] - 360.0) >= 0.01);
5828 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,atm)") {
5834 cache->
dt[ip] = t - atm->
time[ip];
5836 cache->
dt[ip] = 0.0;
5845 if (local && (atm->
lon[ip] <= met0->
lon[0]
5846 || atm->
lon[ip] >= met0->
lon[met0->
nx - 1]
5847 || atm->
lat[ip] <= latmin || atm->
lat[ip] >= latmax))
5848 cache->
dt[ip] = 0.0;
5867 ctl->
t_start = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
5869 ctl->
t_stop = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
5871 ctl->
t_start = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
5873 ctl->
t_stop = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
5878 ERRMSG(
"Nothing to do! Check T_STOP and DIRECTION!");
5898 ERRMSG(
"Only lat/lon grid supported");
5905 "acc data present(ctl,cache,clim,met0,met1,atm)") {
5929 const double K_o1d =
ARRHENIUS(3.30e-10, 0, t) * o1d * M;
5931 atm->
p[ip], sza, o3c);
5932 atm->
q[ctl->
qnt_Cccl4][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5937 const double K_o1d =
ARRHENIUS(2.30e-10, 0, t) * o1d * M;
5939 atm->
p[ip], sza, o3c);
5940 atm->
q[ctl->
qnt_Cccl3f][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5945 const double K_o1d =
ARRHENIUS(1.40e-10, -25, t) * o1d * M;
5947 atm->
p[ip], sza, o3c);
5948 atm->
q[ctl->
qnt_Cccl2f2][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5953 const double K_o1d =
ARRHENIUS(1.19e-10, -20, t) * o1d * M;
5955 atm->
p[ip], sza, o3c);
5956 atm->
q[ctl->
qnt_Cn2o][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5975 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
5978 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
5984 if (!isfinite(pct) || atm->
p[ip] <= pct)
6000 double lwc, rwc, iwc, swc;
6005 const int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
6019 else if (t <= 238.15)
6039 const double K_1 = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
6040 const double K_2 = 6e-8 * exp(1.12e3 * (1. / t - 1. / 298.15));
6041 h *= (1. + K_1 / H_ion + K_1 * K_2 /
SQR(H_ion));
6045 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
6048 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
6074 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
6077 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
6082 const double aux = exp(-cache->
dt[ip] * lambda);
6083 if (ctl->
qnt_m >= 0) {
6086 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
6087 atm->
q[ctl->
qnt_m][ip] *= aux;
6112 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
6114 if (acc_get_num_devices(acc_device_nvidia) <= 0)
6115 ERRMSG(
"Not running on a GPU device!");
6116 acc_set_device_num(rank % acc_get_num_devices(acc_device_nvidia),
6118 acc_device_t device_type = acc_get_device_type();
6119 acc_init(device_type);
6135 ctl_t *ctlup = *ctl;
6138 met_t *met0up = *met0;
6139 met_t *met1up = *met1;
6140 atm_t *atmup = *atm;
6141#pragma acc enter data create(ctlup[:1],cacheup[:1],climup[:1],met0up[:1],met1up[:1],atmup[:1])
6144#pragma acc enter data create(ddup[:1])
6163#pragma acc exit data delete(ctl,cache,clim,met0,met1,atm)
6165#pragma acc exit data delete(dd)
6180 MPI_Type_free(&dd->MPI_Particle);
6199 char cachefile[
LEN], cmd[2 *
LEN], filename[
LEN];
6205 if (t == ctl->
t_start || !init) {
6212 ERRMSG(
"Cannot open file!");
6217 ERRMSG(
"Cannot open file!");
6227 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
6228 LOG(1,
"Caching: %s", cachefile);
6229 if (system(cmd) != 0)
6230 WARN(
"Caching command failed!");
6235 if (t > (*met1)->time) {
6245 ERRMSG(
"Cannot open file!");
6255 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
6256 LOG(1,
"Caching: %s", cachefile);
6257 if (system(cmd) != 0)
6258 WARN(
"Caching command failed!");
6263 if (t < (*met0)->time) {
6273 ERRMSG(
"Cannot open file!");
6283 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
6284 LOG(1,
"Caching: %s", cachefile);
6285 if (system(cmd) != 0)
6286 WARN(
"Caching command failed!");
6290 if ((*met0)->coord_type != (*met1)->coord_type)
6291 ERRMSG(
"Coordinate types do not match!");
6294 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
6295 if ((*met0)->nx != (*met1)->nx
6296 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
6297 ERRMSG(
"Meteo grid dimensions do not match!");
6298 for (
int ix = 0; ix < (*met0)->nx; ix++)
6299 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
6300 ERRMSG(
"Meteo grid longitudes do not match!");
6301 for (
int iy = 0; iy < (*met0)->ny; iy++)
6302 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
6303 ERRMSG(
"Meteo grid latitudes do not match!");
6304 for (
int ip = 0; ip < (*met0)->np; ip++)
6305 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
6306 ERRMSG(
"Meteo grid pressure levels do not match!");
6332 const char *filename,
6345 LOG(1,
"Read atmospheric data: %s", filename);
6365 ERRMSG(
"Atmospheric data type not supported!");
6373 ERRMSG(
"Can not read any data!");
6377 LOG(2,
"Number of particles: %d", atm->
np);
6378 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
6379 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
6380 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
6381 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
6382 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
6383 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
6384 LOG(2,
"%s range: %g ... %g %s",
6385 ctl->
met_coord_type == 0 ?
"Longitude" :
"X coordinate", mini, maxi,
6387 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
6388 LOG(2,
"%s range: %g ... %g %s",
6389 ctl->
met_coord_type == 0 ?
"Latitude" :
"Y coordinate", mini, maxi,
6391 for (
int iq = 0; iq < ctl->
nq; iq++) {
6393 sprintf(msg,
"Quantity %s range: %s ... %s %s",
6396 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
6397 LOG(2, msg, mini, maxi);
6467 const char *filename,
6476 LOG(1,
"\nMassive-Parallel Trajectory Calculations (MPTRAC)\n"
6477 "(executable: %s | version: %s | compiled: %s, %s)\n",
6478 argv[0], VERSION, __DATE__, __TIME__);
6585 ctl->
nq = (int)
scan_ctl(filename, argc, argv,
"NQ", -1,
"0", NULL);
6587 ERRMSG(
"Too many quantities!");
6588 for (
int iq = 0; iq < ctl->
nq; iq++) {
6594 scan_ctl(filename, argc, argv,
"QNT_FORMAT", iq,
"%g",
6596 if (strcasecmp(ctl->
qnt_name[iq],
"aoa") == 0)
6600 SET_QNT(qnt_idx,
"idx",
"particle index",
"-")
6601 SET_QNT(qnt_ens,
"ens",
"ensemble index",
"-")
6602 SET_QNT(qnt_stat,
"stat",
"station flag",
"-")
6603 SET_QNT(qnt_m,
"m",
"mass",
"kg")
6604 SET_QNT(qnt_vmr,
"vmr",
"volume mixing ratio",
"ppv")
6605 SET_QNT(qnt_rp,
"rp",
"particle radius",
"microns")
6606 SET_QNT(qnt_rhop,
"rhop",
"particle density",
"kg/m^3")
6607 SET_QNT(qnt_ps,
"ps",
"surface pressure",
"hPa")
6608 SET_QNT(qnt_ts,
"ts",
"surface temperature",
"K")
6609 SET_QNT(qnt_zs,
"zs",
"surface height",
"km")
6610 SET_QNT(qnt_us,
"us",
"surface zonal wind",
"m/s")
6611 SET_QNT(qnt_vs,
"vs",
"surface meridional wind",
"m/s")
6612 SET_QNT(qnt_ess,
"ess",
"eastward turbulent surface stress",
"N/m^2")
6613 SET_QNT(qnt_nss,
"nss",
"northward turbulent surface stress",
"N/m^2")
6614 SET_QNT(qnt_shf,
"shf",
"surface sensible heat flux",
"W/m^2")
6615 SET_QNT(qnt_lsm,
"lsm",
"land-sea mask",
"1")
6616 SET_QNT(qnt_sst,
"sst",
"sea surface temperature",
"K")
6617 SET_QNT(qnt_pbl,
"pbl",
"planetary boundary layer",
"hPa")
6618 SET_QNT(qnt_pt,
"pt",
"tropopause pressure",
"hPa")
6619 SET_QNT(qnt_tt,
"tt",
"tropopause temperature",
"K")
6620 SET_QNT(qnt_zt,
"zt",
"tropopause geopotential height",
"km")
6621 SET_QNT(qnt_h2ot,
"h2ot",
"tropopause water vapor",
"ppv")
6622 SET_QNT(qnt_zg,
"zg",
"geopotential height",
"km")
6623 SET_QNT(qnt_p,
"p",
"pressure",
"hPa")
6624 SET_QNT(qnt_t,
"t",
"temperature",
"K")
6625 SET_QNT(qnt_rho,
"rho",
"air density",
"kg/m^3")
6626 SET_QNT(qnt_u,
"u",
"zonal wind",
"m/s")
6627 SET_QNT(qnt_v,
"v",
"meridional wind",
"m/s")
6628 SET_QNT(qnt_w,
"w",
"vertical velocity",
"hPa/s")
6629 SET_QNT(qnt_h2o,
"h2o",
"water vapor",
"ppv")
6630 SET_QNT(qnt_o3,
"o3",
"ozone",
"ppv")
6631 SET_QNT(qnt_lwc,
"lwc",
"cloud liquid water content",
"kg/kg")
6632 SET_QNT(qnt_rwc,
"rwc",
"cloud rain water content",
"kg/kg")
6633 SET_QNT(qnt_iwc,
"iwc",
"cloud ice water content",
"kg/kg")
6634 SET_QNT(qnt_swc,
"swc",
"cloud snow water content",
"kg/kg")
6635 SET_QNT(qnt_cc,
"cc",
"cloud cover",
"1")
6636 SET_QNT(qnt_pct,
"pct",
"cloud top pressure",
"hPa")
6637 SET_QNT(qnt_pcb,
"pcb",
"cloud bottom pressure",
"hPa")
6638 SET_QNT(qnt_cl,
"cl",
"total column cloud water",
"kg/m^2")
6639 SET_QNT(qnt_plcl,
"plcl",
"lifted condensation level",
"hPa")
6640 SET_QNT(qnt_plfc,
"plfc",
"level of free convection",
"hPa")
6641 SET_QNT(qnt_pel,
"pel",
"equilibrium level",
"hPa")
6642 SET_QNT(qnt_cape,
"cape",
"convective available potential energy",
6644 SET_QNT(qnt_cin,
"cin",
"convective inhibition",
"J/kg")
6645 SET_QNT(qnt_o3c,
"o3c",
"total column ozone",
"DU")
6646 SET_QNT(qnt_hno3,
"hno3",
"nitric acid",
"ppv")
6647 SET_QNT(qnt_oh,
"oh",
"hydroxyl radical",
"ppv")
6648 SET_QNT(qnt_h2o2,
"h2o2",
"hydrogen peroxide",
"ppv")
6649 SET_QNT(qnt_ho2,
"ho2",
"hydroperoxyl radical",
"ppv")
6650 SET_QNT(qnt_o1d,
"o1d",
"atomic oxygen",
"ppv")
6651 SET_QNT(qnt_mloss_oh,
"mloss_oh",
"mass loss due to OH chemistry",
"kg")
6652 SET_QNT(qnt_mloss_h2o2,
"mloss_h2o2",
6653 "mass loss due to H2O2 chemistry",
"kg")
6654 SET_QNT(qnt_mloss_kpp,
"mloss_kpp",
"mass loss due to kpp chemistry",
6656 SET_QNT(qnt_mloss_wet,
"mloss_wet",
"mass loss due to wet deposition",
6658 SET_QNT(qnt_mloss_dry,
"mloss_dry",
"mass loss due to dry deposition",
6660 SET_QNT(qnt_mloss_decay,
"mloss_decay",
6661 "mass loss due to exponential decay",
"kg")
6662 SET_QNT(qnt_loss_rate,
"loss_rate",
"total loss rate",
"s^-1")
6663 SET_QNT(qnt_psat,
"psat",
"saturation pressure over water",
"hPa")
6664 SET_QNT(qnt_psice,
"psice",
"saturation pressure over ice",
"hPa")
6665 SET_QNT(qnt_pw,
"pw",
"partial water vapor pressure",
"hPa")
6666 SET_QNT(qnt_sh,
"sh",
"specific humidity",
"kg/kg")
6667 SET_QNT(qnt_rh,
"rh",
"relative humidity",
"%%")
6668 SET_QNT(qnt_rhice,
"rhice",
"relative humidity over ice",
"%%")
6669 SET_QNT(qnt_theta,
"theta",
"potential temperature",
"K")
6670 SET_QNT(qnt_zeta,
"zeta",
"zeta coordinate",
"K")
6671 SET_QNT(qnt_zeta_d,
"zeta_d",
"diagnosed zeta coordinate",
"K")
6672 SET_QNT(qnt_zeta_dot,
"zeta_dot",
"velocity of zeta coordinate",
6674 SET_QNT(qnt_eta,
"eta",
"eta coordinate",
"1")
6675 SET_QNT(qnt_eta_dot,
"eta_dot",
"velocity of eta coordinate",
"1/s")
6676 SET_QNT(qnt_tvirt,
"tvirt",
"virtual temperature",
"K")
6677 SET_QNT(qnt_lapse,
"lapse",
"temperature lapse rate",
"K/km")
6678 SET_QNT(qnt_vh,
"vh",
"horizontal velocity",
"m/s")
6679 SET_QNT(qnt_vz,
"vz",
"vertical velocity",
"m/s")
6680 SET_QNT(qnt_pv,
"pv",
"potential vorticity",
"PVU")
6681 SET_QNT(qnt_tdew,
"tdew",
"dew point temperature",
"K")
6682 SET_QNT(qnt_tice,
"tice",
"frost point temperature",
"K")
6683 SET_QNT(qnt_tsts,
"tsts",
"STS existence temperature",
"K")
6684 SET_QNT(qnt_tnat,
"tnat",
"NAT existence temperature",
"K")
6685 SET_QNT(qnt_Cx,
"Cx",
"Trace species x volume mixing ratio",
"ppv")
6686 SET_QNT(qnt_Ch2o,
"Ch2o",
"H2O volume mixing ratio",
"ppv")
6687 SET_QNT(qnt_Co3,
"Co3",
"O3 volume mixing ratio",
"ppv")
6688 SET_QNT(qnt_Cco,
"Cco",
"CO volume mixing ratio",
"ppv")
6689 SET_QNT(qnt_Coh,
"Coh",
"HO volume mixing ratio",
"ppv")
6690 SET_QNT(qnt_Ch,
"Ch",
"H radical volume mixing ratio",
"ppv")
6691 SET_QNT(qnt_Cho2,
"Cho2",
"HO2 volume mixing ratio",
"ppv")
6692 SET_QNT(qnt_Ch2o2,
"Ch2o2",
"H2O2 volume mixing ratio",
"ppv")
6693 SET_QNT(qnt_Co1d,
"Co1d",
"O(1D) volume mixing ratio",
"ppv")
6694 SET_QNT(qnt_Co3p,
"Co3p",
"O(3P) radical volume mixing ratio",
"ppv")
6695 SET_QNT(qnt_Cccl4,
"Cccl4",
"CCl4 (CFC-10) volume mixing ratio",
"ppv")
6696 SET_QNT(qnt_Cccl3f,
"Cccl3f",
"CCl3F (CFC-11) volume mixing ratio",
6698 SET_QNT(qnt_Cccl2f2,
"Cccl2f2",
"CCl2F2 (CFC-12) volume mixing ratio",
6700 SET_QNT(qnt_Cn2o,
"Cn2o",
"N2O volume mixing ratio",
"ppv")
6701 SET_QNT(qnt_Csf6,
"Csf6",
"SF6 volume mixing ratio",
"ppv")
6702 SET_QNT(qnt_aoa,
"aoa",
"age of air",
"s")
6703 SET_QNT(qnt_Arn222,
"Arn222",
"Rn-222 activity",
"Bq")
6704 SET_QNT(qnt_Apb210,
"Apb210",
"Pb-210 activity",
"Bq")
6705 SET_QNT(qnt_Abe7,
"Abe7",
"Be-7 activity",
"Bq")
6706 SET_QNT(qnt_Acs137,
"Acs137",
"Cs-137 activity",
"Bq")
6707 SET_QNT(qnt_Ai131,
"Ai131",
"I-131 activity",
"Bq")
6708 SET_QNT(qnt_Axe133,
"Axe133",
"Xe-133 activity",
"Bq")
6709 SET_QNT(qnt_current_subdomain,
"current_subdomain",
6710 "current subdomain rank",
"-")
6711 SET_QNT(qnt_target_subdomain,
"target_subdomain",
6712 "target subdomain rank",
"-")
6717 (int)
scan_ctl(filename, argc, argv,
"MET_COORD_TYPE", -1,
"0", NULL);
6719 ERRMSG(
"MET_COORD_TYPE must be 0 or 1!");
6724 scan_ctl(filename, argc, argv,
"MET_UTM_REF_LAT", -1,
"", NULL);
6726 scan_ctl(filename, argc, argv,
"MET_UTM_REF_LON", -1,
"", NULL);
6731 (int)
scan_ctl(filename, argc, argv,
"ADVECT_VERT_COORD", -1,
"0", NULL);
6733 ERRMSG(
"ADVECT_VERT_COORD must be 0, 1, 2, or 3!");
6736 ERRMSG(
"Add quantity zeta for diabatic advection!");
6738 ERRMSG(
"Add quantity eta for etadot avection!");
6741 (int)
scan_ctl(filename, argc, argv,
"MET_VERT_COORD", -1,
"0", NULL);
6743 ERRMSG(
"MET_VERT_COORD must be 0, 1, 2, 3, or 4!");
6747 (
"Using ADVECT_VERT_COORD = 2 requires meteo data on model levels!");
6750 (
"Using ADVECT_VERT_COORD = 3 requires A and B model level coefficients!");
6753 (int)
scan_ctl(filename, argc, argv,
"MET_GP2Z", -1,
"0", NULL);
6755 ERRMSG(
"Set MET_GP2Z to 0 or 1!");
6759 (int)
scan_ctl(filename, argc, argv,
"DIRECTION", -1,
"1", NULL);
6761 ERRMSG(
"Set DIRECTION to -1 or 1!");
6762 ctl->
t_stop =
scan_ctl(filename, argc, argv,
"T_STOP", -1,
"1e100", NULL);
6763 ctl->
dt_mod =
scan_ctl(filename, argc, argv,
"DT_MOD", -1,
"180", NULL);
6767 ctl->
dt_met =
scan_ctl(filename, argc, argv,
"DT_MET", -1,
"3600", NULL);
6769 ERRMSG(
"DT_MOD must not exceed DT_MET!");
6771 (int)
scan_ctl(filename, argc, argv,
"MET_CONVENTION", -1,
"0", NULL);
6773 (int)
scan_ctl(filename, argc, argv,
"MET_TYPE", -1,
"0", NULL);
6776 (
"Please use meteo files in netcdf format for diabatic calculations.");
6779 (
"Please use meteo files in netcdf format for etadot calculations.");
6781 (int)
scan_ctl(filename, argc, argv,
"MET_CLAMS", -1,
"0", NULL);
6783 (int)
scan_ctl(filename, argc, argv,
"MET_NC_SCALE", -1,
"1", NULL);
6785 (int)
scan_ctl(filename, argc, argv,
"MET_NC_LEVEL", -1,
"0", NULL);
6787 (int)
scan_ctl(filename, argc, argv,
"MET_NC_QUANT", -1,
"0", NULL);
6789 (int)
scan_ctl(filename, argc, argv,
"MET_ZSTD_LEVEL", -1,
"-3", NULL);
6791 (int)
scan_ctl(filename, argc, argv,
"MET_ZSTD_NWORKERS", -1,
"4", NULL);
6793 (int)
scan_ctl(filename, argc, argv,
"MET_LZ4_ACCEL", -1,
"8", NULL);
6795 (int)
scan_ctl(filename, argc, argv,
"MET_PCK_ZSTD", -1,
"0", NULL);
6797 ERRMSG(
"Set MET_PCK_ZSTD to 0 or 1!");
6800 ERRMSG(
"MET_PCK_ZSTD requires MPTRAC to be compiled with ZSTD support!");
6802 const int def_lossy_scale =
6803 (int)
scan_ctl(filename, argc, argv,
"MET_LOSSY_SCALE", -1,
"0", NULL);
6804 for (
int i = 0; i <
METVAR; i++) {
6805 char defprec_zfp[
LEN] =
"7", deftol_zfp[
LEN] =
"0.0";
6806 char defprec_sz3[
LEN] =
"6", deftol_sz3[
LEN] =
"0.0";
6808 sprintf(defprec_zfp,
"12");
6809 sprintf(defprec_sz3,
"11");
6810 }
else if (i == 1) {
6811 sprintf(defprec_zfp,
"11");
6812 sprintf(defprec_sz3,
"7");
6813 }
else if (i == 2 || i == 3) {
6814 sprintf(defprec_zfp,
"7");
6815 sprintf(defprec_sz3,
"7");
6816 }
else if (i == 4) {
6817 sprintf(defprec_zfp,
"6");
6818 sprintf(defprec_sz3,
"13");
6819 }
else if (i == 5) {
6820 sprintf(defprec_zfp,
"7");
6821 sprintf(defprec_sz3,
"20");
6822 }
else if (i == 6) {
6823 sprintf(defprec_zfp,
"10");
6824 sprintf(defprec_sz3,
"18");
6825 }
else if (i == 7) {
6826 sprintf(defprec_zfp,
"9");
6827 sprintf(defprec_sz3,
"10");
6828 }
else if (i >= 8 && i <= 11) {
6829 sprintf(defprec_zfp,
"6");
6830 sprintf(defprec_sz3,
"13");
6831 }
else if (i == 12) {
6832 sprintf(defprec_zfp,
"9");
6833 sprintf(defprec_sz3,
"6");
6836 (int)
scan_ctl(filename, argc, argv,
"MET_ZFP_PREC", i, defprec_zfp,
6839 scan_ctl(filename, argc, argv,
"MET_ZFP_TOL", i, deftol_zfp, NULL);
6841 (int)
scan_ctl(filename, argc, argv,
"MET_SZ3_PREC", i, defprec_sz3,
6844 scan_ctl(filename, argc, argv,
"MET_SZ3_TOL", i, deftol_sz3, NULL);
6846 snprintf(defscale,
LEN,
"%d", def_lossy_scale);
6848 (int)
scan_ctl(filename, argc, argv,
"MET_LOSSY_SCALE", i, defscale,
6851 ERRMSG(
"Set MET_LOSSY_SCALE to 0 or 1!");
6855 scan_ctl(filename, argc, argv,
"MET_COMP_LOGFILE", -1,
"-",
6858 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_BATCH", -1,
"-1", NULL);
6860 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ZSTD", -1,
"1", NULL);
6862 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ND0X", -1,
"48", NULL);
6864 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ND0Y", -1,
"24", NULL);
6866 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_MAXLEV", -1,
"6", NULL);
6867 for (
int i = 0; i <
METVAR; i++) {
6868 char defeps[
LEN] =
"1.0";
6869 if (i == 1 || i == 2 || i == 3)
6870 sprintf(defeps,
"0.05");
6872 scan_ctl(filename, argc, argv,
"MET_CMS_EPS", i, defeps, NULL);
6874 ctl->
met_dx = (int)
scan_ctl(filename, argc, argv,
"MET_DX", -1,
"1", NULL);
6875 ctl->
met_dy = (int)
scan_ctl(filename, argc, argv,
"MET_DY", -1,
"1", NULL);
6876 ctl->
met_dp = (int)
scan_ctl(filename, argc, argv,
"MET_DP", -1,
"1", NULL);
6878 ERRMSG(
"MET_DX, MET_DY, and MET_DP need to be greater than zero!");
6879 ctl->
met_sx = (int)
scan_ctl(filename, argc, argv,
"MET_SX", -1,
"1", NULL);
6880 ctl->
met_sy = (int)
scan_ctl(filename, argc, argv,
"MET_SY", -1,
"1", NULL);
6881 ctl->
met_sp = (int)
scan_ctl(filename, argc, argv,
"MET_SP", -1,
"1", NULL);
6883 ERRMSG(
"MET_SX, MET_SY, and MET_SP need to be greater than zero!");
6885 scan_ctl(filename, argc, argv,
"MET_DETREND", -1,
"-999", NULL);
6886 ctl->
met_np = (int)
scan_ctl(filename, argc, argv,
"MET_NP", -1,
"0", NULL);
6888 ERRMSG(
"Too many pressure levels!");
6890 (int)
scan_ctl(filename, argc, argv,
"MET_PRESS_LEVEL_DEF", -1,
"-1",
6896 for (
int ip = 0; ip < ctl->
met_np; ip++)
6898 scan_ctl(filename, argc, argv,
"MET_P", ip,
"", NULL);
6902 (int)
scan_ctl(filename, argc, argv,
"MET_NLEV", -1,
"0", NULL);
6904 ERRMSG(
"Too many model levels!");
6905 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
6907 scan_ctl(filename, argc, argv,
"MET_LEV_HYAM", ip,
"", NULL);
6908 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
6910 scan_ctl(filename, argc, argv,
"MET_LEV_HYBM", ip,
"", NULL);
6912 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SX", -1,
"-1", NULL);
6914 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SY", -1,
"-1", NULL);
6916 (int)
scan_ctl(filename, argc, argv,
"MET_RELHUM", -1,
"0", NULL);
6918 (int)
scan_ctl(filename, argc, argv,
"MET_CAPE", -1,
"1", NULL);
6920 ERRMSG(
"Set MET_CAPE to 0 or 1!");
6922 (int)
scan_ctl(filename, argc, argv,
"MET_PBL", -1,
"3", NULL);
6924 ERRMSG(
"Set MET_PBL to 0 ... 3!");
6926 scan_ctl(filename, argc, argv,
"MET_PBL_MIN", -1,
"0.1", NULL);
6928 scan_ctl(filename, argc, argv,
"MET_PBL_MAX", -1,
"5.0", NULL);
6930 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO", -1,
"3", NULL);
6932 ERRMSG(
"Set MET_TROPO to 0 ... 5!");
6934 scan_ctl(filename, argc, argv,
"MET_TROPO_PV", -1,
"3.5", NULL);
6936 scan_ctl(filename, argc, argv,
"MET_TROPO_THETA", -1,
"380", NULL);
6938 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO_SPLINE", -1,
"1", NULL);
6940 scan_ctl(filename, argc, argv,
"MET_DT_OUT", -1,
"0.1", NULL);
6942 (int)
scan_ctl(filename, argc, argv,
"MET_CACHE", -1,
"0", NULL);
6944 (int)
scan_ctl(filename, argc, argv,
"MET_MPI_SHARE", -1,
"0", NULL);
6947 ctl->
sort_dt =
scan_ctl(filename, argc, argv,
"SORT_DT", -1,
"-999", NULL);
6951 (int)
scan_ctl(filename, argc, argv,
"ISOSURF", -1,
"0", NULL);
6956 (int)
scan_ctl(filename, argc, argv,
"RNG_TYPE", -1,
"1", NULL);
6958 ERRMSG(
"Set RNG_TYPE to 0, 1, or 2!");
6961 ctl->
advect = (int)
scan_ctl(filename, argc, argv,
"ADVECT", -1,
"2", NULL);
6963 ERRMSG(
"Set ADVECT to 1, 2, or 4!");
6967 = (int)
scan_ctl(filename, argc, argv,
"DIFFUSION", -1,
"0", NULL);
6969 ERRMSG(
"Set DIFFUSION to 0 or 1!");
6971 (int)
scan_ctl(filename, argc, argv,
"TURB_PBL_SCHEME", -1,
"0", NULL);
6973 ERRMSG(
"Set TURB_PBL_SCHEME to 0 or 1!");
6975 scan_ctl(filename, argc, argv,
"TURB_DX_PBL", -1,
"50", NULL);
6977 scan_ctl(filename, argc, argv,
"TURB_DX_TROP", -1,
"50", NULL);
6979 scan_ctl(filename, argc, argv,
"TURB_DX_STRAT", -1,
"0", NULL);
6981 scan_ctl(filename, argc, argv,
"TURB_DZ_PBL", -1,
"0", NULL);
6983 scan_ctl(filename, argc, argv,
"TURB_DZ_TROP", -1,
"0", NULL);
6985 scan_ctl(filename, argc, argv,
"TURB_DZ_STRAT", -1,
"0.1", NULL);
6987 scan_ctl(filename, argc, argv,
"TURB_MESOX", -1,
"0.16", NULL);
6989 scan_ctl(filename, argc, argv,
"TURB_MESOZ", -1,
"0.16", NULL);
6991 scan_ctl(filename, argc, argv,
"TURB_PBL_TRANS", -1,
"0", NULL);
6993 ERRMSG(
"TURB_PBL_TRANS must be in the range [0, 1]!");
6997 = (int)
scan_ctl(filename, argc, argv,
"CONV_MIX_PBL", -1,
"0", NULL);
6999 =
scan_ctl(filename, argc, argv,
"CONV_PBL_TRANS", -1,
"0", NULL);
7001 ERRMSG(
"CONV_PBL_TRANS must be in the range [0, 1]!");
7003 =
scan_ctl(filename, argc, argv,
"CONV_CAPE", -1,
"-999", NULL);
7005 =
scan_ctl(filename, argc, argv,
"CONV_CIN", -1,
"-999", NULL);
7006 ctl->
conv_dt =
scan_ctl(filename, argc, argv,
"CONV_DT", -1,
"-999", NULL);
7010 scan_ctl(filename, argc, argv,
"BOUND_MASS", -1,
"-999", NULL);
7012 scan_ctl(filename, argc, argv,
"BOUND_MASS_TREND", -1,
"0", NULL);
7014 scan_ctl(filename, argc, argv,
"BOUND_VMR", -1,
"-999", NULL);
7016 scan_ctl(filename, argc, argv,
"BOUND_VMR_TREND", -1,
"0", NULL);
7018 scan_ctl(filename, argc, argv,
"BOUND_LAT0", -1,
"-999", NULL);
7020 scan_ctl(filename, argc, argv,
"BOUND_LAT1", -1,
"-999", NULL);
7022 scan_ctl(filename, argc, argv,
"BOUND_P0", -1,
"-999", NULL);
7024 scan_ctl(filename, argc, argv,
"BOUND_P1", -1,
"-999", NULL);
7026 scan_ctl(filename, argc, argv,
"BOUND_DPS", -1,
"-999", NULL);
7028 scan_ctl(filename, argc, argv,
"BOUND_DZS", -1,
"-999", NULL);
7030 scan_ctl(filename, argc, argv,
"BOUND_ZETAS", -1,
"-999", NULL);
7032 (int)
scan_ctl(filename, argc, argv,
"BOUND_PBL", -1,
"0", NULL);
7036 if (strcasecmp(ctl->
species,
"CF2Cl2") == 0) {
7040 }
else if (strcasecmp(ctl->
species,
"CFCl3") == 0) {
7044 }
else if (strcasecmp(ctl->
species,
"CH4") == 0) {
7051 }
else if (strcasecmp(ctl->
species,
"CO") == 0) {
7060 }
else if (strcasecmp(ctl->
species,
"CO2") == 0) {
7064 }
else if (strcasecmp(ctl->
species,
"H2O") == 0) {
7066 }
else if (strcasecmp(ctl->
species,
"N2O") == 0) {
7070 }
else if (strcasecmp(ctl->
species,
"NH3") == 0) {
7077 }
else if (strcasecmp(ctl->
species,
"HNO3") == 0) {
7081 }
else if (strcasecmp(ctl->
species,
"NO") == 0) {
7090 }
else if (strcasecmp(ctl->
species,
"NO2") == 0) {
7099 }
else if (strcasecmp(ctl->
species,
"O3") == 0) {
7106 }
else if (strcasecmp(ctl->
species,
"SF6") == 0) {
7110 }
else if (strcasecmp(ctl->
species,
"SO2") == 0) {
7123 sprintf(defstr,
"%g", ctl->
molmass);
7124 ctl->
molmass =
scan_ctl(filename, argc, argv,
"MOLMASS", -1, defstr, NULL);
7129 (int)
scan_ctl(filename, argc, argv,
"OH_CHEM_REACTION", -1, defstr,
7131 for (
int ip = 0; ip < 4; ip++) {
7132 sprintf(defstr,
"%g", ctl->
oh_chem[ip]);
7134 scan_ctl(filename, argc, argv,
"OH_CHEM", ip, defstr, NULL);
7137 scan_ctl(filename, argc, argv,
"OH_CHEM_BETA", -1,
"0", NULL);
7141 (int)
scan_ctl(filename, argc, argv,
"H2O2_CHEM_REACTION", -1,
"0", NULL);
7145 (int)
scan_ctl(filename, argc, argv,
"KPP_CHEM", -1,
"0", NULL);
7146 ctl->
dt_kpp =
scan_ctl(filename, argc, argv,
"DT_KPP", -1,
"1800", NULL);
7150 (int)
scan_ctl(filename, argc, argv,
"TRACER_CHEM", -1,
"0", NULL);
7154 (int)
scan_ctl(filename, argc, argv,
"RADIO_DECAY", -1,
"0", NULL);
7157 for (
int ip = 0; ip < 2; ip++) {
7160 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_H", ip, defstr, NULL);
7162 for (
int ip = 0; ip < 1; ip++) {
7165 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_H", ip, defstr, NULL);
7168 scan_ctl(filename, argc, argv,
"WET_DEPO_SO2_PH", -1,
"0", NULL);
7170 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_A", -1,
"0", NULL);
7172 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_B", -1,
"0", NULL);
7174 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_A", -1,
"0", NULL);
7176 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_B", -1,
"0", NULL);
7178 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 0,
"0.5", NULL);
7180 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 1,
"0.36", NULL);
7182 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_RET_RATIO", -1,
"1", NULL);
7184 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_RET_RATIO", -1,
"1", NULL);
7188 scan_ctl(filename, argc, argv,
"DRY_DEPO_VDEP", -1,
"0", NULL);
7190 scan_ctl(filename, argc, argv,
"DRY_DEPO_DP", -1,
"30", NULL);
7193 scan_ctl(filename, argc, argv,
"CLIM_PHOTO", -1,
7194 "../../data/clams_photolysis_rates.nc", ctl->
clim_photo);
7195 scan_ctl(filename, argc, argv,
"CLIM_HNO3_FILENAME", -1,
7197 scan_ctl(filename, argc, argv,
"CLIM_OH_FILENAME", -1,
7199 scan_ctl(filename, argc, argv,
"CLIM_H2O2_FILENAME", -1,
7201 scan_ctl(filename, argc, argv,
"CLIM_HO2_FILENAME", -1,
7203 scan_ctl(filename, argc, argv,
"CLIM_O1D_FILENAME", -1,
7205 scan_ctl(filename, argc, argv,
"CLIM_CCL4_TIMESERIES", -1,
7207 scan_ctl(filename, argc, argv,
"CLIM_CCL3F_TIMESERIES", -1,
7209 scan_ctl(filename, argc, argv,
"CLIM_CCL2F2_TIMESERIES", -1,
7211 scan_ctl(filename, argc, argv,
"CLIM_N2O_TIMESERIES", -1,
7213 scan_ctl(filename, argc, argv,
"CLIM_SF6_TIMESERIES", -1,
7218 scan_ctl(filename, argc, argv,
"MIXING_DT", -1,
"3600.", NULL);
7220 scan_ctl(filename, argc, argv,
"MIXING_TROP", -1,
"-999", NULL);
7222 scan_ctl(filename, argc, argv,
"MIXING_STRAT", -1,
"-999", NULL);
7224 scan_ctl(filename, argc, argv,
"MIXING_Z0", -1,
"-5", NULL);
7226 scan_ctl(filename, argc, argv,
"MIXING_Z1", -1,
"85", NULL);
7228 (int)
scan_ctl(filename, argc, argv,
"MIXING_NZ", -1,
"90", NULL);
7230 scan_ctl(filename, argc, argv,
"MIXING_LON0", -1,
"-180", NULL);
7232 scan_ctl(filename, argc, argv,
"MIXING_LON1", -1,
"180", NULL);
7234 (int)
scan_ctl(filename, argc, argv,
"MIXING_NX", -1,
"360", NULL);
7236 scan_ctl(filename, argc, argv,
"MIXING_LAT0", -1,
"-90", NULL);
7238 scan_ctl(filename, argc, argv,
"MIXING_LAT1", -1,
"90", NULL);
7240 (int)
scan_ctl(filename, argc, argv,
"MIXING_NY", -1,
"180", NULL);
7244 scan_ctl(filename, argc, argv,
"CHEMGRID_Z0", -1,
"-5", NULL);
7246 scan_ctl(filename, argc, argv,
"CHEMGRID_Z1", -1,
"85", NULL);
7248 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NZ", -1,
"90", NULL);
7250 scan_ctl(filename, argc, argv,
"CHEMGRID_LON0", -1,
"-180", NULL);
7252 scan_ctl(filename, argc, argv,
"CHEMGRID_LON1", -1,
"180", NULL);
7254 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NX", -1,
"360", NULL);
7256 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT0", -1,
"-90", NULL);
7258 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT1", -1,
"90", NULL);
7260 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NY", -1,
"180", NULL);
7265 scan_ctl(filename, argc, argv,
"TDEC_STRAT", -1,
"0", NULL);
7268 ctl->
psc_h2o =
scan_ctl(filename, argc, argv,
"PSC_H2O", -1,
"4e-6", NULL);
7270 scan_ctl(filename, argc, argv,
"PSC_HNO3", -1,
"9e-9", NULL);
7276 scan_ctl(filename, argc, argv,
"ATM_DT_OUT", -1,
"86400", NULL);
7278 (int)
scan_ctl(filename, argc, argv,
"ATM_FILTER", -1,
"0", NULL);
7280 (int)
scan_ctl(filename, argc, argv,
"ATM_STRIDE", -1,
"1", NULL);
7282 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE", -1,
"0", NULL);
7284 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE_OUT", -1,
"-1", NULL);
7288 (int)
scan_ctl(filename, argc, argv,
"ATM_NC_LEVEL", -1,
"0", NULL);
7289 for (
int iq = 0; iq < ctl->
nq; iq++)
7291 (
int)
scan_ctl(filename, argc, argv,
"ATM_NC_QUANT", iq,
"0", NULL);
7293 (int)
scan_ctl(filename, argc, argv,
"OBS_TYPE", -1,
"0", NULL);
7299 scan_ctl(filename, argc, argv,
"CSI_DT_OUT", -1,
"86400", NULL);
7302 scan_ctl(filename, argc, argv,
"CSI_OBSMIN", -1,
"0", NULL);
7304 scan_ctl(filename, argc, argv,
"CSI_MODMIN", -1,
"0", NULL);
7305 ctl->
csi_z0 =
scan_ctl(filename, argc, argv,
"CSI_Z0", -1,
"-5", NULL);
7306 ctl->
csi_z1 =
scan_ctl(filename, argc, argv,
"CSI_Z1", -1,
"85", NULL);
7307 ctl->
csi_nz = (int)
scan_ctl(filename, argc, argv,
"CSI_NZ", -1,
"1", NULL);
7309 scan_ctl(filename, argc, argv,
"CSI_LON0", -1,
"-180", NULL);
7310 ctl->
csi_lon1 =
scan_ctl(filename, argc, argv,
"CSI_LON1", -1,
"180", NULL);
7312 (int)
scan_ctl(filename, argc, argv,
"CSI_NX", -1,
"360", NULL);
7313 ctl->
csi_lat0 =
scan_ctl(filename, argc, argv,
"CSI_LAT0", -1,
"-90", NULL);
7314 ctl->
csi_lat1 =
scan_ctl(filename, argc, argv,
"CSI_LAT1", -1,
"90", NULL);
7316 (int)
scan_ctl(filename, argc, argv,
"CSI_NY", -1,
"180", NULL);
7319 ctl->
nens = (int)
scan_ctl(filename, argc, argv,
"NENS", -1,
"0", NULL);
7322 scan_ctl(filename, argc, argv,
"ENS_DT_OUT", -1,
"86400", NULL);
7325 scan_ctl(filename, argc, argv,
"GRID_BASENAME", -1,
"-",
7330 scan_ctl(filename, argc, argv,
"GRID_DT_OUT", -1,
"86400", NULL);
7332 (int)
scan_ctl(filename, argc, argv,
"GRID_SPARSE", -1,
"0", NULL);
7334 (int)
scan_ctl(filename, argc, argv,
"GRID_NC_LEVEL", -1,
"0", NULL);
7335 for (
int iq = 0; iq < ctl->
nq; iq++)
7337 (
int)
scan_ctl(filename, argc, argv,
"GRID_NC_QUANT", iq,
"0", NULL);
7339 (int)
scan_ctl(filename, argc, argv,
"GRID_STDDEV", -1,
"0", NULL);
7340 ctl->
grid_z0 =
scan_ctl(filename, argc, argv,
"GRID_Z0", -1,
"-5", NULL);
7341 ctl->
grid_z1 =
scan_ctl(filename, argc, argv,
"GRID_Z1", -1,
"85", NULL);
7343 (int)
scan_ctl(filename, argc, argv,
"GRID_NZ", -1,
"1", NULL);
7345 scan_ctl(filename, argc, argv,
"GRID_LON0", -1,
"-180", NULL);
7347 scan_ctl(filename, argc, argv,
"GRID_LON1", -1,
"180", NULL);
7349 (int)
scan_ctl(filename, argc, argv,
"GRID_NX", -1,
"360", NULL);
7351 scan_ctl(filename, argc, argv,
"GRID_LAT0", -1,
"-90", NULL);
7353 scan_ctl(filename, argc, argv,
"GRID_LAT1", -1,
"90", NULL);
7355 (int)
scan_ctl(filename, argc, argv,
"GRID_NY", -1,
"180", NULL);
7357 (int)
scan_ctl(filename, argc, argv,
"GRID_TYPE", -1,
"0", NULL);
7360 scan_ctl(filename, argc, argv,
"PROF_BASENAME", -1,
"-",
7363 ctl->
prof_z0 =
scan_ctl(filename, argc, argv,
"PROF_Z0", -1,
"0", NULL);
7364 ctl->
prof_z1 =
scan_ctl(filename, argc, argv,
"PROF_Z1", -1,
"60", NULL);
7366 (int)
scan_ctl(filename, argc, argv,
"PROF_NZ", -1,
"60", NULL);
7368 scan_ctl(filename, argc, argv,
"PROF_LON0", -1,
"-180", NULL);
7370 scan_ctl(filename, argc, argv,
"PROF_LON1", -1,
"180", NULL);
7372 (int)
scan_ctl(filename, argc, argv,
"PROF_NX", -1,
"360", NULL);
7374 scan_ctl(filename, argc, argv,
"PROF_LAT0", -1,
"-90", NULL);
7376 scan_ctl(filename, argc, argv,
"PROF_LAT1", -1,
"90", NULL);
7378 (int)
scan_ctl(filename, argc, argv,
"PROF_NY", -1,
"180", NULL);
7381 scan_ctl(filename, argc, argv,
"SAMPLE_BASENAME", -1,
"-",
7383 scan_ctl(filename, argc, argv,
"SAMPLE_KERNEL", -1,
"-",
7385 scan_ctl(filename, argc, argv,
"SAMPLE_OBSFILE", -1,
"-",
7388 scan_ctl(filename, argc, argv,
"SAMPLE_DX", -1,
"50", NULL);
7390 scan_ctl(filename, argc, argv,
"SAMPLE_DZ", -1,
"-999", NULL);
7393 scan_ctl(filename, argc, argv,
"STAT_BASENAME", -1,
"-",
7397 ctl->
stat_r =
scan_ctl(filename, argc, argv,
"STAT_R", -1,
"50", NULL);
7399 scan_ctl(filename, argc, argv,
"STAT_T0", -1,
"-1e100", NULL);
7400 ctl->
stat_t1 =
scan_ctl(filename, argc, argv,
"STAT_T1", -1,
"1e100", NULL);
7405 scan_ctl(filename, argc, argv,
"VTK_DT_OUT", -1,
"86400", NULL);
7407 (int)
scan_ctl(filename, argc, argv,
"VTK_STRIDE", -1,
"1", NULL);
7409 scan_ctl(filename, argc, argv,
"VTK_SCALE", -1,
"1.0", NULL);
7411 scan_ctl(filename, argc, argv,
"VTK_OFFSET", -1,
"0.0", NULL);
7413 (int)
scan_ctl(filename, argc, argv,
"VTK_SPHERE", -1,
"0", NULL);
7417 ctl->
dd = (int)
scan_ctl(filename, argc, argv,
"DD", -1,
"1", NULL);
7419 ctl->
dd = (int)
scan_ctl(filename, argc, argv,
"DD", -1,
"0", NULL);
7423 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_MERIDIONAL", -1,
7424 (ctl->
dd == 1) ?
"2" :
"1", NULL);
7426 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_ZONAL", -1,
7427 (ctl->
dd == 1) ?
"2" :
"1", NULL);
7429 (int)
scan_ctl(filename, argc, argv,
"DD_HALOS_SIZE", -1,
"1", NULL);
7431 (double)
scan_ctl(filename, argc, argv,
"DD_SORT_DT", -1,
"1800", NULL);
7437 const char *filename,
7444 LOG(1,
"Read meteo data: %s", filename);
7450 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
7478 ERRMSG(
"MET_TYPE not implemented!");
7532 LOG(2,
"Broadcast data on rank %d...", rank);
7663 module_dd(t, ctl, cache, dd, atm, met0);
7673 ERRMSG(
"Code was compiled without KPP!");
7706#pragma acc update device(ctl[:1])
7710 if (cache != NULL) {
7713#pragma acc update device(cache[:1])
7720#pragma acc update device(clim[:1])
7727 met_t *met0up = *met0;
7728#pragma acc update device(met0up[:1])
7735 met_t *met1up = *met1;
7736#pragma acc update device(met1up[:1])
7743#pragma acc update device(atm[:1])
7762#pragma acc update host(ctl[:1])
7766 if (cache != NULL) {
7769#pragma acc update host(cache[:1])
7776#pragma acc update host(clim[:1])
7783 met_t *met0up = *met0;
7784#pragma acc update host(met0up[:1])
7791 met_t *met1up = *met1;
7792#pragma acc update host(met1up[:1])
7799#pragma acc update host(atm[:1])
7807 const char *filename,
7816 LOG(1,
"Write atmospheric data: %s", filename);
7840 ERRMSG(
"Atmospheric data type not supported!");
7844 LOG(2,
"Number of particles: %d", atm->
np);
7845 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
7846 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
7847 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
7848 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
7849 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
7850 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
7851 LOG(2,
"%s range: %g ... %g %s",
7852 ctl->
met_coord_type == 0 ?
"Longitude" :
"X coordinate", mini, maxi,
7854 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
7855 LOG(2,
"%s range: %g ... %g %s",
7856 ctl->
met_coord_type == 0 ?
"Latitude" :
"Y coordinate", mini, maxi,
7858 for (
int iq = 0; iq < ctl->
nq; iq++) {
7860 sprintf(msg,
"Quantity %s range: %s ... %s %s",
7863 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
7864 LOG(2, msg, mini, maxi);
7871 const char *filename,
7879 LOG(1,
"Write meteo data: %s", filename);
7884 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
7888 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
7892 ERRMSG(
"MPTRAC was compiled without LZ4 compression!");
7896 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
7900 ERRMSG(
"MPTRAC was compiled without SZ3 compression!");
7914 ERRMSG(
"MET_TYPE not implemented!");
7920 const char *dirname,
7927 char ext[10], filename[2 *
LEN];
7931 int year, mon, day, hour, min, sec;
7934 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
7949 sprintf(ext,
"tab");
7951 sprintf(ext,
"bin");
7954 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d_%02d.%s",
7955 dirname, ctl->
atm_basename, year, mon, day, hour, min, sec, ext);
7961 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d_%02d.%s",
7962 dirname, ctl->
grid_basename, year, mon, day, hour, min, sec,
7964 write_grid(filename, ctl, met0, met1, atm, t);
7969 sprintf(filename,
"%s/%s.tab", dirname, ctl->
csi_basename);
7975 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d_%02d.tab",
7976 dirname, ctl->
ens_basename, year, mon, day, hour, min, sec);
7982 sprintf(filename,
"%s/%s.tab", dirname, ctl->
prof_basename);
7983 write_prof(filename, ctl, met0, met1, atm, t);
7994 sprintf(filename,
"%s/%s.tab", dirname, ctl->
stat_basename);
8003 sprintf(filename,
"%s/%s_%05d.vtk", dirname, ctl->
vtk_basename, ++nvtk);
8013 const double hno3) {
8016 const double h2o_help =
MAX(h2o, 0.1e-6);
8019 const double p_hno3 = hno3 * p / 1.333224;
8020 const double p_h2o = h2o_help * p / 1.333224;
8021 const double a = 0.009179 - 0.00088 * log10(p_h2o);
8022 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
8023 const double c = -11397.0 / a;
8024 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
8025 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
8043 const double p0 = pbl;
8046 if (atm->
p[ip] > p0)
8048 else if (atm->
p[ip] < p1)
8051 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
8057 const char *filename,
8063 if (!(in = fopen(filename,
"r"))) {
8064 WARN(
"Cannot open file!");
8070 while (fgets(line,
LEN, in)) {
8074 TOK(line, tok,
"%lg", atm->
time[atm->
np]);
8075 TOK(NULL, tok,
"%lg", atm->
p[atm->
np]);
8076 TOK(NULL, tok,
"%lg", atm->
lon[atm->
np]);
8077 TOK(NULL, tok,
"%lg", atm->
lat[atm->
np]);
8078 for (
int iq = 0; iq < ctl->
nq; iq++)
8079 TOK(NULL, tok,
"%lg", atm->
q[iq][atm->
np]);
8082 atm->
p[atm->
np] =
P(atm->
p[atm->
np]);
8085 if ((++atm->
np) >
NP)
8086 ERRMSG(
"Too many data points!");
8099 const char *filename,
8105 if (!(in = fopen(filename,
"r")))
8110 FREAD(&version,
int,
8114 ERRMSG(
"Wrong version of binary data!");
8132 for (
int iq = 0; iq < ctl->
nq; iq++)
8133 FREAD(atm->
q[iq],
double,
8143 ERRMSG(
"Error while reading binary data!");
8155 const char *filename,
8160 ERRMSG(
"CLaMS atmospheric files support only lat/lon grids");
8165 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
8172 if (nc_inq_varid(ncid,
"TIME_INIT", &varid) == NC_NOERR) {
8173 NC(nc_get_var_double(ncid, varid, atm->
time));
8175 WARN(
"TIME_INIT not found use time instead!");
8178 for (
int ip = 0; ip < atm->
np; ip++) {
8179 atm->
time[ip] = time_init;
8191 if (nc_inq_varid(ncid,
"PRESS_INIT", &varid) == NC_NOERR) {
8192 NC(nc_get_var_double(ncid, varid, atm->
p));
8194 WARN(
"PRESS_INIT not found use PRESS instead!");
8195 nc_inq_varid(ncid,
"PRESS", &varid);
8196 NC(nc_get_var_double(ncid, varid, atm->
p));
8201 for (
int iq = 0; iq < ctl->
nq; iq++)
8218 const char *filename,
8225 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
8238 for (
int iq = 0; iq < ctl->
nq; iq++)
8251 const char *filename,
8257 LOG(1,
"Read photolysis rates: %s", filename);
8260 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
8261 WARN(
"Photolysis rate data are missing!");
8268 if (photo->
p[0] < photo->
p[1])
8269 ERRMSG(
"Pressure data are not descending!");
8274 if (photo->
o3c[0] > photo->
o3c[1])
8275 ERRMSG(
"Total column ozone data are not ascending!");
8280 if (photo->
sza[0] > photo->
sza[1])
8281 ERRMSG(
"Solar zenith angle data are not ascending!");
8298 LOG(2,
"Number of pressure levels: %d", photo->
np);
8299 LOG(2,
"Altitude levels: %g, %g ... %g km",
8300 Z(photo->
p[0]),
Z(photo->
p[1]),
Z(photo->
p[photo->
np - 1]));
8301 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
8302 photo->
p[0], photo->
p[1], photo->
p[photo->
np - 1]);
8303 LOG(2,
"Number of solar zenith angles: %d", photo->
nsza);
8304 LOG(2,
"Solar zenith angles: %g, %g ... %g deg",
8307 LOG(2,
"Number of total column ozone values: %d", photo->
no3c);
8308 LOG(2,
"Total column ozone: %g, %g ... %g DU",
8310 LOG(2,
"N2O photolysis rate: %g, %g ... %g s**-1",
8311 photo->
n2o[0][0][0], photo->
n2o[1][0][0],
8312 photo->
n2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
8313 LOG(2,
"CCl4 photolysis rate: %g, %g ... %g s**-1",
8314 photo->
ccl4[0][0][0], photo->
ccl4[1][0][0],
8316 LOG(2,
"CFC-11 photolysis rate: %g, %g ... %g s**-1",
8317 photo->
ccl3f[0][0][0], photo->
ccl3f[1][0][0],
8319 LOG(2,
"CFC-12 photolysis rate: %g, %g ... %g s**-1",
8322 LOG(2,
"O2 photolysis rate: %g, %g ... %g s**-1",
8323 photo->
o2[0][0][0], photo->
o2[1][0][0],
8324 photo->
o2[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
8325 LOG(2,
"O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
8326 photo->
o3_1[0][0][0], photo->
o3_1[1][0][0],
8328 LOG(2,
"O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
8329 photo->
o3_2[0][0][0], photo->
o3_2[1][0][0],
8331 LOG(2,
"H2O2 photolysis rate: %g, %g ... %g s**-1",
8332 photo->
h2o2[0][0][0], photo->
h2o2[1][0][0],
8334 LOG(2,
"H2O photolysis rate: %g, %g ... %g s**-1",
8335 photo->
h2o[0][0][0], photo->
h2o[1][0][0],
8336 photo->
h2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
8343 const char *varname,
8357 for (
int ip = 0; ip < photo->
np; ip++)
8358 for (
int is = 0; is < photo->
nsza; is++)
8359 for (
int io = 0; io < photo->
no3c; io++)
8370 const char *filename,
8374 LOG(1,
"Read climatological time series: %s", filename);
8378 if (!(in = fopen(filename,
"r"))) {
8379 WARN(
"Cannot open file!");
8386 while (fgets(line,
LEN, in))
8387 if (sscanf(line,
"%lg %lg", &ts->
time[nh], &ts->
vmr[nh]) == 2) {
8390 ts->
time[nh] = (ts->
time[nh] - 2000.0) * 365.25 * 86400.;
8393 if (nh > 0 && ts->
time[nh] <= ts->
time[nh - 1])
8394 ERRMSG(
"Time series must be ascending!");
8398 ERRMSG(
"Too many data points!");
8407 ERRMSG(
"Not enough data points!");
8410 LOG(2,
"Number of time steps: %d", ts->
ntime);
8411 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s", ts->
time[0], ts->
time[1],
8413 LOG(2,
"Volume mixing ratio range: %g ... %g ppv",
8414 gsl_stats_min(ts->
vmr, 1, (
size_t) nh), gsl_stats_max(ts->
vmr, 1,
8424 const char *filename,
8425 const char *varname,
8428 int ncid, varid, it, iy, iz, iz2, nt;
8430 double *help, varmin = 1e99, varmax = -1e99;
8433 LOG(1,
"Read %s data: %s", varname, filename);
8436 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
8437 WARN(
"%s climatology data are missing!", varname);
8444 if (zm->
p[0] < zm->
p[1])
8445 ERRMSG(
"Pressure data are not descending!");
8450 if (zm->
lat[0] > zm->
lat[1])
8451 ERRMSG(
"Latitude data are not ascending!");
8455 zm->
time[0] = 1209600.00;
8456 zm->
time[1] = 3888000.00;
8457 zm->
time[2] = 6393600.00;
8458 zm->
time[3] = 9072000.00;
8459 zm->
time[4] = 11664000.00;
8460 zm->
time[5] = 14342400.00;
8461 zm->
time[6] = 16934400.00;
8462 zm->
time[7] = 19612800.00;
8463 zm->
time[8] = 22291200.00;
8464 zm->
time[9] = 24883200.00;
8465 zm->
time[10] = 27561600.00;
8466 zm->
time[11] = 30153600.00;
8475 for (it = 0; it < zm->
ntime; it++)
8476 for (iz = 0; iz < zm->
np; iz++)
8477 for (iy = 0; iy < zm->
nlat; iy++)
8482 for (it = 0; it < zm->
ntime; it++)
8483 for (iy = 0; iy < zm->
nlat; iy++)
8484 for (iz = 0; iz < zm->
np; iz++) {
8485 if (zm->
vmr[it][iz][iy] < 0) {
8486 for (iz2 = 0; iz2 < zm->
np; iz2++)
8487 if (zm->
vmr[it][iz2][iy] >= 0) {
8488 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
8491 for (iz2 = zm->
np - 1; iz2 >= 0; iz2--)
8492 if (zm->
vmr[it][iz2][iy] >= 0) {
8493 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
8497 varmin =
MIN(varmin, zm->
vmr[it][iz][iy]);
8498 varmax =
MAX(varmax, zm->
vmr[it][iz][iy]);
8505 LOG(2,
"Number of time steps: %d", zm->
ntime);
8506 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
8508 LOG(2,
"Number of pressure levels: %d", zm->
np);
8509 LOG(2,
"Altitude levels: %g, %g ... %g km",
8510 Z(zm->
p[0]),
Z(zm->
p[1]),
Z(zm->
p[zm->
np - 1]));
8511 LOG(2,
"Pressure levels: %g, %g ... %g hPa", zm->
p[0],
8512 zm->
p[1], zm->
p[zm->
np - 1]);
8513 LOG(2,
"Number of latitudes: %d", zm->
nlat);
8514 LOG(2,
"Latitudes: %g, %g ... %g deg",
8516 LOG(2,
"%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
8523 const char *filename,
8529 LOG(1,
"Read kernel function: %s", filename);
8533 if (!(in = fopen(filename,
"r")))
8534 ERRMSG(
"Cannot open file!");
8539 while (fgets(line,
LEN, in))
8540 if (sscanf(line,
"%lg %lg", &kz[n], &kw[n]) == 2) {
8541 if (n > 0 && kz[n] < kz[n - 1])
8542 ERRMSG(
"Height levels must be ascending!");
8544 ERRMSG(
"Too many height levels!");
8553 ERRMSG(
"Not enough height levels!");
8556 const double kmax = gsl_stats_max(kw, 1, (
size_t) n);
8557 for (
int iz = 0; iz < n; iz++)
8564 const char *filename,
8572 int year, mon, day, hour, min, sec;
8578 if (!(in = fopen(filename,
"r"))) {
8579 WARN(
"Cannot open file!");
8585 FREAD(&met_type,
int,
8589 ERRMSG(
"Wrong MET_TYPE of binary data!");
8593 FREAD(&version,
int,
8597 ERRMSG(
"Wrong version of binary data!");
8603 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
8604 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
8605 met->
time, year, mon, day, hour, min);
8606 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
8607 || day < 1 || day > 31 || hour < 0 || hour > 23)
8608 ERRMSG(
"Error while reading time!");
8616 LOG(2,
"Number of %s: %d",
8617 (met->
coord_type == 0) ?
"longitudes" :
"x coordinates", met->
nx);
8618 if (met->
nx < 2 || met->
nx >
EX)
8620 ?
"Number of longitudes out of range!"
8621 :
"Number of x coordinates out of range!");
8626 LOG(2,
"Number of %s: %d",
8627 (met->
coord_type == 0) ?
"latitudes" :
"y coordinates", met->
ny);
8628 if (met->
ny < 2 || met->
ny >
EY)
8630 ?
"Number of latitudes out of range!"
8631 :
"Number of y coordinates out of range!");
8636 LOG(2,
"Number of levels: %d", met->
np);
8637 if (met->
np < 2 || met->
np >
EP)
8638 ERRMSG(
"Number of levels out of range!");
8644 LOG(2,
"%s: %g, %g ... %g %s",
8645 met->
coord_type == 0 ?
"Longitudes" :
"X coordinates",
8652 LOG(2,
"%s: %g, %g ... %g %s",
8653 met->
coord_type == 0 ?
"Latitudes" :
"Y coordinates",
8660 LOG(2,
"Altitude levels: %g, %g ... %g km",
8661 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
8662 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
8663 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
8712 ERRMSG(
"Error while reading binary data!");
8727 const char *varname) {
8736 LOG(2,
"Read 2-D variable: %s (uncompressed)", varname);
8738 (
size_t) (met->
nx * met->
ny),
8742 for (
int ix = 0; ix < met->
nx; ix++)
8743 for (
int iy = 0; iy < met->
ny; iy++)
8744 var[ix][iy] = help[
ARRAY_2D(ix, iy, met->
ny)];
8757 const char *varname,
8758 const float bound_min,
8759 const float bound_max) {
8769 LOG(2,
"Read 3-D variable: %s (uncompressed)", varname);
8771 (
size_t) (met->
nx * met->
ny * met->
np),
8783 FREAD(&precision,
int,
8788 FREAD(&tolerance,
double,
8794 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
8803 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
8812 ERRMSG(
"MPTRAC was compiled without LZ4 compression!");
8821 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
8829 FREAD(&precision,
int,
8834 FREAD(&tolerance,
double,
8840 ERRMSG(
"MPTRAC was compiled without sz3 compression!");
8845#pragma omp parallel for default(shared) collapse(2)
8846 for (
int ix = 0; ix < met->
nx; ix++)
8847 for (
int iy = 0; iy < met->
ny; iy++)
8848 for (
int ip = 0; ip < met->
np; ip++) {
8849 var[ix][iy][ip] = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
8850 if (var[ix][iy][ip] < bound_min)
8851 var[ix][iy][ip] = bound_min;
8852 else if (var[ix][iy][ip] > bound_max)
8853 var[ix][iy][ip] = bound_max;
8872 ERRMSG(
"Only lat/lon grid supported");
8876 LOG(2,
"Calculate CAPE...");
8879 const double pfac = 1.01439, dz0 =
RI /
MA /
G0 * log(pfac);
8882#pragma omp parallel for default(shared) collapse(2)
8883 for (
int ix = 0; ix < met->
nx; ix++)
8884 for (
int iy = 0; iy < met->
ny; iy++) {
8888 double h2o = 0, t, theta = 0;
8889 double pbot =
MIN(met->
ps[ix][iy], met->
p[0]);
8890 double ptop = pbot - 50.;
8891 for (
int ip = 0; ip < met->
np; ip++) {
8892 if (met->
p[ip] <= pbot) {
8893 theta +=
THETA(met->
p[ip], met->
t[ix][iy][ip]);
8894 h2o += met->
h2o[ix][iy][ip];
8897 if (met->
p[ip] < ptop && n > 0)
8904 met->
plcl[ix][iy] = NAN;
8905 met->
plfc[ix][iy] = NAN;
8906 met->
pel[ix][iy] = NAN;
8907 met->
cape[ix][iy] = NAN;
8908 met->
cin[ix][iy] = NAN;
8914 pbot = met->
ps[ix][iy];
8916 met->
plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
8917 t = theta / pow(1000. / met->
plcl[ix][iy], 0.286);
8918 if (
RH(met->
plcl[ix][iy], t, h2o) > 100.)
8919 ptop = met->
plcl[ix][iy];
8921 pbot = met->
plcl[ix][iy];
8922 }
while (pbot - ptop > 0.1);
8926 double dcape, dz, h2o_env, t_env;
8927 double p = met->
ps[ix][iy];
8928 met->
cape[ix][iy] = met->
cin[ix][iy] = 0;
8930 dz = dz0 *
TVIRT(t, h2o);
8932 t = theta / pow(1000. / p, 0.286);
8936 &h2o_env, ci, cw, 0);
8937 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
8938 TVIRT(t_env, h2o_env) * dz;
8940 met->
cin[ix][iy] += fabsf((
float) dcape);
8941 }
while (p > met->
plcl[ix][iy]);
8946 p = met->
plcl[ix][iy];
8947 t = theta / pow(1000. / p, 0.286);
8952 dz = dz0 *
TVIRT(t, h2o);
8955 double psat =
PSAT(t);
8956 h2o = psat / (p - (1. -
EPS) * psat);
8960 &h2o_env, ci, cw, 0);
8961 double dcape_old = dcape;
8962 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
8963 TVIRT(t_env, h2o_env) * dz;
8965 met->
cape[ix][iy] += (float) dcape;
8966 if (!isfinite(met->
plfc[ix][iy]))
8967 met->
plfc[ix][iy] = (
float) p;
8968 }
else if (dcape_old > 0)
8969 met->
pel[ix][iy] = (float) p;
8970 if (dcape < 0 && !isfinite(met->
plfc[ix][iy]))
8971 met->
cin[ix][iy] += fabsf((
float) dcape);
8975 if (!isfinite(met->
plfc[ix][iy]))
8976 met->
cin[ix][iy] = NAN;
8987 LOG(2,
"Calculate cloud data...");
8990 const double ccmin = 0.01, cwmin = 1e-6;
8993#pragma omp parallel for default(shared) collapse(2)
8994 for (
int ix = 0; ix < met->
nx; ix++)
8995 for (
int iy = 0; iy < met->
ny; iy++) {
8998 met->
pct[ix][iy] = NAN;
8999 met->
pcb[ix][iy] = NAN;
9000 met->
cl[ix][iy] = 0;
9003 for (
int ip = 0; ip < met->
np - 1; ip++) {
9006 if (met->
p[ip] > met->
ps[ix][iy] || met->
p[ip] <
P(20.))
9010 if (met->
cc[ix][iy][ip] > ccmin
9011 && (met->
lwc[ix][iy][ip] > cwmin
9012 || met->
rwc[ix][iy][ip] > cwmin
9013 || met->
iwc[ix][iy][ip] > cwmin
9014 || met->
swc[ix][iy][ip] > cwmin)) {
9018 = (float) (0.5 * (met->
p[ip] + (
float) met->
p[ip + 1]));
9021 if (!isfinite(met->
pcb[ix][iy]))
9023 = (
float) (0.5 * (met->
p[ip] + met->
p[
MAX(ip - 1, 0)]));
9027 met->
cl[ix][iy] += (float)
9028 (0.5 * (met->
lwc[ix][iy][ip] + met->
lwc[ix][iy][ip + 1]
9029 + met->
rwc[ix][iy][ip] + met->
rwc[ix][iy][ip + 1]
9030 + met->
iwc[ix][iy][ip] + met->
iwc[ix][iy][ip + 1]
9031 + met->
swc[ix][iy][ip] + met->
swc[ix][iy][ip + 1])
9032 * 100. * (met->
p[ip] - met->
p[ip + 1]) /
G0);
9050 ERRMSG(
"Only lat/lon grid supported");
9054 LOG(2,
"Detrend meteo data...");
9061 const double tssq = 2. *
SQR(sigma);
9064 int sy = (int) (3. *
DY2DEG(sigma) / fabs(met->
lat[1] - met->
lat[0]));
9068#pragma omp parallel for default(shared) collapse(2)
9069 for (
int ix = 0; ix < met->
nx; ix++) {
9070 for (
int iy = 0; iy < met->
ny; iy++) {
9078 (int) (3. *
DX2DEG(sigma, met->
lat[iy]) /
9079 fabs(met->
lon[1] - met->
lon[0]));
9084 for (
int ip = 0; ip < met->
np; ip++) {
9085 help->
t[ix][iy][ip] = 0;
9086 help->
u[ix][iy][ip] = 0;
9087 help->
v[ix][iy][ip] = 0;
9088 help->
w[ix][iy][ip] = 0;
9092 for (
int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
9096 else if (ix3 >= met->
nx)
9098 for (
int iy2 =
MAX(iy - sy, 0);
9099 iy2 <=
MIN(iy + sy, met->
ny - 1); iy2++) {
9106 const float w = (float) exp(-
DIST2(x0, x1) / tssq);
9110 for (
int ip = 0; ip < met->
np; ip++) {
9111 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip];
9112 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip];
9113 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip];
9114 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip];
9120 for (
int ip = 0; ip < met->
np; ip++) {
9121 help->
t[ix][iy][ip] /= wsum;
9122 help->
u[ix][iy][ip] /= wsum;
9123 help->
v[ix][iy][ip] /= wsum;
9124 help->
w[ix][iy][ip] /= wsum;
9130#pragma omp parallel for default(shared) collapse(3)
9131 for (
int ix = 0; ix < met->
nx; ix++)
9132 for (
int iy = 0; iy < met->
ny; iy++)
9133 for (
int ip = 0; ip < met->
np; ip++) {
9134 met->
t[ix][iy][ip] -= help->
t[ix][iy][ip];
9135 met->
u[ix][iy][ip] -= help->
u[ix][iy][ip];
9136 met->
v[ix][iy][ip] -= help->
v[ix][iy][ip];
9137 met->
w[ix][iy][ip] -= help->
w[ix][iy][ip];
9151 LOG(2,
"Extrapolate meteo data...");
9154#pragma omp parallel for default(shared) collapse(2)
9155 for (
int ix = 0; ix < met->
nx; ix++)
9156 for (
int iy = 0; iy < met->
ny; iy++) {
9160 for (ip0 = met->
np - 1; ip0 >= 0; ip0--)
9161 if (!isfinite(met->
t[ix][iy][ip0])
9162 || !isfinite(met->
u[ix][iy][ip0])
9163 || !isfinite(met->
v[ix][iy][ip0])
9164 || !isfinite(met->
w[ix][iy][ip0]))
9168 for (
int ip = ip0; ip >= 0; ip--) {
9169 met->
t[ix][iy][ip] = met->
t[ix][iy][ip + 1];
9170 met->
u[ix][iy][ip] = met->
u[ix][iy][ip + 1];
9171 met->
v[ix][iy][ip] = met->
v[ix][iy][ip + 1];
9172 met->
w[ix][iy][ip] = met->
w[ix][iy][ip + 1];
9173 met->
h2o[ix][iy][ip] = met->
h2o[ix][iy][ip + 1];
9174 met->
o3[ix][iy][ip] = met->
o3[ix][iy][ip + 1];
9175 met->
lwc[ix][iy][ip] = met->
lwc[ix][iy][ip + 1];
9176 met->
rwc[ix][iy][ip] = met->
rwc[ix][iy][ip + 1];
9177 met->
iwc[ix][iy][ip] = met->
iwc[ix][iy][ip + 1];
9178 met->
swc[ix][iy][ip] = met->
swc[ix][iy][ip + 1];
9179 met->
cc[ix][iy][ip] = met->
cc[ix][iy][ip + 1];
9198 LOG(2,
"Calculate geopotential heights...");
9205#pragma omp parallel for default(shared)
9206 for (
int ip = 0; ip < met->
np; ip++)
9207 logp[ip] = log(met->
p[ip]);
9210#pragma omp parallel for default(shared) collapse(2)
9211 for (
int ix = 0; ix < met->
nx; ix++)
9212 for (
int iy = 0; iy < met->
ny; iy++) {
9215 const double zs = met->
zs[ix][iy];
9216 const double lnps = log(met->
ps[ix][iy]);
9220 const double ts =
LIN(met->
p[ip0], met->
t[ix][iy][ip0], met->
p[ip0 + 1],
9221 met->
t[ix][iy][ip0 + 1], met->
ps[ix][iy]);
9223 LIN(met->
p[ip0], met->
h2o[ix][iy][ip0], met->
p[ip0 + 1],
9224 met->
h2o[ix][iy][ip0 + 1], met->
ps[ix][iy]);
9227 met->
z[ix][iy][ip0 + 1]
9229 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
9230 met->
t[ix][iy][ip0 + 1], met->
h2o[ix][iy][ip0 + 1]));
9231 for (
int ip = ip0 + 2; ip < met->
np; ip++)
9233 = (
float) (met->
z[ix][iy][ip - 1] +
9234 ZDIFF(logp[ip - 1], met->
t[ix][iy][ip - 1],
9235 met->
h2o[ix][iy][ip - 1], logp[ip],
9236 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
9241 ZDIFF(lnps, ts, h2os, logp[ip0],
9242 met->
t[ix][iy][ip0], met->
h2o[ix][iy][ip0]));
9243 for (
int ip = ip0 - 1; ip >= 0; ip--)
9245 = (
float) (met->
z[ix][iy][ip + 1] +
9246 ZDIFF(logp[ip + 1], met->
t[ix][iy][ip + 1],
9247 met->
h2o[ix][iy][ip + 1], logp[ip],
9248 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
9252 if (dx == 0 || dy == 0)
9256 if (dx < 0 || dy < 0) {
9257 if (fabs(met->
lon[1] - met->
lon[0]) < 0.5) {
9267 float ws[dx + 1][dy + 1];
9268#pragma omp parallel for default(shared) collapse(2)
9269 for (
int ix = 0; ix <= dx; ix++)
9270 for (
int iy = 0; iy < dy; iy++)
9271 ws[ix][iy] = (1.0f - (
float) ix / (float) dx)
9272 * (1.0f - (float) iy / (
float) dy);
9275#pragma omp parallel for default(shared) collapse(3)
9276 for (
int ix = 0; ix < met->
nx; ix++)
9277 for (
int iy = 0; iy < met->
ny; iy++)
9278 for (
int ip = 0; ip < met->
np; ip++)
9279 help[
ARRAY_3D(ip, ix, met->
nx, iy, met->
ny)] = met->
z[ix][iy][ip];
9282#pragma omp parallel for default(shared) collapse(3)
9283 for (
int ip = 0; ip < met->
np; ip++)
9284 for (
int ix = 0; ix < met->
nx; ix++)
9285 for (
int iy = 0; iy < met->
ny; iy++) {
9286 float res = 0, wsum = 0;
9287 int iy0 =
MAX(iy - dy + 1, 0);
9288 int iy1 =
MIN(iy + dy - 1, met->
ny - 1);
9289 for (
int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
9293 else if (ix3 >= met->
nx)
9295 for (
int iy2 = iy0; iy2 <= iy1; ++iy2)
9296 if (isfinite(help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)])) {
9297 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
9298 res += w * help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)];
9303 met->
z[ix][iy][ip] = res / wsum;
9305 met->
z[ix][iy][ip] = NAN;
9315 const char *filename,
9321 char levname[
LEN], tstr[10];
9323 double rtime = 0, r, r2;
9325 int varid, ndims, dimids[NC_MAX_DIMS], year2, mon2, day2, hour2, min2, sec2,
9326 year, mon, day, hour, min, sec;
9332 LOG(2,
"Read meteo grid information...");
9341 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
9342 if (nc_inq_varid(ncid,
"time", &varid) == NC_NOERR) {
9343 NC(nc_get_var_double(ncid, varid, &rtime));
9344 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
9345 WARN(
"Time information in meteo file does not match filename!");
9347 WARN(
"Time information in meteo file is missing!");
9358 sprintf(tstr,
"19%.2s", &filename[strlen(filename) - 11]);
9360 sprintf(tstr,
"20%.2s", &filename[strlen(filename) - 11]);
9362 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 9]);
9364 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 7]);
9366 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 5]);
9372 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
9373 || day < 1 || day > 31 || hour < 0 || hour > 23)
9374 ERRMSG(
"Cannot read time from filename!");
9375 jsec2time(met->
time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
9376 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
9377 met->
time, year2, mon2, day2, hour2, min2);
9380 if (nc_inq_varid(ncid,
"u", &varid) != NC_NOERR)
9381 if (nc_inq_varid(ncid,
"U", &varid) != NC_NOERR)
9383 (
"Variable 'u' or 'U' not found, cannot determine vertical dimension!");
9385 NC(nc_inq_varndims(ncid, varid, &ndims));
9386 NC(nc_inq_vardimid(ncid, varid, dimids));
9390 (ncid, dimids[ctl->
met_convention == 0 ? 1 : 3], levname, &dimlen));
9391 }
else if (ndims == 3) {
9393 (ncid, dimids[ctl->
met_convention == 0 ? 0 : 2], levname, &dimlen));
9395 ERRMSG(
"Cannot determine vertical dimension!")
9396 met->
np = (int) dimlen;
9398 LOG(2,
"Number of levels: %d", met->
np);
9399 if (met->
np < 2 || met->
np >
EP)
9400 ERRMSG(
"Number of levels out of range!");
9408 LOG(2,
"Number of longitudes: %d", met->
nx);
9411 LOG(2,
"Number of latitudes: %d", met->
ny);
9414 LOG(2,
"Longitudes: %g, %g ... %g deg",
9417 LOG(2,
"Latitudes: %g, %g ... %g deg",
9423 LOG(2,
"Number of x coordinates: %d", met->
nx);
9426 LOG(2,
"Number of y coordinates: %d", met->
ny);
9429 LOG(2,
"X coordinates: %g, %g ... %g m",
9432 LOG(2,
"Y coordinates: %g, %g ... %g m",
9439 ERRMSG(
"Domain decomposition is only supported for lat/lon grids!");
9449 for (
int ip = 0; ip < met->
np; ip++)
9451 LOG(2,
"Altitude levels: %g, %g ... %g km",
9452 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
9453 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
9454 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
9458 if (strcasecmp(levname,
"hybrid") == 0)
9470 ERRMSG(
"You need to specify MET_NLEV, MET_LEV_HYAM, and MET_LEV_HYBM!");
9471 for (
int ip = 0; ip < ctl->
met_nlev; ip++) {
9479 met->
eta[k] = met->
hyam[k] / 100000.0 + met->
hybm[k];
9481 ERRMSG(
"Eta levels must be ascending!");
9485 for (
int ix = 2; ix < met->
nx; ix++)
9487 (fabs(met->
lon[ix] - met->
lon[ix - 1]) -
9488 fabs(met->
lon[1] - met->
lon[0])) > 0.001)
9489 ERRMSG(
"No regular grid spacing in longitudes!");
9490 for (
int iy = 2; iy < met->
ny; iy++)
9492 (fabs(met->
lat[iy] - met->
lat[iy - 1]) -
9493 fabs(met->
lat[1] - met->
lat[0])) > 0.001) {
9494 WARN(
"No regular grid spacing in latitudes!");
9509 LOG(2,
"Read surface data...");
9513 (ncid,
"lnsp",
"LNSP", NULL, NULL, NULL, NULL, ctl, met, dd, met->
ps,
9515 for (
int ix = 0; ix < met->
nx; ix++)
9516 for (
int iy = 0; iy < met->
ny; iy++)
9517 met->
ps[ix][iy] = (
float) (exp(met->
ps[ix][iy]) / 100.);
9520 (ncid,
"ps",
"PS",
"sp",
"SP", NULL, NULL, ctl, met, dd, met->
ps,
9522 WARN(
"Cannot not read surface pressure data (use lowest level)!");
9523 for (
int ix = 0; ix < met->
nx; ix++)
9524 for (
int iy = 0; iy < met->
ny; iy++)
9526 = (ctl->
met_np > 0 ? (
float) ctl->
met_p[0] : (
float) met->
p[0]);
9534 (ncid,
"z",
"Z", NULL, NULL, NULL, NULL, ctl, met, dd, met->
zs,
9535 (
float) (1. / (1000. *
G0)), 1))
9537 (ncid,
"zm",
"ZM", NULL, NULL, NULL, NULL, ctl, met, dd, met->
zs,
9538 (ctl->
met_gp2z ? (
float) (1e-3 /
G0) : (
float) (1. / 1000.)), 1))
9539 WARN(
"Cannot read surface geopotential height!");
9550 memcpy(help, met->
pl,
sizeof(met->
pl));
9552 (ncid,
"gph",
"GPH", NULL, NULL, ctl, met, dd, met->
pl,
9553 (
float) (1e-3 /
G0)))
9554 ERRMSG(
"Cannot read geopotential height!");
9555 for (
int ix = 0; ix < met->
nx; ix++)
9556 for (
int iy = 0; iy < met->
ny; iy++)
9557 met->
zs[ix][iy] = met->
pl[ix][iy][0];
9558 memcpy(met->
pl, help,
sizeof(met->
pl));
9564 (ncid,
"t2m",
"T2M",
"2t",
"2T",
"t2",
"T2", ctl, met, dd, met->
ts, 1.0,
9566 WARN(
"Cannot read surface temperature!");
9570 (ncid,
"u10m",
"U10M",
"10u",
"10U",
"u10",
"U10", ctl, met, dd,
9572 WARN(
"Cannot read surface zonal wind!");
9576 (ncid,
"v10m",
"V10M",
"10v",
"10V",
"v10",
"V10", ctl, met, dd,
9578 WARN(
"Cannot read surface meridional wind!");
9582 (ncid,
"iews",
"IEWS", NULL, NULL, NULL, NULL, ctl, met, dd, met->
ess,
9584 WARN(
"Cannot read eastward turbulent surface stress!");
9588 (ncid,
"inss",
"INSS", NULL, NULL, NULL, NULL, ctl, met, dd, met->
nss,
9590 WARN(
"Cannot read nothward turbulent surface stress!");
9594 (ncid,
"ishf",
"ISHF", NULL, NULL, NULL, NULL, ctl, met, dd, met->
shf,
9596 WARN(
"Cannot read surface sensible heat flux!");
9600 (ncid,
"lsm",
"LSM", NULL, NULL, NULL, NULL, ctl, met, dd, met->
lsm,
9602 WARN(
"Cannot read land-sea mask!");
9606 (ncid,
"sstk",
"SSTK",
"sst",
"SST", NULL, NULL, ctl, met, dd, met->
sst,
9608 WARN(
"Cannot read sea surface temperature!");
9613 (ncid,
"blp",
"BLP", NULL, NULL, NULL, NULL, ctl, met, dd, met->
pbl,
9615 WARN(
"Cannot read planetary boundary layer pressure!");
9618 (ncid,
"blh",
"BLH", NULL, NULL, NULL, NULL, ctl, met, dd, met->
pbl,
9620 WARN(
"Cannot read planetary boundary layer height!");
9625 (ncid,
"cape",
"CAPE", NULL, NULL, NULL, NULL, ctl, met, dd,
9627 WARN(
"Cannot read CAPE!");
9632 (ncid,
"cin",
"CIN", NULL, NULL, NULL, NULL, ctl, met, dd, met->
cin,
9634 WARN(
"Cannot read convective inhibition!");
9647 LOG(2,
"Read level data...");
9651 (ncid,
"t",
"T",
"temp",
"TEMP", ctl, met, dd, met->
t, 1.0))
9652 ERRMSG(
"Cannot read temperature!");
9655 if (!
read_met_nc_3d(ncid,
"u",
"U", NULL, NULL, ctl, met, dd, met->
u, 1.0))
9656 ERRMSG(
"Cannot read zonal wind!");
9657 if (!
read_met_nc_3d(ncid,
"v",
"V", NULL, NULL, ctl, met, dd, met->
v, 1.0))
9658 ERRMSG(
"Cannot read meridional wind!");
9660 (ncid,
"w",
"W",
"omega",
"OMEGA", ctl, met, dd, met->
w, 0.01f))
9661 WARN(
"Cannot read vertical velocity!");
9666 (ncid,
"q",
"Q",
"sh",
"SH", ctl, met, dd, met->
h2o,
9668 WARN(
"Cannot read specific humidity!");
9671 (ncid,
"rh",
"RH", NULL, NULL, ctl, met, dd, met->
h2o, 0.01f))
9672 WARN(
"Cannot read relative humidity!");
9673#pragma omp parallel for default(shared) collapse(2)
9674 for (
int ix = 0; ix < met->
nx; ix++)
9675 for (
int iy = 0; iy < met->
ny; iy++)
9676 for (
int ip = 0; ip < met->
np; ip++) {
9677 double pw = met->
h2o[ix][iy][ip] *
PSAT(met->
t[ix][iy][ip]);
9678 met->
h2o[ix][iy][ip] =
9679 (float) (pw / (met->
p[ip] - (1.0 -
EPS) * pw));
9685 (ncid,
"o3",
"O3", NULL, NULL, ctl, met, dd, met->
o3,
9686 (
float) (
MA /
MO3)))
9687 WARN(
"Cannot read ozone data!");
9691 (ncid,
"clwc",
"CLWC", NULL, NULL, ctl, met, dd, met->
lwc, 1.0))
9692 WARN(
"Cannot read cloud liquid water content!");
9694 (ncid,
"crwc",
"CRWC", NULL, NULL, ctl, met, dd, met->
rwc, 1.0))
9695 WARN(
"Cannot read cloud rain water content!");
9697 (ncid,
"ciwc",
"CIWC", NULL, NULL, ctl, met, dd, met->
iwc, 1.0))
9698 WARN(
"Cannot read cloud ice water content!");
9700 (ncid,
"cswc",
"CSWC", NULL, NULL, ctl, met, dd, met->
swc, 1.0))
9701 WARN(
"Cannot read cloud snow water content!");
9703 (ncid,
"cc",
"CC", NULL, NULL, ctl, met, dd, met->
cc, 1.0))
9704 WARN(
"Cannot read cloud cover!");
9709 (ncid,
"ZETA",
"zeta", NULL, NULL, ctl, met, dd, met->
zetal, 1.0))
9710 WARN(
"Cannot read ZETA!");
9712 (ncid,
"ZETA_DOT_TOT",
"ZETA_DOT_clr",
"zeta_dot_clr",
9713 NULL, ctl, met, dd, met->
zeta_dotl, 0.00001157407f))
9714 WARN(
"Cannot read ZETA_DOT!");
9719#pragma omp parallel for default(shared)
9720 for (
int ix = 0; ix < met->
nx; ix++)
9721 for (
int iy = 0; iy < met->
ny; iy++)
9722 for (
int ip = 0; ip < met->
np; ip++)
9723 met->
zetal[ix][iy][ip] =
9724 (
float) (met->
hyam[ip] / 100000.0 + met->
hybm[ip]);
9726 (ncid,
"etadot",
"ETADOT", NULL, NULL, ctl, met, dd, met->
zeta_dotl,
9728 WARN(
"Cannot read eta vertical velocity!");
9733#pragma omp parallel for default(shared)
9734 for (
int ix = 0; ix < met->
nx; ix++)
9735 for (
int iy = 0; iy < met->
ny; iy++)
9736 for (
int ip = 0; ip < met->
np; ip++) {
9737 met->
ul[ix][iy][ip] = met->
u[ix][iy][ip];
9738 met->
vl[ix][iy][ip] = met->
v[ix][iy][ip];
9739 met->
wl[ix][iy][ip] = met->
w[ix][iy][ip];
9752 (ncid,
"pl",
"PL",
"pressure",
"PRESSURE", ctl, met, dd, met->
pl,
9755 (ncid,
"press",
"PRESS", NULL, NULL, ctl, met, dd, met->
pl, 1.0))
9756 ERRMSG(
"Cannot read pressure on model levels!");
9764 ERRMSG(
"Mismatch in number of model levels!");
9767 for (
int ix = 0; ix < met->
nx; ix++)
9768 for (
int iy = 0; iy < met->
ny; iy++)
9769 for (
int ip = 0; ip < met->
np; ip++)
9770 met->
pl[ix][iy][ip] =
9771 (
float) (met->
hyam[ip] / 100. +
9772 met->
hybm[ip] * met->
ps[ix][iy]);
9780 ERRMSG(
"Mismatch in number of model levels!");
9783#pragma omp parallel for default(shared) collapse(2)
9784 for (
int ix = 0; ix < met->
nx; ix++)
9785 for (
int iy = 0; iy < met->
ny; iy++)
9786 for (
int ip = 0; ip < met->
np; ip++) {
9788 met->
hyam[ip] / 100. + met->
hybm[ip] * met->
ps[ix][iy];
9790 met->
hyam[ip + 1] / 100. + met->
hybm[ip + 1] * met->
ps[ix][iy];
9791 met->
pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
9796 for (
int ix = 0; ix < met->
nx; ix++)
9797 for (
int iy = 0; iy < met->
ny; iy++)
9798 for (
int ip = 1; ip < met->
np; ip++)
9799 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
9800 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
9801 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
9802 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip]))
9803 ERRMSG(
"Pressure profiles are not monotonic!");
9824 for (
int ip = 0; ip < met->
np; ip++)
9825 met->
p[ip] = ctl->
met_p[ip];
9829 for (
int ip = 1; ip < met->
np; ip++)
9830 if (met->
p[ip - 1] < met->
p[ip])
9831 ERRMSG(
"Pressure levels must be descending!");
9838 const char *varname,
9839 const char *varname2,
9840 const char *varname3,
9841 const char *varname4,
9842 const char *varname5,
9843 const char *varname6,
9853 float offset, scalfac;
9858 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
9859 sprintf(varsel,
"%s", varname);
9860 else if (varname2 != NULL
9861 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
9862 sprintf(varsel,
"%s", varname2);
9863 else if (varname3 != NULL
9864 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
9865 sprintf(varsel,
"%s", varname3);
9866 else if (varname4 != NULL
9867 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
9868 sprintf(varsel,
"%s", varname4);
9869 else if (varname5 != NULL
9870 && nc_inq_varid(ncid, varname5, &varid) == NC_NOERR)
9871 sprintf(varsel,
"%s", varname5);
9872 else if (varname6 != NULL
9873 && nc_inq_varid(ncid, varname6, &varid) == NC_NOERR)
9874 sprintf(varsel,
"%s", varname6);
9880 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
9881 && nc_get_att_float(ncid, varid,
"scale_factor",
9882 &scalfac) == NC_NOERR) {
9890 short fillval, missval;
9891 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9893 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9897 LOG(2,
"Read 2-D variable: %s"
9898 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
9899 varsel, fillval, missval, scalfac, offset);
9902 NC(nc_get_var_short(ncid, varid, help));
9906 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
9910#pragma omp parallel for default(shared)
9911 for (
int ix = 0; ix < met->
nx; ix++)
9912 for (
int iy = 0; iy < met->
ny; iy++) {
9915 const short aux = help[
ARRAY_2D(iy, ix, met->
nx)];
9916 if ((fillval == 0 || aux != fillval)
9917 && (missval == 0 || aux != missval)
9918 && fabsf(aux * scalfac + offset) < 1e14f)
9919 dest[ix][iy] += scl * (aux * scalfac + offset);
9930 else if (!ctl->
dd) {
9938 float fillval, missval;
9939 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9941 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9945 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
9946 varsel, fillval, missval);
9949 NC(nc_get_var_float(ncid, varid, help));
9956#pragma omp parallel for default(shared)
9957 for (
int ix = 0; ix < met->
nx; ix++)
9958 for (
int iy = 0; iy < met->
ny; iy++) {
9961 const float aux = help[
ARRAY_2D(iy, ix, met->
nx)];
9962 if ((fillval == 0 || aux != fillval)
9963 && (missval == 0 || aux != missval)
9964 && fabsf(aux) < 1e14f)
9965 dest[ix][iy] += scl * aux;
9975#pragma omp parallel for default(shared)
9976 for (
int iy = 0; iy < met->
ny; iy++)
9977 for (
int ix = 0; ix < met->
nx; ix++) {
9980 const float aux = help[
ARRAY_2D(ix, iy, met->
ny)];
9981 if ((fillval == 0 || aux != fillval)
9982 && (missval == 0 || aux != missval)
9983 && fabsf(aux) < 1e14f)
9984 dest[ix][iy] += scl * aux;
9999 float fillval, missval;
10000 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
10002 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
10006 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
10007 varsel, fillval, missval);
10011 size_t help_subdomain_start[3];
10012 size_t help_subdomain_count[3];
10014 help_subdomain_start[0] = 0;
10023 help_subdomain_count[0] = 1;
10037 nc_var_par_access(ncid, varid, NC_COLLECTIVE);
10039 NC(nc_get_vara_float
10040 (ncid, varid, help_subdomain_start, help_subdomain_count, help));
10043 size_t help_halo_bnd_start[3];
10044 size_t help_halo_bnd_count[3];
10046 help_halo_bnd_start[0] = 0;
10055 help_halo_bnd_count[0] = 1;
10065 ALLOC(help_halo,
float,
10066 help_halo_bnd_count[1] * help_halo_bnd_count[2]);
10069 nc_var_par_access(ncid, varid, NC_COLLECTIVE);
10071 NC(nc_get_vara_float
10072 (ncid, varid, help_halo_bnd_start, help_halo_bnd_count, help_halo));
10078 omp_set_dynamic(1);
10079#pragma omp parallel for default(shared)
10080 for (
int ix = 0; ix < (int) help_subdomain_count[2]; ix++)
10081 for (
int iy = 0; iy < (int) help_subdomain_count[1]; iy++) {
10085 help[
ARRAY_2D(iy, ix, (
int) help_subdomain_count[2])];
10086 if ((fillval == 0 || aux != fillval)
10087 && (missval == 0 || aux != missval)
10088 && fabsf(aux) < 1e14f) {
10094#pragma omp parallel for default(shared)
10095 for (
int ix = 0; ix < (int) help_halo_bnd_count[2]; ix++)
10096 for (
int iy = 0; iy < (int) help_halo_bnd_count[1]; iy++) {
10100 help_halo[
ARRAY_2D(iy, ix, (
int) help_halo_bnd_count[2])];
10101 if ((fillval == 0 || aux != fillval)
10102 && (missval == 0 || aux != missval)
10103 && fabsf(aux) < 1e14f)
10109 omp_set_dynamic(0);
10114 omp_set_dynamic(1);
10115#pragma omp parallel for default(shared)
10116 for (
int ix = 0; ix < (int) help_subdomain_count[1]; ix++)
10117 for (
int iy = 0; iy < (int) help_subdomain_count[2]; iy++) {
10121 help[
ARRAY_2D(ix, iy, (
int) help_subdomain_count[1])];
10122 if ((fillval == 0 || aux != fillval)
10123 && (missval == 0 || aux != missval)
10124 && fabsf(aux) < 1e14f)
10130#pragma omp parallel for default(shared)
10131 for (
int ix = 0; ix < (int) help_halo_bnd_count[1]; ix++)
10132 for (
int iy = 0; iy < (int) help_halo_bnd_count[2]; iy++) {
10136 help_halo[
ARRAY_2D(ix, iy, (
int) help_halo_bnd_count[1])];
10137 if ((fillval == 0 || aux != fillval)
10138 && (missval == 0 || aux != missval)
10139 && fabsf(aux) < 1e14f)
10144 omp_set_dynamic(0);
10160 const char *varname,
10161 const char *varname2,
10162 const char *varname3,
10163 const char *varname4,
10172 float offset, scalfac;
10177 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
10178 sprintf(varsel,
"%s", varname);
10179 else if (varname2 != NULL
10180 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
10181 sprintf(varsel,
"%s", varname2);
10182 else if (varname3 != NULL
10183 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
10184 sprintf(varsel,
"%s", varname3);
10185 else if (varname4 != NULL
10186 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
10187 sprintf(varsel,
"%s", varname4);
10193 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
10194 && nc_get_att_float(ncid, varid,
"scale_factor",
10195 &scalfac) == NC_NOERR) {
10203 short fillval, missval;
10204 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
10206 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
10210 LOG(2,
"Read 3-D variable: %s "
10211 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
10212 varsel, fillval, missval, scalfac, offset);
10215 NC(nc_get_var_short(ncid, varid, help));
10219 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
10222 omp_set_dynamic(1);
10223#pragma omp parallel for default(shared)
10224 for (
int ix = 0; ix < met->
nx; ix++)
10225 for (
int iy = 0; iy < met->
ny; iy++)
10226 for (
int ip = 0; ip < met->
np; ip++) {
10227 const short aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
10228 if ((fillval == 0 || aux != fillval)
10229 && (missval == 0 || aux != missval)
10230 && fabsf(aux * scalfac + offset) < 1e14f)
10231 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
10233 dest[ix][iy][ip] = NAN;
10235 omp_set_dynamic(0);
10242 else if (!ctl->
dd) {
10250 float fillval, missval;
10251 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
10253 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
10257 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
10258 varsel, fillval, missval);
10261 NC(nc_get_var_float(ncid, varid, help));
10267 omp_set_dynamic(1);
10268#pragma omp parallel for default(shared)
10269 for (
int ix = 0; ix < met->
nx; ix++)
10270 for (
int iy = 0; iy < met->
ny; iy++)
10271 for (
int ip = 0; ip < met->
np; ip++) {
10272 const float aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
10273 if ((fillval == 0 || aux != fillval)
10274 && (missval == 0 || aux != missval)
10275 && fabsf(aux) < 1e14f)
10276 dest[ix][iy][ip] = scl * aux;
10278 dest[ix][iy][ip] = NAN;
10280 omp_set_dynamic(0);
10285 omp_set_dynamic(1);
10286#pragma omp parallel for default(shared)
10287 for (
int ip = 0; ip < met->
np; ip++)
10288 for (
int iy = 0; iy < met->
ny; iy++)
10289 for (
int ix = 0; ix < met->
nx; ix++) {
10290 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
10291 if ((fillval == 0 || aux != fillval)
10292 && (missval == 0 || aux != missval)
10293 && fabsf(aux) < 1e14f)
10294 dest[ix][iy][ip] = scl * aux;
10296 dest[ix][iy][ip] = NAN;
10298 omp_set_dynamic(0);
10309 float fillval, missval;
10310 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
10312 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
10316 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
10317 varsel, fillval, missval);
10320 size_t help_subdomain_start[4];
10321 size_t help_subdomain_count[4];
10322 size_t help_halo_bnd_start[4];
10323 size_t help_halo_bnd_count[4];
10326 for (
int i = 0; i < 4; i++) {
10362 NC(nc_var_par_access(ncid, varid, NC_INDEPENDENT));
10364 NC(nc_get_vara_float
10365 (ncid, varid, help_subdomain_start, help_subdomain_count, help));
10369 ALLOC(help_halo,
float,
10374 NC(nc_var_par_access(ncid, varid, NC_INDEPENDENT));
10378 NC(nc_get_vara_float
10379 (ncid, varid, help_halo_bnd_start, help_halo_bnd_count, help_halo));
10386 omp_set_dynamic(1);
10387#pragma omp parallel for default(shared)
10390 for (
int ip = 0; ip < met->
np; ip++) {
10394 if ((fillval == 0 || aux != fillval)
10395 && (missval == 0 || aux != missval)
10396 && fabsf(aux) < 1e14f) {
10403#pragma omp parallel for default(shared)
10406 for (
int ip = 0; ip < met->
np; ip++) {
10410 if ((fillval == 0 || aux != fillval)
10411 && (missval == 0 || aux != missval)
10412 && fabsf(aux) < 1e14f)
10417 omp_set_dynamic(0);
10422 omp_set_dynamic(1);
10423#pragma omp parallel for default(shared)
10424 for (
int ip = 0; ip < met->
np; ip++)
10430 if ((fillval == 0 || aux != fillval)
10431 && (missval == 0 || aux != missval)
10432 && fabsf(aux) < 1e14f)
10438#pragma omp parallel for default(shared)
10439 for (
int ip = 0; ip < met->
np; ip++)
10445 if ((fillval == 0 || aux != fillval)
10446 && (missval == 0 || aux != missval)
10447 && fabsf(aux) < 1e14f)
10452 omp_set_dynamic(0);
10468 const char *filename,
10473 size_t filename_len = strlen(filename) + 1;
10474 char sf_filename[filename_len];
10475 char ml_filename[filename_len];
10476 strcpy(sf_filename, filename);
10477 strcpy(ml_filename, filename);
10482 FILE *ml_file = fopen(ml_filename,
"rb");
10483 FILE *sf_file = fopen(sf_filename,
"rb");
10484 if (ml_file == NULL || sf_file == NULL) {
10485 if (ml_file != NULL) {
10487 WARN(
"Cannot open file: %s", sf_filename);
10489 if (sf_file != NULL) {
10491 WARN(
"Cannot open file: %s", ml_filename);
10497 int ml_num_messages = 0, err = 0;
10498 ECC(codes_count_in_file(0, ml_file, &ml_num_messages));
10501 (size_t) ml_num_messages);
10502 for (
int i = 0; i < ml_num_messages; i++) {
10504 if ((h = codes_grib_handle_new_from_file(0, ml_file, &err)) != NULL)
10509 int sf_num_messages = 0;
10510 ECC(codes_count_in_file(0, sf_file, &sf_num_messages));
10513 (size_t) sf_num_messages);
10514 for (
int i = 0; i < sf_num_messages; i++) {
10516 if ((h = codes_grib_handle_new_from_file(0, sf_file, &err)) != NULL)
10529 for (
int i = 0; i < sf_num_messages; i++)
10530 codes_handle_delete(sf_handles[i]);
10534 size_t value_count = 0;
10535 ECC(codes_get_size(ml_handles[0],
"pv", &value_count));
10536 if (value_count % 2 != 0)
10537 ERRMSG(
"Unexpected pv array length!");
10538 size_t nlevels = value_count / 2 - 1;
10540 ALLOC(values,
double,
10542 ECC(codes_get_double_array(ml_handles[0],
"pv", values, &value_count));
10543 double *a_vals = values;
10544 double *b_vals = values + nlevels;
10545 if (met->
npl > (
int) nlevels)
10546 ERRMSG(
"met->npl exceeds number of pressure levels in GRIB!");
10547 for (
int nx = 0; nx < met->
nx; nx++)
10548 for (
int ny = 0; ny < met->
ny; ny++)
10549 for (
int level = 0; level <= met->
npl; level++) {
10550 const float p1 = (float) (a_vals[level] * 0.01f +
10551 met->
ps[nx][ny] * b_vals[level]);
10552 const float p2 = (float) (a_vals[level + 1] * 0.01f +
10553 met->
ps[nx][ny] * b_vals[level + 1]);
10554 met->
pl[nx][ny][level] = 0.5f * (p1 + p2);
10560 for (
int i = 0; i < ml_num_messages; i++)
10561 codes_handle_delete(ml_handles[i]);
10579 LOG(2,
"Read meteo grid information...");
10582 char datestr[
LEN], timestr[
LEN];
10583 size_t s_date =
sizeof(datestr);
10584 ECC(codes_get_string(handles[0],
"dataDate", datestr, &s_date));
10585 size_t s_time =
sizeof(timestr);
10586 ECC(codes_get_string(handles[0],
"dataTime", timestr, &s_time));
10587 int year, month, day, hour;
10588 if (sscanf(datestr,
"%4d%2d%2d", &year, &month, &day) != 3)
10589 ERRMSG(
"Failed to parse dataDate: %s", datestr);
10590 if (sscanf(timestr,
"%2d", &hour) != 1)
10591 ERRMSG(
"Failed to parse dataTime: %s", timestr);
10593 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)", met->
time, year, month,
10597 long count_lat = 0, count_lon = 0;
10598 ECC(codes_get_long(handles[0],
"Nj", &count_lat));
10599 ECC(codes_get_long(handles[0],
"Ni", &count_lon));
10600 met->
ny = (int) count_lat;
10601 met->
nx = (int) count_lon;
10604 LOG(2,
"Number of longitudes: %d", met->
nx);
10605 if (met->
nx < 2 || met->
nx >
EX)
10606 ERRMSG(
"Number of longitudes out of range!");
10607 LOG(2,
"Number of latitudes: %d", met->
ny);
10608 if (met->
ny < 2 || met->
ny >
EY)
10609 ERRMSG(
"Number of latitudes out of range!");
10611 double first_lon, last_lon, first_lat, last_lat, inc_lon, inc_lat;
10612 ECC(codes_get_double
10613 (handles[0],
"longitudeOfFirstGridPointInDegrees", &first_lon));
10614 ECC(codes_get_double
10615 (handles[0],
"latitudeOfFirstGridPointInDegrees", &first_lat));
10616 ECC(codes_get_double
10617 (handles[0],
"longitudeOfLastGridPointInDegrees", &last_lon));
10618 ECC(codes_get_double
10619 (handles[0],
"latitudeOfLastGridPointInDegrees", &last_lat));
10620 ECC(codes_get_double(handles[0],
"iDirectionIncrementInDegrees", &inc_lon));
10621 ECC(codes_get_double(handles[0],
"jDirectionIncrementInDegrees", &inc_lat));
10623 long jscanpos, iscanneg;
10624 ECC(codes_get_long(handles[0],
"iScansNegatively", &iscanneg));
10625 ECC(codes_get_long(handles[0],
"jScansPositively", &jscanpos));
10630 for (
double i = first_lon; i <= last_lon + 1e-6; i += inc_lon) {
10631 met->
lon[counter] = i;
10634 for (
double i = first_lon; i > last_lon - 1e-6; i -= inc_lon) {
10635 met->
lon[counter] = i;
10641 for (
double i = first_lat; i > last_lat - 1e-6; i -= inc_lat) {
10642 met->
lat[counter] = i;
10645 for (
double i = first_lat; i <= last_lat + 1e-6; i += inc_lat) {
10646 met->
lat[counter] = i;
10651 LOG(2,
"Longitudes: %g, %g ... %g deg",
10652 met->
lon[0], met->
lon[1], met->
lon[met->
nx - 1]);
10653 LOG(2,
"Latitudes: %g, %g ... %g deg",
10654 met->
lat[0], met->
lat[1], met->
lat[met->
ny - 1]);
10658 for (
int i = 0; i < count_handles; i++) {
10660 ECC(codes_get_long(handles[i],
"level", &level));
10661 if (level > max_level)
10662 max_level = (int) level;
10664 met->
npl = max_level;
10667 LOG(2,
"Number of levels: %d", met->
npl);
10668 if (met->
npl < 2 || met->
npl >
EP)
10669 ERRMSG(
"Number of levels out of range!");
10678 const int num_messages,
10684 LOG(2,
"Read level data...");
10687 int t_flag = 0, u_flag = 0, v_flag = 0, w_flag = 0, o3_flag = 0, h2o_flag =
10688 0, lwc_flag = 0, rwc_flag = 0, iwc_flag = 0, swc_flag = 0, cc_flag = 0;
10691 for (
int i = 0; i < num_messages; i++) {
10693 size_t max_size =
LEN;
10694 char short_name[max_size];
10695 size_t value_count;
10699 long current_level;
10700 ECC(codes_get_long(handles[i],
"level", ¤t_level));
10701 current_level -= 1;
10704 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
10705 ECC(codes_get_size(handles[i],
"values", &value_count));
10706 ALLOC(values,
double,
10708 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
10716 ECC_READ_3D(
"w", current_level, met->
w, 0.01f, w_flag);
10734 if (t_flag != met->
npl)
10735 ERRMSG(
"Cannot read temperature!");
10736 if (u_flag != met->
npl)
10737 ERRMSG(
"Cannot read zonal wind!");
10738 if (v_flag != met->
npl)
10739 ERRMSG(
"Cannot read meridional wind!");
10740 if (w_flag != met->
npl)
10741 WARN(
"Cannot read vertical velocity!");
10742 if (h2o_flag != met->
npl)
10743 WARN(
"Cannot read specific humidity!");
10744 if (o3_flag != met->
npl)
10745 WARN(
"Cannot read ozone data!");
10746 if (lwc_flag != met->
npl)
10747 WARN(
"Cannot read cloud liquid water content!");
10748 if (rwc_flag != met->
npl)
10749 WARN(
"Cannot read cloud rain water content!");
10750 if (iwc_flag != met->
npl)
10751 WARN(
"Cannot read cloud ice water content!");
10752 if (swc_flag != met->
npl)
10753 WARN(
"Cannot read cloud snow water content!");
10754 if (cc_flag != met->
npl)
10755 WARN(
"Cannot read cloud cover!");
10758 for (
int ix = 0; ix < met->
nx; ix++)
10759 for (
int iy = 0; iy < met->
ny; iy++)
10760 for (
int ip = 1; ip < met->
np; ip++)
10761 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
10762 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
10763 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
10764 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip])) {
10765 LOG(1,
"%f %f %f %f", met->
pl[ix][iy][0], met->
pl[ix][iy][1],
10766 met->
pl[ix][iy][ip - 1], met->
pl[ix][iy][ip]);
10767 ERRMSG(
"Pressure profiles are not monotonic!");
10788 for (
int ip = 0; ip < met->
np; ip++)
10789 met->
p[ip] = ctl->
met_p[ip];
10793 for (
int ip = 1; ip < met->
np; ip++)
10794 if (met->
p[ip - 1] < met->
p[ip])
10795 ERRMSG(
"Pressure levels must be descending!");
10804 const int num_messages,
10810 LOG(2,
"Read surface data...");
10813 int sp_flag = 0, z_flag = 0, t_flag = 0, u_flag = 0, v_flag = 0, ess_flag =
10814 0, nss_flag = 0, shf_flag = 0, lsm_flag = 0, sst_flag = 0, cape_flag = 0,
10815 cin_flag = 0, pbl_flag = 0;
10818 for (
int i = 0; i < num_messages; i++) {
10820 size_t max_size =
LEN, value_count;
10822 char short_name[max_size];
10825 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
10826 ECC(codes_get_size(handles[i],
"values", &value_count));
10827 double *values = (
double *) malloc(value_count *
sizeof(
double));
10828 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
10875 WARN(
"Cannot read surface pressure data!");
10877 WARN(
"Cannot read surface geopotential height!");
10879 WARN(
"Cannot read surface temperature!");
10881 WARN(
"Cannot read surface zonal wind!");
10883 WARN(
"Cannot read surface meridional wind!");
10885 WARN(
"Cannot read eastward turbulent surface stress!");
10887 WARN(
"Cannot read northward turbulent surface stress!");
10889 WARN(
"Cannot read surface sensible heat flux!");
10891 WARN(
"Cannot read land-sea mask!");
10893 WARN(
"Cannot read sea surface temperature!");
10895 if (cape_flag == 0)
10896 WARN(
"Cannot read CAPE!");
10898 WARN(
"Cannot read convective inhibition!");
10900 if (ctl->
met_pbl == 1 && pbl_flag == 0)
10901 WARN(
"Cannot read planetary boundary layer height!");
10911 const char *varname) {
10913 double aux[
EP], p[
EP];
10917 LOG(2,
"Interpolate meteo data to pressure levels: %s", varname);
10920#pragma omp parallel for default(shared) private(aux,p) collapse(2)
10921 for (
int ix = 0; ix < met->
nx; ix++)
10922 for (
int iy = 0; iy < met->
ny; iy++) {
10925 for (
int ip = 0; ip < met->
np; ip++)
10926 p[ip] = met->
pl[ix][iy][ip];
10929 for (
int ip = 0; ip < ctl->
met_np; ip++) {
10930 double pt = ctl->
met_p[ip];
10931 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
10933 else if ((pt > p[met->
np - 1] && p[1] > p[0])
10934 || (pt < p[met->
np - 1] && p[1] < p[0]))
10935 pt = p[met->
np - 1];
10937 aux[ip] =
LIN(p[ip2], var[ix][iy][ip2],
10938 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
10942 for (
int ip = 0; ip < ctl->
met_np; ip++)
10943 var[ix][iy][ip] = (
float) aux[ip];
10959 LOG(2,
"Make zeta profiles monotone...");
10962#pragma omp parallel for default(shared) collapse(2)
10963 for (
int i = 0; i < met->
nx; i++)
10964 for (
int j = 0; j < met->
ny; j++) {
10967 while (k < met->npl) {
10968 if ((met->
zetal[i][j][k - 1] >= met->
zetal[i][j][k])) {
10974 while ((met->
zetal[i][j][k - 1] >=
10975 met->
zetal[i][j][k + l]) & (k + l < met->npl));
10980 (float) (met->
zetal[i][j][k + l] - met->
zetal[i][j][k - 1])
10983 for (
int m = k; m < k + l; m++) {
10984 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
10985 met->
zetal[i][j][m] = s * d + met->
zetal[i][j][k - 1];
10997#pragma omp parallel for default(shared) collapse(2)
10998 for (
int i = 0; i < met->
nx; i++)
10999 for (
int j = 0; j < met->
ny; j++) {
11002 while (k < met->npl) {
11003 if ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k])) {
11010 while ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k + l]) & (k + l <
11015 float s = (float) (met->
pl[i][j][k + l] - met->
pl[i][j][k - 1])
11018 for (
int m = k; m < k + l; m++) {
11019 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
11020 met->
pl[i][j][m] = s * d + met->
pl[i][j][k - 1];
11035 const char *filename,
11046 (filename, NC_NOWRITE | NC_SHARE, MPI_COMM_WORLD, MPI_INFO_NULL,
11050 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
11051 WARN(
"Cannot open file!");
11069 NC(nc_close(ncid));
11086 int rank = 0, size = 1;
11088 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
11089 MPI_Comm_size(MPI_COMM_WORLD, &size);
11096 LOG(2,
"Number of longitudes: %d", dd->
nx_glob);
11097 LOG(2,
"Number of latitudes: %d", dd->
ny_glob);
11101 ERRMSG(
"Global grid is too large!");
11104 ERRMSG(
"Too many zonal subdomains for global x grid!");
11107 ERRMSG(
"Too many meridional subdomains for global y grid!");
11113 LOG(2,
"Longitudes: %g, %g ... %g deg",
11115 LOG(2,
"Latitudes: %g, %g ... %g deg",
11123 const int left = (zonal_rank == 0);
11125 const int top = (merid_rank == 0);
11132 const int ix0 = zonal_rank * nx_block;
11133 const int iy0 = merid_rank * ny_block;
11135 int nx_core = nx_block;
11136 int ny_core = ny_block;
11159 if (!left && !right) {
11162 }
else if (left ^ right) {
11168 if (!top && !bottom) {
11171 }
else if (top ^ bottom) {
11178 double lon_shift = 0.0;
11180 if (left ^ right) {
11196 lon_shift = left ? -360.0 : 360.0;
11229 LOG(2,
"Define subdomain properties.");
11230 LOG(2,
"MPI information: Rank %d, Size %d", rank, size);
11231 LOG(2,
"Edge position: l=%d,r=%d,t=%d,b=%d", left, right, top, bottom);
11232 LOG(2,
"Total size for subdomain meteo data: nx %d ny %d np %d",
11233 met->
nx, met->
ny, met->
np);
11234 LOG(2,
"Hyperslab sizes for boundary halos: nx %d ny %d np %d",
11237 LOG(2,
"Hyperslab sizes for subdomain and inner halos: nx %d ny %d np %d",
11240 LOG(2,
"Subdomain start: nx %ld ny %ld np %ld",
11242 LOG(2,
"Boundary halo start: nx %ld ny %ld np %ld",
11245 LOG(2,
"%d Subdomain longitudes: %g, %g ... %g deg",
11246 rank, met->
lon[0], met->
lon[1], met->
lon[met->
nx - 1]);
11247 LOG(2,
"%d Subdomain latitudes: %g, %g ... %g deg",
11248 rank, met->
lat[0], met->
lat[1], met->
lat[met->
ny - 1]);
11259 LOG(2,
"Calculate planetary boundary layer...");
11265#pragma omp parallel for default(shared) collapse(2)
11266 for (
int ix = 0; ix < met->
nx; ix++)
11267 for (
int iy = 0; iy < met->
ny; iy++) {
11270 const float z = met->
zs[ix][iy] + met->
pbl[ix][iy];
11273 (float) (
LIN(met->
z[ix][iy][ip], met->
p[ip],
11274 met->
z[ix][iy][ip + 1], met->
p[ip + 1], z));
11279 else if (ctl->
met_pbl == 2) {
11283 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
11286#pragma omp parallel for default(shared) collapse(2)
11287 for (
int ix = 0; ix < met->
nx; ix++)
11288 for (
int iy = 0; iy < met->
ny; iy++) {
11291 const double pbl_bot = met->
ps[ix][iy] * exp(-dz /
H0);
11295 for (ip = 1; ip < met->
np; ip++)
11296 if (met->
p[ip] < pbl_bot)
11300 const double h2os =
LIN(met->
p[ip - 1], met->
h2o[ix][iy][ip - 1],
11301 met->
p[ip], met->
h2o[ix][iy][ip], pbl_bot);
11302 const double tvs =
THETAVIRT(pbl_bot, met->
ts[ix][iy], h2os);
11305 double rib_old = 0;
11308 for (; ip < met->
np; ip++) {
11311 double vh2 =
SQR(met->
u[ix][iy][ip] - met->
us[ix][iy])
11312 +
SQR(met->
v[ix][iy][ip] - met->
vs[ix][iy]);
11313 vh2 =
MAX(vh2,
SQR(umin));
11317 G0 * 1e3 * (met->
z[ix][iy][ip] - met->
zs[ix][iy]) / tvs
11319 met->
h2o[ix][iy][ip]) - tvs) / vh2;
11322 if (rib >= rib_crit) {
11323 met->
pbl[ix][iy] = (float) (
LIN(rib_old, met->
p[ip - 1],
11324 rib, met->
p[ip], rib_crit));
11325 if (met->
pbl[ix][iy] > pbl_bot)
11326 met->
pbl[ix][iy] = (float) pbl_bot;
11341 const double dtheta = 2.0, zmin = 0.1;
11344#pragma omp parallel for default(shared) collapse(2)
11345 for (
int ix = 0; ix < met->
nx; ix++)
11346 for (
int iy = 0; iy < met->
ny; iy++) {
11349 const double theta0 =
THETA(met->
ps[ix][iy], met->
ts[ix][iy]);
11353 for (ip = met->
np - 2; ip > 0; ip--)
11354 if (met->
p[ip] >= 300.)
11355 if (met->
p[ip] > met->
ps[ix][iy]
11356 ||
THETA(met->
p[ip], met->
t[ix][iy][ip]) <= theta0 + dtheta)
11361 = (float) (
LIN(
THETA(met->
p[ip + 1], met->
t[ix][iy][ip + 1]),
11363 THETA(met->
p[ip], met->
t[ix][iy][ip]),
11364 met->
p[ip], theta0 + dtheta));
11367 double pbl_min = met->
ps[ix][iy] * exp(-zmin /
H0);
11368 if (met->
pbl[ix][iy] > pbl_min || met->
p[ip] > met->
ps[ix][iy])
11369 met->
pbl[ix][iy] = (float) pbl_min;
11374#pragma omp parallel for default(shared) collapse(2)
11375 for (
int ix = 0; ix < met->
nx; ix++)
11376 for (
int iy = 0; iy < met->
ny; iy++) {
11380 met->
pbl[ix][iy] =
MIN(met->
pbl[ix][iy], (
float) pbl_min);
11384 met->
pbl[ix][iy] =
MAX(met->
pbl[ix][iy], (
float) pbl_max);
11395 LOG(2,
"Apply periodic boundary conditions...");
11398 if (!(fabs(met->
lon[met->
nx - 1] - met->
lon[0]
11399 + met->
lon[1] - met->
lon[0] - 360) < 0.01))
11403 if ((++met->
nx) >=
EX)
11404 ERRMSG(
"Cannot create periodic boundary conditions!");
11407 met->
lon[met->
nx - 1] = met->
lon[met->
nx - 2] + met->
lon[1] - met->
lon[0];
11410#pragma omp parallel for default(shared)
11411 for (
int iy = 0; iy < met->
ny; iy++) {
11412 met->
ps[met->
nx - 1][iy] = met->
ps[0][iy];
11413 met->
zs[met->
nx - 1][iy] = met->
zs[0][iy];
11414 met->
ts[met->
nx - 1][iy] = met->
ts[0][iy];
11415 met->
us[met->
nx - 1][iy] = met->
us[0][iy];
11416 met->
vs[met->
nx - 1][iy] = met->
vs[0][iy];
11417 met->
ess[met->
nx - 1][iy] = met->
ess[0][iy];
11418 met->
nss[met->
nx - 1][iy] = met->
nss[0][iy];
11419 met->
shf[met->
nx - 1][iy] = met->
shf[0][iy];
11420 met->
lsm[met->
nx - 1][iy] = met->
lsm[0][iy];
11421 met->
sst[met->
nx - 1][iy] = met->
sst[0][iy];
11422 met->
pbl[met->
nx - 1][iy] = met->
pbl[0][iy];
11423 met->
cape[met->
nx - 1][iy] = met->
cape[0][iy];
11424 met->
cin[met->
nx - 1][iy] = met->
cin[0][iy];
11425 for (
int ip = 0; ip < met->
np; ip++) {
11426 met->
t[met->
nx - 1][iy][ip] = met->
t[0][iy][ip];
11427 met->
u[met->
nx - 1][iy][ip] = met->
u[0][iy][ip];
11428 met->
v[met->
nx - 1][iy][ip] = met->
v[0][iy][ip];
11429 met->
w[met->
nx - 1][iy][ip] = met->
w[0][iy][ip];
11430 met->
h2o[met->
nx - 1][iy][ip] = met->
h2o[0][iy][ip];
11431 met->
o3[met->
nx - 1][iy][ip] = met->
o3[0][iy][ip];
11432 met->
lwc[met->
nx - 1][iy][ip] = met->
lwc[0][iy][ip];
11433 met->
rwc[met->
nx - 1][iy][ip] = met->
rwc[0][iy][ip];
11434 met->
iwc[met->
nx - 1][iy][ip] = met->
iwc[0][iy][ip];
11435 met->
swc[met->
nx - 1][iy][ip] = met->
swc[0][iy][ip];
11436 met->
cc[met->
nx - 1][iy][ip] = met->
cc[0][iy][ip];
11438 for (
int ip = 0; ip < met->
npl; ip++) {
11439 met->
ul[met->
nx - 1][iy][ip] = met->
ul[0][iy][ip];
11440 met->
vl[met->
nx - 1][iy][ip] = met->
vl[0][iy][ip];
11441 met->
wl[met->
nx - 1][iy][ip] = met->
wl[0][iy][ip];
11442 met->
pl[met->
nx - 1][iy][ip] = met->
pl[0][iy][ip];
11443 met->
zetal[met->
nx - 1][iy][ip] = met->
zetal[0][iy][ip];
11456 LOG(2,
"Apply fix for polar winds...");
11462 if (fabs(met->
lat[0]) < 89.999 || fabs(met->
lat[met->
ny - 1]) < 89.999)
11466 for (
int ihem = 0; ihem < 2; ihem++) {
11469 int i89 = 1, i90 = 0, sign = 1;
11474 if (met->
lat[i90] < 0)
11478 double clon[
EX], slon[
EX];
11479#pragma omp parallel for default(shared)
11480 for (
int ix = 0; ix < met->
nx; ix++) {
11481 clon[ix] = cos(sign *
DEG2RAD(met->
lon[ix]));
11482 slon[ix] = sin(sign *
DEG2RAD(met->
lon[ix]));
11486#pragma omp parallel for default(shared)
11487 for (
int ip = 0; ip < met->
np; ip++) {
11490 double vel89x = 0, vel89y = 0;
11491 for (
int ix = 0; ix < met->
nx; ix++) {
11493 (met->
u[ix][i89][ip] * clon[ix] -
11494 met->
v[ix][i89][ip] * slon[ix]) / met->
nx;
11496 (met->
u[ix][i89][ip] * slon[ix] +
11497 met->
v[ix][i89][ip] * clon[ix]) / met->
nx;
11501 for (
int ix = 0; ix < met->
nx; ix++) {
11502 met->
u[ix][i90][ip]
11503 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
11504 met->
v[ix][i90][ip]
11505 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
11520 LOG(2,
"Calculate potential vorticity...");
11523#pragma omp parallel for default(shared)
11524 for (
int ip = 0; ip < met->
np; ip++)
11525 pows[ip] = pow(1000. / met->
p[ip], 0.286);
11528#pragma omp parallel for default(shared)
11529 for (
int ix = 0; ix < met->
nx; ix++) {
11532 const int ix0 =
MAX(ix - 1, 0);
11533 const int ix1 =
MIN(ix + 1, met->
nx - 1);
11536 for (
int iy = 0; iy < met->
ny; iy++) {
11539 const int iy0 =
MAX(iy - 1, 0);
11540 const int iy1 =
MIN(iy + 1, met->
ny - 1);
11543 const double latr = 0.5 * (met->
lat[iy1] + met->
lat[iy0]);
11544 double dx, dy, c0, c1, cr, vort;
11548 dx = 1000. *
DEG2DX(met->
lon[ix1] - met->
lon[ix0], latr);
11553 vort = 2 * 7.2921e-5 * sin(
DEG2RAD(latr));
11555 dx = met->
lon[ix1] - met->
lon[ix0];
11556 dy = met->
lat[iy1] - met->
lat[iy0];
11562 vort = 2 * 7.2921e-5 * sin(latr / (
RE * 1000));
11566 for (
int ip = 0; ip < met->
np; ip++) {
11570 = (met->
t[ix1][iy][ip] - met->
t[ix0][iy][ip]) * pows[ip] / dx;
11571 const double dvdx = (met->
v[ix1][iy][ip] - met->
v[ix0][iy][ip]) / dx;
11575 = (met->
t[ix][iy1][ip] - met->
t[ix][iy0][ip]) * pows[ip] / dy;
11577 = (met->
u[ix][iy1][ip] * c1 - met->
u[ix][iy0][ip] * c0) / dy;
11580 const int ip0 =
MAX(ip - 1, 0);
11581 const int ip1 =
MIN(ip + 1, met->
np - 1);
11584 double dtdp, dudp, dvdp;
11585 const double dp0 = 100. * (met->
p[ip] - met->
p[ip0]);
11586 const double dp1 = 100. * (met->
p[ip1] - met->
p[ip]);
11587 if (ip != ip0 && ip != ip1) {
11588 double denom = dp0 * dp1 * (dp0 + dp1);
11589 dtdp = (dp0 * dp0 * met->
t[ix][iy][ip1] * pows[ip1]
11590 - dp1 * dp1 * met->
t[ix][iy][ip0] * pows[ip0]
11591 + (dp1 * dp1 - dp0 * dp0) * met->
t[ix][iy][ip] * pows[ip])
11593 dudp = (dp0 * dp0 * met->
u[ix][iy][ip1]
11594 - dp1 * dp1 * met->
u[ix][iy][ip0]
11595 + (dp1 * dp1 - dp0 * dp0) * met->
u[ix][iy][ip])
11597 dvdp = (dp0 * dp0 * met->
v[ix][iy][ip1]
11598 - dp1 * dp1 * met->
v[ix][iy][ip0]
11599 + (dp1 * dp1 - dp0 * dp0) * met->
v[ix][iy][ip])
11602 const double denom = dp0 + dp1;
11604 (met->
t[ix][iy][ip1] * pows[ip1] -
11605 met->
t[ix][iy][ip0] * pows[ip0]) / denom;
11606 dudp = (met->
u[ix][iy][ip1] - met->
u[ix][iy][ip0]) / denom;
11607 dvdp = (met->
v[ix][iy][ip1] - met->
v[ix][iy][ip0]) / denom;
11611 met->
pv[ix][iy][ip] = (float)
11613 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
11619#pragma omp parallel for default(shared)
11620 for (
int ix = 0; ix < met->
nx; ix++)
11621 for (
int ip = 0; ip < met->
np; ip++) {
11623 = met->
pv[ix][1][ip]
11624 = met->
pv[ix][2][ip];
11625 met->
pv[ix][met->
ny - 1][ip]
11626 = met->
pv[ix][met->
ny - 2][ip]
11627 = met->
pv[ix][met->
ny - 3][ip];
11638 LOG(2,
"Calculate total column ozone...");
11641#pragma omp parallel for default(shared) collapse(2)
11642 for (
int ix = 0; ix < met->
nx; ix++)
11643 for (
int iy = 0; iy < met->
ny; iy++) {
11647 for (
int ip = 1; ip < met->
np; ip++)
11648 if (met->
p[ip - 1] <= met->
ps[ix][iy]) {
11650 0.5 * (met->
o3[ix][iy][ip - 1] + met->
o3[ix][iy][ip]);
11651 const double dp = met->
p[ip - 1] - met->
p[ip];
11652 cd += vmr *
MO3 /
MA * dp * 1e2 /
G0;
11656 met->
o3c[ix][iy] = (float) (cd / 2.1415e-5);
11675 LOG(2,
"Downsampling of meteo data...");
11681 help->
nx = met->
nx;
11682 help->
ny = met->
ny;
11683 help->
np = met->
np;
11684 memcpy(help->
lon, met->
lon,
sizeof(met->
lon));
11685 memcpy(help->
lat, met->
lat,
sizeof(met->
lat));
11686 memcpy(help->
p, met->
p,
sizeof(met->
p));
11689 for (
int ix = 0; ix < met->
nx; ix += ctl->
met_dx) {
11690 for (
int iy = 0; iy < met->
ny; iy += ctl->
met_dy) {
11691 for (
int ip = 0; ip < met->
np; ip += ctl->
met_dp) {
11692 help->
ps[ix][iy] = 0;
11693 help->
zs[ix][iy] = 0;
11694 help->
ts[ix][iy] = 0;
11695 help->
us[ix][iy] = 0;
11696 help->
vs[ix][iy] = 0;
11697 help->
ess[ix][iy] = 0;
11698 help->
nss[ix][iy] = 0;
11699 help->
shf[ix][iy] = 0;
11700 help->
lsm[ix][iy] = 0;
11701 help->
sst[ix][iy] = 0;
11702 help->
pbl[ix][iy] = 0;
11703 help->
cape[ix][iy] = 0;
11704 help->
cin[ix][iy] = 0;
11705 help->
t[ix][iy][ip] = 0;
11706 help->
u[ix][iy][ip] = 0;
11707 help->
v[ix][iy][ip] = 0;
11708 help->
w[ix][iy][ip] = 0;
11709 help->
h2o[ix][iy][ip] = 0;
11710 help->
o3[ix][iy][ip] = 0;
11711 help->
lwc[ix][iy][ip] = 0;
11712 help->
rwc[ix][iy][ip] = 0;
11713 help->
iwc[ix][iy][ip] = 0;
11714 help->
swc[ix][iy][ip] = 0;
11715 help->
cc[ix][iy][ip] = 0;
11717 for (
int ix2 = ix - ctl->
met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
11722 else if (ix3 >= met->
nx)
11725 for (
int iy2 =
MAX(iy - ctl->
met_sy + 1, 0);
11726 iy2 <=
MIN(iy + ctl->
met_sy - 1, met->
ny - 1); iy2++)
11727 for (
int ip2 =
MAX(ip - ctl->
met_sp + 1, 0);
11728 ip2 <=
MIN(ip + ctl->
met_sp - 1, met->
np - 1); ip2++) {
11730 (1.0f - (float) abs(ix - ix2) / (float) ctl->
met_sx)
11731 * (1.0f - (float) abs(iy - iy2) / (float) ctl->
met_sy)
11732 * (1.0f - (float) abs(ip - ip2) / (float) ctl->
met_sp);
11733 help->
ps[ix][iy] += w * met->
ps[ix3][iy2];
11734 help->
zs[ix][iy] += w * met->
zs[ix3][iy2];
11735 help->
ts[ix][iy] += w * met->
ts[ix3][iy2];
11736 help->
us[ix][iy] += w * met->
us[ix3][iy2];
11737 help->
vs[ix][iy] += w * met->
vs[ix3][iy2];
11738 help->
ess[ix][iy] += w * met->
ess[ix3][iy2];
11739 help->
nss[ix][iy] += w * met->
nss[ix3][iy2];
11740 help->
shf[ix][iy] += w * met->
shf[ix3][iy2];
11741 help->
lsm[ix][iy] += w * met->
lsm[ix3][iy2];
11742 help->
sst[ix][iy] += w * met->
sst[ix3][iy2];
11743 help->
pbl[ix][iy] += w * met->
pbl[ix3][iy2];
11744 help->
cape[ix][iy] += w * met->
cape[ix3][iy2];
11745 help->
cin[ix][iy] += w * met->
cin[ix3][iy2];
11746 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip2];
11747 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip2];
11748 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip2];
11749 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip2];
11750 help->
h2o[ix][iy][ip] += w * met->
h2o[ix3][iy2][ip2];
11751 help->
o3[ix][iy][ip] += w * met->
o3[ix3][iy2][ip2];
11752 help->
lwc[ix][iy][ip] += w * met->
lwc[ix3][iy2][ip2];
11753 help->
rwc[ix][iy][ip] += w * met->
rwc[ix3][iy2][ip2];
11754 help->
iwc[ix][iy][ip] += w * met->
iwc[ix3][iy2][ip2];
11755 help->
swc[ix][iy][ip] += w * met->
swc[ix3][iy2][ip2];
11756 help->
cc[ix][iy][ip] += w * met->
cc[ix3][iy2][ip2];
11760 help->
ps[ix][iy] /= wsum;
11761 help->
zs[ix][iy] /= wsum;
11762 help->
ts[ix][iy] /= wsum;
11763 help->
us[ix][iy] /= wsum;
11764 help->
vs[ix][iy] /= wsum;
11765 help->
ess[ix][iy] /= wsum;
11766 help->
nss[ix][iy] /= wsum;
11767 help->
shf[ix][iy] /= wsum;
11768 help->
lsm[ix][iy] /= wsum;
11769 help->
sst[ix][iy] /= wsum;
11770 help->
pbl[ix][iy] /= wsum;
11771 help->
cape[ix][iy] /= wsum;
11772 help->
cin[ix][iy] /= wsum;
11773 help->
t[ix][iy][ip] /= wsum;
11774 help->
u[ix][iy][ip] /= wsum;
11775 help->
v[ix][iy][ip] /= wsum;
11776 help->
w[ix][iy][ip] /= wsum;
11777 help->
h2o[ix][iy][ip] /= wsum;
11778 help->
o3[ix][iy][ip] /= wsum;
11779 help->
lwc[ix][iy][ip] /= wsum;
11780 help->
rwc[ix][iy][ip] /= wsum;
11781 help->
iwc[ix][iy][ip] /= wsum;
11782 help->
swc[ix][iy][ip] /= wsum;
11783 help->
cc[ix][iy][ip] /= wsum;
11790 for (
int ix = 0; ix < help->
nx; ix += ctl->
met_dx) {
11791 met->
lon[met->
nx] = help->
lon[ix];
11793 for (
int iy = 0; iy < help->
ny; iy += ctl->
met_dy) {
11794 met->
lat[met->
ny] = help->
lat[iy];
11795 met->
ps[met->
nx][met->
ny] = help->
ps[ix][iy];
11796 met->
zs[met->
nx][met->
ny] = help->
zs[ix][iy];
11797 met->
ts[met->
nx][met->
ny] = help->
ts[ix][iy];
11798 met->
us[met->
nx][met->
ny] = help->
us[ix][iy];
11799 met->
vs[met->
nx][met->
ny] = help->
vs[ix][iy];
11800 met->
ess[met->
nx][met->
ny] = help->
ess[ix][iy];
11801 met->
nss[met->
nx][met->
ny] = help->
nss[ix][iy];
11802 met->
shf[met->
nx][met->
ny] = help->
shf[ix][iy];
11803 met->
lsm[met->
nx][met->
ny] = help->
lsm[ix][iy];
11804 met->
sst[met->
nx][met->
ny] = help->
sst[ix][iy];
11805 met->
pbl[met->
nx][met->
ny] = help->
pbl[ix][iy];
11807 met->
cin[met->
nx][met->
ny] = help->
cin[ix][iy];
11809 for (
int ip = 0; ip < help->
np; ip += ctl->
met_dp) {
11810 met->
p[met->
np] = help->
p[ip];
11811 met->
t[met->
nx][met->
ny][met->
np] = help->
t[ix][iy][ip];
11812 met->
u[met->
nx][met->
ny][met->
np] = help->
u[ix][iy][ip];
11813 met->
v[met->
nx][met->
ny][met->
np] = help->
v[ix][iy][ip];
11814 met->
w[met->
nx][met->
ny][met->
np] = help->
w[ix][iy][ip];
11815 met->
h2o[met->
nx][met->
ny][met->
np] = help->
h2o[ix][iy][ip];
11816 met->
o3[met->
nx][met->
ny][met->
np] = help->
o3[ix][iy][ip];
11817 met->
lwc[met->
nx][met->
ny][met->
np] = help->
lwc[ix][iy][ip];
11818 met->
rwc[met->
nx][met->
ny][met->
np] = help->
rwc[ix][iy][ip];
11819 met->
iwc[met->
nx][met->
ny][met->
np] = help->
iwc[ix][iy][ip];
11820 met->
swc[met->
nx][met->
ny][met->
np] = help->
swc[ix][iy][ip];
11821 met->
cc[met->
nx][met->
ny][met->
np] = help->
cc[ix][iy][ip];
11840 double p2[200], pv[
EP], pv2[200], t[
EP], t2[200], th[
EP],
11841 th2[200], z[
EP], z2[200];
11845 LOG(2,
"Calculate tropopause...");
11848#pragma omp parallel for default(shared)
11849 for (
int iz = 0; iz < met->
np; iz++)
11850 z[iz] =
Z(met->
p[iz]);
11851#pragma omp parallel for default(shared)
11852 for (
int iz = 0; iz <= 190; iz++) {
11853 z2[iz] = 4.5 + 0.1 * iz;
11854 p2[iz] =
P(z2[iz]);
11859#pragma omp parallel for default(shared) collapse(2)
11860 for (
int ix = 0; ix < met->
nx; ix++)
11861 for (
int iy = 0; iy < met->
ny; iy++)
11862 met->
pt[ix][iy] = NAN;
11867 ERRMSG(
"Only lat/lon grid supported");
11868#pragma omp parallel for default(shared) collapse(2)
11869 for (
int ix = 0; ix < met->
nx; ix++)
11870 for (
int iy = 0; iy < met->
ny; iy++)
11878#pragma omp parallel for default(shared) private(t,t2) collapse(2)
11879 for (
int ix = 0; ix < met->
nx; ix++)
11880 for (
int iy = 0; iy < met->
ny; iy++) {
11883 for (
int iz = 0; iz < met->
np; iz++)
11884 t[iz] = met->
t[ix][iy][iz];
11888 int iz = (int) gsl_stats_min_index(t2, 1, 171);
11889 if (iz > 0 && iz < 170)
11890 met->
pt[ix][iy] = (float) p2[iz];
11892 met->
pt[ix][iy] = NAN;
11900#pragma omp parallel for default(shared) private(t,t2) collapse(2)
11901 for (
int ix = 0; ix < met->
nx; ix++)
11902 for (
int iy = 0; iy < met->
ny; iy++) {
11906 for (iz = 0; iz < met->
np; iz++)
11907 t[iz] = met->
t[ix][iy][iz];
11911 met->
pt[ix][iy] = NAN;
11912 for (iz = 0; iz <= 170; iz++) {
11914 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
11915 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
11920 if (iz > 0 && iz < 170)
11921 met->
pt[ix][iy] = (float) p2[iz];
11928 met->
pt[ix][iy] = NAN;
11929 for (; iz <= 170; iz++) {
11931 for (
int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
11932 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
11939 for (; iz <= 170; iz++) {
11941 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
11942 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
11947 if (iz > 0 && iz < 170)
11948 met->
pt[ix][iy] = (float) p2[iz];
11960#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
11961 for (
int ix = 0; ix < met->
nx; ix++)
11962 for (
int iy = 0; iy < met->
ny; iy++) {
11965 for (
int iz = 0; iz < met->
np; iz++)
11966 pv[iz] = met->
pv[ix][iy][iz];
11970 for (
int iz = 0; iz < met->
np; iz++)
11971 th[iz] =
THETA(met->
p[iz], met->
t[ix][iy][iz]);
11975 met->
pt[ix][iy] = NAN;
11976 for (
int iz = 0; iz <= 170; iz++)
11979 if (iz > 0 && iz < 170)
11980 met->
pt[ix][iy] = (float) p2[iz];
11987 ERRMSG(
"Cannot calculate tropopause!");
11990#pragma omp parallel for default(shared) collapse(2)
11991 for (
int ix = 0; ix < met->
nx; ix++)
11992 for (
int iy = 0; iy < met->
ny; iy++) {
11993 double h2ot, tt, zt;
11996 met->
lat[iy], &tt, ci, cw, 1);
11998 met->
lat[iy], &zt, ci, cw, 0);
12000 met->
lat[iy], &h2ot, ci, cw, 0);
12001 met->
tt[ix][iy] = (float) tt;
12002 met->
zt[ix][iy] = (float) zt;
12003 met->
h2ot[ix][iy] = (float) h2ot;
12010 const char *filename,
12020 LOG(1,
"Read observation data: %s", filename);
12024 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
12026 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
12028 ERRMSG(
"Set OBS_TYPE to 0 or 1!");
12031 for (
int i = 1; i < *nobs; i++)
12032 if (rt[i] < rt[i - 1])
12033 ERRMSG(
"Time must be ascending!");
12038 LOG(2,
"Number of observations: %d", *nobs);
12039 gsl_stats_minmax(&mini, &maxi, rt, 1, (
size_t) n);
12040 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
12041 gsl_stats_minmax(&mini, &maxi, rz, 1, (
size_t) n);
12042 LOG(2,
"Altitude range: %g ... %g km", mini, maxi);
12043 gsl_stats_minmax(&mini, &maxi, rlon, 1, (
size_t) n);
12044 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
12045 gsl_stats_minmax(&mini, &maxi, rlat, 1, (
size_t) n);
12046 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
12047 gsl_stats_minmax(&mini, &maxi, robs, 1, (
size_t) n);
12048 LOG(2,
"Observation range: %g ... %g", mini, maxi);
12054 const char *filename,
12064 if (!(in = fopen(filename,
"r")))
12065 ERRMSG(
"Cannot open file!");
12069 while (fgets(line,
LEN, in))
12070 if (sscanf(line,
"%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
12071 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
12072 if ((++(*nobs)) >=
NOBS)
12073 ERRMSG(
"Too many observations!");
12082 const char *filename,
12093 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
12094 ERRMSG(
"Cannot open file!");
12105 NC(nc_close(ncid));
12111 const char *filename,
12114 const char *varname,
12116 const char *defvalue,
12121 char fullname1[
LEN], fullname2[
LEN], rval[
LEN];
12123 int contain = 0, i;
12126 if (filename[strlen(filename) - 1] !=
'-')
12127 if (!(in = fopen(filename,
"r")))
12128 ERRMSG(
"Cannot open file!");
12132 sprintf(fullname1,
"%s[%d]", varname, arridx);
12133 sprintf(fullname2,
"%s[*]", varname);
12135 sprintf(fullname1,
"%s", varname);
12136 sprintf(fullname2,
"%s", varname);
12141 char dummy[
LEN], line[
LEN], rvarname[
LEN];
12142 while (fgets(line,
LEN, in)) {
12143 if (sscanf(line,
"%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
12144 if (strcasecmp(rvarname, fullname1) == 0 ||
12145 strcasecmp(rvarname, fullname2) == 0) {
12151 for (i = 1; i < argc - 1; i++)
12152 if (strcasecmp(argv[i], fullname1) == 0 ||
12153 strcasecmp(argv[i], fullname2) == 0) {
12154 sprintf(rval,
"%s", argv[i + 1]);
12165 if (strlen(defvalue) > 0)
12166 sprintf(rval,
"%s", defvalue);
12168 ERRMSG(
"Missing variable %s!\n", fullname1);
12172 LOG(1,
"%s = %s", fullname1, rval);
12176 sprintf(value,
"%s", rval);
12186 const double rhop) {
12189 const double rp_help = rp * 1e-6;
12192 const double rho =
RHO(p, T);
12195 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
12198 const double v = sqrt(8. *
KB * T / (M_PI * 4.8096e-26));
12201 const double lambda = 2. * eta / (rho * v);
12204 const double K = lambda / rp_help;
12207 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
12210 return 2. *
SQR(rp_help) * (rhop - rho) *
G0 / (9. * eta) * G;
12222 const int method) {
12228 gsl_interp_accel *acc = gsl_interp_accel_alloc();
12229 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (
size_t) n);
12232 gsl_spline_init(s, x, y, (
size_t) n);
12233 for (
int i = 0; i < n2; i++)
12236 else if (x2[i] >= x[n - 1])
12239 y2[i] = gsl_spline_eval(s, x2[i], acc);
12242 gsl_spline_free(s);
12243 gsl_interp_accel_free(acc);
12248 for (
int i = 0; i < n2; i++)
12251 else if (x2[i] >= x[n - 1])
12255 y2[i] =
LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
12269 float mean = 0, var = 0;
12271 for (
int i = 0; i < n; ++i) {
12273 var +=
SQR(data[i]);
12276 var = var / (float) n -
SQR(mean / (
float) n);
12278 return (var > 0 ? sqrtf(var) : 0);
12290 const double remain,
12302 t1.tm_year = year - 1900;
12303 t1.tm_mon = mon - 1;
12309 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
12317 const int output) {
12324 static int iname = -1, igroup = -1, nname, ngroup, ct_name[
NTIMER];
12327 t1 = omp_get_wtime();
12332 rt_name[iname] += dt;
12333 rt_min[iname] = (ct_name[iname] <= 0 ? dt :
MIN(rt_min[iname], dt));
12334 rt_max[iname] = (ct_name[iname] <= 0 ? dt :
MAX(rt_max[iname], dt));
12338 rt_group[igroup] += t1 - t0;
12342 for (
int i = 0; i < nname; i++)
12343 LOG(1,
"TIMER_%s = %.3f s (min= %g s, mean= %g s,"
12344 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
12345 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
12346 for (
int i = 0; i < ngroup; i++)
12347 LOG(1,
"TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
12348 double total = 0.0;
12349 for (
int i = 0; i < nname; i++)
12350 total += rt_name[i];
12351 LOG(1,
"TIMER_TOTAL = %.3f s", total);
12355 for (iname = 0; iname < nname; iname++)
12356 if (strcasecmp(name, names[iname]) == 0)
12358 for (igroup = 0; igroup < ngroup; igroup++)
12359 if (strcasecmp(group, groups[igroup]) == 0)
12363 if (iname >= nname) {
12364 sprintf(names[iname],
"%s", name);
12365 if ((++nname) >=
NTIMER)
12366 ERRMSG(
"Too many timers!");
12370 if (igroup >= ngroup) {
12371 sprintf(groups[igroup],
"%s", group);
12372 if ((++ngroup) >=
NTIMER)
12373 ERRMSG(
"Too many groups!");
12383 const char *filename,
12385 const int with_seconds) {
12392 int len = (int) strlen(filename);
12393 sprintf(tstr,
"%.4s", &filename[len - offset]);
12394 int year = atoi(tstr);
12395 sprintf(tstr,
"%.2s", &filename[len - offset + 5]);
12396 int mon = atoi(tstr);
12397 sprintf(tstr,
"%.2s", &filename[len - offset + 8]);
12398 int day = atoi(tstr);
12399 sprintf(tstr,
"%.2s", &filename[len - offset + 11]);
12400 int hour = atoi(tstr);
12401 sprintf(tstr,
"%.2s", &filename[len - offset + 14]);
12402 int min = atoi(tstr);
12405 if (with_seconds) {
12406 sprintf(tstr,
"%.2s", &filename[len - offset + 17]);
12411 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
12412 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
12413 ERRMSG(
"Cannot read time from filename!");
12416 time2jsec(year, mon, day, hour, min, sec, 0.0, &t);
12436 const double p1 = pt * 0.866877899;
12437 const double p0 = pt / 0.866877899;
12440 if (atm->
p[ip] > p0)
12442 else if (atm->
p[ip] < p1)
12445 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
12451 const char *filename,
12459 const double t0 = t - 0.5 * ctl->
dt_mod;
12460 const double t1 = t + 0.5 * ctl->
dt_mod;
12466 if (!(out = popen(
"gnuplot",
"w")))
12467 ERRMSG(
"Cannot create pipe to gnuplot!");
12470 fprintf(out,
"set out \"%s.png\"\n", filename);
12474 int year, mon, day, hour, min, sec;
12475 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
12476 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
12477 year, mon, day, hour, min);
12482 ERRMSG(
"Cannot open file!");
12484 while (fgets(line,
LEN, in))
12485 fprintf(out,
"%s", line);
12492 if (!(out = fopen(filename,
"w")))
12493 ERRMSG(
"Cannot create file!");
12500 "# $1 = time [s]\n"
12501 "# $2 = altitude [km]\n"
12502 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
12505 "# $1 = time [s]\n"
12506 "# $2 = altitude [km]\n" "# $3 = x [m]\n" "# $4 = y [m]\n");
12509 for (
int iq = 0; iq < ctl->
nq; iq++)
12510 fprintf(out,
"# $%i = %s [%s]\n", iq + 5, ctl->
qnt_name[iq],
12512 fprintf(out,
"\n");
12515 for (
int ip = 0; ip < atm->
np; ip += ctl->
atm_stride) {
12523 fprintf(out,
"%.2f %g %g %g",
12524 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]
12527 fprintf(out,
"%.2f %g %.2f %.2f",
12528 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]
12532 for (
int iq = 0; iq < ctl->
nq; iq++) {
12537 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
12539 fprintf(out,
"\n");
12549 const char *filename,
12551 const atm_t *atm) {
12556 if (!(out = fopen(filename,
"w")))
12557 ERRMSG(
"Cannot create file!");
12581 for (
int iq = 0; iq < ctl->
nq; iq++)
12599 const char *filename,
12601 const atm_t *atm) {
12604 ERRMSG(
"CLaMS atmospheric files support only lat/lon grids");
12606 int tid, pid, ncid, varid;
12607 size_t start[2], count[2];
12610 NC(nc_create(filename, NC_NETCDF4, &ncid));
12613 NC(nc_def_dim(ncid,
"time", 1, &tid));
12614 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
12617 int dim_ids[2] = { tid, pid };
12618 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
12619 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
12620 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
12622 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
12624 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
12627 for (
int iq = 0; iq < ctl->
nq; iq++)
12637 NC(nc_enddef(ncid));
12645 for (
int iq = 0; iq < ctl->
nq; iq++)
12649 NC(nc_close(ncid));
12655 const char *dirname,
12661 ERRMSG(
"CLaMS atmospheric files support only lat/lon grids");
12664 static size_t out_cnt = 0;
12666 double r, r_start, r_stop;
12667 int year, mon, day, hour, min, sec;
12668 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
12669 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
12670 char filename_out[2 *
LEN] =
"traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
12672 int ncid, varid, tid, pid, cid;
12680 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
12682 &min_start, &sec_start, &r_start);
12684 &min_stop, &sec_stop, &r_stop);
12686 sprintf(filename_out,
12687 "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc", dirname,
12688 year_start % 100, mon_start, day_start, hour_start,
12689 year_stop % 100, mon_stop, day_stop, hour_stop);
12690 LOG(1,
"Write traj file: %s", filename_out);
12693 start[0] = out_cnt;
12696 count[1] = (size_t) atm->
np;
12699 if (out_cnt == 0) {
12702 NC(nc_create(filename_out, NC_NETCDF4, &ncid));
12705 NC(nc_def_dim(ncid,
"time", NC_UNLIMITED, &tid));
12706 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
12707 NC(nc_def_dim(ncid,
"TMDT", 7, &cid));
12712 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
12713 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
12714 NC_DEF_VAR(
"LAT", NC_DOUBLE, 2, dim_ids,
"Latitude",
"deg",
12716 NC_DEF_VAR(
"LON", NC_DOUBLE, 2, dim_ids,
"Longitude",
"deg",
12718 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 2, dim_ids,
"Pressure",
"hPa",
12720 NC_DEF_VAR(
"ZETA", NC_DOUBLE, 2, dim_ids,
"Zeta",
"K",
12722 for (
int iq = 0; iq < ctl->
nq; iq++)
12732 NC(nc_enddef(ncid));
12733 NC(nc_close(ncid));
12740 NC(nc_open(filename_out, NC_WRITE, &ncid));
12752 for (
int iq = 0; iq < ctl->
nq; iq++)
12756 NC(nc_close(ncid));
12759 if ((year == year_stop) && (mon == mon_stop)
12760 && (day == day_stop) && (hour == hour_stop)) {
12763 char filename_init[2 *
LEN] =
"./init_fix_YYYYMMDDHH.nc";
12764 sprintf(filename_init,
"%s/init_fix_%02d%02d%02d%02d.nc",
12765 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
12766 LOG(1,
"Write init file: %s", filename_init);
12769 NC(nc_create(filename_init, NC_NETCDF4, &ncid));
12772 NC(nc_def_dim(ncid,
"time", 1, &tid));
12773 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
12778 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
12779 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
12780 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
12782 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
12784 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
12787 for (
int iq = 0; iq < ctl->
nq; iq++)
12797 NC(nc_enddef(ncid));
12805 for (
int iq = 0; iq < ctl->
nq; iq++)
12809 NC(nc_close(ncid));
12816 const char *filename,
12818 const atm_t *atm) {
12820 int ncid, obsid, varid;
12822 size_t start[2], count[2];
12825 NC(nc_create(filename, NC_NETCDF4, &ncid));
12828 NC(nc_def_dim(ncid,
"obs", (
size_t) atm->
np, &obsid));
12831 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &obsid,
"time",
12832 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
12833 NC_DEF_VAR(
"press", NC_DOUBLE, 1, &obsid,
"pressure",
"hPa",
12835 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &obsid,
"longitude",
"degrees_east",
12837 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &obsid,
"latitude",
"degrees_north",
12839 for (
int iq = 0; iq < ctl->
nq; iq++)
12848 NC(nc_enddef(ncid));
12855 for (
int iq = 0; iq < ctl->
nq; iq++)
12859 NC(nc_close(ncid));
12865 const char *filename,
12871 ERRMSG(
"Only lat/lon grid supported");
12875 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
12878 static int *obscount, nobs, nk;
12882 const int ensemble = (ctl->
nens > 0);
12888 if (ctl->
qnt_m < 0)
12889 ERRMSG(
"Need quantity mass!");
12892 ERRMSG(
"Missing ensemble IDs!");
12894 ERRMSG(
"Too many ensembles!");
12901 ALLOC(area,
double,
12907 ALLOC(rlon,
double,
12909 ALLOC(rlat,
double,
12911 ALLOC(robs,
double,
12922 LOG(1,
"Write CSI%s data: %s", ensemble ?
" ensemble" :
"", filename);
12923 if (!(out = fopen(filename,
"w")))
12924 ERRMSG(
"Cannot create file!");
12928 "# $1 = time [s]\n"
12929 "# $2 = ensemble ID\n"
12930 "# $3 = number of hits (cx)\n"
12931 "# $4 = number of misses (cy)\n"
12932 "# $5 = number of false alarms (cz)\n"
12933 "# $6 = number of observations (cx + cy)\n"
12934 "# $7 = number of forecasts (cx + cz)\n"
12935 "# $8 = bias (%%)\n"
12936 "# $9 = POD (%%)\n"
12937 "# $10 = FAR (%%)\n"
12938 "# $11 = CSI (%%)\n"
12939 "# $12 = hits by random chance\n"
12940 "# $13 = ETS (%%)\n"
12941 "# $14 = Pearson R\n"
12942 "# $15 = Spearman R\n"
12943 "# $16 = mean error [kg/m²]\n"
12944 "# $17 = RMSE [kg/m²]\n"
12945 "# $18 = MAE [kg/m²]\n"
12946 "# $19 = log-likelihood\n" "# $20 = number of points\n\n");
12954 for (
int iy = 0; iy < ctl->
csi_ny; iy++) {
12955 const double lat = ctl->
csi_lat0 + dlat * (iy + 0.5);
12956 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.0) * cos(
DEG2RAD(lat));
12961 const double t0 = t - 0.5 * ctl->
dt_mod;
12962 const double t1 = t + 0.5 * ctl->
dt_mod;
12966 ALLOC(modmean,
double,
12967 (ensemble ? ctl->
nens : 1) * grid_size);
12968 ALLOC(obsmean,
double,
12970 ALLOC(obscount,
int,
12972 ALLOC(obsstd,
double,
12976 for (
int i = 0; i < (ensemble ? ctl->
nens : 1); i++)
12977 ct[i] = cx[i] = cy[i] = cz[i] = n[i] = 0;
12980 for (
int i = 0; i < nobs; i++) {
12981 if (rt[i] < t0 || rt[i] >= t1 || !isfinite(robs[i]))
12985 const int ix = (int) ((rlon[i] - ctl->
csi_lon0) / dlon);
12986 const int iy = (int) ((rlat[i] - ctl->
csi_lat0) / dlat);
12987 const int iz = (int) ((rz[i] - ctl->
csi_z0) / dz);
12988 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
12994 obsmean[idx] += robs[i];
12995 obsstd[idx] +=
SQR(robs[i]);
13000 for (
int ip = 0; ip < atm->
np; ip++) {
13003 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13007 int ens_id = ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
13008 if (ens_id < 0 || ens_id >= (ensemble ? ctl->
nens : 1))
13009 ERRMSG(
"Ensemble ID out of range!");
13012 const int ix = (int) ((atm->
lon[ip] - ctl->
csi_lon0) / dlon);
13013 const int iy = (int) ((atm->
lat[ip] - ctl->
csi_lat0) / dlat);
13014 const int iz = (int) ((
Z(atm->
p[ip]) - ctl->
csi_z0) / dz);
13015 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
13025 for (
int e = 0; e < (ensemble ? ctl->
nens : 1); e++) {
13027 for (
int ix = 0; ix < ctl->
csi_nx; ix++)
13028 for (
int iy = 0; iy < ctl->
csi_ny; iy++)
13029 for (
int iz = 0; iz < ctl->
csi_nz; iz++) {
13034 if (obscount[idx]) {
13035 obsmean[idx] /= obscount[idx];
13037 sqrt(obsstd[idx] / obscount[idx] -
SQR(obsmean[idx]));
13041 const int midx = e * grid_size + idx;
13042 if (modmean[midx] > 0)
13043 modmean[midx] /= (1e6 * area[iy]);
13046 if (obscount[idx]) {
13061 x[n[e]] = modmean[midx];
13062 y[n[e]] = obsmean[idx];
13064 obsstdn[n[e]] = obsstd[idx];
13065 if ((++n[e]) >=
NCSI)
13066 ERRMSG(
"Too many points for statistics!");
13078 static double work[2 *
NCSI], work2[2 *
NCSI];
13079 const int n_obs = cx[e] + cy[e];
13080 const int n_for = cx[e] + cz[e];
13081 const double cx_rd = (ct[e] > 0) ? (1. * n_obs * n_for) / ct[e] : NAN;
13082 const double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
13083 const double pod = (n_obs > 0) ? 100. * cx[e] / n_obs : NAN;
13084 const double far = (n_for > 0) ? 100. * cz[e] / n_for : NAN;
13086 (cx[e] + cy[e] + cz[e] >
13087 0) ? 100. * cx[e] / (cx[e] + cy[e] + cz[e]) : NAN;
13089 (cx[e] + cy[e] + cz[e] - cx_rd >
13090 0) ? 100. * (cx[e] - cx_rd) / (cx[e] + cy[e] + cz[e] - cx_rd) : NAN;
13091 const double rho_p = gsl_stats_correlation(x, 1, y, 1, (
size_t) n[e]);
13092 const double rho_s =
13093 gsl_stats_spearman(x, 1, y, 1, (
size_t) n[e], work);
13094 for (
int i = 0; i < n[e]; i++) {
13095 work[i] = x[i] - y[i];
13096 work2[i] = (obsstdn[i] != 0) ? work[i] / obsstdn[i] : 0;
13098 const double mean = gsl_stats_mean(work, 1, (
size_t) n[e]);
13099 const double rmse =
13100 gsl_stats_sd_with_fixed_mean(work, 1, (
size_t) n[e], 0.0);
13101 const double absdev = gsl_stats_absdev_m(work, 1, (
size_t) n[e], 0.0);
13102 const double loglikelihood =
13103 gsl_stats_tss_m(work2, 1, (
size_t) n[e], 0.0) * -0.5;
13107 "%.2f %d %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n",
13108 t, ensemble ? e : -999, cx[e], cy[e], cz[e], n_obs, n_for, bias,
13109 pod, far, csi, cx_rd, ets, rho_p, rho_s, mean, rmse, absdev,
13110 loglikelihood, n[e]);
13113 for (
int i = 0; i < n[e]; i++)
13114 work[i] = work2[i] = x[i] = y[i] = obsstdn[i] = 0;
13115 ct[e] = cx[e] = cy[e] = cz[e] = n[e] = 0;
13143 const char *filename,
13149 ERRMSG(
"Only lat/lon grid supported");
13156 static int n[
NENS];
13163 ERRMSG(
"Missing ensemble IDs!");
13166 const double t0 = t - 0.5 * ctl->
dt_mod;
13167 const double t1 = t + 0.5 * ctl->
dt_mod;
13170 for (
int i = 0; i <
NENS; i++) {
13171 for (
int iq = 0; iq < ctl->
nq; iq++)
13172 qm[iq][i] = qs[iq][i] = 0;
13173 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
13178 for (
int ip = 0; ip < atm->
np; ip++) {
13181 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13186 ERRMSG(
"Ensemble ID is out of range!");
13190 for (
int iq = 0; iq < ctl->
nq; iq++) {
13191 qm[iq][ctl->
qnt_ens] += atm->
q[iq][ip];
13202 LOG(1,
"Write ensemble data: %s", filename);
13203 if (!(out = fopen(filename,
"w")))
13204 ERRMSG(
"Cannot create file!");
13208 "# $1 = time [s]\n"
13209 "# $2 = altitude [km]\n"
13210 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
13211 for (
int iq = 0; iq < ctl->
nq; iq++)
13212 fprintf(out,
"# $%d = %s (mean) [%s]\n", 5 + iq,
13214 for (
int iq = 0; iq < ctl->
nq; iq++)
13215 fprintf(out,
"# $%d = %s (sigma) [%s]\n", 5 + ctl->
nq + iq,
13217 fprintf(out,
"# $%d = number of members\n\n", 5 + 2 * ctl->
nq);
13220 for (
int i = 0; i <
NENS; i++)
13222 cart2geo(xm[i], &dummy, &lon, &lat);
13223 fprintf(out,
"%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
13224 for (
int iq = 0; iq < ctl->
nq; iq++) {
13226 fprintf(out, ctl->
qnt_format[iq], qm[iq][i] / n[i]);
13228 for (
int iq = 0; iq < ctl->
nq; iq++) {
13230 double var = qs[iq][i] / n[i] -
SQR(qm[iq][i] / n[i]);
13231 fprintf(out, ctl->
qnt_format[iq], (var > 0 ? sqrt(var) : 0));
13233 fprintf(out,
" %d\n", n[i]);
13243 const char *filename,
13251 ERRMSG(
"Only lat/lon grid supported");
13253 static double kz[
EP], kw[
EP];
13257 double *cd, *mean[
NQ], *sigma[
NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
13259 int *ixs, *iys, *izs, *np;
13265 LOG(1,
"Write grid data: %s", filename);
13278 for (
int iq = 0; iq < ctl->
nq; iq++) {
13279 ALLOC(mean[iq],
double,
13281 ALLOC(sigma[iq],
double,
13284 ALLOC(vmr_impl,
double,
13292 ALLOC(area,
double,
13294 ALLOC(press,
double,
13311#pragma omp parallel
for default(shared)
13312 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
13313 z[iz] = ctl->
grid_z0 + dz * (iz + 0.5);
13314 press[iz] =
P(z[iz]);
13318 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13319 lon[ix] = ctl->
grid_lon0 + dlon * (ix + 0.5);
13320#pragma omp parallel for default(shared)
13321 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
13322 lat[iy] = ctl->
grid_lat0 + dlat * (iy + 0.5);
13323 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
13327 const double t0 = t - 0.5 * ctl->
dt_mod;
13328 const double t1 = t + 0.5 * ctl->
dt_mod;
13331#pragma omp parallel for default(shared)
13332 for (
int ip = 0; ip < atm->
np; ip++) {
13333 ixs[ip] = (int) ((atm->
lon[ip] - ctl->
grid_lon0) / dlon);
13334 iys[ip] = (int) ((atm->
lat[ip] - ctl->
grid_lat0) / dlat);
13335 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
grid_z0) / dz);
13336 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
13337 || ixs[ip] < 0 || ixs[ip] >= ctl->
grid_nx
13338 || iys[ip] < 0 || iys[ip] >= ctl->
grid_ny
13339 || izs[ip] < 0 || izs[ip] >= ctl->
grid_nz)
13344 for (
int ip = 0; ip < atm->
np; ip++)
13345 if (izs[ip] >= 0) {
13350 for (
int iq = 0; iq < ctl->
nq; iq++) {
13351 mean[iq][idx] += kernel * atm->
q[iq][ip];
13352 sigma[iq][idx] +=
SQR(kernel * atm->
q[iq][ip]);
13357#pragma omp parallel for default(shared)
13358 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13359 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
13360 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
13367 if (ctl->
qnt_m >= 0)
13368 cd[idx] = mean[ctl->
qnt_m][idx] / (1e6 * area[iy]);
13371 vmr_impl[idx] = NAN;
13372 if (ctl->
qnt_m >= 0 && ctl->
molmass > 0 && met0 != NULL
13375 if (mean[ctl->
qnt_m][idx] > 0) {
13381 lon[ix], lat[iy], &temp, ci, cw, 1);
13385 MA / ctl->
molmass * cd[idx] / (
RHO(press[iz], temp) * dz * 1e3);
13391 for (
int iq = 0; iq < ctl->
nq; iq++) {
13392 mean[iq][idx] /= np[idx];
13393 const double var = sigma[iq][idx] / np[idx] -
SQR(mean[iq][idx]);
13394 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
13396 for (
int iq = 0; iq < ctl->
nq; iq++) {
13397 mean[iq][idx] = NAN;
13398 sigma[iq][idx] = NAN;
13405 t, z, lon, lat, area, dz, np);
13410 t, z, lon, lat, area, dz, np);
13414 ERRMSG(
"Grid data format GRID_TYPE unknown!");
13418 for (
int iq = 0; iq < ctl->
nq; iq++) {
13437 const char *filename,
13442 const double *vmr_impl,
13447 const double *area,
13457 if (!(out = popen(
"gnuplot",
"w")))
13458 ERRMSG(
"Cannot create pipe to gnuplot!");
13461 fprintf(out,
"set out \"%s.png\"\n", filename);
13465 int year, mon, day, hour, min, sec;
13466 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
13467 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
13468 year, mon, day, hour, min);
13474 ERRMSG(
"Cannot open file!");
13475 while (fgets(line,
LEN, in))
13476 fprintf(out,
"%s", line);
13483 if (!(out = fopen(filename,
"w")))
13484 ERRMSG(
"Cannot create file!");
13489 "# $1 = time [s]\n"
13490 "# $2 = altitude [km]\n"
13491 "# $3 = longitude [deg]\n"
13492 "# $4 = latitude [deg]\n"
13493 "# $5 = surface area [km^2]\n"
13494 "# $6 = layer depth [km]\n"
13495 "# $7 = column density (implicit) [kg/m^2]\n"
13496 "# $8 = volume mixing ratio (implicit) [ppv]\n"
13497 "# $9 = number of particles [1]\n");
13498 for (
int iq = 0; iq < ctl->
nq; iq++)
13499 fprintf(out,
"# $%i = %s (mean) [%s]\n", 10 + iq, ctl->
qnt_name[iq],
13502 for (
int iq = 0; iq < ctl->
nq; iq++)
13503 fprintf(out,
"# $%i = %s (stddev) [%s]\n", 10 + ctl->
nq + iq,
13505 fprintf(out,
"\n");
13508 for (
int ix = 0; ix < ctl->
grid_nx; ix++) {
13510 fprintf(out,
"\n");
13511 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
13513 fprintf(out,
"\n");
13514 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
13517 fprintf(out,
"%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
13518 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
13519 for (
int iq = 0; iq < ctl->
nq; iq++) {
13521 fprintf(out, ctl->
qnt_format[iq], mean[iq][idx]);
13524 for (
int iq = 0; iq < ctl->
nq; iq++) {
13526 fprintf(out, ctl->
qnt_format[iq], sigma[iq][idx]);
13528 fprintf(out,
"\n");
13541 const char *filename,
13546 const double *vmr_impl,
13551 const double *area,
13555 char longname[2 *
LEN], varname[2 *
LEN];
13559 int *help2, ncid, dimid[10], varid;
13561 size_t start[2], count[2];
13564 ALLOC(help,
double,
13570 NC(nc_create(filename, NC_NETCDF4, &ncid));
13573 NC(nc_def_dim(ncid,
"time", 1, &dimid[0]));
13574 NC(nc_def_dim(ncid,
"z", (
size_t) ctl->
grid_nz, &dimid[1]));
13575 NC(nc_def_dim(ncid,
"lat", (
size_t) ctl->
grid_ny, &dimid[2]));
13576 NC(nc_def_dim(ncid,
"lon", (
size_t) ctl->
grid_nx, &dimid[3]));
13577 NC(nc_def_dim(ncid,
"dz", 1, &dimid[4]));
13580 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &dimid[0],
"time",
13581 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
13582 NC_DEF_VAR(
"z", NC_DOUBLE, 1, &dimid[1],
"altitude",
"km", 0, 0);
13583 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &dimid[2],
"latitude",
"degrees_north", 0,
13585 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &dimid[3],
"longitude",
"degrees_east", 0,
13587 NC_DEF_VAR(
"dz", NC_DOUBLE, 1, &dimid[1],
"layer depth",
"km", 0, 0);
13588 NC_DEF_VAR(
"area", NC_DOUBLE, 1, &dimid[2],
"surface area",
"km**2", 0, 0);
13590 NC_DEF_VAR(
"cd", NC_FLOAT, 4, dimid,
"column density",
"kg m**-2",
13593 "volume mixing ratio (implicit)",
"ppv", ctl->
grid_nc_level, 0);
13594 NC_DEF_VAR(
"np", NC_INT, 4, dimid,
"number of particles",
"1", 0, 0);
13595 for (
int iq = 0; iq < ctl->
nq; iq++) {
13596 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
13597 sprintf(longname,
"%s (mean)", ctl->
qnt_longname[iq]);
13601 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
13602 sprintf(longname,
"%s (stddev)", ctl->
qnt_longname[iq]);
13608 NC(nc_enddef(ncid));
13618 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13619 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
13620 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
13625 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13626 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
13627 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
13632 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13633 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
13634 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
13639 for (
int iq = 0; iq < ctl->
nq; iq++) {
13640 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
13641 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13642 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
13643 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
13650 for (
int iq = 0; iq < ctl->
nq; iq++) {
13651 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
13652 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13653 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
13654 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
13661 NC(nc_close(ncid));
13671 const char *filename,
13676 FILE *out, *level_log = NULL;
13677 if (!(out = fopen(filename,
"w")))
13678 ERRMSG(
"Cannot create file!");
13684 ERRMSG(
"Cannot create compression log file!");
13689 "# $1 = compression codec name [-]\n"
13690 "# $2 = variable name [-]\n"
13691 "# $3 = level index [-]\n"
13692 "# $4 = pressure level [hPa]\n"
13693 "# $5 = compression ratio [-]\n"
13694 "# $6 = bits per value [bit/value]\n"
13695 "# $7 = correlation coefficient [-]\n"
13696 "# $8 = mean compression error [-]\n"
13697 "# $9 = standard deviation of compression error [-]\n"
13698 "# $10 = minimum compression error [-]\n"
13699 "# $11 = maximum compression error [-]\n"
13700 "# $12 = mean value of original field [-]\n"
13701 "# $13 = value range of original field [-]\n"
13702 "# $14 = normalized root mean square error [-]\n"
13703 "# $15 = compression time [s]\n"
13704 "# $16 = compression speed [MiB/s]\n"
13705 "# $17 = decompression time [s]\n"
13706 "# $18 = decompression speed [MiB/s]\n\n");
13784 ERRMSG(
"Number of meteo variables doesn't match!");
13804 const char *varname) {
13813 for (
int ix = 0; ix < met->
nx; ix++)
13814 for (
int iy = 0; iy < met->
ny; iy++)
13815 help[
ARRAY_2D(ix, iy, met->
ny)] = var[ix][iy];
13818 LOG(2,
"Write 2-D variable: %s (uncompressed)", varname);
13820 (
size_t) (met->
nx * met->
ny),
13834 const char *varname,
13845#pragma omp parallel for default(shared) collapse(2)
13846 for (
int ix = 0; ix < met->
nx; ix++)
13847 for (
int iy = 0; iy < met->
ny; iy++)
13848 for (
int ip = 0; ip < met->
np; ip++)
13849 help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)] = var[ix][iy][ip];
13853 LOG(2,
"Write 3-D variable: %s (uncompressed)", varname);
13855 (
size_t) (met->
nx * met->
ny * met->
np),
13861 compress_pck(ctl, met, varname, help, 0, level_log, out);
13872 compress_zfp(ctl, met, varname, help, 0, level_log, out);
13885 compress_lz4(ctl, met, varname, help, 0, level_log, out);
13891 compress_cms(ctl, met, varname, help, 0, level_log, out);
13904 compress_sz3(ctl, met, varname, help, 0, level_log, out);
13910 ERRMSG(
"MET_TYPE not supported!");
13913 LOG(3,
"%d", metvar);
13923 const char *filename,
13929 size_t start[4], count[4];
13930 NC(nc_create(filename, NC_NETCDF4, &ncid));
13933 int tid, lonid, latid, levid;
13934 NC(nc_def_dim(ncid,
"time", 1, &tid));
13937 NC(nc_def_dim(ncid,
"lon", (
size_t) met->
nx, &lonid));
13938 NC(nc_def_dim(ncid,
"lat", (
size_t) met->
ny, &latid));
13939 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &lonid,
"longitude",
"degrees_east", 0,
13941 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &latid,
"latitude",
"degrees_north", 0,
13944 NC(nc_def_dim(ncid,
"x", (
size_t) met->
nx, &lonid));
13945 NC(nc_def_dim(ncid,
"y", (
size_t) met->
ny, &latid));
13946 NC_DEF_VAR(
"x", NC_DOUBLE, 1, &lonid,
"x",
"easting", 0, 0);
13947 NC_DEF_VAR(
"y", NC_DOUBLE, 1, &latid,
"y",
"northing", 0, 0);
13950 NC(nc_def_dim(ncid,
"lev", (
size_t) met->
np, &levid));
13953 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"time",
13954 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
13955 NC_DEF_VAR(
"lev", NC_DOUBLE, 1, &levid,
"pressure",
"Pa", 0, 0);
13958 int dimid2[3] = { tid, latid, lonid };
13959 NC_DEF_VAR(
"sp", NC_FLOAT, 3, dimid2,
"Surface pressure",
"Pa",
13961 NC_DEF_VAR(
"z", NC_FLOAT, 3, dimid2,
"Geopotential",
"m**2 s**-2",
13963 NC_DEF_VAR(
"t2m", NC_FLOAT, 3, dimid2,
"2 metre temperature",
"K",
13965 NC_DEF_VAR(
"u10m", NC_FLOAT, 3, dimid2,
"10 metre U wind component",
13967 NC_DEF_VAR(
"v10m", NC_FLOAT, 3, dimid2,
"10 metre V wind component",
13970 "Instantaneous eastward turbulent surface stress",
"N m**-2",
13973 "Instantaneous northward turbulent surface stress",
"N m**-2",
13976 "Instantaneous surface sensible heat flux",
"W m**-2",
13978 NC_DEF_VAR(
"lsm", NC_FLOAT, 3, dimid2,
"Land/sea mask",
"-",
13980 NC_DEF_VAR(
"sstk", NC_FLOAT, 3, dimid2,
"Sea surface temperature",
"K",
13982 NC_DEF_VAR(
"blp", NC_FLOAT, 3, dimid2,
"Boundary layer pressure",
"Pa",
13984 NC_DEF_VAR(
"pt", NC_FLOAT, 3, dimid2,
"Tropopause pressure",
"Pa",
13986 NC_DEF_VAR(
"tt", NC_FLOAT, 3, dimid2,
"Tropopause temperature",
"K",
13988 NC_DEF_VAR(
"zt", NC_FLOAT, 3, dimid2,
"Tropopause height",
"m",
13990 NC_DEF_VAR(
"h2ot", NC_FLOAT, 3, dimid2,
"Tropopause water vapor",
"ppv",
13992 NC_DEF_VAR(
"pct", NC_FLOAT, 3, dimid2,
"Cloud top pressure",
"Pa",
13994 NC_DEF_VAR(
"pcb", NC_FLOAT, 3, dimid2,
"Cloud bottom pressure",
"Pa",
13996 NC_DEF_VAR(
"cl", NC_FLOAT, 3, dimid2,
"Total column cloud water",
13999 "Pressure at lifted condensation level (LCL)",
"Pa",
14002 "Pressure at level of free convection (LFC)",
"Pa",
14005 "Pressure at equilibrium level (EL)",
"Pa", ctl->
met_nc_level,
14008 "Convective available potential energy",
"J kg**-1",
14010 NC_DEF_VAR(
"cin", NC_FLOAT, 3, dimid2,
"Convective inhibition",
14012 NC_DEF_VAR(
"o3c", NC_FLOAT, 3, dimid2,
"Total column ozone",
"DU",
14016 int dimid3[4] = { tid, levid, latid, lonid };
14017 NC_DEF_VAR(
"t", NC_FLOAT, 4, dimid3,
"Temperature",
"K",
14019 NC_DEF_VAR(
"u", NC_FLOAT, 4, dimid3,
"U velocity",
"m s**-1",
14021 NC_DEF_VAR(
"v", NC_FLOAT, 4, dimid3,
"V velocity",
"m s**-1",
14023 NC_DEF_VAR(
"w", NC_FLOAT, 4, dimid3,
"Vertical velocity",
"Pa s**-1",
14025 NC_DEF_VAR(
"q", NC_FLOAT, 4, dimid3,
"Specific humidity",
"kg kg**-1",
14027 NC_DEF_VAR(
"o3", NC_FLOAT, 4, dimid3,
"Ozone mass mixing ratio",
14029 NC_DEF_VAR(
"clwc", NC_FLOAT, 4, dimid3,
"Cloud liquid water content",
14031 NC_DEF_VAR(
"crwc", NC_FLOAT, 4, dimid3,
"Cloud rain water content",
14033 NC_DEF_VAR(
"ciwc", NC_FLOAT, 4, dimid3,
"Cloud ice water content",
14035 NC_DEF_VAR(
"cswc", NC_FLOAT, 4, dimid3,
"Cloud snow water content",
14037 NC_DEF_VAR(
"cc", NC_FLOAT, 4, dimid3,
"Cloud cover",
"-",
14041 NC(nc_enddef(ncid));
14055 for (
int ip = 0; ip < met->
np; ip++)
14056 phelp[ip] = 100. * met->
p[ip];
14099 NC(nc_close(ncid));
14106 const char *varname,
14112 size_t start[4], count[4];
14120 for (
int ix = 0; ix < met->
nx; ix++)
14121 for (
int iy = 0; iy < met->
ny; iy++)
14122 help[
ARRAY_2D(iy, ix, met->
nx)] = scl * var[ix][iy];
14125 LOG(2,
"Write 2-D variable: %s (netCDF)", varname);
14136 const char *varname,
14142 size_t start[4], count[4];
14150 for (
int ix = 0; ix < met->
nx; ix++)
14151 for (
int iy = 0; iy < met->
ny; iy++)
14152 for (
int ip = 0; ip < met->
np; ip++)
14153 help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)] = scl * var[ix][iy][ip];
14156 LOG(2,
"Write 3-D variable: %s (netCDF)", varname);
14166 const char *filename,
14174 ERRMSG(
"Only lat/lon grid supported");
14178 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
14179 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
14181 static int nobs, *obscount, ip, okay;
14190 if (ctl->
qnt_m < 0)
14191 ERRMSG(
"Need quantity mass!");
14195 ERRMSG(
"Specify molar mass!");
14202 ALLOC(area,
double,
14206 ALLOC(press,
double,
14212 ALLOC(rlon,
double,
14214 ALLOC(rlat,
double,
14216 ALLOC(robs,
double,
14223 LOG(1,
"Write profile data: %s", filename);
14224 if (!(out = fopen(filename,
"w")))
14225 ERRMSG(
"Cannot create file!");
14229 "# $1 = time [s]\n"
14230 "# $2 = altitude [km]\n"
14231 "# $3 = longitude [deg]\n"
14232 "# $4 = latitude [deg]\n"
14233 "# $5 = pressure [hPa]\n"
14234 "# $6 = temperature [K]\n"
14235 "# $7 = volume mixing ratio [ppv]\n"
14236 "# $8 = H2O volume mixing ratio [ppv]\n"
14237 "# $9 = O3 volume mixing ratio [ppv]\n"
14238 "# $10 = observed BT index [K]\n"
14239 "# $11 = number of observations\n");
14247 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
14248 z[iz] = ctl->
prof_z0 + dz * (iz + 0.5);
14249 press[iz] =
P(z[iz]);
14253 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
14254 lon[ix] = ctl->
prof_lon0 + dlon * (ix + 0.5);
14255 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
14256 lat[iy] = ctl->
prof_lat0 + dlat * (iy + 0.5);
14257 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
14262 const double t0 = t - 0.5 * ctl->
dt_mod;
14263 const double t1 = t + 0.5 * ctl->
dt_mod;
14266 ALLOC(mass,
double,
14268 ALLOC(obsmean,
double,
14270 ALLOC(obscount,
int,
14274 for (
int i = 0; i < nobs; i++) {
14279 else if (rt[i] >= t1)
14283 if (!isfinite(robs[i]))
14287 const int ix = (int) ((rlon[i] - ctl->
prof_lon0) / dlon);
14288 const int iy = (int) ((rlat[i] - ctl->
prof_lat0) / dlat);
14291 if (ix < 0 || ix >= ctl->
prof_nx || iy < 0 || iy >= ctl->
prof_ny)
14296 obsmean[idx] += robs[i];
14301 for (ip = 0; ip < atm->
np; ip++) {
14304 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
14308 const int ix = (int) ((atm->
lon[ip] - ctl->
prof_lon0) / dlon);
14309 const int iy = (int) ((atm->
lat[ip] - ctl->
prof_lat0) / dlat);
14310 const int iz = (int) ((
Z(atm->
p[ip]) - ctl->
prof_z0) / dz);
14313 if (ix < 0 || ix >= ctl->
prof_nx ||
14319 mass[idx] += atm->
q[ctl->
qnt_m][ip];
14323 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
14324 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
14326 if (obscount[idx2] > 0) {
14330 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
14332 if (mass[idx3] > 0) {
14341 fprintf(out,
"\n");
14344 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
14349 lon[ix], lat[iy], &temp, ci, cw, 1);
14351 lon[ix], lat[iy], &h2o, ci, cw, 0);
14353 lon[ix], lat[iy], &o3, ci, cw, 0);
14358 / (
RHO(press[iz], temp) * area[iy] * dz * 1e9);
14361 fprintf(out,
"%.2f %g %g %g %g %g %g %g %g %g %d\n",
14362 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
14363 obsmean[idx2] / obscount[idx2], obscount[idx2]);
14396 const char *filename,
14404 ERRMSG(
"Only lat/lon grid supported");
14408 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[
EP],
14411 static int nobs, nk;
14424 ALLOC(rlon,
double,
14426 ALLOC(rlat,
double,
14428 ALLOC(robs,
double,
14439 LOG(1,
"Write sample data: %s", filename);
14440 if (!(out = fopen(filename,
"w")))
14441 ERRMSG(
"Cannot create file!");
14445 "# $1 = time [s]\n"
14446 "# $2 = altitude [km]\n"
14447 "# $3 = longitude [deg]\n"
14448 "# $4 = latitude [deg]\n"
14449 "# $5 = surface area [km^2]\n"
14450 "# $6 = layer depth [km]\n"
14451 "# $7 = number of particles [1]\n"
14452 "# $8 = column density [kg/m^2]\n"
14453 "# $9 = volume mixing ratio [ppv]\n"
14454 "# $10 = observed BT index [K]\n\n");
14459 area = M_PI * rmax2;
14463 const double t0 = t - 0.5 * ctl->
dt_mod;
14464 const double t1 = t + 0.5 * ctl->
dt_mod;
14467 for (
int i = 0; i < nobs; i++) {
14472 else if (rt[i] >= t1)
14477 geo2cart(0, rlon[i], rlat[i], x0);
14480 const double rp =
P(rz[i]);
14481 const double ptop =
P(rz[i] + ctl->
sample_dz);
14482 const double pbot =
P(rz[i] - ctl->
sample_dz);
14490 for (
int ip = 0; ip < atm->
np; ip++) {
14493 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
14497 if (fabs(rlat[i] - atm->
lat[ip]) > dlat)
14503 if (
DIST2(x0, x1) > rmax2)
14508 if (atm->
p[ip] > pbot || atm->
p[ip] < ptop)
14512 if (ctl->
qnt_m >= 0)
14519 const double cd = mass / (1e6 * area);
14530 rlon[i], rlat[i], &temp, ci, cw, 1);
14539 fprintf(out,
"%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
14540 rlon[i], rlat[i], area, ctl->
sample_dz, np, cd, vmr, robs[i]);
14561 const char *filename,
14567 ERRMSG(
"Only lat/lon grid supported");
14571 static double rmax2, x0[3], x1[3];
14580 LOG(1,
"Write station data: %s", filename);
14583 if (!(out = fopen(filename,
"w")))
14584 ERRMSG(
"Cannot create file!");
14588 "# $1 = time [s]\n"
14589 "# $2 = altitude [km]\n"
14590 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
14591 for (
int iq = 0; iq < ctl->
nq; iq++)
14592 fprintf(out,
"# $%i = %s [%s]\n", (iq + 5),
14594 fprintf(out,
"\n");
14602 const double t0 = t - 0.5 * ctl->
dt_mod;
14603 const double t1 = t + 0.5 * ctl->
dt_mod;
14606 for (
int ip = 0; ip < atm->
np; ip++) {
14609 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
14625 if (
DIST2(x0, x1) > rmax2)
14633 fprintf(out,
"%.2f %g %g %g",
14634 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]);
14635 for (
int iq = 0; iq < ctl->
nq; iq++) {
14637 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
14639 fprintf(out,
"\n");
14650 const char *filename,
14656 ERRMSG(
"Only lat/lon grid supported");
14664 LOG(1,
"Write VTK data: %s", filename);
14667 const double t0 = t - 0.5 * ctl->
dt_mod;
14668 const double t1 = t + 0.5 * ctl->
dt_mod;
14671 if (!(out = fopen(filename,
"w")))
14672 ERRMSG(
"Cannot create file!");
14676 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
14677 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
14684 "# vtk DataFile Version 3.0\n"
14685 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
14688 fprintf(out,
"POINTS %d float\n", np);
14690 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
14691 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
14695 const double coslat = cos(
DEG2RAD(atm->
lat[ip]));
14696 const double x = radius * coslat * cos(
DEG2RAD(atm->
lon[ip]));
14697 const double y = radius * coslat * sin(
DEG2RAD(atm->
lon[ip]));
14698 const double z = radius * sin(
DEG2RAD(atm->
lat[ip]));
14699 fprintf(out,
"%g %g %g\n", x, y, z);
14702 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
14703 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
14705 fprintf(out,
"%g %g %g\n", atm->
lon[ip], atm->
lat[ip],
14710 fprintf(out,
"POINT_DATA %d\n", np);
14711 for (
int iq = 0; iq < ctl->
nq; iq++) {
14712 fprintf(out,
"SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
14714 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
14715 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
14717 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 dd_read_met_nc_grid(dd_t *dd, const ctl_t *ctl, met_t *met, const int ncid)
Read meteorological grid information and construct the domain-decomposed grid with halo regions.
void read_met_sample(const ctl_t *ctl, met_t *met)
Downsamples meteorological data based on specified parameters.
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_log_levels_3d(FILE *out, const char *codec, const char *varname, const met_t *met, const float *org_all, const float *cmp_all, const size_t nxy, const size_t nz, const double ratio, const double bpv, const double t_comp, const double t_decomp, const size_t nbytes)
Write per-level compression diagnostics for a full 3-D field.
int read_atm_nc(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a generic netCDF file and populates the given atmospheric structure.
void read_met_pbl(const ctl_t *ctl, met_t *met)
Computes the planetary boundary layer (PBL) pressure based on meteorological data.
void read_met_detrend(const ctl_t *ctl, met_t *met)
Detrends meteorological data.
void read_met_tropo(const ctl_t *ctl, const clim_t *clim, met_t *met)
Calculates the tropopause and related meteorological variables based on various methods and stores th...
void read_obs_asc(const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from an ASCII file.
void module_chem_init(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Initializes the chemistry modules by setting atmospheric composition.
int locate_reg(const double *xx, const int n, const double x)
Locate the index of the interval containing a given value in a regular grid.
void read_met_nc_levels(const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads and processes meteorological level data from NetCDF files with domain decomposition.
void compress_pck(const ctl_t *ctl, const met_t *met, const char *varname, float *array, const int decompress, FILE *level_log, FILE *inout)
Compresses or decompresses a 3‑D float array using the PCK format.
void read_met_monotonize(const ctl_t *ctl, met_t *met)
Makes zeta and pressure profiles monotone.
int read_clim_ts(const char *filename, clim_ts_t *ts)
Reads a climatological time series from a file and populates the given time series structure.
void intpol_check_cartesian(const double *lons, const int nlon, const double *lats, const int nlat, const double lon, const double lat, double *lon2, double *lat2)
Clamps UTM coordinates to the valid bounds.
void read_met_periodic(met_t *met)
Applies periodic boundary conditions to meteorological data along longitudinal axis.
void mptrac_run_timestep(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t **met0, met_t **met1, atm_t *atm, double t, dd_t *dd)
Executes a single timestep of the MPTRAC model simulation.
int compress_metvar_index(const char *varname)
Maps a meteorological variable name to its internal MPTRAC variable index.
void module_timesteps_init(ctl_t *ctl, const atm_t *atm)
Initialize start time and time interval for time-stepping.
void write_ens(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes ensemble data to a file.
void module_mixing(const ctl_t *ctl, const clim_t *clim, atm_t *atm, const double t)
Update atmospheric properties through interparcel mixing.
double clim_zm(const clim_zm_t *zm, const double t, const double lat, const double p)
Interpolates monthly mean zonal mean climatological variables.
void module_mixing_help(const ctl_t *ctl, const clim_t *clim, atm_t *atm, const int *ixs, const int *iys, const int *izs, const int qnt_idx, const int use_ensemble)
Perform subgrid-scale interparcel mixing of a given quantity.
void read_clim_photo_help(const int ncid, const char *varname, const clim_photo_t *photo, double var[CP][CSZA][CO3])
Reads a 3D climatological photochemistry variable from a NetCDF file.
void read_met_ml2pl(const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname)
Interpolates meteorological data to specified pressure levels.
double clim_tropo(const clim_t *clim, const double t, const double lat)
Calculates the tropopause pressure based on climatological data.
void read_obs_nc(const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from a NetCDF file.
void read_met_bin_2d(FILE *in, const met_t *met, float var[EX][EY], const char *varname)
Reads a 2-dimensional meteorological variable from a binary file and stores it in the provided array.
int locate_irr(const double *xx, const int n, const double x)
Locate the index of the interval containing a given value in a sorted array.
void module_isosurf_init(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Initialize the isosurface module based on atmospheric data.
void level_definitions(ctl_t *ctl)
Defines pressure levels for meteorological data.
void write_grid_asc(const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
Writes grid data to an ASCII file.
void mptrac_update_device(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
Updates device memory for specified data structures.
void time2jsec(const int year, const int mon, const int day, const int hour, const int min, const int sec, const double remain, double *jsec)
Converts time components to seconds since January 1, 2000, 12:00:00 UTC.
void mptrac_init(ctl_t *ctl, cache_t *cache, clim_t *clim, atm_t *atm, const int ntask)
Initializes the MPTRAC model and its associated components.
void intpol_met_time_3d(const met_t *met0, float array0[EX][EY][EP], const met_t *met1, float array1[EX][EY][EP], const double ts, const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological data in 3D space and time.
void get_met_filename(const ctl_t *ctl, const double t, const int direct, const char *metbase, const double dt_met, char *filename)
Generates a formatted filename for meteorological data files based on the input parameters.
void fft_help(double *fcReal, double *fcImag, const int n)
Computes the Fast Fourier Transform (FFT) of a complex sequence.
void module_wet_depo(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Perform wet deposition calculations for air parcels.
int compress_read_lossy_scale(FILE *in, const size_t nz, double **off, double **scl)
Read optional lossyscaling metadata for a 3-D field.
double nat_temperature(const double p, const double h2o, const double hno3)
Calculates the nitric acid trihydrate (NAT) temperature.
void spline(const double *x, const double *y, const int n, const double *x2, double *y2, const int n2, const int method)
Performs spline interpolation or linear interpolation.
void 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 module_sedi(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate sedimentation of particles in the atmosphere.
int read_met_nc(const char *filename, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads meteorological data from a NetCDF file and processes it.
void timer(const char *name, const char *group, const int output)
Measures and reports elapsed time for named and grouped timers.
void write_atm_asc(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes air parcel data to an ASCII file or gnuplot.
void intpol_met_space_3d(const met_t *met, float array[EX][EY][EP], const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables in 3D space.
void module_sort(const ctl_t *ctl, const met_t *met0, atm_t *atm)
Sort particles according to box index.
void module_convection(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Performs convective mixing of atmospheric particles.
void compress_scale_to_unit(float *array, const size_t nxy, const size_t nz, double *off, double *scl)
Scales each vertical level of a 3-D field independently to the interval [0,1].
void read_kernel(const char *filename, double kz[EP], double kw[EP], int *nk)
Reads kernel function data from a file and populates the provided arrays.
void module_bound_cond(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Apply boundary conditions to particles based on meteorological and climatological data.
double scan_ctl(const char *filename, int argc, char *argv[], const char *varname, const int arridx, const char *defvalue, char *value)
Scans a control file or command-line arguments for a specified variable.
void module_advect_init(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Initializes the advection module by setting up pressure fields.
void module_radio_decay(const ctl_t *ctl, const cache_t *cache, atm_t *atm)
Apply radioactive decay to atmospheric tracer species.
void mptrac_get_met(ctl_t *ctl, clim_t *clim, const double t, met_t **met0, met_t **met1, dd_t *dd)
Retrieves meteorological data for the specified time.
void module_sort_help(double *a, const int *p, const int np)
Reorder an array based on a given permutation.
float stddev(const float *data, const int n)
Calculates the standard deviation of a set of data.
void intpol_tropo_3d(const double time0, float array0[EX][EY], const double time1, float array1[EX][EY], const double lons[EX], const double lats[EY], const int nlon, const int nlat, const double time, const double lon, const double lat, const int method, double *var, double *sigma)
Interpolates tropopause data in 3D (latitude, longitude, and time).
void read_met_bin_3d(FILE *in, const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname, const float bound_min, const float bound_max)
Reads 3D meteorological data from a binary file, potentially using different compression methods.
int locate_irr_float(const float *xx, const int n, const double x, const int ig)
Locate the index of the interval containing a given value in an irregularly spaced array.
void write_prof(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes profile data to a specified file.
void mptrac_read_clim(const ctl_t *ctl, clim_t *clim)
Reads various climatological data and populates the given climatology structure.
void 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 compress_write_lossy_scale(FILE *out, const int enabled, float *array, const size_t nxy, const size_t nz, double **off, double **scl)
Write optional lossyscaling metadata for a 3-D field.
void read_met_nc_surface(const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads and processes surface meteorological data from NetCDF files with domain decomposition.
void clim_tropo_init(clim_t *clim)
Initializes the tropopause data in the climatology structure.
void module_rng(const ctl_t *ctl, double *rs, const size_t n, const int method)
Generate random numbers using various methods and distributions.
void write_station(const char *filename, const ctl_t *ctl, atm_t *atm, const double t)
Writes station data to a specified file.
void cart2geo(const double *x, double *z, double *lon, double *lat)
State variables of cuRAND random number generator.
double time_from_filename(const char *filename, const int offset, const int with_seconds)
Extracts and converts a timestamp from a filename to Julian seconds.
void doy2day(const int year, const int doy, int *mon, int *day)
Converts a given day of the year (DOY) to a date (month and day).
void intpol_met_4d_zeta(const met_t *met0, float heights0[EX][EY][EP], float array0[EX][EY][EP], const met_t *met1, float heights1[EX][EY][EP], float array1[EX][EY][EP], const double ts, const double height, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables to a given position and time.
void intpol_met_time_2d(const met_t *met0, float array0[EX][EY], const met_t *met1, float array1[EX][EY], const double ts, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological data in 2D space and time.
void module_position(const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Update the positions and pressure levels of atmospheric particles.
void clim_oh_diurnal_correction(const ctl_t *ctl, clim_t *clim)
Applies a diurnal correction to the hydroxyl radical (OH) concentration in climatology data.
void locate_vert(float profiles[EX][EY][EP], const int np, const int lon_ap_ind, const int lat_ap_ind, const double height_ap, int *ind)
Locate the four vertical indizes of a box for a given height value.
void write_met_bin_2d(FILE *out, met_t *met, float var[EX][EY], const char *varname)
Writes a 2-dimensional meteorological variable to a binary file.
void read_met_pv(met_t *met)
Calculates potential vorticity (PV) from meteorological data.
int read_atm_bin(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a binary file and populates the given atmospheric structure.
void module_diff_meso(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate mesoscale diffusion for atmospheric particles.
double clim_ts(const clim_ts_t *ts, const double t)
Interpolates a time series of climatological variables.
void jsec2time(const double jsec, int *year, int *mon, int *day, int *hour, int *min, int *sec, double *remain)
Converts Julian seconds to calendar date and time components.
int read_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a binary file.
void write_atm_clams(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a NetCDF file in the CLaMS format.
void get_met_replace(char *orig, const char *search, const char *repl)
Replaces occurrences of a substring in a string with another substring.
void module_diff_turb(const ctl_t *ctl, cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Applies turbulent diffusion processes to atmospheric particles.
int read_atm_clams(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads atmospheric data from a CLAMS NetCDF file.
int mptrac_read_met(const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met, dd_t *dd)
Reads meteorological data from a file, supporting multiple formats and MPI broadcasting.
void write_vtk(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes VTK (Visualization Toolkit) data to a specified file.
void module_tracer_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Simulate chemical reactions involving long-lived atmospheric tracers.
void mptrac_read_ctl(const char *filename, int argc, char *argv[], ctl_t *ctl)
Reads control parameters from a configuration file and populates the given structure.
void mptrac_free(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm, dd_t *dd)
Frees memory resources allocated for MPTRAC.
void read_met_polar_winds(met_t *met)
Applies a fix for polar winds in meteorological data.
void module_h2o2_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Perform chemical reactions involving H2O2 within cloud particles.
void write_grid_nc(const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
Writes grid data to a NetCDF file.
double pbl_weight(const ctl_t *ctl, const atm_t *atm, const int ip, const double pbl, const double ps)
Computes a weighting factor based on planetary boundary layer pressure.
void module_diff_pbl(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Computes particle diffusion within the planetary boundary layer (PBL).
void write_met_nc_3d(const int ncid, const char *varname, met_t *met, float var[EX][EY][EP], const float scl)
Writes a 3D meteorological variable to a NetCDF file.
void module_isosurf(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Apply the isosurface module to adjust atmospheric properties.
void module_oh_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Perform hydroxyl chemistry calculations for atmospheric particles.
void geo2cart(const double z, const double lon, const double lat, double *x)
Converts geographic coordinates (longitude, latitude, altitude) to Cartesian coordinates.
void read_met_nc_grid(const char *filename, const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads meteorological grid data from NetCDF files with domain decomposition.
void get_tropo(const int met_tropo, ctl_t *ctl, const clim_t *clim, met_t *met, const double *lons, const int nx, const double *lats, const int ny, double *pt, double *zt, double *tt, double *qt, double *o3t, double *ps, double *zs)
Calculate tropopause data.
double kernel_weight(const double kz[EP], const double kw[EP], const int nk, const double p)
Calculates the kernel weight based on altitude and given kernel data.
void compress_log_level(FILE *out, const char *codec, const char *varname, const size_t lev, const double plev, const double ratio, const double bpv, const double t_comp, const double t_decomp, const size_t n, const size_t nbytes, const float *org, const float *cmp)
Write one row of per-level compression diagnostics.
void compress_unscale_from_unit(float *array, const size_t nxy, const size_t nz, const double *off, const double *scl)
Restores a levelwise [0,1]-scaled 3-D field to physical units.
int read_atm_asc(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from an ASCII file and populates the given atmospheric structure.
void intpol_check_lon_lat(const double *lons, const int nlon, const double *lats, const int nlat, const double lon, const double lat, double *lon2, double *lat2)
Adjusts longitude and latitude to ensure they fall within valid bounds.
void write_sample(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes sample data to a specified file.
void write_grid(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes grid data to a file in ASCII or netCDF format.
void module_dry_depo(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate dry deposition of atmospheric particles.
void write_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data in binary format to a specified file.
void write_atm_bin(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a binary file.
void read_met_cape(const ctl_t *ctl, const clim_t *clim, met_t *met)
Calculates Convective Available Potential Energy (CAPE) for each grid point.
void mptrac_write_met(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a file, supporting multiple formats and compression options.
double tropo_weight(const ctl_t *ctl, const clim_t *clim, const atm_t *atm, const int ip)
Computes a weighting factor based on tropopause pressure.
double lapse_rate(const double t, const double h2o)
Calculates the moist adiabatic lapse rate in Kelvin per kilometer.
void write_csi(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes Critical Success Index (CSI) data to a file.
void write_atm_nc(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a NetCDF file.
MPTRAC library declarations.
#define NN(x0, y0, x1, y1, x)
Perform nearest-neighbor interpolation.
void dd_init(const ctl_t *ctl, dd_t *dd, atm_t *atm)
Initialize the domain decomposition infrastructure.
#define LEN
Maximum length of ASCII data lines.
#define RE
Mean radius of Earth [km].
#define TVIRT(t, h2o)
Compute virtual temperature.
void read_met_grib_surface(codes_handle **handles, const int num_messages, const ctl_t *ctl, met_t *met)
Reads surface meteorological data from a grib file and stores it in the meteorological data structure...
#define ARRAY_3D(ix, iy, ny, iz, nz)
Compute the linear index of a 3D array element.
#define PARTICLE_LOOP(ip0, ip1, check_dt,...)
Loop over particle indices with OpenACC acceleration.
#define MA
Molar mass of dry air [g/mol].
#define AVO
Avogadro constant [1/mol].
#define KB
Boltzmann constant [kg m^2/(K s^2)].
#define COMPRESS_BPV(n, stored_size)
Calculate bits per value from stored size and element count.
#define MH2O
Molar mass of water vapor [g/mol].
#define METVAR
Number of 3-D meteorological variables.
#define NENS
Maximum number of data points for ensemble analysis.
#define FWRITE(ptr, type, size, out)
Write data from memory to a file stream.
#define PW(p, h2o)
Calculate partial water vapor pressure.
#define H0
Scale height [km].
#define NC_PUT_ATT_GLOBAL(attname, text)
Add a global text attribute to a NetCDF file.
#define MOLEC_DENS(p, t)
Calculate the density of a gas molecule.
#define LAPSE(p1, t1, p2, t2)
Calculate lapse rate.
#define NC(cmd)
Execute a NetCDF command and check for errors.
#define SELECT_TIMER(id, group)
Select and start a timer with specific attributes.
#define ECC_READ_3D(variable, level, target, scaling_factor, found_flag)
Writes 3D data from a grib message into the meteo struct.
void compress_zfp(const ctl_t *ctl, const met_t *met, const char *varname, float *array, const int decompress, FILE *level_log, FILE *inout)
Compresses or decompresses a 3D array of floats using the ZFP library.
#define DOTP(a, b)
Calculate the dot product of two vectors.
#define RA
Specific gas constant of dry air [J/(kg K)].
int dd_calc_subdomain_from_coords(const ctl_t *ctl, const dd_t *dd, const double lon, const double lat)
Determine MPI subdomain from particle coordinates.
#define DD_EY_GLOB
Maximum number of latitudes of global meteo data.
#define KARMAN
Karman's constant.
#define INTPOL_INIT
Initialize arrays for interpolation.
#define MIN(a, b)
Macro to determine the minimum of two values.
#define ERRMSG(...)
Print an error message with contextual information and terminate the program.
#define NC_PUT_INT(varname, ptr, hyperslab)
Write integer data to a NetCDF variable.
#define EY
Maximum number of latitudes for meteo data.
#define SH(h2o)
Compute specific humidity from water vapor volume mixing ratio.
void compress_sz3(const ctl_t *ctl, const met_t *met, const char *varname, float *array, const int decompress, FILE *level_log, FILE *inout)
Compresses or decompresses a 3-D float array using the SZ3 library.
#define INTPOL_3D(var, init)
Perform 3D interpolation for a meteorological variable.
#define CLAMP(v, lo, hi)
Clamp a value to a specified range.
#define NOBS
Maximum number of observation data points.
#define NTHREADS
Maximum number of OpenMP threads.
#define ARRAY_2D(ix, iy, ny)
Macro for computing the linear index of a 2D array element.
#define Z(p)
Convert pressure to altitude.
#define codes_handle
Placeholder when ECCODES is not available.
void compress_zstd(const ctl_t *ctl, const met_t *met, const char *varname, float *array, const int decompress, FILE *level_log, FILE *inout)
Compresses or decompresses a float array using ZSTD.
#define P(z)
Compute pressure at given altitude.
#define LV
Latent heat of vaporization of water [J/kg].
#define G0
Standard gravity [m/s^2].
void compress_cms(const ctl_t *ctl, const met_t *met, const char *varname, float *array, const int decompress, FILE *level_log, FILE *inout)
Compresses or decompresses a 3-D meteorological field using cmultiscale.
#define CP
Maximum number of pressure levels for climatological data.
#define NQ
Maximum number of quantities per data point.
void dd_assign_subdomains(const ctl_t *ctl, const dd_t *dd, atm_t *atm, const int init)
Assign or update particle subdomain ownership.
#define FREAD(ptr, type, size, in)
Read data from a file stream and store it in memory.
#define DX2DEG(dx, lat)
Convert a distance in kilometers to degrees longitude at a given latitude.
#define DEG2DY(dlat)
Convert a latitude difference to a distance in the y-direction (north-south).
#define EX
Maximum number of longitudes for meteo data.
#define EPS
Ratio of the specific gas constant of dry air and water vapor [1].
#define PSICE(t)
Compute saturation pressure over ice (WMO, 2018).
#define DX2COORD(met, dx, lat)
Convert a distance in meters to a coordinate value based on grid type.
#define COMPRESS_RATIO(raw_size, stored_size)
Calculate the compression ratio from raw and stored byte counts.
#define THETA(p, t)
Compute potential temperature.
void dd_normalize_lon_lat(const dd_t *dd, double *lon, double *lat)
Normalize geographic coordinates to the global grid convention.
#define RI
Ideal gas constant [J/(mol K)].
int read_met_grib(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a grib file and processes it.
#define SET_QNT(qnt, name, longname, unit)
Set atmospheric quantity index.
void dd_sort(const ctl_t *ctl, const met_t *met0, atm_t *atm, dd_t *dd, int *npart)
Sort local atmospheric particles and determine export counts for domain decomposition.
void dd_particles2atm(const ctl_t *ctl, cache_t *cache, const particle_t *particles, const int npart, atm_t *atm)
Copy received particles from the communication buffer into the atmospheric state.
#define TICE(p, h2o)
Calculate frost point temperature (WMO, 2018).
void compress_lz4(const ctl_t *ctl, const met_t *met, const char *varname, float *array, const int decompress, FILE *level_log, FILE *inout)
Compresses or decompresses a float array using LZ4.
#define TOK(line, tok, format, var)
Get string tokens.
#define ZDIFF(lnp0, t0, h2o0, lnp1, t1, h2o1)
Calculate geopotential height difference.
#define THETAVIRT(p, t, h2o)
Compute virtual potential temperature.
#define DZ2DP(dz, p)
Convert a change in altitude to a change in pressure.
#define WARN(...)
Print a warning message with contextual information.
#define ZETA(ps, p, t)
Computes the value of the zeta vertical coordinate.
#define RHICE(p, t, h2o)
Compute relative humidity over ice.
#define INTPOL_TIME_ALL(time, p, lon, lat)
Interpolate multiple meteorological variables in time.
#define ALLOC(ptr, type, n)
Allocate memory for a pointer with error handling.
void read_met_grib_levels(codes_handle **handles, const int num_messages, const ctl_t *ctl, met_t *met)
Reads meteorological variables at different vertical levels from a grib file.
#define SET_ATM(qnt, val)
Set atmospheric quantity value.
#define CTS
Maximum number of data points of climatological time series.
#define ECC_READ_2D(variable, target, scaling_factor, found_flag)
Writes 2-D data from a grib message into the meteo struct.
#define DEG2RAD(deg)
Converts degrees to radians.
void broadcast_large_data(void *data, size_t N)
Broadcasts large data across all processes in an MPI communicator.
#define MO3
Molar mass of ozone [g/mol].
#define SQR(x)
Compute the square of a value.
#define RAD2DEG(rad)
Converts radians to degrees.
void dd_atm2particles(const ctl_t *ctl, cache_t *cache, atm_t *atm, particle_t *particles, const int npart)
Copy migratable atmospheric particles from the ATM state into a particle buffer.
#define NP
Maximum number of atmospheric data points.
#define NTIMER
Maximum number of timers.
#define COMPRESS_SPEED(nbytes, dt)
Calculate compression throughput in MiB/s.
void dd_communicate_particles(const ctl_t *ctl, const dd_t *dd, particle_t **particles, int *npart, int *capacity)
Exchange particles between MPI ranks according to their destination rank.
#define INTPOL_2D(var, init)
Perform 2D interpolation for a meteorological variable.
#define RH(p, t, h2o)
Compute relative humidity over water.
#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.
void module_dd(double t, const ctl_t *ctl, cache_t *cache, dd_t *dd, atm_t *atm, met_t **met)
Perform domain decomposition and exchange particles between MPI ranks.
#define NC_PUT_DOUBLE(varname, ptr, hyperslab)
Write double precision data to a NetCDF variable.
#define ECC(cmd)
Execute an ECCODES command and check for errors.
#define LIN(x0, y0, x1, y1, x)
Linear interpolation.
#define DIST2(a, b)
Calculate the squared Euclidean distance between two points in Cartesian coordinates.
#define NC_INQ_DIM(dimname, ptr, min, max, check)
Inquire the length of a dimension in a NetCDF file.
#define DEG2DX(dlon, lat)
Convert a longitude difference to a distance in the x-direction (east-west) at a specific latitude.
#define DY2COORD(met, dy)
Convert a distance to coordinate value based on grid type.
#define CPD
Specific heat of dry air at constant pressure [J/(kg K)].
#define CSZA
Maximum number of solar zenith angles for climatological data.
#define DY2DEG(dy)
Convert a distance in kilometers to degrees latitude.
void dd_push(const ctl_t *ctl, atm_t *atm, cache_t *cache, int *npart)
Compact and stage non-local particles for domain decomposition transfer.
#define MAX(a, b)
Macro to determine the maximum of two values.
#define FMOD(x, y)
Calculate the floating-point remainder of dividing x by y.
double lat[NP]
Latitude [deg].
double lon[NP]
Longitude [deg].
int np
Number of air parcels.
double q[NQ][NP]
Quantity data (for various, user-defined attributes).
double p[NP]
Pressure [hPa].
double dt[NP]
Timesteps [s].
double iso_ts[NP]
Isosurface balloon time [s].
int iso_n
Isosurface balloon number of data points.
double iso_ps[NP]
Isosurface balloon pressure [hPa].
double rs[3 *NP+1]
Random numbers.
float uvwp[NP][3]
Wind perturbations [m/s].
double iso_var[NP]
Isosurface variables.
Climatological data in the form of photolysis rates.
int nsza
Number of solar zenith angles.
double sza[CSZA]
Solar zenith angle [rad].
double o3_1[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O1d + O2) [1/s].
double p[CP]
Pressure [hPa].
double ccl2f2[CP][CSZA][CO3]
CCl2F2 photolysis rate [1/s].
double o2[CP][CSZA][CO3]
O2 photolysis rate [1/s].
double ccl3f[CP][CSZA][CO3]
CCl3F photolysis rate [1/s].
double n2o[CP][CSZA][CO3]
N2O photolysis rate [1/s].
double h2o2[CP][CSZA][CO3]
H2O2 photolysis rate [1/s].
double h2o[CP][CSZA][CO3]
H2O photolysis rate [1/s].
double ccl4[CP][CSZA][CO3]
CCl4 photolysis rate [1/s].
double o3_2[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O3p + O2) [1/s].
double o3c[CO3]
Total column ozone [DU].
int np
Number of pressure levels.
int no3c
Number of total ozone columns.
clim_ts_t ccl2f2
CFC-12 time series.
clim_photo_t photo
Photolysis rates.
clim_zm_t ho2
HO2 zonal means.
clim_zm_t hno3
HNO3 zonal means.
int tropo_ntime
Number of tropopause timesteps.
clim_ts_t sf6
SF6 time series.
clim_ts_t ccl4
CFC-10 time series.
clim_ts_t ccl3f
CFC-11 time series.
clim_zm_t o1d
O(1D) zonal means.
double tropo_lat[73]
Tropopause latitudes [deg].
clim_zm_t h2o2
H2O2 zonal means.
int tropo_nlat
Number of tropopause latitudes.
clim_zm_t oh
OH zonal means.
double tropo[12][73]
Tropopause pressure values [hPa].
double tropo_time[12]
Tropopause time steps [s].
clim_ts_t n2o
N2O time series.
Climatological data in the form of time series.
double vmr[CTS]
Volume mixing ratio [ppv].
double time[CTS]
Time [s].
int ntime
Number of timesteps.
Climatological data in the form of zonal means.
int np
Number of pressure levels.
double p[CP]
Pressure [hPa].
double vmr[CT][CP][CY]
Volume mixing ratio [ppv].
int ntime
Number of timesteps.
int nlat
Number of latitudes.
double lat[CY]
Latitude [deg].
double met_utm_ref_lon
Reference longitude [deg] for UTM grid.
double grid_z0
Lower altitude of gridded data [km].
int qnt_o3
Quantity array index for ozone volume mixing ratio.
double csi_lat1
Upper latitude of gridded CSI data [deg].
char csi_obsfile[LEN]
Observation data file for CSI analysis.
int qnt_Coh
Quantity array index for OH volume mixing ratio (chemistry code).
double wet_depo_ic_a
Coefficient A for wet deposition in cloud (exponential form).
int qnt_target_subdomain
Quantity array index for destination subdomain in domain decomposition.
int met_nc_scale
Check netCDF scaling factors (0=no, 1=yes).
int qnt_pel
Quantity array index for pressure at equilibrium level (EL).
int csi_nz
Number of altitudes of gridded CSI data.
double molmass
Molar mass [g/mol].
int qnt_p
Quantity array index for pressure.
int qnt_Cccl2f2
Quantity array index for CFC-12 volume mixing ratio (chemistry code).
int dd_halos_size
Domain decomposition size of halos given in grid-points.
char atm_gpfile[LEN]
Gnuplot file for atmospheric data.
int mixing_nx
Number of longitudes of mixing grid.
int met_zstd_nworkers
ZSTD number of worker threads (0=single-threaded, default=4).
double chemgrid_z1
Upper altitude of chemistry grid [km].
char qnt_format[NQ][LEN]
Quantity output format.
int qnt_m
Quantity array index for mass.
int qnt_aoa
Quantity array index for age of air.
int qnt_rhop
Quantity array index for particle density.
int qnt_swc
Quantity array index for cloud snow water content.
double csi_obsmin
Minimum observation index to trigger detection.
int qnt_pcb
Quantity array index for cloud bottom pressure.
char clim_n2o_timeseries[LEN]
Filename of N2O time series.
double bound_dzs
Boundary conditions surface layer depth [km].
double csi_lon1
Upper longitude of gridded CSI data [deg].
int qnt_u
Quantity array index for zonal wind.
double stat_lon
Longitude of station [deg].
double mixing_trop
Interparcel exchange parameter for mixing in the troposphere.
double sort_dt
Time step for sorting of particle data [s].
double mixing_z1
Upper altitude of mixing grid [km].
double stat_r
Search radius around station [km].
double wet_depo_bc_a
Coefficient A for wet deposition below cloud (exponential form).
int met_zstd_level
ZSTD compression level (from -5 to 22, default=-3).
double met_utm_ref_lat
Reference latitude [deg] for UTM grid.
int csi_ny
Number of latitudes of gridded CSI data.
int vtk_sphere
Spherical projection for VTK data (0=no, 1=yes).
double chemgrid_z0
Lower altitude of chemistry grid [km].
double met_pbl_min
Minimum depth of planetary boundary layer [km].
int qnt_iwc
Quantity array index for cloud ice water content.
double chemgrid_lat0
Lower latitude of chemistry grid [deg].
double conv_cape
CAPE threshold for convection module [J/kg].
int qnt_Co1d
Quantity array index for O(1D) volume mixing ratio (chemistry code).
int qnt_pw
Quantity array index for partial water vapor pressure.
char prof_basename[LEN]
Basename for profile output file.
double grid_z1
Upper altitude of gridded data [km].
int direction
Direction flag (1=forward calculation, -1=backward calculation).
char balloon[LEN]
Balloon position filename.
int qnt_Cccl4
Quantity array index for CFC-10 volume mixing ratio (chemistry code).
int met_dp
Stride for pressure levels.
double met_dt_out
Time step for sampling of meteo data along trajectories [s].
int qnt_h2o2
Quantity array index for H2O2 volume mixing ratio (climatology).
int qnt_vh
Quantity array index for horizontal wind.
char species[LEN]
Species.
int csi_nx
Number of longitudes of gridded CSI data.
double csi_lat0
Lower latitude of gridded CSI data [deg].
double turb_dz_trop
Vertical turbulent diffusion coefficient (troposphere) [m^2/s].
int met_pbl
Planetary boundary layer data (0=file, 1=z2p, 2=Richardson, 3=theta).
int qnt_lwc
Quantity array index for cloud liquid water content.
double turb_mesoz
Vertical scaling factor for mesoscale wind fluctuations.
int grid_nc_level
zlib compression level of netCDF grid data files (0=off).
int grid_nx
Number of longitudes of gridded data.
int atm_type
Type of atmospheric data files (0=ASCII, 1=binary, 2=netCDF, 3=CLaMS_traj, 4=CLaMS_pos).
double bound_mass
Boundary conditions mass per particle [kg].
double grid_lat0
Lower latitude of gridded data [deg].
int qnt_ts
Quantity array index for surface temperature.
int qnt_loss_rate
Quantity array index for total loss rate.
int qnt_plfc
Quantity array index for pressure at level of free convection (LCF).
int qnt_Acs137
Quantity array index for radioactive activity of Cs-137.
double grid_lon0
Lower longitude of gridded data [deg].
int qnt_o1d
Quantity array index for O(1D) volume mixing ratio (climatology).
int met_tropo_spline
Tropopause interpolation method (0=linear, 1=spline).
char sample_kernel[LEN]
Kernel data file for sample output.
int qnt_tvirt
Quantity array index for virtual temperature.
double dt_met
Time step of meteo data [s].
char clim_ho2_filename[LEN]
Filename of HO2 climatology.
double chemgrid_lat1
Upper latitude of chemistry grid [deg].
int met_geopot_sy
Latitudinal smoothing of geopotential heights.
char grid_gpfile[LEN]
Gnuplot file for gridded data.
double turb_dx_strat
Horizontal turbulent diffusion coefficient (stratosphere) [m^2/s].
int qnt_vmr
Quantity array index for volume mixing ratio.
int qnt_lsm
Quantity array index for land-sea mask.
int qnt_theta
Quantity array index for potential temperature.
double bound_lat1
Boundary conditions maximum longitude [deg].
double stat_t1
Stop time for station output [s].
char csi_kernel[LEN]
Kernel data file for CSI output.
double turb_dx_trop
Horizontal turbulent diffusion coefficient (troposphere) [m^2/s].
int grid_type
Type of grid data files (0=ASCII, 1=netCDF).
double csi_lon0
Lower longitude of gridded CSI data [deg].
int qnt_pbl
Quantity array index for boundary layer pressure.
double oh_chem[4]
Coefficients for OH reaction rate (A, E/R or k0, n, kinf, m).
int grid_stddev
Include standard deviations in grid output (0=no, 1=yes).
int qnt_psice
Quantity array index for saturation pressure over ice.
double chemgrid_lon0
Lower longitude of chemistry grid [deg].
int bound_pbl
Boundary conditions planetary boundary layer (0=no, 1=yes).
int qnt_mloss_wet
Quantity array index for total mass loss due to wet deposition.
int radio_decay
Switch for radioactive decay module (0=off, 1=on).
int met_geopot_sx
Longitudinal smoothing of geopotential heights.
int met_sy
Smoothing for latitudes.
int qnt_ps
Quantity array index for surface pressure.
int rng_type
Random number generator (0=GSL, 1=Squares, 2=cuRAND).
char prof_obsfile[LEN]
Observation data file for profile output.
int met_pck_zstd
Apply an additional ZSTD compression step to PCK payloads (0=off, 1=on).
int isosurf
Isosurface parameter (0=none, 1=pressure, 2=density, 3=theta, 4=balloon).
double bound_p1
Boundary conditions top pressure [hPa].
int qnt_zs
Quantity array index for surface geopotential height.
int prof_nz
Number of altitudes of gridded profile data.
double csi_dt_out
Time step for CSI output [s].
int met_cape
Convective available potential energy data (0=file, 1=calculate).
double csi_modmin
Minimum column density to trigger detection [kg/m^2].
int met_sx
Smoothing for longitudes.
double chemgrid_lon1
Upper longitude of chemistry grid [deg].
double turb_mesox
Horizontal scaling factor for mesoscale wind fluctuations.
char grid_kernel[LEN]
Kernel data file for grid output.
double prof_z0
Lower altitude of gridded profile data [km].
int qnt_w
Quantity array index for vertical velocity.
double bound_vmr
Boundary conditions volume mixing ratio [ppv].
double met_tropo_pv
Dynamical tropopause potential vorticity threshold [PVU].
int prof_nx
Number of longitudes of gridded profile data.
int qnt_stat
Quantity array index for station flag.
double dd_sort_dt
Sorting time interval for the compactification.
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.
int met_gp2z
Convert surface geopotential to geopotential height (0=no, 1=yes).
double bound_lat0
Boundary conditions minimum longitude [deg].
double met_pbl_max
Maximum depth of planetary boundary layer [km].
int met_dx
Stride for longitudes.
int mixing_ny
Number of latitudes of mixing grid.
int met_convention
Meteo data layout (0=[lev, lat, lon], 1=[lon, lat, lev]).
int qnt_zeta_d
Quantity array index for diagnosed zeta vertical coordinate.
char clim_h2o2_filename[LEN]
Filename of H2O2 climatology.
int tracer_chem
Switch for first order tracer chemistry module (0=off, 1=on).
double dt_mod
Time step of simulation [s].
int diffusion
Diffusion switch (0=off, 1=on).
int qnt_tnat
Quantity array index for T_NAT.
int qnt_eta_dot
Quantity array index for velocity of eta vertical coordinate.
int qnt_tice
Quantity array index for T_ice.
int turb_pbl_scheme
PBL turbulence scheme (0=none, 1=closure).
int qnt_zg
Quantity array index for geopotential height.
double vtk_offset
Vertical offset for VTK data [km].
int qnt_v
Quantity array index for meridional wind.
int qnt_mloss_dry
Quantity array index for total mass loss due to dry deposition.
double bound_vmr_trend
Boundary conditions volume mixing ratio trend [ppv/s].
double met_zfp_tol[METVAR]
ZFP compression tolerance.
int met_cache
Preload meteo data into disk cache (0=no, 1=yes).
int qnt_oh
Quantity array index for OH volume mixing ratio (climatology).
int met_sz3_prec[METVAR]
SZ3 compression precision.
char qnt_unit[NQ][LEN]
Quantity units.
int qnt_Ch
Quantity array index for H volume mixing ratio (chemistry code).
int met_press_level_def
Use predefined pressure levels or not.
int oh_chem_reaction
Reaction type for OH chemistry (0=none, 2=bimolecular, 3=termolecular).
int qnt_h2o
Quantity array index for water vapor volume mixing ratio.
int prof_ny
Number of latitudes of gridded profile data.
int qnt_rhice
Quantity array index for relative humidity over ice.
int qnt_rho
Quantity array index for density of air.
double sample_dz
Layer depth for sample output [km].
double tdec_strat
Life time of particles in the stratosphere [s].
int obs_type
Type of observation data files (0=ASCII, 1=netCDF).
int grid_nc_quant[NQ]
Number of digits for quantization of netCDF grid data files (0=off).
int qnt_us
Quantity array index for surface zonal wind.
double grid_lon1
Upper longitude of gridded data [deg].
int qnt_Cn2o
Quantity array index for N2O volume mixing ratio (chemistry code).
int qnt_Cccl3f
Quantity array index for CFC-11 volume mixing ratio (chemistry code).
char qnt_name[NQ][LEN]
Quantity names.
char atm_basename[LEN]
Basename of atmospheric data files.
double mixing_lat0
Lower latitude of mixing grid [deg].
int nens
Number of ensembles.
int qnt_pt
Quantity array index for tropopause pressure.
int qnt_cl
Quantity array index for total column cloud water.
int advect
Advection scheme (1=Euler, 2=midpoint, 4=Runge-Kutta).
double prof_z1
Upper altitude of gridded profile data [km].
double met_lev_hyam[EP]
Meteo data model level a coefficients.
int qnt_t
Quantity array index for temperature.
int atm_filter
Time filter for atmospheric data output (0=none, 1=missval, 2=remove).
int kpp_chem
Switch for KPP chemistry module (0=off, 1=on).
int qnt_zeta
Quantity array index for zeta vertical coordinate.
double conv_pbl_trans
Depth of PBL transition layer (fraction of PBL pressure thickness).
int met_lz4_accel
LZ4 acceleration factor (>=1, default=8).
char ens_basename[LEN]
Basename of ensemble data file.
int qnt_Ai131
Quantity array index for radioactive activity of I-131.
double wet_depo_pre[2]
Coefficients for precipitation calculation.
int met_vert_coord
Vertical coordinate of input meteo data (0=plev, 1=mlev_p_file, 2=mlev_ab_file, 3=mlev_ab_full,...
double csi_z0
Lower altitude of gridded CSI data [km].
int qnt_lapse
Quantity array index for lapse rate.
int qnt_Apb210
Quantity array index for radioactive activity of Pb-210.
double stat_lat
Latitude of station [deg].
int qnt_Cho2
Quantity array index for HO2 volume mixing ratio (chemistry code).
double wet_depo_bc_h[2]
Coefficients for wet deposition below cloud (Henry's law: Hb, Cb).
int grid_ny
Number of latitudes of gridded data.
int qnt_Csf6
Quantity array index for SF6 volume mixing ratio (chemistry code).
int qnt_Ch2o
Quantity array index for H2O volume mixing ratio (chemistry code).
double met_detrend
FWHM of horizontal Gaussian used for detrending [km].
int conv_mix_pbl
Vertical mixing in the PBL (0=off, 1=on).
char metbase[LEN]
Basename for meteo data.
double bound_dps
Boundary conditions surface layer depth [hPa].
double met_cms_eps[METVAR]
cmultiscale compression epsilon.
int chemgrid_nz
Number of altitudes of chemistry grid.
int qnt_cape
Quantity array index for convective available potential energy (CAPE).
int qnt_zeta_dot
Quantity array index for velocity of zeta vertical coordinate.
double bound_mass_trend
Boundary conditions mass per particle trend [kg/s].
int met_cms_nd0y
cmultiscale number of cells of coarsest grid in y-direction.
int mixing_nz
Number of altitudes of mixing grid.
int qnt_o3c
Quantity array index for total column ozone.
double bound_p0
Boundary conditions bottom pressure [hPa].
double mixing_lon0
Lower longitude of mixing grid [deg].
char clim_ccl4_timeseries[LEN]
Filename of CFC-10 time series.
int qnt_Co3
Quantity array index for O3 volume mixing ratio (chemistry code).
int qnt_tsts
Quantity array index for T_STS.
int grid_nz
Number of altitudes of gridded data.
char clim_oh_filename[LEN]
Filename of OH climatology.
int qnt_nss
Quantity array index for northward turbulent surface stress.
double ens_dt_out
Time step for ensemble output [s].
char sample_basename[LEN]
Basename of sample data file.
int atm_stride
Particle index stride for atmospheric data files.
int met_relhum
Try to read relative humidity (0=no, 1=yes).
double mixing_lat1
Upper latitude of mixing grid [deg].
double atm_dt_out
Time step for atmospheric data output [s].
char clim_sf6_timeseries[LEN]
Filename of SF6 time series.
int met_lossy_scale[METVAR]
Apply levelwise [0,1] scaling before lossy compression (0=off, 1=on).
double prof_lat1
Upper latitude of gridded profile data [deg].
int qnt_current_subdomain
Quantity array index for current subdomain in domain decomposition.
int met_cms_batch
cmultiscale batch size.
double psc_h2o
H2O volume mixing ratio for PSC analysis.
int met_sp
Smoothing for pressure levels.
double prof_lon0
Lower longitude of gridded profile data [deg].
int qnt_Axe133
Quantity array index for radioactive activity of Xe-133.
int chemgrid_nx
Number of longitudes of chemistry grid.
int qnt_pct
Quantity array index for cloud top pressure.
int qnt_mloss_kpp
Quantity array index for total mass loss due to KPP chemistry.
int qnt_psat
Quantity array index for saturation pressure over water.
double met_lev_hybm[EP]
Meteo data model level b coefficients.
double prof_lat0
Lower latitude of gridded profile data [deg].
int qnt_cin
Quantity array index for convective inhibition (CIN).
double turb_pbl_trans
Depth of turbulent PBL transition layer (fraction of PBL pressure thickness).
double psc_hno3
HNO3 volume mixing ratio for PSC analysis.
double prof_lon1
Upper longitude of gridded profile data [deg].
int met_nc_quant
Number of digits for quantization of netCDF meteo files (0=off).
int h2o2_chem_reaction
Reaction type for H2O2 chemistry (0=none, 1=SO2).
int qnt_Co3p
Quantity array index for O(3P) volume mixing ratio (chemistry code).
int atm_nc_quant[NQ]
Number of digits for quantization of netCDF atmospheric data files (0=off).
double wet_depo_bc_ret_ratio
Coefficients for wet deposition below cloud: retention ratio.
int chemgrid_ny
Number of latitudes of chemistry grid.
int qnt_Abe7
Quantity array index for radioactive activity of Be-7.
char clim_ccl3f_timeseries[LEN]
Filename of CFC-11 time series.
int met_cms_zstd
cmultiscale ZSTD compression (0=off, 1=on).
int met_cms_maxlev
cmultiscale maximum refinement level.
int grid_sparse
Sparse output in grid data files (0=no, 1=yes).
double met_sz3_tol[METVAR]
SZ3 compression tolerance.
char vtk_basename[LEN]
Basename of VTK data files.
double dry_depo_vdep
Dry deposition velocity [m/s].
int qnt_tt
Quantity array index for tropopause temperature.
int met_np
Number of target pressure levels.
int qnt_ens
Quantity array index for ensemble IDs.
int met_nc_level
zlib compression level of netCDF meteo files (0=off).
double mixing_dt
Time interval for mixing [s].
int qnt_Arn222
Quantity array index for radioactive activity of Rn-222.
int qnt_mloss_h2o2
Quantity array index for total mass loss due to H2O2 chemistry.
double vtk_scale
Vertical scaling factor for VTK data.
char clim_ccl2f2_timeseries[LEN]
Filename of CFC-12 time series.
double wet_depo_ic_h[2]
Coefficients for wet deposition in cloud (Henry's law: Hb, Cb).
double turb_dx_pbl
Horizontal turbulent diffusion coefficient (PBL) [m^2/s].
double conv_cin
CIN threshold for convection module [J/kg].
int qnt_pv
Quantity array index for potential vorticity.
int advect_vert_coord
Vertical velocity of air parcels (0=omega_on_plev, 1=zetadot_on_mlev, 2=omega_on_mlev,...
int qnt_mloss_oh
Quantity array index for total mass loss due to OH chemistry.
int qnt_Ch2o2
Quantity array index for H2O2 volume mixing ratio (chemistry code).
int qnt_sst
Quantity array index for sea surface temperature.
double mixing_lon1
Upper longitude of mixing grid [deg].
int atm_nc_level
zlib compression level of netCDF atmospheric data files (0=off).
char clim_hno3_filename[LEN]
Filename of HNO3 climatology.
double wet_depo_ic_ret_ratio
Coefficients for wet deposition in cloud: retention ratio.
int qnt_sh
Quantity array index for specific humidity.
int met_coord_type
Type of coordinates for meteo data (-1=detect, 0=lat/lon [deg], 1=UTM [m]).
int qnt_ess
Quantity array index for eastward turbulent surface stress.
double wet_depo_ic_b
Coefficient B for wet deposition in cloud (exponential form).
double wet_depo_bc_b
Coefficient B for wet deposition below cloud (exponential form).
int met_dy
Stride for latitudes.
int qnt_Cx
Quantity array index for trace species x volume mixing ratio (chemistry code).
double turb_dz_strat
Vertical turbulent diffusion coefficient (stratosphere) [m^2/s].
double bound_zetas
Boundary conditions surface layer zeta [K].
int dd_subdomains_zonal
Domain decomposition zonal subdomain number.
int qnt_idx
Quantity array index for air parcel IDs.
double met_tropo_theta
Dynamical tropopause potential temperature threshold [K].
int qnt_rwc
Quantity array index for cloud rain water content.
double t_start
Start time of simulation [s].
char qnt_longname[NQ][LEN]
Quantity long names.
double met_p[EP]
Target pressure levels [hPa].
int nq
Number of quantities.
double tdec_trop
Life time of particles in the troposphere [s].
int met_zfp_prec[METVAR]
ZFP compression precision.
double sample_dx
Horizontal radius for sample output [km].
int vtk_stride
Particle index stride for VTK data.
char stat_basename[LEN]
Basename of station data file.
double turb_dz_pbl
Vertical turbulent diffusion coefficient (PBL) [m^2/s].
double grid_lat1
Upper latitude of gridded data [deg].
int dd_subdomains_meridional
Domain decomposition meridional subdomain number.
int qnt_zt
Quantity array index for tropopause geopotential height.
int met_type
Type of meteo data files (0=netCDF, 1=binary, 2=pck, 3=ZFP, 4=ZSTD, 5=cms, 6=grib,...
int qnt_cc
Quantity array index for cloud cover.
int qnt_plcl
Quantity array index for pressure at lifted condensation level (LCL).
double grid_dt_out
Time step for gridded data output [s].
int qnt_tdew
Quantity array index for dew point temperature.
Domain decomposition data structure.
size_t halo_bnd_count[4]
Extent of the periodic boundary halo hyperslab.
int halo_offset_end
Offset of the periodic halo block at the end of the local x-array.
int nx_glob
Number of global longitudes.
size_t halo_bnd_start[4]
Start indices of the periodic boundary halo hyperslab.
double lon_glob[DD_EX_GLOB]
Longitudes of the global grid [deg].
double lat_glob[DD_EY_GLOB]
Latitudes of the global grid [deg].
int halo_offset_start
Offset of the periodic halo block at the beginning of the local x-array.
size_t subdomain_count[4]
Extent of the local subdomain hyperslab (including inner halos).
int ny_glob
Number of global latitudes.
size_t subdomain_start[4]
Start indices of the local subdomain hyperslab (including inner halos).
float zt[EX][EY]
Tropopause geopotential height [km].
float sst[EX][EY]
Sea surface temperature [K].
float rwc[EX][EY][EP]
Cloud rain water content [kg/kg].
float o3c[EX][EY]
Total column ozone [DU].
float zeta_dotl[EX][EY][EP]
Vertical velocity on model levels [K/s].
float h2o[EX][EY][EP]
Water vapor volume mixing ratio [1].
float cape[EX][EY]
Convective available potential energy [J/kg].
float w[EX][EY][EP]
Vertical velocity [hPa/s].
float pct[EX][EY]
Cloud top pressure [hPa].
double hybrid[EP]
Model hybrid levels.
int nx
Number of longitudes.
int ny
Number of latitudes.
float shf[EX][EY]
Surface sensible heat flux [W/m^2].
float ps[EX][EY]
Surface pressure [hPa].
float lwc[EX][EY][EP]
Cloud liquid water content [kg/kg].
float us[EX][EY]
Surface zonal wind [m/s].
float wl[EX][EY][EP]
Vertical velocity on model levels [hPa/s].
float vl[EX][EY][EP]
Meridional wind on model levels [m/s].
float zs[EX][EY]
Surface geopotential height [km].
float o3[EX][EY][EP]
Ozone volume mixing ratio [1].
float cc[EX][EY][EP]
Cloud cover [1].
int np
Number of pressure levels.
float t[EX][EY][EP]
Temperature [K].
float ts[EX][EY]
Surface temperature [K].
float u[EX][EY][EP]
Zonal wind [m/s].
float ess[EX][EY]
Eastward turbulent surface stress [N/m^2].
float ul[EX][EY][EP]
Zonal wind on model levels [m/s].
float pcb[EX][EY]
Cloud bottom pressure [hPa].
float pel[EX][EY]
Pressure at equilibrium level (EL) [hPa].
float cin[EX][EY]
Convective inhibition [J/kg].
float plcl[EX][EY]
Pressure at lifted condensation level (LCL) [hPa].
double lon[EX]
Longitudes [deg].
float pt[EX][EY]
Tropopause pressure [hPa].
float tt[EX][EY]
Tropopause temperature [K].
float pbl[EX][EY]
Boundary layer pressure [hPa].
float vs[EX][EY]
Surface meridional wind [m/s].
float z[EX][EY][EP]
Geopotential height [km].
float v[EX][EY][EP]
Meridional wind [m/s].
int npl
Number of model levels.
float lsm[EX][EY]
Land-sea mask [1].
float iwc[EX][EY][EP]
Cloud ice water content [kg/kg].
float h2ot[EX][EY]
Tropopause water vapor volume mixing ratio [ppv].
float pv[EX][EY][EP]
Potential vorticity [PVU].
double eta[EP]
Model level eta values.
float cl[EX][EY]
Total column cloud water [kg/m^2].
float nss[EX][EY]
Northward turbulent surface stress [N/m^2].
float pl[EX][EY][EP]
Pressure on model levels [hPa].
float plfc[EX][EY]
Pressure at level of free convection (LFC) [hPa].
double hyam[EP]
Model level a coefficients [Pa].
double lat[EY]
Latitudes [deg].
float swc[EX][EY][EP]
Cloud snow water content [kg/kg].
double hybm[EP]
Model level b coefficients.
float zetal[EX][EY][EP]
Zeta on model levels [K].
double p[EP]
Pressure levels [hPa].
double lat
Latitude [deg].
double lon
Longitude [deg].
double q[NQ]
Quantity data (for various, user-defined attributes).