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++) {
3958 const double zpart =
Z(atm->
p[ip]);
3959 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
3964 || zpart < ctl->chemgrid_z0 || zpart >= ctl->
chemgrid_z1) {
3970 izs[ip] = (int) ((zpart - ctl->
chemgrid_z0) / dz);
3971 if (ixs[ip] >= nx || iys[ip] >= ny || izs[ip] >= nz)
3977#pragma acc parallel loop independent gang vector
3979#pragma omp parallel for default(shared)
3981 for (
int ix = 0; ix < nx; ix++)
3985#pragma acc parallel loop independent gang vector
3987#pragma omp parallel for default(shared)
3989 for (
int iy = 0; iy < ny; iy++) {
3991 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
3996#pragma acc parallel loop independent gang vector
3998 for (
int ip = 0; ip < np; ip++) {
4000 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
4001 if (ensemble_mode) {
4002 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
4003 mass_idx += ens * ngrid;
4006#pragma acc atomic update
4008 mass[mass_idx] += atm->
q[ctl->
qnt_m][ip];
4014#pragma acc parallel loop independent gang vector
4016#pragma omp parallel for default(shared)
4018 for (
int ip = 0; ip < np; ip++)
4026 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
4029 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
4030 if (ensemble_mode) {
4031 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
4032 mass_idx += ens * ngrid;
4036 const double m = mass[mass_idx];
4038 / (
RHO(press[izs[ip]], temp) * area[iys[ip]] * dz * 1e9);
4043#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
4071 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4087 const double lat_ref =
4090 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
4092 lat_ref, atm->
p[ip]));
4094 lat_ref, atm->
p[ip]));
4096 lat_ref, atm->
p[ip]));
4116 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4124 double pbot = ps, ptop = ps;
4141 double cape, cin, pel;
4147 if (isfinite(cape) && cape >= ctl->
conv_cape
4149 ptop = GSL_MIN(ptop, pel);
4153 if (ptop != pbot && atm->
p[ip] >= ptop) {
4158 pbot, atm->
lon[ip], atm->
lat[ip], &tbot, ci, cw, 1);
4160 atm->
lon[ip], atm->
lat[ip], &ttop, ci, cw, 1);
4161 const double rhobot = pbot / tbot;
4162 const double rhotop = ptop / ttop;
4165 const double rho = rhobot + (rhotop - rhobot) * cache->
rs[ip];
4168 atm->
p[ip] =
LIN(rhobot, pbot, rhotop, ptop, rho);
4185 int npart = 0, capacity = 0;
4193 dd_sort(ctl, *met, atm, dd, &npart);
4195 dd_push(ctl, atm, cache, &npart);
4198 if (npart > capacity) {
4199 const int newcap = npart + npart / 2 + 1;
4201 realloc(particles, (
size_t) newcap *
sizeof(
particle_t));
4203 ERRMSG(
"Out of memory!");
4212 MPI_Barrier(MPI_COMM_WORLD);
4238 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4241 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,clim,atm)") {
4250 const double aux = exp(-cache->
dt[ip] / tdec);
4251 if (ctl->
qnt_m >= 0) {
4254 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
4255 atm->
q[ctl->
qnt_m][ip] *= aux;
4280 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4288 float umean = 0, usig = 0, vmean = 0, vsig = 0, wmean = 0, wsig = 0;
4289 for (
int i = 0; i < 2; i++)
4290 for (
int j = 0; j < 2; j++)
4291 for (
int k = 0; k < 2; k++) {
4292 umean += met0->
u[ix + i][iy + j][iz + k];
4293 usig +=
SQR(met0->
u[ix + i][iy + j][iz + k]);
4294 vmean += met0->
v[ix + i][iy + j][iz + k];
4295 vsig +=
SQR(met0->
v[ix + i][iy + j][iz + k]);
4296 wmean += met0->
w[ix + i][iy + j][iz + k];
4297 wsig +=
SQR(met0->
w[ix + i][iy + j][iz + k]);
4299 umean += met1->
u[ix + i][iy + j][iz + k];
4300 usig +=
SQR(met1->
u[ix + i][iy + j][iz + k]);
4301 vmean += met1->
v[ix + i][iy + j][iz + k];
4302 vsig +=
SQR(met1->
v[ix + i][iy + j][iz + k]);
4303 wmean += met1->
w[ix + i][iy + j][iz + k];
4304 wsig +=
SQR(met1->
w[ix + i][iy + j][iz + k]);
4306 usig = usig / 16.f -
SQR(umean / 16.f);
4307 usig = (usig > 0 ? sqrtf(usig) : 0);
4308 vsig = vsig / 16.f -
SQR(vmean / 16.f);
4309 vsig = (vsig > 0 ? sqrtf(vsig) : 0);
4310 wsig = wsig / 16.f -
SQR(wmean / 16.f);
4311 wsig = (wsig > 0 ? sqrtf(wsig) : 0);
4314 const double r = 1 - 2 * fabs(cache->
dt[ip]) / ctl->
dt_met;
4315 const double r2 = sqrt(1 - r * r);
4319 cache->
uvwp[ip][0] =
4320 (float) (r * cache->
uvwp[ip][0] +
4325 cache->
uvwp[ip][1] =
4326 (float) (r * cache->
uvwp[ip][1] +
4333 cache->
uvwp[ip][2] =
4334 (float) (r * cache->
uvwp[ip][2] +
4336 atm->
p[ip] += cache->
uvwp[ip][2] * cache->
dt[ip];
4357 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4359 double pbl, ps, dsigw_dz = 0.0, sig_u = 0.0, sig_v = 0.0, sig_w = 0.0;
4360 double tau_u = 0.0, tau_v = 0.0, tau_w = 0.0;
4367 if (atm->
p[ip] < pbl)
4374 if (!(ps > 0.0 && pbl > 0.0 && ps > pbl))
4379 const double p =
MIN(atm->
p[ip], ps);
4380 const double zs =
Z(ps);
4381 const double z_raw = 1e3 * (
Z(p) - zs);
4382 const double zi = 1e3 * (
Z(pbl) - zs);
4389 const double z =
CLAMP(z_raw, 0.0, zi);
4390 const double zeta =
CLAMP(z / zi, 1e-6, 1.0 - 1e-6);
4391 const double z_m =
MAX(z, 1.0);
4396 const double p_save = atm->
p[ip];
4400 double ess, nss, h2o, t;
4407 atm->
p[ip] = p_save;
4409 const double tv =
TVIRT(t, h2o);
4410 const double thetav =
THETAVIRT(p, t, h2o);
4411 const double rho =
RHO(p, tv);
4412 const double tau = sqrt(
SQR(ess) +
SQR(nss));
4417 const double ustar = sqrt(
MAX(tau / rho, 0.0));
4418 const double ust =
MAX(1e-4, ustar);
4429 if (fabs(shf) > 1e-6)
4433 if (zi / fabs(ol) < 1.0) {
4438 const double corr = z_m / ust;
4439 const double sigw0 = 1.3 * ust * exp(-2e-4 * corr);
4441 sig_u =
MAX(2.0 * ust * exp(-3e-4 * corr), 1e-5);
4442 sig_v =
MAX(sigw0, 1e-5);
4443 sig_w =
MAX(sigw0, 1e-5);
4444 dsigw_dz = -2e-4 * sigw0 / ust;
4446 tau_u = 0.5 * z_m / sig_w / (1.0 + 1.5e-3 * corr);
4452 else if (ol < 0.0) {
4455 const double wstar_arg = -
G0 / thetav * shf / (rho *
CPD) * zi;
4456 const double wstar = pow(
MAX(wstar_arg, 0.0), 1.0 / 3.0);
4457 double dsigw2_dz = 0.0;
4460 sig_u =
MAX(ust * pow(
MAX(12.0 - 0.5 * zi / ol, 0.0), 1.0 / 3.0), 1e-6);
4464 const double arg =
MAX(3.0 * zeta - ol / zi, 1e-12);
4465 sig_w = 0.96 * wstar * pow(arg, 1.0 / 3.0);
4466 dsigw2_dz = 1.8432 *
SQR(wstar) / zi * pow(arg, -1.0 / 3.0);
4467 }
else if (zeta < 0.4) {
4468 const double arg =
MAX(3.0 * zeta - ol / zi, 1e-12);
4469 const double s1 = 0.96 * pow(arg, 1.0 / 3.0);
4470 const double s2 = 0.763 * pow(zeta, 0.175);
4473 dsigw2_dz = 1.8432 *
SQR(wstar) / zi * pow(arg, -1.0 / 3.0);
4476 dsigw2_dz = 0.203759 *
SQR(wstar) / zi * pow(zeta, -0.65);
4478 }
else if (zeta < 0.96) {
4479 sig_w = 0.722 * wstar * pow(1.0 - zeta, 0.207);
4480 dsigw2_dz = -0.215812 *
SQR(wstar) / zi * pow(1.0 - zeta, -0.586);
4482 sig_w = 0.37 * wstar;
4486 sig_w =
MAX(sig_w, 1e-6);
4487 dsigw_dz = sig_w > 1e-12 ? 0.5 * dsigw2_dz / sig_w : 0.0;
4490 tau_u = 0.15 * zi /
MAX(sig_u, 1e-12);
4493 if (z_m < fabs(ol)) {
4494 const double denom = 0.55 - 0.38 * fabs(z_m / ol);
4495 tau_w = 0.1 * z_m / (sig_w *
MAX(denom, 0.05));
4496 }
else if (zeta < 0.1)
4497 tau_w = 0.59 * z_m / sig_w;
4499 tau_w = 0.15 * zi / sig_w * (1.0 - exp(-5.0 * zeta));
4505 sig_u =
MAX(2.0 * ust * (1.0 - zeta), 1e-6);
4506 sig_v =
MAX(1.3 * ust * (1.0 - zeta), 1e-6);
4507 sig_w =
MAX(1.3 * ust * (1.0 - zeta), 1e-6);
4508 dsigw_dz = -1.3 * ust / zi;
4510 tau_u = 0.15 * zi / sig_u * sqrt(zeta);
4511 tau_v = 0.467 * tau_u;
4512 tau_w = 0.1 * zi / sig_w * pow(zeta, 0.8);
4516 tau_u =
MAX(tau_u, 10.0);
4517 tau_v =
MAX(tau_v, 10.0);
4518 tau_w =
MAX(tau_w, 30.0);
4521 if (!(sig_u > 0.0 && sig_v > 0.0
4522 && sig_w > 0.0 && tau_u > 0.0 && tau_v > 0.0 && tau_w > 0.0))
4526 const double dt = cache->
dt[ip];
4527 const double dt_abs = fabs(dt);
4529 const double ru = exp(-dt_abs / tau_u);
4530 const double ru2 = sqrt(
MAX(0.0, 1.0 -
SQR(ru)));
4531 const double rv = exp(-dt_abs / tau_v);
4532 const double rv2 = sqrt(
MAX(0.0, 1.0 -
SQR(rv)));
4535 = (float) (cache->
uvwp[ip][0] * ru + sig_u * ru2 * cache->
rs[3 * ip]);
4538 = (float) (cache->
uvwp[ip][1] * rv
4539 + sig_v * rv2 * cache->
rs[3 * ip + 1]);
4544 const double rw = exp(-dt_abs / tau_w);
4545 const double rw2 = sqrt(
MAX(0.0, 1.0 -
SQR(rw)));
4546 const double rhoaux = -1.0 / (1e3 *
H0);
4549 = (float) (cache->
uvwp[ip][2] * rw + sig_w * rw2 * cache->
rs[3 * ip + 2]
4550 + tau_w * (1.0 - rw)
4551 * (2.0 * sig_w * dsigw_dz + rhoaux *
SQR(sig_w)));
4561 double znew = z + cache->
uvwp[ip][2] * dt;
4563 while (znew < 0.0 || znew > zi) {
4567 cache->
uvwp[ip][2] = -cache->
uvwp[ip][2];
4571 znew = 2.0 * zi - znew;
4572 cache->
uvwp[ip][2] = -cache->
uvwp[ip][2];
4579 atm->
p[ip] =
P(zs + znew / 1000.0);
4582 atm->
p[ip] =
CLAMP(atm->
p[ip], pbl, ps);
4604 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4620 const double ptop = met0->
p[met0->
np - 1];
4623 const double wpbl =
pbl_weight(ctl, atm, ip, pbl, ps);
4624 const double wtrop =
tropo_weight(ctl, clim, atm, ip) * (1.0 - wpbl);
4625 const double wstrat = 1.0 - wpbl - wtrop;
4637 const double dt_abs = fabs(cache->
dt[ip]);
4642 const double sigma_h = sqrt(2.0 * Kx * dt_abs);
4647 atm->
lat[ip] +=
DY2COORD(met0, cache->
rs[3 * ip + 1] * sigma_h);
4655 const double sigma_z = sqrt(2.0 * Kz * dt_abs) * 1e-3;
4659 const double p_save = atm->
p[ip];
4664 const double eps_km = 0.01;
4665 const double p_up = p_save +
DZ2DP(eps_km, p_save);
4666 const double p_dn = p_save +
DZ2DP(-eps_km, p_save);
4669 atm->
p[ip] =
MAX(ptop,
MIN(ps, p_up));
4670 const double wpbl_up =
pbl_weight(ctl, atm, ip, pbl, ps);
4671 const double wtrop_up =
4673 const double wstrat_up = 1.0 - wpbl_up - wtrop_up;
4675 const double Kz_up =
4680 atm->
p[ip] =
MAX(ptop,
MIN(ps, p_dn));
4681 const double wpbl_dn =
pbl_weight(ctl, atm, ip, pbl, ps);
4682 const double wtrop_dn =
4684 const double wstrat_dn = 1.0 - wpbl_dn - wtrop_dn;
4686 const double Kz_dn =
4691 atm->
p[ip] = p_save;
4705 const double dKz_dz = (Kz_up - Kz_dn) / (2.0 * eps_km * 1e3);
4706 const double dlnrho_dz = -1.0 / (1e3 *
H0);
4707 const double w_drift = dKz_dz + Kz * dlnrho_dz;
4708 const double dz_drift = w_drift * dt_abs * 1e-3;
4711 const double dz_tot = cache->
rs[3 * ip + 2] * sigma_z + dz_drift;
4714 double ptrial = p_save +
DZ2DP(dz_tot, p_save);
4721 for (
int iter = 0; iter < 10; iter++) {
4723 ptrial = ps * ps / ptrial;
4724 else if (ptrial < ptop)
4725 ptrial = ptop * ptop / ptrial;
4731 atm->
p[ip] =
MAX(ptop,
MIN(ps, ptrial));
4750 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4753 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4765 const double dz = 1000. * (
Z(ps - ctl->
dry_depo_dp) -
Z(ps));
4785 const double aux = exp(-cache->
dt[ip] * v_dep / dz);
4786 if (ctl->
qnt_m >= 0) {
4789 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
4790 atm->
q[ctl->
qnt_m][ip] *= aux;
4810 ERRMSG(
"Only lat/lon grid supported");
4817 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4823 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4830 if (!(lwc > 0 || rwc > 0))
4844 const double H_SO2 =
4850 const double H_h2o2 =
4858 cor = atm->
q[ctl->
qnt_Cx][ip] >
4861 const double h2o2 = H_h2o2
4863 * M * cor * 1000. /
AVO;
4866 const double rho_air = atm->
p[ip] / (
RI * t) *
MA / 10.;
4867 const double CWC = (lwc + rwc) * rho_air / 1e3;
4870 const double rate_coef = k * K_1S * h2o2 * H_SO2 * CWC;
4871 const double aux = exp(-cache->
dt[ip] * rate_coef);
4872 if (ctl->
qnt_m >= 0) {
4875 atm->
q[ctl->
qnt_m][ip] *= aux;
4907 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
4910 cache->
iso_var[ip] = atm->
p[ip] / t;
4916 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
4927 LOG(1,
"Read balloon pressure data: %s", ctl->
balloon);
4931 if (!(in = fopen(ctl->
balloon,
"r")))
4932 ERRMSG(
"Cannot open file!");
4936 while (fgets(line,
LEN, in))
4937 if (sscanf(line,
"%lg %lg", &(cache->
iso_ts[cache->
iso_n]),
4940 ERRMSG(
"Too many data points!");
4943 if (cache->
iso_n < 1)
4944 ERRMSG(
"Could not read any data!");
4967 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,met1,atm)") {
4980 atm->
p[ip] = cache->
iso_var[ip] * t;
4986 atm->
p[ip] = 1000. * pow(cache->
iso_var[ip] / t, -1. /
KAPPA);
4992 atm->
p[ip] = cache->
iso_ps[0];
5020 const int nvar = NVAR, nfix = NFIX, nreact = NREACT;
5021 double rtol[1] = { 1.0e-3 };
5022 double atol[1] = { 1.0 };
5026#pragma acc data copy(rtol,atol,nvar,nfix,nreact)
5029 "acc data present(ctl,cache,clim,met0,met1,atm) ") {
5032 double var[nvar], fix[nfix], rconst[nreact];
5033 for (
int i = 0; i < nvar; i++)
5035 for (
int i = 0; i < nfix; i++)
5037 for (
int i = 0; i < nreact; i++)
5039 kpp_chem_initialize(ctl, clim, met0, met1, atm, var, fix, rconst, ip);
5044 for (
int i = 0; i < 20; i++) {
5051 Rosenbrock(var, fix, rconst, 0, ctl->
dt_kpp,
5052 atol, rtol, &FunTemplate, &JacTemplate, rpar, ipar);
5055 kpp_chem_output2atm(atm, ctl, met0, met1, var, ip);
5076 ERRMSG(
"Need T_ice and T_NAT to calculate T_STS!");
5080 "acc data present(ctl,cache,clim,met0,met1,atm)") {
5082 double ps, ts, zs, us, vs, ess, nss, shf, lsm, sst, pbl, pt, pct, pcb,
5083 cl, plcl, plfc, pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot,
5084 o3, lwc, rwc, iwc, swc, cc, z, zt;
5129 const double lat_ref =
5134 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
5136 lat_ref, atm->
p[ip]));
5139 SET_ATM(qnt_vh, sqrt(u * u + v * v));
5161 atm->
lat[ip], atm->
p[ip])));
5179 const int np = atm->
np;
5180 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
5181 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
5182 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
5190 const double t0 = t - 0.5 * ctl->
dt_mod;
5191 const double t1 = t + 0.5 * ctl->
dt_mod;
5195#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
5196#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
5197#pragma acc parallel loop independent gang vector
5199#pragma omp parallel for default(shared)
5201 for (
int ip = 0; ip < np; ip++) {
5202 const double zpart =
Z(atm->
p[ip]);
5203 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
5208 || zpart < ctl->mixing_z0 || zpart >= ctl->
mixing_z1) {
5214 izs[ip] = (int) ((zpart - ctl->
mixing_z0) / dz);
5221 const int use_ensemble = (ctl->
nens > 0);
5223 const int quantities[] = {
5231 const int n_qnt =
sizeof(quantities) /
sizeof(quantities[0]);
5233 for (
int i = 0; i < n_qnt; i++)
5234 if (quantities[i] >= 0)
5240#pragma acc exit data delete(ixs,iys,izs)
5257 const int use_ensemble) {
5259 const int np = atm->
np;
5261 const int nens = use_ensemble ? ctl->
nens : 1;
5262 const int total_grid = ngrid * nens;
5264 double *restrict
const cmean =
5265 (
double *) malloc((
size_t) total_grid *
sizeof(double));
5266 int *restrict
const count =
5267 (
int *) malloc((
size_t) total_grid *
sizeof(int));
5271#pragma acc enter data create(cmean[0:total_grid],count[0:total_grid])
5272#pragma acc data present(ctl,clim,atm,ixs,iys,izs,cmean,count)
5273#pragma acc parallel loop independent gang vector
5278#pragma omp parallel for
5280 for (
int i = 0; i < total_grid; i++) {
5287#pragma acc parallel loop independent gang vector
5289 for (
int ip = 0; ip < np; ip++)
5291 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
5296#pragma acc atomic update
5298 cmean[idx] += atm->
q[qnt_idx][ip];
5300#pragma acc atomic update
5307#pragma acc parallel loop independent gang vector
5312#pragma omp parallel for
5314 for (
int i = 0; i < total_grid; i++)
5316 cmean[i] /= count[i];
5320#pragma acc parallel loop independent gang vector
5322#pragma omp parallel for
5324 for (
int ip = 0; ip < np; ip++) {
5326 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
5328 double mixparam = 1.0;
5337 atm->
q[qnt_idx][ip] += (cmean[idx] - atm->
q[qnt_idx][ip]) * mixparam;
5343#pragma acc exit data delete(cmean,count)
5364 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
5367 const double a = 4.71572206e-08;
5368 const double b = -8.28782867e-01;
5369 const double low = pow(1. / a, 1. / b);
5373 "acc data present(ctl,cache,clim,met0,met1,atm)") {
5399 0 ? pow(298. / t, ctl->
oh_chem[1]) : 1.);
5402 0 ? pow(298. / t, ctl->
oh_chem[3]) : 1.);
5403 const double c = log10(k0 * M / ki);
5404 k = k0 * M / (1. + k0 * M / ki) * pow(0.6, 1. / (1. + c * c));
5413 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
5416 const double rate_coef =
5418 atm->
lat[ip], atm->
p[ip]) * M * cor;
5419 const double aux = exp(-cache->
dt[ip] * rate_coef);
5420 if (ctl->
qnt_m >= 0) {
5423 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
5424 atm->
q[ctl->
qnt_m][ip] *= aux;
5445 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(cache,met0,met1,atm)") {
5457 while (atm->
lat[ip] < -90 || atm->
lat[ip] > 90) {
5458 if (atm->
lat[ip] > 90) {
5459 atm->
lat[ip] = 180 - atm->
lat[ip];
5460 atm->
lon[ip] += 180;
5462 if (atm->
lat[ip] < -90) {
5463 atm->
lat[ip] = -180 - atm->
lat[ip];
5464 atm->
lon[ip] += 180;
5469 while (atm->
lon[ip] < -180)
5470 atm->
lon[ip] += 360;
5471 while (atm->
lon[ip] >= 180)
5472 atm->
lon[ip] -= 360;
5475 atm->
lon[ip], atm->
lat[ip], &atm->
lon[ip],
5480 const double ptop = met0->
p[met0->
np - 1];
5481 if (atm->
p[ip] < ptop) {
5482 atm->
p[ip] = ptop * ptop / atm->
p[ip];
5483 }
else if (atm->
p[ip] > 300.) {
5485 if (atm->
p[ip] > ps)
5486 atm->
p[ip] = ps * ps / atm->
p[ip];
5513 const double dt = cache->
dt[ip];
5517 atm->
q[ctl->
qnt_Apb210][ip] *= exp(-dt * lambda_pb210);
5522 const double aux = exp(-dt * lambda_rn222);
5523 const double lost = old * (1.0 - aux);
5528 atm->
q[ctl->
qnt_Apb210][ip] += lost * lambda_pb210 / lambda_rn222;
5533 atm->
q[ctl->
qnt_Abe7][ip] *= exp(-dt * lambda_be7);
5537 atm->
q[ctl->
qnt_Acs137][ip] *= exp(-dt * lambda_cs137);
5541 atm->
q[ctl->
qnt_Ai131][ip] *= exp(-dt * lambda_i131);
5545 atm->
q[ctl->
qnt_Axe133][ip] *= exp(-dt * lambda_xe133);
5574 "acc data present(ctl,cache,met0,met1,atm,depo)") {
5577 const double dt = cache->
dt[ip];
5587 double dry_pb210 = 0, dry_be7 = 0, dry_cs137 = 0, dry_i131 = 0;
5589 const double dz = 1000. * (
Z(ps - ctl->
dry_depo_dp) -
Z(ps));
5599 double wet_pb210 = 0, wet_be7 = 0, wet_cs137 = 0, wet_i131 = 0;
5602 if (isfinite(pct) && atm->
p[ip] > pct) {
5609 double lwc, rwc, iwc, swc, t;
5615 const int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
5640 const int ix = ingrid
5642 const int iy = ingrid
5650 const double aux = exp(-dt * (dry_pb210 + wet_pb210));
5651 const double lost = old * (1. - aux);
5652 const double deposited = lost
5653 * (ctl->
radio_decay ? exp(lambda_pb210 * tref) : 1.0);
5655 if (ingrid && lost > 0) {
5657#pragma acc atomic update
5659#pragma omp atomic update
5661 depo->
Apb210[idx] += deposited;
5667 const double old = atm->
q[ctl->
qnt_Abe7][ip];
5668 const double aux = exp(-dt * (dry_be7 + wet_be7));
5669 const double lost = old * (1. - aux);
5670 const double deposited = lost
5671 * (ctl->
radio_decay ? exp(lambda_be7 * tref) : 1.0);
5673 if (ingrid && lost > 0) {
5675#pragma acc atomic update
5677#pragma omp atomic update
5679 depo->
Abe7[idx] += deposited;
5686 const double aux = exp(-dt * (dry_cs137 + wet_cs137));
5687 const double lost = old * (1. - aux);
5688 const double deposited = lost
5689 * (ctl->
radio_decay ? exp(lambda_cs137 * tref) : 1.0);
5691 if (ingrid && lost > 0) {
5693#pragma acc atomic update
5695#pragma omp atomic update
5697 depo->
Acs137[idx] += deposited;
5703 const double old = atm->
q[ctl->
qnt_Ai131][ip];
5704 const double aux = exp(-dt * (dry_i131 + wet_i131));
5705 const double lost = old * (1. - aux);
5706 const double deposited = lost
5707 * (ctl->
radio_decay ? exp(lambda_i131 * tref) : 1.0);
5709 if (ingrid && lost > 0) {
5711#pragma acc atomic update
5713#pragma omp atomic update
5715 depo->
Ai131[idx] += deposited;
5727 gsl_rng_env_setup();
5728 if (omp_get_max_threads() >
NTHREADS)
5729 ERRMSG(
"Too many threads!");
5730 for (
int i = 0; i <
NTHREADS; i++) {
5731 rng[i] = gsl_rng_alloc(gsl_rng_default);
5732 gsl_rng_set(rng[i], gsl_rng_default_seed
5733 + (
long unsigned) (ntask *
NTHREADS + i));
5738 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
5739 CURAND_STATUS_SUCCESS)
5740 ERRMSG(
"Cannot create random number generator!");
5741 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
5742 CURAND_STATUS_SUCCESS)
5743 ERRMSG(
"Cannot set seed for random number generator!");
5746 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
5747 CURAND_STATUS_SUCCESS)
5748 ERRMSG(
"Cannot set stream for random number generator!");
5765#pragma omp parallel for default(shared)
5766 for (
size_t i = 0; i < n; ++i)
5767 rs[i] = gsl_rng_uniform(rng[omp_get_thread_num()]);
5771 else if (method == 1) {
5772#pragma omp parallel for default(shared)
5773 for (
size_t i = 0; i < n; ++i)
5774 rs[i] = gsl_ran_gaussian_ziggurat(rng[omp_get_thread_num()], 1.0);
5780#pragma acc update device(rs[:n])
5788 const uint64_t key = 0xc8e4fd154ce32f6d;
5792#pragma acc data present(rs)
5793#pragma acc parallel loop independent gang vector
5795#pragma omp parallel for default(shared)
5797 for (
size_t i = 0; i < n + 1; ++i) {
5798 uint64_t r, t, x, y, z;
5799 y = x = (rng_ctr + i) * key;
5802 x = (x >> 32) | (x << 32);
5804 x = (x >> 32) | (x << 32);
5806 x = (x >> 32) | (x << 32);
5808 x = (x >> 32) | (x << 32);
5809 r = t ^ ((x * x + y) >> 32);
5810 rs[i] = (double) r / (
double) UINT64_MAX;
5817#pragma acc parallel loop independent gang vector
5819#pragma omp parallel for default(shared)
5821 for (
size_t i = 0; i < n; i += 2) {
5822 const double r = sqrt(-2.0 * log(rs[i]));
5823 const double phi = 2.0 * M_PI * rs[i + 1];
5824 rs[i] = r * cosf((
float) phi);
5825 rs[i + 1] = r * sinf((
float) phi);
5833#pragma acc host_data use_device(rs)
5838 if (curandGenerateUniformDouble(rng_curand, rs, (n < 4 ? 4 : n)) !=
5839 CURAND_STATUS_SUCCESS)
5840 ERRMSG(
"Cannot create random numbers!");
5844 else if (method == 1) {
5845 if (curandGenerateNormalDouble
5846 (rng_curand, rs, (n < 4 ? 4 : n), 0.0,
5847 1.0) != CURAND_STATUS_SUCCESS)
5848 ERRMSG(
"Cannot create random numbers!");
5852 ERRMSG(
"MPTRAC was compiled without cuRAND!");
5869 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
5877 const double v_s =
sedi(atm->
p[ip], t, atm->
q[ctl->
qnt_rp][ip],
5881 atm->
p[ip] +=
DZ2DP(v_s * cache->
dt[ip] / 1000., atm->
p[ip]);
5896 const int np = atm->
np;
5897 double *restrict
const a = (
double *) malloc((
size_t) np *
sizeof(double));
5898 int *restrict
const p = (
int *) malloc((
size_t) np *
sizeof(int));
5899 if (a == NULL || p == NULL)
5900 ERRMSG(
"Out of memory!");
5903#pragma acc enter data create(a[0:np],p[0:np])
5904#pragma acc data present(ctl,met0,atm,a,p)
5909#pragma acc parallel loop independent gang vector
5911#pragma omp parallel for default(shared)
5913 for (
int ip = 0; ip < np; ip++) {
5924#pragma acc host_data use_device(a,p)
5926 thrustSortWrapper(a, np, p);
5928 size_t *perm_sz = (
size_t *) malloc((
size_t) np *
sizeof(size_t));
5929 if (perm_sz == NULL)
5930 ERRMSG(
"Out of memory!");
5932#pragma acc update self(a[0:np])
5934 gsl_sort_index(perm_sz, a, 1, (
size_t) np);
5935 for (
int ip = 0; ip < np; ++ip)
5936 p[ip] = (
int) perm_sz[ip];
5939#pragma acc update device(p[0:np])
5948 for (
int iq = 0; iq < ctl->
nq; iq++)
5953#pragma acc exit data delete(a,p)
5967 double *restrict
const help =
5968 (
double *) malloc((
size_t) np *
sizeof(double));
5970 ERRMSG(
"Out of memory!");
5974#pragma acc enter data create(help[0:np])
5975#pragma acc data present(a,p,help)
5976#pragma acc parallel loop independent gang vector
5978#pragma omp parallel for default(shared)
5980 for (
int ip = 0; ip < np; ip++)
5981 help[ip] = a[p[ip]];
5983#pragma acc parallel loop independent gang vector
5985#pragma omp parallel for default(shared)
5987 for (
int ip = 0; ip < np; ip++)
5992#pragma acc exit data delete(help)
6009 const double latmin = gsl_stats_min(met0->
lat, 1, (
size_t) met0->
ny),
6010 latmax = gsl_stats_max(met0->
lat, 1, (
size_t) met0->
ny);
6013 (fabs(met0->
lon[met0->
nx - 1] - met0->
lon[0] - 360.0) >= 0.01);
6016 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,atm)") {
6022 cache->
dt[ip] = t - atm->
time[ip];
6024 cache->
dt[ip] = 0.0;
6033 if (local && (atm->
lon[ip] <= met0->
lon[0]
6034 || atm->
lon[ip] >= met0->
lon[met0->
nx - 1]
6035 || atm->
lat[ip] <= latmin || atm->
lat[ip] >= latmax))
6036 cache->
dt[ip] = 0.0;
6055 ctl->
t_start = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
6057 ctl->
t_stop = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
6059 ctl->
t_start = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
6061 ctl->
t_stop = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
6066 ERRMSG(
"Nothing to do! Check T_STOP and DIRECTION!");
6086 ERRMSG(
"Only lat/lon grid supported");
6093 "acc data present(ctl,cache,clim,met0,met1,atm)") {
6117 const double K_o1d =
6120 atm->
p[ip], sza, o3c);
6121 atm->
q[ctl->
qnt_Cccl4][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
6126 const double K_o1d =
6129 atm->
p[ip], sza, o3c);
6130 atm->
q[ctl->
qnt_Cccl3f][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
6135 const double K_o1d =
6138 atm->
p[ip], sza, o3c);
6139 atm->
q[ctl->
qnt_Cccl2f2][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
6144 const double K_o1d =
6147 atm->
p[ip], sza, o3c);
6148 atm->
q[ctl->
qnt_Cn2o][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
6167 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
6170 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
6176 if (!isfinite(pct) || atm->
p[ip] <= pct)
6192 double lwc, rwc, iwc, swc;
6197 const int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
6237 h *= (1. + K_1 / H_ion + K_1 * K_2 /
SQR(H_ion));
6241 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
6244 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
6270 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
6273 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
6278 const double aux = exp(-cache->
dt[ip] * lambda);
6279 if (ctl->
qnt_m >= 0) {
6282 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
6283 atm->
q[ctl->
qnt_m][ip] *= aux;
6306 if (ctl != NULL || cache != NULL || clim != NULL || met0 != NULL
6307 || met1 != NULL || atm != NULL || depo != NULL || dd != NULL) {
6309 if (acc_get_num_devices(acc_device_nvidia) <= 0)
6310 ERRMSG(
"Not running on a GPU device!");
6311 acc_device_t device_type = acc_get_device_type();
6312 acc_init(device_type);
6339 ctl_t *ctlup = *ctl;
6340#pragma acc enter data create(ctlup[:1])
6342 if (cache != NULL) {
6344#pragma acc enter data create(cacheup[:1])
6348#pragma acc enter data create(climup[:1])
6351 met_t *met0up = *met0;
6352#pragma acc enter data create(met0up[:1])
6355 met_t *met1up = *met1;
6356#pragma acc enter data create(met1up[:1])
6359 atm_t *atmup = *atm;
6360#pragma acc enter data create(atmup[:1])
6364#pragma acc enter data create(depoup[:1])
6369#pragma acc enter data create(ddup[:1])
6391#pragma acc exit data delete(ctl[:1])
6393 if (cache != NULL) {
6394#pragma acc exit data delete(cache[:1])
6397#pragma acc exit data delete(clim[:1])
6400#pragma acc exit data delete(met0[:1])
6403#pragma acc exit data delete(met1[:1])
6406#pragma acc exit data delete(atm[:1])
6409#pragma acc exit data delete(depo[:1])
6413#pragma acc exit data delete(dd[:1])
6431 MPI_Type_free(&dd->MPI_Particle);
6450 char cachefile[
LEN], cmd[2 *
LEN], filename[
LEN];
6456 if (t == ctl->
t_start || !init) {
6463 ERRMSG(
"Cannot open file!");
6468 ERRMSG(
"Cannot open file!");
6478 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
6479 LOG(1,
"Caching: %s", cachefile);
6480 if (system(cmd) != 0)
6481 WARN(
"Caching command failed!");
6486 if (t > (*met1)->time) {
6496 ERRMSG(
"Cannot open file!");
6506 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
6507 LOG(1,
"Caching: %s", cachefile);
6508 if (system(cmd) != 0)
6509 WARN(
"Caching command failed!");
6514 if (t < (*met0)->time) {
6524 ERRMSG(
"Cannot open file!");
6534 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
6535 LOG(1,
"Caching: %s", cachefile);
6536 if (system(cmd) != 0)
6537 WARN(
"Caching command failed!");
6541 if ((*met0)->coord_type != (*met1)->coord_type)
6542 ERRMSG(
"Coordinate types do not match!");
6545 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
6546 if ((*met0)->nx != (*met1)->nx
6547 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
6548 ERRMSG(
"Meteo grid dimensions do not match!");
6549 for (
int ix = 0; ix < (*met0)->nx; ix++)
6550 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
6551 ERRMSG(
"Meteo grid longitudes do not match!");
6552 for (
int iy = 0; iy < (*met0)->ny; iy++)
6553 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
6554 ERRMSG(
"Meteo grid latitudes do not match!");
6555 for (
int ip = 0; ip < (*met0)->np; ip++)
6556 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
6557 ERRMSG(
"Meteo grid pressure levels do not match!");
6580#pragma acc update device(depo[:1])
6589 const char *filename,
6602 LOG(1,
"Read atmospheric data: %s", filename);
6622 ERRMSG(
"Atmospheric data type not supported!");
6630 ERRMSG(
"Can not read any data!");
6634 LOG(2,
"Number of particles: %d", atm->
np);
6635 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
6636 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
6637 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
6638 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
6639 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
6640 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
6641 LOG(2,
"%s range: %g ... %g %s",
6642 ctl->
met_coord_type == 0 ?
"Longitude" :
"X coordinate", mini, maxi,
6644 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
6645 LOG(2,
"%s range: %g ... %g %s",
6646 ctl->
met_coord_type == 0 ?
"Latitude" :
"Y coordinate", mini, maxi,
6648 for (
int iq = 0; iq < ctl->
nq; iq++) {
6650 sprintf(msg,
"Quantity %s range: %s ... %s %s",
6653 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
6654 LOG(2, msg, mini, maxi);
6724 const char *filename,
6733 LOG(1,
"\nMassive-Parallel Trajectory Calculations (MPTRAC)\n"
6734 "(executable: %s | version: %s | compiled: %s, %s)\n",
6735 argv[0], VERSION, __DATE__, __TIME__);
6842 ctl->
nq = (int)
scan_ctl(filename, argc, argv,
"NQ", -1,
"0", NULL);
6844 ERRMSG(
"Too many quantities!");
6845 for (
int iq = 0; iq < ctl->
nq; iq++) {
6851 scan_ctl(filename, argc, argv,
"QNT_FORMAT", iq,
"%g",
6853 if (strcasecmp(ctl->
qnt_name[iq],
"aoa") == 0)
6857 SET_QNT(qnt_idx,
"idx",
"particle index",
"-")
6858 SET_QNT(qnt_ens,
"ens",
"ensemble index",
"-")
6859 SET_QNT(qnt_stat,
"stat",
"station flag",
"-")
6860 SET_QNT(qnt_m,
"m",
"mass",
"kg")
6861 SET_QNT(qnt_vmr,
"vmr",
"volume mixing ratio",
"ppv")
6862 SET_QNT(qnt_rp,
"rp",
"particle radius",
"microns")
6863 SET_QNT(qnt_rhop,
"rhop",
"particle density",
"kg/m^3")
6864 SET_QNT(qnt_ps,
"ps",
"surface pressure",
"hPa")
6865 SET_QNT(qnt_ts,
"ts",
"surface temperature",
"K")
6866 SET_QNT(qnt_zs,
"zs",
"surface height",
"km")
6867 SET_QNT(qnt_us,
"us",
"surface zonal wind",
"m/s")
6868 SET_QNT(qnt_vs,
"vs",
"surface meridional wind",
"m/s")
6869 SET_QNT(qnt_ess,
"ess",
"eastward turbulent surface stress",
"N/m^2")
6870 SET_QNT(qnt_nss,
"nss",
"northward turbulent surface stress",
"N/m^2")
6871 SET_QNT(qnt_shf,
"shf",
"surface sensible heat flux",
"W/m^2")
6872 SET_QNT(qnt_lsm,
"lsm",
"land-sea mask",
"1")
6873 SET_QNT(qnt_sst,
"sst",
"sea surface temperature",
"K")
6874 SET_QNT(qnt_pbl,
"pbl",
"planetary boundary layer",
"hPa")
6875 SET_QNT(qnt_pt,
"pt",
"tropopause pressure",
"hPa")
6876 SET_QNT(qnt_tt,
"tt",
"tropopause temperature",
"K")
6877 SET_QNT(qnt_zt,
"zt",
"tropopause geopotential height",
"km")
6878 SET_QNT(qnt_h2ot,
"h2ot",
"tropopause water vapor",
"ppv")
6879 SET_QNT(qnt_zg,
"zg",
"geopotential height",
"km")
6880 SET_QNT(qnt_p,
"p",
"pressure",
"hPa")
6881 SET_QNT(qnt_t,
"t",
"temperature",
"K")
6882 SET_QNT(qnt_rho,
"rho",
"air density",
"kg/m^3")
6883 SET_QNT(qnt_u,
"u",
"zonal wind",
"m/s")
6884 SET_QNT(qnt_v,
"v",
"meridional wind",
"m/s")
6885 SET_QNT(qnt_w,
"w",
"vertical velocity",
"hPa/s")
6886 SET_QNT(qnt_h2o,
"h2o",
"water vapor",
"ppv")
6887 SET_QNT(qnt_o3,
"o3",
"ozone",
"ppv")
6888 SET_QNT(qnt_lwc,
"lwc",
"cloud liquid water content",
"kg/kg")
6889 SET_QNT(qnt_rwc,
"rwc",
"cloud rain water content",
"kg/kg")
6890 SET_QNT(qnt_iwc,
"iwc",
"cloud ice water content",
"kg/kg")
6891 SET_QNT(qnt_swc,
"swc",
"cloud snow water content",
"kg/kg")
6892 SET_QNT(qnt_cc,
"cc",
"cloud cover",
"1")
6893 SET_QNT(qnt_pct,
"pct",
"cloud top pressure",
"hPa")
6894 SET_QNT(qnt_pcb,
"pcb",
"cloud bottom pressure",
"hPa")
6895 SET_QNT(qnt_cl,
"cl",
"total column cloud water",
"kg/m^2")
6896 SET_QNT(qnt_plcl,
"plcl",
"lifted condensation level",
"hPa")
6897 SET_QNT(qnt_plfc,
"plfc",
"level of free convection",
"hPa")
6898 SET_QNT(qnt_pel,
"pel",
"equilibrium level",
"hPa")
6899 SET_QNT(qnt_cape,
"cape",
"convective available potential energy",
6901 SET_QNT(qnt_cin,
"cin",
"convective inhibition",
"J/kg")
6902 SET_QNT(qnt_o3c,
"o3c",
"total column ozone",
"DU")
6903 SET_QNT(qnt_hno3,
"hno3",
"nitric acid",
"ppv")
6904 SET_QNT(qnt_oh,
"oh",
"hydroxyl radical",
"ppv")
6905 SET_QNT(qnt_h2o2,
"h2o2",
"hydrogen peroxide",
"ppv")
6906 SET_QNT(qnt_ho2,
"ho2",
"hydroperoxyl radical",
"ppv")
6907 SET_QNT(qnt_o1d,
"o1d",
"atomic oxygen",
"ppv")
6908 SET_QNT(qnt_mloss_oh,
"mloss_oh",
"mass loss due to OH chemistry",
"kg")
6909 SET_QNT(qnt_mloss_h2o2,
"mloss_h2o2",
6910 "mass loss due to H2O2 chemistry",
"kg")
6911 SET_QNT(qnt_mloss_kpp,
"mloss_kpp",
"mass loss due to kpp chemistry",
6913 SET_QNT(qnt_mloss_wet,
"mloss_wet",
"mass loss due to wet deposition",
6915 SET_QNT(qnt_mloss_dry,
"mloss_dry",
"mass loss due to dry deposition",
6917 SET_QNT(qnt_mloss_decay,
"mloss_decay",
6918 "mass loss due to exponential decay",
"kg")
6919 SET_QNT(qnt_loss_rate,
"loss_rate",
"total loss rate",
"s^-1")
6920 SET_QNT(qnt_psat,
"psat",
"saturation pressure over water",
"hPa")
6921 SET_QNT(qnt_psice,
"psice",
"saturation pressure over ice",
"hPa")
6922 SET_QNT(qnt_pw,
"pw",
"partial water vapor pressure",
"hPa")
6923 SET_QNT(qnt_sh,
"sh",
"specific humidity",
"kg/kg")
6924 SET_QNT(qnt_rh,
"rh",
"relative humidity",
"%%")
6925 SET_QNT(qnt_rhice,
"rhice",
"relative humidity over ice",
"%%")
6926 SET_QNT(qnt_theta,
"theta",
"potential temperature",
"K")
6927 SET_QNT(qnt_zeta,
"zeta",
"zeta coordinate",
"K")
6928 SET_QNT(qnt_zeta_d,
"zeta_d",
"diagnosed zeta coordinate",
"K")
6929 SET_QNT(qnt_zeta_dot,
"zeta_dot",
"velocity of zeta coordinate",
6931 SET_QNT(qnt_eta,
"eta",
"eta coordinate",
"1")
6932 SET_QNT(qnt_eta_dot,
"eta_dot",
"velocity of eta coordinate",
"1/s")
6933 SET_QNT(qnt_tvirt,
"tvirt",
"virtual temperature",
"K")
6934 SET_QNT(qnt_lapse,
"lapse",
"temperature lapse rate",
"K/km")
6935 SET_QNT(qnt_vh,
"vh",
"horizontal velocity",
"m/s")
6936 SET_QNT(qnt_vz,
"vz",
"vertical velocity",
"m/s")
6937 SET_QNT(qnt_pv,
"pv",
"potential vorticity",
"PVU")
6938 SET_QNT(qnt_tdew,
"tdew",
"dew point temperature",
"K")
6939 SET_QNT(qnt_tice,
"tice",
"frost point temperature",
"K")
6940 SET_QNT(qnt_tsts,
"tsts",
"STS existence temperature",
"K")
6941 SET_QNT(qnt_tnat,
"tnat",
"NAT existence temperature",
"K")
6942 SET_QNT(qnt_Cx,
"Cx",
"Trace species x volume mixing ratio",
"ppv")
6943 SET_QNT(qnt_Ch2o,
"Ch2o",
"H2O volume mixing ratio",
"ppv")
6944 SET_QNT(qnt_Co3,
"Co3",
"O3 volume mixing ratio",
"ppv")
6945 SET_QNT(qnt_Cco,
"Cco",
"CO volume mixing ratio",
"ppv")
6946 SET_QNT(qnt_Coh,
"Coh",
"HO volume mixing ratio",
"ppv")
6947 SET_QNT(qnt_Ch,
"Ch",
"H radical volume mixing ratio",
"ppv")
6948 SET_QNT(qnt_Cho2,
"Cho2",
"HO2 volume mixing ratio",
"ppv")
6949 SET_QNT(qnt_Ch2o2,
"Ch2o2",
"H2O2 volume mixing ratio",
"ppv")
6950 SET_QNT(qnt_Co1d,
"Co1d",
"O(1D) volume mixing ratio",
"ppv")
6951 SET_QNT(qnt_Co3p,
"Co3p",
"O(3P) radical volume mixing ratio",
"ppv")
6952 SET_QNT(qnt_Cccl4,
"Cccl4",
"CCl4 (CFC-10) volume mixing ratio",
"ppv")
6953 SET_QNT(qnt_Cccl3f,
"Cccl3f",
"CCl3F (CFC-11) volume mixing ratio",
6955 SET_QNT(qnt_Cccl2f2,
"Cccl2f2",
"CCl2F2 (CFC-12) volume mixing ratio",
6957 SET_QNT(qnt_Cn2o,
"Cn2o",
"N2O volume mixing ratio",
"ppv")
6958 SET_QNT(qnt_Csf6,
"Csf6",
"SF6 volume mixing ratio",
"ppv")
6959 SET_QNT(qnt_aoa,
"aoa",
"age of air",
"s")
6960 SET_QNT(qnt_Arn222,
"Arn222",
"Rn-222 activity",
"Bq")
6961 SET_QNT(qnt_Apb210,
"Apb210",
"Pb-210 activity",
"Bq")
6962 SET_QNT(qnt_Abe7,
"Abe7",
"Be-7 activity",
"Bq")
6963 SET_QNT(qnt_Acs137,
"Acs137",
"Cs-137 activity",
"Bq")
6964 SET_QNT(qnt_Ai131,
"Ai131",
"I-131 activity",
"Bq")
6965 SET_QNT(qnt_Axe133,
"Axe133",
"Xe-133 activity",
"Bq")
6966 SET_QNT(qnt_current_subdomain,
"current_subdomain",
6967 "current subdomain rank",
"-")
6968 SET_QNT(qnt_target_subdomain,
"target_subdomain",
6969 "target subdomain rank",
"-")
6974 (int)
scan_ctl(filename, argc, argv,
"MET_COORD_TYPE", -1,
"0", NULL);
6976 ERRMSG(
"MET_COORD_TYPE must be 0 or 1!");
6981 scan_ctl(filename, argc, argv,
"MET_UTM_REF_LAT", -1,
"", NULL);
6983 scan_ctl(filename, argc, argv,
"MET_UTM_REF_LON", -1,
"", NULL);
6988 (int)
scan_ctl(filename, argc, argv,
"ADVECT_VERT_COORD", -1,
"0", NULL);
6990 ERRMSG(
"ADVECT_VERT_COORD must be 0, 1, 2, or 3!");
6993 ERRMSG(
"Add quantity zeta for diabatic advection!");
6995 ERRMSG(
"Add quantity eta for etadot avection!");
6998 (int)
scan_ctl(filename, argc, argv,
"MET_VERT_COORD", -1,
"0", NULL);
7000 ERRMSG(
"MET_VERT_COORD must be 0, 1, 2, 3, or 4!");
7004 (
"Using ADVECT_VERT_COORD = 2 requires meteo data on model levels!");
7007 (
"Using ADVECT_VERT_COORD = 3 requires A and B model level coefficients!");
7010 (int)
scan_ctl(filename, argc, argv,
"MET_GP2Z", -1,
"0", NULL);
7012 ERRMSG(
"Set MET_GP2Z to 0 or 1!");
7016 (int)
scan_ctl(filename, argc, argv,
"DIRECTION", -1,
"1", NULL);
7018 ERRMSG(
"Set DIRECTION to -1 or 1!");
7019 ctl->
t_stop =
scan_ctl(filename, argc, argv,
"T_STOP", -1,
"1e100", NULL);
7020 ctl->
dt_mod =
scan_ctl(filename, argc, argv,
"DT_MOD", -1,
"180", NULL);
7024 ctl->
dt_met =
scan_ctl(filename, argc, argv,
"DT_MET", -1,
"3600", NULL);
7026 ERRMSG(
"DT_MOD must not exceed DT_MET!");
7028 (int)
scan_ctl(filename, argc, argv,
"MET_CONVENTION", -1,
"0", NULL);
7030 (int)
scan_ctl(filename, argc, argv,
"MET_TYPE", -1,
"0", NULL);
7033 (
"Please use meteo files in netcdf format for diabatic calculations.");
7036 (
"Please use meteo files in netcdf format for etadot calculations.");
7038 (int)
scan_ctl(filename, argc, argv,
"MET_CLAMS", -1,
"0", NULL);
7040 (int)
scan_ctl(filename, argc, argv,
"MET_NC_SCALE", -1,
"1", NULL);
7042 (int)
scan_ctl(filename, argc, argv,
"MET_NC_LEVEL", -1,
"0", NULL);
7044 (int)
scan_ctl(filename, argc, argv,
"MET_NC_QUANT", -1,
"0", NULL);
7046 (int)
scan_ctl(filename, argc, argv,
"MET_ZSTD_LEVEL", -1,
"-3", NULL);
7048 (int)
scan_ctl(filename, argc, argv,
"MET_ZSTD_NWORKERS", -1,
"4", NULL);
7050 (int)
scan_ctl(filename, argc, argv,
"MET_LZ4_ACCEL", -1,
"8", NULL);
7052 (int)
scan_ctl(filename, argc, argv,
"MET_PCK_ZSTD", -1,
"0", NULL);
7054 ERRMSG(
"Set MET_PCK_ZSTD to 0 or 1!");
7057 ERRMSG(
"MET_PCK_ZSTD requires MPTRAC to be compiled with ZSTD support!");
7059 const int def_lossy_scale =
7060 (int)
scan_ctl(filename, argc, argv,
"MET_LOSSY_SCALE", -1,
"0", NULL);
7061 for (
int i = 0; i <
METVAR; i++) {
7062 char defprec_zfp[
LEN] =
"7", deftol_zfp[
LEN] =
"0.0";
7063 char defprec_sz3[
LEN] =
"6", deftol_sz3[
LEN] =
"0.0";
7065 sprintf(defprec_zfp,
"12");
7066 sprintf(defprec_sz3,
"11");
7067 }
else if (i == 1) {
7068 sprintf(defprec_zfp,
"11");
7069 sprintf(defprec_sz3,
"7");
7070 }
else if (i == 2 || i == 3) {
7071 sprintf(defprec_zfp,
"7");
7072 sprintf(defprec_sz3,
"7");
7073 }
else if (i == 4) {
7074 sprintf(defprec_zfp,
"6");
7075 sprintf(defprec_sz3,
"13");
7076 }
else if (i == 5) {
7077 sprintf(defprec_zfp,
"7");
7078 sprintf(defprec_sz3,
"20");
7079 }
else if (i == 6) {
7080 sprintf(defprec_zfp,
"10");
7081 sprintf(defprec_sz3,
"18");
7082 }
else if (i == 7) {
7083 sprintf(defprec_zfp,
"9");
7084 sprintf(defprec_sz3,
"10");
7085 }
else if (i >= 8 && i <= 11) {
7086 sprintf(defprec_zfp,
"6");
7087 sprintf(defprec_sz3,
"13");
7088 }
else if (i == 12) {
7089 sprintf(defprec_zfp,
"9");
7090 sprintf(defprec_sz3,
"6");
7093 (int)
scan_ctl(filename, argc, argv,
"MET_ZFP_PREC", i, defprec_zfp,
7096 scan_ctl(filename, argc, argv,
"MET_ZFP_TOL", i, deftol_zfp, NULL);
7098 (int)
scan_ctl(filename, argc, argv,
"MET_SZ3_PREC", i, defprec_sz3,
7101 scan_ctl(filename, argc, argv,
"MET_SZ3_TOL", i, deftol_sz3, NULL);
7103 snprintf(defscale,
LEN,
"%d", def_lossy_scale);
7105 (int)
scan_ctl(filename, argc, argv,
"MET_LOSSY_SCALE", i, defscale,
7108 ERRMSG(
"Set MET_LOSSY_SCALE to 0 or 1!");
7112 scan_ctl(filename, argc, argv,
"MET_COMP_LOGFILE", -1,
"-",
7115 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_BATCH", -1,
"-1", NULL);
7117 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ZSTD", -1,
"1", NULL);
7119 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ND0X", -1,
"48", NULL);
7121 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ND0Y", -1,
"24", NULL);
7123 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_MAXLEV", -1,
"6", NULL);
7124 for (
int i = 0; i <
METVAR; i++) {
7125 char defeps[
LEN] =
"1.0";
7126 if (i == 1 || i == 2 || i == 3)
7127 sprintf(defeps,
"0.05");
7129 scan_ctl(filename, argc, argv,
"MET_CMS_EPS", i, defeps, NULL);
7131 ctl->
met_dx = (int)
scan_ctl(filename, argc, argv,
"MET_DX", -1,
"1", NULL);
7132 ctl->
met_dy = (int)
scan_ctl(filename, argc, argv,
"MET_DY", -1,
"1", NULL);
7133 ctl->
met_dp = (int)
scan_ctl(filename, argc, argv,
"MET_DP", -1,
"1", NULL);
7135 ERRMSG(
"MET_DX, MET_DY, and MET_DP need to be greater than zero!");
7136 ctl->
met_sx = (int)
scan_ctl(filename, argc, argv,
"MET_SX", -1,
"1", NULL);
7137 ctl->
met_sy = (int)
scan_ctl(filename, argc, argv,
"MET_SY", -1,
"1", NULL);
7138 ctl->
met_sp = (int)
scan_ctl(filename, argc, argv,
"MET_SP", -1,
"1", NULL);
7140 ERRMSG(
"MET_SX, MET_SY, and MET_SP need to be greater than zero!");
7142 scan_ctl(filename, argc, argv,
"MET_DETREND", -1,
"-999", NULL);
7143 ctl->
met_np = (int)
scan_ctl(filename, argc, argv,
"MET_NP", -1,
"0", NULL);
7145 ERRMSG(
"Too many pressure levels!");
7147 (int)
scan_ctl(filename, argc, argv,
"MET_PRESS_LEVEL_DEF", -1,
"-1",
7153 for (
int ip = 0; ip < ctl->
met_np; ip++)
7155 scan_ctl(filename, argc, argv,
"MET_P", ip,
"", NULL);
7159 (int)
scan_ctl(filename, argc, argv,
"MET_NLEV", -1,
"0", NULL);
7161 ERRMSG(
"Too many model levels!");
7162 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
7164 scan_ctl(filename, argc, argv,
"MET_LEV_HYAM", ip,
"", NULL);
7165 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
7167 scan_ctl(filename, argc, argv,
"MET_LEV_HYBM", ip,
"", NULL);
7169 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SX", -1,
"-1", NULL);
7171 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SY", -1,
"-1", NULL);
7173 (int)
scan_ctl(filename, argc, argv,
"MET_RELHUM", -1,
"0", NULL);
7175 (int)
scan_ctl(filename, argc, argv,
"MET_CAPE", -1,
"1", NULL);
7177 ERRMSG(
"Set MET_CAPE to 0 or 1!");
7179 (int)
scan_ctl(filename, argc, argv,
"MET_PBL", -1,
"3", NULL);
7181 ERRMSG(
"Set MET_PBL to 0 ... 3!");
7183 scan_ctl(filename, argc, argv,
"MET_PBL_MIN", -1,
"0.1", NULL);
7185 scan_ctl(filename, argc, argv,
"MET_PBL_MAX", -1,
"5.0", NULL);
7187 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO", -1,
"3", NULL);
7189 ERRMSG(
"Set MET_TROPO to 0 ... 5!");
7191 scan_ctl(filename, argc, argv,
"MET_TROPO_PV", -1,
"3.5", NULL);
7193 scan_ctl(filename, argc, argv,
"MET_TROPO_THETA", -1,
"380", NULL);
7195 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO_SPLINE", -1,
"1", NULL);
7197 scan_ctl(filename, argc, argv,
"MET_DT_OUT", -1,
"0.1", NULL);
7199 (int)
scan_ctl(filename, argc, argv,
"MET_CACHE", -1,
"0", NULL);
7201 (int)
scan_ctl(filename, argc, argv,
"MET_MPI_SHARE", -1,
"0", NULL);
7204 ctl->
sort_dt =
scan_ctl(filename, argc, argv,
"SORT_DT", -1,
"-999", NULL);
7208 (int)
scan_ctl(filename, argc, argv,
"ISOSURF", -1,
"0", NULL);
7213 (int)
scan_ctl(filename, argc, argv,
"RNG_TYPE", -1,
"1", NULL);
7215 ERRMSG(
"Set RNG_TYPE to 0, 1, or 2!");
7218 ctl->
advect = (int)
scan_ctl(filename, argc, argv,
"ADVECT", -1,
"2", NULL);
7220 ERRMSG(
"Set ADVECT to 1, 2, or 4!");
7224 = (int)
scan_ctl(filename, argc, argv,
"DIFFUSION", -1,
"0", NULL);
7226 ERRMSG(
"Set DIFFUSION to 0 or 1!");
7228 (int)
scan_ctl(filename, argc, argv,
"TURB_PBL_SCHEME", -1,
"0", NULL);
7230 ERRMSG(
"Set TURB_PBL_SCHEME to 0 or 1!");
7232 scan_ctl(filename, argc, argv,
"TURB_DX_PBL", -1,
"50", NULL);
7234 scan_ctl(filename, argc, argv,
"TURB_DX_TROP", -1,
"50", NULL);
7236 scan_ctl(filename, argc, argv,
"TURB_DX_STRAT", -1,
"0", NULL);
7238 scan_ctl(filename, argc, argv,
"TURB_DZ_PBL", -1,
"0", NULL);
7240 scan_ctl(filename, argc, argv,
"TURB_DZ_TROP", -1,
"0", NULL);
7242 scan_ctl(filename, argc, argv,
"TURB_DZ_STRAT", -1,
"0.1", NULL);
7244 scan_ctl(filename, argc, argv,
"TURB_MESOX", -1,
"0.16", NULL);
7246 scan_ctl(filename, argc, argv,
"TURB_MESOZ", -1,
"0.16", NULL);
7248 scan_ctl(filename, argc, argv,
"TURB_PBL_TRANS", -1,
"0", NULL);
7250 ERRMSG(
"TURB_PBL_TRANS must be in the range [0, 1]!");
7254 = (int)
scan_ctl(filename, argc, argv,
"CONV_MIX_PBL", -1,
"0", NULL);
7256 =
scan_ctl(filename, argc, argv,
"CONV_PBL_TRANS", -1,
"0", NULL);
7258 ERRMSG(
"CONV_PBL_TRANS must be in the range [0, 1]!");
7260 =
scan_ctl(filename, argc, argv,
"CONV_CAPE", -1,
"-999", NULL);
7262 =
scan_ctl(filename, argc, argv,
"CONV_CIN", -1,
"-999", NULL);
7263 ctl->
conv_dt =
scan_ctl(filename, argc, argv,
"CONV_DT", -1,
"-999", NULL);
7267 scan_ctl(filename, argc, argv,
"BOUND_MASS", -1,
"-999", NULL);
7269 scan_ctl(filename, argc, argv,
"BOUND_MASS_TREND", -1,
"0", NULL);
7271 scan_ctl(filename, argc, argv,
"BOUND_VMR", -1,
"-999", NULL);
7273 scan_ctl(filename, argc, argv,
"BOUND_VMR_TREND", -1,
"0", NULL);
7275 scan_ctl(filename, argc, argv,
"BOUND_LAT0", -1,
"-999", NULL);
7277 scan_ctl(filename, argc, argv,
"BOUND_LAT1", -1,
"-999", NULL);
7279 scan_ctl(filename, argc, argv,
"BOUND_P0", -1,
"-999", NULL);
7281 scan_ctl(filename, argc, argv,
"BOUND_P1", -1,
"-999", NULL);
7283 scan_ctl(filename, argc, argv,
"BOUND_DPS", -1,
"-999", NULL);
7285 scan_ctl(filename, argc, argv,
"BOUND_DZS", -1,
"-999", NULL);
7287 scan_ctl(filename, argc, argv,
"BOUND_ZETAS", -1,
"-999", NULL);
7289 (int)
scan_ctl(filename, argc, argv,
"BOUND_PBL", -1,
"0", NULL);
7293 if (strcasecmp(ctl->
species,
"CF2Cl2") == 0) {
7297 }
else if (strcasecmp(ctl->
species,
"CFCl3") == 0) {
7301 }
else if (strcasecmp(ctl->
species,
"CH4") == 0) {
7308 }
else if (strcasecmp(ctl->
species,
"CO") == 0) {
7317 }
else if (strcasecmp(ctl->
species,
"CO2") == 0) {
7321 }
else if (strcasecmp(ctl->
species,
"H2O") == 0) {
7323 }
else if (strcasecmp(ctl->
species,
"N2O") == 0) {
7327 }
else if (strcasecmp(ctl->
species,
"NH3") == 0) {
7334 }
else if (strcasecmp(ctl->
species,
"HNO3") == 0) {
7338 }
else if (strcasecmp(ctl->
species,
"NO") == 0) {
7347 }
else if (strcasecmp(ctl->
species,
"NO2") == 0) {
7356 }
else if (strcasecmp(ctl->
species,
"O3") == 0) {
7363 }
else if (strcasecmp(ctl->
species,
"SF6") == 0) {
7367 }
else if (strcasecmp(ctl->
species,
"SO2") == 0) {
7380 sprintf(defstr,
"%g", ctl->
molmass);
7381 ctl->
molmass =
scan_ctl(filename, argc, argv,
"MOLMASS", -1, defstr, NULL);
7386 (int)
scan_ctl(filename, argc, argv,
"OH_CHEM_REACTION", -1, defstr,
7388 for (
int ip = 0; ip < 4; ip++) {
7389 sprintf(defstr,
"%g", ctl->
oh_chem[ip]);
7391 scan_ctl(filename, argc, argv,
"OH_CHEM", ip, defstr, NULL);
7394 scan_ctl(filename, argc, argv,
"OH_CHEM_BETA", -1,
"0", NULL);
7398 (int)
scan_ctl(filename, argc, argv,
"H2O2_CHEM_REACTION", -1,
"0", NULL);
7402 (int)
scan_ctl(filename, argc, argv,
"KPP_CHEM", -1,
"0", NULL);
7403 ctl->
dt_kpp =
scan_ctl(filename, argc, argv,
"DT_KPP", -1,
"1800", NULL);
7407 (int)
scan_ctl(filename, argc, argv,
"TRACER_CHEM", -1,
"0", NULL);
7411 (int)
scan_ctl(filename, argc, argv,
"RADIO_DECAY", -1,
"0", NULL);
7413 (int)
scan_ctl(filename, argc, argv,
"RADIO_DEPO", -1,
"0", NULL);
7415 ERRMSG(
"Radioactive deposition requires a lat/lon meteorological grid!");
7419 (
"Radioactive deposition is not supported with domain decomposition!");
7423 for (
int ip = 0; ip < 2; ip++) {
7426 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_H", ip, defstr, NULL);
7428 for (
int ip = 0; ip < 1; ip++) {
7431 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_H", ip, defstr, NULL);
7434 scan_ctl(filename, argc, argv,
"WET_DEPO_SO2_PH", -1,
"0", NULL);
7436 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_A", -1,
"0", NULL);
7438 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_B", -1,
"0", NULL);
7440 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_A", -1,
"0", NULL);
7442 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_B", -1,
"0", NULL);
7444 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 0,
"0.5", NULL);
7446 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 1,
"0.36", NULL);
7448 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_RET_RATIO", -1,
"1", NULL);
7450 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_RET_RATIO", -1,
"1", NULL);
7454 scan_ctl(filename, argc, argv,
"DRY_DEPO_VDEP", -1,
"0", NULL);
7456 scan_ctl(filename, argc, argv,
"DRY_DEPO_DP", -1,
"30", NULL);
7459 scan_ctl(filename, argc, argv,
"CLIM_PHOTO", -1,
7460 "../../data/clams_photolysis_rates.nc", ctl->
clim_photo);
7461 scan_ctl(filename, argc, argv,
"CLIM_HNO3_FILENAME", -1,
7463 scan_ctl(filename, argc, argv,
"CLIM_OH_FILENAME", -1,
7465 scan_ctl(filename, argc, argv,
"CLIM_H2O2_FILENAME", -1,
7467 scan_ctl(filename, argc, argv,
"CLIM_HO2_FILENAME", -1,
7469 scan_ctl(filename, argc, argv,
"CLIM_O1D_FILENAME", -1,
7471 scan_ctl(filename, argc, argv,
"CLIM_CCL4_TIMESERIES", -1,
7473 scan_ctl(filename, argc, argv,
"CLIM_CCL3F_TIMESERIES", -1,
7475 scan_ctl(filename, argc, argv,
"CLIM_CCL2F2_TIMESERIES", -1,
7477 scan_ctl(filename, argc, argv,
"CLIM_N2O_TIMESERIES", -1,
7479 scan_ctl(filename, argc, argv,
"CLIM_SF6_TIMESERIES", -1,
7484 scan_ctl(filename, argc, argv,
"MIXING_DT", -1,
"3600.", NULL);
7486 scan_ctl(filename, argc, argv,
"MIXING_TROP", -1,
"-999", NULL);
7488 scan_ctl(filename, argc, argv,
"MIXING_STRAT", -1,
"-999", NULL);
7490 scan_ctl(filename, argc, argv,
"MIXING_Z0", -1,
"-5", NULL);
7492 scan_ctl(filename, argc, argv,
"MIXING_Z1", -1,
"85", NULL);
7494 (int)
scan_ctl(filename, argc, argv,
"MIXING_NZ", -1,
"90", NULL);
7496 scan_ctl(filename, argc, argv,
"MIXING_LON0", -1,
"-180", NULL);
7498 scan_ctl(filename, argc, argv,
"MIXING_LON1", -1,
"180", NULL);
7500 (int)
scan_ctl(filename, argc, argv,
"MIXING_NX", -1,
"360", NULL);
7502 scan_ctl(filename, argc, argv,
"MIXING_LAT0", -1,
"-90", NULL);
7504 scan_ctl(filename, argc, argv,
"MIXING_LAT1", -1,
"90", NULL);
7506 (int)
scan_ctl(filename, argc, argv,
"MIXING_NY", -1,
"180", NULL);
7512 ERRMSG(
"Invalid mixing grid!");
7516 scan_ctl(filename, argc, argv,
"CHEMGRID_Z0", -1,
"-5", NULL);
7518 scan_ctl(filename, argc, argv,
"CHEMGRID_Z1", -1,
"85", NULL);
7520 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NZ", -1,
"90", NULL);
7522 scan_ctl(filename, argc, argv,
"CHEMGRID_LON0", -1,
"-180", NULL);
7524 scan_ctl(filename, argc, argv,
"CHEMGRID_LON1", -1,
"180", NULL);
7526 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NX", -1,
"360", NULL);
7528 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT0", -1,
"-90", NULL);
7530 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT1", -1,
"90", NULL);
7532 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NY", -1,
"180", NULL);
7538 ERRMSG(
"Invalid chemistry grid!");
7543 scan_ctl(filename, argc, argv,
"TDEC_STRAT", -1,
"0", NULL);
7546 ctl->
psc_h2o =
scan_ctl(filename, argc, argv,
"PSC_H2O", -1,
"4e-6", NULL);
7548 scan_ctl(filename, argc, argv,
"PSC_HNO3", -1,
"9e-9", NULL);
7554 scan_ctl(filename, argc, argv,
"ATM_DT_OUT", -1,
"86400", NULL);
7556 (int)
scan_ctl(filename, argc, argv,
"ATM_FILTER", -1,
"0", NULL);
7558 (int)
scan_ctl(filename, argc, argv,
"ATM_STRIDE", -1,
"1", NULL);
7560 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE", -1,
"0", NULL);
7562 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE_OUT", -1,
"-1", NULL);
7566 (int)
scan_ctl(filename, argc, argv,
"ATM_NC_LEVEL", -1,
"0", NULL);
7567 for (
int iq = 0; iq < ctl->
nq; iq++)
7569 (
int)
scan_ctl(filename, argc, argv,
"ATM_NC_QUANT", iq,
"0", NULL);
7571 (int)
scan_ctl(filename, argc, argv,
"OBS_TYPE", -1,
"0", NULL);
7574 scan_ctl(filename, argc, argv,
"DEPO_BASENAME", -1,
"-",
7577 scan_ctl(filename, argc, argv,
"DEPO_DT_OUT", -1,
"86400", NULL);
7579 (int)
scan_ctl(filename, argc, argv,
"DEPO_TYPE", -1,
"0", NULL);
7585 scan_ctl(filename, argc, argv,
"CSI_DT_OUT", -1,
"86400", NULL);
7588 scan_ctl(filename, argc, argv,
"CSI_OBSMIN", -1,
"0", NULL);
7590 scan_ctl(filename, argc, argv,
"CSI_MODMIN", -1,
"0", NULL);
7591 ctl->
csi_z0 =
scan_ctl(filename, argc, argv,
"CSI_Z0", -1,
"-5", NULL);
7592 ctl->
csi_z1 =
scan_ctl(filename, argc, argv,
"CSI_Z1", -1,
"85", NULL);
7593 ctl->
csi_nz = (int)
scan_ctl(filename, argc, argv,
"CSI_NZ", -1,
"1", NULL);
7595 scan_ctl(filename, argc, argv,
"CSI_LON0", -1,
"-180", NULL);
7596 ctl->
csi_lon1 =
scan_ctl(filename, argc, argv,
"CSI_LON1", -1,
"180", NULL);
7598 (int)
scan_ctl(filename, argc, argv,
"CSI_NX", -1,
"360", NULL);
7599 ctl->
csi_lat0 =
scan_ctl(filename, argc, argv,
"CSI_LAT0", -1,
"-90", NULL);
7600 ctl->
csi_lat1 =
scan_ctl(filename, argc, argv,
"CSI_LAT1", -1,
"90", NULL);
7602 (int)
scan_ctl(filename, argc, argv,
"CSI_NY", -1,
"180", NULL);
7607 ERRMSG(
"Invalid CSI grid!");
7610 ctl->
nens = (int)
scan_ctl(filename, argc, argv,
"NENS", -1,
"0", NULL);
7613 scan_ctl(filename, argc, argv,
"ENS_DT_OUT", -1,
"86400", NULL);
7616 scan_ctl(filename, argc, argv,
"GRID_BASENAME", -1,
"-",
7621 scan_ctl(filename, argc, argv,
"GRID_DT_OUT", -1,
"86400", NULL);
7623 (int)
scan_ctl(filename, argc, argv,
"GRID_SPARSE", -1,
"0", NULL);
7625 (int)
scan_ctl(filename, argc, argv,
"GRID_NC_LEVEL", -1,
"0", NULL);
7626 for (
int iq = 0; iq < ctl->
nq; iq++)
7628 (
int)
scan_ctl(filename, argc, argv,
"GRID_NC_QUANT", iq,
"0", NULL);
7630 (int)
scan_ctl(filename, argc, argv,
"GRID_STDDEV", -1,
"0", NULL);
7631 ctl->
grid_z0 =
scan_ctl(filename, argc, argv,
"GRID_Z0", -1,
"-5", NULL);
7632 ctl->
grid_z1 =
scan_ctl(filename, argc, argv,
"GRID_Z1", -1,
"85", NULL);
7634 (int)
scan_ctl(filename, argc, argv,
"GRID_NZ", -1,
"1", NULL);
7636 scan_ctl(filename, argc, argv,
"GRID_LON0", -1,
"-180", NULL);
7638 scan_ctl(filename, argc, argv,
"GRID_LON1", -1,
"180", NULL);
7640 (int)
scan_ctl(filename, argc, argv,
"GRID_NX", -1,
"360", NULL);
7642 scan_ctl(filename, argc, argv,
"GRID_LAT0", -1,
"-90", NULL);
7644 scan_ctl(filename, argc, argv,
"GRID_LAT1", -1,
"90", NULL);
7646 (int)
scan_ctl(filename, argc, argv,
"GRID_NY", -1,
"180", NULL);
7648 (int)
scan_ctl(filename, argc, argv,
"GRID_TYPE", -1,
"0", NULL);
7651 ERRMSG(
"Invalid output grid dimensions!");
7655 ERRMSG(
"Invalid output grid boundaries!");
7658 ERRMSG(
"Invalid radioactive deposition output settings!");
7661 scan_ctl(filename, argc, argv,
"PROF_BASENAME", -1,
"-",
7664 ctl->
prof_z0 =
scan_ctl(filename, argc, argv,
"PROF_Z0", -1,
"0", NULL);
7665 ctl->
prof_z1 =
scan_ctl(filename, argc, argv,
"PROF_Z1", -1,
"60", NULL);
7667 (int)
scan_ctl(filename, argc, argv,
"PROF_NZ", -1,
"60", NULL);
7669 scan_ctl(filename, argc, argv,
"PROF_LON0", -1,
"-180", NULL);
7671 scan_ctl(filename, argc, argv,
"PROF_LON1", -1,
"180", NULL);
7673 (int)
scan_ctl(filename, argc, argv,
"PROF_NX", -1,
"360", NULL);
7675 scan_ctl(filename, argc, argv,
"PROF_LAT0", -1,
"-90", NULL);
7677 scan_ctl(filename, argc, argv,
"PROF_LAT1", -1,
"90", NULL);
7679 (int)
scan_ctl(filename, argc, argv,
"PROF_NY", -1,
"180", NULL);
7684 ERRMSG(
"Invalid profile grid!");
7687 scan_ctl(filename, argc, argv,
"SAMPLE_BASENAME", -1,
"-",
7689 scan_ctl(filename, argc, argv,
"SAMPLE_KERNEL", -1,
"-",
7691 scan_ctl(filename, argc, argv,
"SAMPLE_OBSFILE", -1,
"-",
7694 scan_ctl(filename, argc, argv,
"SAMPLE_DX", -1,
"50", NULL);
7696 scan_ctl(filename, argc, argv,
"SAMPLE_DZ", -1,
"-999", NULL);
7699 scan_ctl(filename, argc, argv,
"STAT_BASENAME", -1,
"-",
7703 ctl->
stat_r =
scan_ctl(filename, argc, argv,
"STAT_R", -1,
"50", NULL);
7705 scan_ctl(filename, argc, argv,
"STAT_T0", -1,
"-1e100", NULL);
7706 ctl->
stat_t1 =
scan_ctl(filename, argc, argv,
"STAT_T1", -1,
"1e100", NULL);
7711 scan_ctl(filename, argc, argv,
"VTK_DT_OUT", -1,
"86400", NULL);
7713 (int)
scan_ctl(filename, argc, argv,
"VTK_STRIDE", -1,
"1", NULL);
7715 scan_ctl(filename, argc, argv,
"VTK_SCALE", -1,
"1.0", NULL);
7717 scan_ctl(filename, argc, argv,
"VTK_OFFSET", -1,
"0.0", NULL);
7719 (int)
scan_ctl(filename, argc, argv,
"VTK_SPHERE", -1,
"0", NULL);
7723 ctl->
dd = (int)
scan_ctl(filename, argc, argv,
"DD", -1,
"1", NULL);
7725 ctl->
dd = (int)
scan_ctl(filename, argc, argv,
"DD", -1,
"0", NULL);
7729 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_MERIDIONAL", -1,
7730 (ctl->
dd == 1) ?
"2" :
"1", NULL);
7732 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_ZONAL", -1,
7733 (ctl->
dd == 1) ?
"2" :
"1", NULL);
7735 (int)
scan_ctl(filename, argc, argv,
"DD_HALOS_SIZE", -1,
"1", NULL);
7737 (double)
scan_ctl(filename, argc, argv,
"DD_SORT_DT", -1,
"1800", NULL);
7743 const char *filename,
7750 LOG(1,
"Read meteo data: %s", filename);
7756 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
7784 ERRMSG(
"MET_TYPE not implemented!");
7838 LOG(2,
"Broadcast data on rank %d...", rank);
7970 module_dd(t, ctl, cache, dd, atm, met0);
7984 ERRMSG(
"Code was compiled without KPP!");
8017#pragma acc update device(ctl[:1])
8021 if (cache != NULL) {
8024#pragma acc update device(cache[:1])
8031#pragma acc update device(clim[:1])
8038 met_t *met0up = *met0;
8039#pragma acc update device(met0up[:1])
8046 met_t *met1up = *met1;
8047#pragma acc update device(met1up[:1])
8054#pragma acc update device(atm[:1])
8073#pragma acc update host(ctl[:1])
8077 if (cache != NULL) {
8080#pragma acc update host(cache[:1])
8087#pragma acc update host(clim[:1])
8094 met_t *met0up = *met0;
8095#pragma acc update host(met0up[:1])
8102 met_t *met1up = *met1;
8103#pragma acc update host(met1up[:1])
8110#pragma acc update host(atm[:1])
8118 const char *filename,
8127 LOG(1,
"Write atmospheric data: %s", filename);
8151 ERRMSG(
"Atmospheric data type not supported!");
8155 LOG(2,
"Number of particles: %d", atm->
np);
8156 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
8157 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
8158 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
8159 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
8160 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
8161 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
8162 LOG(2,
"%s range: %g ... %g %s",
8163 ctl->
met_coord_type == 0 ?
"Longitude" :
"X coordinate", mini, maxi,
8165 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
8166 LOG(2,
"%s range: %g ... %g %s",
8167 ctl->
met_coord_type == 0 ?
"Latitude" :
"Y coordinate", mini, maxi,
8169 for (
int iq = 0; iq < ctl->
nq; iq++) {
8171 sprintf(msg,
"Quantity %s range: %s ... %s %s",
8174 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
8175 LOG(2, msg, mini, maxi);
8182 const char *filename,
8190 LOG(1,
"Write meteo data: %s", filename);
8195 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
8199 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
8203 ERRMSG(
"MPTRAC was compiled without LZ4 compression!");
8207 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
8211 ERRMSG(
"MPTRAC was compiled without SZ3 compression!");
8225 ERRMSG(
"MET_TYPE not implemented!");
8231 const char *dirname,
8239 char ext[10], filename[2 *
LEN];
8243 int year, mon, day, hour, min, sec;
8246 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
8261 sprintf(ext,
"tab");
8263 sprintf(ext,
"bin");
8266 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d_%02d.%s",
8267 dirname, ctl->
atm_basename, year, mon, day, hour, min, sec, ext);
8273 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d_%02d.%s",
8274 dirname, ctl->
grid_basename, year, mon, day, hour, min, sec,
8276 write_grid(filename, ctl, met0, met1, atm, t);
8283#pragma acc update host(depo[:1])
8285 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d_%02d.%s",
8286 dirname, ctl->
depo_basename, year, mon, day, hour, min, sec,
8293 sprintf(filename,
"%s/%s.tab", dirname, ctl->
csi_basename);
8299 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d_%02d.tab",
8300 dirname, ctl->
ens_basename, year, mon, day, hour, min, sec);
8306 sprintf(filename,
"%s/%s.tab", dirname, ctl->
prof_basename);
8307 write_prof(filename, ctl, met0, met1, atm, t);
8318 sprintf(filename,
"%s/%s.tab", dirname, ctl->
stat_basename);
8327 sprintf(filename,
"%s/%s_%05d.vtk", dirname, ctl->
vtk_basename, ++nvtk);
8337 const double hno3) {
8340 const double h2o_help =
MAX(h2o, 0.1e-6);
8343 const double p_hno3 = hno3 * p / 1.333224;
8344 const double p_h2o = h2o_help * p / 1.333224;
8345 const double a = 0.009179 - 0.00088 * log10(p_h2o);
8346 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
8347 const double c = -11397.0 / a;
8348 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
8349 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
8367 const double p0 = pbl;
8370 if (atm->
p[ip] > p0)
8372 else if (atm->
p[ip] < p1)
8375 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
8381 const char *filename,
8387 if (!(in = fopen(filename,
"r"))) {
8388 WARN(
"Cannot open file!");
8394 while (fgets(line,
LEN, in)) {
8398 TOK(line, tok,
"%lg", atm->
time[atm->
np]);
8399 TOK(NULL, tok,
"%lg", atm->
p[atm->
np]);
8400 TOK(NULL, tok,
"%lg", atm->
lon[atm->
np]);
8401 TOK(NULL, tok,
"%lg", atm->
lat[atm->
np]);
8402 for (
int iq = 0; iq < ctl->
nq; iq++)
8403 TOK(NULL, tok,
"%lg", atm->
q[iq][atm->
np]);
8406 atm->
p[atm->
np] =
P(atm->
p[atm->
np]);
8409 if ((++atm->
np) >
NP)
8410 ERRMSG(
"Too many data points!");
8423 const char *filename,
8429 if (!(in = fopen(filename,
"r")))
8434 FREAD(&version,
int,
8438 ERRMSG(
"Wrong version of binary data!");
8456 for (
int iq = 0; iq < ctl->
nq; iq++)
8457 FREAD(atm->
q[iq],
double,
8467 ERRMSG(
"Error while reading binary data!");
8479 const char *filename,
8484 ERRMSG(
"CLaMS atmospheric files support only lat/lon grids");
8489 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
8496 if (nc_inq_varid(ncid,
"TIME_INIT", &varid) == NC_NOERR) {
8497 NC(nc_get_var_double(ncid, varid, atm->
time));
8499 WARN(
"TIME_INIT not found use time instead!");
8502 for (
int ip = 0; ip < atm->
np; ip++) {
8503 atm->
time[ip] = time_init;
8515 if (nc_inq_varid(ncid,
"PRESS_INIT", &varid) == NC_NOERR) {
8516 NC(nc_get_var_double(ncid, varid, atm->
p));
8518 WARN(
"PRESS_INIT not found use PRESS instead!");
8519 nc_inq_varid(ncid,
"PRESS", &varid);
8520 NC(nc_get_var_double(ncid, varid, atm->
p));
8525 for (
int iq = 0; iq < ctl->
nq; iq++)
8542 const char *filename,
8549 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
8562 for (
int iq = 0; iq < ctl->
nq; iq++)
8575 const char *filename,
8581 LOG(1,
"Read photolysis rates: %s", filename);
8584 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
8585 WARN(
"Photolysis rate data are missing!");
8592 if (photo->
p[0] < photo->
p[1])
8593 ERRMSG(
"Pressure data are not descending!");
8598 if (photo->
o3c[0] > photo->
o3c[1])
8599 ERRMSG(
"Total column ozone data are not ascending!");
8604 if (photo->
sza[0] > photo->
sza[1])
8605 ERRMSG(
"Solar zenith angle data are not ascending!");
8622 LOG(2,
"Number of pressure levels: %d", photo->
np);
8623 LOG(2,
"Altitude levels: %g, %g ... %g km",
8624 Z(photo->
p[0]),
Z(photo->
p[1]),
Z(photo->
p[photo->
np - 1]));
8625 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
8626 photo->
p[0], photo->
p[1], photo->
p[photo->
np - 1]);
8627 LOG(2,
"Number of solar zenith angles: %d", photo->
nsza);
8628 LOG(2,
"Solar zenith angles: %g, %g ... %g deg",
8631 LOG(2,
"Number of total column ozone values: %d", photo->
no3c);
8632 LOG(2,
"Total column ozone: %g, %g ... %g DU",
8634 LOG(2,
"N2O photolysis rate: %g, %g ... %g s**-1",
8635 photo->
n2o[0][0][0], photo->
n2o[1][0][0],
8636 photo->
n2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
8637 LOG(2,
"CCl4 photolysis rate: %g, %g ... %g s**-1",
8638 photo->
ccl4[0][0][0], photo->
ccl4[1][0][0],
8640 LOG(2,
"CFC-11 photolysis rate: %g, %g ... %g s**-1",
8641 photo->
ccl3f[0][0][0], photo->
ccl3f[1][0][0],
8643 LOG(2,
"CFC-12 photolysis rate: %g, %g ... %g s**-1",
8646 LOG(2,
"O2 photolysis rate: %g, %g ... %g s**-1",
8647 photo->
o2[0][0][0], photo->
o2[1][0][0],
8648 photo->
o2[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
8649 LOG(2,
"O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
8650 photo->
o3_1[0][0][0], photo->
o3_1[1][0][0],
8652 LOG(2,
"O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
8653 photo->
o3_2[0][0][0], photo->
o3_2[1][0][0],
8655 LOG(2,
"H2O2 photolysis rate: %g, %g ... %g s**-1",
8656 photo->
h2o2[0][0][0], photo->
h2o2[1][0][0],
8658 LOG(2,
"H2O photolysis rate: %g, %g ... %g s**-1",
8659 photo->
h2o[0][0][0], photo->
h2o[1][0][0],
8660 photo->
h2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
8667 const char *varname,
8681 for (
int ip = 0; ip < photo->
np; ip++)
8682 for (
int is = 0; is < photo->
nsza; is++)
8683 for (
int io = 0; io < photo->
no3c; io++)
8694 const char *filename,
8698 LOG(1,
"Read climatological time series: %s", filename);
8702 if (!(in = fopen(filename,
"r"))) {
8703 WARN(
"Cannot open file!");
8710 while (fgets(line,
LEN, in))
8711 if (sscanf(line,
"%lg %lg", &ts->
time[nh], &ts->
vmr[nh]) == 2) {
8714 ts->
time[nh] = (ts->
time[nh] - 2000.0) * 365.25 * 86400.;
8717 if (nh > 0 && ts->
time[nh] <= ts->
time[nh - 1])
8718 ERRMSG(
"Time series must be ascending!");
8722 ERRMSG(
"Too many data points!");
8731 ERRMSG(
"Not enough data points!");
8734 LOG(2,
"Number of time steps: %d", ts->
ntime);
8735 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s", ts->
time[0], ts->
time[1],
8737 LOG(2,
"Volume mixing ratio range: %g ... %g ppv",
8738 gsl_stats_min(ts->
vmr, 1, (
size_t) nh), gsl_stats_max(ts->
vmr, 1,
8748 const char *filename,
8749 const char *varname,
8752 int ncid, varid, it, iy, iz, iz2, nt;
8754 double *help, varmin = 1e99, varmax = -1e99;
8757 LOG(1,
"Read %s data: %s", varname, filename);
8760 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
8761 WARN(
"%s climatology data are missing!", varname);
8768 if (zm->
p[0] < zm->
p[1])
8769 ERRMSG(
"Pressure data are not descending!");
8774 if (zm->
lat[0] > zm->
lat[1])
8775 ERRMSG(
"Latitude data are not ascending!");
8779 zm->
time[0] = 1209600.00;
8780 zm->
time[1] = 3888000.00;
8781 zm->
time[2] = 6393600.00;
8782 zm->
time[3] = 9072000.00;
8783 zm->
time[4] = 11664000.00;
8784 zm->
time[5] = 14342400.00;
8785 zm->
time[6] = 16934400.00;
8786 zm->
time[7] = 19612800.00;
8787 zm->
time[8] = 22291200.00;
8788 zm->
time[9] = 24883200.00;
8789 zm->
time[10] = 27561600.00;
8790 zm->
time[11] = 30153600.00;
8799 for (it = 0; it < zm->
ntime; it++)
8800 for (iz = 0; iz < zm->
np; iz++)
8801 for (iy = 0; iy < zm->
nlat; iy++)
8806 for (it = 0; it < zm->
ntime; it++)
8807 for (iy = 0; iy < zm->
nlat; iy++)
8808 for (iz = 0; iz < zm->
np; iz++) {
8809 if (zm->
vmr[it][iz][iy] < 0) {
8810 for (iz2 = 0; iz2 < zm->
np; iz2++)
8811 if (zm->
vmr[it][iz2][iy] >= 0) {
8812 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
8815 for (iz2 = zm->
np - 1; iz2 >= 0; iz2--)
8816 if (zm->
vmr[it][iz2][iy] >= 0) {
8817 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
8821 varmin =
MIN(varmin, zm->
vmr[it][iz][iy]);
8822 varmax =
MAX(varmax, zm->
vmr[it][iz][iy]);
8829 LOG(2,
"Number of time steps: %d", zm->
ntime);
8830 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
8832 LOG(2,
"Number of pressure levels: %d", zm->
np);
8833 LOG(2,
"Altitude levels: %g, %g ... %g km",
8834 Z(zm->
p[0]),
Z(zm->
p[1]),
Z(zm->
p[zm->
np - 1]));
8835 LOG(2,
"Pressure levels: %g, %g ... %g hPa", zm->
p[0],
8836 zm->
p[1], zm->
p[zm->
np - 1]);
8837 LOG(2,
"Number of latitudes: %d", zm->
nlat);
8838 LOG(2,
"Latitudes: %g, %g ... %g deg",
8840 LOG(2,
"%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
8847 const char *filename,
8853 LOG(1,
"Read kernel function: %s", filename);
8857 if (!(in = fopen(filename,
"r")))
8858 ERRMSG(
"Cannot open file!");
8863 while (fgets(line,
LEN, in))
8864 if (sscanf(line,
"%lg %lg", &kz[n], &kw[n]) == 2) {
8865 if (n > 0 && kz[n] < kz[n - 1])
8866 ERRMSG(
"Height levels must be ascending!");
8868 ERRMSG(
"Too many height levels!");
8877 ERRMSG(
"Not enough height levels!");
8880 const double kmax = gsl_stats_max(kw, 1, (
size_t) n);
8881 for (
int iz = 0; iz < n; iz++)
8888 const char *filename,
8896 int year, mon, day, hour, min, sec;
8902 if (!(in = fopen(filename,
"r"))) {
8903 WARN(
"Cannot open file!");
8909 FREAD(&met_type,
int,
8913 ERRMSG(
"Wrong MET_TYPE of binary data!");
8917 FREAD(&version,
int,
8921 ERRMSG(
"Wrong version of binary data!");
8927 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
8928 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
8929 met->
time, year, mon, day, hour, min);
8930 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
8931 || day < 1 || day > 31 || hour < 0 || hour > 23)
8932 ERRMSG(
"Error while reading time!");
8940 LOG(2,
"Number of %s: %d",
8941 (met->
coord_type == 0) ?
"longitudes" :
"x coordinates", met->
nx);
8942 if (met->
nx < 2 || met->
nx >
EX)
8944 ?
"Number of longitudes out of range!"
8945 :
"Number of x coordinates out of range!");
8950 LOG(2,
"Number of %s: %d",
8951 (met->
coord_type == 0) ?
"latitudes" :
"y coordinates", met->
ny);
8952 if (met->
ny < 2 || met->
ny >
EY)
8954 ?
"Number of latitudes out of range!"
8955 :
"Number of y coordinates out of range!");
8960 LOG(2,
"Number of levels: %d", met->
np);
8961 if (met->
np < 2 || met->
np >
EP)
8962 ERRMSG(
"Number of levels out of range!");
8968 LOG(2,
"%s: %g, %g ... %g %s",
8969 met->
coord_type == 0 ?
"Longitudes" :
"X coordinates",
8976 LOG(2,
"%s: %g, %g ... %g %s",
8977 met->
coord_type == 0 ?
"Latitudes" :
"Y coordinates",
8984 LOG(2,
"Altitude levels: %g, %g ... %g km",
8985 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
8986 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
8987 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
9036 ERRMSG(
"Error while reading binary data!");
9051 const char *varname) {
9060 LOG(2,
"Read 2-D variable: %s (uncompressed)", varname);
9062 (
size_t) (met->
nx * met->
ny),
9066 for (
int ix = 0; ix < met->
nx; ix++)
9067 for (
int iy = 0; iy < met->
ny; iy++)
9068 var[ix][iy] = help[
ARRAY_2D(ix, iy, met->
ny)];
9081 const char *varname,
9082 const float bound_min,
9083 const float bound_max) {
9093 LOG(2,
"Read 3-D variable: %s (uncompressed)", varname);
9095 (
size_t) (met->
nx * met->
ny * met->
np),
9107 FREAD(&precision,
int,
9112 FREAD(&tolerance,
double,
9118 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
9127 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
9136 ERRMSG(
"MPTRAC was compiled without LZ4 compression!");
9145 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
9153 FREAD(&precision,
int,
9158 FREAD(&tolerance,
double,
9164 ERRMSG(
"MPTRAC was compiled without sz3 compression!");
9169#pragma omp parallel for default(shared) collapse(2)
9170 for (
int ix = 0; ix < met->
nx; ix++)
9171 for (
int iy = 0; iy < met->
ny; iy++)
9172 for (
int ip = 0; ip < met->
np; ip++) {
9173 var[ix][iy][ip] = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9174 if (var[ix][iy][ip] < bound_min)
9175 var[ix][iy][ip] = bound_min;
9176 else if (var[ix][iy][ip] > bound_max)
9177 var[ix][iy][ip] = bound_max;
9196 ERRMSG(
"Only lat/lon grid supported");
9200 LOG(2,
"Calculate CAPE...");
9203 const double pfac = 1.01439, dz0 =
RI /
MA /
G0 * log(pfac);
9206#pragma omp parallel for default(shared) collapse(2)
9207 for (
int ix = 0; ix < met->
nx; ix++)
9208 for (
int iy = 0; iy < met->
ny; iy++) {
9212 double h2o = 0, t, theta = 0;
9213 double pbot =
MIN(met->
ps[ix][iy], met->
p[0]);
9214 double ptop = pbot - 50.;
9215 for (
int ip = 0; ip < met->
np; ip++) {
9216 if (met->
p[ip] <= pbot) {
9217 theta +=
THETA(met->
p[ip], met->
t[ix][iy][ip]);
9218 h2o += met->
h2o[ix][iy][ip];
9221 if (met->
p[ip] < ptop && n > 0)
9228 met->
plcl[ix][iy] = NAN;
9229 met->
plfc[ix][iy] = NAN;
9230 met->
pel[ix][iy] = NAN;
9231 met->
cape[ix][iy] = NAN;
9232 met->
cin[ix][iy] = NAN;
9238 pbot = met->
ps[ix][iy];
9240 met->
plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
9241 t = theta / pow(1000. / met->
plcl[ix][iy],
KAPPA);
9242 if (
RH(met->
plcl[ix][iy], t, h2o) > 100.)
9243 ptop = met->
plcl[ix][iy];
9245 pbot = met->
plcl[ix][iy];
9246 }
while (pbot - ptop > 0.1);
9250 double dcape, dz, h2o_env, t_env;
9251 double p = met->
ps[ix][iy];
9252 met->
cape[ix][iy] = met->
cin[ix][iy] = 0;
9254 dz = dz0 *
TVIRT(t, h2o);
9256 t = theta / pow(1000. / p,
KAPPA);
9260 &h2o_env, ci, cw, 0);
9261 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
9262 TVIRT(t_env, h2o_env) * dz;
9264 met->
cin[ix][iy] += fabsf((
float) dcape);
9265 }
while (p > met->
plcl[ix][iy]);
9270 p = met->
plcl[ix][iy];
9271 t = theta / pow(1000. / p,
KAPPA);
9276 dz = dz0 *
TVIRT(t, h2o);
9279 double psat =
PSAT(t);
9280 h2o = psat / (p - (1. -
EPS) * psat);
9284 &h2o_env, ci, cw, 0);
9285 double dcape_old = dcape;
9286 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
9287 TVIRT(t_env, h2o_env) * dz;
9289 met->
cape[ix][iy] += (float) dcape;
9290 if (!isfinite(met->
plfc[ix][iy]))
9291 met->
plfc[ix][iy] = (
float) p;
9292 }
else if (dcape_old > 0)
9293 met->
pel[ix][iy] = (float) p;
9294 if (dcape < 0 && !isfinite(met->
plfc[ix][iy]))
9295 met->
cin[ix][iy] += fabsf((
float) dcape);
9299 if (!isfinite(met->
plfc[ix][iy]))
9300 met->
cin[ix][iy] = NAN;
9311 LOG(2,
"Calculate cloud data...");
9314 const double ccmin = 0.01, cwmin = 1e-6;
9317#pragma omp parallel for default(shared) collapse(2)
9318 for (
int ix = 0; ix < met->
nx; ix++)
9319 for (
int iy = 0; iy < met->
ny; iy++) {
9322 met->
pct[ix][iy] = NAN;
9323 met->
pcb[ix][iy] = NAN;
9324 met->
cl[ix][iy] = 0;
9327 for (
int ip = 0; ip < met->
np - 1; ip++) {
9330 if (met->
p[ip] > met->
ps[ix][iy] || met->
p[ip] <
P(20.))
9334 if (met->
cc[ix][iy][ip] > ccmin
9335 && (met->
lwc[ix][iy][ip] > cwmin
9336 || met->
rwc[ix][iy][ip] > cwmin
9337 || met->
iwc[ix][iy][ip] > cwmin
9338 || met->
swc[ix][iy][ip] > cwmin)) {
9342 = (float) (0.5 * (met->
p[ip] + (
float) met->
p[ip + 1]));
9345 if (!isfinite(met->
pcb[ix][iy]))
9347 = (
float) (0.5 * (met->
p[ip] + met->
p[
MAX(ip - 1, 0)]));
9351 met->
cl[ix][iy] += (float)
9352 (0.5 * (met->
lwc[ix][iy][ip] + met->
lwc[ix][iy][ip + 1]
9353 + met->
rwc[ix][iy][ip] + met->
rwc[ix][iy][ip + 1]
9354 + met->
iwc[ix][iy][ip] + met->
iwc[ix][iy][ip + 1]
9355 + met->
swc[ix][iy][ip] + met->
swc[ix][iy][ip + 1])
9356 * 100. * (met->
p[ip] - met->
p[ip + 1]) /
G0);
9374 ERRMSG(
"Only lat/lon grid supported");
9378 LOG(2,
"Detrend meteo data...");
9385 const double tssq = 2. *
SQR(sigma);
9388 int sy = (int) (3. *
DY2DEG(sigma) / fabs(met->
lat[1] - met->
lat[0]));
9392#pragma omp parallel for default(shared) collapse(2)
9393 for (
int ix = 0; ix < met->
nx; ix++) {
9394 for (
int iy = 0; iy < met->
ny; iy++) {
9402 (int) (3. *
DX2DEG(sigma, met->
lat[iy]) /
9403 fabs(met->
lon[1] - met->
lon[0]));
9408 for (
int ip = 0; ip < met->
np; ip++) {
9409 help->
t[ix][iy][ip] = 0;
9410 help->
u[ix][iy][ip] = 0;
9411 help->
v[ix][iy][ip] = 0;
9412 help->
w[ix][iy][ip] = 0;
9416 for (
int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
9420 else if (ix3 >= met->
nx)
9422 for (
int iy2 =
MAX(iy - sy, 0);
9423 iy2 <=
MIN(iy + sy, met->
ny - 1); iy2++) {
9430 const float w = (float) exp(-
DIST2(x0, x1) / tssq);
9434 for (
int ip = 0; ip < met->
np; ip++) {
9435 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip];
9436 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip];
9437 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip];
9438 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip];
9444 for (
int ip = 0; ip < met->
np; ip++) {
9445 help->
t[ix][iy][ip] /= wsum;
9446 help->
u[ix][iy][ip] /= wsum;
9447 help->
v[ix][iy][ip] /= wsum;
9448 help->
w[ix][iy][ip] /= wsum;
9454#pragma omp parallel for default(shared) collapse(3)
9455 for (
int ix = 0; ix < met->
nx; ix++)
9456 for (
int iy = 0; iy < met->
ny; iy++)
9457 for (
int ip = 0; ip < met->
np; ip++) {
9458 met->
t[ix][iy][ip] -= help->
t[ix][iy][ip];
9459 met->
u[ix][iy][ip] -= help->
u[ix][iy][ip];
9460 met->
v[ix][iy][ip] -= help->
v[ix][iy][ip];
9461 met->
w[ix][iy][ip] -= help->
w[ix][iy][ip];
9475 LOG(2,
"Extrapolate meteo data...");
9478#pragma omp parallel for default(shared) collapse(2)
9479 for (
int ix = 0; ix < met->
nx; ix++)
9480 for (
int iy = 0; iy < met->
ny; iy++) {
9484 for (ip0 = met->
np - 1; ip0 >= 0; ip0--)
9485 if (!isfinite(met->
t[ix][iy][ip0])
9486 || !isfinite(met->
u[ix][iy][ip0])
9487 || !isfinite(met->
v[ix][iy][ip0])
9488 || !isfinite(met->
w[ix][iy][ip0]))
9492 for (
int ip = ip0; ip >= 0; ip--) {
9493 met->
t[ix][iy][ip] = met->
t[ix][iy][ip + 1];
9494 met->
u[ix][iy][ip] = met->
u[ix][iy][ip + 1];
9495 met->
v[ix][iy][ip] = met->
v[ix][iy][ip + 1];
9496 met->
w[ix][iy][ip] = met->
w[ix][iy][ip + 1];
9497 met->
h2o[ix][iy][ip] = met->
h2o[ix][iy][ip + 1];
9498 met->
o3[ix][iy][ip] = met->
o3[ix][iy][ip + 1];
9499 met->
lwc[ix][iy][ip] = met->
lwc[ix][iy][ip + 1];
9500 met->
rwc[ix][iy][ip] = met->
rwc[ix][iy][ip + 1];
9501 met->
iwc[ix][iy][ip] = met->
iwc[ix][iy][ip + 1];
9502 met->
swc[ix][iy][ip] = met->
swc[ix][iy][ip + 1];
9503 met->
cc[ix][iy][ip] = met->
cc[ix][iy][ip + 1];
9522 LOG(2,
"Calculate geopotential heights...");
9529#pragma omp parallel for default(shared)
9530 for (
int ip = 0; ip < met->
np; ip++)
9531 logp[ip] = log(met->
p[ip]);
9534#pragma omp parallel for default(shared) collapse(2)
9535 for (
int ix = 0; ix < met->
nx; ix++)
9536 for (
int iy = 0; iy < met->
ny; iy++) {
9539 const double zs = met->
zs[ix][iy];
9540 const double lnps = log(met->
ps[ix][iy]);
9544 const double ts =
LIN(met->
p[ip0], met->
t[ix][iy][ip0], met->
p[ip0 + 1],
9545 met->
t[ix][iy][ip0 + 1], met->
ps[ix][iy]);
9547 LIN(met->
p[ip0], met->
h2o[ix][iy][ip0], met->
p[ip0 + 1],
9548 met->
h2o[ix][iy][ip0 + 1], met->
ps[ix][iy]);
9551 met->
z[ix][iy][ip0 + 1]
9553 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
9554 met->
t[ix][iy][ip0 + 1], met->
h2o[ix][iy][ip0 + 1]));
9555 for (
int ip = ip0 + 2; ip < met->
np; ip++)
9557 = (
float) (met->
z[ix][iy][ip - 1] +
9558 ZDIFF(logp[ip - 1], met->
t[ix][iy][ip - 1],
9559 met->
h2o[ix][iy][ip - 1], logp[ip],
9560 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
9565 ZDIFF(lnps, ts, h2os, logp[ip0],
9566 met->
t[ix][iy][ip0], met->
h2o[ix][iy][ip0]));
9567 for (
int ip = ip0 - 1; ip >= 0; ip--)
9569 = (
float) (met->
z[ix][iy][ip + 1] +
9570 ZDIFF(logp[ip + 1], met->
t[ix][iy][ip + 1],
9571 met->
h2o[ix][iy][ip + 1], logp[ip],
9572 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
9576 if (dx == 0 || dy == 0)
9580 if (dx < 0 || dy < 0) {
9581 if (fabs(met->
lon[1] - met->
lon[0]) < 0.5) {
9591 float ws[dx + 1][dy + 1];
9592#pragma omp parallel for default(shared) collapse(2)
9593 for (
int ix = 0; ix <= dx; ix++)
9594 for (
int iy = 0; iy < dy; iy++)
9595 ws[ix][iy] = (1.0f - (
float) ix / (float) dx)
9596 * (1.0f - (float) iy / (
float) dy);
9599#pragma omp parallel for default(shared) collapse(3)
9600 for (
int ix = 0; ix < met->
nx; ix++)
9601 for (
int iy = 0; iy < met->
ny; iy++)
9602 for (
int ip = 0; ip < met->
np; ip++)
9603 help[
ARRAY_3D(ip, ix, met->
nx, iy, met->
ny)] = met->
z[ix][iy][ip];
9606#pragma omp parallel for default(shared) collapse(3)
9607 for (
int ip = 0; ip < met->
np; ip++)
9608 for (
int ix = 0; ix < met->
nx; ix++)
9609 for (
int iy = 0; iy < met->
ny; iy++) {
9610 float res = 0, wsum = 0;
9611 int iy0 =
MAX(iy - dy + 1, 0);
9612 int iy1 =
MIN(iy + dy - 1, met->
ny - 1);
9613 for (
int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
9617 else if (ix3 >= met->
nx)
9619 for (
int iy2 = iy0; iy2 <= iy1; ++iy2)
9620 if (isfinite(help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)])) {
9621 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
9622 res += w * help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)];
9627 met->
z[ix][iy][ip] = res / wsum;
9629 met->
z[ix][iy][ip] = NAN;
9639 const char *filename,
9645 char levname[
LEN], tstr[10];
9647 double rtime = 0, r, r2;
9649 int varid, ndims, dimids[NC_MAX_DIMS], year2, mon2, day2, hour2, min2, sec2,
9650 year, mon, day, hour, min, sec;
9656 LOG(2,
"Read meteo grid information...");
9665 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
9666 if (nc_inq_varid(ncid,
"time", &varid) == NC_NOERR) {
9667 NC(nc_get_var_double(ncid, varid, &rtime));
9668 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
9669 WARN(
"Time information in meteo file does not match filename!");
9671 WARN(
"Time information in meteo file is missing!");
9682 sprintf(tstr,
"19%.2s", &filename[strlen(filename) - 11]);
9684 sprintf(tstr,
"20%.2s", &filename[strlen(filename) - 11]);
9686 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 9]);
9688 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 7]);
9690 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 5]);
9696 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
9697 || day < 1 || day > 31 || hour < 0 || hour > 23)
9698 ERRMSG(
"Cannot read time from filename!");
9699 jsec2time(met->
time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
9700 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
9701 met->
time, year2, mon2, day2, hour2, min2);
9704 if (nc_inq_varid(ncid,
"u", &varid) != NC_NOERR)
9705 if (nc_inq_varid(ncid,
"U", &varid) != NC_NOERR)
9707 (
"Variable 'u' or 'U' not found, cannot determine vertical dimension!");
9709 NC(nc_inq_varndims(ncid, varid, &ndims));
9710 NC(nc_inq_vardimid(ncid, varid, dimids));
9714 (ncid, dimids[ctl->
met_convention == 0 ? 1 : 3], levname, &dimlen));
9715 }
else if (ndims == 3) {
9717 (ncid, dimids[ctl->
met_convention == 0 ? 0 : 2], levname, &dimlen));
9719 ERRMSG(
"Cannot determine vertical dimension!")
9720 met->
np = (int) dimlen;
9722 LOG(2,
"Number of levels: %d", met->
np);
9723 if (met->
np < 2 || met->
np >
EP)
9724 ERRMSG(
"Number of levels out of range!");
9732 LOG(2,
"Number of longitudes: %d", met->
nx);
9735 LOG(2,
"Number of latitudes: %d", met->
ny);
9738 LOG(2,
"Longitudes: %g, %g ... %g deg",
9741 LOG(2,
"Latitudes: %g, %g ... %g deg",
9747 LOG(2,
"Number of x coordinates: %d", met->
nx);
9750 LOG(2,
"Number of y coordinates: %d", met->
ny);
9753 LOG(2,
"X coordinates: %g, %g ... %g m",
9756 LOG(2,
"Y coordinates: %g, %g ... %g m",
9763 ERRMSG(
"Domain decomposition is only supported for lat/lon grids!");
9773 for (
int ip = 0; ip < met->
np; ip++)
9775 LOG(2,
"Altitude levels: %g, %g ... %g km",
9776 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
9777 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
9778 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
9782 if (strcasecmp(levname,
"hybrid") == 0)
9794 ERRMSG(
"You need to specify MET_NLEV, MET_LEV_HYAM, and MET_LEV_HYBM!");
9795 for (
int ip = 0; ip < ctl->
met_nlev; ip++) {
9803 met->
eta[k] = met->
hyam[k] / 100000.0 + met->
hybm[k];
9805 ERRMSG(
"Eta levels must be ascending!");
9809 for (
int ix = 2; ix < met->
nx; ix++)
9811 (fabs(met->
lon[ix] - met->
lon[ix - 1]) -
9812 fabs(met->
lon[1] - met->
lon[0])) > 0.001)
9813 ERRMSG(
"No regular grid spacing in longitudes!");
9814 for (
int iy = 2; iy < met->
ny; iy++)
9816 (fabs(met->
lat[iy] - met->
lat[iy - 1]) -
9817 fabs(met->
lat[1] - met->
lat[0])) > 0.001) {
9818 WARN(
"No regular grid spacing in latitudes!");
9833 LOG(2,
"Read surface data...");
9837 (ncid,
"lnsp",
"LNSP", NULL, NULL, NULL, NULL, ctl, met, dd, met->
ps,
9839 for (
int ix = 0; ix < met->
nx; ix++)
9840 for (
int iy = 0; iy < met->
ny; iy++)
9841 met->
ps[ix][iy] = (
float) (exp(met->
ps[ix][iy]) / 100.);
9844 (ncid,
"ps",
"PS",
"sp",
"SP", NULL, NULL, ctl, met, dd, met->
ps,
9846 WARN(
"Cannot not read surface pressure data (use lowest level)!");
9847 for (
int ix = 0; ix < met->
nx; ix++)
9848 for (
int iy = 0; iy < met->
ny; iy++)
9850 = (ctl->
met_np > 0 ? (
float) ctl->
met_p[0] : (
float) met->
p[0]);
9858 (ncid,
"z",
"Z", NULL, NULL, NULL, NULL, ctl, met, dd, met->
zs,
9859 (
float) (1. / (1000. *
G0)), 1))
9861 (ncid,
"zm",
"ZM", NULL, NULL, NULL, NULL, ctl, met, dd, met->
zs,
9862 (ctl->
met_gp2z ? (
float) (1e-3 /
G0) : (
float) (1. / 1000.)), 1))
9863 WARN(
"Cannot read surface geopotential height!");
9874 memcpy(help, met->
pl,
sizeof(met->
pl));
9876 (ncid,
"gph",
"GPH", NULL, NULL, ctl, met, dd, met->
pl,
9877 (
float) (1e-3 /
G0)))
9878 ERRMSG(
"Cannot read geopotential height!");
9879 for (
int ix = 0; ix < met->
nx; ix++)
9880 for (
int iy = 0; iy < met->
ny; iy++)
9881 met->
zs[ix][iy] = met->
pl[ix][iy][0];
9882 memcpy(met->
pl, help,
sizeof(met->
pl));
9888 (ncid,
"t2m",
"T2M",
"2t",
"2T",
"t2",
"T2", ctl, met, dd, met->
ts, 1.0,
9890 WARN(
"Cannot read surface temperature!");
9894 (ncid,
"u10m",
"U10M",
"10u",
"10U",
"u10",
"U10", ctl, met, dd,
9896 WARN(
"Cannot read surface zonal wind!");
9900 (ncid,
"v10m",
"V10M",
"10v",
"10V",
"v10",
"V10", ctl, met, dd,
9902 WARN(
"Cannot read surface meridional wind!");
9906 (ncid,
"iews",
"IEWS", NULL, NULL, NULL, NULL, ctl, met, dd, met->
ess,
9908 WARN(
"Cannot read eastward turbulent surface stress!");
9912 (ncid,
"inss",
"INSS", NULL, NULL, NULL, NULL, ctl, met, dd, met->
nss,
9914 WARN(
"Cannot read nothward turbulent surface stress!");
9918 (ncid,
"ishf",
"ISHF", NULL, NULL, NULL, NULL, ctl, met, dd, met->
shf,
9920 WARN(
"Cannot read surface sensible heat flux!");
9924 (ncid,
"lsm",
"LSM", NULL, NULL, NULL, NULL, ctl, met, dd, met->
lsm,
9926 WARN(
"Cannot read land-sea mask!");
9930 (ncid,
"sstk",
"SSTK",
"sst",
"SST", NULL, NULL, ctl, met, dd, met->
sst,
9932 WARN(
"Cannot read sea surface temperature!");
9937 (ncid,
"blp",
"BLP", NULL, NULL, NULL, NULL, ctl, met, dd, met->
pbl,
9939 WARN(
"Cannot read planetary boundary layer pressure!");
9942 (ncid,
"blh",
"BLH", NULL, NULL, NULL, NULL, ctl, met, dd, met->
pbl,
9944 WARN(
"Cannot read planetary boundary layer height!");
9949 (ncid,
"cape",
"CAPE", NULL, NULL, NULL, NULL, ctl, met, dd,
9951 WARN(
"Cannot read CAPE!");
9956 (ncid,
"cin",
"CIN", NULL, NULL, NULL, NULL, ctl, met, dd, met->
cin,
9958 WARN(
"Cannot read convective inhibition!");
9971 LOG(2,
"Read level data...");
9975 (ncid,
"t",
"T",
"temp",
"TEMP", ctl, met, dd, met->
t, 1.0))
9976 ERRMSG(
"Cannot read temperature!");
9979 if (!
read_met_nc_3d(ncid,
"u",
"U", NULL, NULL, ctl, met, dd, met->
u, 1.0))
9980 ERRMSG(
"Cannot read zonal wind!");
9981 if (!
read_met_nc_3d(ncid,
"v",
"V", NULL, NULL, ctl, met, dd, met->
v, 1.0))
9982 ERRMSG(
"Cannot read meridional wind!");
9984 (ncid,
"w",
"W",
"omega",
"OMEGA", ctl, met, dd, met->
w, 0.01f))
9985 WARN(
"Cannot read vertical velocity!");
9990 (ncid,
"q",
"Q",
"sh",
"SH", ctl, met, dd, met->
h2o,
9992 WARN(
"Cannot read specific humidity!");
9995 (ncid,
"rh",
"RH", NULL, NULL, ctl, met, dd, met->
h2o, 0.01f))
9996 WARN(
"Cannot read relative humidity!");
9997#pragma omp parallel for default(shared) collapse(2)
9998 for (
int ix = 0; ix < met->
nx; ix++)
9999 for (
int iy = 0; iy < met->
ny; iy++)
10000 for (
int ip = 0; ip < met->
np; ip++) {
10001 double pw = met->
h2o[ix][iy][ip] *
PSAT(met->
t[ix][iy][ip]);
10002 met->
h2o[ix][iy][ip] =
10003 (float) (pw / (met->
p[ip] - (1.0 -
EPS) * pw));
10009 (ncid,
"o3",
"O3", NULL, NULL, ctl, met, dd, met->
o3,
10010 (
float) (
MA /
MO3)))
10011 WARN(
"Cannot read ozone data!");
10015 (ncid,
"clwc",
"CLWC", NULL, NULL, ctl, met, dd, met->
lwc, 1.0))
10016 WARN(
"Cannot read cloud liquid water content!");
10018 (ncid,
"crwc",
"CRWC", NULL, NULL, ctl, met, dd, met->
rwc, 1.0))
10019 WARN(
"Cannot read cloud rain water content!");
10021 (ncid,
"ciwc",
"CIWC", NULL, NULL, ctl, met, dd, met->
iwc, 1.0))
10022 WARN(
"Cannot read cloud ice water content!");
10024 (ncid,
"cswc",
"CSWC", NULL, NULL, ctl, met, dd, met->
swc, 1.0))
10025 WARN(
"Cannot read cloud snow water content!");
10027 (ncid,
"cc",
"CC", NULL, NULL, ctl, met, dd, met->
cc, 1.0))
10028 WARN(
"Cannot read cloud cover!");
10033 (ncid,
"ZETA",
"zeta", NULL, NULL, ctl, met, dd, met->
zetal, 1.0))
10034 WARN(
"Cannot read ZETA!");
10036 (ncid,
"ZETA_DOT_TOT",
"ZETA_DOT_clr",
"zeta_dot_clr",
10037 NULL, ctl, met, dd, met->
zeta_dotl, 0.00001157407f))
10038 WARN(
"Cannot read ZETA_DOT!");
10043#pragma omp parallel for default(shared)
10044 for (
int ix = 0; ix < met->
nx; ix++)
10045 for (
int iy = 0; iy < met->
ny; iy++)
10046 for (
int ip = 0; ip < met->
np; ip++)
10047 met->
zetal[ix][iy][ip] =
10048 (
float) (met->
hyam[ip] / 100000.0 + met->
hybm[ip]);
10050 (ncid,
"etadot",
"ETADOT", NULL, NULL, ctl, met, dd, met->
zeta_dotl,
10052 WARN(
"Cannot read eta vertical velocity!");
10057#pragma omp parallel for default(shared)
10058 for (
int ix = 0; ix < met->
nx; ix++)
10059 for (
int iy = 0; iy < met->
ny; iy++)
10060 for (
int ip = 0; ip < met->
np; ip++) {
10061 met->
ul[ix][iy][ip] = met->
u[ix][iy][ip];
10062 met->
vl[ix][iy][ip] = met->
v[ix][iy][ip];
10063 met->
wl[ix][iy][ip] = met->
w[ix][iy][ip];
10067 met->
npl = met->
np;
10076 (ncid,
"pl",
"PL",
"pressure",
"PRESSURE", ctl, met, dd, met->
pl,
10079 (ncid,
"press",
"PRESS", NULL, NULL, ctl, met, dd, met->
pl, 1.0))
10080 ERRMSG(
"Cannot read pressure on model levels!");
10088 ERRMSG(
"Mismatch in number of model levels!");
10091 for (
int ix = 0; ix < met->
nx; ix++)
10092 for (
int iy = 0; iy < met->
ny; iy++)
10093 for (
int ip = 0; ip < met->
np; ip++)
10094 met->
pl[ix][iy][ip] =
10095 (
float) (met->
hyam[ip] / 100. +
10096 met->
hybm[ip] * met->
ps[ix][iy]);
10104 ERRMSG(
"Mismatch in number of model levels!");
10107#pragma omp parallel for default(shared) collapse(2)
10108 for (
int ix = 0; ix < met->
nx; ix++)
10109 for (
int iy = 0; iy < met->
ny; iy++)
10110 for (
int ip = 0; ip < met->
np; ip++) {
10112 met->
hyam[ip] / 100. + met->
hybm[ip] * met->
ps[ix][iy];
10114 met->
hyam[ip + 1] / 100. + met->
hybm[ip + 1] * met->
ps[ix][iy];
10115 met->
pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
10120 for (
int ix = 0; ix < met->
nx; ix++)
10121 for (
int iy = 0; iy < met->
ny; iy++)
10122 for (
int ip = 1; ip < met->
np; ip++)
10123 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
10124 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
10125 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
10126 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip]))
10127 ERRMSG(
"Pressure profiles are not monotonic!");
10148 for (
int ip = 0; ip < met->
np; ip++)
10149 met->
p[ip] = ctl->
met_p[ip];
10153 for (
int ip = 1; ip < met->
np; ip++)
10154 if (met->
p[ip - 1] < met->
p[ip])
10155 ERRMSG(
"Pressure levels must be descending!");
10162 const char *varname,
10163 const char *varname2,
10164 const char *varname3,
10165 const char *varname4,
10166 const char *varname5,
10167 const char *varname6,
10171 float dest[
EX][
EY],
10177 float offset, scalfac;
10182 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
10183 sprintf(varsel,
"%s", varname);
10184 else if (varname2 != NULL
10185 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
10186 sprintf(varsel,
"%s", varname2);
10187 else if (varname3 != NULL
10188 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
10189 sprintf(varsel,
"%s", varname3);
10190 else if (varname4 != NULL
10191 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
10192 sprintf(varsel,
"%s", varname4);
10193 else if (varname5 != NULL
10194 && nc_inq_varid(ncid, varname5, &varid) == NC_NOERR)
10195 sprintf(varsel,
"%s", varname5);
10196 else if (varname6 != NULL
10197 && nc_inq_varid(ncid, varname6, &varid) == NC_NOERR)
10198 sprintf(varsel,
"%s", varname6);
10204 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
10205 && nc_get_att_float(ncid, varid,
"scale_factor",
10206 &scalfac) == NC_NOERR) {
10214 short fillval, missval;
10215 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
10217 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
10221 LOG(2,
"Read 2-D variable: %s"
10222 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
10223 varsel, fillval, missval, scalfac, offset);
10226 NC(nc_get_var_short(ncid, varid, help));
10230 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
10233 omp_set_dynamic(1);
10234#pragma omp parallel for default(shared)
10235 for (
int ix = 0; ix < met->
nx; ix++)
10236 for (
int iy = 0; iy < met->
ny; iy++) {
10239 const short aux = help[
ARRAY_2D(iy, ix, met->
nx)];
10240 if ((fillval == 0 || aux != fillval)
10241 && (missval == 0 || aux != missval)
10242 && fabsf(aux * scalfac + offset) < 1e14f)
10243 dest[ix][iy] += scl * (aux * scalfac + offset);
10245 dest[ix][iy] = NAN;
10247 omp_set_dynamic(0);
10254 else if (!ctl->
dd) {
10262 float fillval, missval;
10263 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
10265 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
10269 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
10270 varsel, fillval, missval);
10273 NC(nc_get_var_float(ncid, varid, help));
10279 omp_set_dynamic(1);
10280#pragma omp parallel for default(shared)
10281 for (
int ix = 0; ix < met->
nx; ix++)
10282 for (
int iy = 0; iy < met->
ny; iy++) {
10285 const float aux = help[
ARRAY_2D(iy, ix, met->
nx)];
10286 if ((fillval == 0 || aux != fillval)
10287 && (missval == 0 || aux != missval)
10288 && fabsf(aux) < 1e14f)
10289 dest[ix][iy] += scl * aux;
10291 dest[ix][iy] = NAN;
10293 omp_set_dynamic(0);
10298 omp_set_dynamic(1);
10299#pragma omp parallel for default(shared)
10300 for (
int iy = 0; iy < met->
ny; iy++)
10301 for (
int ix = 0; ix < met->
nx; ix++) {
10304 const float aux = help[
ARRAY_2D(ix, iy, met->
ny)];
10305 if ((fillval == 0 || aux != fillval)
10306 && (missval == 0 || aux != missval)
10307 && fabsf(aux) < 1e14f)
10308 dest[ix][iy] += scl * aux;
10310 dest[ix][iy] = NAN;
10312 omp_set_dynamic(0);
10323 float fillval, missval;
10324 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
10326 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
10330 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
10331 varsel, fillval, missval);
10335 size_t help_subdomain_start[3];
10336 size_t help_subdomain_count[3];
10338 help_subdomain_start[0] = 0;
10347 help_subdomain_count[0] = 1;
10361 nc_var_par_access(ncid, varid, NC_COLLECTIVE);
10363 NC(nc_get_vara_float
10364 (ncid, varid, help_subdomain_start, help_subdomain_count, help));
10367 size_t help_halo_bnd_start[3];
10368 size_t help_halo_bnd_count[3];
10370 help_halo_bnd_start[0] = 0;
10379 help_halo_bnd_count[0] = 1;
10389 ALLOC(help_halo,
float,
10390 help_halo_bnd_count[1] * help_halo_bnd_count[2]);
10393 nc_var_par_access(ncid, varid, NC_COLLECTIVE);
10395 NC(nc_get_vara_float
10396 (ncid, varid, help_halo_bnd_start, help_halo_bnd_count, help_halo));
10402 omp_set_dynamic(1);
10403#pragma omp parallel for default(shared)
10404 for (
int ix = 0; ix < (int) help_subdomain_count[2]; ix++)
10405 for (
int iy = 0; iy < (int) help_subdomain_count[1]; iy++) {
10409 help[
ARRAY_2D(iy, ix, (
int) help_subdomain_count[2])];
10410 if ((fillval == 0 || aux != fillval)
10411 && (missval == 0 || aux != missval)
10412 && fabsf(aux) < 1e14f) {
10418#pragma omp parallel for default(shared)
10419 for (
int ix = 0; ix < (int) help_halo_bnd_count[2]; ix++)
10420 for (
int iy = 0; iy < (int) help_halo_bnd_count[1]; iy++) {
10424 help_halo[
ARRAY_2D(iy, ix, (
int) help_halo_bnd_count[2])];
10425 if ((fillval == 0 || aux != fillval)
10426 && (missval == 0 || aux != missval)
10427 && fabsf(aux) < 1e14f)
10433 omp_set_dynamic(0);
10438 omp_set_dynamic(1);
10439#pragma omp parallel for default(shared)
10440 for (
int ix = 0; ix < (int) help_subdomain_count[1]; ix++)
10441 for (
int iy = 0; iy < (int) help_subdomain_count[2]; iy++) {
10445 help[
ARRAY_2D(ix, iy, (
int) help_subdomain_count[1])];
10446 if ((fillval == 0 || aux != fillval)
10447 && (missval == 0 || aux != missval)
10448 && fabsf(aux) < 1e14f)
10454#pragma omp parallel for default(shared)
10455 for (
int ix = 0; ix < (int) help_halo_bnd_count[1]; ix++)
10456 for (
int iy = 0; iy < (int) help_halo_bnd_count[2]; iy++) {
10460 help_halo[
ARRAY_2D(ix, iy, (
int) help_halo_bnd_count[1])];
10461 if ((fillval == 0 || aux != fillval)
10462 && (missval == 0 || aux != missval)
10463 && fabsf(aux) < 1e14f)
10468 omp_set_dynamic(0);
10484 const char *varname,
10485 const char *varname2,
10486 const char *varname3,
10487 const char *varname4,
10496 float offset, scalfac;
10501 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
10502 sprintf(varsel,
"%s", varname);
10503 else if (varname2 != NULL
10504 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
10505 sprintf(varsel,
"%s", varname2);
10506 else if (varname3 != NULL
10507 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
10508 sprintf(varsel,
"%s", varname3);
10509 else if (varname4 != NULL
10510 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
10511 sprintf(varsel,
"%s", varname4);
10517 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
10518 && nc_get_att_float(ncid, varid,
"scale_factor",
10519 &scalfac) == NC_NOERR) {
10527 short fillval, missval;
10528 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
10530 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
10534 LOG(2,
"Read 3-D variable: %s "
10535 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
10536 varsel, fillval, missval, scalfac, offset);
10539 NC(nc_get_var_short(ncid, varid, help));
10543 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
10546 omp_set_dynamic(1);
10547#pragma omp parallel for default(shared)
10548 for (
int ix = 0; ix < met->
nx; ix++)
10549 for (
int iy = 0; iy < met->
ny; iy++)
10550 for (
int ip = 0; ip < met->
np; ip++) {
10551 const short aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
10552 if ((fillval == 0 || aux != fillval)
10553 && (missval == 0 || aux != missval)
10554 && fabsf(aux * scalfac + offset) < 1e14f)
10555 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
10557 dest[ix][iy][ip] = NAN;
10559 omp_set_dynamic(0);
10566 else if (!ctl->
dd) {
10574 float fillval, missval;
10575 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
10577 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
10581 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
10582 varsel, fillval, missval);
10585 NC(nc_get_var_float(ncid, varid, help));
10591 omp_set_dynamic(1);
10592#pragma omp parallel for default(shared)
10593 for (
int ix = 0; ix < met->
nx; ix++)
10594 for (
int iy = 0; iy < met->
ny; iy++)
10595 for (
int ip = 0; ip < met->
np; ip++) {
10596 const float aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
10597 if ((fillval == 0 || aux != fillval)
10598 && (missval == 0 || aux != missval)
10599 && fabsf(aux) < 1e14f)
10600 dest[ix][iy][ip] = scl * aux;
10602 dest[ix][iy][ip] = NAN;
10604 omp_set_dynamic(0);
10609 omp_set_dynamic(1);
10610#pragma omp parallel for default(shared)
10611 for (
int ip = 0; ip < met->
np; ip++)
10612 for (
int iy = 0; iy < met->
ny; iy++)
10613 for (
int ix = 0; ix < met->
nx; ix++) {
10614 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
10615 if ((fillval == 0 || aux != fillval)
10616 && (missval == 0 || aux != missval)
10617 && fabsf(aux) < 1e14f)
10618 dest[ix][iy][ip] = scl * aux;
10620 dest[ix][iy][ip] = NAN;
10622 omp_set_dynamic(0);
10633 float fillval, missval;
10634 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
10636 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
10640 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
10641 varsel, fillval, missval);
10644 size_t help_subdomain_start[4];
10645 size_t help_subdomain_count[4];
10646 size_t help_halo_bnd_start[4];
10647 size_t help_halo_bnd_count[4];
10650 for (
int i = 0; i < 4; i++) {
10686 NC(nc_var_par_access(ncid, varid, NC_INDEPENDENT));
10688 NC(nc_get_vara_float
10689 (ncid, varid, help_subdomain_start, help_subdomain_count, help));
10693 ALLOC(help_halo,
float,
10698 NC(nc_var_par_access(ncid, varid, NC_INDEPENDENT));
10702 NC(nc_get_vara_float
10703 (ncid, varid, help_halo_bnd_start, help_halo_bnd_count, help_halo));
10710 omp_set_dynamic(1);
10711#pragma omp parallel for default(shared)
10714 for (
int ip = 0; ip < met->
np; ip++) {
10718 if ((fillval == 0 || aux != fillval)
10719 && (missval == 0 || aux != missval)
10720 && fabsf(aux) < 1e14f) {
10727#pragma omp parallel for default(shared)
10730 for (
int ip = 0; ip < met->
np; ip++) {
10734 if ((fillval == 0 || aux != fillval)
10735 && (missval == 0 || aux != missval)
10736 && fabsf(aux) < 1e14f)
10741 omp_set_dynamic(0);
10746 omp_set_dynamic(1);
10747#pragma omp parallel for default(shared)
10748 for (
int ip = 0; ip < met->
np; ip++)
10754 if ((fillval == 0 || aux != fillval)
10755 && (missval == 0 || aux != missval)
10756 && fabsf(aux) < 1e14f)
10762#pragma omp parallel for default(shared)
10763 for (
int ip = 0; ip < met->
np; ip++)
10769 if ((fillval == 0 || aux != fillval)
10770 && (missval == 0 || aux != missval)
10771 && fabsf(aux) < 1e14f)
10776 omp_set_dynamic(0);
10792 const char *filename,
10797 size_t filename_len = strlen(filename) + 1;
10798 char sf_filename[filename_len];
10799 char ml_filename[filename_len];
10800 strcpy(sf_filename, filename);
10801 strcpy(ml_filename, filename);
10806 FILE *ml_file = fopen(ml_filename,
"rb");
10807 FILE *sf_file = fopen(sf_filename,
"rb");
10808 if (ml_file == NULL || sf_file == NULL) {
10809 if (ml_file != NULL) {
10811 WARN(
"Cannot open file: %s", sf_filename);
10813 if (sf_file != NULL) {
10815 WARN(
"Cannot open file: %s", ml_filename);
10821 int ml_num_messages = 0, err = 0;
10822 ECC(codes_count_in_file(0, ml_file, &ml_num_messages));
10825 (size_t) ml_num_messages);
10826 for (
int i = 0; i < ml_num_messages; i++) {
10828 if ((h = codes_grib_handle_new_from_file(0, ml_file, &err)) != NULL)
10833 int sf_num_messages = 0;
10834 ECC(codes_count_in_file(0, sf_file, &sf_num_messages));
10837 (size_t) sf_num_messages);
10838 for (
int i = 0; i < sf_num_messages; i++) {
10840 if ((h = codes_grib_handle_new_from_file(0, sf_file, &err)) != NULL)
10853 for (
int i = 0; i < sf_num_messages; i++)
10854 codes_handle_delete(sf_handles[i]);
10858 size_t value_count = 0;
10859 ECC(codes_get_size(ml_handles[0],
"pv", &value_count));
10860 if (value_count % 2 != 0)
10861 ERRMSG(
"Unexpected pv array length!");
10862 size_t nlevels = value_count / 2 - 1;
10864 ALLOC(values,
double,
10866 ECC(codes_get_double_array(ml_handles[0],
"pv", values, &value_count));
10867 double *a_vals = values;
10868 double *b_vals = values + nlevels;
10869 if (met->
npl > (
int) nlevels)
10870 ERRMSG(
"met->npl exceeds number of pressure levels in GRIB!");
10871 for (
int nx = 0; nx < met->
nx; nx++)
10872 for (
int ny = 0; ny < met->
ny; ny++)
10873 for (
int level = 0; level <= met->
npl; level++) {
10874 const float p1 = (float) (a_vals[level] * 0.01f +
10875 met->
ps[nx][ny] * b_vals[level]);
10876 const float p2 = (float) (a_vals[level + 1] * 0.01f +
10877 met->
ps[nx][ny] * b_vals[level + 1]);
10878 met->
pl[nx][ny][level] = 0.5f * (p1 + p2);
10884 for (
int i = 0; i < ml_num_messages; i++)
10885 codes_handle_delete(ml_handles[i]);
10903 LOG(2,
"Read meteo grid information...");
10906 char datestr[
LEN], timestr[
LEN];
10907 size_t s_date =
sizeof(datestr);
10908 ECC(codes_get_string(handles[0],
"dataDate", datestr, &s_date));
10909 size_t s_time =
sizeof(timestr);
10910 ECC(codes_get_string(handles[0],
"dataTime", timestr, &s_time));
10911 int year, month, day, hour;
10912 if (sscanf(datestr,
"%4d%2d%2d", &year, &month, &day) != 3)
10913 ERRMSG(
"Failed to parse dataDate: %s", datestr);
10914 if (sscanf(timestr,
"%2d", &hour) != 1)
10915 ERRMSG(
"Failed to parse dataTime: %s", timestr);
10917 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)", met->
time, year, month,
10921 long count_lat = 0, count_lon = 0;
10922 ECC(codes_get_long(handles[0],
"Nj", &count_lat));
10923 ECC(codes_get_long(handles[0],
"Ni", &count_lon));
10924 met->
ny = (int) count_lat;
10925 met->
nx = (int) count_lon;
10928 LOG(2,
"Number of longitudes: %d", met->
nx);
10929 if (met->
nx < 2 || met->
nx >
EX)
10930 ERRMSG(
"Number of longitudes out of range!");
10931 LOG(2,
"Number of latitudes: %d", met->
ny);
10932 if (met->
ny < 2 || met->
ny >
EY)
10933 ERRMSG(
"Number of latitudes out of range!");
10935 double first_lon, last_lon, first_lat, last_lat, inc_lon, inc_lat;
10936 ECC(codes_get_double
10937 (handles[0],
"longitudeOfFirstGridPointInDegrees", &first_lon));
10938 ECC(codes_get_double
10939 (handles[0],
"latitudeOfFirstGridPointInDegrees", &first_lat));
10940 ECC(codes_get_double
10941 (handles[0],
"longitudeOfLastGridPointInDegrees", &last_lon));
10942 ECC(codes_get_double
10943 (handles[0],
"latitudeOfLastGridPointInDegrees", &last_lat));
10944 ECC(codes_get_double(handles[0],
"iDirectionIncrementInDegrees", &inc_lon));
10945 ECC(codes_get_double(handles[0],
"jDirectionIncrementInDegrees", &inc_lat));
10947 long jscanpos, iscanneg;
10948 ECC(codes_get_long(handles[0],
"iScansNegatively", &iscanneg));
10949 ECC(codes_get_long(handles[0],
"jScansPositively", &jscanpos));
10954 for (
double i = first_lon; i <= last_lon + 1e-6; i += inc_lon) {
10955 met->
lon[counter] = i;
10958 for (
double i = first_lon; i > last_lon - 1e-6; i -= inc_lon) {
10959 met->
lon[counter] = i;
10965 for (
double i = first_lat; i > last_lat - 1e-6; i -= inc_lat) {
10966 met->
lat[counter] = i;
10969 for (
double i = first_lat; i <= last_lat + 1e-6; i += inc_lat) {
10970 met->
lat[counter] = i;
10975 LOG(2,
"Longitudes: %g, %g ... %g deg",
10976 met->
lon[0], met->
lon[1], met->
lon[met->
nx - 1]);
10977 LOG(2,
"Latitudes: %g, %g ... %g deg",
10978 met->
lat[0], met->
lat[1], met->
lat[met->
ny - 1]);
10982 for (
int i = 0; i < count_handles; i++) {
10984 ECC(codes_get_long(handles[i],
"level", &level));
10985 if (level > max_level)
10986 max_level = (int) level;
10988 met->
npl = max_level;
10991 LOG(2,
"Number of levels: %d", met->
npl);
10992 if (met->
npl < 2 || met->
npl >
EP)
10993 ERRMSG(
"Number of levels out of range!");
11002 const int num_messages,
11008 LOG(2,
"Read level data...");
11011 int t_flag = 0, u_flag = 0, v_flag = 0, w_flag = 0, o3_flag = 0, h2o_flag =
11012 0, lwc_flag = 0, rwc_flag = 0, iwc_flag = 0, swc_flag = 0, cc_flag = 0;
11015 for (
int i = 0; i < num_messages; i++) {
11017 size_t max_size =
LEN;
11018 char short_name[max_size];
11019 size_t value_count;
11023 long current_level;
11024 ECC(codes_get_long(handles[i],
"level", ¤t_level));
11025 current_level -= 1;
11028 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
11029 ECC(codes_get_size(handles[i],
"values", &value_count));
11030 ALLOC(values,
double,
11032 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
11040 ECC_READ_3D(
"w", current_level, met->
w, 0.01f, w_flag);
11058 if (t_flag != met->
npl)
11059 ERRMSG(
"Cannot read temperature!");
11060 if (u_flag != met->
npl)
11061 ERRMSG(
"Cannot read zonal wind!");
11062 if (v_flag != met->
npl)
11063 ERRMSG(
"Cannot read meridional wind!");
11064 if (w_flag != met->
npl)
11065 WARN(
"Cannot read vertical velocity!");
11066 if (h2o_flag != met->
npl)
11067 WARN(
"Cannot read specific humidity!");
11068 if (o3_flag != met->
npl)
11069 WARN(
"Cannot read ozone data!");
11070 if (lwc_flag != met->
npl)
11071 WARN(
"Cannot read cloud liquid water content!");
11072 if (rwc_flag != met->
npl)
11073 WARN(
"Cannot read cloud rain water content!");
11074 if (iwc_flag != met->
npl)
11075 WARN(
"Cannot read cloud ice water content!");
11076 if (swc_flag != met->
npl)
11077 WARN(
"Cannot read cloud snow water content!");
11078 if (cc_flag != met->
npl)
11079 WARN(
"Cannot read cloud cover!");
11082 for (
int ix = 0; ix < met->
nx; ix++)
11083 for (
int iy = 0; iy < met->
ny; iy++)
11084 for (
int ip = 1; ip < met->
np; ip++)
11085 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
11086 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
11087 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
11088 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip])) {
11089 LOG(1,
"%f %f %f %f", met->
pl[ix][iy][0], met->
pl[ix][iy][1],
11090 met->
pl[ix][iy][ip - 1], met->
pl[ix][iy][ip]);
11091 ERRMSG(
"Pressure profiles are not monotonic!");
11112 for (
int ip = 0; ip < met->
np; ip++)
11113 met->
p[ip] = ctl->
met_p[ip];
11117 for (
int ip = 1; ip < met->
np; ip++)
11118 if (met->
p[ip - 1] < met->
p[ip])
11119 ERRMSG(
"Pressure levels must be descending!");
11128 const int num_messages,
11134 LOG(2,
"Read surface data...");
11137 int sp_flag = 0, z_flag = 0, t_flag = 0, u_flag = 0, v_flag = 0, ess_flag =
11138 0, nss_flag = 0, shf_flag = 0, lsm_flag = 0, sst_flag = 0, cape_flag = 0,
11139 cin_flag = 0, pbl_flag = 0;
11142 for (
int i = 0; i < num_messages; i++) {
11144 size_t max_size =
LEN, value_count;
11146 char short_name[max_size];
11149 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
11150 ECC(codes_get_size(handles[i],
"values", &value_count));
11151 double *values = (
double *) malloc(value_count *
sizeof(
double));
11152 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
11199 WARN(
"Cannot read surface pressure data!");
11201 WARN(
"Cannot read surface geopotential height!");
11203 WARN(
"Cannot read surface temperature!");
11205 WARN(
"Cannot read surface zonal wind!");
11207 WARN(
"Cannot read surface meridional wind!");
11209 WARN(
"Cannot read eastward turbulent surface stress!");
11211 WARN(
"Cannot read northward turbulent surface stress!");
11213 WARN(
"Cannot read surface sensible heat flux!");
11215 WARN(
"Cannot read land-sea mask!");
11217 WARN(
"Cannot read sea surface temperature!");
11219 if (cape_flag == 0)
11220 WARN(
"Cannot read CAPE!");
11222 WARN(
"Cannot read convective inhibition!");
11224 if (ctl->
met_pbl == 1 && pbl_flag == 0)
11225 WARN(
"Cannot read planetary boundary layer height!");
11235 const char *varname) {
11237 double aux[
EP], p[
EP];
11241 LOG(2,
"Interpolate meteo data to pressure levels: %s", varname);
11244#pragma omp parallel for default(shared) private(aux,p) collapse(2)
11245 for (
int ix = 0; ix < met->
nx; ix++)
11246 for (
int iy = 0; iy < met->
ny; iy++) {
11249 for (
int ip = 0; ip < met->
np; ip++)
11250 p[ip] = met->
pl[ix][iy][ip];
11253 for (
int ip = 0; ip < ctl->
met_np; ip++) {
11254 double pt = ctl->
met_p[ip];
11255 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
11257 else if ((pt > p[met->
np - 1] && p[1] > p[0])
11258 || (pt < p[met->
np - 1] && p[1] < p[0]))
11259 pt = p[met->
np - 1];
11261 aux[ip] =
LIN(p[ip2], var[ix][iy][ip2],
11262 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
11266 for (
int ip = 0; ip < ctl->
met_np; ip++)
11267 var[ix][iy][ip] = (
float) aux[ip];
11283 LOG(2,
"Make zeta profiles monotone...");
11286#pragma omp parallel for default(shared) collapse(2)
11287 for (
int i = 0; i < met->
nx; i++)
11288 for (
int j = 0; j < met->
ny; j++) {
11291 while (k < met->npl) {
11292 if ((met->
zetal[i][j][k - 1] >= met->
zetal[i][j][k])) {
11298 while ((met->
zetal[i][j][k - 1] >=
11299 met->
zetal[i][j][k + l]) & (k + l < met->npl));
11304 (float) (met->
zetal[i][j][k + l] - met->
zetal[i][j][k - 1])
11307 for (
int m = k; m < k + l; m++) {
11308 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
11309 met->
zetal[i][j][m] = s * d + met->
zetal[i][j][k - 1];
11321#pragma omp parallel for default(shared) collapse(2)
11322 for (
int i = 0; i < met->
nx; i++)
11323 for (
int j = 0; j < met->
ny; j++) {
11326 while (k < met->npl) {
11327 if ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k])) {
11334 while ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k + l]) & (k + l <
11339 float s = (float) (met->
pl[i][j][k + l] - met->
pl[i][j][k - 1])
11342 for (
int m = k; m < k + l; m++) {
11343 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
11344 met->
pl[i][j][m] = s * d + met->
pl[i][j][k - 1];
11359 const char *filename,
11370 (filename, NC_NOWRITE | NC_SHARE, MPI_COMM_WORLD, MPI_INFO_NULL,
11374 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
11375 WARN(
"Cannot open file!");
11393 NC(nc_close(ncid));
11410 int rank = 0, size = 1;
11412 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
11413 MPI_Comm_size(MPI_COMM_WORLD, &size);
11420 LOG(2,
"Number of longitudes: %d", dd->
nx_glob);
11421 LOG(2,
"Number of latitudes: %d", dd->
ny_glob);
11425 ERRMSG(
"Global grid is too large!");
11428 ERRMSG(
"Too many zonal subdomains for global x grid!");
11431 ERRMSG(
"Too many meridional subdomains for global y grid!");
11437 LOG(2,
"Longitudes: %g, %g ... %g deg",
11439 LOG(2,
"Latitudes: %g, %g ... %g deg",
11447 const int left = (zonal_rank == 0);
11449 const int top = (merid_rank == 0);
11456 const int ix0 = zonal_rank * nx_block;
11457 const int iy0 = merid_rank * ny_block;
11459 int nx_core = nx_block;
11460 int ny_core = ny_block;
11483 if (!left && !right) {
11486 }
else if (left ^ right) {
11492 if (!top && !bottom) {
11495 }
else if (top ^ bottom) {
11502 double lon_shift = 0.0;
11504 if (left ^ right) {
11520 lon_shift = left ? -360.0 : 360.0;
11553 LOG(2,
"Define subdomain properties.");
11554 LOG(2,
"MPI information: Rank %d, Size %d", rank, size);
11555 LOG(2,
"Edge position: l=%d,r=%d,t=%d,b=%d", left, right, top, bottom);
11556 LOG(2,
"Total size for subdomain meteo data: nx %d ny %d np %d",
11557 met->
nx, met->
ny, met->
np);
11558 LOG(2,
"Hyperslab sizes for boundary halos: nx %d ny %d np %d",
11561 LOG(2,
"Hyperslab sizes for subdomain and inner halos: nx %d ny %d np %d",
11564 LOG(2,
"Subdomain start: nx %ld ny %ld np %ld",
11566 LOG(2,
"Boundary halo start: nx %ld ny %ld np %ld",
11569 LOG(2,
"%d Subdomain longitudes: %g, %g ... %g deg",
11570 rank, met->
lon[0], met->
lon[1], met->
lon[met->
nx - 1]);
11571 LOG(2,
"%d Subdomain latitudes: %g, %g ... %g deg",
11572 rank, met->
lat[0], met->
lat[1], met->
lat[met->
ny - 1]);
11583 LOG(2,
"Calculate planetary boundary layer...");
11589#pragma omp parallel for default(shared) collapse(2)
11590 for (
int ix = 0; ix < met->
nx; ix++)
11591 for (
int iy = 0; iy < met->
ny; iy++) {
11594 const float z = met->
zs[ix][iy] + met->
pbl[ix][iy];
11597 (float) (
LIN(met->
z[ix][iy][ip], met->
p[ip],
11598 met->
z[ix][iy][ip + 1], met->
p[ip + 1], z));
11603 else if (ctl->
met_pbl == 2) {
11607 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
11610#pragma omp parallel for default(shared) collapse(2)
11611 for (
int ix = 0; ix < met->
nx; ix++)
11612 for (
int iy = 0; iy < met->
ny; iy++) {
11615 const double pbl_bot = met->
ps[ix][iy] * exp(-dz /
H0);
11619 for (ip = 1; ip < met->
np; ip++)
11620 if (met->
p[ip] < pbl_bot)
11624 const double h2os =
LIN(met->
p[ip - 1], met->
h2o[ix][iy][ip - 1],
11625 met->
p[ip], met->
h2o[ix][iy][ip], pbl_bot);
11626 const double tvs =
THETAVIRT(pbl_bot, met->
ts[ix][iy], h2os);
11629 double rib_old = 0;
11632 for (; ip < met->
np; ip++) {
11635 double vh2 =
SQR(met->
u[ix][iy][ip] - met->
us[ix][iy])
11636 +
SQR(met->
v[ix][iy][ip] - met->
vs[ix][iy]);
11637 vh2 =
MAX(vh2,
SQR(umin));
11641 G0 * 1e3 * (met->
z[ix][iy][ip] - met->
zs[ix][iy]) / tvs
11643 met->
h2o[ix][iy][ip]) - tvs) / vh2;
11646 if (rib >= rib_crit) {
11647 met->
pbl[ix][iy] = (float) (
LIN(rib_old, met->
p[ip - 1],
11648 rib, met->
p[ip], rib_crit));
11649 if (met->
pbl[ix][iy] > pbl_bot)
11650 met->
pbl[ix][iy] = (float) pbl_bot;
11665 const double dtheta = 2.0, zmin = 0.1;
11668#pragma omp parallel for default(shared) collapse(2)
11669 for (
int ix = 0; ix < met->
nx; ix++)
11670 for (
int iy = 0; iy < met->
ny; iy++) {
11673 const double theta0 =
THETA(met->
ps[ix][iy], met->
ts[ix][iy]);
11677 for (ip = met->
np - 2; ip > 0; ip--)
11678 if (met->
p[ip] >= 300.)
11679 if (met->
p[ip] > met->
ps[ix][iy]
11680 ||
THETA(met->
p[ip], met->
t[ix][iy][ip]) <= theta0 + dtheta)
11685 = (float) (
LIN(
THETA(met->
p[ip + 1], met->
t[ix][iy][ip + 1]),
11687 THETA(met->
p[ip], met->
t[ix][iy][ip]),
11688 met->
p[ip], theta0 + dtheta));
11691 double pbl_min = met->
ps[ix][iy] * exp(-zmin /
H0);
11692 if (met->
pbl[ix][iy] > pbl_min || met->
p[ip] > met->
ps[ix][iy])
11693 met->
pbl[ix][iy] = (float) pbl_min;
11698#pragma omp parallel for default(shared) collapse(2)
11699 for (
int ix = 0; ix < met->
nx; ix++)
11700 for (
int iy = 0; iy < met->
ny; iy++) {
11704 met->
pbl[ix][iy] =
MIN(met->
pbl[ix][iy], (
float) pbl_min);
11708 met->
pbl[ix][iy] =
MAX(met->
pbl[ix][iy], (
float) pbl_max);
11719 LOG(2,
"Apply periodic boundary conditions...");
11722 if (!(fabs(met->
lon[met->
nx - 1] - met->
lon[0]
11723 + met->
lon[1] - met->
lon[0] - 360) < 0.01))
11727 if ((++met->
nx) >=
EX)
11728 ERRMSG(
"Cannot create periodic boundary conditions!");
11731 met->
lon[met->
nx - 1] = met->
lon[met->
nx - 2] + met->
lon[1] - met->
lon[0];
11734#pragma omp parallel for default(shared)
11735 for (
int iy = 0; iy < met->
ny; iy++) {
11736 met->
ps[met->
nx - 1][iy] = met->
ps[0][iy];
11737 met->
zs[met->
nx - 1][iy] = met->
zs[0][iy];
11738 met->
ts[met->
nx - 1][iy] = met->
ts[0][iy];
11739 met->
us[met->
nx - 1][iy] = met->
us[0][iy];
11740 met->
vs[met->
nx - 1][iy] = met->
vs[0][iy];
11741 met->
ess[met->
nx - 1][iy] = met->
ess[0][iy];
11742 met->
nss[met->
nx - 1][iy] = met->
nss[0][iy];
11743 met->
shf[met->
nx - 1][iy] = met->
shf[0][iy];
11744 met->
lsm[met->
nx - 1][iy] = met->
lsm[0][iy];
11745 met->
sst[met->
nx - 1][iy] = met->
sst[0][iy];
11746 met->
pbl[met->
nx - 1][iy] = met->
pbl[0][iy];
11747 met->
cape[met->
nx - 1][iy] = met->
cape[0][iy];
11748 met->
cin[met->
nx - 1][iy] = met->
cin[0][iy];
11749 for (
int ip = 0; ip < met->
np; ip++) {
11750 met->
t[met->
nx - 1][iy][ip] = met->
t[0][iy][ip];
11751 met->
u[met->
nx - 1][iy][ip] = met->
u[0][iy][ip];
11752 met->
v[met->
nx - 1][iy][ip] = met->
v[0][iy][ip];
11753 met->
w[met->
nx - 1][iy][ip] = met->
w[0][iy][ip];
11754 met->
h2o[met->
nx - 1][iy][ip] = met->
h2o[0][iy][ip];
11755 met->
o3[met->
nx - 1][iy][ip] = met->
o3[0][iy][ip];
11756 met->
lwc[met->
nx - 1][iy][ip] = met->
lwc[0][iy][ip];
11757 met->
rwc[met->
nx - 1][iy][ip] = met->
rwc[0][iy][ip];
11758 met->
iwc[met->
nx - 1][iy][ip] = met->
iwc[0][iy][ip];
11759 met->
swc[met->
nx - 1][iy][ip] = met->
swc[0][iy][ip];
11760 met->
cc[met->
nx - 1][iy][ip] = met->
cc[0][iy][ip];
11762 for (
int ip = 0; ip < met->
npl; ip++) {
11763 met->
ul[met->
nx - 1][iy][ip] = met->
ul[0][iy][ip];
11764 met->
vl[met->
nx - 1][iy][ip] = met->
vl[0][iy][ip];
11765 met->
wl[met->
nx - 1][iy][ip] = met->
wl[0][iy][ip];
11766 met->
pl[met->
nx - 1][iy][ip] = met->
pl[0][iy][ip];
11767 met->
zetal[met->
nx - 1][iy][ip] = met->
zetal[0][iy][ip];
11780 LOG(2,
"Apply fix for polar winds...");
11786 if (fabs(met->
lat[0]) < 89.999 || fabs(met->
lat[met->
ny - 1]) < 89.999)
11790 for (
int ihem = 0; ihem < 2; ihem++) {
11793 int i89 = 1, i90 = 0, sign = 1;
11798 if (met->
lat[i90] < 0)
11802 double clon[
EX], slon[
EX];
11803#pragma omp parallel for default(shared)
11804 for (
int ix = 0; ix < met->
nx; ix++) {
11805 clon[ix] = cos(sign *
DEG2RAD(met->
lon[ix]));
11806 slon[ix] = sin(sign *
DEG2RAD(met->
lon[ix]));
11810#pragma omp parallel for default(shared)
11811 for (
int ip = 0; ip < met->
np; ip++) {
11814 double vel89x = 0, vel89y = 0;
11815 for (
int ix = 0; ix < met->
nx; ix++) {
11817 (met->
u[ix][i89][ip] * clon[ix] -
11818 met->
v[ix][i89][ip] * slon[ix]) / met->
nx;
11820 (met->
u[ix][i89][ip] * slon[ix] +
11821 met->
v[ix][i89][ip] * clon[ix]) / met->
nx;
11825 for (
int ix = 0; ix < met->
nx; ix++) {
11826 met->
u[ix][i90][ip]
11827 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
11828 met->
v[ix][i90][ip]
11829 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
11844 LOG(2,
"Calculate potential vorticity...");
11847#pragma omp parallel for default(shared)
11848 for (
int ip = 0; ip < met->
np; ip++)
11849 pows[ip] = pow(1000. / met->
p[ip],
KAPPA);
11852#pragma omp parallel for default(shared)
11853 for (
int ix = 0; ix < met->
nx; ix++) {
11856 const int ix0 =
MAX(ix - 1, 0);
11857 const int ix1 =
MIN(ix + 1, met->
nx - 1);
11860 for (
int iy = 0; iy < met->
ny; iy++) {
11863 const int iy0 =
MAX(iy - 1, 0);
11864 const int iy1 =
MIN(iy + 1, met->
ny - 1);
11867 const double latr = 0.5 * (met->
lat[iy1] + met->
lat[iy0]);
11868 double dx, dy, c0, c1, cr, vort;
11872 dx = 1000. *
DEG2DX(met->
lon[ix1] - met->
lon[ix0], latr);
11879 dx = met->
lon[ix1] - met->
lon[ix0];
11880 dy = met->
lat[iy1] - met->
lat[iy0];
11890 for (
int ip = 0; ip < met->
np; ip++) {
11894 = (met->
t[ix1][iy][ip] - met->
t[ix0][iy][ip]) * pows[ip] / dx;
11895 const double dvdx = (met->
v[ix1][iy][ip] - met->
v[ix0][iy][ip]) / dx;
11899 = (met->
t[ix][iy1][ip] - met->
t[ix][iy0][ip]) * pows[ip] / dy;
11901 = (met->
u[ix][iy1][ip] * c1 - met->
u[ix][iy0][ip] * c0) / dy;
11904 const int ip0 =
MAX(ip - 1, 0);
11905 const int ip1 =
MIN(ip + 1, met->
np - 1);
11908 double dtdp, dudp, dvdp;
11909 const double dp0 = 100. * (met->
p[ip] - met->
p[ip0]);
11910 const double dp1 = 100. * (met->
p[ip1] - met->
p[ip]);
11911 if (ip != ip0 && ip != ip1) {
11912 double denom = dp0 * dp1 * (dp0 + dp1);
11913 dtdp = (dp0 * dp0 * met->
t[ix][iy][ip1] * pows[ip1]
11914 - dp1 * dp1 * met->
t[ix][iy][ip0] * pows[ip0]
11915 + (dp1 * dp1 - dp0 * dp0) * met->
t[ix][iy][ip] * pows[ip])
11917 dudp = (dp0 * dp0 * met->
u[ix][iy][ip1]
11918 - dp1 * dp1 * met->
u[ix][iy][ip0]
11919 + (dp1 * dp1 - dp0 * dp0) * met->
u[ix][iy][ip])
11921 dvdp = (dp0 * dp0 * met->
v[ix][iy][ip1]
11922 - dp1 * dp1 * met->
v[ix][iy][ip0]
11923 + (dp1 * dp1 - dp0 * dp0) * met->
v[ix][iy][ip])
11926 const double denom = dp0 + dp1;
11928 (met->
t[ix][iy][ip1] * pows[ip1] -
11929 met->
t[ix][iy][ip0] * pows[ip0]) / denom;
11930 dudp = (met->
u[ix][iy][ip1] - met->
u[ix][iy][ip0]) / denom;
11931 dvdp = (met->
v[ix][iy][ip1] - met->
v[ix][iy][ip0]) / denom;
11935 met->
pv[ix][iy][ip] = (float)
11937 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
11943#pragma omp parallel for default(shared)
11944 for (
int ix = 0; ix < met->
nx; ix++)
11945 for (
int ip = 0; ip < met->
np; ip++) {
11947 = met->
pv[ix][1][ip]
11948 = met->
pv[ix][2][ip];
11949 met->
pv[ix][met->
ny - 1][ip]
11950 = met->
pv[ix][met->
ny - 2][ip]
11951 = met->
pv[ix][met->
ny - 3][ip];
11962 LOG(2,
"Calculate total column ozone...");
11965#pragma omp parallel for default(shared) collapse(2)
11966 for (
int ix = 0; ix < met->
nx; ix++)
11967 for (
int iy = 0; iy < met->
ny; iy++) {
11971 for (
int ip = 1; ip < met->
np; ip++)
11972 if (met->
p[ip - 1] <= met->
ps[ix][iy]) {
11974 0.5 * (met->
o3[ix][iy][ip - 1] + met->
o3[ix][iy][ip]);
11975 const double dp = met->
p[ip - 1] - met->
p[ip];
11976 cd += vmr *
MO3 /
MA * dp * 1e2 /
G0;
11999 LOG(2,
"Downsampling of meteo data...");
12005 help->
nx = met->
nx;
12006 help->
ny = met->
ny;
12007 help->
np = met->
np;
12008 memcpy(help->
lon, met->
lon,
sizeof(met->
lon));
12009 memcpy(help->
lat, met->
lat,
sizeof(met->
lat));
12010 memcpy(help->
p, met->
p,
sizeof(met->
p));
12013 for (
int ix = 0; ix < met->
nx; ix += ctl->
met_dx) {
12014 for (
int iy = 0; iy < met->
ny; iy += ctl->
met_dy) {
12015 for (
int ip = 0; ip < met->
np; ip += ctl->
met_dp) {
12016 help->
ps[ix][iy] = 0;
12017 help->
zs[ix][iy] = 0;
12018 help->
ts[ix][iy] = 0;
12019 help->
us[ix][iy] = 0;
12020 help->
vs[ix][iy] = 0;
12021 help->
ess[ix][iy] = 0;
12022 help->
nss[ix][iy] = 0;
12023 help->
shf[ix][iy] = 0;
12024 help->
lsm[ix][iy] = 0;
12025 help->
sst[ix][iy] = 0;
12026 help->
pbl[ix][iy] = 0;
12027 help->
cape[ix][iy] = 0;
12028 help->
cin[ix][iy] = 0;
12029 help->
t[ix][iy][ip] = 0;
12030 help->
u[ix][iy][ip] = 0;
12031 help->
v[ix][iy][ip] = 0;
12032 help->
w[ix][iy][ip] = 0;
12033 help->
h2o[ix][iy][ip] = 0;
12034 help->
o3[ix][iy][ip] = 0;
12035 help->
lwc[ix][iy][ip] = 0;
12036 help->
rwc[ix][iy][ip] = 0;
12037 help->
iwc[ix][iy][ip] = 0;
12038 help->
swc[ix][iy][ip] = 0;
12039 help->
cc[ix][iy][ip] = 0;
12041 for (
int ix2 = ix - ctl->
met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
12046 else if (ix3 >= met->
nx)
12049 for (
int iy2 =
MAX(iy - ctl->
met_sy + 1, 0);
12050 iy2 <=
MIN(iy + ctl->
met_sy - 1, met->
ny - 1); iy2++)
12051 for (
int ip2 =
MAX(ip - ctl->
met_sp + 1, 0);
12052 ip2 <=
MIN(ip + ctl->
met_sp - 1, met->
np - 1); ip2++) {
12054 (1.0f - (float) abs(ix - ix2) / (float) ctl->
met_sx)
12055 * (1.0f - (float) abs(iy - iy2) / (float) ctl->
met_sy)
12056 * (1.0f - (float) abs(ip - ip2) / (float) ctl->
met_sp);
12057 help->
ps[ix][iy] += w * met->
ps[ix3][iy2];
12058 help->
zs[ix][iy] += w * met->
zs[ix3][iy2];
12059 help->
ts[ix][iy] += w * met->
ts[ix3][iy2];
12060 help->
us[ix][iy] += w * met->
us[ix3][iy2];
12061 help->
vs[ix][iy] += w * met->
vs[ix3][iy2];
12062 help->
ess[ix][iy] += w * met->
ess[ix3][iy2];
12063 help->
nss[ix][iy] += w * met->
nss[ix3][iy2];
12064 help->
shf[ix][iy] += w * met->
shf[ix3][iy2];
12065 help->
lsm[ix][iy] += w * met->
lsm[ix3][iy2];
12066 help->
sst[ix][iy] += w * met->
sst[ix3][iy2];
12067 help->
pbl[ix][iy] += w * met->
pbl[ix3][iy2];
12068 help->
cape[ix][iy] += w * met->
cape[ix3][iy2];
12069 help->
cin[ix][iy] += w * met->
cin[ix3][iy2];
12070 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip2];
12071 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip2];
12072 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip2];
12073 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip2];
12074 help->
h2o[ix][iy][ip] += w * met->
h2o[ix3][iy2][ip2];
12075 help->
o3[ix][iy][ip] += w * met->
o3[ix3][iy2][ip2];
12076 help->
lwc[ix][iy][ip] += w * met->
lwc[ix3][iy2][ip2];
12077 help->
rwc[ix][iy][ip] += w * met->
rwc[ix3][iy2][ip2];
12078 help->
iwc[ix][iy][ip] += w * met->
iwc[ix3][iy2][ip2];
12079 help->
swc[ix][iy][ip] += w * met->
swc[ix3][iy2][ip2];
12080 help->
cc[ix][iy][ip] += w * met->
cc[ix3][iy2][ip2];
12084 help->
ps[ix][iy] /= wsum;
12085 help->
zs[ix][iy] /= wsum;
12086 help->
ts[ix][iy] /= wsum;
12087 help->
us[ix][iy] /= wsum;
12088 help->
vs[ix][iy] /= wsum;
12089 help->
ess[ix][iy] /= wsum;
12090 help->
nss[ix][iy] /= wsum;
12091 help->
shf[ix][iy] /= wsum;
12092 help->
lsm[ix][iy] /= wsum;
12093 help->
sst[ix][iy] /= wsum;
12094 help->
pbl[ix][iy] /= wsum;
12095 help->
cape[ix][iy] /= wsum;
12096 help->
cin[ix][iy] /= wsum;
12097 help->
t[ix][iy][ip] /= wsum;
12098 help->
u[ix][iy][ip] /= wsum;
12099 help->
v[ix][iy][ip] /= wsum;
12100 help->
w[ix][iy][ip] /= wsum;
12101 help->
h2o[ix][iy][ip] /= wsum;
12102 help->
o3[ix][iy][ip] /= wsum;
12103 help->
lwc[ix][iy][ip] /= wsum;
12104 help->
rwc[ix][iy][ip] /= wsum;
12105 help->
iwc[ix][iy][ip] /= wsum;
12106 help->
swc[ix][iy][ip] /= wsum;
12107 help->
cc[ix][iy][ip] /= wsum;
12114 for (
int ix = 0; ix < help->
nx; ix += ctl->
met_dx) {
12115 met->
lon[met->
nx] = help->
lon[ix];
12117 for (
int iy = 0; iy < help->
ny; iy += ctl->
met_dy) {
12118 met->
lat[met->
ny] = help->
lat[iy];
12119 met->
ps[met->
nx][met->
ny] = help->
ps[ix][iy];
12120 met->
zs[met->
nx][met->
ny] = help->
zs[ix][iy];
12121 met->
ts[met->
nx][met->
ny] = help->
ts[ix][iy];
12122 met->
us[met->
nx][met->
ny] = help->
us[ix][iy];
12123 met->
vs[met->
nx][met->
ny] = help->
vs[ix][iy];
12124 met->
ess[met->
nx][met->
ny] = help->
ess[ix][iy];
12125 met->
nss[met->
nx][met->
ny] = help->
nss[ix][iy];
12126 met->
shf[met->
nx][met->
ny] = help->
shf[ix][iy];
12127 met->
lsm[met->
nx][met->
ny] = help->
lsm[ix][iy];
12128 met->
sst[met->
nx][met->
ny] = help->
sst[ix][iy];
12129 met->
pbl[met->
nx][met->
ny] = help->
pbl[ix][iy];
12131 met->
cin[met->
nx][met->
ny] = help->
cin[ix][iy];
12133 for (
int ip = 0; ip < help->
np; ip += ctl->
met_dp) {
12134 met->
p[met->
np] = help->
p[ip];
12135 met->
t[met->
nx][met->
ny][met->
np] = help->
t[ix][iy][ip];
12136 met->
u[met->
nx][met->
ny][met->
np] = help->
u[ix][iy][ip];
12137 met->
v[met->
nx][met->
ny][met->
np] = help->
v[ix][iy][ip];
12138 met->
w[met->
nx][met->
ny][met->
np] = help->
w[ix][iy][ip];
12139 met->
h2o[met->
nx][met->
ny][met->
np] = help->
h2o[ix][iy][ip];
12140 met->
o3[met->
nx][met->
ny][met->
np] = help->
o3[ix][iy][ip];
12141 met->
lwc[met->
nx][met->
ny][met->
np] = help->
lwc[ix][iy][ip];
12142 met->
rwc[met->
nx][met->
ny][met->
np] = help->
rwc[ix][iy][ip];
12143 met->
iwc[met->
nx][met->
ny][met->
np] = help->
iwc[ix][iy][ip];
12144 met->
swc[met->
nx][met->
ny][met->
np] = help->
swc[ix][iy][ip];
12145 met->
cc[met->
nx][met->
ny][met->
np] = help->
cc[ix][iy][ip];
12164 double p2[200], pv[
EP], pv2[200], t[
EP], t2[200], th[
EP],
12165 th2[200], z[
EP], z2[200];
12169 LOG(2,
"Calculate tropopause...");
12172#pragma omp parallel for default(shared)
12173 for (
int iz = 0; iz < met->
np; iz++)
12174 z[iz] =
Z(met->
p[iz]);
12175#pragma omp parallel for default(shared)
12176 for (
int iz = 0; iz <= 190; iz++) {
12177 z2[iz] = 4.5 + 0.1 * iz;
12178 p2[iz] =
P(z2[iz]);
12183#pragma omp parallel for default(shared) collapse(2)
12184 for (
int ix = 0; ix < met->
nx; ix++)
12185 for (
int iy = 0; iy < met->
ny; iy++)
12186 met->
pt[ix][iy] = NAN;
12191 ERRMSG(
"Only lat/lon grid supported");
12192#pragma omp parallel for default(shared) collapse(2)
12193 for (
int ix = 0; ix < met->
nx; ix++)
12194 for (
int iy = 0; iy < met->
ny; iy++)
12202#pragma omp parallel for default(shared) private(t,t2) collapse(2)
12203 for (
int ix = 0; ix < met->
nx; ix++)
12204 for (
int iy = 0; iy < met->
ny; iy++) {
12207 for (
int iz = 0; iz < met->
np; iz++)
12208 t[iz] = met->
t[ix][iy][iz];
12212 int iz = (int) gsl_stats_min_index(t2, 1, 171);
12213 if (iz > 0 && iz < 170)
12214 met->
pt[ix][iy] = (float) p2[iz];
12216 met->
pt[ix][iy] = NAN;
12224#pragma omp parallel for default(shared) private(t,t2) collapse(2)
12225 for (
int ix = 0; ix < met->
nx; ix++)
12226 for (
int iy = 0; iy < met->
ny; iy++) {
12230 for (iz = 0; iz < met->
np; iz++)
12231 t[iz] = met->
t[ix][iy][iz];
12235 met->
pt[ix][iy] = NAN;
12236 for (iz = 0; iz <= 170; iz++) {
12238 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
12239 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
12244 if (iz > 0 && iz < 170)
12245 met->
pt[ix][iy] = (float) p2[iz];
12252 met->
pt[ix][iy] = NAN;
12253 for (; iz <= 170; iz++) {
12255 for (
int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
12256 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
12263 for (; iz <= 170; iz++) {
12265 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
12266 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
12271 if (iz > 0 && iz < 170)
12272 met->
pt[ix][iy] = (float) p2[iz];
12284#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
12285 for (
int ix = 0; ix < met->
nx; ix++)
12286 for (
int iy = 0; iy < met->
ny; iy++) {
12289 for (
int iz = 0; iz < met->
np; iz++)
12290 pv[iz] = met->
pv[ix][iy][iz];
12294 for (
int iz = 0; iz < met->
np; iz++)
12295 th[iz] =
THETA(met->
p[iz], met->
t[ix][iy][iz]);
12299 met->
pt[ix][iy] = NAN;
12300 for (
int iz = 0; iz <= 170; iz++)
12303 if (iz > 0 && iz < 170)
12304 met->
pt[ix][iy] = (float) p2[iz];
12311 ERRMSG(
"Cannot calculate tropopause!");
12314#pragma omp parallel for default(shared) collapse(2)
12315 for (
int ix = 0; ix < met->
nx; ix++)
12316 for (
int iy = 0; iy < met->
ny; iy++) {
12317 double h2ot, tt, zt;
12320 met->
lat[iy], &tt, ci, cw, 1);
12322 met->
lat[iy], &zt, ci, cw, 0);
12324 met->
lat[iy], &h2ot, ci, cw, 0);
12325 met->
tt[ix][iy] = (float) tt;
12326 met->
zt[ix][iy] = (float) zt;
12327 met->
h2ot[ix][iy] = (float) h2ot;
12334 const char *filename,
12344 LOG(1,
"Read observation data: %s", filename);
12348 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
12350 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
12352 ERRMSG(
"Set OBS_TYPE to 0 or 1!");
12355 for (
int i = 1; i < *nobs; i++)
12356 if (rt[i] < rt[i - 1])
12357 ERRMSG(
"Time must be ascending!");
12362 LOG(2,
"Number of observations: %d", *nobs);
12363 gsl_stats_minmax(&mini, &maxi, rt, 1, (
size_t) n);
12364 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
12365 gsl_stats_minmax(&mini, &maxi, rz, 1, (
size_t) n);
12366 LOG(2,
"Altitude range: %g ... %g km", mini, maxi);
12367 gsl_stats_minmax(&mini, &maxi, rlon, 1, (
size_t) n);
12368 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
12369 gsl_stats_minmax(&mini, &maxi, rlat, 1, (
size_t) n);
12370 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
12371 gsl_stats_minmax(&mini, &maxi, robs, 1, (
size_t) n);
12372 LOG(2,
"Observation range: %g ... %g", mini, maxi);
12378 const char *filename,
12388 if (!(in = fopen(filename,
"r")))
12389 ERRMSG(
"Cannot open file!");
12393 while (fgets(line,
LEN, in))
12394 if (sscanf(line,
"%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
12395 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
12396 if ((++(*nobs)) >=
NOBS)
12397 ERRMSG(
"Too many observations!");
12406 const char *filename,
12417 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
12418 ERRMSG(
"Cannot open file!");
12429 NC(nc_close(ncid));
12435 const char *filename,
12438 const char *varname,
12440 const char *defvalue,
12445 char fullname1[
LEN], fullname2[
LEN], rval[
LEN];
12447 int contain = 0, i;
12450 if (filename[strlen(filename) - 1] !=
'-')
12451 if (!(in = fopen(filename,
"r")))
12452 ERRMSG(
"Cannot open file!");
12456 sprintf(fullname1,
"%s[%d]", varname, arridx);
12457 sprintf(fullname2,
"%s[*]", varname);
12459 sprintf(fullname1,
"%s", varname);
12460 sprintf(fullname2,
"%s", varname);
12465 char dummy[
LEN], line[
LEN], rvarname[
LEN];
12466 while (fgets(line,
LEN, in)) {
12467 if (sscanf(line,
"%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
12468 if (strcasecmp(rvarname, fullname1) == 0 ||
12469 strcasecmp(rvarname, fullname2) == 0) {
12475 for (i = 1; i < argc - 1; i++)
12476 if (strcasecmp(argv[i], fullname1) == 0 ||
12477 strcasecmp(argv[i], fullname2) == 0) {
12478 sprintf(rval,
"%s", argv[i + 1]);
12489 if (strlen(defvalue) > 0)
12490 sprintf(rval,
"%s", defvalue);
12492 ERRMSG(
"Missing variable %s!\n", fullname1);
12496 LOG(1,
"%s = %s", fullname1, rval);
12500 sprintf(value,
"%s", rval);
12510 const double rhop) {
12513 const double rp_help = rp * 1e-6;
12516 const double rho =
RHO(p, T);
12519 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
12525 const double lambda = 2. * eta / (rho * v);
12528 const double K = lambda / rp_help;
12531 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
12534 return 2. *
SQR(rp_help) * (rhop - rho) *
G0 / (9. * eta) * G;
12546 const int method) {
12552 gsl_interp_accel *acc = gsl_interp_accel_alloc();
12553 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (
size_t) n);
12556 gsl_spline_init(s, x, y, (
size_t) n);
12557 for (
int i = 0; i < n2; i++)
12560 else if (x2[i] >= x[n - 1])
12563 y2[i] = gsl_spline_eval(s, x2[i], acc);
12566 gsl_spline_free(s);
12567 gsl_interp_accel_free(acc);
12572 for (
int i = 0; i < n2; i++)
12575 else if (x2[i] >= x[n - 1])
12579 y2[i] =
LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
12593 float mean = 0, var = 0;
12595 for (
int i = 0; i < n; ++i) {
12597 var +=
SQR(data[i]);
12600 var = var / (float) n -
SQR(mean / (
float) n);
12602 return (var > 0 ? sqrtf(var) : 0);
12614 const double remain,
12626 t1.tm_year = year - 1900;
12627 t1.tm_mon = mon - 1;
12633 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
12641 const int output) {
12648 static int iname = -1, igroup = -1, nname, ngroup, ct_name[
NTIMER];
12651 t1 = omp_get_wtime();
12656 rt_name[iname] += dt;
12657 rt_min[iname] = (ct_name[iname] <= 0 ? dt :
MIN(rt_min[iname], dt));
12658 rt_max[iname] = (ct_name[iname] <= 0 ? dt :
MAX(rt_max[iname], dt));
12662 rt_group[igroup] += t1 - t0;
12666 for (
int i = 0; i < nname; i++)
12667 LOG(1,
"TIMER_%s = %.3f s (min= %g s, mean= %g s,"
12668 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
12669 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
12670 for (
int i = 0; i < ngroup; i++)
12671 LOG(1,
"TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
12672 double total = 0.0;
12673 for (
int i = 0; i < nname; i++)
12674 total += rt_name[i];
12675 LOG(1,
"TIMER_TOTAL = %.3f s", total);
12679 for (iname = 0; iname < nname; iname++)
12680 if (strcasecmp(name, names[iname]) == 0)
12682 for (igroup = 0; igroup < ngroup; igroup++)
12683 if (strcasecmp(group, groups[igroup]) == 0)
12687 if (iname >= nname) {
12688 sprintf(names[iname],
"%s", name);
12689 if ((++nname) >=
NTIMER)
12690 ERRMSG(
"Too many timers!");
12694 if (igroup >= ngroup) {
12695 sprintf(groups[igroup],
"%s", group);
12696 if ((++ngroup) >=
NTIMER)
12697 ERRMSG(
"Too many groups!");
12707 const char *filename,
12709 const int with_seconds) {
12716 int len = (int) strlen(filename);
12717 sprintf(tstr,
"%.4s", &filename[len - offset]);
12718 int year = atoi(tstr);
12719 sprintf(tstr,
"%.2s", &filename[len - offset + 5]);
12720 int mon = atoi(tstr);
12721 sprintf(tstr,
"%.2s", &filename[len - offset + 8]);
12722 int day = atoi(tstr);
12723 sprintf(tstr,
"%.2s", &filename[len - offset + 11]);
12724 int hour = atoi(tstr);
12725 sprintf(tstr,
"%.2s", &filename[len - offset + 14]);
12726 int min = atoi(tstr);
12729 if (with_seconds) {
12730 sprintf(tstr,
"%.2s", &filename[len - offset + 17]);
12735 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
12736 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
12737 ERRMSG(
"Cannot read time from filename!");
12740 time2jsec(year, mon, day, hour, min, sec, 0.0, &t);
12760 const double p1 = pt * 0.866877899;
12761 const double p0 = pt / 0.866877899;
12764 if (atm->
p[ip] > p0)
12766 else if (atm->
p[ip] < p1)
12769 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
12775 const char *filename,
12783 const double t0 = t - 0.5 * ctl->
dt_mod;
12784 const double t1 = t + 0.5 * ctl->
dt_mod;
12790 if (!(out = popen(
"gnuplot",
"w")))
12791 ERRMSG(
"Cannot create pipe to gnuplot!");
12794 fprintf(out,
"set out \"%s.png\"\n", filename);
12798 int year, mon, day, hour, min, sec;
12799 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
12800 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
12801 year, mon, day, hour, min);
12806 ERRMSG(
"Cannot open file!");
12808 while (fgets(line,
LEN, in))
12809 fprintf(out,
"%s", line);
12816 if (!(out = fopen(filename,
"w")))
12817 ERRMSG(
"Cannot create file!");
12824 "# $1 = time [s]\n"
12825 "# $2 = altitude [km]\n"
12826 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
12829 "# $1 = time [s]\n"
12830 "# $2 = altitude [km]\n" "# $3 = x [m]\n" "# $4 = y [m]\n");
12833 for (
int iq = 0; iq < ctl->
nq; iq++)
12834 fprintf(out,
"# $%i = %s [%s]\n", iq + 5, ctl->
qnt_name[iq],
12836 fprintf(out,
"\n");
12839 for (
int ip = 0; ip < atm->
np; ip += ctl->
atm_stride) {
12847 fprintf(out,
"%.2f %g %g %g",
12848 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]
12851 fprintf(out,
"%.2f %g %.2f %.2f",
12852 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]
12856 for (
int iq = 0; iq < ctl->
nq; iq++) {
12861 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
12863 fprintf(out,
"\n");
12873 const char *filename,
12875 const atm_t *atm) {
12880 if (!(out = fopen(filename,
"w")))
12881 ERRMSG(
"Cannot create file!");
12905 for (
int iq = 0; iq < ctl->
nq; iq++)
12923 const char *filename,
12925 const atm_t *atm) {
12928 ERRMSG(
"CLaMS atmospheric files support only lat/lon grids");
12930 int tid, pid, ncid, varid;
12931 size_t start[2], count[2];
12934 NC(nc_create(filename, NC_NETCDF4, &ncid));
12937 NC(nc_def_dim(ncid,
"time", 1, &tid));
12938 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
12941 int dim_ids[2] = { tid, pid };
12942 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
12943 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
12944 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
12946 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
12948 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
12951 for (
int iq = 0; iq < ctl->
nq; iq++)
12961 NC(nc_enddef(ncid));
12969 for (
int iq = 0; iq < ctl->
nq; iq++)
12973 NC(nc_close(ncid));
12979 const char *dirname,
12985 ERRMSG(
"CLaMS atmospheric files support only lat/lon grids");
12988 static size_t out_cnt = 0;
12990 double r, r_start, r_stop;
12991 int year, mon, day, hour, min, sec;
12992 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
12993 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
12994 char filename_out[2 *
LEN] =
"traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
12996 int ncid, varid, tid, pid, cid;
13004 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
13006 &min_start, &sec_start, &r_start);
13008 &min_stop, &sec_stop, &r_stop);
13010 sprintf(filename_out,
13011 "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc", dirname,
13012 year_start % 100, mon_start, day_start, hour_start,
13013 year_stop % 100, mon_stop, day_stop, hour_stop);
13014 LOG(1,
"Write traj file: %s", filename_out);
13017 start[0] = out_cnt;
13020 count[1] = (size_t) atm->
np;
13023 if (out_cnt == 0) {
13026 NC(nc_create(filename_out, NC_NETCDF4, &ncid));
13029 NC(nc_def_dim(ncid,
"time", NC_UNLIMITED, &tid));
13030 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
13031 NC(nc_def_dim(ncid,
"TMDT", 7, &cid));
13036 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
13037 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
13038 NC_DEF_VAR(
"LAT", NC_DOUBLE, 2, dim_ids,
"Latitude",
"deg",
13040 NC_DEF_VAR(
"LON", NC_DOUBLE, 2, dim_ids,
"Longitude",
"deg",
13042 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 2, dim_ids,
"Pressure",
"hPa",
13044 NC_DEF_VAR(
"ZETA", NC_DOUBLE, 2, dim_ids,
"Zeta",
"K",
13046 for (
int iq = 0; iq < ctl->
nq; iq++)
13056 NC(nc_enddef(ncid));
13057 NC(nc_close(ncid));
13064 NC(nc_open(filename_out, NC_WRITE, &ncid));
13076 for (
int iq = 0; iq < ctl->
nq; iq++)
13080 NC(nc_close(ncid));
13083 if ((year == year_stop) && (mon == mon_stop)
13084 && (day == day_stop) && (hour == hour_stop)) {
13087 char filename_init[2 *
LEN] =
"./init_fix_YYYYMMDDHH.nc";
13088 sprintf(filename_init,
"%s/init_fix_%02d%02d%02d%02d.nc",
13089 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
13090 LOG(1,
"Write init file: %s", filename_init);
13093 NC(nc_create(filename_init, NC_NETCDF4, &ncid));
13096 NC(nc_def_dim(ncid,
"time", 1, &tid));
13097 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
13102 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
13103 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
13104 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
13106 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
13108 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
13111 for (
int iq = 0; iq < ctl->
nq; iq++)
13121 NC(nc_enddef(ncid));
13129 for (
int iq = 0; iq < ctl->
nq; iq++)
13133 NC(nc_close(ncid));
13140 const char *filename,
13142 const atm_t *atm) {
13144 int ncid, obsid, varid;
13146 size_t start[2], count[2];
13149 NC(nc_create(filename, NC_NETCDF4, &ncid));
13152 NC(nc_def_dim(ncid,
"obs", (
size_t) atm->
np, &obsid));
13155 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &obsid,
"time",
13156 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
13157 NC_DEF_VAR(
"press", NC_DOUBLE, 1, &obsid,
"pressure",
"hPa",
13159 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &obsid,
"longitude",
"degrees_east",
13161 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &obsid,
"latitude",
"degrees_north",
13163 for (
int iq = 0; iq < ctl->
nq; iq++)
13172 NC(nc_enddef(ncid));
13179 for (
int iq = 0; iq < ctl->
nq; iq++)
13183 NC(nc_close(ncid));
13189 const char *filename,
13195 ERRMSG(
"Only lat/lon grid supported");
13199 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
13202 static int *obscount, nobs, nk;
13206 const int ensemble = (ctl->
nens > 0);
13212 if (ctl->
qnt_m < 0)
13213 ERRMSG(
"Need quantity mass!");
13216 ERRMSG(
"Missing ensemble IDs!");
13218 ERRMSG(
"Too many ensembles!");
13225 ALLOC(area,
double,
13231 ALLOC(rlon,
double,
13233 ALLOC(rlat,
double,
13235 ALLOC(robs,
double,
13246 LOG(1,
"Write CSI%s data: %s", ensemble ?
" ensemble" :
"", filename);
13247 if (!(out = fopen(filename,
"w")))
13248 ERRMSG(
"Cannot create file!");
13252 "# $1 = time [s]\n"
13253 "# $2 = ensemble ID\n"
13254 "# $3 = number of hits (cx)\n"
13255 "# $4 = number of misses (cy)\n"
13256 "# $5 = number of false alarms (cz)\n"
13257 "# $6 = number of observations (cx + cy)\n"
13258 "# $7 = number of forecasts (cx + cz)\n"
13259 "# $8 = bias (%%)\n"
13260 "# $9 = POD (%%)\n"
13261 "# $10 = FAR (%%)\n"
13262 "# $11 = CSI (%%)\n"
13263 "# $12 = hits by random chance\n"
13264 "# $13 = ETS (%%)\n"
13265 "# $14 = Pearson R\n"
13266 "# $15 = Spearman R\n"
13267 "# $16 = mean error [kg/m²]\n"
13268 "# $17 = RMSE [kg/m²]\n"
13269 "# $18 = MAE [kg/m²]\n"
13270 "# $19 = log-likelihood\n" "# $20 = number of points\n\n");
13278 for (
int iy = 0; iy < ctl->
csi_ny; iy++) {
13279 const double lat = ctl->
csi_lat0 + dlat * (iy + 0.5);
13280 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.0) * cos(
DEG2RAD(lat));
13285 const double t0 = t - 0.5 * ctl->
dt_mod;
13286 const double t1 = t + 0.5 * ctl->
dt_mod;
13290 ALLOC(modmean,
double,
13291 (ensemble ? ctl->
nens : 1) * grid_size);
13292 ALLOC(obsmean,
double,
13294 ALLOC(obscount,
int,
13296 ALLOC(obsstd,
double,
13300 for (
int i = 0; i < (ensemble ? ctl->
nens : 1); i++)
13301 ct[i] = cx[i] = cy[i] = cz[i] = n[i] = 0;
13304 for (
int i = 0; i < nobs; i++) {
13305 if (rt[i] < t0 || rt[i] >= t1 || !isfinite(robs[i]))
13313 const int ix = (int) ((rlon[i] - ctl->
csi_lon0) / dlon);
13314 const int iy = (int) ((rlat[i] - ctl->
csi_lat0) / dlat);
13315 const int iz = (int) ((rz[i] - ctl->
csi_z0) / dz);
13321 obsmean[idx] += robs[i];
13322 obsstd[idx] +=
SQR(robs[i]);
13327 for (
int ip = 0; ip < atm->
np; ip++) {
13330 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13334 int ens_id = ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
13335 if (ens_id < 0 || ens_id >= (ensemble ? ctl->
nens : 1))
13336 ERRMSG(
"Ensemble ID out of range!");
13339 const double zpart =
Z(atm->
p[ip]);
13344 || zpart < ctl->csi_z0 || zpart >= ctl->
csi_z1)
13346 const int ix = (int) ((atm->
lon[ip] - ctl->
csi_lon0) / dlon);
13347 const int iy = (int) ((atm->
lat[ip] - ctl->
csi_lat0) / dlat);
13348 const int iz = (int) ((zpart - ctl->
csi_z0) / dz);
13358 for (
int e = 0; e < (ensemble ? ctl->
nens : 1); e++) {
13360 for (
int ix = 0; ix < ctl->
csi_nx; ix++)
13361 for (
int iy = 0; iy < ctl->
csi_ny; iy++)
13362 for (
int iz = 0; iz < ctl->
csi_nz; iz++) {
13367 if (obscount[idx]) {
13368 obsmean[idx] /= obscount[idx];
13370 sqrt(obsstd[idx] / obscount[idx] -
SQR(obsmean[idx]));
13374 const int midx = e * grid_size + idx;
13375 if (modmean[midx] > 0)
13376 modmean[midx] /= (1e6 * area[iy]);
13379 if (obscount[idx]) {
13394 x[n[e]] = modmean[midx];
13395 y[n[e]] = obsmean[idx];
13397 obsstdn[n[e]] = obsstd[idx];
13398 if ((++n[e]) >=
NCSI)
13399 ERRMSG(
"Too many points for statistics!");
13411 static double work[2 *
NCSI], work2[2 *
NCSI];
13412 const int n_obs = cx[e] + cy[e];
13413 const int n_for = cx[e] + cz[e];
13414 const double cx_rd = (ct[e] > 0) ? (1. * n_obs * n_for) / ct[e] : NAN;
13415 const double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
13416 const double pod = (n_obs > 0) ? 100. * cx[e] / n_obs : NAN;
13417 const double far = (n_for > 0) ? 100. * cz[e] / n_for : NAN;
13419 (cx[e] + cy[e] + cz[e] >
13420 0) ? 100. * cx[e] / (cx[e] + cy[e] + cz[e]) : NAN;
13422 (cx[e] + cy[e] + cz[e] - cx_rd >
13423 0) ? 100. * (cx[e] - cx_rd) / (cx[e] + cy[e] + cz[e] - cx_rd) : NAN;
13424 const double rho_p = gsl_stats_correlation(x, 1, y, 1, (
size_t) n[e]);
13425 const double rho_s =
13426 gsl_stats_spearman(x, 1, y, 1, (
size_t) n[e], work);
13427 for (
int i = 0; i < n[e]; i++) {
13428 work[i] = x[i] - y[i];
13429 work2[i] = (obsstdn[i] != 0) ? work[i] / obsstdn[i] : 0;
13431 const double mean = gsl_stats_mean(work, 1, (
size_t) n[e]);
13432 const double rmse =
13433 gsl_stats_sd_with_fixed_mean(work, 1, (
size_t) n[e], 0.0);
13434 const double absdev = gsl_stats_absdev_m(work, 1, (
size_t) n[e], 0.0);
13435 const double loglikelihood =
13436 gsl_stats_tss_m(work2, 1, (
size_t) n[e], 0.0) * -0.5;
13440 "%.2f %d %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n",
13441 t, ensemble ? e : -999, cx[e], cy[e], cz[e], n_obs, n_for, bias,
13442 pod, far, csi, cx_rd, ets, rho_p, rho_s, mean, rmse, absdev,
13443 loglikelihood, n[e]);
13446 for (
int i = 0; i < n[e]; i++)
13447 work[i] = work2[i] = x[i] = y[i] = obsstdn[i] = 0;
13448 ct[e] = cx[e] = cy[e] = cz[e] = n[e] = 0;
13476 const char *filename,
13482 ERRMSG(
"Only lat/lon grid supported");
13489 static int n[
NENS];
13496 ERRMSG(
"Missing ensemble IDs!");
13499 const double t0 = t - 0.5 * ctl->
dt_mod;
13500 const double t1 = t + 0.5 * ctl->
dt_mod;
13503 for (
int i = 0; i <
NENS; i++) {
13504 for (
int iq = 0; iq < ctl->
nq; iq++)
13505 qm[iq][i] = qs[iq][i] = 0;
13506 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
13511 for (
int ip = 0; ip < atm->
np; ip++) {
13514 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13519 ERRMSG(
"Ensemble ID is out of range!");
13523 for (
int iq = 0; iq < ctl->
nq; iq++) {
13524 qm[iq][ctl->
qnt_ens] += atm->
q[iq][ip];
13535 LOG(1,
"Write ensemble data: %s", filename);
13536 if (!(out = fopen(filename,
"w")))
13537 ERRMSG(
"Cannot create file!");
13541 "# $1 = time [s]\n"
13542 "# $2 = altitude [km]\n"
13543 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
13544 for (
int iq = 0; iq < ctl->
nq; iq++)
13545 fprintf(out,
"# $%d = %s (mean) [%s]\n", 5 + iq,
13547 for (
int iq = 0; iq < ctl->
nq; iq++)
13548 fprintf(out,
"# $%d = %s (sigma) [%s]\n", 5 + ctl->
nq + iq,
13550 fprintf(out,
"# $%d = number of members\n\n", 5 + 2 * ctl->
nq);
13553 for (
int i = 0; i <
NENS; i++)
13555 cart2geo(xm[i], &dummy, &lon, &lat);
13556 fprintf(out,
"%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
13557 for (
int iq = 0; iq < ctl->
nq; iq++) {
13559 fprintf(out, ctl->
qnt_format[iq], qm[iq][i] / n[i]);
13561 for (
int iq = 0; iq < ctl->
nq; iq++) {
13563 double var = qs[iq][i] / n[i] -
SQR(qm[iq][i] / n[i]);
13564 fprintf(out, ctl->
qnt_format[iq], (var > 0 ? sqrt(var) : 0));
13566 fprintf(out,
" %d\n", n[i]);
13576 const char *filename,
13581 double *area, *data, *lat, *lon;
13585 LOG(1,
"Write radioactive deposition data: %s", filename);
13589 ALLOC(area,
double,
13591 ALLOC(data,
double,
13601 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13602 lon[ix] = ctl->
grid_lon0 + dlon * (ix + 0.5);
13603 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
13604 lat[iy] = ctl->
grid_lat0 + dlat * (iy + 0.5);
13605 area[iy] = 1e6 * dlat * dlon *
SQR(
RE * M_PI / 180.)
13610 const double lambda[4] = {
13616 const double *inventory[4] = {
13619 for (
int iq = 0; iq < 4; iq++) {
13621 ? exp(-lambda[iq] * (t - ctl->
t_start)) : 1.0;
13622 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13623 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
13625 data[iq * nxy + idx] = inventory[iq][idx] * decay / area[iy];
13635 ERRMSG(
"Radioactive deposition output type unknown!");
13647 const char *filename,
13649 const double *data,
13653 const double *area) {
13656 if (!(out = fopen(filename,
"w")))
13657 ERRMSG(
"Cannot create file!");
13660 "# $1 = time [s]\n"
13661 "# $2 = longitude [deg]\n"
13662 "# $3 = latitude [deg]\n"
13663 "# $4 = area [m^2]\n"
13664 "# $5 = deposited Pb-210 activity [Bq/m^2]\n"
13665 "# $6 = deposited Be-7 activity [Bq/m^2]\n"
13666 "# $7 = deposited Cs-137 activity [Bq/m^2]\n"
13667 "# $8 = deposited I-131 activity [Bq/m^2]\n\n");
13670 for (
int ix = 0; ix < ctl->
grid_nx; ix++) {
13671 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
13673 fprintf(out,
"%.2f %g %g %g %g %g %g %g\n",
13674 t, lon[ix], lat[iy], area[iy],
13675 data[idx], data[nxy + idx],
13676 data[2 * nxy + idx], data[3 * nxy + idx]);
13678 fprintf(out,
"\n");
13687 const char *filename,
13689 const double *data,
13693 const double *area) {
13696 int ncid, dimid[3], varid;
13697 size_t start[2], count[2];
13700 ALLOC(help,
double,
13704 NC(nc_create(filename, NC_NETCDF4, &ncid));
13705 NC(nc_def_dim(ncid,
"time", 1, &dimid[0]));
13706 NC(nc_def_dim(ncid,
"lat", (
size_t) ctl->
grid_ny, &dimid[1]));
13707 NC(nc_def_dim(ncid,
"lon", (
size_t) ctl->
grid_nx, &dimid[2]));
13710 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &dimid[0],
"time",
13711 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
13712 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &dimid[1],
"latitude",
13713 "degrees_north", 0, 0);
13714 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &dimid[2],
"longitude",
13715 "degrees_east", 0, 0);
13716 NC_DEF_VAR(
"area", NC_DOUBLE, 1, &dimid[1],
"surface area",
"m**2", 0, 0);
13717 NC_DEF_VAR(
"depo_pb210", NC_DOUBLE, 3, dimid,
13718 "ground inventory of Pb-210",
"Bq m**-2", ctl->
grid_nc_level, 0);
13720 "ground inventory of Be-7",
"Bq m**-2", ctl->
grid_nc_level, 0);
13721 NC_DEF_VAR(
"depo_cs137", NC_DOUBLE, 3, dimid,
13722 "ground inventory of Cs-137",
"Bq m**-2", ctl->
grid_nc_level, 0);
13723 NC_DEF_VAR(
"depo_i131", NC_DOUBLE, 3, dimid,
13724 "ground inventory of aerosol-bound I-131",
"Bq m**-2",
13726 NC(nc_enddef(ncid));
13735 const char *varname[4] = {
13736 "depo_pb210",
"depo_be7",
"depo_cs137",
"depo_i131"
13738 for (
int iq = 0; iq < 4; iq++) {
13739 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13740 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
13746 NC(nc_close(ncid));
13753 const char *filename,
13761 ERRMSG(
"Only lat/lon grid supported");
13763 static double kz[
EP], kw[
EP];
13767 double *cd, *mean[
NQ], *sigma[
NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
13769 int *ixs, *iys, *izs, *np;
13775 LOG(1,
"Write grid data: %s", filename);
13788 for (
int iq = 0; iq < ctl->
nq; iq++) {
13789 ALLOC(mean[iq],
double,
13791 ALLOC(sigma[iq],
double,
13794 ALLOC(vmr_impl,
double,
13802 ALLOC(area,
double,
13804 ALLOC(press,
double,
13821#pragma omp parallel
for default(shared)
13822 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
13823 z[iz] = ctl->
grid_z0 + dz * (iz + 0.5);
13824 press[iz] =
P(z[iz]);
13828 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13829 lon[ix] = ctl->
grid_lon0 + dlon * (ix + 0.5);
13830#pragma omp parallel for default(shared)
13831 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
13832 lat[iy] = ctl->
grid_lat0 + dlat * (iy + 0.5);
13833 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
13837 const double t0 = t - 0.5 * ctl->
dt_mod;
13838 const double t1 = t + 0.5 * ctl->
dt_mod;
13841#pragma omp parallel for default(shared)
13842 for (
int ip = 0; ip < atm->
np; ip++) {
13843 const double zpart =
Z(atm->
p[ip]);
13844 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
13849 || zpart < ctl->grid_z0 || zpart >= ctl->
grid_z1) {
13853 ixs[ip] = (int) ((atm->
lon[ip] - ctl->
grid_lon0) / dlon);
13854 iys[ip] = (int) ((atm->
lat[ip] - ctl->
grid_lat0) / dlat);
13855 izs[ip] = (int) ((zpart - ctl->
grid_z0) / dz);
13862 for (
int ip = 0; ip < atm->
np; ip++)
13863 if (izs[ip] >= 0) {
13868 for (
int iq = 0; iq < ctl->
nq; iq++) {
13869 mean[iq][idx] += kernel * atm->
q[iq][ip];
13870 sigma[iq][idx] +=
SQR(kernel * atm->
q[iq][ip]);
13875#pragma omp parallel for default(shared)
13876 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13877 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
13878 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
13885 if (ctl->
qnt_m >= 0)
13886 cd[idx] = mean[ctl->
qnt_m][idx] / (1e6 * area[iy]);
13889 vmr_impl[idx] = NAN;
13890 if (ctl->
qnt_m >= 0 && ctl->
molmass > 0 && met0 != NULL
13893 if (mean[ctl->
qnt_m][idx] > 0) {
13899 lon[ix], lat[iy], &temp, ci, cw, 1);
13903 MA / ctl->
molmass * cd[idx] / (
RHO(press[iz], temp) * dz * 1e3);
13909 for (
int iq = 0; iq < ctl->
nq; iq++) {
13910 mean[iq][idx] /= np[idx];
13911 const double var = sigma[iq][idx] / np[idx] -
SQR(mean[iq][idx]);
13912 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
13914 for (
int iq = 0; iq < ctl->
nq; iq++) {
13915 mean[iq][idx] = NAN;
13916 sigma[iq][idx] = NAN;
13923 t, z, lon, lat, area, dz, np);
13928 t, z, lon, lat, area, dz, np);
13932 ERRMSG(
"Grid data format GRID_TYPE unknown!");
13936 for (
int iq = 0; iq < ctl->
nq; iq++) {
13955 const char *filename,
13960 const double *vmr_impl,
13965 const double *area,
13975 if (!(out = popen(
"gnuplot",
"w")))
13976 ERRMSG(
"Cannot create pipe to gnuplot!");
13979 fprintf(out,
"set out \"%s.png\"\n", filename);
13983 int year, mon, day, hour, min, sec;
13984 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
13985 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
13986 year, mon, day, hour, min);
13992 ERRMSG(
"Cannot open file!");
13993 while (fgets(line,
LEN, in))
13994 fprintf(out,
"%s", line);
14001 if (!(out = fopen(filename,
"w")))
14002 ERRMSG(
"Cannot create file!");
14007 "# $1 = time [s]\n"
14008 "# $2 = altitude [km]\n"
14009 "# $3 = longitude [deg]\n"
14010 "# $4 = latitude [deg]\n"
14011 "# $5 = surface area [km^2]\n"
14012 "# $6 = layer depth [km]\n"
14013 "# $7 = column density (implicit) [kg/m^2]\n"
14014 "# $8 = volume mixing ratio (implicit) [ppv]\n"
14015 "# $9 = number of particles [1]\n");
14016 for (
int iq = 0; iq < ctl->
nq; iq++)
14017 fprintf(out,
"# $%i = %s (mean) [%s]\n", 10 + iq, ctl->
qnt_name[iq],
14020 for (
int iq = 0; iq < ctl->
nq; iq++)
14021 fprintf(out,
"# $%i = %s (stddev) [%s]\n", 10 + ctl->
nq + iq,
14023 fprintf(out,
"\n");
14026 for (
int ix = 0; ix < ctl->
grid_nx; ix++) {
14028 fprintf(out,
"\n");
14029 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
14031 fprintf(out,
"\n");
14032 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
14035 fprintf(out,
"%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
14036 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
14037 for (
int iq = 0; iq < ctl->
nq; iq++) {
14039 fprintf(out, ctl->
qnt_format[iq], mean[iq][idx]);
14042 for (
int iq = 0; iq < ctl->
nq; iq++) {
14044 fprintf(out, ctl->
qnt_format[iq], sigma[iq][idx]);
14046 fprintf(out,
"\n");
14059 const char *filename,
14064 const double *vmr_impl,
14069 const double *area,
14073 char longname[2 *
LEN], varname[2 *
LEN];
14077 int *help2, ncid, dimid[10], varid;
14079 size_t start[2], count[2];
14082 ALLOC(help,
double,
14088 NC(nc_create(filename, NC_NETCDF4, &ncid));
14091 NC(nc_def_dim(ncid,
"time", 1, &dimid[0]));
14092 NC(nc_def_dim(ncid,
"z", (
size_t) ctl->
grid_nz, &dimid[1]));
14093 NC(nc_def_dim(ncid,
"lat", (
size_t) ctl->
grid_ny, &dimid[2]));
14094 NC(nc_def_dim(ncid,
"lon", (
size_t) ctl->
grid_nx, &dimid[3]));
14095 NC(nc_def_dim(ncid,
"dz", 1, &dimid[4]));
14098 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &dimid[0],
"time",
14099 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
14100 NC_DEF_VAR(
"z", NC_DOUBLE, 1, &dimid[1],
"altitude",
"km", 0, 0);
14101 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &dimid[2],
"latitude",
"degrees_north", 0,
14103 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &dimid[3],
"longitude",
"degrees_east", 0,
14105 NC_DEF_VAR(
"dz", NC_DOUBLE, 1, &dimid[1],
"layer depth",
"km", 0, 0);
14106 NC_DEF_VAR(
"area", NC_DOUBLE, 1, &dimid[2],
"surface area",
"km**2", 0, 0);
14108 NC_DEF_VAR(
"cd", NC_FLOAT, 4, dimid,
"column density",
"kg m**-2",
14111 "volume mixing ratio (implicit)",
"ppv", ctl->
grid_nc_level, 0);
14112 NC_DEF_VAR(
"np", NC_INT, 4, dimid,
"number of particles",
"1", 0, 0);
14113 for (
int iq = 0; iq < ctl->
nq; iq++) {
14114 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
14115 sprintf(longname,
"%s (mean)", ctl->
qnt_longname[iq]);
14119 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
14120 sprintf(longname,
"%s (stddev)", ctl->
qnt_longname[iq]);
14126 NC(nc_enddef(ncid));
14136 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
14137 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
14138 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
14143 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
14144 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
14145 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
14150 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
14151 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
14152 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
14157 for (
int iq = 0; iq < ctl->
nq; iq++) {
14158 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
14159 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
14160 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
14161 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
14168 for (
int iq = 0; iq < ctl->
nq; iq++) {
14169 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
14170 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
14171 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
14172 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
14179 NC(nc_close(ncid));
14189 const char *filename,
14194 FILE *out, *level_log = NULL;
14195 if (!(out = fopen(filename,
"w")))
14196 ERRMSG(
"Cannot create file!");
14202 ERRMSG(
"Cannot create compression log file!");
14207 "# $1 = compression codec name [-]\n"
14208 "# $2 = variable name [-]\n"
14209 "# $3 = level index [-]\n"
14210 "# $4 = pressure level [hPa]\n"
14211 "# $5 = compression ratio [-]\n"
14212 "# $6 = bits per value [bit/value]\n"
14213 "# $7 = correlation coefficient [-]\n"
14214 "# $8 = mean compression error [-]\n"
14215 "# $9 = standard deviation of compression error [-]\n"
14216 "# $10 = minimum compression error [-]\n"
14217 "# $11 = maximum compression error [-]\n"
14218 "# $12 = mean value of original field [-]\n"
14219 "# $13 = value range of original field [-]\n"
14220 "# $14 = normalized root mean square error [-]\n"
14221 "# $15 = compression time [s]\n"
14222 "# $16 = compression speed [MiB/s]\n"
14223 "# $17 = decompression time [s]\n"
14224 "# $18 = decompression speed [MiB/s]\n\n");
14302 ERRMSG(
"Number of meteo variables doesn't match!");
14322 const char *varname) {
14331 for (
int ix = 0; ix < met->
nx; ix++)
14332 for (
int iy = 0; iy < met->
ny; iy++)
14333 help[
ARRAY_2D(ix, iy, met->
ny)] = var[ix][iy];
14336 LOG(2,
"Write 2-D variable: %s (uncompressed)", varname);
14338 (
size_t) (met->
nx * met->
ny),
14352 const char *varname,
14363#pragma omp parallel for default(shared) collapse(2)
14364 for (
int ix = 0; ix < met->
nx; ix++)
14365 for (
int iy = 0; iy < met->
ny; iy++)
14366 for (
int ip = 0; ip < met->
np; ip++)
14367 help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)] = var[ix][iy][ip];
14371 LOG(2,
"Write 3-D variable: %s (uncompressed)", varname);
14373 (
size_t) (met->
nx * met->
ny * met->
np),
14379 compress_pck(ctl, met, varname, help, 0, level_log, out);
14390 compress_zfp(ctl, met, varname, help, 0, level_log, out);
14403 compress_lz4(ctl, met, varname, help, 0, level_log, out);
14409 compress_cms(ctl, met, varname, help, 0, level_log, out);
14422 compress_sz3(ctl, met, varname, help, 0, level_log, out);
14428 ERRMSG(
"MET_TYPE not supported!");
14431 LOG(3,
"%d", metvar);
14441 const char *filename,
14447 size_t start[4], count[4];
14448 NC(nc_create(filename, NC_NETCDF4, &ncid));
14451 int tid, lonid, latid, levid;
14452 NC(nc_def_dim(ncid,
"time", 1, &tid));
14455 NC(nc_def_dim(ncid,
"lon", (
size_t) met->
nx, &lonid));
14456 NC(nc_def_dim(ncid,
"lat", (
size_t) met->
ny, &latid));
14457 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &lonid,
"longitude",
"degrees_east", 0,
14459 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &latid,
"latitude",
"degrees_north", 0,
14462 NC(nc_def_dim(ncid,
"x", (
size_t) met->
nx, &lonid));
14463 NC(nc_def_dim(ncid,
"y", (
size_t) met->
ny, &latid));
14464 NC_DEF_VAR(
"x", NC_DOUBLE, 1, &lonid,
"x",
"easting", 0, 0);
14465 NC_DEF_VAR(
"y", NC_DOUBLE, 1, &latid,
"y",
"northing", 0, 0);
14468 NC(nc_def_dim(ncid,
"lev", (
size_t) met->
np, &levid));
14471 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"time",
14472 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
14473 NC_DEF_VAR(
"lev", NC_DOUBLE, 1, &levid,
"pressure",
"Pa", 0, 0);
14476 int dimid2[3] = { tid, latid, lonid };
14477 NC_DEF_VAR(
"sp", NC_FLOAT, 3, dimid2,
"Surface pressure",
"Pa",
14479 NC_DEF_VAR(
"z", NC_FLOAT, 3, dimid2,
"Geopotential",
"m**2 s**-2",
14481 NC_DEF_VAR(
"t2m", NC_FLOAT, 3, dimid2,
"2 metre temperature",
"K",
14483 NC_DEF_VAR(
"u10m", NC_FLOAT, 3, dimid2,
"10 metre U wind component",
14485 NC_DEF_VAR(
"v10m", NC_FLOAT, 3, dimid2,
"10 metre V wind component",
14488 "Instantaneous eastward turbulent surface stress",
"N m**-2",
14491 "Instantaneous northward turbulent surface stress",
"N m**-2",
14494 "Instantaneous surface sensible heat flux",
"W m**-2",
14496 NC_DEF_VAR(
"lsm", NC_FLOAT, 3, dimid2,
"Land/sea mask",
"-",
14498 NC_DEF_VAR(
"sstk", NC_FLOAT, 3, dimid2,
"Sea surface temperature",
"K",
14500 NC_DEF_VAR(
"blp", NC_FLOAT, 3, dimid2,
"Boundary layer pressure",
"Pa",
14502 NC_DEF_VAR(
"pt", NC_FLOAT, 3, dimid2,
"Tropopause pressure",
"Pa",
14504 NC_DEF_VAR(
"tt", NC_FLOAT, 3, dimid2,
"Tropopause temperature",
"K",
14506 NC_DEF_VAR(
"zt", NC_FLOAT, 3, dimid2,
"Tropopause height",
"m",
14508 NC_DEF_VAR(
"h2ot", NC_FLOAT, 3, dimid2,
"Tropopause water vapor",
"ppv",
14510 NC_DEF_VAR(
"pct", NC_FLOAT, 3, dimid2,
"Cloud top pressure",
"Pa",
14512 NC_DEF_VAR(
"pcb", NC_FLOAT, 3, dimid2,
"Cloud bottom pressure",
"Pa",
14514 NC_DEF_VAR(
"cl", NC_FLOAT, 3, dimid2,
"Total column cloud water",
14517 "Pressure at lifted condensation level (LCL)",
"Pa",
14520 "Pressure at level of free convection (LFC)",
"Pa",
14523 "Pressure at equilibrium level (EL)",
"Pa", ctl->
met_nc_level,
14526 "Convective available potential energy",
"J kg**-1",
14528 NC_DEF_VAR(
"cin", NC_FLOAT, 3, dimid2,
"Convective inhibition",
14530 NC_DEF_VAR(
"o3c", NC_FLOAT, 3, dimid2,
"Total column ozone",
"DU",
14534 int dimid3[4] = { tid, levid, latid, lonid };
14535 NC_DEF_VAR(
"t", NC_FLOAT, 4, dimid3,
"Temperature",
"K",
14537 NC_DEF_VAR(
"u", NC_FLOAT, 4, dimid3,
"U velocity",
"m s**-1",
14539 NC_DEF_VAR(
"v", NC_FLOAT, 4, dimid3,
"V velocity",
"m s**-1",
14541 NC_DEF_VAR(
"w", NC_FLOAT, 4, dimid3,
"Vertical velocity",
"Pa s**-1",
14543 NC_DEF_VAR(
"q", NC_FLOAT, 4, dimid3,
"Specific humidity",
"kg kg**-1",
14545 NC_DEF_VAR(
"o3", NC_FLOAT, 4, dimid3,
"Ozone mass mixing ratio",
14547 NC_DEF_VAR(
"clwc", NC_FLOAT, 4, dimid3,
"Cloud liquid water content",
14549 NC_DEF_VAR(
"crwc", NC_FLOAT, 4, dimid3,
"Cloud rain water content",
14551 NC_DEF_VAR(
"ciwc", NC_FLOAT, 4, dimid3,
"Cloud ice water content",
14553 NC_DEF_VAR(
"cswc", NC_FLOAT, 4, dimid3,
"Cloud snow water content",
14555 NC_DEF_VAR(
"cc", NC_FLOAT, 4, dimid3,
"Cloud cover",
"-",
14559 NC(nc_enddef(ncid));
14573 for (
int ip = 0; ip < met->
np; ip++)
14574 phelp[ip] = 100. * met->
p[ip];
14617 NC(nc_close(ncid));
14624 const char *varname,
14630 size_t start[4], count[4];
14638 for (
int ix = 0; ix < met->
nx; ix++)
14639 for (
int iy = 0; iy < met->
ny; iy++)
14640 help[
ARRAY_2D(iy, ix, met->
nx)] = scl * var[ix][iy];
14643 LOG(2,
"Write 2-D variable: %s (netCDF)", varname);
14654 const char *varname,
14660 size_t start[4], count[4];
14668 for (
int ix = 0; ix < met->
nx; ix++)
14669 for (
int iy = 0; iy < met->
ny; iy++)
14670 for (
int ip = 0; ip < met->
np; ip++)
14671 help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)] = scl * var[ix][iy][ip];
14674 LOG(2,
"Write 3-D variable: %s (netCDF)", varname);
14684 const char *filename,
14692 ERRMSG(
"Only lat/lon grid supported");
14696 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
14697 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
14699 static int nobs, *obscount, ip, okay;
14708 if (ctl->
qnt_m < 0)
14709 ERRMSG(
"Need quantity mass!");
14713 ERRMSG(
"Specify molar mass!");
14720 ALLOC(area,
double,
14724 ALLOC(press,
double,
14730 ALLOC(rlon,
double,
14732 ALLOC(rlat,
double,
14734 ALLOC(robs,
double,
14741 LOG(1,
"Write profile data: %s", filename);
14742 if (!(out = fopen(filename,
"w")))
14743 ERRMSG(
"Cannot create file!");
14747 "# $1 = time [s]\n"
14748 "# $2 = altitude [km]\n"
14749 "# $3 = longitude [deg]\n"
14750 "# $4 = latitude [deg]\n"
14751 "# $5 = pressure [hPa]\n"
14752 "# $6 = temperature [K]\n"
14753 "# $7 = volume mixing ratio [ppv]\n"
14754 "# $8 = H2O volume mixing ratio [ppv]\n"
14755 "# $9 = O3 volume mixing ratio [ppv]\n"
14756 "# $10 = observed BT index [K]\n"
14757 "# $11 = number of observations\n");
14765 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
14766 z[iz] = ctl->
prof_z0 + dz * (iz + 0.5);
14767 press[iz] =
P(z[iz]);
14771 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
14772 lon[ix] = ctl->
prof_lon0 + dlon * (ix + 0.5);
14773 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
14774 lat[iy] = ctl->
prof_lat0 + dlat * (iy + 0.5);
14775 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
14780 const double t0 = t - 0.5 * ctl->
dt_mod;
14781 const double t1 = t + 0.5 * ctl->
dt_mod;
14784 ALLOC(mass,
double,
14786 ALLOC(obsmean,
double,
14788 ALLOC(obscount,
int,
14792 for (
int i = 0; i < nobs; i++) {
14797 else if (rt[i] >= t1)
14801 if (!isfinite(robs[i]))
14808 const int ix = (int) ((rlon[i] - ctl->
prof_lon0) / dlon);
14809 const int iy = (int) ((rlat[i] - ctl->
prof_lat0) / dlat);
14815 obsmean[idx] += robs[i];
14820 for (ip = 0; ip < atm->
np; ip++) {
14823 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
14827 const double zpart =
Z(atm->
p[ip]);
14832 || zpart < ctl->prof_z0 || zpart >= ctl->
prof_z1)
14834 const int ix = (int) ((atm->
lon[ip] - ctl->
prof_lon0) / dlon);
14835 const int iy = (int) ((atm->
lat[ip] - ctl->
prof_lat0) / dlat);
14836 const int iz = (int) ((zpart - ctl->
prof_z0) / dz);
14842 mass[idx] += atm->
q[ctl->
qnt_m][ip];
14846 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
14847 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
14849 if (obscount[idx2] > 0) {
14853 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
14855 if (mass[idx3] > 0) {
14864 fprintf(out,
"\n");
14867 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
14872 lon[ix], lat[iy], &temp, ci, cw, 1);
14874 lon[ix], lat[iy], &h2o, ci, cw, 0);
14876 lon[ix], lat[iy], &o3, ci, cw, 0);
14881 / (
RHO(press[iz], temp) * area[iy] * dz * 1e9);
14884 fprintf(out,
"%.2f %g %g %g %g %g %g %g %g %g %d\n",
14885 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
14886 obsmean[idx2] / obscount[idx2], obscount[idx2]);
14919 const char *filename,
14927 ERRMSG(
"Only lat/lon grid supported");
14931 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[
EP],
14934 static int nobs, nk;
14947 ALLOC(rlon,
double,
14949 ALLOC(rlat,
double,
14951 ALLOC(robs,
double,
14962 LOG(1,
"Write sample data: %s", filename);
14963 if (!(out = fopen(filename,
"w")))
14964 ERRMSG(
"Cannot create file!");
14968 "# $1 = time [s]\n"
14969 "# $2 = altitude [km]\n"
14970 "# $3 = longitude [deg]\n"
14971 "# $4 = latitude [deg]\n"
14972 "# $5 = surface area [km^2]\n"
14973 "# $6 = layer depth [km]\n"
14974 "# $7 = number of particles [1]\n"
14975 "# $8 = column density [kg/m^2]\n"
14976 "# $9 = volume mixing ratio [ppv]\n"
14977 "# $10 = observed BT index [K]\n\n");
14982 area = M_PI * rmax2;
14986 const double t0 = t - 0.5 * ctl->
dt_mod;
14987 const double t1 = t + 0.5 * ctl->
dt_mod;
14990 for (
int i = 0; i < nobs; i++) {
14995 else if (rt[i] >= t1)
15000 geo2cart(0, rlon[i], rlat[i], x0);
15003 const double rp =
P(rz[i]);
15004 const double ptop =
P(rz[i] + ctl->
sample_dz);
15005 const double pbot =
P(rz[i] - ctl->
sample_dz);
15013 for (
int ip = 0; ip < atm->
np; ip++) {
15016 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
15020 if (fabs(rlat[i] - atm->
lat[ip]) > dlat)
15026 if (
DIST2(x0, x1) > rmax2)
15031 if (atm->
p[ip] > pbot || atm->
p[ip] < ptop)
15035 if (ctl->
qnt_m >= 0)
15042 const double cd = mass / (1e6 * area);
15053 rlon[i], rlat[i], &temp, ci, cw, 1);
15062 fprintf(out,
"%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
15063 rlon[i], rlat[i], area, ctl->
sample_dz, np, cd, vmr, robs[i]);
15084 const char *filename,
15090 ERRMSG(
"Only lat/lon grid supported");
15094 static double rmax2, x0[3], x1[3];
15103 LOG(1,
"Write station data: %s", filename);
15106 if (!(out = fopen(filename,
"w")))
15107 ERRMSG(
"Cannot create file!");
15111 "# $1 = time [s]\n"
15112 "# $2 = altitude [km]\n"
15113 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
15114 for (
int iq = 0; iq < ctl->
nq; iq++)
15115 fprintf(out,
"# $%i = %s [%s]\n", (iq + 5),
15117 fprintf(out,
"\n");
15125 const double t0 = t - 0.5 * ctl->
dt_mod;
15126 const double t1 = t + 0.5 * ctl->
dt_mod;
15129 for (
int ip = 0; ip < atm->
np; ip++) {
15132 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
15148 if (
DIST2(x0, x1) > rmax2)
15156 fprintf(out,
"%.2f %g %g %g",
15157 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]);
15158 for (
int iq = 0; iq < ctl->
nq; iq++) {
15160 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
15162 fprintf(out,
"\n");
15173 const char *filename,
15179 ERRMSG(
"Only lat/lon grid supported");
15187 LOG(1,
"Write VTK data: %s", filename);
15190 const double t0 = t - 0.5 * ctl->
dt_mod;
15191 const double t1 = t + 0.5 * ctl->
dt_mod;
15194 if (!(out = fopen(filename,
"w")))
15195 ERRMSG(
"Cannot create file!");
15199 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
15200 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
15207 "# vtk DataFile Version 3.0\n"
15208 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
15211 fprintf(out,
"POINTS %d float\n", np);
15213 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
15214 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
15218 const double coslat = cos(
DEG2RAD(atm->
lat[ip]));
15219 const double x = radius * coslat * cos(
DEG2RAD(atm->
lon[ip]));
15220 const double y = radius * coslat * sin(
DEG2RAD(atm->
lon[ip]));
15221 const double z = radius * sin(
DEG2RAD(atm->
lat[ip]));
15222 fprintf(out,
"%g %g %g\n", x, y, z);
15225 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
15226 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
15228 fprintf(out,
"%g %g %g\n", atm->
lon[ip], atm->
lat[ip],
15233 fprintf(out,
"POINT_DATA %d\n", np);
15234 for (
int iq = 0; iq < ctl->
nq; iq++) {
15235 fprintf(out,
"SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
15237 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
15238 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
15240 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 write_depo(const char *filename, const ctl_t *ctl, const depo_t *depo, const double t)
Convert cumulative ground inventories to Bq m^-2 and write them.
void mptrac_write_atm(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes air parcel data to a file in various formats.
void day2doy(const int year, const int mon, const int day, int *doy)
Get day of year from date.
void read_met_extrapolate(met_t *met)
Extrapolates meteorological data.
void write_atm_clams_traj(const char *dirname, const ctl_t *ctl, const atm_t *atm, const double t)
Writes CLaMS trajectory data to a NetCDF file.
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 write_depo_asc(const char *filename, const ctl_t *ctl, const double *data, const double t, const double *lon, const double *lat, const double *area)
Write radioactive deposition densities as a gnuplot-compatible table.
void module_chem_init(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Initializes the chemistry modules by setting atmospheric composition.
int locate_reg(const double *xx, const int n, const double x)
Locate the index of the interval containing a given value in a regular grid.
void read_met_nc_levels(const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads and processes meteorological level data from NetCDF files with domain decomposition.
void compress_pck(const ctl_t *ctl, const met_t *met, const char *varname, float *array, const int decompress, FILE *level_log, FILE *inout)
Compresses or decompresses a 3‑D float array using the PCK format.
void read_met_monotonize(const ctl_t *ctl, met_t *met)
Makes zeta and pressure profiles monotone.
int read_clim_ts(const char *filename, clim_ts_t *ts)
Reads a climatological time series from a file and populates the given time series structure.
void intpol_check_cartesian(const double *lons, const int nlon, const double *lats, const int nlat, const double lon, const double lat, double *lon2, double *lat2)
Clamps UTM coordinates to the valid bounds.
void read_met_periodic(met_t *met)
Applies periodic boundary conditions to meteorological data along longitudinal axis.
int compress_metvar_index(const char *varname)
Maps a meteorological variable name to its internal MPTRAC variable index.
void module_timesteps_init(ctl_t *ctl, const atm_t *atm)
Initialize start time and time interval for time-stepping.
void write_ens(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes ensemble data to a file.
void module_mixing(const ctl_t *ctl, const clim_t *clim, atm_t *atm, const double t)
Update atmospheric properties through interparcel mixing.
double clim_zm(const clim_zm_t *zm, const double t, const double lat, const double p)
Interpolates monthly mean zonal mean climatological variables.
void 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 mptrac_free(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm, depo_t *depo, dd_t *dd)
Frees memory resources allocated for MPTRAC.
void level_definitions(ctl_t *ctl)
Defines pressure levels for meteorological data.
void write_grid_asc(const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
Writes grid data to an ASCII file.
void mptrac_update_device(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
Updates device memory for specified data structures.
void mptrac_write_output(const char *dirname, const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, depo_t *depo, const double t)
Writes various types of output data to files in a specified directory.
void time2jsec(const int year, const int mon, const int day, const int hour, const int min, const int sec, const double remain, double *jsec)
Converts time components to seconds since January 1, 2000, 12:00:00 UTC.
void intpol_met_time_3d(const met_t *met0, float array0[EX][EY][EP], const met_t *met1, float array1[EX][EY][EP], const double ts, const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological data in 3D space and time.
void get_met_filename(const ctl_t *ctl, const double t, const int direct, const char *metbase, const double dt_met, char *filename)
Generates a formatted filename for meteorological data files based on the input parameters.
void fft_help(double *fcReal, double *fcImag, const int n)
Computes the Fast Fourier Transform (FFT) of a complex sequence.
void module_wet_depo(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Perform wet deposition calculations for air parcels.
int compress_read_lossy_scale(FILE *in, const size_t nz, double **off, double **scl)
Read optional lossyscaling metadata for a 3-D field.
double nat_temperature(const double p, const double h2o, const double hno3)
Calculates the nitric acid trihydrate (NAT) temperature.
void spline(const double *x, const double *y, const int n, const double *x2, double *y2, const int n2, const int method)
Performs spline interpolation or linear interpolation.
void 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.
void mptrac_init(ctl_t *ctl, cache_t *cache, clim_t *clim, atm_t *atm, depo_t *depo, const int ntask)
Initializes the MPTRAC model and its associated components.
int mptrac_read_atm(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a specified file into the given atmospheric structure.
void mptrac_update_host(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
Updates host memory for specified data structures.
double clim_oh(const ctl_t *ctl, const clim_t *clim, const double t, const double lon, const double lat, const double p)
Calculates the hydroxyl radical (OH) concentration from climatology data, with an optional diurnal co...
void write_met_bin_3d(FILE *out, const ctl_t *ctl, met_t *met, float var[EX][EY][EP], const char *varname, const int metvar, FILE *level_log)
Writes a 3-dimensional meteorological variable to a binary file.
void read_met_ozone(met_t *met)
Calculates the total column ozone from meteorological ozone data.
void mptrac_alloc(ctl_t **ctl, cache_t **cache, clim_t **clim, met_t **met0, met_t **met1, atm_t **atm, depo_t **depo, dd_t **dd)
Allocates and initializes memory resources for MPTRAC.
void 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.
void write_depo_nc(const char *filename, const ctl_t *ctl, const double *data, const double t, const double *lon, const double *lat, const double *area)
Write radioactive deposition densities as a CF-style netCDF file.
int mptrac_read_met(const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met, dd_t *dd)
Reads meteorological data from a file, supporting multiple formats and MPI broadcasting.
void mptrac_run_timestep(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t **met0, met_t **met1, atm_t *atm, depo_t *depo, double t, dd_t *dd)
Executes a single timestep of the MPTRAC model simulation.
void write_vtk(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes VTK (Visualization Toolkit) data to a specified file.
void module_tracer_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Simulate chemical reactions involving long-lived atmospheric tracers.
void mptrac_read_ctl(const char *filename, int argc, char *argv[], ctl_t *ctl)
Reads control parameters from a configuration file and populates the given structure.
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 module_radio_depo(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm, depo_t *depo)
Deposit supported radionuclides from air parcels onto the ground grid.
void write_csi(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes Critical Success Index (CSI) data to a file.
void write_atm_nc(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a NetCDF file.
MPTRAC library declarations.
#define NN(x0, y0, x1, y1, x)
Perform nearest-neighbor interpolation.
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 SO2_DISS_K2_TEMP
Temperature dependence of the second SO2 dissociation constant [K].
#define PARTICLE_LOOP(ip0, ip1, check_dt,...)
Loop over particle indices with OpenACC acceleration.
#define MA
Molar mass of dry air [g/mol].
#define RADIO_HALF_LIFE_CS137
Half-life of Cs-137 [s].
#define AVO
Avogadro constant [1/mol].
#define KB
Boltzmann constant [kg m^2/(K s^2)].
#define SO2_CORR_B
Exponent of the high-SO2 correction [1].
#define COMPRESS_BPV(n, stored_size)
Calculate bits per value from stored size and element count.
#define MH2O
Molar mass of water vapor [g/mol].
#define METVAR
Number of 3-D meteorological variables.
#define NENS
Maximum number of data points for ensemble analysis.
#define FWRITE(ptr, type, size, out)
Write data from memory to a file stream.
#define PW(p, h2o)
Calculate partial water vapor pressure.
#define H0
Scale height [km].
#define NC_PUT_ATT_GLOBAL(attname, text)
Add a global text attribute to a NetCDF file.
#define MOLEC_DENS(p, t)
Calculate the density of a gas molecule.
#define LAPSE(p1, t1, p2, t2)
Calculate lapse rate.
#define NC(cmd)
Execute a NetCDF command and check for errors.
#define RADIO_DRY_VDEP_I131
Dry deposition velocity of aerosol-bound I-131 [m/s].
#define SELECT_TIMER(id, group)
Select and start a timer with specific attributes.
#define RADIO_DRY_VDEP_CS137
Dry deposition velocity of Cs-137 [m/s].
#define SO2_DISS_K1_REF
First SO2 dissociation constant at CHEM_REF_TEMP [mol/L].
#define ECC_READ_3D(variable, level, target, scaling_factor, found_flag)
Writes 3D data from a grib message into the meteo struct.
void compress_zfp(const ctl_t *ctl, const met_t *met, const char *varname, float *array, const int decompress, FILE *level_log, FILE *inout)
Compresses or decompresses a 3D array of floats using the ZFP library.
#define SO2_DISS_K1_TEMP
Temperature dependence of the first SO2 dissociation constant [K].
#define DOTP(a, b)
Calculate the dot product of two vectors.
#define RA
Specific gas constant of dry air [J/(kg K)].
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 O1D_RATE_CFC12_B
O(1D) reaction temperature parameter for CFC-12 [K].
#define ERRMSG(...)
Print an error message with contextual information and terminate the program.
#define NC_PUT_INT(varname, ptr, hyperslab)
Write integer data to a NetCDF variable.
#define O1D_RATE_N2O_A
O(1D) reaction pre-factor for N2O [cm^3/s].
#define EY
Maximum number of latitudes for meteo data.
#define RADIO_DRY_VDEP_PB210
Dry deposition velocity of Pb-210 [m/s].
#define SH(h2o)
Compute specific humidity from water vapor volume mixing ratio.
void compress_sz3(const ctl_t *ctl, const met_t *met, const char *varname, float *array, const int decompress, FILE *level_log, FILE *inout)
Compresses or decompresses a 3-D float array using the SZ3 library.
#define H2O2_HENRY_TEMP
Temperature dependence of the H2O2 Henry constant [K].
#define INTPOL_3D(var, init)
Perform 3D interpolation for a meteorological variable.
#define CLAMP(v, lo, hi)
Clamp a value to a specified range.
#define M_AIR_MOLECULE
Mean mass of an air molecule [kg].
#define NOBS
Maximum number of observation data points.
#define NTHREADS
Maximum number of OpenMP threads.
#define ARRAY_2D(ix, iy, ny)
Macro for computing the linear index of a 2D array element.
#define Z(p)
Convert pressure to altitude.
#define codes_handle
Placeholder when ECCODES is not available.
void compress_zstd(const ctl_t *ctl, const met_t *met, const char *varname, float *array, const int decompress, FILE *level_log, FILE *inout)
Compresses or decompresses a float array using ZSTD.
#define SO2_CORR_A
Scale factor of the high-SO2 correction [1].
#define P(z)
Compute pressure at given altitude.
#define LV
Latent heat of vaporization of water [J/kg].
#define RADIO_HALF_LIFE_I131
Half-life of I-131 [s].
#define RADIO_HALF_LIFE_BE7
Half-life of Be-7 [s].
#define G0
Standard gravity [m/s^2].
void compress_cms(const ctl_t *ctl, const met_t *met, const char *varname, float *array, const int decompress, FILE *level_log, FILE *inout)
Compresses or decompresses a 3-D meteorological field using cmultiscale.
#define CP
Maximum number of pressure levels for climatological data.
#define NQ
Maximum number of quantities per data point.
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 H2O2_SO2_RATE_REF
Reference rate for aqueous H2O2-SO2 chemistry [L^2/(mol^2 s)].
#define DX2DEG(dx, lat)
Convert a distance in kilometers to degrees longitude at a given latitude.
#define DEG2DY(dlat)
Convert a latitude difference to a distance in the y-direction (north-south).
#define O1D_RATE_CFC12_A
O(1D) reaction pre-factor for CFC-12 [cm^3/s].
#define EX
Maximum number of longitudes for meteo data.
#define EPS
Ratio of the specific gas constant of dry air and water vapor [1].
#define PSICE(t)
Compute saturation pressure over ice (WMO, 2018).
#define O1D_RATE_N2O_B
O(1D) reaction temperature parameter for N2O [K].
#define DX2COORD(met, dx, lat)
Convert a distance in meters to a coordinate value based on grid type.
#define O1D_RATE_CCL4_B
O(1D) reaction temperature parameter for CCl4 [K].
#define COMPRESS_RATIO(raw_size, stored_size)
Calculate the compression ratio from raw and stored byte counts.
#define WET_DEPO_T_ICE
Lower temperature of the ice-cloud retention transition [K].
#define THETA(p, t)
Compute potential temperature.
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 RADIO_WET_COEFF_BE7
Wet deposition coefficient of Be-7 [s^-1].
#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 O1D_RATE_CFC11_A
O(1D) reaction pre-factor for CFC-11 [cm^3/s].
#define RADIO_WET_COEFF_CS137
Wet deposition coefficient of Cs-137 [s^-1].
#define TOK(line, tok, format, var)
Get string tokens.
#define ZDIFF(lnp0, t0, h2o0, lnp1, t1, h2o1)
Calculate geopotential height difference.
#define THETAVIRT(p, t, h2o)
Compute virtual potential temperature.
#define DZ2DP(dz, p)
Convert a change in altitude to a change in pressure.
#define WARN(...)
Print a warning message with contextual information.
#define H2O2_SO2_RATE_TEMP
Temperature parameter for the aqueous H2O2-SO2 rate [K].
#define ZETA(ps, p, t)
Computes the value of the zeta vertical coordinate.
#define RHICE(p, t, h2o)
Compute relative humidity over ice.
#define INTPOL_TIME_ALL(time, p, lon, lat)
Interpolate multiple meteorological variables in time.
#define ALLOC(ptr, type, n)
Allocate memory for a pointer with error handling.
void read_met_grib_levels(codes_handle **handles, const int num_messages, const ctl_t *ctl, met_t *met)
Reads meteorological variables at different vertical levels from a grib file.
#define SET_ATM(qnt, val)
Set atmospheric quantity value.
#define O1D_RATE_CCL4_A
O(1D) reaction pre-factor for CCl4 [cm^3/s].
#define CTS
Maximum number of data points of climatological time series.
#define ECC_READ_2D(variable, target, scaling_factor, found_flag)
Writes 2-D data from a grib message into the meteo struct.
#define OMEGA_EARTH
Angular velocity of Earth [s^-1].
#define DEG2RAD(deg)
Converts degrees to radians.
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 RADIO_WET_COEFF_I131
Wet deposition coefficient of aerosol-bound I-131 [s^-1].
#define RAD2DEG(rad)
Converts radians to degrees.
#define RADIO_DRY_VDEP_BE7
Dry deposition velocity of Be-7 [m/s].
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 H2O2_HENRY_REF
Henry constant of H2O2 at CHEM_REF_TEMP [mol/(L atm)].
#define CHEM_REF_TEMP
Reference temperature for chemical equilibrium constants [K].
#define NC_PUT_FLOAT(varname, ptr, hyperslab)
Write a float array to a NetCDF file.
#define DD_EX_GLOB
Maximum number of longitudes of global meteo data.
#define CY
Maximum number of latitudes for climatological data.
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 RADIO_HALF_LIFE_RN222
Half-life of Rn-222 [s].
#define NC_DEF_VAR(varname, type, ndims, dims, long_name, units, level, quant)
Define a NetCDF variable with attributes.
#define TDEW(p, h2o)
Calculate dew point temperature.
#define KAPPA
Exponent used for potential-temperature calculations [1].
#define ARRHENIUS(a, b, t)
Calculate the Arrhenius rate constant.
#define NCSI
Maximum number of data points for CSI calculation.
#define NC_GET_DOUBLE(varname, ptr, force)
Retrieve a double-precision variable from a NetCDF file.
#define EP
Maximum number of pressure levels for meteo data.
#define PSAT(t)
Compute saturation pressure over water.
#define SO2_DISS_K2_REF
Second SO2 dissociation constant at CHEM_REF_TEMP [mol/L].
#define SO2_HENRY_REF
Henry constant of SO2 at CHEM_REF_TEMP [mol/(L atm)].
#define SO2_HENRY_TEMP
Temperature dependence of the SO2 Henry constant [K].
#define RHO(p, t)
Compute density of air.
#define RADIO_HALF_LIFE_PB210
Half-life of Pb-210 [s].
void module_kpp_chem(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
KPP chemistry module.
#define CO3
Maximum number of total column ozone data for climatological data.
void read_met_grib_grid(codes_handle **handles, int count_handles, met_t *met)
Reads global meteorological information from a grib file.
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 WET_DEPO_T_LIQUID
Upper temperature of the ice-cloud retention transition [K].
#define DIST2(a, b)
Calculate the squared Euclidean distance between two points in Cartesian coordinates.
#define NC_INQ_DIM(dimname, ptr, min, max, check)
Inquire the length of a dimension in a NetCDF file.
#define DEG2DX(dlon, lat)
Convert a longitude difference to a distance in the x-direction (east-west) at a specific latitude.
#define DY2COORD(met, dy)
Convert a distance to coordinate value based on grid type.
#define CPD
Specific heat of dry air at constant pressure [J/(kg K)].
#define CSZA
Maximum number of solar zenith angles for climatological data.
#define DY2DEG(dy)
Convert a distance in kilometers to degrees latitude.
#define O1D_RATE_CFC11_B
O(1D) reaction temperature parameter for CFC-11 [K].
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 WET_DEPO_T_LIQUID_BC
Temperature threshold for below-cloud retention [K].
#define RADIO_HALF_LIFE_XE133
Half-life of Xe-133 [s].
#define RADIO_WET_COEFF_PB210
Wet deposition coefficient of Pb-210 [s^-1].
#define FMOD(x, y)
Calculate the floating-point remainder of dividing x by y.
#define DOBSON_UNIT
Ozone column mass corresponding to one Dobson unit [kg/m^2].
double lat[NP]
Latitude [deg].
double lon[NP]
Longitude [deg].
int np
Number of air parcels.
double q[NQ][NP]
Quantity data (for various, user-defined attributes).
double p[NP]
Pressure [hPa].
double dt[NP]
Timesteps [s].
double iso_ts[NP]
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
RADIO_DECAY switch for airborne and deposited activity (0=off, 1=on, default: 0).
int met_geopot_sx
Longitudinal smoothing of geopotential heights.
int met_sy
Smoothing for latitudes.
int qnt_ps
Quantity array index for surface pressure.
int rng_type
Random number generator (0=GSL, 1=Squares, 2=cuRAND).
char prof_obsfile[LEN]
Observation data file for profile output.
int met_pck_zstd
Apply an additional ZSTD compression step to PCK payloads (0=off, 1=on).
int isosurf
Isosurface parameter (0=none, 1=pressure, 2=density, 3=theta, 4=balloon).
double bound_p1
Boundary conditions top pressure [hPa].
int qnt_zs
Quantity array index for surface geopotential height.
int prof_nz
Number of altitudes of gridded profile data.
double csi_dt_out
Time step for CSI output [s].
int met_cape
Convective available potential energy data (0=file, 1=calculate).
double csi_modmin
Minimum column density to trigger detection [kg/m^2].
int met_sx
Smoothing for longitudes.
double chemgrid_lon1
Upper longitude of chemistry grid [deg].
double depo_dt_out
DEPO_DT_OUT time interval for radioactive deposition output [s] (default: 86400).
double turb_mesox
Horizontal scaling factor for mesoscale wind fluctuations.
char grid_kernel[LEN]
Kernel data file for grid output.
double prof_z0
Lower altitude of gridded profile data [km].
int qnt_w
Quantity array index for vertical velocity.
double bound_vmr
Boundary conditions volume mixing ratio [ppv].
double met_tropo_pv
Dynamical tropopause potential vorticity threshold [PVU].
int prof_nx
Number of longitudes of gridded profile data.
int qnt_stat
Quantity array index for station flag.
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]).
char depo_basename[LEN]
DEPO_BASENAME for radioactive deposition files (default: disabled with "-").
int qnt_zeta_d
Quantity array index for diagnosed zeta vertical coordinate.
char clim_h2o2_filename[LEN]
Filename of H2O2 climatology.
int tracer_chem
Switch for first order tracer chemistry module (0=off, 1=on).
double dt_mod
Time step of simulation [s].
int diffusion
Diffusion switch (0=off, 1=on).
int qnt_tnat
Quantity array index for T_NAT.
int qnt_eta_dot
Quantity array index for velocity of eta vertical coordinate.
int qnt_tice
Quantity array index for T_ice.
int turb_pbl_scheme
PBL turbulence scheme (0=none, 1=closure).
int qnt_zg
Quantity array index for geopotential height.
double vtk_offset
Vertical offset for VTK data [km].
int qnt_v
Quantity array index for meridional wind.
int qnt_mloss_dry
Quantity array index for total mass loss due to dry deposition.
double bound_vmr_trend
Boundary conditions volume mixing ratio trend [ppv/s].
double met_zfp_tol[METVAR]
ZFP compression tolerance.
int met_cache
Preload meteo data into disk cache (0=no, 1=yes).
int qnt_oh
Quantity array index for OH volume mixing ratio (climatology).
int met_sz3_prec[METVAR]
SZ3 compression precision.
char qnt_unit[NQ][LEN]
Quantity units.
int qnt_Ch
Quantity array index for H volume mixing ratio (chemistry code).
int met_press_level_def
Use predefined pressure levels or not.
int oh_chem_reaction
Reaction type for OH chemistry (0=none, 2=bimolecular, 3=termolecular).
int qnt_h2o
Quantity array index for water vapor volume mixing ratio.
int prof_ny
Number of latitudes of gridded profile data.
int qnt_rhice
Quantity array index for relative humidity over ice.
int qnt_rho
Quantity array index for density of air.
double sample_dz
Layer depth for sample output [km].
double tdec_strat
Life time of particles in the stratosphere [s].
int obs_type
Type of observation data files (0=ASCII, 1=netCDF).
int grid_nc_quant[NQ]
Number of digits for quantization of netCDF grid data files (0=off).
int qnt_us
Quantity array index for surface zonal wind.
double grid_lon1
Upper longitude of gridded data [deg].
int qnt_Cn2o
Quantity array index for N2O volume mixing ratio (chemistry code).
int qnt_Cccl3f
Quantity array index for CFC-11 volume mixing ratio (chemistry code).
char qnt_name[NQ][LEN]
Quantity names.
int depo_type
DEPO_TYPE of deposition files (0=ASCII, 1=netCDF, default: 0).
char 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 radio_depo
RADIO_DEPO switch for radionuclide deposition (0=off, 1=on, default: 0).
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).
Ground inventories of deposited radionuclides.
double Ai131[EX *EY]
Deposited I-131 activity [Bq].
double Abe7[EX *EY]
Deposited Be-7 activity [Bq].
double Acs137[EX *EY]
Deposited Cs-137 activity [Bq].
double Apb210[EX *EY]
Deposited Pb-210 activity [Bq].
float zt[EX][EY]
Tropopause geopotential height [km].
float sst[EX][EY]
Sea surface temperature [K].
float rwc[EX][EY][EP]
Cloud rain water content [kg/kg].
float o3c[EX][EY]
Total column ozone [DU].
float zeta_dotl[EX][EY][EP]
Vertical velocity on model levels [K/s].
float h2o[EX][EY][EP]
Water vapor volume mixing ratio [1].
float cape[EX][EY]
Convective available potential energy [J/kg].
float w[EX][EY][EP]
Vertical velocity [hPa/s].
float pct[EX][EY]
Cloud top pressure [hPa].
double hybrid[EP]
Model hybrid levels.
int nx
Number of longitudes.
int ny
Number of latitudes.
float shf[EX][EY]
Surface sensible heat flux [W/m^2].
float ps[EX][EY]
Surface pressure [hPa].
float lwc[EX][EY][EP]
Cloud liquid water content [kg/kg].
float us[EX][EY]
Surface zonal wind [m/s].
float wl[EX][EY][EP]
Vertical velocity on model levels [hPa/s].
float vl[EX][EY][EP]
Meridional wind on model levels [m/s].
float zs[EX][EY]
Surface geopotential height [km].
float o3[EX][EY][EP]
Ozone volume mixing ratio [1].
float cc[EX][EY][EP]
Cloud cover [1].
int np
Number of pressure levels.
float t[EX][EY][EP]
Temperature [K].
float ts[EX][EY]
Surface temperature [K].
float u[EX][EY][EP]
Zonal wind [m/s].
float ess[EX][EY]
Eastward turbulent surface stress [N/m^2].
float ul[EX][EY][EP]
Zonal wind on model levels [m/s].
float pcb[EX][EY]
Cloud bottom pressure [hPa].
float pel[EX][EY]
Pressure at equilibrium level (EL) [hPa].
float cin[EX][EY]
Convective inhibition [J/kg].
float plcl[EX][EY]
Pressure at lifted condensation level (LCL) [hPa].
double lon[EX]
Longitudes [deg].
float pt[EX][EY]
Tropopause pressure [hPa].
float tt[EX][EY]
Tropopause temperature [K].
float pbl[EX][EY]
Boundary layer pressure [hPa].
float vs[EX][EY]
Surface meridional wind [m/s].
float z[EX][EY][EP]
Geopotential height [km].
float v[EX][EY][EP]
Meridional wind [m/s].
int npl
Number of model levels.
float lsm[EX][EY]
Land-sea mask [1].
float iwc[EX][EY][EP]
Cloud ice water content [kg/kg].
float h2ot[EX][EY]
Tropopause water vapor volume mixing ratio [ppv].
float pv[EX][EY][EP]
Potential vorticity [PVU].
double eta[EP]
Model level eta values.
float cl[EX][EY]
Total column cloud water [kg/m^2].
float nss[EX][EY]
Northward turbulent surface stress [N/m^2].
float pl[EX][EY][EP]
Pressure on model levels [hPa].
float plfc[EX][EY]
Pressure at level of free convection (LFC) [hPa].
double hyam[EP]
Model level a coefficients [Pa].
double lat[EY]
Latitudes [deg].
float swc[EX][EY][EP]
Cloud snow water content [kg/kg].
double hybm[EP]
Model level b coefficients.
float zetal[EX][EY][EP]
Zeta on model levels [K].
double p[EP]
Pressure levels [hPa].
double lat
Latitude [deg].
double lon
Longitude [deg].
double q[NQ]
Quantity data (for various, user-defined attributes).