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 control 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]);
3949#pragma acc parallel loop independent gang vector
3951 for (
int i = 0; i < ngrid * nens; i++)
3955 const double t0 = tt - 0.5 * ctl->
dt_mod;
3956 const double t1 = tt + 0.5 * ctl->
dt_mod;
3960#pragma acc parallel loop independent gang vector
3962#pragma omp parallel for default(shared)
3964 for (
int ip = 0; ip < np; ip++) {
3965 const double zpart =
Z(atm->
p[ip]);
3966 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
3971 || zpart < ctl->chemgrid_z0 || zpart >= ctl->
chemgrid_z1) {
3977 izs[ip] = (int) ((zpart - ctl->
chemgrid_z0) / dz);
3978 if (ixs[ip] >= nx || iys[ip] >= ny || izs[ip] >= nz)
3984#pragma acc parallel loop independent gang vector
3986#pragma omp parallel for default(shared)
3988 for (
int ix = 0; ix < nx; ix++)
3992#pragma acc parallel loop independent gang vector
3994#pragma omp parallel for default(shared)
3996 for (
int iy = 0; iy < ny; iy++) {
3998 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
4003#pragma acc parallel loop independent gang vector
4005 for (
int ip = 0; ip < np; ip++) {
4007 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
4008 if (ensemble_mode) {
4009 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
4010 mass_idx += ens * ngrid;
4013#pragma acc atomic update
4015 mass[mass_idx] += atm->
q[ctl->
qnt_m][ip];
4021#pragma acc parallel loop independent gang vector
4023#pragma omp parallel for default(shared)
4025 for (
int ip = 0; ip < np; ip++)
4033 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
4036 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
4037 if (ensemble_mode) {
4038 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
4039 mass_idx += ens * ngrid;
4043 const double m = mass[mass_idx];
4045 / (
RHO(press[izs[ip]], temp) * area[iys[ip]] * dz * 1e9);
4050#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
4078 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4094 const double lat_ref =
4097 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
4099 lat_ref, atm->
p[ip]));
4101 lat_ref, atm->
p[ip]));
4103 lat_ref, atm->
p[ip]));
4123 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4131 double pbot = ps, ptop = ps;
4148 double cape, cin, pel;
4154 if (isfinite(cape) && cape >= ctl->
conv_cape
4156 ptop =
MIN(ptop, pel);
4160 if (ptop != pbot && atm->
p[ip] >= ptop) {
4165 pbot, atm->
lon[ip], atm->
lat[ip], &tbot, ci, cw, 1);
4167 atm->
lon[ip], atm->
lat[ip], &ttop, ci, cw, 1);
4168 const double rhobot = pbot / tbot;
4169 const double rhotop = ptop / ttop;
4172 const double rho = rhobot + (rhotop - rhobot) * cache->
rs[ip];
4175 atm->
p[ip] =
LIN(rhobot, pbot, rhotop, ptop, rho);
4192 int npart = 0, capacity = 0;
4200 dd_sort(ctl, *met, atm, dd, &npart);
4202 dd_push(ctl, atm, cache, &npart);
4205 if (npart > capacity) {
4206 const int newcap = npart + npart / 2 + 1;
4208 realloc(particles, (
size_t) newcap *
sizeof(
particle_t));
4210 ERRMSG(
"Out of memory!");
4219 MPI_Barrier(MPI_COMM_WORLD);
4245 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4248 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,clim,atm)") {
4257 const double aux = exp(-cache->
dt[ip] / tdec);
4258 if (ctl->
qnt_m >= 0) {
4261 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
4262 atm->
q[ctl->
qnt_m][ip] *= aux;
4287 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4295 float umean = 0, usig = 0, vmean = 0, vsig = 0, wmean = 0, wsig = 0;
4296 for (
int i = 0; i < 2; i++)
4297 for (
int j = 0; j < 2; j++)
4298 for (
int k = 0; k < 2; k++) {
4299 umean += met0->
u[ix + i][iy + j][iz + k];
4300 usig +=
SQR(met0->
u[ix + i][iy + j][iz + k]);
4301 vmean += met0->
v[ix + i][iy + j][iz + k];
4302 vsig +=
SQR(met0->
v[ix + i][iy + j][iz + k]);
4303 wmean += met0->
w[ix + i][iy + j][iz + k];
4304 wsig +=
SQR(met0->
w[ix + i][iy + j][iz + k]);
4306 umean += met1->
u[ix + i][iy + j][iz + k];
4307 usig +=
SQR(met1->
u[ix + i][iy + j][iz + k]);
4308 vmean += met1->
v[ix + i][iy + j][iz + k];
4309 vsig +=
SQR(met1->
v[ix + i][iy + j][iz + k]);
4310 wmean += met1->
w[ix + i][iy + j][iz + k];
4311 wsig +=
SQR(met1->
w[ix + i][iy + j][iz + k]);
4313 usig = usig / 16.f -
SQR(umean / 16.f);
4314 usig = (usig > 0 ? sqrtf(usig) : 0);
4315 vsig = vsig / 16.f -
SQR(vmean / 16.f);
4316 vsig = (vsig > 0 ? sqrtf(vsig) : 0);
4317 wsig = wsig / 16.f -
SQR(wmean / 16.f);
4318 wsig = (wsig > 0 ? sqrtf(wsig) : 0);
4321 const double r = 1 - 2 * fabs(cache->
dt[ip]) / ctl->
dt_met;
4322 const double r2 = sqrt(1 - r * r);
4326 cache->
uvwp[ip][0] =
4327 (float) (r * cache->
uvwp[ip][0] +
4332 cache->
uvwp[ip][1] =
4333 (float) (r * cache->
uvwp[ip][1] +
4340 cache->
uvwp[ip][2] =
4341 (float) (r * cache->
uvwp[ip][2] +
4343 atm->
p[ip] += cache->
uvwp[ip][2] * cache->
dt[ip];
4364 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4366 double pbl, ps, dsigw_dz = 0.0, sig_u = 0.0, sig_v = 0.0, sig_w = 0.0;
4367 double tau_u = 0.0, tau_v = 0.0, tau_w = 0.0;
4374 if (atm->
p[ip] < pbl)
4381 if (!(ps > 0.0 && pbl > 0.0 && ps > pbl))
4386 const double p =
MIN(atm->
p[ip], ps);
4387 const double zs =
Z(ps);
4388 const double z_raw = 1e3 * (
Z(p) - zs);
4389 const double zi = 1e3 * (
Z(pbl) - zs);
4396 const double z =
CLAMP(z_raw, 0.0, zi);
4397 const double zeta =
CLAMP(z / zi, 1e-6, 1.0 - 1e-6);
4398 const double z_m =
MAX(z, 1.0);
4403 const double p_save = atm->
p[ip];
4407 double ess, nss, h2o, t;
4414 atm->
p[ip] = p_save;
4416 const double tv =
TVIRT(t, h2o);
4417 const double thetav =
THETAVIRT(p, t, h2o);
4418 const double rho =
RHO(p, tv);
4419 const double tau = sqrt(
SQR(ess) +
SQR(nss));
4424 const double ustar = sqrt(
MAX(tau / rho, 0.0));
4425 const double ust =
MAX(1e-4, ustar);
4436 if (fabs(shf) > 1e-6)
4440 if (zi / fabs(ol) < 1.0) {
4445 const double corr = z_m / ust;
4446 const double sigw0 = 1.3 * ust * exp(-2e-4 * corr);
4448 sig_u =
MAX(2.0 * ust * exp(-3e-4 * corr), 1e-5);
4449 sig_v =
MAX(sigw0, 1e-5);
4450 sig_w =
MAX(sigw0, 1e-5);
4451 dsigw_dz = -2e-4 * sigw0 / ust;
4453 tau_u = 0.5 * z_m / sig_w / (1.0 + 1.5e-3 * corr);
4459 else if (ol < 0.0) {
4462 const double wstar_arg = -
G0 / thetav * shf / (rho *
CPD) * zi;
4463 const double wstar = pow(
MAX(wstar_arg, 0.0), 1.0 / 3.0);
4464 double dsigw2_dz = 0.0;
4467 sig_u =
MAX(ust * pow(
MAX(12.0 - 0.5 * zi / ol, 0.0), 1.0 / 3.0), 1e-6);
4471 const double arg =
MAX(3.0 * zeta - ol / zi, 1e-12);
4472 sig_w = 0.96 * wstar * pow(arg, 1.0 / 3.0);
4473 dsigw2_dz = 1.8432 *
SQR(wstar) / zi * pow(arg, -1.0 / 3.0);
4474 }
else if (zeta < 0.4) {
4475 const double arg =
MAX(3.0 * zeta - ol / zi, 1e-12);
4476 const double s1 = 0.96 * pow(arg, 1.0 / 3.0);
4477 const double s2 = 0.763 * pow(zeta, 0.175);
4480 dsigw2_dz = 1.8432 *
SQR(wstar) / zi * pow(arg, -1.0 / 3.0);
4483 dsigw2_dz = 0.203759 *
SQR(wstar) / zi * pow(zeta, -0.65);
4485 }
else if (zeta < 0.96) {
4486 sig_w = 0.722 * wstar * pow(1.0 - zeta, 0.207);
4487 dsigw2_dz = -0.215812 *
SQR(wstar) / zi * pow(1.0 - zeta, -0.586);
4489 sig_w = 0.37 * wstar;
4493 sig_w =
MAX(sig_w, 1e-6);
4494 dsigw_dz = sig_w > 1e-12 ? 0.5 * dsigw2_dz / sig_w : 0.0;
4497 tau_u = 0.15 * zi /
MAX(sig_u, 1e-12);
4500 if (z_m < fabs(ol)) {
4501 const double denom = 0.55 - 0.38 * fabs(z_m / ol);
4502 tau_w = 0.1 * z_m / (sig_w *
MAX(denom, 0.05));
4503 }
else if (zeta < 0.1)
4504 tau_w = 0.59 * z_m / sig_w;
4506 tau_w = 0.15 * zi / sig_w * (1.0 - exp(-5.0 * zeta));
4512 sig_u =
MAX(2.0 * ust * (1.0 - zeta), 1e-6);
4513 sig_v =
MAX(1.3 * ust * (1.0 - zeta), 1e-6);
4514 sig_w =
MAX(1.3 * ust * (1.0 - zeta), 1e-6);
4515 dsigw_dz = -1.3 * ust / zi;
4517 tau_u = 0.15 * zi / sig_u * sqrt(zeta);
4518 tau_v = 0.467 * tau_u;
4519 tau_w = 0.1 * zi / sig_w * pow(zeta, 0.8);
4523 tau_u =
MAX(tau_u, 10.0);
4524 tau_v =
MAX(tau_v, 10.0);
4525 tau_w =
MAX(tau_w, 30.0);
4528 if (!(sig_u > 0.0 && sig_v > 0.0
4529 && sig_w > 0.0 && tau_u > 0.0 && tau_v > 0.0 && tau_w > 0.0))
4533 const double dt = cache->
dt[ip];
4534 const double dt_abs = fabs(dt);
4536 const double ru = exp(-dt_abs / tau_u);
4537 const double ru2 = sqrt(
MAX(0.0, 1.0 -
SQR(ru)));
4538 const double rv = exp(-dt_abs / tau_v);
4539 const double rv2 = sqrt(
MAX(0.0, 1.0 -
SQR(rv)));
4542 = (float) (cache->
uvwp[ip][0] * ru + sig_u * ru2 * cache->
rs[3 * ip]);
4545 = (float) (cache->
uvwp[ip][1] * rv
4546 + sig_v * rv2 * cache->
rs[3 * ip + 1]);
4551 const double rw = exp(-dt_abs / tau_w);
4552 const double rw2 = sqrt(
MAX(0.0, 1.0 -
SQR(rw)));
4553 const double rhoaux = -1.0 / (1e3 *
H0);
4556 = (float) (cache->
uvwp[ip][2] * rw + sig_w * rw2 * cache->
rs[3 * ip + 2]
4557 + tau_w * (1.0 - rw)
4558 * (2.0 * sig_w * dsigw_dz + rhoaux *
SQR(sig_w)));
4568 double znew = z + cache->
uvwp[ip][2] * dt;
4570 while (znew < 0.0 || znew > zi) {
4574 cache->
uvwp[ip][2] = -cache->
uvwp[ip][2];
4578 znew = 2.0 * zi - znew;
4579 cache->
uvwp[ip][2] = -cache->
uvwp[ip][2];
4586 atm->
p[ip] =
P(zs + znew / 1000.0);
4589 atm->
p[ip] =
CLAMP(atm->
p[ip], pbl, ps);
4611 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4627 const double ptop = met0->
p[met0->
np - 1];
4630 const double wpbl =
pbl_weight(ctl, atm, ip, pbl, ps);
4631 const double wtrop =
tropo_weight(ctl, clim, atm, ip) * (1.0 - wpbl);
4632 const double wstrat = 1.0 - wpbl - wtrop;
4644 const double dt_abs = fabs(cache->
dt[ip]);
4649 const double sigma_h = sqrt(2.0 * Kx * dt_abs);
4654 atm->
lat[ip] +=
DY2COORD(met0, cache->
rs[3 * ip + 1] * sigma_h);
4662 const double sigma_z = sqrt(2.0 * Kz * dt_abs) * 1e-3;
4666 const double p_save = atm->
p[ip];
4671 const double eps_km = 0.01;
4672 const double p_up = p_save +
DZ2DP(eps_km, p_save);
4673 const double p_dn = p_save +
DZ2DP(-eps_km, p_save);
4676 atm->
p[ip] =
MAX(ptop,
MIN(ps, p_up));
4677 const double wpbl_up =
pbl_weight(ctl, atm, ip, pbl, ps);
4678 const double wtrop_up =
4680 const double wstrat_up = 1.0 - wpbl_up - wtrop_up;
4682 const double Kz_up =
4687 atm->
p[ip] =
MAX(ptop,
MIN(ps, p_dn));
4688 const double wpbl_dn =
pbl_weight(ctl, atm, ip, pbl, ps);
4689 const double wtrop_dn =
4691 const double wstrat_dn = 1.0 - wpbl_dn - wtrop_dn;
4693 const double Kz_dn =
4698 atm->
p[ip] = p_save;
4712 const double dKz_dz = (Kz_up - Kz_dn) / (2.0 * eps_km * 1e3);
4713 const double dlnrho_dz = -1.0 / (1e3 *
H0);
4714 const double w_drift = dKz_dz + Kz * dlnrho_dz;
4715 const double dz_drift = w_drift * dt_abs * 1e-3;
4718 const double dz_tot = cache->
rs[3 * ip + 2] * sigma_z + dz_drift;
4721 double ptrial = p_save +
DZ2DP(dz_tot, p_save);
4728 for (
int iter = 0; iter < 10; iter++) {
4730 ptrial = ps * ps / ptrial;
4731 else if (ptrial < ptop)
4732 ptrial = ptop * ptop / ptrial;
4738 atm->
p[ip] =
MAX(ptop,
MIN(ps, ptrial));
4757 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4760 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4772 const double dz = 1000. * (
Z(ps - ctl->
dry_depo_dp) -
Z(ps));
4792 const double aux = exp(-cache->
dt[ip] * v_dep / dz);
4793 if (ctl->
qnt_m >= 0) {
4796 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
4797 atm->
q[ctl->
qnt_m][ip] *= aux;
4817 ERRMSG(
"Only lat/lon grid supported");
4824 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4830 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4837 if (!(lwc > 0 || rwc > 0))
4851 const double H_SO2 =
4857 const double H_h2o2 =
4865 cor = atm->
q[ctl->
qnt_Cx][ip] >
4868 const double h2o2 = H_h2o2
4870 * M * cor * 1000. /
AVO;
4873 const double rho_air = atm->
p[ip] / (
RI * t) *
MA / 10.;
4874 const double CWC = (lwc + rwc) * rho_air / 1e3;
4877 const double rate_coef = k * K_1S * h2o2 * H_SO2 * CWC;
4878 const double aux = exp(-cache->
dt[ip] * rate_coef);
4879 if (ctl->
qnt_m >= 0) {
4882 atm->
q[ctl->
qnt_m][ip] *= aux;
4914 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
4917 cache->
iso_var[ip] = atm->
p[ip] / t;
4923 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
4934 LOG(1,
"Read balloon pressure data: %s", ctl->
balloon);
4938 if (!(in = fopen(ctl->
balloon,
"r")))
4939 ERRMSG(
"Cannot open file!");
4943 while (fgets(line,
LEN, in))
4944 if (sscanf(line,
"%lg %lg", &(cache->
iso_ts[cache->
iso_n]),
4947 ERRMSG(
"Too many data points!");
4950 if (cache->
iso_n < 1)
4951 ERRMSG(
"Could not read any data!");
4974 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,met1,atm)") {
4987 atm->
p[ip] = cache->
iso_var[ip] * t;
4993 atm->
p[ip] = 1000. * pow(cache->
iso_var[ip] / t, -1. /
KAPPA);
4999 atm->
p[ip] = cache->
iso_ps[0];
5027 const int nvar = NVAR, nfix = NFIX, nreact = NREACT;
5028 double rtol[1] = { 1.0e-3 };
5029 double atol[1] = { 1.0 };
5033#pragma acc data copy(rtol,atol,nvar,nfix,nreact)
5036 "acc data present(ctl,cache,clim,met0,met1,atm) ") {
5039 double var[nvar], fix[nfix], rconst[nreact];
5040 for (
int i = 0; i < nvar; i++)
5042 for (
int i = 0; i < nfix; i++)
5044 for (
int i = 0; i < nreact; i++)
5046 kpp_chem_initialize(ctl, clim, met0, met1, atm, var, fix, rconst, ip);
5051 for (
int i = 0; i < 20; i++) {
5058 Rosenbrock(var, fix, rconst, 0, ctl->
dt_kpp,
5059 atol, rtol, &FunTemplate, &JacTemplate, rpar, ipar);
5062 kpp_chem_output2atm(atm, ctl, met0, met1, var, ip);
5083 ERRMSG(
"Need T_ice and T_NAT to calculate T_STS!");
5087 "acc data present(ctl,cache,clim,met0,met1,atm)") {
5089 double ps, ts, zs, us, vs, ess, nss, shf, lsm, sst, pbl, pt, pct, pcb,
5090 cl, plcl, plfc, pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot,
5091 o3, lwc, rwc, iwc, swc, cc, z, zt, eta_d = 0, wdot = 0;
5101 atm->
time[ip], atm->
p[ip], atm->
lon[ip],
5102 atm->
lat[ip], &eta_d, ci, cw, 1);
5109 atm->
time[ip], atm->
p[ip], atm->
lon[ip],
5110 atm->
lat[ip], &wdot, ci, cw, 1);
5151 const double lat_ref =
5156 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
5158 lat_ref, atm->
p[ip]));
5161 SET_ATM(qnt_vh, sqrt(u * u + v * v));
5187 atm->
lat[ip], atm->
p[ip])));
5205 const int np = atm->
np;
5206 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
5207 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
5208 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
5209 double *restrict
const mixparam =
5210 (
double *) malloc((
size_t) np *
sizeof(double));
5211 if (ixs == NULL || iys == NULL || izs == NULL || mixparam == NULL)
5212 ERRMSG(
"Out of memory!");
5220 const double t0 = t - 0.5 * ctl->
dt_mod;
5221 const double t1 = t + 0.5 * ctl->
dt_mod;
5226#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np],mixparam[0:np])
5227#pragma acc data present(ctl,clim,atm,ixs,iys,izs,mixparam)
5228#pragma acc parallel loop independent gang vector
5230#pragma omp parallel for default(shared)
5232 for (
int ip = 0; ip < np; ip++) {
5233 const double zpart =
Z(atm->
p[ip]);
5234 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
5239 || zpart < ctl->mixing_z0 || zpart >= ctl->
mixing_z1) {
5245 izs[ip] = (int) ((zpart - ctl->
mixing_z0) / dz);
5254 mixparam[ip] = -expm1(-dt_mix * rate);
5258 const int use_ensemble = (ctl->
nens > 0);
5260 const int quantities[] = {
5268 const int n_qnt =
sizeof(quantities) /
sizeof(quantities[0]);
5270 for (
int i = 0; i < n_qnt; i++)
5271 if (quantities[i] >= 0)
5277#pragma acc exit data delete(ixs,iys,izs,mixparam)
5293 const double *mixparam,
5295 const int use_ensemble) {
5297 const int np = atm->
np;
5299 const int nens = use_ensemble ? ctl->
nens : 1;
5300 const int total_grid = ngrid * nens;
5302 double *restrict
const cmean =
5303 (
double *) malloc((
size_t) total_grid *
sizeof(double));
5304 double *restrict
const cweight =
5305 (
double *) malloc((
size_t) total_grid *
sizeof(double));
5306 if (cmean == NULL || cweight == NULL)
5307 ERRMSG(
"Out of memory!");
5311#pragma acc enter data create(cmean[0:total_grid],cweight[0:total_grid])
5312#pragma acc data present(ctl,atm,ixs,iys,izs,mixparam,cmean,cweight)
5313#pragma acc parallel loop independent gang vector
5318#pragma omp parallel for
5320 for (
int i = 0; i < total_grid; i++) {
5327#pragma acc parallel loop independent gang vector
5329 for (
int ip = 0; ip < np; ip++)
5331 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
5332 if (ens < 0 || ens >= nens)
5338#pragma acc atomic update
5340 cmean[idx] += mixparam[ip] * atm->
q[qnt_idx][ip];
5342#pragma acc atomic update
5344 cweight[idx] += mixparam[ip];
5349#pragma acc parallel loop independent gang vector
5354#pragma omp parallel for
5356 for (
int i = 0; i < total_grid; i++)
5358 cmean[i] /= cweight[i];
5362#pragma acc parallel loop independent gang vector
5364#pragma omp parallel for
5366 for (
int ip = 0; ip < np; ip++) {
5368 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
5370 if (ens < 0 || ens >= nens)
5375 atm->
q[qnt_idx][ip] +=
5376 (cmean[idx] - atm->
q[qnt_idx][ip]) * mixparam[ip];
5382#pragma acc exit data delete(cmean,cweight)
5403 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
5406 const double a = 4.71572206e-08;
5407 const double b = -8.28782867e-01;
5408 const double low = pow(1. / a, 1. / b);
5412 "acc data present(ctl,cache,clim,met0,met1,atm)") {
5438 0 ? pow(298. / t, ctl->
oh_chem[1]) : 1.);
5441 0 ? pow(298. / t, ctl->
oh_chem[3]) : 1.);
5442 const double c = log10(k0 * M / ki);
5443 k = k0 * M / (1. + k0 * M / ki) * pow(0.6, 1. / (1. + c * c));
5452 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
5455 const double rate_coef =
5457 atm->
lat[ip], atm->
p[ip]) * M * cor;
5458 const double aux = exp(-cache->
dt[ip] * rate_coef);
5459 if (ctl->
qnt_m >= 0) {
5462 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
5463 atm->
q[ctl->
qnt_m][ip] *= aux;
5479 const int reflect) {
5485 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(cache,met0,met1,atm)") {
5497 while (atm->
lat[ip] < -90 || atm->
lat[ip] > 90) {
5498 if (atm->
lat[ip] > 90) {
5499 atm->
lat[ip] = 180 - atm->
lat[ip];
5500 atm->
lon[ip] += 180;
5502 if (atm->
lat[ip] < -90) {
5503 atm->
lat[ip] = -180 - atm->
lat[ip];
5504 atm->
lon[ip] += 180;
5509 while (atm->
lon[ip] < -180)
5510 atm->
lon[ip] += 360;
5511 while (atm->
lon[ip] >= 180)
5512 atm->
lon[ip] -= 360;
5515 atm->
lon[ip], atm->
lat[ip], &atm->
lon[ip],
5520 const double ptop = met0->
p[met0->
np - 1];
5521 if (atm->
p[ip] < ptop) {
5522 atm->
p[ip] = reflect ? ptop * ptop / atm->
p[ip] : ptop;
5523 }
else if (atm->
p[ip] > 300.) {
5525 if (atm->
p[ip] > ps)
5526 atm->
p[ip] = reflect ? ps * ps / atm->
p[ip] : ps;
5553 const double dt = cache->
dt[ip];
5557 atm->
q[ctl->
qnt_Apb210][ip] *= exp(-dt * lambda_pb210);
5562 const double aux = exp(-dt * lambda_rn222);
5563 const double lost = old * (1.0 - aux);
5568 atm->
q[ctl->
qnt_Apb210][ip] += lost * lambda_pb210 / lambda_rn222;
5573 atm->
q[ctl->
qnt_Abe7][ip] *= exp(-dt * lambda_be7);
5577 atm->
q[ctl->
qnt_Acs137][ip] *= exp(-dt * lambda_cs137);
5581 atm->
q[ctl->
qnt_Ai131][ip] *= exp(-dt * lambda_i131);
5585 atm->
q[ctl->
qnt_Axe133][ip] *= exp(-dt * lambda_xe133);
5614 "acc data present(ctl,cache,met0,met1,atm,depo)") {
5617 const double dt = cache->
dt[ip];
5627 double dry_pb210 = 0, dry_be7 = 0, dry_cs137 = 0, dry_i131 = 0;
5629 const double dz = 1000. * (
Z(ps - ctl->
dry_depo_dp) -
Z(ps));
5639 double wet_pb210 = 0, wet_be7 = 0, wet_cs137 = 0, wet_i131 = 0;
5642 if (isfinite(pct) && atm->
p[ip] > pct) {
5649 double lwc, rwc, iwc, swc, t;
5655 const int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
5680 const int ix = ingrid
5682 const int iy = ingrid
5690 const double aux = exp(-dt * (dry_pb210 + wet_pb210));
5691 const double lost = old * (1. - aux);
5692 const double deposited = lost
5693 * (ctl->
radio_decay ? exp(lambda_pb210 * tref) : 1.0);
5695 if (ingrid && lost > 0) {
5697#pragma acc atomic update
5699#pragma omp atomic update
5701 depo->
Apb210[idx] += deposited;
5707 const double old = atm->
q[ctl->
qnt_Abe7][ip];
5708 const double aux = exp(-dt * (dry_be7 + wet_be7));
5709 const double lost = old * (1. - aux);
5710 const double deposited = lost
5711 * (ctl->
radio_decay ? exp(lambda_be7 * tref) : 1.0);
5713 if (ingrid && lost > 0) {
5715#pragma acc atomic update
5717#pragma omp atomic update
5719 depo->
Abe7[idx] += deposited;
5726 const double aux = exp(-dt * (dry_cs137 + wet_cs137));
5727 const double lost = old * (1. - aux);
5728 const double deposited = lost
5729 * (ctl->
radio_decay ? exp(lambda_cs137 * tref) : 1.0);
5731 if (ingrid && lost > 0) {
5733#pragma acc atomic update
5735#pragma omp atomic update
5737 depo->
Acs137[idx] += deposited;
5743 const double old = atm->
q[ctl->
qnt_Ai131][ip];
5744 const double aux = exp(-dt * (dry_i131 + wet_i131));
5745 const double lost = old * (1. - aux);
5746 const double deposited = lost
5747 * (ctl->
radio_decay ? exp(lambda_i131 * tref) : 1.0);
5749 if (ingrid && lost > 0) {
5751#pragma acc atomic update
5753#pragma omp atomic update
5755 depo->
Ai131[idx] += deposited;
5767 gsl_rng_env_setup();
5768 if (omp_get_max_threads() >
NTHREADS)
5769 ERRMSG(
"Too many threads!");
5770 for (
int i = 0; i <
NTHREADS; i++) {
5771 rng[i] = gsl_rng_alloc(gsl_rng_default);
5772 gsl_rng_set(rng[i], gsl_rng_default_seed
5773 + (
long unsigned) (ntask *
NTHREADS + i));
5778 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
5779 CURAND_STATUS_SUCCESS)
5780 ERRMSG(
"Cannot create random number generator!");
5781 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
5782 CURAND_STATUS_SUCCESS)
5783 ERRMSG(
"Cannot set seed for random number generator!");
5786 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
5787 CURAND_STATUS_SUCCESS)
5788 ERRMSG(
"Cannot set stream for random number generator!");
5805#pragma omp parallel for default(shared)
5806 for (
size_t i = 0; i < n; ++i)
5807 rs[i] = gsl_rng_uniform(rng[omp_get_thread_num()]);
5811 else if (method == 1) {
5812#pragma omp parallel for default(shared)
5813 for (
size_t i = 0; i < n; ++i)
5814 rs[i] = gsl_ran_gaussian_ziggurat(rng[omp_get_thread_num()], 1.0);
5820#pragma acc update device(rs[:n])
5828 const uint64_t key = 0xc8e4fd154ce32f6d;
5832#pragma acc data present(rs)
5833#pragma acc parallel loop independent gang vector
5835#pragma omp parallel for default(shared)
5837 for (
size_t i = 0; i < n + 1; ++i) {
5838 uint64_t r, t, x, y, z;
5839 y = x = (rng_ctr + i) * key;
5842 x = (x >> 32) | (x << 32);
5844 x = (x >> 32) | (x << 32);
5846 x = (x >> 32) | (x << 32);
5848 x = (x >> 32) | (x << 32);
5849 r = t ^ ((x * x + y) >> 32);
5850 rs[i] = (double) r / (
double) UINT64_MAX;
5857#pragma acc parallel loop independent gang vector
5859#pragma omp parallel for default(shared)
5861 for (
size_t i = 0; i < n; i += 2) {
5862 const double r = sqrt(-2.0 * log(rs[i]));
5863 const double phi = 2.0 * M_PI * rs[i + 1];
5864 rs[i] = r * cosf((
float) phi);
5865 rs[i + 1] = r * sinf((
float) phi);
5873#pragma acc host_data use_device(rs)
5878 if (curandGenerateUniformDouble(rng_curand, rs, (n < 4 ? 4 : n)) !=
5879 CURAND_STATUS_SUCCESS)
5880 ERRMSG(
"Cannot create random numbers!");
5884 else if (method == 1) {
5885 if (curandGenerateNormalDouble
5886 (rng_curand, rs, (n < 4 ? 4 : n), 0.0,
5887 1.0) != CURAND_STATUS_SUCCESS)
5888 ERRMSG(
"Cannot create random numbers!");
5892 ERRMSG(
"MPTRAC was compiled without cuRAND!");
5909 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
5917 const double v_s =
sedi(atm->
p[ip], t, atm->
q[ctl->
qnt_rp][ip],
5921 atm->
p[ip] +=
DZ2DP(v_s * cache->
dt[ip] / 1000., atm->
p[ip]);
5936 const int np = atm->
np;
5937 double *restrict
const a = (
double *) malloc((
size_t) np *
sizeof(double));
5938 int *restrict
const p = (
int *) malloc((
size_t) np *
sizeof(int));
5939 if (a == NULL || p == NULL)
5940 ERRMSG(
"Out of memory!");
5943#pragma acc enter data create(a[0:np],p[0:np])
5944#pragma acc data present(ctl,met0,atm,a,p)
5949#pragma acc parallel loop independent gang vector
5951#pragma omp parallel for default(shared)
5953 for (
int ip = 0; ip < np; ip++) {
5964#pragma acc host_data use_device(a,p)
5966 thrustSortWrapper(a, np, p);
5968 size_t *perm_sz = (
size_t *) malloc((
size_t) np *
sizeof(size_t));
5969 if (perm_sz == NULL)
5970 ERRMSG(
"Out of memory!");
5972#pragma acc update self(a[0:np])
5974 gsl_sort_index(perm_sz, a, 1, (
size_t) np);
5975 for (
int ip = 0; ip < np; ++ip)
5976 p[ip] = (
int) perm_sz[ip];
5979#pragma acc update device(p[0:np])
5988 for (
int iq = 0; iq < ctl->
nq; iq++)
5993#pragma acc exit data delete(a,p)
6007 double *restrict
const help =
6008 (
double *) malloc((
size_t) np *
sizeof(double));
6010 ERRMSG(
"Out of memory!");
6014#pragma acc enter data create(help[0:np])
6015#pragma acc data present(a,p,help)
6016#pragma acc parallel loop independent gang vector
6018#pragma omp parallel for default(shared)
6020 for (
int ip = 0; ip < np; ip++)
6021 help[ip] = a[p[ip]];
6023#pragma acc parallel loop independent gang vector
6025#pragma omp parallel for default(shared)
6027 for (
int ip = 0; ip < np; ip++)
6032#pragma acc exit data delete(help)
6049 const double latmin = gsl_stats_min(met0->
lat, 1, (
size_t) met0->
ny),
6050 latmax = gsl_stats_max(met0->
lat, 1, (
size_t) met0->
ny);
6053 (fabs(met0->
lon[met0->
nx - 1] - met0->
lon[0] - 360.0) >= 0.01);
6056 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,atm)") {
6062 cache->
dt[ip] = t - atm->
time[ip];
6064 cache->
dt[ip] = 0.0;
6073 if (local && (atm->
lon[ip] <= met0->
lon[0]
6074 || atm->
lon[ip] >= met0->
lon[met0->
nx - 1]
6075 || atm->
lat[ip] <= latmin || atm->
lat[ip] >= latmax))
6076 cache->
dt[ip] = 0.0;
6095 ctl->
t_start = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
6097 ctl->
t_stop = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
6099 ctl->
t_start = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
6101 ctl->
t_stop = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
6106 ERRMSG(
"Nothing to do! Check T_STOP and DIRECTION!");
6126 ERRMSG(
"Only lat/lon grid supported");
6133 "acc data present(ctl,cache,clim,met0,met1,atm)") {
6157 const double K_o1d =
6160 atm->
p[ip], sza, o3c);
6161 atm->
q[ctl->
qnt_Cccl4][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
6166 const double K_o1d =
6169 atm->
p[ip], sza, o3c);
6170 atm->
q[ctl->
qnt_Cccl3f][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
6175 const double K_o1d =
6178 atm->
p[ip], sza, o3c);
6179 atm->
q[ctl->
qnt_Cccl2f2][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
6184 const double K_o1d =
6187 atm->
p[ip], sza, o3c);
6188 atm->
q[ctl->
qnt_Cn2o][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
6207 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
6210 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
6216 if (!isfinite(pct) || atm->
p[ip] <= pct)
6232 double lwc, rwc, iwc, swc;
6237 const int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
6277 h *= (1. + K_1 / H_ion + K_1 * K_2 /
SQR(H_ion));
6281 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
6284 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
6310 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
6313 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
6318 const double aux = exp(-cache->
dt[ip] * lambda);
6319 if (ctl->
qnt_m >= 0) {
6322 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
6323 atm->
q[ctl->
qnt_m][ip] *= aux;
6346 if (ctl != NULL || cache != NULL || clim != NULL || met0 != NULL
6347 || met1 != NULL || atm != NULL || depo != NULL || dd != NULL) {
6349 if (acc_get_num_devices(acc_device_nvidia) <= 0)
6350 ERRMSG(
"Not running on a GPU device!");
6351 acc_device_t device_type = acc_get_device_type();
6352 acc_init(device_type);
6379 ctl_t *ctlup = *ctl;
6380#pragma acc enter data create(ctlup[:1])
6382 if (cache != NULL) {
6384#pragma acc enter data create(cacheup[:1])
6388#pragma acc enter data create(climup[:1])
6391 met_t *met0up = *met0;
6392#pragma acc enter data create(met0up[:1])
6395 met_t *met1up = *met1;
6396#pragma acc enter data create(met1up[:1])
6399 atm_t *atmup = *atm;
6400#pragma acc enter data create(atmup[:1])
6404#pragma acc enter data create(depoup[:1])
6409#pragma acc enter data create(ddup[:1])
6431#pragma acc exit data delete(ctl[:1])
6433 if (cache != NULL) {
6434#pragma acc exit data delete(cache[:1])
6437#pragma acc exit data delete(clim[:1])
6440#pragma acc exit data delete(met0[:1])
6443#pragma acc exit data delete(met1[:1])
6446#pragma acc exit data delete(atm[:1])
6449#pragma acc exit data delete(depo[:1])
6453#pragma acc exit data delete(dd[:1])
6471 MPI_Type_free(&dd->MPI_Particle);
6490 char cachefile[
LEN], cmd[2 *
LEN], filename[
LEN];
6496 if (t == ctl->
t_start || !init) {
6503 ERRMSG(
"Cannot open file!");
6508 ERRMSG(
"Cannot open file!");
6518 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
6519 LOG(1,
"Caching: %s", cachefile);
6520 if (system(cmd) != 0)
6521 WARN(
"Caching command failed!");
6526 if (t > (*met1)->time) {
6536 ERRMSG(
"Cannot open file!");
6546 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
6547 LOG(1,
"Caching: %s", cachefile);
6548 if (system(cmd) != 0)
6549 WARN(
"Caching command failed!");
6554 if (t < (*met0)->time) {
6564 ERRMSG(
"Cannot open file!");
6574 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
6575 LOG(1,
"Caching: %s", cachefile);
6576 if (system(cmd) != 0)
6577 WARN(
"Caching command failed!");
6581 if ((*met0)->coord_type != (*met1)->coord_type)
6582 ERRMSG(
"Coordinate types do not match!");
6585 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
6586 if ((*met0)->nx != (*met1)->nx
6587 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
6588 ERRMSG(
"Meteo grid dimensions do not match!");
6589 for (
int ix = 0; ix < (*met0)->nx; ix++)
6590 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
6591 ERRMSG(
"Meteo grid longitudes do not match!");
6592 for (
int iy = 0; iy < (*met0)->ny; iy++)
6593 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
6594 ERRMSG(
"Meteo grid latitudes do not match!");
6595 for (
int ip = 0; ip < (*met0)->np; ip++)
6596 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
6597 ERRMSG(
"Meteo grid pressure levels do not match!");
6620#pragma acc update device(depo[:1])
6629 const char *filename,
6642 LOG(1,
"Read atmospheric data: %s", filename);
6662 ERRMSG(
"Atmospheric data type not supported!");
6670 ERRMSG(
"Can not read any data!");
6674 LOG(2,
"Number of particles: %d", atm->
np);
6675 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
6676 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
6677 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
6678 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
6679 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
6680 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
6681 LOG(2,
"%s range: %g ... %g %s",
6682 ctl->
met_coord_type == 0 ?
"Longitude" :
"X coordinate", mini, maxi,
6684 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
6685 LOG(2,
"%s range: %g ... %g %s",
6686 ctl->
met_coord_type == 0 ?
"Latitude" :
"Y coordinate", mini, maxi,
6688 for (
int iq = 0; iq < ctl->
nq; iq++) {
6690 sprintf(msg,
"Quantity %s range: %s ... %s %s",
6693 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
6694 LOG(2, msg, mini, maxi);
6764 const char *filename,
6773 LOG(1,
"\nMassive-Parallel Trajectory Calculations (MPTRAC)\n"
6774 "(executable: %s | version: %s | compiled: %s, %s)\n",
6775 argv[0], VERSION, __DATE__, __TIME__);
6883 ctl->
nq = (int)
scan_ctl(filename, argc, argv,
"NQ", -1,
"0", NULL);
6885 ERRMSG(
"Too many quantities!");
6886 for (
int iq = 0; iq < ctl->
nq; iq++) {
6892 scan_ctl(filename, argc, argv,
"QNT_FORMAT", iq,
"%g",
6894 if (strcasecmp(ctl->
qnt_name[iq],
"aoa") == 0)
6898 SET_QNT(qnt_idx,
"idx",
"particle index",
"-")
6899 SET_QNT(qnt_ens,
"ens",
"ensemble index",
"-")
6900 SET_QNT(qnt_stat,
"stat",
"station flag",
"-")
6901 SET_QNT(qnt_m,
"m",
"mass",
"kg")
6902 SET_QNT(qnt_vmr,
"vmr",
"volume mixing ratio",
"ppv")
6903 SET_QNT(qnt_rp,
"rp",
"particle radius",
"microns")
6904 SET_QNT(qnt_rhop,
"rhop",
"particle density",
"kg/m^3")
6905 SET_QNT(qnt_ps,
"ps",
"surface pressure",
"hPa")
6906 SET_QNT(qnt_ts,
"ts",
"surface temperature",
"K")
6907 SET_QNT(qnt_zs,
"zs",
"surface height",
"km")
6908 SET_QNT(qnt_us,
"us",
"surface zonal wind",
"m/s")
6909 SET_QNT(qnt_vs,
"vs",
"surface meridional wind",
"m/s")
6910 SET_QNT(qnt_ess,
"ess",
"eastward turbulent surface stress",
"N/m^2")
6911 SET_QNT(qnt_nss,
"nss",
"northward turbulent surface stress",
"N/m^2")
6912 SET_QNT(qnt_shf,
"shf",
"surface sensible heat flux",
"W/m^2")
6913 SET_QNT(qnt_lsm,
"lsm",
"land-sea mask",
"1")
6914 SET_QNT(qnt_sst,
"sst",
"sea surface temperature",
"K")
6915 SET_QNT(qnt_pbl,
"pbl",
"planetary boundary layer",
"hPa")
6916 SET_QNT(qnt_pt,
"pt",
"tropopause pressure",
"hPa")
6917 SET_QNT(qnt_tt,
"tt",
"tropopause temperature",
"K")
6918 SET_QNT(qnt_zt,
"zt",
"tropopause geopotential height",
"km")
6919 SET_QNT(qnt_h2ot,
"h2ot",
"tropopause water vapor",
"ppv")
6920 SET_QNT(qnt_zg,
"zg",
"geopotential height",
"km")
6921 SET_QNT(qnt_p,
"p",
"pressure",
"hPa")
6922 SET_QNT(qnt_t,
"t",
"temperature",
"K")
6923 SET_QNT(qnt_rho,
"rho",
"air density",
"kg/m^3")
6924 SET_QNT(qnt_u,
"u",
"zonal wind",
"m/s")
6925 SET_QNT(qnt_v,
"v",
"meridional wind",
"m/s")
6926 SET_QNT(qnt_w,
"w",
"vertical velocity",
"hPa/s")
6927 SET_QNT(qnt_h2o,
"h2o",
"water vapor",
"ppv")
6928 SET_QNT(qnt_o3,
"o3",
"ozone",
"ppv")
6929 SET_QNT(qnt_lwc,
"lwc",
"cloud liquid water content",
"kg/kg")
6930 SET_QNT(qnt_rwc,
"rwc",
"cloud rain water content",
"kg/kg")
6931 SET_QNT(qnt_iwc,
"iwc",
"cloud ice water content",
"kg/kg")
6932 SET_QNT(qnt_swc,
"swc",
"cloud snow water content",
"kg/kg")
6933 SET_QNT(qnt_cc,
"cc",
"cloud cover",
"1")
6934 SET_QNT(qnt_pct,
"pct",
"cloud top pressure",
"hPa")
6935 SET_QNT(qnt_pcb,
"pcb",
"cloud bottom pressure",
"hPa")
6936 SET_QNT(qnt_cl,
"cl",
"total column cloud water",
"kg/m^2")
6937 SET_QNT(qnt_plcl,
"plcl",
"lifted condensation level",
"hPa")
6938 SET_QNT(qnt_plfc,
"plfc",
"level of free convection",
"hPa")
6939 SET_QNT(qnt_pel,
"pel",
"equilibrium level",
"hPa")
6940 SET_QNT(qnt_cape,
"cape",
"convective available potential energy",
6942 SET_QNT(qnt_cin,
"cin",
"convective inhibition",
"J/kg")
6943 SET_QNT(qnt_o3c,
"o3c",
"total column ozone",
"DU")
6944 SET_QNT(qnt_hno3,
"hno3",
"nitric acid",
"ppv")
6945 SET_QNT(qnt_oh,
"oh",
"hydroxyl radical",
"ppv")
6946 SET_QNT(qnt_h2o2,
"h2o2",
"hydrogen peroxide",
"ppv")
6947 SET_QNT(qnt_ho2,
"ho2",
"hydroperoxyl radical",
"ppv")
6948 SET_QNT(qnt_o1d,
"o1d",
"atomic oxygen",
"ppv")
6949 SET_QNT(qnt_mloss_oh,
"mloss_oh",
"mass loss due to OH chemistry",
"kg")
6950 SET_QNT(qnt_mloss_h2o2,
"mloss_h2o2",
6951 "mass loss due to H2O2 chemistry",
"kg")
6952 SET_QNT(qnt_mloss_kpp,
"mloss_kpp",
"mass loss due to kpp chemistry",
6954 SET_QNT(qnt_mloss_wet,
"mloss_wet",
"mass loss due to wet deposition",
6956 SET_QNT(qnt_mloss_dry,
"mloss_dry",
"mass loss due to dry deposition",
6958 SET_QNT(qnt_mloss_decay,
"mloss_decay",
6959 "mass loss due to exponential decay",
"kg")
6960 SET_QNT(qnt_loss_rate,
"loss_rate",
"total loss rate",
"s^-1")
6961 SET_QNT(qnt_psat,
"psat",
"saturation pressure over water",
"hPa")
6962 SET_QNT(qnt_psice,
"psice",
"saturation pressure over ice",
"hPa")
6963 SET_QNT(qnt_pw,
"pw",
"partial water vapor pressure",
"hPa")
6964 SET_QNT(qnt_sh,
"sh",
"specific humidity",
"kg/kg")
6965 SET_QNT(qnt_rh,
"rh",
"relative humidity",
"%%")
6966 SET_QNT(qnt_rhice,
"rhice",
"relative humidity over ice",
"%%")
6967 SET_QNT(qnt_theta,
"theta",
"potential temperature",
"K")
6968 SET_QNT(qnt_zeta,
"zeta",
"zeta coordinate",
"K")
6969 SET_QNT(qnt_zeta_d,
"zeta_d",
"diagnosed zeta coordinate",
"K")
6970 SET_QNT(qnt_zeta_dot,
"zeta_dot",
"velocity of zeta coordinate",
6972 SET_QNT(qnt_eta,
"eta",
"eta coordinate",
"1")
6973 SET_QNT(qnt_eta_d,
"eta_d",
"diagnosed eta coordinate",
"1")
6974 SET_QNT(qnt_eta_dot,
"eta_dot",
"velocity of eta coordinate",
"1/s")
6975 SET_QNT(qnt_tvirt,
"tvirt",
"virtual temperature",
"K")
6976 SET_QNT(qnt_lapse,
"lapse",
"temperature lapse rate",
"K/km")
6977 SET_QNT(qnt_vh,
"vh",
"horizontal velocity",
"m/s")
6978 SET_QNT(qnt_vz,
"vz",
"vertical velocity",
"m/s")
6979 SET_QNT(qnt_pv,
"pv",
"potential vorticity",
"PVU")
6980 SET_QNT(qnt_tdew,
"tdew",
"dew point temperature",
"K")
6981 SET_QNT(qnt_tice,
"tice",
"frost point temperature",
"K")
6982 SET_QNT(qnt_tsts,
"tsts",
"STS existence temperature",
"K")
6983 SET_QNT(qnt_tnat,
"tnat",
"NAT existence temperature",
"K")
6984 SET_QNT(qnt_Cx,
"Cx",
"Trace species x volume mixing ratio",
"ppv")
6985 SET_QNT(qnt_Ch2o,
"Ch2o",
"H2O volume mixing ratio",
"ppv")
6986 SET_QNT(qnt_Co3,
"Co3",
"O3 volume mixing ratio",
"ppv")
6987 SET_QNT(qnt_Cco,
"Cco",
"CO volume mixing ratio",
"ppv")
6988 SET_QNT(qnt_Coh,
"Coh",
"HO volume mixing ratio",
"ppv")
6989 SET_QNT(qnt_Ch,
"Ch",
"H radical volume mixing ratio",
"ppv")
6990 SET_QNT(qnt_Cho2,
"Cho2",
"HO2 volume mixing ratio",
"ppv")
6991 SET_QNT(qnt_Ch2o2,
"Ch2o2",
"H2O2 volume mixing ratio",
"ppv")
6992 SET_QNT(qnt_Co1d,
"Co1d",
"O(1D) volume mixing ratio",
"ppv")
6993 SET_QNT(qnt_Co3p,
"Co3p",
"O(3P) radical volume mixing ratio",
"ppv")
6994 SET_QNT(qnt_Cccl4,
"Cccl4",
"CCl4 (CFC-10) volume mixing ratio",
"ppv")
6995 SET_QNT(qnt_Cccl3f,
"Cccl3f",
"CCl3F (CFC-11) volume mixing ratio",
6997 SET_QNT(qnt_Cccl2f2,
"Cccl2f2",
"CCl2F2 (CFC-12) volume mixing ratio",
6999 SET_QNT(qnt_Cn2o,
"Cn2o",
"N2O volume mixing ratio",
"ppv")
7000 SET_QNT(qnt_Csf6,
"Csf6",
"SF6 volume mixing ratio",
"ppv")
7001 SET_QNT(qnt_aoa,
"aoa",
"age of air",
"s")
7002 SET_QNT(qnt_Arn222,
"Arn222",
"Rn-222 activity",
"Bq")
7003 SET_QNT(qnt_Apb210,
"Apb210",
"Pb-210 activity",
"Bq")
7004 SET_QNT(qnt_Abe7,
"Abe7",
"Be-7 activity",
"Bq")
7005 SET_QNT(qnt_Acs137,
"Acs137",
"Cs-137 activity",
"Bq")
7006 SET_QNT(qnt_Ai131,
"Ai131",
"I-131 activity",
"Bq")
7007 SET_QNT(qnt_Axe133,
"Axe133",
"Xe-133 activity",
"Bq")
7008 SET_QNT(qnt_current_subdomain,
"current_subdomain",
7009 "current subdomain rank",
"-")
7010 SET_QNT(qnt_target_subdomain,
"target_subdomain",
7011 "target subdomain rank",
"-")
7016 (int)
scan_ctl(filename, argc, argv,
"MET_COORD_TYPE", -1,
"0", NULL);
7018 ERRMSG(
"MET_COORD_TYPE must be 0 or 1!");
7023 scan_ctl(filename, argc, argv,
"MET_UTM_REF_LAT", -1,
"", NULL);
7025 scan_ctl(filename, argc, argv,
"MET_UTM_REF_LON", -1,
"", NULL);
7030 (int)
scan_ctl(filename, argc, argv,
"ADVECT_VERT_COORD", -1,
"0", NULL);
7032 ERRMSG(
"ADVECT_VERT_COORD must be 0, 1, 2, or 3!");
7035 ERRMSG(
"Add quantity zeta for diabatic advection!");
7037 ERRMSG(
"Add quantity eta for etadot avection!");
7040 (int)
scan_ctl(filename, argc, argv,
"MET_VERT_COORD", -1,
"0", NULL);
7042 ERRMSG(
"MET_VERT_COORD must be 0, 1, 2, 3, or 4!");
7045 ERRMSG(
"Quantity eta_d requires full-level A and B coefficients!");
7049 (
"Using ADVECT_VERT_COORD = 2 requires meteo data on model levels!");
7052 (
"Using ADVECT_VERT_COORD = 3 requires A and B model level coefficients!");
7055 (int)
scan_ctl(filename, argc, argv,
"MET_GP2Z", -1,
"0", NULL);
7057 ERRMSG(
"Set MET_GP2Z to 0 or 1!");
7061 (int)
scan_ctl(filename, argc, argv,
"DIRECTION", -1,
"1", NULL);
7063 ERRMSG(
"Set DIRECTION to -1 or 1!");
7064 ctl->
t_stop =
scan_ctl(filename, argc, argv,
"T_STOP", -1,
"1e100", NULL);
7065 ctl->
dt_mod =
scan_ctl(filename, argc, argv,
"DT_MOD", -1,
"180", NULL);
7069 ctl->
dt_met =
scan_ctl(filename, argc, argv,
"DT_MET", -1,
"3600", NULL);
7071 ERRMSG(
"DT_MOD must not exceed DT_MET!");
7073 (int)
scan_ctl(filename, argc, argv,
"MET_CONVENTION", -1,
"0", NULL);
7075 (int)
scan_ctl(filename, argc, argv,
"MET_TYPE", -1,
"0", NULL);
7078 (
"Please use meteo files in netcdf format for diabatic calculations.");
7081 (
"Please use meteo files in netcdf format for etadot calculations.");
7083 (int)
scan_ctl(filename, argc, argv,
"MET_CLAMS", -1,
"0", NULL);
7085 (int)
scan_ctl(filename, argc, argv,
"MET_NC_SCALE", -1,
"1", NULL);
7087 (int)
scan_ctl(filename, argc, argv,
"MET_NC_LEVEL", -1,
"0", NULL);
7089 (int)
scan_ctl(filename, argc, argv,
"MET_NC_QUANT", -1,
"0", NULL);
7091 (int)
scan_ctl(filename, argc, argv,
"MET_ZSTD_LEVEL", -1,
"-3", NULL);
7093 (int)
scan_ctl(filename, argc, argv,
"MET_ZSTD_NWORKERS", -1,
"4", NULL);
7095 (int)
scan_ctl(filename, argc, argv,
"MET_LZ4_ACCEL", -1,
"8", NULL);
7097 (int)
scan_ctl(filename, argc, argv,
"MET_PCK_ZSTD", -1,
"0", NULL);
7099 ERRMSG(
"Set MET_PCK_ZSTD to 0 or 1!");
7102 ERRMSG(
"MET_PCK_ZSTD requires MPTRAC to be compiled with ZSTD support!");
7104 const int def_lossy_scale =
7105 (int)
scan_ctl(filename, argc, argv,
"MET_LOSSY_SCALE", -1,
"0", NULL);
7106 for (
int i = 0; i <
METVAR; i++) {
7107 char defprec_zfp[
LEN] =
"7", deftol_zfp[
LEN] =
"0.0";
7108 char defprec_sz3[
LEN] =
"6", deftol_sz3[
LEN] =
"0.0";
7110 sprintf(defprec_zfp,
"12");
7111 sprintf(defprec_sz3,
"11");
7112 }
else if (i == 1) {
7113 sprintf(defprec_zfp,
"11");
7114 sprintf(defprec_sz3,
"7");
7115 }
else if (i == 2 || i == 3) {
7116 sprintf(defprec_zfp,
"7");
7117 sprintf(defprec_sz3,
"7");
7118 }
else if (i == 4) {
7119 sprintf(defprec_zfp,
"6");
7120 sprintf(defprec_sz3,
"13");
7121 }
else if (i == 5) {
7122 sprintf(defprec_zfp,
"7");
7123 sprintf(defprec_sz3,
"20");
7124 }
else if (i == 6) {
7125 sprintf(defprec_zfp,
"10");
7126 sprintf(defprec_sz3,
"18");
7127 }
else if (i == 7) {
7128 sprintf(defprec_zfp,
"9");
7129 sprintf(defprec_sz3,
"10");
7130 }
else if (i >= 8 && i <= 11) {
7131 sprintf(defprec_zfp,
"6");
7132 sprintf(defprec_sz3,
"13");
7133 }
else if (i == 12) {
7134 sprintf(defprec_zfp,
"9");
7135 sprintf(defprec_sz3,
"6");
7138 (int)
scan_ctl(filename, argc, argv,
"MET_ZFP_PREC", i, defprec_zfp,
7141 scan_ctl(filename, argc, argv,
"MET_ZFP_TOL", i, deftol_zfp, NULL);
7143 (int)
scan_ctl(filename, argc, argv,
"MET_SZ3_PREC", i, defprec_sz3,
7146 scan_ctl(filename, argc, argv,
"MET_SZ3_TOL", i, deftol_sz3, NULL);
7148 snprintf(defscale,
LEN,
"%d", def_lossy_scale);
7150 (int)
scan_ctl(filename, argc, argv,
"MET_LOSSY_SCALE", i, defscale,
7153 ERRMSG(
"Set MET_LOSSY_SCALE to 0 or 1!");
7157 scan_ctl(filename, argc, argv,
"MET_COMP_LOGFILE", -1,
"-",
7160 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_BATCH", -1,
"-1", NULL);
7162 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ZSTD", -1,
"1", NULL);
7164 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ND0X", -1,
"48", NULL);
7166 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ND0Y", -1,
"24", NULL);
7168 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_MAXLEV", -1,
"6", NULL);
7169 for (
int i = 0; i <
METVAR; i++) {
7170 char defeps[
LEN] =
"1.0";
7171 if (i == 1 || i == 2 || i == 3)
7172 sprintf(defeps,
"0.05");
7174 scan_ctl(filename, argc, argv,
"MET_CMS_EPS", i, defeps, NULL);
7176 ctl->
met_dx = (int)
scan_ctl(filename, argc, argv,
"MET_DX", -1,
"1", NULL);
7177 ctl->
met_dy = (int)
scan_ctl(filename, argc, argv,
"MET_DY", -1,
"1", NULL);
7178 ctl->
met_dp = (int)
scan_ctl(filename, argc, argv,
"MET_DP", -1,
"1", NULL);
7180 ERRMSG(
"MET_DX, MET_DY, and MET_DP need to be greater than zero!");
7181 ctl->
met_sx = (int)
scan_ctl(filename, argc, argv,
"MET_SX", -1,
"1", NULL);
7182 ctl->
met_sy = (int)
scan_ctl(filename, argc, argv,
"MET_SY", -1,
"1", NULL);
7183 ctl->
met_sp = (int)
scan_ctl(filename, argc, argv,
"MET_SP", -1,
"1", NULL);
7185 ERRMSG(
"MET_SX, MET_SY, and MET_SP need to be greater than zero!");
7187 scan_ctl(filename, argc, argv,
"MET_DETREND", -1,
"-999", NULL);
7188 ctl->
met_np = (int)
scan_ctl(filename, argc, argv,
"MET_NP", -1,
"0", NULL);
7190 ERRMSG(
"Too many pressure levels!");
7192 (int)
scan_ctl(filename, argc, argv,
"MET_PRESS_LEVEL_DEF", -1,
"-1",
7198 for (
int ip = 0; ip < ctl->
met_np; ip++)
7200 scan_ctl(filename, argc, argv,
"MET_P", ip,
"", NULL);
7204 (int)
scan_ctl(filename, argc, argv,
"MET_NLEV", -1,
"0", NULL);
7206 ERRMSG(
"Too many model levels!");
7207 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
7209 scan_ctl(filename, argc, argv,
"MET_LEV_HYAM", ip,
"", NULL);
7210 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
7212 scan_ctl(filename, argc, argv,
"MET_LEV_HYBM", ip,
"", NULL);
7214 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SX", -1,
"-1", NULL);
7216 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SY", -1,
"-1", NULL);
7218 (int)
scan_ctl(filename, argc, argv,
"MET_RELHUM", -1,
"0", NULL);
7220 (int)
scan_ctl(filename, argc, argv,
"MET_CAPE", -1,
"1", NULL);
7222 ERRMSG(
"Set MET_CAPE to 0 or 1!");
7224 (int)
scan_ctl(filename, argc, argv,
"MET_PBL", -1,
"3", NULL);
7226 ERRMSG(
"Set MET_PBL to 0 ... 3!");
7228 scan_ctl(filename, argc, argv,
"MET_PBL_MIN", -1,
"0.1", NULL);
7230 scan_ctl(filename, argc, argv,
"MET_PBL_MAX", -1,
"5.0", NULL);
7232 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO", -1,
"3", NULL);
7234 ERRMSG(
"Set MET_TROPO to 0 ... 5!");
7236 scan_ctl(filename, argc, argv,
"MET_TROPO_PV", -1,
"3.5", NULL);
7238 scan_ctl(filename, argc, argv,
"MET_TROPO_THETA", -1,
"380", NULL);
7240 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO_SPLINE", -1,
"1", NULL);
7242 scan_ctl(filename, argc, argv,
"MET_DT_OUT", -1,
"0.1", NULL);
7244 (int)
scan_ctl(filename, argc, argv,
"MET_CACHE", -1,
"0", NULL);
7246 (int)
scan_ctl(filename, argc, argv,
"MET_MPI_SHARE", -1,
"0", NULL);
7249 ctl->
sort_dt =
scan_ctl(filename, argc, argv,
"SORT_DT", -1,
"-999", NULL);
7253 (int)
scan_ctl(filename, argc, argv,
"ISOSURF", -1,
"0", NULL);
7258 (int)
scan_ctl(filename, argc, argv,
"RNG_TYPE", -1,
"1", NULL);
7260 ERRMSG(
"Set RNG_TYPE to 0, 1, or 2!");
7263 ctl->
advect = (int)
scan_ctl(filename, argc, argv,
"ADVECT", -1,
"2", NULL);
7265 ERRMSG(
"Set ADVECT to 1, 2, or 4!");
7269 = (int)
scan_ctl(filename, argc, argv,
"DIFFUSION", -1,
"0", NULL);
7271 ERRMSG(
"Set DIFFUSION to 0 or 1!");
7273 (int)
scan_ctl(filename, argc, argv,
"TURB_PBL_SCHEME", -1,
"0", NULL);
7275 ERRMSG(
"Set TURB_PBL_SCHEME to 0 or 1!");
7277 scan_ctl(filename, argc, argv,
"TURB_DX_PBL", -1,
"50", NULL);
7279 scan_ctl(filename, argc, argv,
"TURB_DX_TROP", -1,
"50", NULL);
7281 scan_ctl(filename, argc, argv,
"TURB_DX_STRAT", -1,
"0", NULL);
7283 scan_ctl(filename, argc, argv,
"TURB_DZ_PBL", -1,
"0", NULL);
7285 scan_ctl(filename, argc, argv,
"TURB_DZ_TROP", -1,
"0", NULL);
7287 scan_ctl(filename, argc, argv,
"TURB_DZ_STRAT", -1,
"0.1", NULL);
7289 scan_ctl(filename, argc, argv,
"TURB_MESOX", -1,
"0.16", NULL);
7291 scan_ctl(filename, argc, argv,
"TURB_MESOZ", -1,
"0.16", NULL);
7293 scan_ctl(filename, argc, argv,
"TURB_PBL_TRANS", -1,
"0", NULL);
7295 ERRMSG(
"TURB_PBL_TRANS must be in the range [0, 1]!");
7299 = (int)
scan_ctl(filename, argc, argv,
"CONV_MIX_PBL", -1,
"0", NULL);
7301 =
scan_ctl(filename, argc, argv,
"CONV_PBL_TRANS", -1,
"0", NULL);
7303 ERRMSG(
"CONV_PBL_TRANS must be in the range [0, 1]!");
7305 =
scan_ctl(filename, argc, argv,
"CONV_CAPE", -1,
"-999", NULL);
7307 =
scan_ctl(filename, argc, argv,
"CONV_CIN", -1,
"-999", NULL);
7308 ctl->
conv_dt =
scan_ctl(filename, argc, argv,
"CONV_DT", -1,
"-999", NULL);
7312 scan_ctl(filename, argc, argv,
"BOUND_MASS", -1,
"-999", NULL);
7314 scan_ctl(filename, argc, argv,
"BOUND_MASS_TREND", -1,
"0", NULL);
7316 scan_ctl(filename, argc, argv,
"BOUND_VMR", -1,
"-999", NULL);
7318 scan_ctl(filename, argc, argv,
"BOUND_VMR_TREND", -1,
"0", NULL);
7320 scan_ctl(filename, argc, argv,
"BOUND_LAT0", -1,
"-999", NULL);
7322 scan_ctl(filename, argc, argv,
"BOUND_LAT1", -1,
"-999", NULL);
7324 scan_ctl(filename, argc, argv,
"BOUND_P0", -1,
"-999", NULL);
7326 scan_ctl(filename, argc, argv,
"BOUND_P1", -1,
"-999", NULL);
7328 scan_ctl(filename, argc, argv,
"BOUND_DPS", -1,
"-999", NULL);
7330 scan_ctl(filename, argc, argv,
"BOUND_DZS", -1,
"-999", NULL);
7332 scan_ctl(filename, argc, argv,
"BOUND_ZETAS", -1,
"-999", NULL);
7334 (int)
scan_ctl(filename, argc, argv,
"BOUND_PBL", -1,
"0", NULL);
7338 if (strcasecmp(ctl->
species,
"CF2Cl2") == 0) {
7342 }
else if (strcasecmp(ctl->
species,
"CFCl3") == 0) {
7346 }
else if (strcasecmp(ctl->
species,
"CH4") == 0) {
7353 }
else if (strcasecmp(ctl->
species,
"CO") == 0) {
7362 }
else if (strcasecmp(ctl->
species,
"CO2") == 0) {
7366 }
else if (strcasecmp(ctl->
species,
"H2O") == 0) {
7368 }
else if (strcasecmp(ctl->
species,
"N2O") == 0) {
7372 }
else if (strcasecmp(ctl->
species,
"NH3") == 0) {
7379 }
else if (strcasecmp(ctl->
species,
"HNO3") == 0) {
7383 }
else if (strcasecmp(ctl->
species,
"NO") == 0) {
7392 }
else if (strcasecmp(ctl->
species,
"NO2") == 0) {
7401 }
else if (strcasecmp(ctl->
species,
"O3") == 0) {
7408 }
else if (strcasecmp(ctl->
species,
"SF6") == 0) {
7412 }
else if (strcasecmp(ctl->
species,
"SO2") == 0) {
7425 sprintf(defstr,
"%g", ctl->
molmass);
7426 ctl->
molmass =
scan_ctl(filename, argc, argv,
"MOLMASS", -1, defstr, NULL);
7431 (int)
scan_ctl(filename, argc, argv,
"OH_CHEM_REACTION", -1, defstr,
7433 for (
int ip = 0; ip < 4; ip++) {
7434 sprintf(defstr,
"%g", ctl->
oh_chem[ip]);
7436 scan_ctl(filename, argc, argv,
"OH_CHEM", ip, defstr, NULL);
7439 scan_ctl(filename, argc, argv,
"OH_CHEM_BETA", -1,
"0", NULL);
7443 (int)
scan_ctl(filename, argc, argv,
"H2O2_CHEM_REACTION", -1,
"0", NULL);
7447 (int)
scan_ctl(filename, argc, argv,
"KPP_CHEM", -1,
"0", NULL);
7448 ctl->
dt_kpp =
scan_ctl(filename, argc, argv,
"DT_KPP", -1,
"1800", NULL);
7452 (int)
scan_ctl(filename, argc, argv,
"TRACER_CHEM", -1,
"0", NULL);
7456 (int)
scan_ctl(filename, argc, argv,
"RADIO_DECAY", -1,
"0", NULL);
7458 (int)
scan_ctl(filename, argc, argv,
"RADIO_DEPO", -1,
"0", NULL);
7460 ERRMSG(
"Radioactive deposition requires a lat/lon meteorological grid!");
7464 (
"Radioactive deposition is not supported with domain decomposition!");
7468 for (
int ip = 0; ip < 2; ip++) {
7471 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_H", ip, defstr, NULL);
7473 for (
int ip = 0; ip < 1; ip++) {
7476 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_H", ip, defstr, NULL);
7479 scan_ctl(filename, argc, argv,
"WET_DEPO_SO2_PH", -1,
"0", NULL);
7481 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_A", -1,
"0", NULL);
7483 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_B", -1,
"0", NULL);
7485 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_A", -1,
"0", NULL);
7487 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_B", -1,
"0", NULL);
7489 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 0,
"0.5", NULL);
7491 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 1,
"0.36", NULL);
7493 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_RET_RATIO", -1,
"1", NULL);
7495 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_RET_RATIO", -1,
"1", NULL);
7499 scan_ctl(filename, argc, argv,
"DRY_DEPO_VDEP", -1,
"0", NULL);
7501 scan_ctl(filename, argc, argv,
"DRY_DEPO_DP", -1,
"30", NULL);
7504 scan_ctl(filename, argc, argv,
"CLIM_PHOTO", -1,
7505 "../../data/clams_photolysis_rates.nc", ctl->
clim_photo);
7506 scan_ctl(filename, argc, argv,
"CLIM_HNO3_FILENAME", -1,
7508 scan_ctl(filename, argc, argv,
"CLIM_OH_FILENAME", -1,
7510 scan_ctl(filename, argc, argv,
"CLIM_H2O2_FILENAME", -1,
7512 scan_ctl(filename, argc, argv,
"CLIM_HO2_FILENAME", -1,
7514 scan_ctl(filename, argc, argv,
"CLIM_O1D_FILENAME", -1,
7516 scan_ctl(filename, argc, argv,
"CLIM_CCL4_TIMESERIES", -1,
7518 scan_ctl(filename, argc, argv,
"CLIM_CCL3F_TIMESERIES", -1,
7520 scan_ctl(filename, argc, argv,
"CLIM_CCL2F2_TIMESERIES", -1,
7522 scan_ctl(filename, argc, argv,
"CLIM_N2O_TIMESERIES", -1,
7524 scan_ctl(filename, argc, argv,
"CLIM_SF6_TIMESERIES", -1,
7529 scan_ctl(filename, argc, argv,
"MIXING_DT", -1,
"3600.", NULL);
7531 scan_ctl(filename, argc, argv,
"MIXING_TAU_TROP", -1,
"-999", NULL);
7533 scan_ctl(filename, argc, argv,
"MIXING_TAU_STRAT", -1,
"-999", NULL);
7535 scan_ctl(filename, argc, argv,
"MIXING_Z0", -1,
"-5", NULL);
7537 scan_ctl(filename, argc, argv,
"MIXING_Z1", -1,
"85", NULL);
7539 (int)
scan_ctl(filename, argc, argv,
"MIXING_NZ", -1,
"90", NULL);
7541 scan_ctl(filename, argc, argv,
"MIXING_LON0", -1,
"-180", NULL);
7543 scan_ctl(filename, argc, argv,
"MIXING_LON1", -1,
"180", NULL);
7545 (int)
scan_ctl(filename, argc, argv,
"MIXING_NX", -1,
"360", NULL);
7547 scan_ctl(filename, argc, argv,
"MIXING_LAT0", -1,
"-90", NULL);
7549 scan_ctl(filename, argc, argv,
"MIXING_LAT1", -1,
"90", NULL);
7551 (int)
scan_ctl(filename, argc, argv,
"MIXING_NY", -1,
"180", NULL);
7557 ERRMSG(
"Invalid mixing grid!");
7560 ERRMSG(
"Mixing times must either both be positive or both be disabled!");
7564 scan_ctl(filename, argc, argv,
"CHEMGRID_Z0", -1,
"-5", NULL);
7566 scan_ctl(filename, argc, argv,
"CHEMGRID_Z1", -1,
"85", NULL);
7568 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NZ", -1,
"90", NULL);
7570 scan_ctl(filename, argc, argv,
"CHEMGRID_LON0", -1,
"-180", NULL);
7572 scan_ctl(filename, argc, argv,
"CHEMGRID_LON1", -1,
"180", NULL);
7574 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NX", -1,
"360", NULL);
7576 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT0", -1,
"-90", NULL);
7578 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT1", -1,
"90", NULL);
7580 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NY", -1,
"180", NULL);
7586 ERRMSG(
"Invalid chemistry grid!");
7591 scan_ctl(filename, argc, argv,
"TDEC_STRAT", -1,
"0", NULL);
7594 ctl->
psc_h2o =
scan_ctl(filename, argc, argv,
"PSC_H2O", -1,
"4e-6", NULL);
7596 scan_ctl(filename, argc, argv,
"PSC_HNO3", -1,
"9e-9", NULL);
7602 scan_ctl(filename, argc, argv,
"ATM_DT_OUT", -1,
"86400", NULL);
7604 (int)
scan_ctl(filename, argc, argv,
"ATM_FILTER", -1,
"0", NULL);
7606 (int)
scan_ctl(filename, argc, argv,
"ATM_STRIDE", -1,
"1", NULL);
7608 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE", -1,
"0", NULL);
7610 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE_OUT", -1,
"-1", NULL);
7614 (int)
scan_ctl(filename, argc, argv,
"ATM_NC_LEVEL", -1,
"0", NULL);
7615 for (
int iq = 0; iq < ctl->
nq; iq++)
7617 (
int)
scan_ctl(filename, argc, argv,
"ATM_NC_QUANT", iq,
"0", NULL);
7619 (int)
scan_ctl(filename, argc, argv,
"OBS_TYPE", -1,
"0", NULL);
7622 scan_ctl(filename, argc, argv,
"BUDGET_BASENAME", -1,
"-",
7625 scan_ctl(filename, argc, argv,
"BUDGET_DT_OUT", -1,
"86400", NULL);
7627 ERRMSG(
"Invalid mass budget output settings!");
7630 scan_ctl(filename, argc, argv,
"DEPO_BASENAME", -1,
"-",
7633 scan_ctl(filename, argc, argv,
"DEPO_DT_OUT", -1,
"86400", NULL);
7635 (int)
scan_ctl(filename, argc, argv,
"DEPO_TYPE", -1,
"0", NULL);
7641 scan_ctl(filename, argc, argv,
"CSI_DT_OUT", -1,
"86400", NULL);
7644 scan_ctl(filename, argc, argv,
"CSI_OBSMIN", -1,
"0", NULL);
7646 scan_ctl(filename, argc, argv,
"CSI_MODMIN", -1,
"0", NULL);
7647 ctl->
csi_z0 =
scan_ctl(filename, argc, argv,
"CSI_Z0", -1,
"-5", NULL);
7648 ctl->
csi_z1 =
scan_ctl(filename, argc, argv,
"CSI_Z1", -1,
"85", NULL);
7649 ctl->
csi_nz = (int)
scan_ctl(filename, argc, argv,
"CSI_NZ", -1,
"1", NULL);
7651 scan_ctl(filename, argc, argv,
"CSI_LON0", -1,
"-180", NULL);
7652 ctl->
csi_lon1 =
scan_ctl(filename, argc, argv,
"CSI_LON1", -1,
"180", NULL);
7654 (int)
scan_ctl(filename, argc, argv,
"CSI_NX", -1,
"360", NULL);
7655 ctl->
csi_lat0 =
scan_ctl(filename, argc, argv,
"CSI_LAT0", -1,
"-90", NULL);
7656 ctl->
csi_lat1 =
scan_ctl(filename, argc, argv,
"CSI_LAT1", -1,
"90", NULL);
7658 (int)
scan_ctl(filename, argc, argv,
"CSI_NY", -1,
"180", NULL);
7663 ERRMSG(
"Invalid CSI grid!");
7666 ctl->
nens = (int)
scan_ctl(filename, argc, argv,
"NENS", -1,
"0", NULL);
7668 ERRMSG(
"NENS must not be negative!");
7670 ERRMSG(
"Add quantity ens for ensemble calculations!");
7673 scan_ctl(filename, argc, argv,
"ENS_DT_OUT", -1,
"86400", NULL);
7676 scan_ctl(filename, argc, argv,
"GRID_BASENAME", -1,
"-",
7681 scan_ctl(filename, argc, argv,
"GRID_DT_OUT", -1,
"86400", NULL);
7683 (int)
scan_ctl(filename, argc, argv,
"GRID_SPARSE", -1,
"0", NULL);
7685 (int)
scan_ctl(filename, argc, argv,
"GRID_NC_LEVEL", -1,
"0", NULL);
7686 for (
int iq = 0; iq < ctl->
nq; iq++)
7688 (
int)
scan_ctl(filename, argc, argv,
"GRID_NC_QUANT", iq,
"0", NULL);
7690 (int)
scan_ctl(filename, argc, argv,
"GRID_STDDEV", -1,
"0", NULL);
7691 ctl->
grid_z0 =
scan_ctl(filename, argc, argv,
"GRID_Z0", -1,
"-5", NULL);
7692 ctl->
grid_z1 =
scan_ctl(filename, argc, argv,
"GRID_Z1", -1,
"85", NULL);
7694 (int)
scan_ctl(filename, argc, argv,
"GRID_NZ", -1,
"1", NULL);
7696 scan_ctl(filename, argc, argv,
"GRID_LON0", -1,
"-180", NULL);
7698 scan_ctl(filename, argc, argv,
"GRID_LON1", -1,
"180", NULL);
7700 (int)
scan_ctl(filename, argc, argv,
"GRID_NX", -1,
"360", NULL);
7702 scan_ctl(filename, argc, argv,
"GRID_LAT0", -1,
"-90", NULL);
7704 scan_ctl(filename, argc, argv,
"GRID_LAT1", -1,
"90", NULL);
7706 (int)
scan_ctl(filename, argc, argv,
"GRID_NY", -1,
"180", NULL);
7708 (int)
scan_ctl(filename, argc, argv,
"GRID_TYPE", -1,
"0", NULL);
7711 ERRMSG(
"Invalid output grid dimensions!");
7715 ERRMSG(
"Invalid output grid boundaries!");
7718 ERRMSG(
"Invalid radioactive deposition output settings!");
7721 scan_ctl(filename, argc, argv,
"PROF_BASENAME", -1,
"-",
7724 ctl->
prof_z0 =
scan_ctl(filename, argc, argv,
"PROF_Z0", -1,
"0", NULL);
7725 ctl->
prof_z1 =
scan_ctl(filename, argc, argv,
"PROF_Z1", -1,
"60", NULL);
7727 (int)
scan_ctl(filename, argc, argv,
"PROF_NZ", -1,
"60", NULL);
7729 scan_ctl(filename, argc, argv,
"PROF_LON0", -1,
"-180", NULL);
7731 scan_ctl(filename, argc, argv,
"PROF_LON1", -1,
"180", NULL);
7733 (int)
scan_ctl(filename, argc, argv,
"PROF_NX", -1,
"360", NULL);
7735 scan_ctl(filename, argc, argv,
"PROF_LAT0", -1,
"-90", NULL);
7737 scan_ctl(filename, argc, argv,
"PROF_LAT1", -1,
"90", NULL);
7739 (int)
scan_ctl(filename, argc, argv,
"PROF_NY", -1,
"180", NULL);
7744 ERRMSG(
"Invalid profile grid!");
7747 scan_ctl(filename, argc, argv,
"SAMPLE_BASENAME", -1,
"-",
7749 scan_ctl(filename, argc, argv,
"SAMPLE_KERNEL", -1,
"-",
7751 scan_ctl(filename, argc, argv,
"SAMPLE_OBSFILE", -1,
"-",
7754 scan_ctl(filename, argc, argv,
"SAMPLE_DX", -1,
"50", NULL);
7756 scan_ctl(filename, argc, argv,
"SAMPLE_DZ", -1,
"-999", NULL);
7759 scan_ctl(filename, argc, argv,
"STAT_BASENAME", -1,
"-",
7763 ctl->
stat_r =
scan_ctl(filename, argc, argv,
"STAT_R", -1,
"50", NULL);
7765 scan_ctl(filename, argc, argv,
"STAT_T0", -1,
"-1e100", NULL);
7766 ctl->
stat_t1 =
scan_ctl(filename, argc, argv,
"STAT_T1", -1,
"1e100", NULL);
7771 scan_ctl(filename, argc, argv,
"VTK_DT_OUT", -1,
"86400", NULL);
7773 (int)
scan_ctl(filename, argc, argv,
"VTK_STRIDE", -1,
"1", NULL);
7775 scan_ctl(filename, argc, argv,
"VTK_SCALE", -1,
"1.0", NULL);
7777 scan_ctl(filename, argc, argv,
"VTK_OFFSET", -1,
"0.0", NULL);
7779 (int)
scan_ctl(filename, argc, argv,
"VTK_SPHERE", -1,
"0", NULL);
7783 ctl->
dd = (int)
scan_ctl(filename, argc, argv,
"DD", -1,
"1", NULL);
7785 ctl->
dd = (int)
scan_ctl(filename, argc, argv,
"DD", -1,
"0", NULL);
7789 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_MERIDIONAL", -1,
7790 (ctl->
dd == 1) ?
"2" :
"1", NULL);
7792 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_ZONAL", -1,
7793 (ctl->
dd == 1) ?
"2" :
"1", NULL);
7795 (int)
scan_ctl(filename, argc, argv,
"DD_HALOS_SIZE", -1,
"1", NULL);
7797 (double)
scan_ctl(filename, argc, argv,
"DD_SORT_DT", -1,
"1800", NULL);
7803 const char *filename,
7810 LOG(1,
"Read meteo data: %s", filename);
7816 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
7844 ERRMSG(
"MET_TYPE not implemented!");
7898 LOG(2,
"Broadcast data on rank %d...", rank);
8030 module_dd(t, ctl, cache, dd, atm, met0);
8044 ERRMSG(
"Code was compiled without KPP!");
8077#pragma acc update device(ctl[:1])
8081 if (cache != NULL) {
8084#pragma acc update device(cache[:1])
8091#pragma acc update device(clim[:1])
8098 met_t *met0up = *met0;
8099#pragma acc update device(met0up[:1])
8106 met_t *met1up = *met1;
8107#pragma acc update device(met1up[:1])
8114#pragma acc update device(atm[:1])
8133#pragma acc update host(ctl[:1])
8137 if (cache != NULL) {
8140#pragma acc update host(cache[:1])
8147#pragma acc update host(clim[:1])
8154 met_t *met0up = *met0;
8155#pragma acc update host(met0up[:1])
8162 met_t *met1up = *met1;
8163#pragma acc update host(met1up[:1])
8170#pragma acc update host(atm[:1])
8178 const char *filename,
8187 LOG(1,
"Write atmospheric data: %s", filename);
8211 ERRMSG(
"Atmospheric data type not supported!");
8215 LOG(2,
"Number of particles: %d", atm->
np);
8216 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
8217 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
8218 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
8219 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
8220 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
8221 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
8222 LOG(2,
"%s range: %g ... %g %s",
8223 ctl->
met_coord_type == 0 ?
"Longitude" :
"X coordinate", mini, maxi,
8225 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
8226 LOG(2,
"%s range: %g ... %g %s",
8227 ctl->
met_coord_type == 0 ?
"Latitude" :
"Y coordinate", mini, maxi,
8229 for (
int iq = 0; iq < ctl->
nq; iq++) {
8231 sprintf(msg,
"Quantity %s range: %s ... %s %s",
8234 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
8235 LOG(2, msg, mini, maxi);
8242 const char *filename,
8250 LOG(1,
"Write meteo data: %s", filename);
8255 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
8259 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
8263 ERRMSG(
"MPTRAC was compiled without LZ4 compression!");
8267 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
8271 ERRMSG(
"MPTRAC was compiled without SZ3 compression!");
8285 ERRMSG(
"MET_TYPE not implemented!");
8291 const char *dirname,
8299 char ext[10], filename[2 *
LEN];
8303 int year, mon, day, hour, min, sec;
8306 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
8323 sprintf(ext,
"tab");
8325 sprintf(ext,
"bin");
8328 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d_%02d.%s",
8329 dirname, ctl->
atm_basename, year, mon, day, hour, min, sec, ext);
8335 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d_%02d.%s",
8336 dirname, ctl->
grid_basename, year, mon, day, hour, min, sec,
8338 write_grid(filename, ctl, met0, met1, atm, t);
8352#pragma acc update host(depo[:1])
8354 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d_%02d.%s",
8355 dirname, ctl->
depo_basename, year, mon, day, hour, min, sec,
8362 sprintf(filename,
"%s/%s.tab", dirname, ctl->
csi_basename);
8368 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d_%02d.tab",
8369 dirname, ctl->
ens_basename, year, mon, day, hour, min, sec);
8375 sprintf(filename,
"%s/%s.tab", dirname, ctl->
prof_basename);
8376 write_prof(filename, ctl, met0, met1, atm, t);
8387 sprintf(filename,
"%s/%s.tab", dirname, ctl->
stat_basename);
8396 sprintf(filename,
"%s/%s_%05d.vtk", dirname, ctl->
vtk_basename, ++nvtk);
8406 const double hno3) {
8409 const double h2o_help =
MAX(h2o, 0.1e-6);
8412 const double p_hno3 = hno3 * p / 1.333224;
8413 const double p_h2o = h2o_help * p / 1.333224;
8414 const double a = 0.009179 - 0.00088 * log10(p_h2o);
8415 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
8416 const double c = -11397.0 / a;
8417 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
8418 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
8436 const double p0 = pbl;
8439 if (atm->
p[ip] > p0)
8441 else if (atm->
p[ip] < p1)
8444 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
8450 const char *filename,
8456 if (!(in = fopen(filename,
"r"))) {
8457 WARN(
"Cannot open file!");
8463 while (fgets(line,
LEN, in)) {
8467 TOK(line, tok,
"%lg", atm->
time[atm->
np]);
8468 TOK(NULL, tok,
"%lg", atm->
p[atm->
np]);
8469 TOK(NULL, tok,
"%lg", atm->
lon[atm->
np]);
8470 TOK(NULL, tok,
"%lg", atm->
lat[atm->
np]);
8471 for (
int iq = 0; iq < ctl->
nq; iq++)
8472 TOK(NULL, tok,
"%lg", atm->
q[iq][atm->
np]);
8475 atm->
p[atm->
np] =
P(atm->
p[atm->
np]);
8478 if ((++atm->
np) >
NP)
8479 ERRMSG(
"Too many data points!");
8492 const char *filename,
8498 if (!(in = fopen(filename,
"r")))
8503 FREAD(&version,
int,
8507 ERRMSG(
"Wrong version of binary data!");
8525 for (
int iq = 0; iq < ctl->
nq; iq++)
8526 FREAD(atm->
q[iq],
double,
8536 ERRMSG(
"Error while reading binary data!");
8548 const char *filename,
8553 ERRMSG(
"CLaMS atmospheric files support only lat/lon grids");
8558 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
8565 if (nc_inq_varid(ncid,
"TIME_INIT", &varid) == NC_NOERR) {
8566 NC(nc_get_var_double(ncid, varid, atm->
time));
8568 WARN(
"TIME_INIT not found use time instead!");
8571 for (
int ip = 0; ip < atm->
np; ip++) {
8572 atm->
time[ip] = time_init;
8584 if (nc_inq_varid(ncid,
"PRESS_INIT", &varid) == NC_NOERR) {
8585 NC(nc_get_var_double(ncid, varid, atm->
p));
8587 WARN(
"PRESS_INIT not found use PRESS instead!");
8588 nc_inq_varid(ncid,
"PRESS", &varid);
8589 NC(nc_get_var_double(ncid, varid, atm->
p));
8594 for (
int iq = 0; iq < ctl->
nq; iq++)
8611 const char *filename,
8618 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
8631 for (
int iq = 0; iq < ctl->
nq; iq++)
8644 const char *filename,
8650 LOG(1,
"Read photolysis rates: %s", filename);
8653 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
8654 WARN(
"Photolysis rate data are missing!");
8661 if (photo->
p[0] < photo->
p[1])
8662 ERRMSG(
"Pressure data are not descending!");
8667 if (photo->
o3c[0] > photo->
o3c[1])
8668 ERRMSG(
"Total column ozone data are not ascending!");
8673 if (photo->
sza[0] > photo->
sza[1])
8674 ERRMSG(
"Solar zenith angle data are not ascending!");
8691 LOG(2,
"Number of pressure levels: %d", photo->
np);
8692 LOG(2,
"Altitude levels: %g, %g ... %g km",
8693 Z(photo->
p[0]),
Z(photo->
p[1]),
Z(photo->
p[photo->
np - 1]));
8694 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
8695 photo->
p[0], photo->
p[1], photo->
p[photo->
np - 1]);
8696 LOG(2,
"Number of solar zenith angles: %d", photo->
nsza);
8697 LOG(2,
"Solar zenith angles: %g, %g ... %g deg",
8700 LOG(2,
"Number of total column ozone values: %d", photo->
no3c);
8701 LOG(2,
"Total column ozone: %g, %g ... %g DU",
8703 LOG(2,
"N2O photolysis rate: %g, %g ... %g s**-1",
8704 photo->
n2o[0][0][0], photo->
n2o[1][0][0],
8705 photo->
n2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
8706 LOG(2,
"CCl4 photolysis rate: %g, %g ... %g s**-1",
8707 photo->
ccl4[0][0][0], photo->
ccl4[1][0][0],
8709 LOG(2,
"CFC-11 photolysis rate: %g, %g ... %g s**-1",
8710 photo->
ccl3f[0][0][0], photo->
ccl3f[1][0][0],
8712 LOG(2,
"CFC-12 photolysis rate: %g, %g ... %g s**-1",
8715 LOG(2,
"O2 photolysis rate: %g, %g ... %g s**-1",
8716 photo->
o2[0][0][0], photo->
o2[1][0][0],
8717 photo->
o2[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
8718 LOG(2,
"O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
8719 photo->
o3_1[0][0][0], photo->
o3_1[1][0][0],
8721 LOG(2,
"O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
8722 photo->
o3_2[0][0][0], photo->
o3_2[1][0][0],
8724 LOG(2,
"H2O2 photolysis rate: %g, %g ... %g s**-1",
8725 photo->
h2o2[0][0][0], photo->
h2o2[1][0][0],
8727 LOG(2,
"H2O photolysis rate: %g, %g ... %g s**-1",
8728 photo->
h2o[0][0][0], photo->
h2o[1][0][0],
8729 photo->
h2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
8736 const char *varname,
8750 for (
int ip = 0; ip < photo->
np; ip++)
8751 for (
int is = 0; is < photo->
nsza; is++)
8752 for (
int io = 0; io < photo->
no3c; io++)
8763 const char *filename,
8767 LOG(1,
"Read climatological time series: %s", filename);
8771 if (!(in = fopen(filename,
"r"))) {
8772 WARN(
"Cannot open file!");
8779 while (fgets(line,
LEN, in))
8780 if (sscanf(line,
"%lg %lg", &ts->
time[nh], &ts->
vmr[nh]) == 2) {
8783 ts->
time[nh] = (ts->
time[nh] - 2000.0) * 365.25 * 86400.;
8786 if (nh > 0 && ts->
time[nh] <= ts->
time[nh - 1])
8787 ERRMSG(
"Time series must be ascending!");
8791 ERRMSG(
"Too many data points!");
8800 ERRMSG(
"Not enough data points!");
8803 LOG(2,
"Number of time steps: %d", ts->
ntime);
8804 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s", ts->
time[0], ts->
time[1],
8806 LOG(2,
"Volume mixing ratio range: %g ... %g ppv",
8807 gsl_stats_min(ts->
vmr, 1, (
size_t) nh), gsl_stats_max(ts->
vmr, 1,
8817 const char *filename,
8818 const char *varname,
8821 int ncid, varid, it, iy, iz, iz2, nt;
8823 double *help, varmin = 1e99, varmax = -1e99;
8826 LOG(1,
"Read %s data: %s", varname, filename);
8829 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
8830 WARN(
"%s climatology data are missing!", varname);
8837 if (zm->
p[0] < zm->
p[1])
8838 ERRMSG(
"Pressure data are not descending!");
8843 if (zm->
lat[0] > zm->
lat[1])
8844 ERRMSG(
"Latitude data are not ascending!");
8848 zm->
time[0] = 1209600.00;
8849 zm->
time[1] = 3888000.00;
8850 zm->
time[2] = 6393600.00;
8851 zm->
time[3] = 9072000.00;
8852 zm->
time[4] = 11664000.00;
8853 zm->
time[5] = 14342400.00;
8854 zm->
time[6] = 16934400.00;
8855 zm->
time[7] = 19612800.00;
8856 zm->
time[8] = 22291200.00;
8857 zm->
time[9] = 24883200.00;
8858 zm->
time[10] = 27561600.00;
8859 zm->
time[11] = 30153600.00;
8868 for (it = 0; it < zm->
ntime; it++)
8869 for (iz = 0; iz < zm->
np; iz++)
8870 for (iy = 0; iy < zm->
nlat; iy++)
8875 for (it = 0; it < zm->
ntime; it++)
8876 for (iy = 0; iy < zm->
nlat; iy++)
8877 for (iz = 0; iz < zm->
np; iz++) {
8878 if (zm->
vmr[it][iz][iy] < 0) {
8879 for (iz2 = 0; iz2 < zm->
np; iz2++)
8880 if (zm->
vmr[it][iz2][iy] >= 0) {
8881 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
8884 for (iz2 = zm->
np - 1; iz2 >= 0; iz2--)
8885 if (zm->
vmr[it][iz2][iy] >= 0) {
8886 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
8890 varmin =
MIN(varmin, zm->
vmr[it][iz][iy]);
8891 varmax =
MAX(varmax, zm->
vmr[it][iz][iy]);
8898 LOG(2,
"Number of time steps: %d", zm->
ntime);
8899 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
8901 LOG(2,
"Number of pressure levels: %d", zm->
np);
8902 LOG(2,
"Altitude levels: %g, %g ... %g km",
8903 Z(zm->
p[0]),
Z(zm->
p[1]),
Z(zm->
p[zm->
np - 1]));
8904 LOG(2,
"Pressure levels: %g, %g ... %g hPa", zm->
p[0],
8905 zm->
p[1], zm->
p[zm->
np - 1]);
8906 LOG(2,
"Number of latitudes: %d", zm->
nlat);
8907 LOG(2,
"Latitudes: %g, %g ... %g deg",
8909 LOG(2,
"%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
8916 const char *filename,
8922 LOG(1,
"Read kernel function: %s", filename);
8926 if (!(in = fopen(filename,
"r")))
8927 ERRMSG(
"Cannot open file!");
8932 while (fgets(line,
LEN, in))
8933 if (sscanf(line,
"%lg %lg", &kz[n], &kw[n]) == 2) {
8934 if (n > 0 && kz[n] < kz[n - 1])
8935 ERRMSG(
"Height levels must be ascending!");
8937 ERRMSG(
"Too many height levels!");
8946 ERRMSG(
"Not enough height levels!");
8949 const double kmax = gsl_stats_max(kw, 1, (
size_t) n);
8950 for (
int iz = 0; iz < n; iz++)
8957 const char *filename,
8965 int year, mon, day, hour, min, sec;
8971 if (!(in = fopen(filename,
"r"))) {
8972 WARN(
"Cannot open file!");
8978 FREAD(&met_type,
int,
8982 ERRMSG(
"Wrong MET_TYPE of binary data!");
8986 FREAD(&version,
int,
8990 ERRMSG(
"Wrong version of binary data!");
8996 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
8997 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
8998 met->
time, year, mon, day, hour, min);
8999 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
9000 || day < 1 || day > 31 || hour < 0 || hour > 23)
9001 ERRMSG(
"Error while reading time!");
9009 LOG(2,
"Number of %s: %d",
9010 (met->
coord_type == 0) ?
"longitudes" :
"x coordinates", met->
nx);
9011 if (met->
nx < 2 || met->
nx >
EX)
9013 ?
"Number of longitudes out of range!"
9014 :
"Number of x coordinates out of range!");
9019 LOG(2,
"Number of %s: %d",
9020 (met->
coord_type == 0) ?
"latitudes" :
"y coordinates", met->
ny);
9021 if (met->
ny < 2 || met->
ny >
EY)
9023 ?
"Number of latitudes out of range!"
9024 :
"Number of y coordinates out of range!");
9029 LOG(2,
"Number of levels: %d", met->
np);
9030 if (met->
np < 2 || met->
np >
EP)
9031 ERRMSG(
"Number of levels out of range!");
9037 LOG(2,
"%s: %g, %g ... %g %s",
9038 met->
coord_type == 0 ?
"Longitudes" :
"X coordinates",
9045 LOG(2,
"%s: %g, %g ... %g %s",
9046 met->
coord_type == 0 ?
"Latitudes" :
"Y coordinates",
9053 LOG(2,
"Altitude levels: %g, %g ... %g km",
9054 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
9055 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
9056 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
9105 ERRMSG(
"Error while reading binary data!");
9120 const char *varname) {
9129 LOG(2,
"Read 2-D variable: %s (uncompressed)", varname);
9131 (
size_t) (met->
nx * met->
ny),
9135 for (
int ix = 0; ix < met->
nx; ix++)
9136 for (
int iy = 0; iy < met->
ny; iy++)
9137 var[ix][iy] = help[
ARRAY_2D(ix, iy, met->
ny)];
9150 const char *varname,
9151 const float bound_min,
9152 const float bound_max) {
9162 LOG(2,
"Read 3-D variable: %s (uncompressed)", varname);
9164 (
size_t) (met->
nx * met->
ny * met->
np),
9176 FREAD(&precision,
int,
9181 FREAD(&tolerance,
double,
9187 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
9196 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
9205 ERRMSG(
"MPTRAC was compiled without LZ4 compression!");
9214 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
9222 FREAD(&precision,
int,
9227 FREAD(&tolerance,
double,
9233 ERRMSG(
"MPTRAC was compiled without sz3 compression!");
9238#pragma omp parallel for default(shared) collapse(2)
9239 for (
int ix = 0; ix < met->
nx; ix++)
9240 for (
int iy = 0; iy < met->
ny; iy++)
9241 for (
int ip = 0; ip < met->
np; ip++) {
9242 var[ix][iy][ip] = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9243 if (var[ix][iy][ip] < bound_min)
9244 var[ix][iy][ip] = bound_min;
9245 else if (var[ix][iy][ip] > bound_max)
9246 var[ix][iy][ip] = bound_max;
9265 ERRMSG(
"Only lat/lon grid supported");
9269 LOG(2,
"Calculate CAPE...");
9272 const double pfac = 1.01439, dz0 =
RI /
MA /
G0 * log(pfac);
9275#pragma omp parallel for default(shared) collapse(2)
9276 for (
int ix = 0; ix < met->
nx; ix++)
9277 for (
int iy = 0; iy < met->
ny; iy++) {
9281 double h2o = 0, t, theta = 0;
9282 double pbot =
MIN(met->
ps[ix][iy], met->
p[0]);
9283 double ptop = pbot - 50.;
9284 for (
int ip = 0; ip < met->
np; ip++) {
9285 if (met->
p[ip] <= pbot) {
9286 theta +=
THETA(met->
p[ip], met->
t[ix][iy][ip]);
9287 h2o += met->
h2o[ix][iy][ip];
9290 if (met->
p[ip] < ptop && n > 0)
9297 met->
plcl[ix][iy] = NAN;
9298 met->
plfc[ix][iy] = NAN;
9299 met->
pel[ix][iy] = NAN;
9300 met->
cape[ix][iy] = NAN;
9301 met->
cin[ix][iy] = NAN;
9307 pbot = met->
ps[ix][iy];
9309 met->
plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
9310 t = theta / pow(1000. / met->
plcl[ix][iy],
KAPPA);
9311 if (
RH(met->
plcl[ix][iy], t, h2o) > 100.)
9312 ptop = met->
plcl[ix][iy];
9314 pbot = met->
plcl[ix][iy];
9315 }
while (pbot - ptop > 0.1);
9319 double dcape, dz, h2o_env, t_env;
9320 double p = met->
ps[ix][iy];
9321 met->
cape[ix][iy] = met->
cin[ix][iy] = 0;
9323 dz = dz0 *
TVIRT(t, h2o);
9325 t = theta / pow(1000. / p,
KAPPA);
9329 &h2o_env, ci, cw, 0);
9330 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
9331 TVIRT(t_env, h2o_env) * dz;
9333 met->
cin[ix][iy] += fabsf((
float) dcape);
9334 }
while (p > met->
plcl[ix][iy]);
9339 p = met->
plcl[ix][iy];
9340 t = theta / pow(1000. / p,
KAPPA);
9345 dz = dz0 *
TVIRT(t, h2o);
9348 double psat =
PSAT(t);
9349 h2o = psat / (p - (1. -
EPS) * psat);
9353 &h2o_env, ci, cw, 0);
9354 double dcape_old = dcape;
9355 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
9356 TVIRT(t_env, h2o_env) * dz;
9358 met->
cape[ix][iy] += (float) dcape;
9359 if (!isfinite(met->
plfc[ix][iy]))
9360 met->
plfc[ix][iy] = (
float) p;
9361 }
else if (dcape_old > 0)
9362 met->
pel[ix][iy] = (float) p;
9363 if (dcape < 0 && !isfinite(met->
plfc[ix][iy]))
9364 met->
cin[ix][iy] += fabsf((
float) dcape);
9368 if (!isfinite(met->
plfc[ix][iy]))
9369 met->
cin[ix][iy] = NAN;
9380 LOG(2,
"Calculate cloud data...");
9383 const double ccmin = 0.01, cwmin = 1e-6;
9386#pragma omp parallel for default(shared) collapse(2)
9387 for (
int ix = 0; ix < met->
nx; ix++)
9388 for (
int iy = 0; iy < met->
ny; iy++) {
9391 met->
pct[ix][iy] = NAN;
9392 met->
pcb[ix][iy] = NAN;
9393 met->
cl[ix][iy] = 0;
9396 for (
int ip = 0; ip < met->
np - 1; ip++) {
9399 if (met->
p[ip] > met->
ps[ix][iy] || met->
p[ip] <
P(20.))
9403 if (met->
cc[ix][iy][ip] > ccmin
9404 && (met->
lwc[ix][iy][ip] > cwmin
9405 || met->
rwc[ix][iy][ip] > cwmin
9406 || met->
iwc[ix][iy][ip] > cwmin
9407 || met->
swc[ix][iy][ip] > cwmin)) {
9411 = (float) (0.5 * (met->
p[ip] + (
float) met->
p[ip + 1]));
9414 if (!isfinite(met->
pcb[ix][iy]))
9416 = (
float) (0.5 * (met->
p[ip] + met->
p[
MAX(ip - 1, 0)]));
9420 met->
cl[ix][iy] += (float)
9421 (0.5 * (met->
lwc[ix][iy][ip] + met->
lwc[ix][iy][ip + 1]
9422 + met->
rwc[ix][iy][ip] + met->
rwc[ix][iy][ip + 1]
9423 + met->
iwc[ix][iy][ip] + met->
iwc[ix][iy][ip + 1]
9424 + met->
swc[ix][iy][ip] + met->
swc[ix][iy][ip + 1])
9425 * 100. * (met->
p[ip] - met->
p[ip + 1]) /
G0);
9443 ERRMSG(
"Only lat/lon grid supported");
9447 LOG(2,
"Detrend meteo data...");
9454 const double tssq = 2. *
SQR(sigma);
9457 int sy = (int) (3. *
DY2DEG(sigma) / fabs(met->
lat[1] - met->
lat[0]));
9461#pragma omp parallel for default(shared) collapse(2)
9462 for (
int ix = 0; ix < met->
nx; ix++) {
9463 for (
int iy = 0; iy < met->
ny; iy++) {
9471 (int) (3. *
DX2DEG(sigma, met->
lat[iy]) /
9472 fabs(met->
lon[1] - met->
lon[0]));
9477 for (
int ip = 0; ip < met->
np; ip++) {
9478 help->
t[ix][iy][ip] = 0;
9479 help->
u[ix][iy][ip] = 0;
9480 help->
v[ix][iy][ip] = 0;
9481 help->
w[ix][iy][ip] = 0;
9485 for (
int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
9489 else if (ix3 >= met->
nx)
9491 for (
int iy2 =
MAX(iy - sy, 0);
9492 iy2 <=
MIN(iy + sy, met->
ny - 1); iy2++) {
9499 const float w = (float) exp(-
DIST2(x0, x1) / tssq);
9503 for (
int ip = 0; ip < met->
np; ip++) {
9504 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip];
9505 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip];
9506 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip];
9507 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip];
9513 for (
int ip = 0; ip < met->
np; ip++) {
9514 help->
t[ix][iy][ip] /= wsum;
9515 help->
u[ix][iy][ip] /= wsum;
9516 help->
v[ix][iy][ip] /= wsum;
9517 help->
w[ix][iy][ip] /= wsum;
9523#pragma omp parallel for default(shared) collapse(3)
9524 for (
int ix = 0; ix < met->
nx; ix++)
9525 for (
int iy = 0; iy < met->
ny; iy++)
9526 for (
int ip = 0; ip < met->
np; ip++) {
9527 met->
t[ix][iy][ip] -= help->
t[ix][iy][ip];
9528 met->
u[ix][iy][ip] -= help->
u[ix][iy][ip];
9529 met->
v[ix][iy][ip] -= help->
v[ix][iy][ip];
9530 met->
w[ix][iy][ip] -= help->
w[ix][iy][ip];
9544 LOG(2,
"Extrapolate meteo data...");
9547#pragma omp parallel for default(shared) collapse(2)
9548 for (
int ix = 0; ix < met->
nx; ix++)
9549 for (
int iy = 0; iy < met->
ny; iy++) {
9553 for (ip0 = met->
np - 1; ip0 >= 0; ip0--)
9554 if (!isfinite(met->
t[ix][iy][ip0])
9555 || !isfinite(met->
u[ix][iy][ip0])
9556 || !isfinite(met->
v[ix][iy][ip0])
9557 || !isfinite(met->
w[ix][iy][ip0]))
9561 for (
int ip = ip0; ip >= 0; ip--) {
9562 met->
t[ix][iy][ip] = met->
t[ix][iy][ip + 1];
9563 met->
u[ix][iy][ip] = met->
u[ix][iy][ip + 1];
9564 met->
v[ix][iy][ip] = met->
v[ix][iy][ip + 1];
9565 met->
w[ix][iy][ip] = met->
w[ix][iy][ip + 1];
9566 met->
h2o[ix][iy][ip] = met->
h2o[ix][iy][ip + 1];
9567 met->
o3[ix][iy][ip] = met->
o3[ix][iy][ip + 1];
9568 met->
lwc[ix][iy][ip] = met->
lwc[ix][iy][ip + 1];
9569 met->
rwc[ix][iy][ip] = met->
rwc[ix][iy][ip + 1];
9570 met->
iwc[ix][iy][ip] = met->
iwc[ix][iy][ip + 1];
9571 met->
swc[ix][iy][ip] = met->
swc[ix][iy][ip + 1];
9572 met->
cc[ix][iy][ip] = met->
cc[ix][iy][ip + 1];
9591 LOG(2,
"Calculate geopotential heights...");
9598#pragma omp parallel for default(shared)
9599 for (
int ip = 0; ip < met->
np; ip++)
9600 logp[ip] = log(met->
p[ip]);
9603#pragma omp parallel for default(shared) collapse(2)
9604 for (
int ix = 0; ix < met->
nx; ix++)
9605 for (
int iy = 0; iy < met->
ny; iy++) {
9608 const double zs = met->
zs[ix][iy];
9609 const double lnps = log(met->
ps[ix][iy]);
9613 const double ts =
LIN(met->
p[ip0], met->
t[ix][iy][ip0], met->
p[ip0 + 1],
9614 met->
t[ix][iy][ip0 + 1], met->
ps[ix][iy]);
9616 LIN(met->
p[ip0], met->
h2o[ix][iy][ip0], met->
p[ip0 + 1],
9617 met->
h2o[ix][iy][ip0 + 1], met->
ps[ix][iy]);
9620 met->
z[ix][iy][ip0 + 1]
9622 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
9623 met->
t[ix][iy][ip0 + 1], met->
h2o[ix][iy][ip0 + 1]));
9624 for (
int ip = ip0 + 2; ip < met->
np; ip++)
9626 = (
float) (met->
z[ix][iy][ip - 1] +
9627 ZDIFF(logp[ip - 1], met->
t[ix][iy][ip - 1],
9628 met->
h2o[ix][iy][ip - 1], logp[ip],
9629 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
9634 ZDIFF(lnps, ts, h2os, logp[ip0],
9635 met->
t[ix][iy][ip0], met->
h2o[ix][iy][ip0]));
9636 for (
int ip = ip0 - 1; ip >= 0; ip--)
9638 = (
float) (met->
z[ix][iy][ip + 1] +
9639 ZDIFF(logp[ip + 1], met->
t[ix][iy][ip + 1],
9640 met->
h2o[ix][iy][ip + 1], logp[ip],
9641 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
9645 if (dx == 0 || dy == 0)
9649 if (dx < 0 || dy < 0) {
9650 if (fabs(met->
lon[1] - met->
lon[0]) < 0.5) {
9660 float ws[dx + 1][dy + 1];
9661#pragma omp parallel for default(shared) collapse(2)
9662 for (
int ix = 0; ix <= dx; ix++)
9663 for (
int iy = 0; iy < dy; iy++)
9664 ws[ix][iy] = (1.0f - (
float) ix / (float) dx)
9665 * (1.0f - (float) iy / (
float) dy);
9668#pragma omp parallel for default(shared) collapse(3)
9669 for (
int ix = 0; ix < met->
nx; ix++)
9670 for (
int iy = 0; iy < met->
ny; iy++)
9671 for (
int ip = 0; ip < met->
np; ip++)
9672 help[
ARRAY_3D(ip, ix, met->
nx, iy, met->
ny)] = met->
z[ix][iy][ip];
9675#pragma omp parallel for default(shared) collapse(3)
9676 for (
int ip = 0; ip < met->
np; ip++)
9677 for (
int ix = 0; ix < met->
nx; ix++)
9678 for (
int iy = 0; iy < met->
ny; iy++) {
9679 float res = 0, wsum = 0;
9680 int iy0 =
MAX(iy - dy + 1, 0);
9681 int iy1 =
MIN(iy + dy - 1, met->
ny - 1);
9682 for (
int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
9686 else if (ix3 >= met->
nx)
9688 for (
int iy2 = iy0; iy2 <= iy1; ++iy2)
9689 if (isfinite(help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)])) {
9690 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
9691 res += w * help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)];
9696 met->
z[ix][iy][ip] = res / wsum;
9698 met->
z[ix][iy][ip] = NAN;
9708 const char *filename,
9714 char levname[
LEN], tstr[10];
9716 double rtime = 0, r, r2;
9718 int varid, ndims, dimids[NC_MAX_DIMS], year2, mon2, day2, hour2, min2, sec2,
9719 year, mon, day, hour, min, sec;
9725 LOG(2,
"Read meteo grid information...");
9734 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
9735 if (nc_inq_varid(ncid,
"time", &varid) == NC_NOERR) {
9736 NC(nc_get_var_double(ncid, varid, &rtime));
9737 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
9738 WARN(
"Time information in meteo file does not match filename!");
9740 WARN(
"Time information in meteo file is missing!");
9751 sprintf(tstr,
"19%.2s", &filename[strlen(filename) - 11]);
9753 sprintf(tstr,
"20%.2s", &filename[strlen(filename) - 11]);
9755 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 9]);
9757 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 7]);
9759 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 5]);
9765 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
9766 || day < 1 || day > 31 || hour < 0 || hour > 23)
9767 ERRMSG(
"Cannot read time from filename!");
9768 jsec2time(met->
time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
9769 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
9770 met->
time, year2, mon2, day2, hour2, min2);
9773 if (nc_inq_varid(ncid,
"u", &varid) != NC_NOERR)
9774 if (nc_inq_varid(ncid,
"U", &varid) != NC_NOERR)
9776 (
"Variable 'u' or 'U' not found, cannot determine vertical dimension!");
9778 NC(nc_inq_varndims(ncid, varid, &ndims));
9779 NC(nc_inq_vardimid(ncid, varid, dimids));
9783 (ncid, dimids[ctl->
met_convention == 0 ? 1 : 3], levname, &dimlen));
9784 }
else if (ndims == 3) {
9786 (ncid, dimids[ctl->
met_convention == 0 ? 0 : 2], levname, &dimlen));
9788 ERRMSG(
"Cannot determine vertical dimension!")
9789 met->
np = (int) dimlen;
9791 LOG(2,
"Number of levels: %d", met->
np);
9792 if (met->
np < 2 || met->
np >
EP)
9793 ERRMSG(
"Number of levels out of range!");
9801 LOG(2,
"Number of longitudes: %d", met->
nx);
9804 LOG(2,
"Number of latitudes: %d", met->
ny);
9807 LOG(2,
"Longitudes: %g, %g ... %g deg",
9810 LOG(2,
"Latitudes: %g, %g ... %g deg",
9816 LOG(2,
"Number of x coordinates: %d", met->
nx);
9819 LOG(2,
"Number of y coordinates: %d", met->
ny);
9822 LOG(2,
"X coordinates: %g, %g ... %g m",
9825 LOG(2,
"Y coordinates: %g, %g ... %g m",
9832 ERRMSG(
"Domain decomposition is only supported for lat/lon grids!");
9842 for (
int ip = 0; ip < met->
np; ip++)
9844 LOG(2,
"Altitude levels: %g, %g ... %g km",
9845 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
9846 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
9847 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
9851 if (strcasecmp(levname,
"hybrid") == 0)
9863 ERRMSG(
"You need to specify MET_NLEV, MET_LEV_HYAM, and MET_LEV_HYBM!");
9864 for (
int ip = 0; ip < ctl->
met_nlev; ip++) {
9874 ERRMSG(
"Eta levels must be ascending!");
9878 for (
int ix = 2; ix < met->
nx; ix++)
9880 (fabs(met->
lon[ix] - met->
lon[ix - 1]) -
9881 fabs(met->
lon[1] - met->
lon[0])) > 0.001)
9882 ERRMSG(
"No regular grid spacing in longitudes!");
9883 for (
int iy = 2; iy < met->
ny; iy++)
9885 (fabs(met->
lat[iy] - met->
lat[iy - 1]) -
9886 fabs(met->
lat[1] - met->
lat[0])) > 0.001) {
9887 WARN(
"No regular grid spacing in latitudes!");
9902 LOG(2,
"Read surface data...");
9906 (ncid, (
const char *
const[]) {
"lnsp",
"LNSP" }, 2, ctl, met, dd,
9909 for (
int ix = 0; ix < met->
nx; ix++)
9910 for (
int iy = 0; iy < met->
ny; iy++)
9911 met->
ps[ix][iy] = (
float) (exp(met->
ps[ix][iy]) / 100.);
9914 (ncid, (
const char *
const[]) {
"ps",
"PS",
"sp",
"SP" }, 4, ctl, met,
9917 WARN(
"Cannot not read surface pressure data (use lowest level)!");
9918 for (
int ix = 0; ix < met->
nx; ix++)
9919 for (
int iy = 0; iy < met->
ny; iy++)
9921 = (ctl->
met_np > 0 ? (
float) ctl->
met_p[0] : (
float) met->
p[0]);
9929 (ncid, (
const char *
const[]) {
"z",
"Z" }, 2, ctl, met, dd, met->zs,
9930 (float) (1. / (1000. *
G0)), 1))
9932 (ncid, (
const char *
const[]) {
"zm",
"ZM" }, 2, ctl, met, dd,
9934 (ctl->
met_gp2z ? (float) (1e-3 /
G0) : (float) (1. / 1000.)), 1))
9935 WARN(
"Cannot read surface geopotential height!");
9946 memcpy(help, met->
pl,
sizeof(met->
pl));
9948 (ncid, (
const char *
const[]) {
"gph",
"GPH" }, 2, ctl, met, dd,
9950 (float) (1e-3 /
G0)))
9951 ERRMSG(
"Cannot read geopotential height!");
9952 for (
int ix = 0; ix < met->nx; ix++)
9953 for (
int iy = 0; iy < met->ny; iy++)
9954 met->zs[ix][iy] = met->pl[ix][iy][0];
9955 memcpy(met->pl, help,
sizeof(met->pl));
9961 (ncid, (
const char *
const[]) {
"t2m",
"T2M",
"2t",
"2T",
"t2",
"T2" },
9962 6, ctl, met, dd, met->
ts, 1.0,
9964 WARN(
"Cannot read surface temperature!");
9968 (ncid, (
const char *
const[]) {
"u10m",
"U10M",
"10u",
"10U",
"u10",
9972 WARN(
"Cannot read surface zonal wind!");
9976 (ncid, (
const char *
const[]) {
"v10m",
"V10M",
"10v",
"10V",
"v10",
9980 WARN(
"Cannot read surface meridional wind!");
9984 (ncid, (
const char *
const[]) {
"iews",
"IEWS" }, 2, ctl, met, dd,
9987 WARN(
"Cannot read eastward turbulent surface stress!");
9991 (ncid, (
const char *
const[]) {
"inss",
"INSS" }, 2, ctl, met, dd,
9994 WARN(
"Cannot read northward turbulent surface stress!");
9998 (ncid, (
const char *
const[]) {
"ishf",
"ISHF" }, 2, ctl, met, dd,
10001 WARN(
"Cannot read surface sensible heat flux!");
10005 (ncid, (
const char *
const[]) {
"lsm",
"LSM" }, 2, ctl, met, dd,
10008 WARN(
"Cannot read land-sea mask!");
10012 (ncid, (
const char *
const[]) {
"sstk",
"SSTK",
"sst",
"SST" }, 4, ctl,
10015 WARN(
"Cannot read sea surface temperature!");
10020 (ncid, (
const char *
const[]) {
"blp",
"BLP" }, 2, ctl, met, dd,
10023 WARN(
"Cannot read planetary boundary layer pressure!");
10026 (ncid, (
const char *
const[]) {
"blh",
"BLH" }, 2, ctl, met, dd,
10029 WARN(
"Cannot read planetary boundary layer height!");
10034 (ncid, (
const char *
const[]) {
"cape",
"CAPE" }, 2, ctl, met, dd,
10035 met->
cape, 1.0, 1))
10036 WARN(
"Cannot read CAPE!");
10041 (ncid, (
const char *
const[]) {
"cin",
"CIN" }, 2, ctl, met, dd,
10044 WARN(
"Cannot read convective inhibition!");
10057 LOG(2,
"Read level data...");
10061 (ncid, (
const char *
const[]) {
"t",
"T",
"temp",
"TEMP" }, 4, ctl, met,
10063 ERRMSG(
"Cannot read temperature!");
10067 (ncid, (
const char *
const[]) {
"u",
"U" }, 2, ctl, met, dd, met->
u,
10069 ERRMSG(
"Cannot read zonal wind!");
10071 (ncid, (
const char *
const[]) {
"v",
"V" }, 2, ctl, met, dd, met->
v,
10073 ERRMSG(
"Cannot read meridional wind!");
10075 (ncid, (
const char *
const[]) {
"w",
"W",
"omega",
"OMEGA" }, 4, ctl,
10076 met, dd, met->
w, 0.01f))
10077 WARN(
"Cannot read vertical velocity!");
10082 (ncid, (
const char *
const[]) {
"q",
"Q",
"sh",
"SH" }, 4, ctl, met,
10085 WARN(
"Cannot read specific humidity!");
10088 (ncid, (
const char *
const[]) {
"rh",
"RH" }, 2, ctl, met, dd,
10090 WARN(
"Cannot read relative humidity!");
10091#pragma omp parallel for default(shared) collapse(2)
10092 for (
int ix = 0; ix < met->nx; ix++)
10093 for (
int iy = 0; iy < met->ny; iy++)
10094 for (
int ip = 0; ip < met->np; ip++) {
10095 double pw = met->h2o[ix][iy][ip] *
PSAT(met->t[ix][iy][ip]);
10096 met->h2o[ix][iy][ip] =
10097 (float) (pw / (met->p[ip] - (1.0 -
EPS) * pw));
10103 (ncid, (
const char *
const[]) {
"o3",
"O3" }, 2, ctl, met, dd, met->
o3,
10104 (float) (
MA /
MO3)))
10105 WARN(
"Cannot read ozone data!");
10109 (ncid, (
const char *
const[]) {
"clwc",
"CLWC" }, 2, ctl, met, dd,
10111 WARN(
"Cannot read cloud liquid water content!");
10113 (ncid, (
const char *
const[]) {
"crwc",
"CRWC" }, 2, ctl, met, dd,
10115 WARN(
"Cannot read cloud rain water content!");
10117 (ncid, (
const char *
const[]) {
"ciwc",
"CIWC" }, 2, ctl, met, dd,
10119 WARN(
"Cannot read cloud ice water content!");
10121 (ncid, (
const char *
const[]) {
"cswc",
"CSWC" }, 2, ctl, met, dd,
10123 WARN(
"Cannot read cloud snow water content!");
10125 (ncid, (
const char *
const[]) {
"cc",
"CC" }, 2, ctl, met, dd, met->
cc,
10127 WARN(
"Cannot read cloud cover!");
10132 (ncid, (
const char *
const[]) {
"ZETA",
"zeta" }, 2, ctl, met, dd,
10134 WARN(
"Cannot read ZETA!");
10136 (ncid, (
const char *
const[]) {
"ZETA_DOT_TOT",
"ZETA_DOT_clr",
10138 }, 3, ctl, met, dd, met->zeta_dotl, 0.00001157407f))
10139 ERRMSG(
"Cannot read ZETA_DOT!");
10144#pragma omp parallel for default(shared)
10145 for (
int ix = 0; ix < met->
nx; ix++)
10146 for (
int iy = 0; iy < met->
ny; iy++)
10147 for (
int ip = 0; ip < met->
np; ip++)
10148 met->
zetal[ix][iy][ip] =
10149 (
float) (met->
hyam[ip] / (100.0 *
P0) + met->
hybm[ip]);
10155 (ncid, (
const char *
const[]) {
"etadot",
"ETADOT" }, 2, ctl, met, dd,
10158 ERRMSG(
"Cannot read eta vertical velocity!");
10162#pragma omp parallel for default(shared)
10163 for (
int ix = 0; ix < met->
nx; ix++)
10164 for (
int iy = 0; iy < met->
ny; iy++)
10165 for (
int ip = 0; ip < met->
np; ip++) {
10166 met->
ul[ix][iy][ip] = met->
u[ix][iy][ip];
10167 met->
vl[ix][iy][ip] = met->
v[ix][iy][ip];
10168 met->
wl[ix][iy][ip] = met->
w[ix][iy][ip];
10172 met->
npl = met->
np;
10181 (ncid, (
const char *
const[]) {
"pl",
"PL",
"pressure",
"PRESSURE" },
10182 4, ctl, met, dd, met->pl,
10185 (ncid, (
const char *
const[]) {
"press",
"PRESS" }, 2, ctl, met,
10187 ERRMSG(
"Cannot read pressure on model levels!");
10195 ERRMSG(
"Mismatch in number of model levels!");
10198 for (
int ix = 0; ix < met->
nx; ix++)
10199 for (
int iy = 0; iy < met->
ny; iy++)
10200 for (
int ip = 0; ip < met->
np; ip++)
10201 met->
pl[ix][iy][ip] =
10202 (
float) (met->
hyam[ip] / 100. +
10203 met->
hybm[ip] * met->
ps[ix][iy]);
10211 ERRMSG(
"Mismatch in number of model levels!");
10214#pragma omp parallel for default(shared) collapse(2)
10215 for (
int ix = 0; ix < met->
nx; ix++)
10216 for (
int iy = 0; iy < met->
ny; iy++)
10217 for (
int ip = 0; ip < met->
np; ip++) {
10219 met->
hyam[ip] / 100. + met->
hybm[ip] * met->
ps[ix][iy];
10221 met->
hyam[ip + 1] / 100. + met->
hybm[ip + 1] * met->
ps[ix][iy];
10222 met->
pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
10227 for (
int ix = 0; ix < met->
nx; ix++)
10228 for (
int iy = 0; iy < met->
ny; iy++)
10229 for (
int ip = 1; ip < met->
np; ip++)
10230 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
10231 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
10232 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
10233 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip]))
10234 ERRMSG(
"Pressure profiles are not monotonic!");
10255 for (
int ip = 0; ip < met->
np; ip++)
10256 met->
p[ip] = ctl->
met_p[ip];
10260 for (
int ip = 1; ip < met->
np; ip++)
10261 if (met->
p[ip - 1] < met->
p[ip])
10262 ERRMSG(
"Pressure levels must be descending!");
10269 const char *
const varnames[],
10270 const size_t nvarnames,
10274 float dest[
EX][
EY],
10278 const char *varsel = NULL;
10280 float offset, scalfac;
10285 for (
size_t i = 0; i < nvarnames; i++)
10286 if (nc_inq_varid(ncid, varnames[i], &varid) == NC_NOERR) {
10287 varsel = varnames[i];
10290 if (varsel == NULL)
10295 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
10296 && nc_get_att_float(ncid, varid,
"scale_factor",
10297 &scalfac) == NC_NOERR) {
10305 short fillval, missval;
10306 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
10308 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
10312 LOG(2,
"Read 2-D variable: %s"
10313 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
10314 varsel, fillval, missval, scalfac, offset);
10317 NC(nc_get_var_short(ncid, varid, help));
10321 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
10324 omp_set_dynamic(1);
10325#pragma omp parallel for default(shared)
10326 for (
int ix = 0; ix < met->
nx; ix++)
10327 for (
int iy = 0; iy < met->
ny; iy++) {
10330 const short aux = help[
ARRAY_2D(iy, ix, met->
nx)];
10331 if ((fillval == 0 || aux != fillval)
10332 && (missval == 0 || aux != missval)
10333 && fabsf(aux * scalfac + offset) < 1e14f)
10334 dest[ix][iy] += scl * (aux * scalfac + offset);
10336 dest[ix][iy] = NAN;
10338 omp_set_dynamic(0);
10345 else if (!ctl->
dd) {
10353 float fillval, missval;
10354 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
10356 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
10360 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
10361 varsel, fillval, missval);
10364 NC(nc_get_var_float(ncid, varid, help));
10370 omp_set_dynamic(1);
10371#pragma omp parallel for default(shared)
10372 for (
int ix = 0; ix < met->
nx; ix++)
10373 for (
int iy = 0; iy < met->
ny; iy++) {
10376 const float aux = help[
ARRAY_2D(iy, ix, met->
nx)];
10377 if ((fillval == 0 || aux != fillval)
10378 && (missval == 0 || aux != missval)
10379 && fabsf(aux) < 1e14f)
10380 dest[ix][iy] += scl * aux;
10382 dest[ix][iy] = NAN;
10384 omp_set_dynamic(0);
10389 omp_set_dynamic(1);
10390#pragma omp parallel for default(shared)
10391 for (
int iy = 0; iy < met->
ny; iy++)
10392 for (
int ix = 0; ix < met->
nx; ix++) {
10395 const float aux = help[
ARRAY_2D(ix, iy, met->
ny)];
10396 if ((fillval == 0 || aux != fillval)
10397 && (missval == 0 || aux != missval)
10398 && fabsf(aux) < 1e14f)
10399 dest[ix][iy] += scl * aux;
10401 dest[ix][iy] = NAN;
10403 omp_set_dynamic(0);
10414 float fillval, missval;
10415 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
10417 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
10421 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
10422 varsel, fillval, missval);
10426 size_t help_subdomain_start[3];
10427 size_t help_subdomain_count[3];
10429 help_subdomain_start[0] = 0;
10438 help_subdomain_count[0] = 1;
10452 nc_var_par_access(ncid, varid, NC_COLLECTIVE);
10454 NC(nc_get_vara_float
10455 (ncid, varid, help_subdomain_start, help_subdomain_count, help));
10458 size_t help_halo_bnd_start[3];
10459 size_t help_halo_bnd_count[3];
10461 help_halo_bnd_start[0] = 0;
10470 help_halo_bnd_count[0] = 1;
10480 ALLOC(help_halo,
float,
10481 help_halo_bnd_count[1] * help_halo_bnd_count[2]);
10484 nc_var_par_access(ncid, varid, NC_COLLECTIVE);
10486 NC(nc_get_vara_float
10487 (ncid, varid, help_halo_bnd_start, help_halo_bnd_count, help_halo));
10493 omp_set_dynamic(1);
10494#pragma omp parallel for default(shared)
10495 for (
int ix = 0; ix < (int) help_subdomain_count[2]; ix++)
10496 for (
int iy = 0; iy < (int) help_subdomain_count[1]; iy++) {
10500 help[
ARRAY_2D(iy, ix, (
int) help_subdomain_count[2])];
10501 if ((fillval == 0 || aux != fillval)
10502 && (missval == 0 || aux != missval)
10503 && fabsf(aux) < 1e14f) {
10509#pragma omp parallel for default(shared)
10510 for (
int ix = 0; ix < (int) help_halo_bnd_count[2]; ix++)
10511 for (
int iy = 0; iy < (int) help_halo_bnd_count[1]; iy++) {
10515 help_halo[
ARRAY_2D(iy, ix, (
int) help_halo_bnd_count[2])];
10516 if ((fillval == 0 || aux != fillval)
10517 && (missval == 0 || aux != missval)
10518 && fabsf(aux) < 1e14f)
10524 omp_set_dynamic(0);
10529 omp_set_dynamic(1);
10530#pragma omp parallel for default(shared)
10531 for (
int ix = 0; ix < (int) help_subdomain_count[1]; ix++)
10532 for (
int iy = 0; iy < (int) help_subdomain_count[2]; iy++) {
10536 help[
ARRAY_2D(ix, iy, (
int) help_subdomain_count[1])];
10537 if ((fillval == 0 || aux != fillval)
10538 && (missval == 0 || aux != missval)
10539 && fabsf(aux) < 1e14f)
10545#pragma omp parallel for default(shared)
10546 for (
int ix = 0; ix < (int) help_halo_bnd_count[1]; ix++)
10547 for (
int iy = 0; iy < (int) help_halo_bnd_count[2]; iy++) {
10551 help_halo[
ARRAY_2D(ix, iy, (
int) help_halo_bnd_count[1])];
10552 if ((fillval == 0 || aux != fillval)
10553 && (missval == 0 || aux != missval)
10554 && fabsf(aux) < 1e14f)
10559 omp_set_dynamic(0);
10575 const char *
const varnames[],
10576 const size_t nvarnames,
10583 const char *varsel = NULL;
10585 float offset, scalfac;
10590 for (
size_t i = 0; i < nvarnames; i++)
10591 if (nc_inq_varid(ncid, varnames[i], &varid) == NC_NOERR) {
10592 varsel = varnames[i];
10595 if (varsel == NULL)
10600 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
10601 && nc_get_att_float(ncid, varid,
"scale_factor",
10602 &scalfac) == NC_NOERR) {
10610 short fillval, missval;
10611 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
10613 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
10617 LOG(2,
"Read 3-D variable: %s "
10618 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
10619 varsel, fillval, missval, scalfac, offset);
10622 NC(nc_get_var_short(ncid, varid, help));
10626 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
10629 omp_set_dynamic(1);
10630#pragma omp parallel for default(shared)
10631 for (
int ix = 0; ix < met->
nx; ix++)
10632 for (
int iy = 0; iy < met->
ny; iy++)
10633 for (
int ip = 0; ip < met->
np; ip++) {
10634 const short aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
10635 if ((fillval == 0 || aux != fillval)
10636 && (missval == 0 || aux != missval)
10637 && fabsf(aux * scalfac + offset) < 1e14f)
10638 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
10640 dest[ix][iy][ip] = NAN;
10642 omp_set_dynamic(0);
10649 else if (!ctl->
dd) {
10657 float fillval, missval;
10658 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
10660 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
10664 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
10665 varsel, fillval, missval);
10668 NC(nc_get_var_float(ncid, varid, help));
10674 omp_set_dynamic(1);
10675#pragma omp parallel for default(shared)
10676 for (
int ix = 0; ix < met->
nx; ix++)
10677 for (
int iy = 0; iy < met->
ny; iy++)
10678 for (
int ip = 0; ip < met->
np; ip++) {
10679 const float aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
10680 if ((fillval == 0 || aux != fillval)
10681 && (missval == 0 || aux != missval)
10682 && fabsf(aux) < 1e14f)
10683 dest[ix][iy][ip] = scl * aux;
10685 dest[ix][iy][ip] = NAN;
10687 omp_set_dynamic(0);
10692 omp_set_dynamic(1);
10693#pragma omp parallel for default(shared)
10694 for (
int ip = 0; ip < met->
np; ip++)
10695 for (
int iy = 0; iy < met->
ny; iy++)
10696 for (
int ix = 0; ix < met->
nx; ix++) {
10697 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
10698 if ((fillval == 0 || aux != fillval)
10699 && (missval == 0 || aux != missval)
10700 && fabsf(aux) < 1e14f)
10701 dest[ix][iy][ip] = scl * aux;
10703 dest[ix][iy][ip] = NAN;
10705 omp_set_dynamic(0);
10716 float fillval, missval;
10717 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
10719 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
10723 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
10724 varsel, fillval, missval);
10727 size_t help_subdomain_start[4];
10728 size_t help_subdomain_count[4];
10729 size_t help_halo_bnd_start[4];
10730 size_t help_halo_bnd_count[4];
10733 for (
int i = 0; i < 4; i++) {
10769 NC(nc_var_par_access(ncid, varid, NC_INDEPENDENT));
10771 NC(nc_get_vara_float
10772 (ncid, varid, help_subdomain_start, help_subdomain_count, help));
10776 ALLOC(help_halo,
float,
10781 NC(nc_var_par_access(ncid, varid, NC_INDEPENDENT));
10785 NC(nc_get_vara_float
10786 (ncid, varid, help_halo_bnd_start, help_halo_bnd_count, help_halo));
10793 omp_set_dynamic(1);
10794#pragma omp parallel for default(shared)
10797 for (
int ip = 0; ip < met->
np; ip++) {
10801 if ((fillval == 0 || aux != fillval)
10802 && (missval == 0 || aux != missval)
10803 && fabsf(aux) < 1e14f) {
10810#pragma omp parallel for default(shared)
10813 for (
int ip = 0; ip < met->
np; ip++) {
10817 if ((fillval == 0 || aux != fillval)
10818 && (missval == 0 || aux != missval)
10819 && fabsf(aux) < 1e14f)
10824 omp_set_dynamic(0);
10829 omp_set_dynamic(1);
10830#pragma omp parallel for default(shared)
10831 for (
int ip = 0; ip < met->
np; ip++)
10837 if ((fillval == 0 || aux != fillval)
10838 && (missval == 0 || aux != missval)
10839 && fabsf(aux) < 1e14f)
10845#pragma omp parallel for default(shared)
10846 for (
int ip = 0; ip < met->
np; ip++)
10852 if ((fillval == 0 || aux != fillval)
10853 && (missval == 0 || aux != missval)
10854 && fabsf(aux) < 1e14f)
10859 omp_set_dynamic(0);
10875 const char *filename,
10880 size_t filename_len = strlen(filename) + 1;
10881 char sf_filename[filename_len];
10882 char ml_filename[filename_len];
10883 strcpy(sf_filename, filename);
10884 strcpy(ml_filename, filename);
10889 FILE *ml_file = fopen(ml_filename,
"rb");
10890 FILE *sf_file = fopen(sf_filename,
"rb");
10891 if (ml_file == NULL || sf_file == NULL) {
10892 if (ml_file != NULL) {
10894 WARN(
"Cannot open file: %s", sf_filename);
10896 if (sf_file != NULL) {
10898 WARN(
"Cannot open file: %s", ml_filename);
10904 int ml_num_messages = 0, err = 0;
10905 ECC(codes_count_in_file(0, ml_file, &ml_num_messages));
10908 (size_t) ml_num_messages);
10909 for (
int i = 0; i < ml_num_messages; i++) {
10911 if ((h = codes_grib_handle_new_from_file(0, ml_file, &err)) != NULL)
10916 int sf_num_messages = 0;
10917 ECC(codes_count_in_file(0, sf_file, &sf_num_messages));
10920 (size_t) sf_num_messages);
10921 for (
int i = 0; i < sf_num_messages; i++) {
10923 if ((h = codes_grib_handle_new_from_file(0, sf_file, &err)) != NULL)
10936 for (
int i = 0; i < sf_num_messages; i++)
10937 codes_handle_delete(sf_handles[i]);
10941 size_t value_count = 0;
10942 ECC(codes_get_size(ml_handles[0],
"pv", &value_count));
10943 if (value_count % 2 != 0)
10944 ERRMSG(
"Unexpected pv array length!");
10945 size_t nlevels = value_count / 2 - 1;
10947 ALLOC(values,
double,
10949 ECC(codes_get_double_array(ml_handles[0],
"pv", values, &value_count));
10950 double *a_vals = values;
10951 double *b_vals = values + nlevels;
10952 if (met->
npl > (
int) nlevels)
10953 ERRMSG(
"met->npl exceeds number of pressure levels in GRIB!");
10954 for (
int nx = 0; nx < met->
nx; nx++)
10955 for (
int ny = 0; ny < met->
ny; ny++)
10956 for (
int level = 0; level <= met->
npl; level++) {
10957 const float p1 = (float) (a_vals[level] * 0.01f +
10958 met->
ps[nx][ny] * b_vals[level]);
10959 const float p2 = (float) (a_vals[level + 1] * 0.01f +
10960 met->
ps[nx][ny] * b_vals[level + 1]);
10961 met->
pl[nx][ny][level] = 0.5f * (p1 + p2);
10967 for (
int i = 0; i < ml_num_messages; i++)
10968 codes_handle_delete(ml_handles[i]);
10986 LOG(2,
"Read meteo grid information...");
10989 char datestr[
LEN], timestr[
LEN];
10990 size_t s_date =
sizeof(datestr);
10991 ECC(codes_get_string(handles[0],
"dataDate", datestr, &s_date));
10992 size_t s_time =
sizeof(timestr);
10993 ECC(codes_get_string(handles[0],
"dataTime", timestr, &s_time));
10994 int year, month, day, hour;
10995 if (sscanf(datestr,
"%4d%2d%2d", &year, &month, &day) != 3)
10996 ERRMSG(
"Failed to parse dataDate: %s", datestr);
10997 if (sscanf(timestr,
"%2d", &hour) != 1)
10998 ERRMSG(
"Failed to parse dataTime: %s", timestr);
11000 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)", met->
time, year, month,
11004 long count_lat = 0, count_lon = 0;
11005 ECC(codes_get_long(handles[0],
"Nj", &count_lat));
11006 ECC(codes_get_long(handles[0],
"Ni", &count_lon));
11007 met->
ny = (int) count_lat;
11008 met->
nx = (int) count_lon;
11011 LOG(2,
"Number of longitudes: %d", met->
nx);
11012 if (met->
nx < 2 || met->
nx >
EX)
11013 ERRMSG(
"Number of longitudes out of range!");
11014 LOG(2,
"Number of latitudes: %d", met->
ny);
11015 if (met->
ny < 2 || met->
ny >
EY)
11016 ERRMSG(
"Number of latitudes out of range!");
11018 double first_lon, last_lon, first_lat, last_lat, inc_lon, inc_lat;
11019 ECC(codes_get_double
11020 (handles[0],
"longitudeOfFirstGridPointInDegrees", &first_lon));
11021 ECC(codes_get_double
11022 (handles[0],
"latitudeOfFirstGridPointInDegrees", &first_lat));
11023 ECC(codes_get_double
11024 (handles[0],
"longitudeOfLastGridPointInDegrees", &last_lon));
11025 ECC(codes_get_double
11026 (handles[0],
"latitudeOfLastGridPointInDegrees", &last_lat));
11027 ECC(codes_get_double(handles[0],
"iDirectionIncrementInDegrees", &inc_lon));
11028 ECC(codes_get_double(handles[0],
"jDirectionIncrementInDegrees", &inc_lat));
11030 long jscanpos, iscanneg;
11031 ECC(codes_get_long(handles[0],
"iScansNegatively", &iscanneg));
11032 ECC(codes_get_long(handles[0],
"jScansPositively", &jscanpos));
11037 for (
double i = first_lon; i <= last_lon + 1e-6; i += inc_lon) {
11038 met->
lon[counter] = i;
11041 for (
double i = first_lon; i > last_lon - 1e-6; i -= inc_lon) {
11042 met->
lon[counter] = i;
11048 for (
double i = first_lat; i > last_lat - 1e-6; i -= inc_lat) {
11049 met->
lat[counter] = i;
11052 for (
double i = first_lat; i <= last_lat + 1e-6; i += inc_lat) {
11053 met->
lat[counter] = i;
11058 LOG(2,
"Longitudes: %g, %g ... %g deg",
11059 met->
lon[0], met->
lon[1], met->
lon[met->
nx - 1]);
11060 LOG(2,
"Latitudes: %g, %g ... %g deg",
11061 met->
lat[0], met->
lat[1], met->
lat[met->
ny - 1]);
11065 for (
int i = 0; i < count_handles; i++) {
11067 ECC(codes_get_long(handles[i],
"level", &level));
11068 if (level > max_level)
11069 max_level = (int) level;
11071 met->
npl = max_level;
11074 LOG(2,
"Number of levels: %d", met->
npl);
11075 if (met->
npl < 2 || met->
npl >
EP)
11076 ERRMSG(
"Number of levels out of range!");
11085 const int num_messages,
11091 LOG(2,
"Read level data...");
11094 int t_flag = 0, u_flag = 0, v_flag = 0, w_flag = 0, o3_flag = 0, h2o_flag =
11095 0, lwc_flag = 0, rwc_flag = 0, iwc_flag = 0, swc_flag = 0, cc_flag = 0;
11098 for (
int i = 0; i < num_messages; i++) {
11100 size_t max_size =
LEN;
11101 char short_name[max_size];
11102 size_t value_count;
11106 long current_level;
11107 ECC(codes_get_long(handles[i],
"level", ¤t_level));
11108 current_level -= 1;
11111 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
11112 ECC(codes_get_size(handles[i],
"values", &value_count));
11113 ALLOC(values,
double,
11115 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
11123 ECC_READ_3D(
"w", current_level, met->
w, 0.01f, w_flag);
11141 if (t_flag != met->
npl)
11142 ERRMSG(
"Cannot read temperature!");
11143 if (u_flag != met->
npl)
11144 ERRMSG(
"Cannot read zonal wind!");
11145 if (v_flag != met->
npl)
11146 ERRMSG(
"Cannot read meridional wind!");
11147 if (w_flag != met->
npl)
11148 WARN(
"Cannot read vertical velocity!");
11149 if (h2o_flag != met->
npl)
11150 WARN(
"Cannot read specific humidity!");
11151 if (o3_flag != met->
npl)
11152 WARN(
"Cannot read ozone data!");
11153 if (lwc_flag != met->
npl)
11154 WARN(
"Cannot read cloud liquid water content!");
11155 if (rwc_flag != met->
npl)
11156 WARN(
"Cannot read cloud rain water content!");
11157 if (iwc_flag != met->
npl)
11158 WARN(
"Cannot read cloud ice water content!");
11159 if (swc_flag != met->
npl)
11160 WARN(
"Cannot read cloud snow water content!");
11161 if (cc_flag != met->
npl)
11162 WARN(
"Cannot read cloud cover!");
11165 for (
int ix = 0; ix < met->
nx; ix++)
11166 for (
int iy = 0; iy < met->
ny; iy++)
11167 for (
int ip = 1; ip < met->
np; ip++)
11168 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
11169 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
11170 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
11171 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip])) {
11172 LOG(1,
"%f %f %f %f", met->
pl[ix][iy][0], met->
pl[ix][iy][1],
11173 met->
pl[ix][iy][ip - 1], met->
pl[ix][iy][ip]);
11174 ERRMSG(
"Pressure profiles are not monotonic!");
11195 for (
int ip = 0; ip < met->
np; ip++)
11196 met->
p[ip] = ctl->
met_p[ip];
11200 for (
int ip = 1; ip < met->
np; ip++)
11201 if (met->
p[ip - 1] < met->
p[ip])
11202 ERRMSG(
"Pressure levels must be descending!");
11211 const int num_messages,
11217 LOG(2,
"Read surface data...");
11220 int sp_flag = 0, z_flag = 0, t_flag = 0, u_flag = 0, v_flag = 0, ess_flag =
11221 0, nss_flag = 0, shf_flag = 0, lsm_flag = 0, sst_flag = 0, cape_flag = 0,
11222 cin_flag = 0, pbl_flag = 0;
11225 for (
int i = 0; i < num_messages; i++) {
11227 size_t max_size =
LEN, value_count;
11229 char short_name[max_size];
11232 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
11233 ECC(codes_get_size(handles[i],
"values", &value_count));
11234 double *values = (
double *) malloc(value_count *
sizeof(
double));
11235 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
11282 WARN(
"Cannot read surface pressure data!");
11284 WARN(
"Cannot read surface geopotential height!");
11286 WARN(
"Cannot read surface temperature!");
11288 WARN(
"Cannot read surface zonal wind!");
11290 WARN(
"Cannot read surface meridional wind!");
11292 WARN(
"Cannot read eastward turbulent surface stress!");
11294 WARN(
"Cannot read northward turbulent surface stress!");
11296 WARN(
"Cannot read surface sensible heat flux!");
11298 WARN(
"Cannot read land-sea mask!");
11300 WARN(
"Cannot read sea surface temperature!");
11302 if (cape_flag == 0)
11303 WARN(
"Cannot read CAPE!");
11305 WARN(
"Cannot read convective inhibition!");
11307 if (ctl->
met_pbl == 1 && pbl_flag == 0)
11308 WARN(
"Cannot read planetary boundary layer height!");
11318 const char *varname) {
11320 double aux[
EP], p[
EP];
11324 LOG(2,
"Interpolate meteo data to pressure levels: %s", varname);
11327#pragma omp parallel for default(shared) private(aux,p) collapse(2)
11328 for (
int ix = 0; ix < met->
nx; ix++)
11329 for (
int iy = 0; iy < met->
ny; iy++) {
11332 for (
int ip = 0; ip < met->
np; ip++)
11333 p[ip] = met->
pl[ix][iy][ip];
11336 for (
int ip = 0; ip < ctl->
met_np; ip++) {
11337 double pt = ctl->
met_p[ip];
11338 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
11340 else if ((pt > p[met->
np - 1] && p[1] > p[0])
11341 || (pt < p[met->
np - 1] && p[1] < p[0]))
11342 pt = p[met->
np - 1];
11344 aux[ip] =
LIN(p[ip2], var[ix][iy][ip2],
11345 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
11349 for (
int ip = 0; ip < ctl->
met_np; ip++)
11350 var[ix][iy][ip] = (
float) aux[ip];
11366 LOG(2,
"Make zeta profiles monotone...");
11369#pragma omp parallel for default(shared) collapse(2)
11370 for (
int i = 0; i < met->
nx; i++)
11371 for (
int j = 0; j < met->
ny; j++) {
11374 while (k < met->npl) {
11375 if ((met->
zetal[i][j][k - 1] >= met->
zetal[i][j][k])) {
11381 while ((met->
zetal[i][j][k - 1] >=
11382 met->
zetal[i][j][k + l]) & (k + l < met->npl));
11387 (float) (met->
zetal[i][j][k + l] - met->
zetal[i][j][k - 1])
11390 for (
int m = k; m < k + l; m++) {
11391 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
11392 met->
zetal[i][j][m] = s * d + met->
zetal[i][j][k - 1];
11404#pragma omp parallel for default(shared) collapse(2)
11405 for (
int i = 0; i < met->
nx; i++)
11406 for (
int j = 0; j < met->
ny; j++) {
11409 while (k < met->npl) {
11410 if ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k])) {
11417 while ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k + l]) & (k + l <
11422 float s = (float) (met->
pl[i][j][k + l] - met->
pl[i][j][k - 1])
11425 for (
int m = k; m < k + l; m++) {
11426 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
11427 met->
pl[i][j][m] = s * d + met->
pl[i][j][k - 1];
11442 const char *filename,
11453 (filename, NC_NOWRITE | NC_SHARE, MPI_COMM_WORLD, MPI_INFO_NULL,
11457 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
11458 WARN(
"Cannot open file!");
11476 NC(nc_close(ncid));
11493 int rank = 0, size = 1;
11495 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
11496 MPI_Comm_size(MPI_COMM_WORLD, &size);
11503 LOG(2,
"Number of longitudes: %d", dd->
nx_glob);
11504 LOG(2,
"Number of latitudes: %d", dd->
ny_glob);
11508 ERRMSG(
"Global grid is too large!");
11511 ERRMSG(
"Too many zonal subdomains for global x grid!");
11514 ERRMSG(
"Too many meridional subdomains for global y grid!");
11520 LOG(2,
"Longitudes: %g, %g ... %g deg",
11522 LOG(2,
"Latitudes: %g, %g ... %g deg",
11530 const int left = (zonal_rank == 0);
11532 const int top = (merid_rank == 0);
11539 const int ix0 = zonal_rank * nx_block;
11540 const int iy0 = merid_rank * ny_block;
11542 int nx_core = nx_block;
11543 int ny_core = ny_block;
11566 if (!left && !right) {
11569 }
else if (left ^ right) {
11575 if (!top && !bottom) {
11578 }
else if (top ^ bottom) {
11585 double lon_shift = 0.0;
11587 if (left ^ right) {
11603 lon_shift = left ? -360.0 : 360.0;
11636 LOG(2,
"Define subdomain properties.");
11637 LOG(2,
"MPI information: Rank %d, Size %d", rank, size);
11638 LOG(2,
"Edge position: l=%d,r=%d,t=%d,b=%d", left, right, top, bottom);
11639 LOG(2,
"Total size for subdomain meteo data: nx %d ny %d np %d",
11640 met->
nx, met->
ny, met->
np);
11641 LOG(2,
"Hyperslab sizes for boundary halos: nx %d ny %d np %d",
11644 LOG(2,
"Hyperslab sizes for subdomain and inner halos: nx %d ny %d np %d",
11647 LOG(2,
"Subdomain start: nx %ld ny %ld np %ld",
11649 LOG(2,
"Boundary halo start: nx %ld ny %ld np %ld",
11652 LOG(2,
"%d Subdomain longitudes: %g, %g ... %g deg",
11653 rank, met->
lon[0], met->
lon[1], met->
lon[met->
nx - 1]);
11654 LOG(2,
"%d Subdomain latitudes: %g, %g ... %g deg",
11655 rank, met->
lat[0], met->
lat[1], met->
lat[met->
ny - 1]);
11666 LOG(2,
"Calculate planetary boundary layer...");
11672#pragma omp parallel for default(shared) collapse(2)
11673 for (
int ix = 0; ix < met->
nx; ix++)
11674 for (
int iy = 0; iy < met->
ny; iy++) {
11677 const float z = met->
zs[ix][iy] + met->
pbl[ix][iy];
11680 (float) (
LIN(met->
z[ix][iy][ip], met->
p[ip],
11681 met->
z[ix][iy][ip + 1], met->
p[ip + 1], z));
11686 else if (ctl->
met_pbl == 2) {
11690 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
11693#pragma omp parallel for default(shared) collapse(2)
11694 for (
int ix = 0; ix < met->
nx; ix++)
11695 for (
int iy = 0; iy < met->
ny; iy++) {
11698 const double pbl_bot = met->
ps[ix][iy] * exp(-dz /
H0);
11702 for (ip = 1; ip < met->
np; ip++)
11703 if (met->
p[ip] < pbl_bot)
11707 const double h2os =
LIN(met->
p[ip - 1], met->
h2o[ix][iy][ip - 1],
11708 met->
p[ip], met->
h2o[ix][iy][ip], pbl_bot);
11709 const double tvs =
THETAVIRT(pbl_bot, met->
ts[ix][iy], h2os);
11712 double rib_old = 0;
11715 for (; ip < met->
np; ip++) {
11718 double vh2 =
SQR(met->
u[ix][iy][ip] - met->
us[ix][iy])
11719 +
SQR(met->
v[ix][iy][ip] - met->
vs[ix][iy]);
11720 vh2 =
MAX(vh2,
SQR(umin));
11724 G0 * 1e3 * (met->
z[ix][iy][ip] - met->
zs[ix][iy]) / tvs
11726 met->
h2o[ix][iy][ip]) - tvs) / vh2;
11729 if (rib >= rib_crit) {
11730 met->
pbl[ix][iy] = (float) (
LIN(rib_old, met->
p[ip - 1],
11731 rib, met->
p[ip], rib_crit));
11732 if (met->
pbl[ix][iy] > pbl_bot)
11733 met->
pbl[ix][iy] = (float) pbl_bot;
11748 const double dtheta = 2.0, zmin = 0.1;
11751#pragma omp parallel for default(shared) collapse(2)
11752 for (
int ix = 0; ix < met->
nx; ix++)
11753 for (
int iy = 0; iy < met->
ny; iy++) {
11756 const double theta0 =
THETA(met->
ps[ix][iy], met->
ts[ix][iy]);
11760 for (ip = met->
np - 2; ip > 0; ip--)
11761 if (met->
p[ip] >= 300.)
11762 if (met->
p[ip] > met->
ps[ix][iy]
11763 ||
THETA(met->
p[ip], met->
t[ix][iy][ip]) <= theta0 + dtheta)
11768 = (float) (
LIN(
THETA(met->
p[ip + 1], met->
t[ix][iy][ip + 1]),
11770 THETA(met->
p[ip], met->
t[ix][iy][ip]),
11771 met->
p[ip], theta0 + dtheta));
11774 double pbl_min = met->
ps[ix][iy] * exp(-zmin /
H0);
11775 if (met->
pbl[ix][iy] > pbl_min || met->
p[ip] > met->
ps[ix][iy])
11776 met->
pbl[ix][iy] = (float) pbl_min;
11781#pragma omp parallel for default(shared) collapse(2)
11782 for (
int ix = 0; ix < met->
nx; ix++)
11783 for (
int iy = 0; iy < met->
ny; iy++) {
11787 met->
pbl[ix][iy] =
MIN(met->
pbl[ix][iy], (
float) pbl_min);
11791 met->
pbl[ix][iy] =
MAX(met->
pbl[ix][iy], (
float) pbl_max);
11802 LOG(2,
"Apply periodic boundary conditions...");
11805 if (!(fabs(met->
lon[met->
nx - 1] - met->
lon[0]
11806 + met->
lon[1] - met->
lon[0] - 360) < 0.01))
11810 if ((++met->
nx) >=
EX)
11811 ERRMSG(
"Cannot create periodic boundary conditions!");
11814 met->
lon[met->
nx - 1] = met->
lon[met->
nx - 2] + met->
lon[1] - met->
lon[0];
11817#pragma omp parallel for default(shared)
11818 for (
int iy = 0; iy < met->
ny; iy++) {
11819 met->
ps[met->
nx - 1][iy] = met->
ps[0][iy];
11820 met->
zs[met->
nx - 1][iy] = met->
zs[0][iy];
11821 met->
ts[met->
nx - 1][iy] = met->
ts[0][iy];
11822 met->
us[met->
nx - 1][iy] = met->
us[0][iy];
11823 met->
vs[met->
nx - 1][iy] = met->
vs[0][iy];
11824 met->
ess[met->
nx - 1][iy] = met->
ess[0][iy];
11825 met->
nss[met->
nx - 1][iy] = met->
nss[0][iy];
11826 met->
shf[met->
nx - 1][iy] = met->
shf[0][iy];
11827 met->
lsm[met->
nx - 1][iy] = met->
lsm[0][iy];
11828 met->
sst[met->
nx - 1][iy] = met->
sst[0][iy];
11829 met->
pbl[met->
nx - 1][iy] = met->
pbl[0][iy];
11830 met->
cape[met->
nx - 1][iy] = met->
cape[0][iy];
11831 met->
cin[met->
nx - 1][iy] = met->
cin[0][iy];
11832 for (
int ip = 0; ip < met->
np; ip++) {
11833 met->
t[met->
nx - 1][iy][ip] = met->
t[0][iy][ip];
11834 met->
u[met->
nx - 1][iy][ip] = met->
u[0][iy][ip];
11835 met->
v[met->
nx - 1][iy][ip] = met->
v[0][iy][ip];
11836 met->
w[met->
nx - 1][iy][ip] = met->
w[0][iy][ip];
11837 met->
h2o[met->
nx - 1][iy][ip] = met->
h2o[0][iy][ip];
11838 met->
o3[met->
nx - 1][iy][ip] = met->
o3[0][iy][ip];
11839 met->
lwc[met->
nx - 1][iy][ip] = met->
lwc[0][iy][ip];
11840 met->
rwc[met->
nx - 1][iy][ip] = met->
rwc[0][iy][ip];
11841 met->
iwc[met->
nx - 1][iy][ip] = met->
iwc[0][iy][ip];
11842 met->
swc[met->
nx - 1][iy][ip] = met->
swc[0][iy][ip];
11843 met->
cc[met->
nx - 1][iy][ip] = met->
cc[0][iy][ip];
11845 for (
int ip = 0; ip < met->
npl; ip++) {
11846 met->
ul[met->
nx - 1][iy][ip] = met->
ul[0][iy][ip];
11847 met->
vl[met->
nx - 1][iy][ip] = met->
vl[0][iy][ip];
11848 met->
wl[met->
nx - 1][iy][ip] = met->
wl[0][iy][ip];
11849 met->
pl[met->
nx - 1][iy][ip] = met->
pl[0][iy][ip];
11850 met->
zetal[met->
nx - 1][iy][ip] = met->
zetal[0][iy][ip];
11863 LOG(2,
"Apply fix for polar winds...");
11869 if (fabs(met->
lat[0]) < 89.999 || fabs(met->
lat[met->
ny - 1]) < 89.999)
11873 for (
int ihem = 0; ihem < 2; ihem++) {
11876 int i89 = 1, i90 = 0, sign = 1;
11881 if (met->
lat[i90] < 0)
11885 double clon[
EX], slon[
EX];
11886#pragma omp parallel for default(shared)
11887 for (
int ix = 0; ix < met->
nx; ix++) {
11888 clon[ix] = cos(sign *
DEG2RAD(met->
lon[ix]));
11889 slon[ix] = sin(sign *
DEG2RAD(met->
lon[ix]));
11893#pragma omp parallel for default(shared)
11894 for (
int ip = 0; ip < met->
np; ip++) {
11897 double vel89x = 0, vel89y = 0;
11898 for (
int ix = 0; ix < met->
nx; ix++) {
11900 (met->
u[ix][i89][ip] * clon[ix] -
11901 met->
v[ix][i89][ip] * slon[ix]) / met->
nx;
11903 (met->
u[ix][i89][ip] * slon[ix] +
11904 met->
v[ix][i89][ip] * clon[ix]) / met->
nx;
11908 for (
int ix = 0; ix < met->
nx; ix++) {
11909 met->
u[ix][i90][ip]
11910 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
11911 met->
v[ix][i90][ip]
11912 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
11927 LOG(2,
"Calculate potential vorticity...");
11930#pragma omp parallel for default(shared)
11931 for (
int ip = 0; ip < met->
np; ip++)
11932 pows[ip] = pow(1000. / met->
p[ip],
KAPPA);
11935#pragma omp parallel for default(shared)
11936 for (
int ix = 0; ix < met->
nx; ix++) {
11939 const int ix0 =
MAX(ix - 1, 0);
11940 const int ix1 =
MIN(ix + 1, met->
nx - 1);
11943 for (
int iy = 0; iy < met->
ny; iy++) {
11946 const int iy0 =
MAX(iy - 1, 0);
11947 const int iy1 =
MIN(iy + 1, met->
ny - 1);
11950 const double latr = 0.5 * (met->
lat[iy1] + met->
lat[iy0]);
11951 double dx, dy, c0, c1, cr, vort;
11955 dx = 1000. *
DEG2DX(met->
lon[ix1] - met->
lon[ix0], latr);
11962 dx = met->
lon[ix1] - met->
lon[ix0];
11963 dy = met->
lat[iy1] - met->
lat[iy0];
11973 for (
int ip = 0; ip < met->
np; ip++) {
11977 = (met->
t[ix1][iy][ip] - met->
t[ix0][iy][ip]) * pows[ip] / dx;
11978 const double dvdx = (met->
v[ix1][iy][ip] - met->
v[ix0][iy][ip]) / dx;
11982 = (met->
t[ix][iy1][ip] - met->
t[ix][iy0][ip]) * pows[ip] / dy;
11984 = (met->
u[ix][iy1][ip] * c1 - met->
u[ix][iy0][ip] * c0) / dy;
11987 const int ip0 =
MAX(ip - 1, 0);
11988 const int ip1 =
MIN(ip + 1, met->
np - 1);
11991 double dtdp, dudp, dvdp;
11992 const double dp0 = 100. * (met->
p[ip] - met->
p[ip0]);
11993 const double dp1 = 100. * (met->
p[ip1] - met->
p[ip]);
11994 if (ip != ip0 && ip != ip1) {
11995 double denom = dp0 * dp1 * (dp0 + dp1);
11996 dtdp = (dp0 * dp0 * met->
t[ix][iy][ip1] * pows[ip1]
11997 - dp1 * dp1 * met->
t[ix][iy][ip0] * pows[ip0]
11998 + (dp1 * dp1 - dp0 * dp0) * met->
t[ix][iy][ip] * pows[ip])
12000 dudp = (dp0 * dp0 * met->
u[ix][iy][ip1]
12001 - dp1 * dp1 * met->
u[ix][iy][ip0]
12002 + (dp1 * dp1 - dp0 * dp0) * met->
u[ix][iy][ip])
12004 dvdp = (dp0 * dp0 * met->
v[ix][iy][ip1]
12005 - dp1 * dp1 * met->
v[ix][iy][ip0]
12006 + (dp1 * dp1 - dp0 * dp0) * met->
v[ix][iy][ip])
12009 const double denom = dp0 + dp1;
12011 (met->
t[ix][iy][ip1] * pows[ip1] -
12012 met->
t[ix][iy][ip0] * pows[ip0]) / denom;
12013 dudp = (met->
u[ix][iy][ip1] - met->
u[ix][iy][ip0]) / denom;
12014 dvdp = (met->
v[ix][iy][ip1] - met->
v[ix][iy][ip0]) / denom;
12018 met->
pv[ix][iy][ip] = (float)
12020 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
12026#pragma omp parallel for default(shared)
12027 for (
int ix = 0; ix < met->
nx; ix++)
12028 for (
int ip = 0; ip < met->
np; ip++) {
12030 = met->
pv[ix][1][ip]
12031 = met->
pv[ix][2][ip];
12032 met->
pv[ix][met->
ny - 1][ip]
12033 = met->
pv[ix][met->
ny - 2][ip]
12034 = met->
pv[ix][met->
ny - 3][ip];
12045 LOG(2,
"Calculate total column ozone...");
12048#pragma omp parallel for default(shared) collapse(2)
12049 for (
int ix = 0; ix < met->
nx; ix++)
12050 for (
int iy = 0; iy < met->
ny; iy++) {
12054 for (
int ip = 1; ip < met->
np; ip++)
12055 if (met->
p[ip - 1] <= met->
ps[ix][iy]) {
12057 0.5 * (met->
o3[ix][iy][ip - 1] + met->
o3[ix][iy][ip]);
12058 const double dp = met->
p[ip - 1] - met->
p[ip];
12059 cd += vmr *
MO3 /
MA * dp * 1e2 /
G0;
12082 LOG(2,
"Downsampling of meteo data...");
12088 help->
nx = met->
nx;
12089 help->
ny = met->
ny;
12090 help->
np = met->
np;
12091 memcpy(help->
lon, met->
lon,
sizeof(met->
lon));
12092 memcpy(help->
lat, met->
lat,
sizeof(met->
lat));
12093 memcpy(help->
p, met->
p,
sizeof(met->
p));
12096 for (
int ix = 0; ix < met->
nx; ix += ctl->
met_dx) {
12097 for (
int iy = 0; iy < met->
ny; iy += ctl->
met_dy) {
12098 for (
int ip = 0; ip < met->
np; ip += ctl->
met_dp) {
12099 help->
ps[ix][iy] = 0;
12100 help->
zs[ix][iy] = 0;
12101 help->
ts[ix][iy] = 0;
12102 help->
us[ix][iy] = 0;
12103 help->
vs[ix][iy] = 0;
12104 help->
ess[ix][iy] = 0;
12105 help->
nss[ix][iy] = 0;
12106 help->
shf[ix][iy] = 0;
12107 help->
lsm[ix][iy] = 0;
12108 help->
sst[ix][iy] = 0;
12109 help->
pbl[ix][iy] = 0;
12110 help->
cape[ix][iy] = 0;
12111 help->
cin[ix][iy] = 0;
12112 help->
t[ix][iy][ip] = 0;
12113 help->
u[ix][iy][ip] = 0;
12114 help->
v[ix][iy][ip] = 0;
12115 help->
w[ix][iy][ip] = 0;
12116 help->
h2o[ix][iy][ip] = 0;
12117 help->
o3[ix][iy][ip] = 0;
12118 help->
lwc[ix][iy][ip] = 0;
12119 help->
rwc[ix][iy][ip] = 0;
12120 help->
iwc[ix][iy][ip] = 0;
12121 help->
swc[ix][iy][ip] = 0;
12122 help->
cc[ix][iy][ip] = 0;
12124 for (
int ix2 = ix - ctl->
met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
12129 else if (ix3 >= met->
nx)
12132 for (
int iy2 =
MAX(iy - ctl->
met_sy + 1, 0);
12133 iy2 <=
MIN(iy + ctl->
met_sy - 1, met->
ny - 1); iy2++)
12134 for (
int ip2 =
MAX(ip - ctl->
met_sp + 1, 0);
12135 ip2 <=
MIN(ip + ctl->
met_sp - 1, met->
np - 1); ip2++) {
12137 (1.0f - (float) abs(ix - ix2) / (float) ctl->
met_sx)
12138 * (1.0f - (float) abs(iy - iy2) / (float) ctl->
met_sy)
12139 * (1.0f - (float) abs(ip - ip2) / (float) ctl->
met_sp);
12140 help->
ps[ix][iy] += w * met->
ps[ix3][iy2];
12141 help->
zs[ix][iy] += w * met->
zs[ix3][iy2];
12142 help->
ts[ix][iy] += w * met->
ts[ix3][iy2];
12143 help->
us[ix][iy] += w * met->
us[ix3][iy2];
12144 help->
vs[ix][iy] += w * met->
vs[ix3][iy2];
12145 help->
ess[ix][iy] += w * met->
ess[ix3][iy2];
12146 help->
nss[ix][iy] += w * met->
nss[ix3][iy2];
12147 help->
shf[ix][iy] += w * met->
shf[ix3][iy2];
12148 help->
lsm[ix][iy] += w * met->
lsm[ix3][iy2];
12149 help->
sst[ix][iy] += w * met->
sst[ix3][iy2];
12150 help->
pbl[ix][iy] += w * met->
pbl[ix3][iy2];
12151 help->
cape[ix][iy] += w * met->
cape[ix3][iy2];
12152 help->
cin[ix][iy] += w * met->
cin[ix3][iy2];
12153 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip2];
12154 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip2];
12155 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip2];
12156 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip2];
12157 help->
h2o[ix][iy][ip] += w * met->
h2o[ix3][iy2][ip2];
12158 help->
o3[ix][iy][ip] += w * met->
o3[ix3][iy2][ip2];
12159 help->
lwc[ix][iy][ip] += w * met->
lwc[ix3][iy2][ip2];
12160 help->
rwc[ix][iy][ip] += w * met->
rwc[ix3][iy2][ip2];
12161 help->
iwc[ix][iy][ip] += w * met->
iwc[ix3][iy2][ip2];
12162 help->
swc[ix][iy][ip] += w * met->
swc[ix3][iy2][ip2];
12163 help->
cc[ix][iy][ip] += w * met->
cc[ix3][iy2][ip2];
12167 help->
ps[ix][iy] /= wsum;
12168 help->
zs[ix][iy] /= wsum;
12169 help->
ts[ix][iy] /= wsum;
12170 help->
us[ix][iy] /= wsum;
12171 help->
vs[ix][iy] /= wsum;
12172 help->
ess[ix][iy] /= wsum;
12173 help->
nss[ix][iy] /= wsum;
12174 help->
shf[ix][iy] /= wsum;
12175 help->
lsm[ix][iy] /= wsum;
12176 help->
sst[ix][iy] /= wsum;
12177 help->
pbl[ix][iy] /= wsum;
12178 help->
cape[ix][iy] /= wsum;
12179 help->
cin[ix][iy] /= wsum;
12180 help->
t[ix][iy][ip] /= wsum;
12181 help->
u[ix][iy][ip] /= wsum;
12182 help->
v[ix][iy][ip] /= wsum;
12183 help->
w[ix][iy][ip] /= wsum;
12184 help->
h2o[ix][iy][ip] /= wsum;
12185 help->
o3[ix][iy][ip] /= wsum;
12186 help->
lwc[ix][iy][ip] /= wsum;
12187 help->
rwc[ix][iy][ip] /= wsum;
12188 help->
iwc[ix][iy][ip] /= wsum;
12189 help->
swc[ix][iy][ip] /= wsum;
12190 help->
cc[ix][iy][ip] /= wsum;
12197 for (
int ix = 0; ix < help->
nx; ix += ctl->
met_dx) {
12198 met->
lon[met->
nx] = help->
lon[ix];
12200 for (
int iy = 0; iy < help->
ny; iy += ctl->
met_dy) {
12201 met->
lat[met->
ny] = help->
lat[iy];
12202 met->
ps[met->
nx][met->
ny] = help->
ps[ix][iy];
12203 met->
zs[met->
nx][met->
ny] = help->
zs[ix][iy];
12204 met->
ts[met->
nx][met->
ny] = help->
ts[ix][iy];
12205 met->
us[met->
nx][met->
ny] = help->
us[ix][iy];
12206 met->
vs[met->
nx][met->
ny] = help->
vs[ix][iy];
12207 met->
ess[met->
nx][met->
ny] = help->
ess[ix][iy];
12208 met->
nss[met->
nx][met->
ny] = help->
nss[ix][iy];
12209 met->
shf[met->
nx][met->
ny] = help->
shf[ix][iy];
12210 met->
lsm[met->
nx][met->
ny] = help->
lsm[ix][iy];
12211 met->
sst[met->
nx][met->
ny] = help->
sst[ix][iy];
12212 met->
pbl[met->
nx][met->
ny] = help->
pbl[ix][iy];
12214 met->
cin[met->
nx][met->
ny] = help->
cin[ix][iy];
12216 for (
int ip = 0; ip < help->
np; ip += ctl->
met_dp) {
12217 met->
p[met->
np] = help->
p[ip];
12218 met->
t[met->
nx][met->
ny][met->
np] = help->
t[ix][iy][ip];
12219 met->
u[met->
nx][met->
ny][met->
np] = help->
u[ix][iy][ip];
12220 met->
v[met->
nx][met->
ny][met->
np] = help->
v[ix][iy][ip];
12221 met->
w[met->
nx][met->
ny][met->
np] = help->
w[ix][iy][ip];
12222 met->
h2o[met->
nx][met->
ny][met->
np] = help->
h2o[ix][iy][ip];
12223 met->
o3[met->
nx][met->
ny][met->
np] = help->
o3[ix][iy][ip];
12224 met->
lwc[met->
nx][met->
ny][met->
np] = help->
lwc[ix][iy][ip];
12225 met->
rwc[met->
nx][met->
ny][met->
np] = help->
rwc[ix][iy][ip];
12226 met->
iwc[met->
nx][met->
ny][met->
np] = help->
iwc[ix][iy][ip];
12227 met->
swc[met->
nx][met->
ny][met->
np] = help->
swc[ix][iy][ip];
12228 met->
cc[met->
nx][met->
ny][met->
np] = help->
cc[ix][iy][ip];
12247 double p2[200], pv[
EP], pv2[200], t[
EP], t2[200], th[
EP],
12248 th2[200], z[
EP], z2[200];
12252 LOG(2,
"Calculate tropopause...");
12255#pragma omp parallel for default(shared)
12256 for (
int iz = 0; iz < met->
np; iz++)
12257 z[iz] =
Z(met->
p[iz]);
12258#pragma omp parallel for default(shared)
12259 for (
int iz = 0; iz <= 190; iz++) {
12260 z2[iz] = 4.5 + 0.1 * iz;
12261 p2[iz] =
P(z2[iz]);
12266#pragma omp parallel for default(shared) collapse(2)
12267 for (
int ix = 0; ix < met->
nx; ix++)
12268 for (
int iy = 0; iy < met->
ny; iy++)
12269 met->
pt[ix][iy] = NAN;
12274 ERRMSG(
"Only lat/lon grid supported");
12275#pragma omp parallel for default(shared) collapse(2)
12276 for (
int ix = 0; ix < met->
nx; ix++)
12277 for (
int iy = 0; iy < met->
ny; iy++)
12285#pragma omp parallel for default(shared) private(t,t2) collapse(2)
12286 for (
int ix = 0; ix < met->
nx; ix++)
12287 for (
int iy = 0; iy < met->
ny; iy++) {
12290 for (
int iz = 0; iz < met->
np; iz++)
12291 t[iz] = met->
t[ix][iy][iz];
12295 int iz = (int) gsl_stats_min_index(t2, 1, 171);
12296 if (iz > 0 && iz < 170)
12297 met->
pt[ix][iy] = (float) p2[iz];
12299 met->
pt[ix][iy] = NAN;
12307#pragma omp parallel for default(shared) private(t,t2) collapse(2)
12308 for (
int ix = 0; ix < met->
nx; ix++)
12309 for (
int iy = 0; iy < met->
ny; iy++) {
12313 for (iz = 0; iz < met->
np; iz++)
12314 t[iz] = met->
t[ix][iy][iz];
12318 met->
pt[ix][iy] = NAN;
12319 for (iz = 0; iz <= 170; iz++) {
12321 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
12322 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
12327 if (iz > 0 && iz < 170)
12328 met->
pt[ix][iy] = (float) p2[iz];
12335 met->
pt[ix][iy] = NAN;
12336 for (; iz <= 170; iz++) {
12338 for (
int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
12339 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
12346 for (; iz <= 170; iz++) {
12348 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
12349 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
12354 if (iz > 0 && iz < 170)
12355 met->
pt[ix][iy] = (float) p2[iz];
12367#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
12368 for (
int ix = 0; ix < met->
nx; ix++)
12369 for (
int iy = 0; iy < met->
ny; iy++) {
12372 for (
int iz = 0; iz < met->
np; iz++)
12373 pv[iz] = met->
pv[ix][iy][iz];
12377 for (
int iz = 0; iz < met->
np; iz++)
12378 th[iz] =
THETA(met->
p[iz], met->
t[ix][iy][iz]);
12382 met->
pt[ix][iy] = NAN;
12383 for (
int iz = 0; iz <= 170; iz++)
12386 if (iz > 0 && iz < 170)
12387 met->
pt[ix][iy] = (float) p2[iz];
12394 ERRMSG(
"Cannot calculate tropopause!");
12397#pragma omp parallel for default(shared) collapse(2)
12398 for (
int ix = 0; ix < met->
nx; ix++)
12399 for (
int iy = 0; iy < met->
ny; iy++) {
12400 double h2ot, tt, zt;
12403 met->
lat[iy], &tt, ci, cw, 1);
12405 met->
lat[iy], &zt, ci, cw, 0);
12407 met->
lat[iy], &h2ot, ci, cw, 0);
12408 met->
tt[ix][iy] = (float) tt;
12409 met->
zt[ix][iy] = (float) zt;
12410 met->
h2ot[ix][iy] = (float) h2ot;
12417 const char *filename,
12427 LOG(1,
"Read observation data: %s", filename);
12431 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
12433 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
12435 ERRMSG(
"Set OBS_TYPE to 0 or 1!");
12438 for (
int i = 1; i < *nobs; i++)
12439 if (rt[i] < rt[i - 1])
12440 ERRMSG(
"Time must be ascending!");
12445 LOG(2,
"Number of observations: %d", *nobs);
12446 gsl_stats_minmax(&mini, &maxi, rt, 1, (
size_t) n);
12447 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
12448 gsl_stats_minmax(&mini, &maxi, rz, 1, (
size_t) n);
12449 LOG(2,
"Altitude range: %g ... %g km", mini, maxi);
12450 gsl_stats_minmax(&mini, &maxi, rlon, 1, (
size_t) n);
12451 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
12452 gsl_stats_minmax(&mini, &maxi, rlat, 1, (
size_t) n);
12453 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
12454 gsl_stats_minmax(&mini, &maxi, robs, 1, (
size_t) n);
12455 LOG(2,
"Observation range: %g ... %g", mini, maxi);
12461 const char *filename,
12471 if (!(in = fopen(filename,
"r")))
12472 ERRMSG(
"Cannot open file!");
12476 while (fgets(line,
LEN, in))
12477 if (sscanf(line,
"%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
12478 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
12479 if ((++(*nobs)) >=
NOBS)
12480 ERRMSG(
"Too many observations!");
12489 const char *filename,
12500 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
12501 ERRMSG(
"Cannot open file!");
12512 NC(nc_close(ncid));
12518 const char *filename,
12521 const char *varname,
12523 const char *defvalue,
12528 char fullname1[
LEN], fullname2[
LEN], rval[
LEN];
12530 int contain = 0, i;
12533 if (filename[strlen(filename) - 1] !=
'-')
12534 if (!(in = fopen(filename,
"r")))
12535 ERRMSG(
"Cannot open file!");
12539 sprintf(fullname1,
"%s[%d]", varname, arridx);
12540 sprintf(fullname2,
"%s[*]", varname);
12542 sprintf(fullname1,
"%s", varname);
12543 sprintf(fullname2,
"%s", varname);
12548 char dummy[
LEN], line[
LEN], rvarname[
LEN];
12549 while (fgets(line,
LEN, in)) {
12550 if (sscanf(line,
"%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
12551 if (strcasecmp(rvarname, fullname1) == 0 ||
12552 strcasecmp(rvarname, fullname2) == 0) {
12558 for (i = 1; i < argc - 1; i++)
12559 if (strcasecmp(argv[i], fullname1) == 0 ||
12560 strcasecmp(argv[i], fullname2) == 0) {
12561 sprintf(rval,
"%s", argv[i + 1]);
12572 if (strlen(defvalue) > 0)
12573 sprintf(rval,
"%s", defvalue);
12575 ERRMSG(
"Missing variable %s!\n", fullname1);
12579 LOG(1,
"%s = %s", fullname1, rval);
12583 sprintf(value,
"%s", rval);
12593 const double rhop) {
12596 const double rp_help = rp * 1e-6;
12599 const double rho =
RHO(p, T);
12602 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
12608 const double lambda = 2. * eta / (rho * v);
12611 const double K = lambda / rp_help;
12614 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
12617 return 2. *
SQR(rp_help) * (rhop - rho) *
G0 / (9. * eta) * G;
12629 const int method) {
12635 gsl_interp_accel *acc = gsl_interp_accel_alloc();
12636 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (
size_t) n);
12639 gsl_spline_init(s, x, y, (
size_t) n);
12640 for (
int i = 0; i < n2; i++)
12643 else if (x2[i] >= x[n - 1])
12646 y2[i] = gsl_spline_eval(s, x2[i], acc);
12649 gsl_spline_free(s);
12650 gsl_interp_accel_free(acc);
12655 for (
int i = 0; i < n2; i++)
12658 else if (x2[i] >= x[n - 1])
12662 y2[i] =
LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
12676 float mean = 0, var = 0;
12678 for (
int i = 0; i < n; ++i) {
12680 var +=
SQR(data[i]);
12683 var = var / (float) n -
SQR(mean / (
float) n);
12685 return (var > 0 ? sqrtf(var) : 0);
12697 const double remain,
12709 t1.tm_year = year - 1900;
12710 t1.tm_mon = mon - 1;
12716 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
12724 const int output) {
12731 static int iname = -1, igroup = -1, nname, ngroup, ct_name[
NTIMER];
12734 t1 = omp_get_wtime();
12739 rt_name[iname] += dt;
12740 rt_min[iname] = (ct_name[iname] <= 0 ? dt :
MIN(rt_min[iname], dt));
12741 rt_max[iname] = (ct_name[iname] <= 0 ? dt :
MAX(rt_max[iname], dt));
12745 rt_group[igroup] += t1 - t0;
12749 for (
int i = 0; i < nname; i++)
12750 LOG(1,
"TIMER_%s = %.3f s (min= %g s, mean= %g s,"
12751 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
12752 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
12753 for (
int i = 0; i < ngroup; i++)
12754 LOG(1,
"TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
12755 double total = 0.0;
12756 for (
int i = 0; i < nname; i++)
12757 total += rt_name[i];
12758 LOG(1,
"TIMER_TOTAL = %.3f s", total);
12762 for (iname = 0; iname < nname; iname++)
12763 if (strcasecmp(name, names[iname]) == 0)
12765 for (igroup = 0; igroup < ngroup; igroup++)
12766 if (strcasecmp(group, groups[igroup]) == 0)
12770 if (iname >= nname) {
12771 sprintf(names[iname],
"%s", name);
12772 if ((++nname) >=
NTIMER)
12773 ERRMSG(
"Too many timers!");
12777 if (igroup >= ngroup) {
12778 sprintf(groups[igroup],
"%s", group);
12779 if ((++ngroup) >=
NTIMER)
12780 ERRMSG(
"Too many groups!");
12790 const char *filename,
12792 const int with_seconds) {
12799 int len = (int) strlen(filename);
12800 sprintf(tstr,
"%.4s", &filename[len - offset]);
12801 int year = atoi(tstr);
12802 sprintf(tstr,
"%.2s", &filename[len - offset + 5]);
12803 int mon = atoi(tstr);
12804 sprintf(tstr,
"%.2s", &filename[len - offset + 8]);
12805 int day = atoi(tstr);
12806 sprintf(tstr,
"%.2s", &filename[len - offset + 11]);
12807 int hour = atoi(tstr);
12808 sprintf(tstr,
"%.2s", &filename[len - offset + 14]);
12809 int min = atoi(tstr);
12812 if (with_seconds) {
12813 sprintf(tstr,
"%.2s", &filename[len - offset + 17]);
12818 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
12819 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
12820 ERRMSG(
"Cannot read time from filename!");
12823 time2jsec(year, mon, day, hour, min, sec, 0.0, &t);
12843 const double p1 = pt * 0.866877899;
12844 const double p0 = pt / 0.866877899;
12847 if (atm->
p[ip] > p0)
12849 else if (atm->
p[ip] < p1)
12852 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
12858 const char *filename,
12866 const double t0 = t - 0.5 * ctl->
dt_mod;
12867 const double t1 = t + 0.5 * ctl->
dt_mod;
12873 if (!(out = popen(
"gnuplot",
"w")))
12874 ERRMSG(
"Cannot create pipe to gnuplot!");
12877 fprintf(out,
"set out \"%s.png\"\n", filename);
12881 int year, mon, day, hour, min, sec;
12882 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
12883 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
12884 year, mon, day, hour, min);
12889 ERRMSG(
"Cannot open file!");
12891 while (fgets(line,
LEN, in))
12892 fprintf(out,
"%s", line);
12899 if (!(out = fopen(filename,
"w")))
12900 ERRMSG(
"Cannot create file!");
12907 "# $1 = time [s]\n"
12908 "# $2 = altitude [km]\n"
12909 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
12912 "# $1 = time [s]\n"
12913 "# $2 = altitude [km]\n" "# $3 = x [m]\n" "# $4 = y [m]\n");
12916 for (
int iq = 0; iq < ctl->
nq; iq++)
12917 fprintf(out,
"# $%i = %s [%s]\n", iq + 5, ctl->
qnt_name[iq],
12919 fprintf(out,
"\n");
12922 for (
int ip = 0; ip < atm->
np; ip += ctl->
atm_stride) {
12930 fprintf(out,
"%.2f %g %g %g",
12931 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]
12934 fprintf(out,
"%.2f %g %.2f %.2f",
12935 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]
12939 for (
int iq = 0; iq < ctl->
nq; iq++) {
12944 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
12946 fprintf(out,
"\n");
12956 const char *filename,
12958 const atm_t *atm) {
12963 if (!(out = fopen(filename,
"w")))
12964 ERRMSG(
"Cannot create file!");
12988 for (
int iq = 0; iq < ctl->
nq; iq++)
13006 const char *filename,
13008 const atm_t *atm) {
13011 ERRMSG(
"CLaMS atmospheric files support only lat/lon grids");
13013 int tid, pid, ncid, varid;
13014 size_t start[2], count[2];
13017 NC(nc_create(filename, NC_NETCDF4, &ncid));
13020 NC(nc_def_dim(ncid,
"time", 1, &tid));
13021 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
13024 int dim_ids[2] = { tid, pid };
13025 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
13026 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
13027 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
13029 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
13031 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
13034 for (
int iq = 0; iq < ctl->
nq; iq++)
13044 NC(nc_enddef(ncid));
13052 for (
int iq = 0; iq < ctl->
nq; iq++)
13056 NC(nc_close(ncid));
13062 const char *dirname,
13068 ERRMSG(
"CLaMS atmospheric files support only lat/lon grids");
13071 static size_t out_cnt = 0;
13073 double r, r_start, r_stop;
13074 int year, mon, day, hour, min, sec;
13075 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
13076 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
13077 char filename_out[2 *
LEN] =
"traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
13079 int ncid, varid, tid, pid, cid;
13087 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
13089 &min_start, &sec_start, &r_start);
13091 &min_stop, &sec_stop, &r_stop);
13093 sprintf(filename_out,
13094 "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc", dirname,
13095 year_start % 100, mon_start, day_start, hour_start,
13096 year_stop % 100, mon_stop, day_stop, hour_stop);
13097 LOG(1,
"Write traj file: %s", filename_out);
13100 start[0] = out_cnt;
13103 count[1] = (size_t) atm->
np;
13106 if (out_cnt == 0) {
13109 NC(nc_create(filename_out, NC_NETCDF4, &ncid));
13112 NC(nc_def_dim(ncid,
"time", NC_UNLIMITED, &tid));
13113 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
13114 NC(nc_def_dim(ncid,
"TMDT", 7, &cid));
13119 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
13120 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
13121 NC_DEF_VAR(
"LAT", NC_DOUBLE, 2, dim_ids,
"Latitude",
"deg",
13123 NC_DEF_VAR(
"LON", NC_DOUBLE, 2, dim_ids,
"Longitude",
"deg",
13125 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 2, dim_ids,
"Pressure",
"hPa",
13127 NC_DEF_VAR(
"ZETA", NC_DOUBLE, 2, dim_ids,
"Zeta",
"K",
13129 for (
int iq = 0; iq < ctl->
nq; iq++)
13139 NC(nc_enddef(ncid));
13140 NC(nc_close(ncid));
13147 NC(nc_open(filename_out, NC_WRITE, &ncid));
13159 for (
int iq = 0; iq < ctl->
nq; iq++)
13163 NC(nc_close(ncid));
13166 if ((year == year_stop) && (mon == mon_stop)
13167 && (day == day_stop) && (hour == hour_stop)) {
13170 char filename_init[2 *
LEN] =
"./init_fix_YYYYMMDDHH.nc";
13171 sprintf(filename_init,
"%s/init_fix_%02d%02d%02d%02d.nc",
13172 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
13173 LOG(1,
"Write init file: %s", filename_init);
13176 NC(nc_create(filename_init, NC_NETCDF4, &ncid));
13179 NC(nc_def_dim(ncid,
"time", 1, &tid));
13180 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
13185 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
13186 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
13187 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
13189 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
13191 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
13194 for (
int iq = 0; iq < ctl->
nq; iq++)
13204 NC(nc_enddef(ncid));
13212 for (
int iq = 0; iq < ctl->
nq; iq++)
13216 NC(nc_close(ncid));
13223 const char *filename,
13225 const atm_t *atm) {
13227 int ncid, obsid, varid;
13229 size_t start[2], count[2];
13232 NC(nc_create(filename, NC_NETCDF4, &ncid));
13235 NC(nc_def_dim(ncid,
"obs", (
size_t) atm->
np, &obsid));
13238 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &obsid,
"time",
13239 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
13240 NC_DEF_VAR(
"press", NC_DOUBLE, 1, &obsid,
"pressure",
"hPa",
13242 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &obsid,
"longitude",
"degrees_east",
13244 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &obsid,
"latitude",
"degrees_north",
13246 for (
int iq = 0; iq < ctl->
nq; iq++)
13255 NC(nc_enddef(ncid));
13262 for (
int iq = 0; iq < ctl->
nq; iq++)
13266 NC(nc_close(ncid));
13272 const char *filename,
13283 if (ctl->
qnt_m < 0)
13284 ERRMSG(
"Need quantity mass!");
13285 const int ensemble = (ctl->
nens > 0);
13286 if (ensemble && ctl->
qnt_ens < 0)
13287 ERRMSG(
"Missing ensemble IDs!");
13289 ERRMSG(
"Too many ensembles!");
13293 LOG(1,
"Write mass budget data: %s", filename);
13294 if (!(out = fopen(filename,
"w")))
13295 ERRMSG(
"Cannot create file!");
13297 "# $1 = time [s]\n"
13298 "# $2 = ensemble ID (-999=total)\n"
13299 "# $3 = number of active air parcels [1]\n"
13300 "# $4 = total mass [kg]\n"
13301 "# $5 = mass loss due to OH chemistry [kg]\n"
13302 "# $6 = mass loss due to H2O2 chemistry [kg]\n"
13303 "# $7 = mass loss due to KPP chemistry [kg]\n"
13304 "# $8 = mass loss due to wet deposition [kg]\n"
13305 "# $9 = mass loss due to dry deposition [kg]\n"
13306 "# $10 = mass loss due to exponential decay [kg]\n"
13307 "# $11 = total tracked mass loss [kg]\n"
13308 "# $12 = accounted mass [kg]\n\n");
13313 const int qnt[7] = {
13318 double sum[
NENS + 1][7] = { {0} };
13319 int np[
NENS + 1] = { 0 };
13320 const double t0 = t - 0.5 * ctl->
dt_mod;
13321 const double t1 = t + 0.5 * ctl->
dt_mod;
13324 for (
int ip = 0; ip < atm->
np; ip++) {
13325 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13329 e = (int) atm->
q[ctl->
qnt_ens][ip];
13330 if (e < 0 || e >= ctl->
nens)
13331 ERRMSG(
"Ensemble ID out of range!");
13335 for (
int iq = 0; iq < nq; iq++)
13336 if (qnt[iq] >= 0) {
13337 sum[e][iq] += atm->
q[qnt[iq]][ip];
13338 sum[
NENS][iq] += atm->
q[qnt[iq]][ip];
13343 for (
int ie = -1; ie < (ensemble ? ctl->
nens : 0); ie++) {
13344 const int e = (ie < 0 ?
NENS : ie);
13346 for (
int iq = 1; iq < nq; iq++)
13348 mloss += sum[e][iq];
13349 fprintf(out,
"%.2f %d %d %g", t, ie < 0 ? -999 : ie, np[e], sum[e][0]);
13350 for (
int iq = 1; iq < nq; iq++)
13351 fprintf(out,
" %g", qnt[iq] >= 0 ? sum[e][iq] : NAN);
13352 fprintf(out,
" %g %g\n", mloss, sum[e][0] + mloss);
13366 const char *filename,
13372 ERRMSG(
"Only lat/lon grid supported");
13376 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
13379 static int *obscount, nobs, nk;
13383 const int ensemble = (ctl->
nens > 0);
13389 if (ctl->
qnt_m < 0)
13390 ERRMSG(
"Need quantity mass!");
13393 ERRMSG(
"Missing ensemble IDs!");
13395 ERRMSG(
"Too many ensembles!");
13402 ALLOC(area,
double,
13408 ALLOC(rlon,
double,
13410 ALLOC(rlat,
double,
13412 ALLOC(robs,
double,
13423 LOG(1,
"Write CSI%s data: %s", ensemble ?
" ensemble" :
"", filename);
13424 if (!(out = fopen(filename,
"w")))
13425 ERRMSG(
"Cannot create file!");
13429 "# $1 = time [s]\n"
13430 "# $2 = ensemble ID\n"
13431 "# $3 = number of hits (cx)\n"
13432 "# $4 = number of misses (cy)\n"
13433 "# $5 = number of false alarms (cz)\n"
13434 "# $6 = number of observations (cx + cy)\n"
13435 "# $7 = number of forecasts (cx + cz)\n"
13436 "# $8 = bias (%%)\n"
13437 "# $9 = POD (%%)\n"
13438 "# $10 = FAR (%%)\n"
13439 "# $11 = CSI (%%)\n"
13440 "# $12 = hits by random chance\n"
13441 "# $13 = ETS (%%)\n"
13442 "# $14 = Pearson R\n"
13443 "# $15 = Spearman R\n"
13444 "# $16 = mean error [kg/m²]\n"
13445 "# $17 = RMSE [kg/m²]\n"
13446 "# $18 = MAE [kg/m²]\n"
13447 "# $19 = log-likelihood\n" "# $20 = number of points\n\n");
13455 for (
int iy = 0; iy < ctl->
csi_ny; iy++) {
13456 const double lat = ctl->
csi_lat0 + dlat * (iy + 0.5);
13457 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.0) * cos(
DEG2RAD(lat));
13462 const double t0 = t - 0.5 * ctl->
dt_mod;
13463 const double t1 = t + 0.5 * ctl->
dt_mod;
13467 ALLOC(modmean,
double,
13468 (ensemble ? ctl->
nens : 1) * grid_size);
13469 ALLOC(obsmean,
double,
13471 ALLOC(obscount,
int,
13473 ALLOC(obsstd,
double,
13477 for (
int i = 0; i < (ensemble ? ctl->
nens : 1); i++)
13478 ct[i] = cx[i] = cy[i] = cz[i] = n[i] = 0;
13481 for (
int i = 0; i < nobs; i++) {
13482 if (rt[i] < t0 || rt[i] >= t1 || !isfinite(robs[i]))
13490 const int ix = (int) ((rlon[i] - ctl->
csi_lon0) / dlon);
13491 const int iy = (int) ((rlat[i] - ctl->
csi_lat0) / dlat);
13492 const int iz = (int) ((rz[i] - ctl->
csi_z0) / dz);
13498 obsmean[idx] += robs[i];
13499 obsstd[idx] +=
SQR(robs[i]);
13504 for (
int ip = 0; ip < atm->
np; ip++) {
13507 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13511 int ens_id = ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
13512 if (ens_id < 0 || ens_id >= (ensemble ? ctl->
nens : 1))
13513 ERRMSG(
"Ensemble ID out of range!");
13516 const double zpart =
Z(atm->
p[ip]);
13521 || zpart < ctl->csi_z0 || zpart >= ctl->
csi_z1)
13523 const int ix = (int) ((atm->
lon[ip] - ctl->
csi_lon0) / dlon);
13524 const int iy = (int) ((atm->
lat[ip] - ctl->
csi_lat0) / dlat);
13525 const int iz = (int) ((zpart - ctl->
csi_z0) / dz);
13535 for (
int e = 0; e < (ensemble ? ctl->
nens : 1); e++) {
13537 for (
int ix = 0; ix < ctl->
csi_nx; ix++)
13538 for (
int iy = 0; iy < ctl->
csi_ny; iy++)
13539 for (
int iz = 0; iz < ctl->
csi_nz; iz++) {
13544 if (obscount[idx]) {
13545 obsmean[idx] /= obscount[idx];
13547 sqrt(obsstd[idx] / obscount[idx] -
SQR(obsmean[idx]));
13551 const int midx = e * grid_size + idx;
13552 if (modmean[midx] > 0)
13553 modmean[midx] /= (1e6 * area[iy]);
13556 if (obscount[idx]) {
13571 x[n[e]] = modmean[midx];
13572 y[n[e]] = obsmean[idx];
13574 obsstdn[n[e]] = obsstd[idx];
13575 if ((++n[e]) >=
NCSI)
13576 ERRMSG(
"Too many points for statistics!");
13588 static double work[2 *
NCSI], work2[2 *
NCSI];
13589 const int n_obs = cx[e] + cy[e];
13590 const int n_for = cx[e] + cz[e];
13591 const double cx_rd = (ct[e] > 0) ? (1. * n_obs * n_for) / ct[e] : NAN;
13592 const double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
13593 const double pod = (n_obs > 0) ? 100. * cx[e] / n_obs : NAN;
13594 const double far = (n_for > 0) ? 100. * cz[e] / n_for : NAN;
13596 (cx[e] + cy[e] + cz[e] >
13597 0) ? 100. * cx[e] / (cx[e] + cy[e] + cz[e]) : NAN;
13599 (cx[e] + cy[e] + cz[e] - cx_rd >
13600 0) ? 100. * (cx[e] - cx_rd) / (cx[e] + cy[e] + cz[e] - cx_rd) : NAN;
13601 const double rho_p = gsl_stats_correlation(x, 1, y, 1, (
size_t) n[e]);
13602 const double rho_s =
13603 gsl_stats_spearman(x, 1, y, 1, (
size_t) n[e], work);
13604 for (
int i = 0; i < n[e]; i++) {
13605 work[i] = x[i] - y[i];
13606 work2[i] = (obsstdn[i] != 0) ? work[i] / obsstdn[i] : 0;
13608 const double mean = gsl_stats_mean(work, 1, (
size_t) n[e]);
13609 const double rmse =
13610 gsl_stats_sd_with_fixed_mean(work, 1, (
size_t) n[e], 0.0);
13611 const double absdev = gsl_stats_absdev_m(work, 1, (
size_t) n[e], 0.0);
13612 const double loglikelihood =
13613 gsl_stats_tss_m(work2, 1, (
size_t) n[e], 0.0) * -0.5;
13617 "%.2f %d %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n",
13618 t, ensemble ? e : -999, cx[e], cy[e], cz[e], n_obs, n_for, bias,
13619 pod, far, csi, cx_rd, ets, rho_p, rho_s, mean, rmse, absdev,
13620 loglikelihood, n[e]);
13623 for (
int i = 0; i < n[e]; i++)
13624 work[i] = work2[i] = x[i] = y[i] = obsstdn[i] = 0;
13625 ct[e] = cx[e] = cy[e] = cz[e] = n[e] = 0;
13653 const char *filename,
13659 ERRMSG(
"Only lat/lon grid supported");
13666 static int n[
NENS];
13673 ERRMSG(
"Missing ensemble IDs!");
13676 const double t0 = t - 0.5 * ctl->
dt_mod;
13677 const double t1 = t + 0.5 * ctl->
dt_mod;
13680 for (
int i = 0; i <
NENS; i++) {
13681 for (
int iq = 0; iq < ctl->
nq; iq++)
13682 qm[iq][i] = qs[iq][i] = 0;
13683 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
13688 for (
int ip = 0; ip < atm->
np; ip++) {
13691 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13696 ERRMSG(
"Ensemble ID is out of range!");
13700 for (
int iq = 0; iq < ctl->
nq; iq++) {
13701 qm[iq][ctl->
qnt_ens] += atm->
q[iq][ip];
13712 LOG(1,
"Write ensemble data: %s", filename);
13713 if (!(out = fopen(filename,
"w")))
13714 ERRMSG(
"Cannot create file!");
13718 "# $1 = time [s]\n"
13719 "# $2 = altitude [km]\n"
13720 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
13721 for (
int iq = 0; iq < ctl->
nq; iq++)
13722 fprintf(out,
"# $%d = %s (mean) [%s]\n", 5 + iq,
13724 for (
int iq = 0; iq < ctl->
nq; iq++)
13725 fprintf(out,
"# $%d = %s (sigma) [%s]\n", 5 + ctl->
nq + iq,
13727 fprintf(out,
"# $%d = number of members\n\n", 5 + 2 * ctl->
nq);
13730 for (
int i = 0; i <
NENS; i++)
13732 cart2geo(xm[i], &dummy, &lon, &lat);
13733 fprintf(out,
"%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
13734 for (
int iq = 0; iq < ctl->
nq; iq++) {
13736 fprintf(out, ctl->
qnt_format[iq], qm[iq][i] / n[i]);
13738 for (
int iq = 0; iq < ctl->
nq; iq++) {
13740 double var = qs[iq][i] / n[i] -
SQR(qm[iq][i] / n[i]);
13741 fprintf(out, ctl->
qnt_format[iq], (var > 0 ? sqrt(var) : 0));
13743 fprintf(out,
" %d\n", n[i]);
13753 const char *filename,
13758 double *area, *data, *lat, *lon;
13762 LOG(1,
"Write radioactive deposition data: %s", filename);
13766 ALLOC(area,
double,
13768 ALLOC(data,
double,
13778 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13779 lon[ix] = ctl->
grid_lon0 + dlon * (ix + 0.5);
13780 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
13781 lat[iy] = ctl->
grid_lat0 + dlat * (iy + 0.5);
13782 area[iy] = 1e6 * dlat * dlon *
SQR(
RE * M_PI / 180.)
13787 const double lambda[4] = {
13793 const double *inventory[4] = {
13796 for (
int iq = 0; iq < 4; iq++) {
13798 ? exp(-lambda[iq] * (t - ctl->
t_start)) : 1.0;
13799 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13800 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
13802 data[iq * nxy + idx] = inventory[iq][idx] * decay / area[iy];
13812 ERRMSG(
"Radioactive deposition output type unknown!");
13824 const char *filename,
13826 const double *data,
13830 const double *area) {
13833 if (!(out = fopen(filename,
"w")))
13834 ERRMSG(
"Cannot create file!");
13837 "# $1 = time [s]\n"
13838 "# $2 = longitude [deg]\n"
13839 "# $3 = latitude [deg]\n"
13840 "# $4 = area [m^2]\n"
13841 "# $5 = deposited Pb-210 activity [Bq/m^2]\n"
13842 "# $6 = deposited Be-7 activity [Bq/m^2]\n"
13843 "# $7 = deposited Cs-137 activity [Bq/m^2]\n"
13844 "# $8 = deposited I-131 activity [Bq/m^2]\n\n");
13847 for (
int ix = 0; ix < ctl->
grid_nx; ix++) {
13848 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
13850 fprintf(out,
"%.2f %g %g %g %g %g %g %g\n",
13851 t, lon[ix], lat[iy], area[iy],
13852 data[idx], data[nxy + idx],
13853 data[2 * nxy + idx], data[3 * nxy + idx]);
13855 fprintf(out,
"\n");
13864 const char *filename,
13866 const double *data,
13870 const double *area) {
13873 int ncid, dimid[3], varid;
13874 size_t start[2], count[2];
13877 ALLOC(help,
double,
13881 NC(nc_create(filename, NC_NETCDF4, &ncid));
13882 NC(nc_def_dim(ncid,
"time", 1, &dimid[0]));
13883 NC(nc_def_dim(ncid,
"lat", (
size_t) ctl->
grid_ny, &dimid[1]));
13884 NC(nc_def_dim(ncid,
"lon", (
size_t) ctl->
grid_nx, &dimid[2]));
13887 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &dimid[0],
"time",
13888 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
13889 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &dimid[1],
"latitude",
13890 "degrees_north", 0, 0);
13891 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &dimid[2],
"longitude",
13892 "degrees_east", 0, 0);
13893 NC_DEF_VAR(
"area", NC_DOUBLE, 1, &dimid[1],
"surface area",
"m**2", 0, 0);
13894 NC_DEF_VAR(
"depo_pb210", NC_DOUBLE, 3, dimid,
13895 "ground inventory of Pb-210",
"Bq m**-2", ctl->
grid_nc_level, 0);
13897 "ground inventory of Be-7",
"Bq m**-2", ctl->
grid_nc_level, 0);
13898 NC_DEF_VAR(
"depo_cs137", NC_DOUBLE, 3, dimid,
13899 "ground inventory of Cs-137",
"Bq m**-2", ctl->
grid_nc_level, 0);
13900 NC_DEF_VAR(
"depo_i131", NC_DOUBLE, 3, dimid,
13901 "ground inventory of aerosol-bound I-131",
"Bq m**-2",
13903 NC(nc_enddef(ncid));
13912 const char *varname[4] = {
13913 "depo_pb210",
"depo_be7",
"depo_cs137",
"depo_i131"
13915 for (
int iq = 0; iq < 4; iq++) {
13916 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
13917 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
13923 NC(nc_close(ncid));
13930 const char *filename,
13938 ERRMSG(
"Only lat/lon grid supported");
13940 static double kz[
EP], kw[
EP];
13944 double *cd, *mean[
NQ], *sigma[
NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
13946 int *ixs, *iys, *izs, *np;
13952 LOG(1,
"Write grid data: %s", filename);
13965 for (
int iq = 0; iq < ctl->
nq; iq++) {
13966 ALLOC(mean[iq],
double,
13968 ALLOC(sigma[iq],
double,
13971 ALLOC(vmr_impl,
double,
13979 ALLOC(area,
double,
13981 ALLOC(press,
double,
13998#pragma omp parallel
for default(shared)
13999 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
14000 z[iz] = ctl->
grid_z0 + dz * (iz + 0.5);
14001 press[iz] =
P(z[iz]);
14005 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
14006 lon[ix] = ctl->
grid_lon0 + dlon * (ix + 0.5);
14007#pragma omp parallel for default(shared)
14008 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
14009 lat[iy] = ctl->
grid_lat0 + dlat * (iy + 0.5);
14010 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
14014 const double t0 = t - 0.5 * ctl->
dt_mod;
14015 const double t1 = t + 0.5 * ctl->
dt_mod;
14018#pragma omp parallel for default(shared)
14019 for (
int ip = 0; ip < atm->
np; ip++) {
14020 const double zpart =
Z(atm->
p[ip]);
14021 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
14026 || zpart < ctl->grid_z0 || zpart >= ctl->
grid_z1) {
14030 ixs[ip] = (int) ((atm->
lon[ip] - ctl->
grid_lon0) / dlon);
14031 iys[ip] = (int) ((atm->
lat[ip] - ctl->
grid_lat0) / dlat);
14032 izs[ip] = (int) ((zpart - ctl->
grid_z0) / dz);
14039 for (
int ip = 0; ip < atm->
np; ip++)
14040 if (izs[ip] >= 0) {
14045 for (
int iq = 0; iq < ctl->
nq; iq++) {
14046 mean[iq][idx] += kernel * atm->
q[iq][ip];
14047 sigma[iq][idx] +=
SQR(kernel * atm->
q[iq][ip]);
14052#pragma omp parallel for default(shared)
14053 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
14054 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
14055 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
14062 if (ctl->
qnt_m >= 0)
14063 cd[idx] = mean[ctl->
qnt_m][idx] / (1e6 * area[iy]);
14066 vmr_impl[idx] = NAN;
14067 if (ctl->
qnt_m >= 0 && ctl->
molmass > 0 && met0 != NULL
14070 if (mean[ctl->
qnt_m][idx] > 0) {
14076 lon[ix], lat[iy], &temp, ci, cw, 1);
14080 MA / ctl->
molmass * cd[idx] / (
RHO(press[iz], temp) * dz * 1e3);
14086 for (
int iq = 0; iq < ctl->
nq; iq++) {
14087 mean[iq][idx] /= np[idx];
14088 const double var = sigma[iq][idx] / np[idx] -
SQR(mean[iq][idx]);
14089 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
14091 for (
int iq = 0; iq < ctl->
nq; iq++) {
14092 mean[iq][idx] = NAN;
14093 sigma[iq][idx] = NAN;
14100 t, z, lon, lat, area, dz, np);
14105 t, z, lon, lat, area, dz, np);
14109 ERRMSG(
"Grid data format GRID_TYPE unknown!");
14113 for (
int iq = 0; iq < ctl->
nq; iq++) {
14132 const char *filename,
14137 const double *vmr_impl,
14142 const double *area,
14152 if (!(out = popen(
"gnuplot",
"w")))
14153 ERRMSG(
"Cannot create pipe to gnuplot!");
14156 fprintf(out,
"set out \"%s.png\"\n", filename);
14160 int year, mon, day, hour, min, sec;
14161 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
14162 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
14163 year, mon, day, hour, min);
14169 ERRMSG(
"Cannot open file!");
14170 while (fgets(line,
LEN, in))
14171 fprintf(out,
"%s", line);
14178 if (!(out = fopen(filename,
"w")))
14179 ERRMSG(
"Cannot create file!");
14184 "# $1 = time [s]\n"
14185 "# $2 = altitude [km]\n"
14186 "# $3 = longitude [deg]\n"
14187 "# $4 = latitude [deg]\n"
14188 "# $5 = surface area [km^2]\n"
14189 "# $6 = layer depth [km]\n"
14190 "# $7 = column density (implicit) [kg/m^2]\n"
14191 "# $8 = volume mixing ratio (implicit) [ppv]\n"
14192 "# $9 = number of particles [1]\n");
14193 for (
int iq = 0; iq < ctl->
nq; iq++)
14194 fprintf(out,
"# $%i = %s (mean) [%s]\n", 10 + iq, ctl->
qnt_name[iq],
14197 for (
int iq = 0; iq < ctl->
nq; iq++)
14198 fprintf(out,
"# $%i = %s (stddev) [%s]\n", 10 + ctl->
nq + iq,
14200 fprintf(out,
"\n");
14203 for (
int ix = 0; ix < ctl->
grid_nx; ix++) {
14205 fprintf(out,
"\n");
14206 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
14208 fprintf(out,
"\n");
14209 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
14212 fprintf(out,
"%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
14213 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
14214 for (
int iq = 0; iq < ctl->
nq; iq++) {
14216 fprintf(out, ctl->
qnt_format[iq], mean[iq][idx]);
14219 for (
int iq = 0; iq < ctl->
nq; iq++) {
14221 fprintf(out, ctl->
qnt_format[iq], sigma[iq][idx]);
14223 fprintf(out,
"\n");
14236 const char *filename,
14241 const double *vmr_impl,
14246 const double *area,
14250 char longname[2 *
LEN], varname[2 *
LEN];
14254 int *help2, ncid, dimid[10], varid;
14256 size_t start[2], count[2];
14259 ALLOC(help,
double,
14265 NC(nc_create(filename, NC_NETCDF4, &ncid));
14268 NC(nc_def_dim(ncid,
"time", 1, &dimid[0]));
14269 NC(nc_def_dim(ncid,
"z", (
size_t) ctl->
grid_nz, &dimid[1]));
14270 NC(nc_def_dim(ncid,
"lat", (
size_t) ctl->
grid_ny, &dimid[2]));
14271 NC(nc_def_dim(ncid,
"lon", (
size_t) ctl->
grid_nx, &dimid[3]));
14272 NC(nc_def_dim(ncid,
"dz", 1, &dimid[4]));
14275 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &dimid[0],
"time",
14276 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
14277 NC_DEF_VAR(
"z", NC_DOUBLE, 1, &dimid[1],
"altitude",
"km", 0, 0);
14278 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &dimid[2],
"latitude",
"degrees_north", 0,
14280 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &dimid[3],
"longitude",
"degrees_east", 0,
14282 NC_DEF_VAR(
"dz", NC_DOUBLE, 1, &dimid[1],
"layer depth",
"km", 0, 0);
14283 NC_DEF_VAR(
"area", NC_DOUBLE, 1, &dimid[2],
"surface area",
"km**2", 0, 0);
14285 NC_DEF_VAR(
"cd", NC_FLOAT, 4, dimid,
"column density",
"kg m**-2",
14288 "volume mixing ratio (implicit)",
"ppv", ctl->
grid_nc_level, 0);
14289 NC_DEF_VAR(
"np", NC_INT, 4, dimid,
"number of particles",
"1", 0, 0);
14290 for (
int iq = 0; iq < ctl->
nq; iq++) {
14291 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
14292 sprintf(longname,
"%s (mean)", ctl->
qnt_longname[iq]);
14296 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
14297 sprintf(longname,
"%s (stddev)", ctl->
qnt_longname[iq]);
14303 NC(nc_enddef(ncid));
14313 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
14314 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
14315 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
14320 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
14321 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
14322 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
14327 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
14328 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
14329 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
14334 for (
int iq = 0; iq < ctl->
nq; iq++) {
14335 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
14336 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
14337 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
14338 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
14345 for (
int iq = 0; iq < ctl->
nq; iq++) {
14346 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
14347 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
14348 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
14349 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
14356 NC(nc_close(ncid));
14366 const char *filename,
14371 FILE *out, *level_log = NULL;
14372 if (!(out = fopen(filename,
"w")))
14373 ERRMSG(
"Cannot create file!");
14379 ERRMSG(
"Cannot create compression log file!");
14384 "# $1 = compression codec name [-]\n"
14385 "# $2 = variable name [-]\n"
14386 "# $3 = level index [-]\n"
14387 "# $4 = pressure level [hPa]\n"
14388 "# $5 = compression ratio [-]\n"
14389 "# $6 = bits per value [bit/value]\n"
14390 "# $7 = correlation coefficient [-]\n"
14391 "# $8 = mean compression error [-]\n"
14392 "# $9 = standard deviation of compression error [-]\n"
14393 "# $10 = minimum compression error [-]\n"
14394 "# $11 = maximum compression error [-]\n"
14395 "# $12 = mean value of original field [-]\n"
14396 "# $13 = value range of original field [-]\n"
14397 "# $14 = normalized root mean square error [-]\n"
14398 "# $15 = compression time [s]\n"
14399 "# $16 = compression speed [MiB/s]\n"
14400 "# $17 = decompression time [s]\n"
14401 "# $18 = decompression speed [MiB/s]\n\n");
14479 ERRMSG(
"Number of meteo variables doesn't match!");
14499 const char *varname) {
14508 for (
int ix = 0; ix < met->
nx; ix++)
14509 for (
int iy = 0; iy < met->
ny; iy++)
14510 help[
ARRAY_2D(ix, iy, met->
ny)] = var[ix][iy];
14513 LOG(2,
"Write 2-D variable: %s (uncompressed)", varname);
14515 (
size_t) (met->
nx * met->
ny),
14529 const char *varname,
14540#pragma omp parallel for default(shared) collapse(2)
14541 for (
int ix = 0; ix < met->
nx; ix++)
14542 for (
int iy = 0; iy < met->
ny; iy++)
14543 for (
int ip = 0; ip < met->
np; ip++)
14544 help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)] = var[ix][iy][ip];
14548 LOG(2,
"Write 3-D variable: %s (uncompressed)", varname);
14550 (
size_t) (met->
nx * met->
ny * met->
np),
14556 compress_pck(ctl, met, varname, help, 0, level_log, out);
14567 compress_zfp(ctl, met, varname, help, 0, level_log, out);
14580 compress_lz4(ctl, met, varname, help, 0, level_log, out);
14586 compress_cms(ctl, met, varname, help, 0, level_log, out);
14599 compress_sz3(ctl, met, varname, help, 0, level_log, out);
14605 ERRMSG(
"MET_TYPE not supported!");
14608 LOG(3,
"%d", metvar);
14618 const char *filename,
14624 size_t start[4], count[4];
14625 NC(nc_create(filename, NC_NETCDF4, &ncid));
14628 int tid, lonid, latid, levid;
14629 NC(nc_def_dim(ncid,
"time", 1, &tid));
14632 NC(nc_def_dim(ncid,
"lon", (
size_t) met->
nx, &lonid));
14633 NC(nc_def_dim(ncid,
"lat", (
size_t) met->
ny, &latid));
14634 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &lonid,
"longitude",
"degrees_east", 0,
14636 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &latid,
"latitude",
"degrees_north", 0,
14639 NC(nc_def_dim(ncid,
"x", (
size_t) met->
nx, &lonid));
14640 NC(nc_def_dim(ncid,
"y", (
size_t) met->
ny, &latid));
14641 NC_DEF_VAR(
"x", NC_DOUBLE, 1, &lonid,
"x",
"easting", 0, 0);
14642 NC_DEF_VAR(
"y", NC_DOUBLE, 1, &latid,
"y",
"northing", 0, 0);
14645 NC(nc_def_dim(ncid,
"lev", (
size_t) met->
np, &levid));
14648 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"time",
14649 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
14650 NC_DEF_VAR(
"lev", NC_DOUBLE, 1, &levid,
"pressure",
"Pa", 0, 0);
14653 int dimid2[3] = { tid, latid, lonid };
14654 NC_DEF_VAR(
"sp", NC_FLOAT, 3, dimid2,
"Surface pressure",
"Pa",
14656 NC_DEF_VAR(
"z", NC_FLOAT, 3, dimid2,
"Geopotential",
"m**2 s**-2",
14658 NC_DEF_VAR(
"t2m", NC_FLOAT, 3, dimid2,
"2 metre temperature",
"K",
14660 NC_DEF_VAR(
"u10m", NC_FLOAT, 3, dimid2,
"10 metre U wind component",
14662 NC_DEF_VAR(
"v10m", NC_FLOAT, 3, dimid2,
"10 metre V wind component",
14665 "Instantaneous eastward turbulent surface stress",
"N m**-2",
14668 "Instantaneous northward turbulent surface stress",
"N m**-2",
14671 "Instantaneous surface sensible heat flux",
"W m**-2",
14673 NC_DEF_VAR(
"lsm", NC_FLOAT, 3, dimid2,
"Land/sea mask",
"-",
14675 NC_DEF_VAR(
"sstk", NC_FLOAT, 3, dimid2,
"Sea surface temperature",
"K",
14677 NC_DEF_VAR(
"blp", NC_FLOAT, 3, dimid2,
"Boundary layer pressure",
"Pa",
14679 NC_DEF_VAR(
"pt", NC_FLOAT, 3, dimid2,
"Tropopause pressure",
"Pa",
14681 NC_DEF_VAR(
"tt", NC_FLOAT, 3, dimid2,
"Tropopause temperature",
"K",
14683 NC_DEF_VAR(
"zt", NC_FLOAT, 3, dimid2,
"Tropopause height",
"m",
14685 NC_DEF_VAR(
"h2ot", NC_FLOAT, 3, dimid2,
"Tropopause water vapor",
"ppv",
14687 NC_DEF_VAR(
"pct", NC_FLOAT, 3, dimid2,
"Cloud top pressure",
"Pa",
14689 NC_DEF_VAR(
"pcb", NC_FLOAT, 3, dimid2,
"Cloud bottom pressure",
"Pa",
14691 NC_DEF_VAR(
"cl", NC_FLOAT, 3, dimid2,
"Total column cloud water",
14694 "Pressure at lifted condensation level (LCL)",
"Pa",
14697 "Pressure at level of free convection (LFC)",
"Pa",
14700 "Pressure at equilibrium level (EL)",
"Pa", ctl->
met_nc_level,
14703 "Convective available potential energy",
"J kg**-1",
14705 NC_DEF_VAR(
"cin", NC_FLOAT, 3, dimid2,
"Convective inhibition",
14707 NC_DEF_VAR(
"o3c", NC_FLOAT, 3, dimid2,
"Total column ozone",
"DU",
14711 int dimid3[4] = { tid, levid, latid, lonid };
14712 NC_DEF_VAR(
"t", NC_FLOAT, 4, dimid3,
"Temperature",
"K",
14714 NC_DEF_VAR(
"u", NC_FLOAT, 4, dimid3,
"U velocity",
"m s**-1",
14716 NC_DEF_VAR(
"v", NC_FLOAT, 4, dimid3,
"V velocity",
"m s**-1",
14718 NC_DEF_VAR(
"w", NC_FLOAT, 4, dimid3,
"Vertical velocity",
"Pa s**-1",
14720 NC_DEF_VAR(
"q", NC_FLOAT, 4, dimid3,
"Specific humidity",
"kg kg**-1",
14722 NC_DEF_VAR(
"o3", NC_FLOAT, 4, dimid3,
"Ozone mass mixing ratio",
14724 NC_DEF_VAR(
"clwc", NC_FLOAT, 4, dimid3,
"Cloud liquid water content",
14726 NC_DEF_VAR(
"crwc", NC_FLOAT, 4, dimid3,
"Cloud rain water content",
14728 NC_DEF_VAR(
"ciwc", NC_FLOAT, 4, dimid3,
"Cloud ice water content",
14730 NC_DEF_VAR(
"cswc", NC_FLOAT, 4, dimid3,
"Cloud snow water content",
14732 NC_DEF_VAR(
"cc", NC_FLOAT, 4, dimid3,
"Cloud cover",
"-",
14736 NC(nc_enddef(ncid));
14750 for (
int ip = 0; ip < met->
np; ip++)
14751 phelp[ip] = 100. * met->
p[ip];
14794 NC(nc_close(ncid));
14801 const char *varname,
14807 size_t start[4], count[4];
14815 for (
int ix = 0; ix < met->
nx; ix++)
14816 for (
int iy = 0; iy < met->
ny; iy++)
14817 help[
ARRAY_2D(iy, ix, met->
nx)] = scl * var[ix][iy];
14820 LOG(2,
"Write 2-D variable: %s (netCDF)", varname);
14831 const char *varname,
14837 size_t start[4], count[4];
14845 for (
int ix = 0; ix < met->
nx; ix++)
14846 for (
int iy = 0; iy < met->
ny; iy++)
14847 for (
int ip = 0; ip < met->
np; ip++)
14848 help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)] = scl * var[ix][iy][ip];
14851 LOG(2,
"Write 3-D variable: %s (netCDF)", varname);
14861 const char *filename,
14869 ERRMSG(
"Only lat/lon grid supported");
14873 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
14874 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
14876 static int nobs, *obscount, ip, okay;
14885 if (ctl->
qnt_m < 0)
14886 ERRMSG(
"Need quantity mass!");
14890 ERRMSG(
"Specify molar mass!");
14897 ALLOC(area,
double,
14901 ALLOC(press,
double,
14907 ALLOC(rlon,
double,
14909 ALLOC(rlat,
double,
14911 ALLOC(robs,
double,
14918 LOG(1,
"Write profile data: %s", filename);
14919 if (!(out = fopen(filename,
"w")))
14920 ERRMSG(
"Cannot create file!");
14924 "# $1 = time [s]\n"
14925 "# $2 = altitude [km]\n"
14926 "# $3 = longitude [deg]\n"
14927 "# $4 = latitude [deg]\n"
14928 "# $5 = pressure [hPa]\n"
14929 "# $6 = temperature [K]\n"
14930 "# $7 = volume mixing ratio [ppv]\n"
14931 "# $8 = H2O volume mixing ratio [ppv]\n"
14932 "# $9 = O3 volume mixing ratio [ppv]\n"
14933 "# $10 = observed BT index [K]\n"
14934 "# $11 = number of observations\n");
14942 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
14943 z[iz] = ctl->
prof_z0 + dz * (iz + 0.5);
14944 press[iz] =
P(z[iz]);
14948 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
14949 lon[ix] = ctl->
prof_lon0 + dlon * (ix + 0.5);
14950 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
14951 lat[iy] = ctl->
prof_lat0 + dlat * (iy + 0.5);
14952 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
14957 const double t0 = t - 0.5 * ctl->
dt_mod;
14958 const double t1 = t + 0.5 * ctl->
dt_mod;
14961 ALLOC(mass,
double,
14963 ALLOC(obsmean,
double,
14965 ALLOC(obscount,
int,
14969 for (
int i = 0; i < nobs; i++) {
14974 else if (rt[i] >= t1)
14978 if (!isfinite(robs[i]))
14985 const int ix = (int) ((rlon[i] - ctl->
prof_lon0) / dlon);
14986 const int iy = (int) ((rlat[i] - ctl->
prof_lat0) / dlat);
14992 obsmean[idx] += robs[i];
14997 for (ip = 0; ip < atm->
np; ip++) {
15000 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
15004 const double zpart =
Z(atm->
p[ip]);
15009 || zpart < ctl->prof_z0 || zpart >= ctl->
prof_z1)
15011 const int ix = (int) ((atm->
lon[ip] - ctl->
prof_lon0) / dlon);
15012 const int iy = (int) ((atm->
lat[ip] - ctl->
prof_lat0) / dlat);
15013 const int iz = (int) ((zpart - ctl->
prof_z0) / dz);
15019 mass[idx] += atm->
q[ctl->
qnt_m][ip];
15023 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
15024 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
15026 if (obscount[idx2] > 0) {
15030 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
15032 if (mass[idx3] > 0) {
15041 fprintf(out,
"\n");
15044 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
15049 lon[ix], lat[iy], &temp, ci, cw, 1);
15051 lon[ix], lat[iy], &h2o, ci, cw, 0);
15053 lon[ix], lat[iy], &o3, ci, cw, 0);
15058 / (
RHO(press[iz], temp) * area[iy] * dz * 1e9);
15061 fprintf(out,
"%.2f %g %g %g %g %g %g %g %g %g %d\n",
15062 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
15063 obsmean[idx2] / obscount[idx2], obscount[idx2]);
15096 const char *filename,
15104 ERRMSG(
"Only lat/lon grid supported");
15108 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[
EP],
15111 static int nobs, nk;
15124 ALLOC(rlon,
double,
15126 ALLOC(rlat,
double,
15128 ALLOC(robs,
double,
15139 LOG(1,
"Write sample data: %s", filename);
15140 if (!(out = fopen(filename,
"w")))
15141 ERRMSG(
"Cannot create file!");
15145 "# $1 = time [s]\n"
15146 "# $2 = altitude [km]\n"
15147 "# $3 = longitude [deg]\n"
15148 "# $4 = latitude [deg]\n"
15149 "# $5 = surface area [km^2]\n"
15150 "# $6 = layer depth [km]\n"
15151 "# $7 = number of particles [1]\n"
15152 "# $8 = column density [kg/m^2]\n"
15153 "# $9 = volume mixing ratio [ppv]\n"
15154 "# $10 = observed BT index [K]\n\n");
15159 area = M_PI * rmax2;
15163 const double t0 = t - 0.5 * ctl->
dt_mod;
15164 const double t1 = t + 0.5 * ctl->
dt_mod;
15167 for (
int i = 0; i < nobs; i++) {
15172 else if (rt[i] >= t1)
15177 geo2cart(0, rlon[i], rlat[i], x0);
15180 const double rp =
P(rz[i]);
15181 const double ptop =
P(rz[i] + ctl->
sample_dz);
15182 const double pbot =
P(rz[i] - ctl->
sample_dz);
15190 for (
int ip = 0; ip < atm->
np; ip++) {
15193 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
15197 if (fabs(rlat[i] - atm->
lat[ip]) > dlat)
15203 if (
DIST2(x0, x1) > rmax2)
15208 if (atm->
p[ip] > pbot || atm->
p[ip] < ptop)
15212 if (ctl->
qnt_m >= 0)
15219 const double cd = mass / (1e6 * area);
15230 rlon[i], rlat[i], &temp, ci, cw, 1);
15239 fprintf(out,
"%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
15240 rlon[i], rlat[i], area, ctl->
sample_dz, np, cd, vmr, robs[i]);
15261 const char *filename,
15267 ERRMSG(
"Only lat/lon grid supported");
15271 static double rmax2, x0[3], x1[3];
15280 LOG(1,
"Write station data: %s", filename);
15283 if (!(out = fopen(filename,
"w")))
15284 ERRMSG(
"Cannot create file!");
15288 "# $1 = time [s]\n"
15289 "# $2 = altitude [km]\n"
15290 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
15291 for (
int iq = 0; iq < ctl->
nq; iq++)
15292 fprintf(out,
"# $%i = %s [%s]\n", (iq + 5),
15294 fprintf(out,
"\n");
15302 const double t0 = t - 0.5 * ctl->
dt_mod;
15303 const double t1 = t + 0.5 * ctl->
dt_mod;
15306 for (
int ip = 0; ip < atm->
np; ip++) {
15309 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
15325 if (
DIST2(x0, x1) > rmax2)
15333 fprintf(out,
"%.2f %g %g %g",
15334 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]);
15335 for (
int iq = 0; iq < ctl->
nq; iq++) {
15337 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
15339 fprintf(out,
"\n");
15350 const char *filename,
15356 ERRMSG(
"Only lat/lon grid supported");
15364 LOG(1,
"Write VTK data: %s", filename);
15367 const double t0 = t - 0.5 * ctl->
dt_mod;
15368 const double t1 = t + 0.5 * ctl->
dt_mod;
15371 if (!(out = fopen(filename,
"w")))
15372 ERRMSG(
"Cannot create file!");
15376 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
15377 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
15384 "# vtk DataFile Version 3.0\n"
15385 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
15388 fprintf(out,
"POINTS %d float\n", np);
15390 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
15391 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
15395 const double coslat = cos(
DEG2RAD(atm->
lat[ip]));
15396 const double x = radius * coslat * cos(
DEG2RAD(atm->
lon[ip]));
15397 const double y = radius * coslat * sin(
DEG2RAD(atm->
lon[ip]));
15398 const double z = radius * sin(
DEG2RAD(atm->
lat[ip]));
15399 fprintf(out,
"%g %g %g\n", x, y, z);
15402 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
15403 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
15405 fprintf(out,
"%g %g %g\n", atm->
lon[ip], atm->
lat[ip],
15410 fprintf(out,
"POINT_DATA %d\n", np);
15411 for (
int iq = 0; iq < ctl->
nq; iq++) {
15412 fprintf(out,
"SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
15414 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
15415 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
15417 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.
void write_met_nc_2d(const int ncid, const char *varname, met_t *met, float var[EX][EY], const float scl)
Writes a 2D meteorological variable to a NetCDF file.
void dd_read_met_nc_grid(dd_t *dd, const ctl_t *ctl, met_t *met, const int ncid)
Read meteorological grid information and construct the domain-decomposed grid with halo regions.
void read_met_sample(const ctl_t *ctl, met_t *met)
Downsamples meteorological data based on specified parameters.
int read_met_nc_2d(const int ncid, const char *const varnames[], const size_t nvarnames, const ctl_t *ctl, const met_t *met, dd_t *dd, float dest[EX][EY], const float scl, const int init)
Reads a 2-dimensional meteorological variable from a NetCDF file.
void read_obs(const char *filename, const ctl_t *ctl, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from a file and stores it in arrays.
void module_advect(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Advances particle positions using different advection schemes.
void module_meteo(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Update atmospheric properties using meteorological data.
void read_clim_photo(const char *filename, clim_photo_t *photo)
Reads photolysis rates from a NetCDF file and populates the given photolysis structure.
void read_met_cloud(met_t *met)
Calculates cloud-related variables for each grid point.
void module_decay(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, atm_t *atm)
Simulate exponential decay processes for atmospheric particles.
double sedi(const double p, const double T, const double rp, const double rhop)
Calculates the sedimentation velocity of a particle in air.
double cos_sza(const double sec, const double lon, const double lat)
Calculates the cosine of the solar zenith angle.
void intpol_met_space_2d(const met_t *met, float array[EX][EY], const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables in 2D space.
void compress_log_levels_3d(FILE *out, const char *codec, const char *varname, const met_t *met, const float *org_all, const float *cmp_all, const size_t nxy, const size_t nz, const double ratio, const double bpv, const double t_comp, const double t_decomp, const size_t nbytes)
Write per-level compression diagnostics for a full 3-D field.
int read_atm_nc(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a generic netCDF file and populates the given atmospheric structure.
void read_met_pbl(const ctl_t *ctl, met_t *met)
Computes the planetary boundary layer (PBL) pressure based on meteorological data.
void read_met_detrend(const ctl_t *ctl, met_t *met)
Detrends meteorological data.
void read_met_tropo(const ctl_t *ctl, const clim_t *clim, met_t *met)
Calculates the tropopause and related meteorological variables based on various methods and stores th...
void read_obs_asc(const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from an ASCII file.
void write_depo_asc(const char *filename, const ctl_t *ctl, const double *data, const double t, const double *lon, const double *lat, const double *area)
Write radioactive deposition densities as a gnuplot-compatible table.
void module_chem_init(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Initializes the chemistry modules by setting atmospheric composition.
int locate_reg(const double *xx, const int n, const double x)
Locate the index of the interval containing a given value in a regular grid.
void read_met_nc_levels(const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads and processes meteorological level data from NetCDF files with domain decomposition.
void compress_pck(const ctl_t *ctl, const met_t *met, const char *varname, float *array, const int decompress, FILE *level_log, FILE *inout)
Compresses or decompresses a 3‑D float array using the PCK format.
void read_met_monotonize(const ctl_t *ctl, met_t *met)
Makes zeta and pressure profiles monotone.
int read_clim_ts(const char *filename, clim_ts_t *ts)
Reads a climatological time series from a file and populates the given time series structure.
void intpol_check_cartesian(const double *lons, const int nlon, const double *lats, const int nlat, const double lon, const double lat, double *lon2, double *lat2)
Clamps UTM coordinates to the valid bounds.
void read_met_periodic(met_t *met)
Applies periodic boundary conditions to meteorological data along longitudinal axis.
int compress_metvar_index(const char *varname)
Maps a meteorological variable name to its internal MPTRAC variable index.
void module_timesteps_init(ctl_t *ctl, const atm_t *atm)
Initialize start time and time interval for time-stepping.
void write_ens(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes ensemble data to a file.
void module_mixing(const ctl_t *ctl, const clim_t *clim, atm_t *atm, const double t)
Update atmospheric properties through interparcel mixing.
double clim_zm(const clim_zm_t *zm, const double t, const double lat, const double p)
Interpolates monthly mean zonal mean climatological variables.
void read_clim_photo_help(const int ncid, const char *varname, const clim_photo_t *photo, double var[CP][CSZA][CO3])
Reads a 3D climatological photochemistry variable from a NetCDF file.
void read_met_ml2pl(const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname)
Interpolates meteorological data to specified pressure levels.
double clim_tropo(const clim_t *clim, const double t, const double lat)
Calculates the tropopause pressure based on climatological data.
void read_obs_nc(const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from a NetCDF file.
void read_met_bin_2d(FILE *in, const met_t *met, float var[EX][EY], const char *varname)
Reads a 2-dimensional meteorological variable from a binary file and stores it in the provided array.
int locate_irr(const double *xx, const int n, const double x)
Locate the index of the interval containing a given value in a sorted array.
void module_isosurf_init(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Initialize the isosurface module based on atmospheric data.
void mptrac_free(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm, depo_t *depo, dd_t *dd)
Frees memory resources allocated for MPTRAC.
void 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_mixing_help(const ctl_t *ctl, atm_t *atm, const int *ixs, const int *iys, const int *izs, const double *mixparam, const int qnt_idx, const int use_ensemble)
Perform subgrid-scale interparcel mixing of a given quantity.
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_position(const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm, const int reflect)
Update the positions and pressure levels of atmospheric particles.
void module_radio_decay(const ctl_t *ctl, const cache_t *cache, atm_t *atm)
Apply radioactive decay to atmospheric tracer species.
void mptrac_get_met(ctl_t *ctl, clim_t *clim, const double t, met_t **met0, met_t **met1, dd_t *dd)
Retrieves meteorological data for the specified time.
void 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 module_diff_meso(const ctl_t *ctl, cache_t *cache, const met_t *met0, const met_t *met1, atm_t *atm)
Simulate mesoscale diffusion for atmospheric particles.
void write_met_nc(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a NetCDF file.
void module_rng_init(const int ntask)
Initialize random number generators for parallel tasks.
void mptrac_init(ctl_t *ctl, cache_t *cache, clim_t *clim, atm_t *atm, depo_t *depo, const int ntask)
Initializes the MPTRAC model and its associated components.
int mptrac_read_atm(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a specified file into the given atmospheric structure.
void mptrac_update_host(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
Updates host memory for specified data structures.
double clim_oh(const ctl_t *ctl, const clim_t *clim, const double t, const double lon, const double lat, const double p)
Calculates the hydroxyl radical (OH) concentration from climatology data, with an optional diurnal co...
void write_met_bin_3d(FILE *out, const ctl_t *ctl, met_t *met, float var[EX][EY][EP], const char *varname, const int metvar, FILE *level_log)
Writes a 3-dimensional meteorological variable to a binary file.
void read_met_ozone(met_t *met)
Calculates the total column ozone from meteorological ozone data.
void 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.
int read_met_nc_3d(const int ncid, const char *const varnames[], const size_t nvarnames, const ctl_t *ctl, const met_t *met, dd_t *dd, float dest[EX][EY][EP], const float scl)
Reads a 3-dimensional meteorological variable from a NetCDF file.
void intpol_met_time_2d(const met_t *met0, float array0[EX][EY], const met_t *met1, float array1[EX][EY], const double ts, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological data in 2D space and time.
void clim_oh_diurnal_correction(const ctl_t *ctl, clim_t *clim)
Applies a diurnal correction to the hydroxyl radical (OH) concentration in climatology data.
void locate_vert(float profiles[EX][EY][EP], const int np, const int lon_ap_ind, const int lat_ap_ind, const double height_ap, int *ind)
Locate the four vertical indizes of a box for a given height value.
void write_met_bin_2d(FILE *out, met_t *met, float var[EX][EY], const char *varname)
Writes a 2-dimensional meteorological variable to a binary file.
void read_met_pv(met_t *met)
Calculates potential vorticity (PV) from meteorological data.
int read_atm_bin(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a binary file and populates the given atmospheric structure.
void write_budget(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes a time series of the atmospheric tracer mass budget.
double clim_ts(const clim_ts_t *ts, const double t)
Interpolates a time series of climatological variables.
void jsec2time(const double jsec, int *year, int *mon, int *day, int *hour, int *min, int *sec, double *remain)
Converts Julian seconds to calendar date and time components.
int read_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a binary file.
void write_atm_clams(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a NetCDF file in the CLaMS format.
void get_met_replace(char *orig, const char *search, const char *repl)
Replaces occurrences of a substring in a string with another substring.
void module_diff_turb(const ctl_t *ctl, cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Applies turbulent diffusion processes to atmospheric particles.
int read_atm_clams(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads atmospheric data from a CLAMS NetCDF file.
void write_depo_nc(const char *filename, const ctl_t *ctl, const double *data, const double t, const double *lon, const double *lat, const double *area)
Write radioactive deposition densities as a CF-style netCDF file.
void module_timesteps(const ctl_t *ctl, cache_t *cache, const met_t *met0, atm_t *atm, const double t)
Calculate time steps for air parcels based on specified conditions.
int mptrac_read_met(const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met, dd_t *dd)
Reads meteorological data from a file, supporting multiple formats and MPI broadcasting.
void mptrac_run_timestep(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t **met0, met_t **met1, atm_t *atm, depo_t *depo, double t, dd_t *dd)
Executes a single timestep of the MPTRAC model simulation.
void write_vtk(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes VTK (Visualization Toolkit) data to a specified file.
void module_tracer_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Simulate chemical reactions involving long-lived atmospheric tracers.
void mptrac_read_ctl(const char *filename, int argc, char *argv[], ctl_t *ctl)
Reads control parameters from a configuration file and populates the given structure.
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 P0
Standard pressure [hPa].
#define AVO
Avogadro constant [1/mol].
#define KB
Boltzmann constant [kg m^2/(K s^2)].
#define SO2_CORR_B
Exponent of the high-SO2 correction [1].
#define COMPRESS_BPV(n, stored_size)
Calculate bits per value from stored size and element count.
#define MH2O
Molar mass of water vapor [g/mol].
#define METVAR
Number of 3-D meteorological variables.
#define NENS
Maximum number of data points for ensemble analysis.
#define FWRITE(ptr, type, size, out)
Write data from memory to a file stream.
#define PW(p, h2o)
Calculate partial water vapor pressure.
#define H0
Scale height [km].
#define NC_PUT_ATT_GLOBAL(attname, text)
Add a global text attribute to a NetCDF file.
#define MOLEC_DENS(p, t)
Calculate the density of a gas molecule.
#define LAPSE(p1, t1, p2, t2)
Calculate lapse rate.
#define NC(cmd)
Execute a NetCDF command and check for errors.
#define RADIO_DRY_VDEP_I131
Dry deposition velocity of aerosol-bound I-131 [m/s].
#define SELECT_TIMER(id, group)
Select and start a timer with specific attributes.
#define RADIO_DRY_VDEP_CS137
Dry deposition velocity of Cs-137 [m/s].
#define SO2_DISS_K1_REF
First SO2 dissociation constant at CHEM_REF_TEMP [mol/L].
#define ECC_READ_3D(variable, level, target, scaling_factor, found_flag)
Writes 3D data from a grib message into the meteo struct.
void compress_zfp(const ctl_t *ctl, const met_t *met, const char *varname, float *array, const int decompress, FILE *level_log, FILE *inout)
Compresses or decompresses a 3D array of floats using the ZFP library.
#define SO2_DISS_K1_TEMP
Temperature dependence of the first SO2 dissociation constant [K].
#define DOTP(a, b)
Calculate the dot product of two vectors.
#define RA
Specific gas constant of dry air [J/(kg K)].
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_eta_d
Quantity array index for diagnosed eta vertical coordinate.
int qnt_target_subdomain
Quantity array index for destination subdomain in domain decomposition.
int met_nc_scale
Check netCDF scaling factors (0=no, 1=yes).
int qnt_pel
Quantity array index for pressure at equilibrium level (EL).
int csi_nz
Number of altitudes of gridded CSI data.
double molmass
Molar mass [g/mol].
int qnt_p
Quantity array index for pressure.
int qnt_Cccl2f2
Quantity array index for CFC-12 volume mixing ratio (chemistry code).
int dd_halos_size
Domain decomposition 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 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).
int qnt_vz
Quantity array index for vertical velocity.
int qnt_ho2
Quantity array index for HO2 volume mixing ratio (climatology).
double csi_z1
Upper altitude of gridded CSI data [km].
double stat_t0
Start time for station output [s].
double oh_chem_beta
Beta parameter for diurnal variability of OH.
int dd
Domain decomposition (0=no, 1=yes, 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).
double budget_dt_out
Time step for mass budget output [s].
int qnt_zg
Quantity array index for geopotential height.
double vtk_offset
Vertical offset for VTK data [km].
int qnt_v
Quantity array index for meridional wind.
int qnt_mloss_dry
Quantity array index for total mass loss due to dry deposition.
double bound_vmr_trend
Boundary conditions volume mixing ratio trend [ppv/s].
double met_zfp_tol[METVAR]
ZFP compression tolerance.
int met_cache
Preload meteo data into disk cache (0=no, 1=yes).
int qnt_oh
Quantity array index for OH volume mixing ratio (climatology).
int met_sz3_prec[METVAR]
SZ3 compression precision.
char qnt_unit[NQ][LEN]
Quantity units.
int qnt_Ch
Quantity array index for H volume mixing ratio (chemistry code).
int met_press_level_def
Use predefined pressure levels or not.
int oh_chem_reaction
Reaction type for OH chemistry (0=none, 2=bimolecular, 3=termolecular).
int qnt_h2o
Quantity array index for water vapor volume mixing ratio.
int prof_ny
Number of latitudes of gridded profile data.
int qnt_rhice
Quantity array index for relative humidity over ice.
int qnt_rho
Quantity array index for density of air.
double sample_dz
Layer depth for sample output [km].
double tdec_strat
Life time of particles in the stratosphere [s].
int obs_type
Type of observation data files (0=ASCII, 1=netCDF).
int grid_nc_quant[NQ]
Number of digits for quantization of netCDF grid data files (0=off).
int qnt_us
Quantity array index for surface zonal wind.
double grid_lon1
Upper longitude of gridded data [deg].
int qnt_Cn2o
Quantity array index for N2O volume mixing ratio (chemistry code).
int qnt_Cccl3f
Quantity array index for CFC-11 volume mixing ratio (chemistry code).
char qnt_name[NQ][LEN]
Quantity names.
int depo_type
DEPO_TYPE of deposition files (0=ASCII, 1=netCDF, default: 0).
char budget_basename[LEN]
Basename of mass budget data file.
char atm_basename[LEN]
Basename of atmospheric data files.
double mixing_lat0
Lower latitude of mixing grid [deg].
int nens
Number of ensembles.
int qnt_pt
Quantity array index for tropopause pressure.
int qnt_cl
Quantity array index for total column cloud water.
int advect
Advection scheme (1=Euler, 2=midpoint, 4=Runge-Kutta).
double prof_z1
Upper altitude of gridded profile data [km].
double met_lev_hyam[EP]
Meteo data model level a coefficients.
int qnt_t
Quantity array index for temperature.
int atm_filter
Time filter for atmospheric data output (0=none, 1=missval, 2=remove).
int kpp_chem
Switch for KPP chemistry module (0=off, 1=on).
int qnt_zeta
Quantity array index for zeta vertical coordinate.
double conv_pbl_trans
Depth of PBL transition layer (fraction of PBL pressure thickness).
int met_lz4_accel
LZ4 acceleration factor (>=1, default=8).
char ens_basename[LEN]
Basename of ensemble data file.
int qnt_Ai131
Quantity array index for radioactive activity of I-131.
double wet_depo_pre[2]
Coefficients for precipitation calculation.
double mixing_tau_trop
E-folding time for interparcel mixing in the troposphere [s].
int met_vert_coord
Vertical coordinate of input meteo data (0=plev, 1=mlev_p_file, 2=mlev_ab_file, 3=mlev_ab_full,...
double csi_z0
Lower altitude of gridded CSI data [km].
int qnt_lapse
Quantity array index for lapse rate.
int qnt_Apb210
Quantity array index for radioactive activity of Pb-210.
double stat_lat
Latitude of station [deg].
int qnt_Cho2
Quantity array index for HO2 volume mixing ratio (chemistry code).
double wet_depo_bc_h[2]
Coefficients for wet deposition below cloud (Henry's law: Hb, Cb).
int grid_ny
Number of latitudes of gridded data.
int qnt_Csf6
Quantity array index for SF6 volume mixing ratio (chemistry code).
int qnt_Ch2o
Quantity array index for H2O volume mixing ratio (chemistry code).
double met_detrend
FWHM of horizontal Gaussian used for detrending [km].
int conv_mix_pbl
Vertical mixing in the PBL (0=off, 1=on).
char metbase[LEN]
Basename for meteo data.
double bound_dps
Boundary conditions surface layer depth [hPa].
double met_cms_eps[METVAR]
cmultiscale compression epsilon.
int chemgrid_nz
Number of altitudes of chemistry grid.
int qnt_cape
Quantity array index for convective available potential energy (CAPE).
int qnt_zeta_dot
Quantity array index for velocity of zeta vertical coordinate.
double bound_mass_trend
Boundary conditions mass per particle trend [kg/s].
int met_cms_nd0y
cmultiscale number of cells of coarsest grid in y-direction.
int mixing_nz
Number of altitudes of mixing grid.
int qnt_o3c
Quantity array index for total column ozone.
double bound_p0
Boundary conditions bottom pressure [hPa].
double mixing_lon0
Lower longitude of mixing grid [deg].
char clim_ccl4_timeseries[LEN]
Filename of CFC-10 time series.
int qnt_Co3
Quantity array index for O3 volume mixing ratio (chemistry code).
int qnt_tsts
Quantity array index for T_STS.
int grid_nz
Number of altitudes of gridded data.
char clim_oh_filename[LEN]
Filename of OH climatology.
int qnt_nss
Quantity array index for northward turbulent surface stress.
double ens_dt_out
Time step for ensemble output [s].
char sample_basename[LEN]
Basename of sample data file.
int atm_stride
Particle index stride for atmospheric data files.
int met_relhum
Try to read relative humidity (0=no, 1=yes).
double mixing_lat1
Upper latitude of mixing grid [deg].
double atm_dt_out
Time step for atmospheric data output [s].
char clim_sf6_timeseries[LEN]
Filename of SF6 time series.
int met_lossy_scale[METVAR]
Apply levelwise [0,1] scaling before lossy compression (0=off, 1=on).
double prof_lat1
Upper latitude of gridded profile data [deg].
int qnt_current_subdomain
Quantity array index for current subdomain in domain decomposition.
int met_cms_batch
cmultiscale batch size.
double psc_h2o
H2O volume mixing ratio for PSC analysis.
int met_sp
Smoothing for pressure levels.
double prof_lon0
Lower longitude of gridded profile data [deg].
int qnt_Axe133
Quantity array index for radioactive activity of Xe-133.
int chemgrid_nx
Number of longitudes of chemistry grid.
int qnt_pct
Quantity array index for cloud top pressure.
int qnt_mloss_kpp
Quantity array index for total mass loss due to KPP chemistry.
int qnt_psat
Quantity array index for saturation pressure over water.
double met_lev_hybm[EP]
Meteo data model level b coefficients.
double prof_lat0
Lower latitude of gridded profile data [deg].
int qnt_cin
Quantity array index for convective inhibition (CIN).
double turb_pbl_trans
Depth of turbulent PBL transition layer (fraction of PBL pressure thickness).
double psc_hno3
HNO3 volume mixing ratio for PSC analysis.
double prof_lon1
Upper longitude of gridded profile data [deg].
int met_nc_quant
Number of digits for quantization of netCDF meteo files (0=off).
int h2o2_chem_reaction
Reaction type for H2O2 chemistry (0=none, 1=SO2).
int qnt_Co3p
Quantity array index for O(3P) volume mixing ratio (chemistry code).
int atm_nc_quant[NQ]
Number of digits for quantization of netCDF atmospheric data files (0=off).
double wet_depo_bc_ret_ratio
Coefficients for wet deposition below cloud: retention ratio.
int chemgrid_ny
Number of latitudes of chemistry grid.
int qnt_Abe7
Quantity array index for radioactive activity of Be-7.
char clim_ccl3f_timeseries[LEN]
Filename of CFC-11 time series.
int met_cms_zstd
cmultiscale ZSTD compression (0=off, 1=on).
int met_cms_maxlev
cmultiscale maximum refinement level.
int grid_sparse
Sparse output in grid data files (0=no, 1=yes).
double met_sz3_tol[METVAR]
SZ3 compression tolerance.
char vtk_basename[LEN]
Basename of VTK data files.
double dry_depo_vdep
Dry deposition velocity [m/s].
int qnt_tt
Quantity array index for tropopause temperature.
int met_np
Number of target pressure levels.
int qnt_ens
Quantity array index for ensemble IDs.
int met_nc_level
zlib compression level of netCDF meteo files (0=off).
double mixing_dt
Time interval for mixing [s].
double mixing_tau_strat
E-folding time for interparcel mixing in the stratosphere [s].
int qnt_Arn222
Quantity array index for radioactive activity of Rn-222.
int qnt_mloss_h2o2
Quantity array index for total mass loss due to H2O2 chemistry.
double vtk_scale
Vertical scaling factor for VTK data.
char clim_ccl2f2_timeseries[LEN]
Filename of CFC-12 time series.
double wet_depo_ic_h[2]
Coefficients for wet deposition in cloud (Henry's law: Hb, Cb).
double turb_dx_pbl
Horizontal turbulent diffusion coefficient (PBL) [m^2/s].
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).