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 oh =
clim_zm(&clim->
oh, t, lat, p);
108 const double csza =
cos_sza(t, lon, lat);
109 const double denom = (csza >= csza_thresh) ? csza : csza_thresh;
120 const double sza_thresh =
DEG2RAD(85.), csza_thresh = cos(sza_thresh);
123 for (
int it = 0; it < clim->
oh.
ntime; it++)
124 for (
int iz = 0; iz < clim->
oh.
np; iz++)
125 for (
int iy = 0; iy < clim->
oh.
nlat; iy++) {
132 for (
double lon = -180; lon < 180; lon += 1.0) {
135 const double denom = (csza >= csza_thresh) ? csza : csza_thresh;
141 clim->
oh.
vmr[it][iz][iy] /= (sum / (double) n);
156 if (p < photo->p[photo->
np - 1])
157 p_help = photo->
p[photo->
np - 1];
158 else if (p > photo->
p[0])
159 p_help = photo->
p[0];
162 double sza_help = sza;
163 if (sza < photo->sza[0])
164 sza_help = photo->
sza[0];
165 else if (sza > photo->
sza[photo->
nsza - 1])
166 sza_help = photo->
sza[photo->
nsza - 1];
169 double o3c_help = o3c;
170 if (o3c < photo->o3c[0])
171 o3c_help = photo->
o3c[0];
172 else if (o3c > photo->
o3c[photo->
no3c - 1])
173 o3c_help = photo->
o3c[photo->
no3c - 1];
181 const double aux00 =
LIN(photo->
p[ip], rate[ip][isza][io3c],
182 photo->
p[ip + 1], rate[ip + 1][isza][io3c],
184 const double aux01 =
LIN(photo->
p[ip], rate[ip][isza][io3c + 1],
185 photo->
p[ip + 1], rate[ip + 1][isza][io3c + 1],
187 const double aux10 =
LIN(photo->
p[ip], rate[ip][isza + 1][io3c],
188 photo->
p[ip + 1], rate[ip + 1][isza + 1][io3c],
190 const double aux11 =
LIN(photo->
p[ip], rate[ip][isza + 1][io3c + 1],
191 photo->
p[ip + 1], rate[ip + 1][isza + 1][io3c + 1],
194 LIN(photo->
o3c[io3c], aux00, photo->
o3c[io3c + 1], aux01, o3c_help);
196 LIN(photo->
o3c[io3c], aux10, photo->
o3c[io3c + 1], aux11, o3c_help);
198 LIN(photo->
sza[isza], aux0, photo->
sza[isza + 1], aux1, sza_help);
199 return MAX(aux, 0.0);
210 double sec =
FMOD(t, 365.25 * 86400.);
212 sec += 365.25 * 86400.;
220 clim->
tropo[isec][ilat],
222 clim->
tropo[isec][ilat + 1], lat);
224 clim->
tropo[isec + 1][ilat],
226 clim->
tropo[isec + 1][ilat + 1], lat);
236 LOG(1,
"Initialize tropopause data...");
240 double tropo_time[12] = {
241 1209600.00, 3888000.00, 6393600.00,
242 9072000.00, 11664000.00, 14342400.00,
243 16934400.00, 19612800.00, 22291200.00,
244 24883200.00, 27561600.00, 30153600.00
250 const double tropo_lat[73] = {
251 -90, -87.5, -85, -82.5, -80, -77.5, -75, -72.5, -70, -67.5,
252 -65, -62.5, -60, -57.5, -55, -52.5, -50, -47.5, -45, -42.5,
253 -40, -37.5, -35, -32.5, -30, -27.5, -25, -22.5, -20, -17.5,
254 -15, -12.5, -10, -7.5, -5, -2.5, 0, 2.5, 5, 7.5, 10, 12.5,
255 15, 17.5, 20, 22.5, 25, 27.5, 30, 32.5, 35, 37.5, 40, 42.5,
256 45, 47.5, 50, 52.5, 55, 57.5, 60, 62.5, 65, 67.5, 70, 72.5,
257 75, 77.5, 80, 82.5, 85, 87.5, 90
262 const double tropo[12][73] = {
263 {324.1, 325.6, 325, 324.3, 322.5, 319.7, 314, 307.2, 301.8, 299.6,
264 297.1, 292.2, 285.6, 276.1, 264, 248.9, 231.9, 213.5, 194.4,
265 175.3, 157, 140.4, 126.7, 116.3, 109.5, 105.4, 103, 101.4, 100.4,
266 99.69, 99.19, 98.84, 98.56, 98.39, 98.39, 98.42, 98.44, 98.54,
267 98.68, 98.81, 98.89, 98.96, 99.12, 99.65, 101.4, 105.4, 113.5, 128,
268 152.1, 184.7, 214, 234.1, 247.3, 255.8, 262.6, 267.7, 271.7, 275,
269 277.2, 279, 280.1, 280.4, 280.6, 280.1, 279.3, 278.3, 276.8, 275.8,
270 275.3, 275.6, 275.4, 274.1, 273.5},
271 {337.3, 338.7, 337.8, 336.4, 333, 328.8, 321.1, 312.6, 306.6, 303.7,
272 300.2, 293.8, 285.4, 273.8, 259.6, 242.7, 224.4, 205.2, 186, 167.5,
273 150.3, 135, 122.8, 113.9, 108.2, 104.7, 102.5, 101.1, 100.2, 99.42,
274 98.88, 98.52, 98.25, 98.09, 98.07, 98.1, 98.12, 98.2, 98.25, 98.27,
275 98.26, 98.27, 98.36, 98.79, 100.2, 104.2, 113.7, 131.2, 159.5, 193,
276 220.4, 238.1, 250.2, 258.1, 264.7, 269.7, 273.7, 277.3, 280.2, 282.8,
277 284.9, 286.5, 288.1, 288.8, 289, 288.5, 287.2, 286.3, 286.1, 287.2,
278 287.5, 286.2, 285.8},
279 {335, 336, 335.7, 335.1, 332.3, 328.1, 320.6, 311.8, 305.1, 301.9,
280 297.6, 290, 280.4, 268.3, 254.6, 239.6, 223.9, 207.9, 192.2, 176.9,
281 161.7, 146.4, 132.2, 120.6, 112.3, 107.2, 104.3, 102.4, 101.3,
282 100.4, 99.86, 99.47, 99.16, 98.97, 98.94, 98.97, 99, 99.09, 99.2,
283 99.31, 99.35, 99.41, 99.51, 99.86, 101.1, 104.9, 114.3, 131, 156.8,
284 186.3, 209.3, 224.6, 236.8, 246.3, 254.9, 262.3, 268.8, 274.8,
285 279.9, 284.6, 288.6, 291.6, 294.9, 297.5, 299.8, 301.8, 303.1,
286 304.3, 304.9, 306, 306.6, 306.2, 306},
287 {306.2, 306.7, 305.7, 307.1, 307.3, 306.4, 301.8, 296.2, 292.4,
288 290.3, 287.1, 280.9, 273.4, 264.3, 254.1, 242.8, 231, 219, 207.2,
289 195.5, 183.3, 169.7, 154.7, 138.7, 124.1, 113.6, 107.8, 104.7,
290 102.8, 101.7, 100.9, 100.4, 100, 99.79, 99.7, 99.66, 99.68, 99.79,
291 99.94, 100.2, 100.5, 100.9, 101.4, 102.1, 103.4, 107, 115.2, 129.1,
292 148.7, 171, 190.8, 205.6, 218.4, 229.4, 239.6, 248.6, 256.5,
293 263.7, 270.3, 276.6, 282.6, 288.1, 294.5, 300.4, 306.3, 311.4,
294 315.1, 318.3, 320.3, 322.2, 322.8, 321.5, 321.1},
295 {266.5, 264.9, 260.8, 261, 262, 263, 261.3, 259.7, 259.2, 259.8,
296 260.1, 258.6, 256.7, 253.6, 249.5, 243.9, 237.4, 230, 222.1, 213.9,
297 205, 194.4, 180.4, 161.8, 140.7, 122.9, 112.1, 106.7, 104.1, 102.7,
298 101.8, 101.4, 101.1, 101, 101, 101, 101.1, 101.2, 101.5, 101.9,
299 102.4, 103, 103.8, 104.9, 106.8, 110.1, 115.6, 124, 135.2, 148.9,
300 165.2, 181.3, 198, 211.8, 223.5, 233.8, 242.9, 251.5, 259, 266.2,
301 273.1, 279.2, 286.2, 292.8, 299.6, 306, 311.1, 315.5, 318.8, 322.6,
302 325.3, 325.8, 325.8},
303 {220.1, 218.1, 210.8, 207.2, 207.6, 210.5, 211.4, 213.5, 217.3,
304 222.4, 227.9, 232.8, 237.4, 240.8, 242.8, 243, 241.5, 238.6, 234.2,
305 228.5, 221, 210.7, 195.1, 172.9, 147.8, 127.6, 115.6, 109.9, 107.1,
306 105.7, 105, 104.8, 104.8, 104.9, 105, 105.1, 105.3, 105.5, 105.8,
307 106.4, 107, 107.6, 108.1, 108.8, 110, 111.8, 114.2, 117.4, 121.6,
308 127.9, 137.3, 151.2, 169.5, 189, 205.8, 218.9, 229.1, 237.8, 245,
309 251.5, 257.1, 262.3, 268.2, 274, 280.4, 286.7, 292.4, 297.9, 302.9,
310 308.5, 312.2, 313.1, 313.3},
311 {187.4, 184.5, 173.3, 166.1, 165.4, 167.8, 169.6, 173.6, 179.6,
312 187.9, 198.9, 210, 220.5, 229.2, 235.7, 239.9, 241.8, 241.6, 239.6,
313 235.8, 229.4, 218.6, 200.9, 175.9, 149.4, 129.4, 118.3, 113.1,
314 110.8, 109.7, 109.3, 109.4, 109.7, 110, 110.2, 110.4, 110.5, 110.7,
315 111, 111.4, 111.8, 112.1, 112.3, 112.7, 113.2, 113.9, 115, 116.4,
316 117.9, 120.4, 124.1, 130.9, 142.2, 159.6, 179.6, 198.5, 212.9,
317 224.2, 232.7, 239.1, 243.8, 247.7, 252.4, 257.3, 263.2, 269.5,
318 275.4, 281.1, 286.3, 292, 296.3, 298.2, 298.8},
319 {166, 166.4, 155.7, 148.3, 147.1, 149, 152.1, 157, 163.6, 172.4,
320 185.3, 199.2, 212.6, 224, 233.2, 239.6, 243.3, 244.6, 243.6, 240.3,
321 233.9, 222.6, 203.7, 177, 149.5, 129.7, 119, 114, 111.7, 110.7,
322 110.3, 110.3, 110.6, 110.9, 111.1, 111.3, 111.5, 111.6, 111.9,
323 112.2, 112.5, 112.6, 112.8, 113, 113.4, 114, 115.1, 116.5, 118.3,
324 120.9, 124.4, 130.2, 139.4, 154.6, 173.8, 193.1, 208.1, 220.4,
325 230.1, 238.2, 244.7, 249.5, 254.5, 259.3, 264.5, 269.4, 273.7,
326 278.2, 282.6, 287.4, 290.9, 292.5, 293},
327 {171.9, 172.8, 166.2, 162.3, 161.4, 162.5, 165.2, 169.6, 175.3,
328 183.1, 193.8, 205.9, 218.3, 229.6, 238.5, 244.3, 246.9, 246.7,
329 243.8, 238.4, 230.2, 217.9, 199.6, 174.9, 148.9, 129.8, 119.5,
330 114.8, 112.3, 110.9, 110.3, 110.1, 110.2, 110.3, 110.4, 110.5,
331 110.6, 110.8, 111, 111.4, 111.8, 112, 112.2, 112.4, 112.9, 113.6,
332 114.7, 116.3, 118.4, 121.9, 127.1, 136.1, 149.8, 168.4, 186.9,
333 203.3, 217, 229.1, 238.7, 247, 254, 259.3, 264.3, 268.3, 272.5,
334 276.6, 280.4, 284.4, 288.4, 293.3, 297.2, 298.7, 299.1},
335 {191.6, 192.2, 189, 188.1, 190.2, 193.7, 197.8, 202.9, 208.5,
336 215.6, 224.2, 233.1, 241.2, 247.3, 250.8, 251.3, 248.9, 244.2,
337 237.3, 228.4, 217.2, 202.9, 184.5, 162.5, 140.7, 124.8, 116.2,
338 111.8, 109.4, 107.9, 107, 106.7, 106.6, 106.6, 106.7, 106.7,
339 106.8, 107, 107.4, 108, 108.7, 109.3, 109.8, 110.4, 111.2,
340 112.4, 114.2, 116.9, 121.1, 127.9, 139.3, 155.2, 173.6, 190.7,
341 206.1, 220.1, 232.3, 243, 251.8, 259.2, 265.7, 270.6, 275.3,
342 279.3, 283.3, 286.9, 289.7, 292.8, 296.1, 300.5, 303.9, 304.8,
344 {241.5, 239.6, 236.8, 237.4, 239.4, 242.3, 244.2, 246.4, 249.2,
345 253.6, 258.6, 262.7, 264.8, 264.2, 260.6, 254.1, 245.5, 235.3,
346 223.9, 211.7, 198.3, 183.1, 165.6, 147.1, 130.5, 118.7, 111.9,
347 108.1, 105.8, 104.3, 103.4, 102.8, 102.5, 102.4, 102.5, 102.5,
348 102.5, 102.7, 103.1, 103.8, 104.6, 105.4, 106.1, 107, 108.2,
349 109.9, 112.8, 117.5, 126, 140.4, 161, 181.9, 201.2, 216.8, 230.4,
350 241.8, 251.4, 259.9, 266.9, 272.8, 277.4, 280.4, 282.9, 284.6,
351 286.1, 287.4, 288.3, 289.5, 290.9, 294.2, 296.9, 297.5, 297.6},
352 {301.2, 300.3, 296.6, 295.4, 295, 294.3, 291.2, 287.4, 284.9, 284.7,
353 284.1, 281.5, 277.1, 270.4, 261.7, 250.6, 237.6, 223.1, 207.9, 192,
354 175.8, 158.8, 142.1, 127.6, 116.8, 109.9, 106, 103.6, 102.1, 101.1,
355 100.4, 99.96, 99.6, 99.37, 99.32, 99.32, 99.31, 99.46, 99.77, 100.2,
356 100.7, 101.3, 101.8, 102.7, 104.1, 106.8, 111.9, 121, 136.7, 160,
357 186.9, 209.9, 228.1, 241.2, 251.5, 259.5, 265.7, 270.9, 274.8, 278,
358 280.3, 281.8, 283, 283.3, 283.7, 283.8, 283, 282.2, 281.2, 281.4,
361 memcpy(clim->
tropo, tropo,
sizeof(clim->
tropo));
364 double tropomin = 1e99, tropomax = -1e99;
366 for (
int iy = 0; iy < clim->
tropo_nlat; iy++) {
367 tropomin =
MIN(tropomin, clim->
tropo[it][iy]);
368 tropomax =
MAX(tropomax, clim->
tropo[it][iy]);
373 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
377 LOG(2,
"Latitudes: %g, %g ... %g deg",
380 LOG(2,
"Tropopause altitude range: %g ... %g hPa",
Z(tropomax),
382 LOG(2,
"Tropopause pressure range: %g ... %g hPa", tropomin, tropomax);
392 if (t <= ts->time[0])
399 ts->
time[idx + 1], ts->
vmr[idx + 1], t);
412 double sec =
FMOD(t, 365.25 * 86400.);
414 sec += 365.25 * 86400.;
418 if (p < zm->p[zm->
np - 1])
419 p_help = zm->
p[zm->
np - 1];
420 else if (p > zm->
p[0])
424 double lat_help = lat;
425 if (lat < zm->lat[0])
426 lat_help = zm->
lat[0];
427 else if (lat > zm->
lat[zm->
nlat - 1])
428 lat_help = zm->
lat[zm->
nlat - 1];
436 const double aux00 =
LIN(zm->
p[ip], zm->
vmr[isec][ip][ilat],
437 zm->
p[ip + 1], zm->
vmr[isec][ip + 1][ilat],
439 const double aux01 =
LIN(zm->
p[ip], zm->
vmr[isec][ip][ilat + 1],
440 zm->
p[ip + 1], zm->
vmr[isec][ip + 1][ilat + 1],
442 const double aux10 =
LIN(zm->
p[ip], zm->
vmr[isec + 1][ip][ilat],
443 zm->
p[ip + 1], zm->
vmr[isec + 1][ip + 1][ilat],
445 const double aux11 =
LIN(zm->
p[ip], zm->
vmr[isec + 1][ip][ilat + 1],
446 zm->
p[ip + 1], zm->
vmr[isec + 1][ip + 1][ilat + 1],
449 LIN(zm->
lat[ilat], aux00, zm->
lat[ilat + 1], aux01, lat_help);
451 LIN(zm->
lat[ilat], aux10, zm->
lat[ilat + 1], aux11, lat_help);
452 const double aux =
LIN(zm->
time[isec], aux0, zm->
time[isec + 1], aux1, sec);
453 return MAX(aux, 0.0);
466 const int decompress,
470 const size_t nxy = nx * ny;
471 double lon[
EX], lat[
EY];
472 for (
size_t ix = 0; ix < nx; ix++)
473 lon[ix] = 360. * (
double) ix / ((double) nx - 1.);
474 for (
size_t iy = 0; iy < ny; iy++)
475 lat[iy] = 90. - 180. * (
double) iy / ((double) ny - 1.);
478 const char domain[] =
"[0.0, 360.0]x[-90.0, 90.0]";
479 const int Nd0_x = 48;
480 const int Nd0_y = 24;
481 const int max_level_grid = 6;
482 cms_param_t *cms_param
483 = cms_set_parameters(nx, ny, max_level_grid, Nd0_x, Nd0_y, domain);
486 double cr = 0, t_coars = 0, t_eval = 0;
492 for (
size_t ip = 0; ip < np; ip++) {
495 cms_module_t *cms_ptr = cms_init(cms_param);
500 cms_sol = cms_read_zstd_sol(cms_ptr, inout);
502 cms_sol = cms_read_sol(cms_ptr, inout);
505#pragma omp parallel for collapse(2) default(shared)
506 for (
size_t ix = 0; ix < nx; ix++)
507 for (
size_t iy = 0; iy < ny; iy++) {
509 const double x[] = { lon[ix], lat[iy] };
510 cms_eval(cms_ptr, cms_sol, x, &val);
511 array[
ARRAY_3D(ix, iy, ny, ip, np)] = (float) val;
515 cr += cms_compression_rate(cms_ptr, cms_sol) / (double) np;
518 cms_delete_sol(cms_sol);
519 cms_delete_module(cms_ptr);
523 LOG(2,
"Read 3-D variable: %s (CMS, RATIO= %g)", varname, cr);
530 cms_module_t *cms_ptr[
EP];
531 cms_sol_t *cms_sol[
EP];
535 ? (size_t) omp_get_max_threads()
537 for (
size_t ip0 = 0; ip0 < np; ip0 += dip) {
540 double t0 = omp_get_wtime();
543#pragma omp parallel for default(shared)
544 for (
size_t ip = ip0; ip <
MIN(ip0 + dip, np); ip++) {
548 ALLOC(tmp_arr,
float,
552 for (
size_t ix = 0; ix < nx; ++ix)
553 for (
size_t iy = 0; iy < ny; ++iy)
555 array[
ARRAY_3D(ix, iy, ny, ip, np)];
558 double c_thresh_test;
559 if (strcasecmp(varname,
"Z") == 0)
561 else if (strcasecmp(varname,
"T") == 0)
563 else if (strcasecmp(varname,
"U") == 0)
565 else if (strcasecmp(varname,
"V") == 0)
567 else if (strcasecmp(varname,
"W") == 0)
569 else if (strcasecmp(varname,
"PV") == 0)
571 else if (strcasecmp(varname,
"H2O") == 0)
573 else if (strcasecmp(varname,
"O3") == 0)
575 else if (strcasecmp(varname,
"LWC") == 0)
577 else if (strcasecmp(varname,
"RWC") == 0)
579 else if (strcasecmp(varname,
"IWC") == 0)
581 else if (strcasecmp(varname,
"SWC") == 0)
583 else if (strcasecmp(varname,
"CC") == 0)
586 ERRMSG(
"Variable name unknown!");
589 cms_ptr[ip] = cms_init(cms_param);
593 cms_read_arr_new(cms_ptr[ip], tmp_arr, lon, lat,
594 nx, ny, c_thresh_test);
601 t_coars += (omp_get_wtime() - t0);
604 for (
size_t ip = ip0; ip <
MIN(ip0 + dip, np); ip++) {
607 double *tmp_cms, *tmp_org, *tmp_diff;
608 ALLOC(tmp_cms,
double,
610 ALLOC(tmp_org,
double,
612 ALLOC(tmp_diff,
double,
616 t0 = omp_get_wtime();
619#pragma omp parallel for collapse(2) default(shared)
620 for (
size_t ix = 0; ix < nx; ix++)
621 for (
size_t iy = 0; iy < ny; iy++) {
622 const size_t idx =
ARRAY_2D(ix, iy, ny);
623 const double x[] = { lon[ix], lat[iy] };
624 cms_eval(cms_ptr[ip], cms_sol[ip], x, &tmp_cms[idx]);
625 tmp_org[idx] = array[
ARRAY_3D(ix, iy, ny, ip, np)];
626 tmp_diff[idx] = tmp_cms[idx] - tmp_org[idx];
630 t_eval += (omp_get_wtime() - t0);
634 "cmultiscale: var= %s / lev= %lu / ratio= %g / rho= %g"
635 " / mean= %g / sd= %g / min= %g / max= %g", varname, ip,
636 cms_compression_rate(cms_ptr[ip], cms_sol[ip]),
637 gsl_stats_correlation(tmp_cms, 1, tmp_org, 1, nxy),
638 gsl_stats_mean(tmp_diff, 1, nxy), gsl_stats_sd(tmp_diff, 1, nxy),
639 gsl_stats_min(tmp_diff, 1, nxy), gsl_stats_max(tmp_diff, 1, nxy));
642 cr += cms_compression_rate(cms_ptr[ip], cms_sol[ip]) / (double) np;
646 cms_save_zstd_sol(cms_sol[ip], inout, 3);
648 cms_save_sol(cms_sol[ip], inout);
651 cms_delete_sol(cms_sol[ip]);
652 cms_delete_module(cms_ptr[ip]);
660 LOG(2,
"Write 3-D variable: %s"
661 " (CMS, RATIO= %g, T_COARS= %g s, T_EVAL= %g s)",
662 varname, cr, t_coars, t_eval);
666 cms_delete_param(cms_param);
677 const int decompress,
680 double min[
EP], max[
EP], off[
EP], scl[
EP];
682 unsigned short *sarray;
685 ALLOC(sarray,
unsigned short,
692 LOG(2,
"Read 3-D variable: %s (pck, RATIO= %g)",
693 varname, (
double)
sizeof(
float) / (
double)
sizeof(
unsigned short));
702 FREAD(sarray,
unsigned short,
707#pragma omp parallel for default(shared)
708 for (
size_t ixy = 0; ixy < nxy; ixy++)
709 for (
size_t iz = 0; iz < nz; iz++)
711 = (
float) (sarray[ixy * nz + iz] * scl[iz] + off[iz]);
718 LOG(2,
"Write 3-D variable: %s (pck, RATIO= %g)",
719 varname, (
double)
sizeof(
float) / (
double)
sizeof(
unsigned short));
722 for (
size_t iz = 0; iz < nz; iz++) {
726 for (
size_t ixy = 1; ixy < nxy; ixy++)
727 for (
size_t iz = 0; iz < nz; iz++) {
728 if (array[ixy * nz + iz] < min[iz])
729 min[iz] = array[ixy * nz + iz];
730 if (array[ixy * nz + iz] > max[iz])
731 max[iz] = array[ixy * nz + iz];
735 for (
size_t iz = 0; iz < nz; iz++) {
736 scl[iz] = (max[iz] - min[iz]) / 65533.;
741#pragma omp parallel for default(shared)
742 for (
size_t ixy = 0; ixy < nxy; ixy++)
743 for (
size_t iz = 0; iz < nz; iz++)
745 sarray[ixy * nz + iz] = (
unsigned short)
746 ((array[ixy * nz + iz] - off[iz]) / scl[iz] + .5);
748 sarray[ixy * nz + iz] = 0;
757 FWRITE(sarray,
unsigned short,
779 if ((precision > 0) == (tolerance > 0.0))
780 ERRMSG(
"Exactly one of precision or tolerance must be set for SZ3!");
782 size_t r1 = (size_t) nx, r2 = (
size_t) ny, r3 = (size_t) nz,
783 outSize = 0, total_elems = r1 * r2 * r3;
785 unsigned char *bytes = NULL;
791 FREAD(&sz3size,
size_t,
796 FREAD(bytes,
unsigned char,
800 void *outData = SZ_decompress(SZ_FLOAT, bytes, sz3size, 0, 0, r3, r2, r1);
802 ERRMSG(
"Decompression failed!");
804 memcpy(array, outData, total_elems *
sizeof(
float));
809 LOG(2,
"Read 3-D variable: %s (SZ3, PREC=%d, TOL=%g, RATIO=%g)",
810 varname, precision, tolerance,
811 (
double) (total_elems *
sizeof(
float)) / (
double) sz3size);
817 const int errBoundMode = (precision > 0) ? REL : ABS;
818 const double absBound = (errBoundMode == ABS) ? tolerance : 0.0;
819 const double relBound =
820 (errBoundMode == REL) ? pow(2.0, -(
double) precision) : 0.0;
822 bytes = SZ_compress_args(SZ_FLOAT, array, &outSize,
823 errBoundMode, absBound, relBound, 0.0,
825 if (!bytes || outSize == 0)
826 ERRMSG(
"Compression failed!");
831 FWRITE(bytes,
unsigned char,
837 LOG(2,
"Write 3-D variable: %s (SZ3, PREC=%d, TOL=%g, RATIO=%g)",
838 varname, precision, tolerance,
839 (
double) (total_elems *
sizeof(
float)) / (
double) outSize);
854 const double tolerance,
855 const int decompress,
859 const size_t snx = (size_t) nx;
860 const size_t sny = (size_t) ny;
861 const size_t snz = (size_t) nz;
862 const zfp_type type = zfp_type_float;
863 zfp_field *field = zfp_field_3d(array, type, snx, sny, snz);
866 zfp_stream *zfp = zfp_stream_open(NULL);
868 ERRMSG(
"Failed to allocate zfp structures!");
872 double actual_tol = 0;
873 if ((precision > 0 && tolerance > 0) || (precision <= 0 && tolerance <= 0)) {
874 ERRMSG(
"Exactly one of precision or tolerance must be set for zfp!");
875 }
else if (precision > 0)
877 (int) zfp_stream_set_precision(zfp, (
unsigned int) precision);
878 else if (tolerance > 0)
879 actual_tol = zfp_stream_set_accuracy(zfp, tolerance);
882 const size_t bufsize = zfp_stream_maximum_size(zfp, field);
888 bitstream *stream = stream_open(buffer, bufsize);
889 zfp_stream_set_bit_stream(zfp, stream);
890 zfp_stream_rewind(zfp);
895 FREAD(&zfpsize,
size_t,
898 if (zfpsize > bufsize)
899 ERRMSG(
"Compressed data size exceeds allocated buffer!");
900 FREAD(buffer,
unsigned char,
903 if (!zfp_decompress(zfp, field)) {
904 ERRMSG(
"Decompression failed!");
907 ((double) (snx * sny * snz *
sizeof(
float))) / (double) zfpsize;
908 const double bpv = (8.0 * (double) zfpsize) / (double) (snx * sny * snz);
910 "Read 3-D variable: %s (ZFP, PREC= %d, TOL= %g, RATIO= %g, BPV= %g)",
911 varname, actual_prec, actual_tol, cr, bpv);
916 zfpsize = zfp_compress(zfp, field);
918 ERRMSG(
"Compression failed!");
923 FWRITE(buffer,
unsigned char,
928 ((double) (snx * sny * snz *
sizeof(
float))) / (double) zfpsize;
929 const double bpv = (8.0 * (double) zfpsize) / (double) (snx * sny * snz);
931 "Write 3-D variable: %s (ZFP, PREC= %d, TOL= %g, RATIO= %g, BPV= %g)",
932 varname, actual_prec, actual_tol, cr, bpv);
936 zfp_field_free(field);
937 stream_close(stream);
938 zfp_stream_close(zfp);
950 const int decompress,
955 const size_t uncomprLen = n *
sizeof(float);
956 size_t compsize, comprLen = ZSTD_compressBound(uncomprLen);
959 char *compr = calloc(comprLen, 1);
961 ERRMSG(
"Memory allocation failed!");
962 char *uncompr = (
char *) array;
966 FREAD(&comprLen,
size_t,
969 FREAD(compr,
unsigned char,
972 compsize = ZSTD_decompress(uncompr, uncomprLen, compr, comprLen);
973 if (ZSTD_isError(compsize) || compsize != uncomprLen)
974 ERRMSG(
"Decompression failed or size mismatch!");
975 LOG(2,
"Read 3-D variable: %s (ZSTD, RATIO= %g)",
976 varname, ((
double) uncomprLen) / (
double) comprLen);
981 compsize = ZSTD_compress(compr, comprLen, uncompr, uncomprLen, level);
982 if (ZSTD_isError(compsize)) {
983 ERRMSG(
"Compression failed!");
988 FWRITE(compr,
unsigned char,
992 LOG(2,
"Write 3-D variable: %s (ZSTD, RATIO= %g)",
993 varname, ((
double) uncomprLen) / (
double) compsize);
1009 const double D = sec / 86400 - 0.5;
1012 const double g =
DEG2RAD(357.529 + 0.98560028 * D);
1013 const double q = 280.459 + 0.98564736 * D;
1014 const double L =
DEG2RAD(q + 1.915 * sin(g) + 0.020 * sin(2 * g));
1017 const double e =
DEG2RAD(23.439 - 0.00000036 * D);
1020 const double sindec = sin(e) * sin(L);
1023 const double ra = atan2(cos(e) * sin(L), cos(L));
1026 const double GMST = 18.697374558 + 24.06570982441908 * D;
1029 const double LST = GMST + lon / 15;
1032 const double h = LST / 12 * M_PI - ra;
1035 const double lat_help =
DEG2RAD(lat);
1038 return sin(lat_help) * sindec + cos(lat_help) * sqrt(1 -
1039 SQR(sindec)) * cos(h);
1051 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
1052 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
1055 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
1056 *doy = d0l[mon - 1] + day - 1;
1058 *doy = d0[mon - 1] + day - 1;
1070 SELECT_TIMER(
"DD_ASSIGN_RECT_SUBDOMAINS",
"DD", NVTX_GPU);
1074#pragma acc enter data create(dd)
1075#pragma acc update device(dd->rank, dd->subdomain_lon_min, dd->subdomain_lon_max, dd->subdomain_lat_min, dd->subdomain_lat_max)
1076#pragma acc data present(atm, ctl, dd)
1077#pragma acc parallel loop independent gang vector
1079 for (
int ip = 0; ip < atm->
np; ip++) {
1081 double lont = atm->
lon[ip];
1093 (
"DD: Particle is outside the domain (lon: %f, lat: %f, subdomain: %d, subdomain bounds: [%f, %f], [%f, %f])",
1102#pragma acc exit data delete(dd)
1108#pragma acc enter data create(dd)
1109#pragma acc update device(dd->neighbours[:DD_NNMAX], dd->rank, dd->size, dd->subdomain_lon_min, dd->subdomain_lon_max, dd->subdomain_lat_min, dd->subdomain_lat_max)
1110#pragma acc data present(atm, ctl, dd)
1111#pragma acc parallel loop independent gang vector
1113 for (
int ip = 0; ip < atm->
np; ip++) {
1119 double lont = atm->
lon[ip];
1120 double latt = atm->
lat[ip];
1135 bound = (lont - lon_max > 90) ? 1 : 0;
1137 bound = (lon_min - lont > 90) ? 1 : 0;
1140 if ((lont >= lon_max) && (latt >= lat_max)) {
1144 "DD: Particle crossing to upper right: from rank %d to rank %d (lon: %f, lat: %f)",
1146 }
else if ((lont >= lon_max) && (latt <= lat_min)) {
1150 "DD: Particle crossing to lower right: from rank %d to rank %d (lon: %f, lat: %f)",
1152 }
else if ((lont <= lon_min) && (latt >= lat_max)) {
1156 "DD: Particle crossing to upper left: from rank %d to rank %d (lon: %f, lat: %f)",
1158 }
else if ((lont <= lon_min) && (latt <= lat_min)) {
1162 "DD: Particle crossing to lower left: from rank %d to rank %d (lon: %f, lat: %f)",
1164 }
else if (lont >= lon_max) {
1168 "DD: Particle crossing to right: from rank %d to rank %d (lon: %f, lat: %f)",
1170 }
else if (lont <= lon_min) {
1174 "DD: Particle crossing to left: from rank %d to rank %d (lon: %f, lat: %f)",
1176 }
else if (latt <= lat_min) {
1180 "DD: Particle crossing downward: from rank %d to rank %d (lon: %f, lat: %f)",
1182 }
else if (latt >= lat_max) {
1186 "DD: Particle crossing upward: from rank %d to rank %d (lon: %f, lat: %f)",
1193 if ((lont >= lon_max) && (latt >= lat_max)) {
1197 "DD: Particle crossing to upper left (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1199 }
else if ((lont >= lon_max) && (latt <= lat_min)) {
1203 "DD: Particle crossing to lower left (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1205 }
else if ((lont <= lon_min) && (latt >= lat_max)) {
1209 "DD: Particle crossing to upper right (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1211 }
else if ((lont <= lon_min) && (latt <= lat_min)) {
1215 "DD: Particle crossing to lower right (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1217 }
else if (lont >= lon_max) {
1221 "DD: Particle crossing to left (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1223 }
else if (lont <= lon_min) {
1227 "DD: Particle crossing to right (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1229 }
else if (latt <= lat_min) {
1233 "DD: Particle crossing downward (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1235 }
else if (latt >= lat_max) {
1239 "DD: Particle crossing upward (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1268#pragma acc exit data delete(dd)
1289 int npart = *nparticles;
1290#pragma acc enter data create( nparticles, particles[:DD_NPART])
1291#pragma acc update device( nparticles)
1292#pragma acc parallel loop present( atm, ctl, particles, cache, nparticles)
1294 for (
int ip = atm->
np; ip < atm->np + *nparticles; ip++)
1299 particles[ip - atm->
np].
time = atm->
time[ip];
1300 particles[ip - atm->
np].
lon = atm->
lon[ip];
1301 particles[ip - atm->
np].
lat = atm->
lat[ip];
1302 particles[ip - atm->
np].
p = atm->
p[ip];
1304 for (
int iq = 0; iq < ctl->
nq; iq++)
1305 particles[ip - atm->
np].q[iq] = atm->
q[iq][ip];
1308 "DD: Particle being prepared for transfer: subdomain %d -> destination %d (lon: %f, lat: %f)",
1315#pragma acc update host( particles[:npart])
1316#pragma acc exit data delete( nparticles, particles)
1334 double wrapped_lon = lon;
1335 while (wrapped_lon < 0)
1337 while (wrapped_lon >= 360)
1341 double wrapped_lat = lat;
1344 wrapped_lat = 180 - lat;
1345 wrapped_lon = fmod(wrapped_lon + 180, 360);
1346 }
else if (lat < -90) {
1348 wrapped_lat = -180 - lat;
1349 wrapped_lon = fmod(wrapped_lon + 180, 360);
1354 double lon_range = 360.0;
1365 LOG(2,
"nx_glob: %d", nx_glob);
1367 double lat_range = met->
lat[ny_glob - 1] - met->
lat[0];
1368 double global_lon_min = met->
lon[0];
1369 double global_lat_min = met->
lat[0];
1373 (int) ((wrapped_lon -
1376 (int) ((wrapped_lat -
1381 (
"DD: Input Lon: %f, Lat: %f | Wrapped Lon: %f, Lat: %f | Lon Range: %f, Lat Range: %f | Lon Min: %f, Lat Min: %f | Lon Idx: %d, Lat Idx: %d\n",
1382 lon, lat, wrapped_lon, wrapped_lat, lon_range, lat_range, global_lon_min,
1383 global_lat_min, lon_idx, lat_idx);
1388 0) ? 0 : ((lon_idx >=
1393 0) ? 0 : ((lat_idx >=
1395 dd_subdomains_meridional - 1 : lat_idx);
1401 if (target_rank >= mpi_size)
1402 target_rank = mpi_size - 1;
1403 if (target_rank < 0)
1433 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
1436 MPI_Request *requests_snd_nbr =
1437 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1438 MPI_Request *requests_rcv_nbr =
1439 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1440 MPI_Request *requests_snd_part =
1441 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1442 MPI_Request *requests_rcv_part =
1443 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1444 MPI_Status *states =
1445 (MPI_Status *) calloc((
size_t) nneighbours,
sizeof(MPI_Status));
1448 for (
int i = 0; i < nneighbours; i++) {
1449 requests_snd_nbr[i] = MPI_REQUEST_NULL;
1450 requests_rcv_nbr[i] = MPI_REQUEST_NULL;
1451 requests_snd_part[i] = MPI_REQUEST_NULL;
1452 requests_rcv_part[i] = MPI_REQUEST_NULL;
1456 for (
int idest = 0; idest < nneighbours; idest++) {
1459 if (neighbours[idest] < 0)
1465 for (
int ip = 0; ip < *nparticles; ip++)
1468 nbs[idest] = help_sum;
1471 LOG(3,
"DD: Rank %d sending %d particles to neighbour %d (rank %d)",
1472 rank, help_sum, idest, neighbours[idest]);
1477 MPI_Isend(&nbs[idest], 1, MPI_INT,
1478 neighbours[idest], 0, MPI_COMM_WORLD, &requests_snd_nbr[idest]);
1481 if (nbs[idest] == 0)
1490 for (
int ip = 0; ip < *nparticles; ip++) {
1491 if ((
int) particles[ip].q[ctl.
qnt_destination] == neighbours[idest]) {
1492 memcpy(&send_buffers[idest][ibs], &particles[ip],
sizeof(
particle_t));
1496 if (ibs == nbs[idest])
1503 MPI_Isend(send_buffers[idest], nbs[idest], MPI_Particle,
1504 neighbours[idest], 1, MPI_COMM_WORLD,
1505 &requests_snd_part[idest]);
1511 for (
int isourc = 0; isourc < nneighbours; isourc++) {
1514 if (neighbours[isourc] < 0) {
1515 requests_rcv_nbr[isourc] = MPI_REQUEST_NULL;
1520 MPI_Irecv(&nbr[isourc], 1, MPI_INT, neighbours[isourc], 0, MPI_COMM_WORLD,
1521 &requests_rcv_nbr[isourc]);
1525 MPI_Waitall(nneighbours, requests_rcv_nbr, states);
1528 for (
int isourc = 0; isourc < nneighbours; isourc++) {
1531 if ((neighbours[isourc] < 0) || (nbr[isourc] == 0)) {
1532 requests_rcv_part[isourc] = MPI_REQUEST_NULL;
1540 MPI_Irecv(recieve_buffers[isourc], nbr[isourc], MPI_Particle,
1541 neighbours[isourc], 1, MPI_COMM_WORLD,
1542 &requests_rcv_part[isourc]);
1546 MPI_Waitall(nneighbours, requests_rcv_part, states);
1554 for (
int isourc = 0; isourc < nneighbours; isourc++) {
1557 if (neighbours[isourc] < 0)
1560 if (nbr[isourc] > 0) {
1561 LOG(3,
"DD: Rank %d receiving %d particles from neighbour %d (rank %d)",
1562 rank, nbr[isourc], isourc, neighbours[isourc]);
1566 for (
int ip = 0; ip < nbr[isourc]; ip++) {
1567 memcpy(&particles[ip + api], &recieve_buffers[isourc][ip],
1581 MPI_Waitall(nneighbours, requests_snd_part, states);
1582 MPI_Waitall(nneighbours, requests_snd_nbr, states);
1585 for (
int i = 0; i < nneighbours; i++) {
1587 if ((send_buffers[i] != NULL) && (nbs[i] != 0)) {
1588 free(send_buffers[i]);
1589 send_buffers[i] = NULL;
1592 if ((recieve_buffers[i] != NULL) && (nbr[i] != 0)) {
1593 free(recieve_buffers[i]);
1594 recieve_buffers[i] = NULL;
1611 const int rank = dd->
rank;
1612 const int size = dd->
size;
1616 nb[0] = (size + rank - m) % size;
1617 nb[3] = (rank + m) % size;
1618 nb[1] = ((rank + 1) % m == 0) ?
DD_SPOLE : (size + rank - m + 1) % size;
1619 nb[2] = (rank % m == 0) ?
DD_NPOLE : (size + rank - m - 1) % size;
1620 nb[4] = ((rank + 1) % m == 0) ?
DD_SPOLE : (rank + m + 1) % size;
1621 nb[5] = (rank % m == 0) ?
DD_NPOLE : (rank + m - 1) % size;
1622 nb[6] = (rank % m == 0) ?
DD_NPOLE : rank - 1;
1623 nb[7] = ((rank + 1) % m == 0) ?
DD_SPOLE : rank + 1;
1639 double lon_spacing = met->
lon[1] - met->
lon[0];
1643 double total_range = met->
lon[nx_glob - 1] - met->
lon[0] + lon_spacing;
1646 return (fabs(total_range - 360.0) < 0.01);
1660 ERRMSG(
"The number of tasks and subdomains is not identical.");
1691 int npart = *nparticles;
1692#pragma acc enter data create(nparticles, particles[:DD_NPART])
1693#pragma acc update device(particles[:npart], nparticles)
1694#pragma acc data present(atm, ctl, cache, particles, nparticles)
1695#pragma acc parallel loop
1697 for (
int ip = atm->
np; ip < atm->np + *nparticles; ip++) {
1698 atm->
time[ip] = particles[ip - atm->
np].
time;
1699 atm->
lon[ip] = particles[ip - atm->
np].
lon;
1700 atm->
lat[ip] = particles[ip - atm->
np].
lat;
1701 atm->
p[ip] = particles[ip - atm->
np].
p;
1702 for (
int iq = 0; iq < ctl->
nq; iq++)
1703 atm->
q[iq][ip] = particles[ip - atm->
np].q[iq];
1707#pragma acc exit data delete(nparticles, particles)
1711 atm->
np += *nparticles;
1713#pragma acc update device(atm->np)
1716 ERRMSG(
"Number of particles to high. Increase NP!");
1725 MPI_Datatype types[5] = { MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE,
1726 MPI_DOUBLE, MPI_DOUBLE
1728 int blocklengths[5] = { 1, 1, 1, 1,
NQ };
1729 MPI_Aint displacements[5] = { offsetof(
particle_t, time),
1735 MPI_Type_create_struct(5, blocklengths, displacements, types, MPI_Particle);
1736 MPI_Type_commit(MPI_Particle);
1755 const int np = atm->
np;
1756 double amax = (met0->
nx * met0->
ny + met0->
ny) * met0->
np + met0->
np;
1758#pragma acc enter data create(amax, rank)
1759#pragma acc update device(rank, amax)
1760#pragma acc data present(ctl,met0,atm,dd,amax,rank)
1765#pragma acc parallel loop independent gang vector
1767#pragma omp parallel for default(shared)
1769 for (
int ip = 0; ip < np; ip++) {
1777 dd->a[ip] = amax + 1;
1779 dd->a[ip] = amax + 2;
1787#pragma acc host_data use_device(dd->a,dd->p)
1789 thrustSortWrapper(dd->a, np, dd->p);
1792 ERRMSG(
"GSL sort fallback not available on GPU, use THRUST!");
1794 gsl_sort_index((
size_t *) (dd->p), (dd->a), 1, (
size_t) np);
1802 for (
int iq = 0; iq < ctl->
nq; iq++)
1808#pragma acc parallel loop reduction(+:npt) present(atm, rank, ctl)
1810 for (
int ip = 0; ip < np; ip++)
1816 int nparticlest = 0;
1818#pragma acc parallel loop reduction(+:nparticlest) present(atm, rank, ctl)
1820 for (
int ip = npt; ip < np; ip++)
1826 *nparticles = nparticlest;
1830 for (
int ip = 0; ip < np; ip++)
1836 (
"DD: Rank %d: %d particles have subdomain index -1 and will be lost (kept: %d, to_send: %d, total_before: %d)",
1837 *rank, nlost, npt, nparticlest, np);
1842#pragma acc update device(atm->np)
1847 (
"Number of particles to send and recieve to small. Increase DD_NPART!");
1851#pragma acc exit data delete(amax, rank)
1866#pragma acc data present(dd,a)
1867#pragma acc parallel loop independent gang vector
1869#pragma omp parallel for default(shared)
1871 for (
int ip = 0; ip < np; ip++)
1872 dd->help[ip] = a[dd->p[ip]];
1874#pragma acc parallel loop independent gang vector
1876#pragma omp parallel
for default(shared)
1878 for (
int ip = 0; ip < np; ip++)
1879 a[ip] = dd->help[ip];
1892 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
1893 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
1898 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
1899 for (i = 11; i > 0; i--)
1903 *day = doy - d0l[i] + 1;
1905 for (i = 11; i > 0; i--)
1909 *day = doy - d0[i] + 1;
1920 double data[2 *
EX];
1924 ERRMSG(
"Too many data points!");
1927 gsl_fft_complex_wavetable *wavetable =
1928 gsl_fft_complex_wavetable_alloc((
size_t) n);
1929 gsl_fft_complex_workspace *workspace =
1930 gsl_fft_complex_workspace_alloc((
size_t) n);
1933 for (
int i = 0; i < n; i++) {
1934 data[2 * i] = fcReal[i];
1935 data[2 * i + 1] = fcImag[i];
1939 gsl_fft_complex_forward(data, 1, (
size_t) n, wavetable, workspace);
1942 for (
int i = 0; i < n; i++) {
1943 fcReal[i] = data[2 * i];
1944 fcImag[i] = data[2 * i + 1];
1948 gsl_fft_complex_wavetable_free(wavetable);
1949 gsl_fft_complex_workspace_free(workspace);
1960 const double radius = z +
RE;
1961 const double latrad =
DEG2RAD(lat);
1962 const double lonrad =
DEG2RAD(lon);
1963 const double coslat = cos(latrad);
1965 x[0] = radius * coslat * cos(lonrad);
1966 x[1] = radius * coslat * sin(lonrad);
1967 x[2] = radius * sin(latrad);
1976 const char *metbase,
1977 const double dt_met,
1984 int year, mon, day, hour, min, sec;
1988 t6 = floor(t / dt_met) * dt_met;
1990 t6 = ceil(t / dt_met) * dt_met;
1993 jsec2time(t6, &year, &mon, &day, &hour, &min, &sec, &r);
1998 sprintf(filename,
"%s_YYYY_MM_DD_HH.nc", metbase);
2000 sprintf(filename,
"%s_YYYY_MM_DD_HH.bin", metbase);
2002 sprintf(filename,
"%s_YYYY_MM_DD_HH.pck", metbase);
2004 sprintf(filename,
"%s_YYYY_MM_DD_HH.zfp", metbase);
2006 sprintf(filename,
"%s_YYYY_MM_DD_HH.zstd", metbase);
2008 sprintf(filename,
"%s_YYYY_MM_DD_HH.cms", metbase);
2010 sprintf(filename,
"%s_YYYY_MM_DD_HH.sz3", metbase);
2011 sprintf(repl,
"%d", year);
2013 sprintf(repl,
"%02d", mon);
2015 sprintf(repl,
"%02d", day);
2017 sprintf(repl,
"%02d", hour);
2023 sprintf(filename,
"%s_YYMMDDHH.nc", metbase);
2024 sprintf(repl,
"%d", year);
2026 sprintf(repl,
"%02d", year % 100);
2028 sprintf(repl,
"%02d", mon);
2030 sprintf(repl,
"%02d", day);
2032 sprintf(repl,
"%02d", hour);
2047 for (
int i = 0; i < 3; i++) {
2051 if (!(ch = strstr(orig, search)))
2053 strncpy(buffer, orig, (
size_t) (ch - orig));
2054 buffer[ch - orig] = 0;
2055 sprintf(buffer + (ch - orig),
"%s%s", repl, ch + strlen(search));
2057 strcpy(orig, buffer);
2064 const int met_tropo,
2084#pragma omp parallel for default(shared) private(ci,cw)
2085 for (
int ix = 0; ix < nx; ix++)
2086 for (
int iy = 0; iy < ny; iy++) {
2088 &pt[iy * nx + ix], ci, cw, 1);
2090 &ps[iy * nx + ix], ci, cw, 0);
2092 &zs[iy * nx + ix], ci, cw, 0);
2094 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
2096 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
2098 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
2100 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
2117 *lon2 =
FMOD(lon, 360.);
2118 if (*lon2 < lons[0])
2120 else if (*lon2 > lons[nlon - 1])
2125 if (lats[0] < lats[nlat - 1])
2126 *lat2 =
MIN(
MAX(*lat2, lats[0]), lats[nlat - 1]);
2128 *lat2 =
MIN(
MAX(*lat2, lats[nlat - 1]), lats[0]);
2135 float heights0[
EX][
EY][
EP],
2136 float array0[
EX][
EY][
EP],
2138 float heights1[
EX][
EY][
EP],
2139 float array1[
EX][
EY][
EP],
2141 const double height,
2167 int k_max = ind[0][0];
2168 for (
int i = 0; i < 2; i++)
2169 for (
int j = 0; j < 4; j++) {
2170 if (ci[2] > ind[i][j])
2172 if (k_max < ind[i][j])
2178 cw[0] = (lon2 - met0->
lon[ci[0]]) /
2179 (met0->
lon[ci[0] + 1] - met0->
lon[ci[0]]);
2180 cw[1] = (lat2 - met0->
lat[ci[1]]) /
2181 (met0->
lat[ci[1] + 1] - met0->
lat[ci[1]]);
2184 double height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2]]
2185 - heights0[ci[0]][ci[1]][ci[2]])
2186 + heights0[ci[0]][ci[1]][ci[2]];
2187 double height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2]]
2188 - heights0[ci[0]][ci[1] + 1][ci[2]])
2189 + heights0[ci[0]][ci[1] + 1][ci[2]];
2190 double height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2]]
2191 - heights0[ci[0] + 1][ci[1]][ci[2]])
2192 + heights0[ci[0] + 1][ci[1]][ci[2]];
2193 double height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2]]
2194 - heights0[ci[0] + 1][ci[1] + 1][ci[2]])
2195 + heights0[ci[0] + 1][ci[1] + 1][ci[2]];
2198 double height0 = cw[1] * (height01 - height00) + height00;
2199 double height1 = cw[1] * (height11 - height10) + height10;
2202 double height_bot = cw[0] * (height1 - height0) + height0;
2205 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
2206 - heights0[ci[0]][ci[1]][ci[2] + 1])
2207 + heights0[ci[0]][ci[1]][ci[2] + 1];
2208 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
2209 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
2210 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
2211 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
2212 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
2213 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
2214 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2215 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2216 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2219 height0 = cw[1] * (height01 - height00) + height00;
2220 height1 = cw[1] * (height11 - height10) + height10;
2223 double height_top = cw[0] * (height1 - height0) + height0;
2226 while (((heights0[0][0][0] > heights0[0][0][1]) &&
2227 ((height_bot <= height) || (height_top > height))
2228 && (height_bot >= height) && (ci[2] < k_max))
2230 ((heights0[0][0][0] < heights0[0][0][1]) &&
2231 ((height_bot >= height) || (height_top < height))
2232 && (height_bot <= height) && (ci[2] < k_max))
2236 height_bot = height_top;
2239 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
2240 - heights0[ci[0]][ci[1]][ci[2] + 1])
2241 + heights0[ci[0]][ci[1]][ci[2] + 1];
2242 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
2243 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
2244 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
2245 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
2246 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
2247 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
2248 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2249 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2250 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2253 height0 = cw[1] * (height01 - height00) + height00;
2254 height1 = cw[1] * (height11 - height10) + height10;
2257 height_top = cw[0] * (height1 - height0) + height0;
2261 cw[2] = (height - height_bot)
2262 / (height_top - height_bot);
2266 const double array000 = cw[3] * (array1[ci[0]][ci[1]][ci[2]]
2267 - array0[ci[0]][ci[1]][ci[2]])
2268 + array0[ci[0]][ci[1]][ci[2]];
2269 const double array100 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2]]
2270 - array0[ci[0] + 1][ci[1]][ci[2]])
2271 + array0[ci[0] + 1][ci[1]][ci[2]];
2272 const double array010 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2]]
2273 - array0[ci[0]][ci[1] + 1][ci[2]])
2274 + array0[ci[0]][ci[1] + 1][ci[2]];
2275 const double array110 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2]]
2276 - array0[ci[0] + 1][ci[1] + 1][ci[2]])
2277 + array0[ci[0] + 1][ci[1] + 1][ci[2]];
2278 const double array001 = cw[3] * (array1[ci[0]][ci[1]][ci[2] + 1]
2279 - array0[ci[0]][ci[1]][ci[2] + 1])
2280 + array0[ci[0]][ci[1]][ci[2] + 1];
2281 const double array101 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2] + 1]
2282 - array0[ci[0] + 1][ci[1]][ci[2] + 1])
2283 + array0[ci[0] + 1][ci[1]][ci[2] + 1];
2284 const double array011 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2] + 1]
2285 - array0[ci[0]][ci[1] + 1][ci[2] + 1])
2286 + array0[ci[0]][ci[1] + 1][ci[2] + 1];
2287 const double array111 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2288 - array0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2289 + array0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2291 const double array00 = cw[0] * (array100 - array000) + array000;
2292 const double array10 = cw[0] * (array110 - array010) + array010;
2293 const double array01 = cw[0] * (array101 - array001) + array001;
2294 const double array11 = cw[0] * (array111 - array011) + array011;
2296 const double aux0 = cw[1] * (array10 - array00) + array00;
2297 const double aux1 = cw[1] * (array11 - array01) + array01;
2300 *var = cw[2] * (aux1 - aux0) + aux0;
2330 cw[0] = (met->
p[ci[0] + 1] - p)
2331 / (met->
p[ci[0] + 1] - met->
p[ci[0]]);
2332 cw[1] = (met->
lon[ci[1] + 1] - lon2)
2333 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
2334 cw[2] = (met->
lat[ci[2] + 1] - lat2)
2335 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
2339 const double aux00 =
2340 cw[0] * (array[ci[1]][ci[2]][ci[0]] - array[ci[1]][ci[2]][ci[0] + 1])
2341 + array[ci[1]][ci[2]][ci[0] + 1];
2342 const double aux01 =
2343 cw[0] * (array[ci[1]][ci[2] + 1][ci[0]] -
2344 array[ci[1]][ci[2] + 1][ci[0] + 1])
2345 + array[ci[1]][ci[2] + 1][ci[0] + 1];
2346 const double aux10 =
2347 cw[0] * (array[ci[1] + 1][ci[2]][ci[0]] -
2348 array[ci[1] + 1][ci[2]][ci[0] + 1])
2349 + array[ci[1] + 1][ci[2]][ci[0] + 1];
2350 const double aux11 =
2351 cw[0] * (array[ci[1] + 1][ci[2] + 1][ci[0]] -
2352 array[ci[1] + 1][ci[2] + 1][ci[0] + 1])
2353 + array[ci[1] + 1][ci[2] + 1][ci[0] + 1];
2356 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
2357 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
2358 *var = cw[1] * (aux0 - aux1) + aux1;
2365 float array[
EX][
EY],
2386 cw[1] = (met->
lon[ci[1] + 1] - lon2)
2387 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
2388 cw[2] = (met->
lat[ci[2] + 1] - lat2)
2389 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
2393 const double aux00 = array[ci[1]][ci[2]];
2394 const double aux01 = array[ci[1]][ci[2] + 1];
2395 const double aux10 = array[ci[1] + 1][ci[2]];
2396 const double aux11 = array[ci[1] + 1][ci[2] + 1];
2399 if (isfinite(aux00) && isfinite(aux01)
2400 && isfinite(aux10) && isfinite(aux11)) {
2401 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
2402 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
2403 *var = cw[1] * (aux0 - aux1) + aux1;
2423 float array0[
EX][
EY][
EP],
2425 float array1[
EX][
EY][
EP],
2442 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
2445 *var = wt * (var0 - var1) + var1;
2452 float array0[
EX][
EY],
2454 float array1[
EX][
EY],
2470 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
2473 if (isfinite(var0) && isfinite(var1))
2474 *var = wt * (var0 - var1) + var1;
2485 float array0[
EX][
EY],
2487 float array1[
EX][
EY],
2488 const double lons[
EX],
2489 const double lats[
EY],
2508 const int ix =
locate_reg(lons, (
int) nlon, lon2);
2509 const int iy =
locate_irr(lats, (
int) nlat, lat2);
2513 for (
int dx = 0; dx < 2; dx++)
2514 for (
int dy = 0; dy < 2; dy++) {
2515 if (isfinite(array0[ix + dx][iy + dy])) {
2516 mean += array0[ix + dx][iy + dy];
2517 *sigma +=
SQR(array0[ix + dx][iy + dy]);
2520 if (isfinite(array1[ix + dx][iy + dy])) {
2521 mean += array1[ix + dx][iy + dy];
2522 *sigma +=
SQR(array1[ix + dx][iy + dy]);
2527 *sigma = sqrt(
MAX(*sigma / n -
SQR(mean / n), 0.0));
2530 if (method == 1 && isfinite(array0[ix][iy])
2531 && isfinite(array0[ix][iy + 1])
2532 && isfinite(array0[ix + 1][iy])
2533 && isfinite(array0[ix + 1][iy + 1])
2534 && isfinite(array1[ix][iy])
2535 && isfinite(array1[ix][iy + 1])
2536 && isfinite(array1[ix + 1][iy])
2537 && isfinite(array1[ix + 1][iy + 1])) {
2539 const double aux00 =
LIN(lons[ix], array0[ix][iy],
2540 lons[ix + 1], array0[ix + 1][iy], lon2);
2541 const double aux01 =
LIN(lons[ix], array0[ix][iy + 1],
2542 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
2543 const double aux0 =
LIN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
2545 const double aux10 =
LIN(lons[ix], array1[ix][iy],
2546 lons[ix + 1], array1[ix + 1][iy], lon2);
2547 const double aux11 =
LIN(lons[ix], array1[ix][iy + 1],
2548 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
2549 const double aux1 =
LIN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
2551 *var =
LIN(time0, aux0, time1, aux1, time);
2556 const double aux00 =
NN(lons[ix], array0[ix][iy],
2557 lons[ix + 1], array0[ix + 1][iy], lon2);
2558 const double aux01 =
NN(lons[ix], array0[ix][iy + 1],
2559 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
2560 const double aux0 =
NN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
2562 const double aux10 =
NN(lons[ix], array1[ix][iy],
2563 lons[ix + 1], array1[ix + 1][iy], lon2);
2564 const double aux11 =
NN(lons[ix], array1[ix][iy + 1],
2565 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
2566 const double aux1 =
NN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
2568 *var =
NN(time0, aux0, time1, aux1, time);
2593 const time_t jsec0 = (time_t) jsec + timegm(&t0);
2594 t1 = gmtime(&jsec0);
2596 *year = t1->tm_year + 1900;
2597 *mon = t1->tm_mon + 1;
2599 *hour = t1->tm_hour;
2602 *remain = jsec - floor(jsec);
2608 const double kz[
EP],
2609 const double kw[
EP],
2618 const double z =
Z(p);
2623 else if (z > kz[nk - 1])
2627 return LIN(kz[idx], kw[idx], kz[idx + 1], kw[idx + 1], z);
2644 const double a =
RA *
SQR(t), r =
SH(h2o) / (1. -
SH(h2o));
2658 const double press[138] = {
2659 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
2660 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
2661 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
2662 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
2663 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2664 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
2665 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
2666 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
2667 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
2668 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
2669 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
2670 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
2671 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
2672 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
2673 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
2674 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
2675 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
2676 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
2677 1010.8487, 1013.2500, 1044.45
2680 for (
int ip = 0; ip < ctl->
met_np; ip++)
2687 const double press[92] = {
2688 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
2689 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
2690 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
2691 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
2692 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
2694 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
2695 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
2696 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
2697 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
2698 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
2699 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
2700 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
2701 1007.4431, 1010.8487, 1013.2500, 1044.45
2704 for (
int ip = 0; ip < ctl->
met_np; ip++)
2711 const double press[60] = {
2712 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
2713 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
2714 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
2715 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
2716 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
2717 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
2718 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
2719 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1044.45
2722 for (
int ip = 0; ip < ctl->
met_np; ip++)
2729 const double press[147] = {
2730 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
2731 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
2732 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
2733 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
2734 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2735 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
2736 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
2737 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
2738 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
2739 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
2740 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
2741 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
2742 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
2743 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
2744 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
2745 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
2746 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
2747 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
2748 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73, 1028.85,
2750 1035.09, 1038.21, 1041.33, 1044.45
2753 for (
int ip = 0; ip < ctl->
met_np; ip++)
2760 const double press[101] = {
2761 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
2762 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
2763 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
2764 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
2765 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
2767 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
2768 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
2769 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
2770 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
2771 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
2772 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
2773 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
2774 1007.4431, 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73,
2776 1035.09, 1038.21, 1041.33, 1044.45
2779 for (
int ip = 0; ip < ctl->
met_np; ip++)
2786 const double press[62] = {
2787 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
2788 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
2789 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
2790 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
2791 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
2792 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
2793 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
2794 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1034.86, 1039.65,
2798 for (
int ip = 0; ip < ctl->
met_np; ip++)
2805 const double press[137] = {
2806 0.01, 0.02, 0.031, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861,
2807 0.2499, 0.3299, 0.4288, 0.5496, 0.6952, 0.869, 1.0742,
2808 1.3143, 1.5928, 1.9134, 2.2797, 2.6954, 3.1642, 3.6898,
2809 4.2759, 4.9262, 5.6441, 6.4334, 7.2974, 8.2397, 9.2634,
2810 10.372, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945, 18.9752,
2811 20.761, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2812 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.199, 54.5299,
2813 57.9834, 61.5607, 65.2695, 69.1187, 73.1187, 77.281, 81.6182,
2814 86.145, 90.8774, 95.828, 101.005, 106.415, 112.068, 117.971,
2815 124.134, 130.564, 137.27, 144.262, 151.549, 159.14, 167.045,
2816 175.273, 183.834, 192.739, 201.997, 211.619, 221.615, 231.995,
2817 242.772, 253.955, 265.556, 277.585, 290.055, 302.976, 316.361,
2818 330.22, 344.566, 359.411, 374.767, 390.645, 407.058, 424.019,
2819 441.539, 459.632, 478.31, 497.584, 517.42, 537.72, 558.343,
2820 579.193, 600.167, 621.162, 642.076, 662.808, 683.262, 703.347,
2821 722.979, 742.086, 760.6, 778.466, 795.64, 812.085, 827.776,
2822 842.696, 856.838, 870.2, 882.791, 894.622, 905.712, 916.081,
2823 925.757, 934.767, 943.14, 950.908, 958.104, 965.299, 972.495,
2824 979.69, 986.886, 994.081, 1001.28, 1008.47, 1015.67, 1022.86,
2825 1030.06, 1037.25, 1044.45
2828 for (
int ip = 0; ip < ctl->
met_np; ip++)
2835 const double press[59] = {
2836 0.1, 0.2, 0.3843, 0.6365, 0.9564, 1.3448, 1.8058, 2.3478,
2837 2.985, 3.7397, 4.6462, 5.7565, 7.1322, 8.8366, 10.9483,
2838 13.5647, 16.8064, 20.8227, 25.7989, 31.9642, 39.6029, 49.0671,
2839 60.1802, 73.0663, 87.7274, 104.229, 122.614, 142.902, 165.089,
2840 189.147, 215.025, 242.652, 272.059, 303.217, 336.044, 370.407,
2841 406.133, 443.009, 480.791, 519.209, 557.973, 596.777, 635.306,
2842 673.24, 710.263, 746.063, 780.346, 812.83, 843.263, 871.42,
2843 897.112, 920.189, 940.551, 958.148, 975.744, 993.341, 1010.94,
2847 for (
int ip = 0; ip < ctl->
met_np; ip++)
2851 ERRMSG(
"Use 0 for l137, 1 for l91, 2 for l60 or values between 3 and 7.");
2855 ERRMSG(
"Recompile with larger EP to use this pressure level definition.");
2868 int i = (ihi + ilo) >> 1;
2870 if (xx[i] < xx[i + 1])
2871 while (ihi > ilo + 1) {
2872 i = (ihi + ilo) >> 1;
2878 while (ihi > ilo + 1) {
2879 i = (ihi + ilo) >> 1;
2899 int i = (ihi + ilo) >> 1;
2901 if ((xx[ig] <= x && x < xx[ig + 1]) || (xx[ig] >= x && x > xx[ig + 1]))
2904 if (xx[i] < xx[i + 1])
2905 while (ihi > ilo + 1) {
2906 i = (ihi + ilo) >> 1;
2912 while (ihi > ilo + 1) {
2913 i = (ihi + ilo) >> 1;
2931 const int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
2945 float profiles[
EX][
EY][
EP],
2947 const int lon_ap_ind,
2948 const int lat_ap_ind,
2949 const double height_ap,
2955 np, height_ap, ind[0]);
2957 np, height_ap, ind[1]);
2959 np, height_ap, ind[2]);
2978 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2982 double dts, u[4], um = 0, v[4], vm = 0, w[4], wm = 0,
2986 for (
int i = 0; i < ctl->
advect; i++) {
2991 x[0] = atm->
lon[ip];
2992 x[1] = atm->
lat[ip];
2995 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
2996 x[0] = atm->
lon[ip] +
DX2DEG(dts * u[i - 1] / 1000., atm->
lat[ip]);
2997 x[1] = atm->
lat[ip] +
DY2DEG(dts * v[i - 1] / 1000.);
2998 x[2] = atm->
p[ip] + dts * w[i - 1];
3000 const double tm = atm->
time[ip] + dts;
3005 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3007 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3009 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
3015 met1, met1->
pl, met1->
ul,
3016 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3018 met1, met1->
pl, met1->
vl,
3019 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3021 met1, met1->
pl, met1->
wl,
3022 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
3028 k = (i == 0 ? 0.0 : 1.0);
3029 else if (ctl->
advect == 4)
3030 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
3037 atm->
time[ip] += cache->
dt[ip];
3038 atm->
lon[ip] +=
DX2DEG(cache->
dt[ip] * um / 1000.,
3039 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
3040 atm->
lat[ip] +=
DY2DEG(cache->
dt[ip] * vm / 1000.);
3041 atm->
p[ip] += cache->
dt[ip] * wm;
3053 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3059 atm->
time[ip], atm->
p[ip],
3060 atm->
lon[ip], atm->
lat[ip],
3061 &atm->
q[qnt][ip], ci, cw, 1);
3064 double dts, u[4], um = 0, v[4], vm = 0, wdot[4],
3065 wdotm = 0, x[3] = { 0, 0, 0 };
3068 for (
int i = 0; i < ctl->
advect; i++) {
3073 x[0] = atm->
lon[ip];
3074 x[1] = atm->
lat[ip];
3075 x[2] = atm->
q[qnt][ip];
3077 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
3078 x[0] = atm->
lon[ip] +
DX2DEG(dts * u[i - 1] / 1000., atm->
lat[ip]);
3079 x[1] = atm->
lat[ip] +
DY2DEG(dts * v[i - 1] / 1000.);
3080 x[2] = atm->
q[qnt][ip] + dts * wdot[i - 1];
3083 const double tm = atm->
time[ip] + dts;
3088 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3091 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3094 tm, x[2], x[0], x[1], &wdot[i], ci, cw, 0);
3099 k = (i == 0 ? 0.0 : 1.0);
3100 else if (ctl->
advect == 4)
3101 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
3105 wdotm += k * wdot[i];
3109 atm->
time[ip] += cache->
dt[ip];
3110 atm->
lon[ip] +=
DX2DEG(cache->
dt[ip] * um / 1000.,
3111 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
3112 atm->
lat[ip] +=
DY2DEG(cache->
dt[ip] * vm / 1000.);
3113 atm->
q[qnt][ip] += cache->
dt[ip] * wdotm;
3119 atm->
q[qnt][ip], atm->
lon[ip], atm->
lat[ip],
3120 &atm->
p[ip], ci, cw, 1);
3139 SELECT_TIMER(
"MODULE_ADVECT_INIT",
"PHYSICS", NVTX_GPU);
3148 atm->
lon[ip], atm->
lat[ip], &atm->
p[ip], ci, cw, 1);
3163 SELECT_TIMER(
"MODULE_BOUND_COND",
"PHYSICS", NVTX_GPU);
3173 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3209 if (atm->
p[ip] < pbl)
3261 ERRMSG(
"Molar mass is not defined!");
3267 const int ensemble_mode = (ctl->
nens > 0);
3268 const int np = atm->
np;
3272 const int ngrid = nx * ny * nz;
3273 const int nens = ensemble_mode ? ctl->
nens : 1;
3275 double *restrict
const z = (
double *) malloc((
size_t) nz *
sizeof(double));
3276 double *restrict
const press =
3277 (
double *) malloc((
size_t) nz *
sizeof(double));
3278 double *restrict
const mass =
3279 (
double *) calloc((
size_t) ngrid * (size_t) nens,
sizeof(
double));
3280 double *restrict
const area =
3281 (
double *) malloc((
size_t) ny *
sizeof(double));
3282 double *restrict
const lon =
3283 (
double *) malloc((
size_t) nx *
sizeof(double));
3284 double *restrict
const lat =
3285 (
double *) malloc((
size_t) ny *
sizeof(double));
3287 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
3288 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
3289 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
3298#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])
3299#pragma acc data present(ctl,met0,met1,atm,ixs,iys,izs,z,press,mass,area,lon,lat)
3300#pragma acc parallel loop independent gang vector
3302#pragma omp parallel for default(shared)
3304 for (
int iz = 0; iz < nz; iz++) {
3306 press[iz] =
P(z[iz]);
3310 const double t0 = tt - 0.5 * ctl->
dt_mod;
3311 const double t1 = tt + 0.5 * ctl->
dt_mod;
3315#pragma acc parallel loop independent gang vector
3317#pragma omp parallel for default(shared)
3319 for (
int ip = 0; ip < np; ip++) {
3323 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
3324 || ixs[ip] < 0 || ixs[ip] >= nx
3325 || iys[ip] < 0 || iys[ip] >= ny || izs[ip] < 0 || izs[ip] >= nz)
3331#pragma acc parallel loop independent gang vector
3333#pragma omp parallel for default(shared)
3335 for (
int ix = 0; ix < nx; ix++)
3339#pragma acc parallel loop independent gang vector
3341#pragma omp parallel for default(shared)
3343 for (
int iy = 0; iy < ny; iy++) {
3345 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
3350#pragma acc parallel loop independent gang vector
3352 for (
int ip = 0; ip < np; ip++) {
3354 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
3355 if (ensemble_mode) {
3356 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
3357 mass_idx += ens * ngrid;
3360#pragma acc atomic update
3362 mass[mass_idx] += atm->
q[ctl->
qnt_m][ip];
3368#pragma acc parallel loop independent gang vector
3370#pragma omp parallel for default(shared)
3372 for (
int ip = 0; ip < np; ip++)
3380 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
3383 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
3384 if (ensemble_mode) {
3385 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
3386 mass_idx += ens * ngrid;
3390 const double m = mass[mass_idx];
3392 / (
RHO(press[izs[ip]], temp) * area[iys[ip]] * dz * 1e9);
3397#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
3425 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3442 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
3444 atm->
lat[ip], atm->
p[ip]));
3446 atm->
lat[ip], atm->
p[ip]));
3448 atm->
lat[ip], atm->
p[ip]));
3462 SELECT_TIMER(
"MODULE_CONVECTION",
"PHYSICS", NVTX_GPU);
3468 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3476 double pbot = ps, ptop = ps;
3493 double cape, cin, pel;
3499 if (isfinite(cape) && cape >= ctl->
conv_cape
3501 ptop = GSL_MIN(ptop, pel);
3505 if (ptop != pbot && atm->
p[ip] >= ptop) {
3510 pbot, atm->
lon[ip], atm->
lat[ip], &tbot, ci, cw, 1);
3512 atm->
lon[ip], atm->
lat[ip], &ttop, ci, cw, 1);
3513 const double rhobot = pbot / tbot;
3514 const double rhotop = ptop / ttop;
3517 const double rho = rhobot + (rhotop - rhobot) * cache->
rs[ip];
3520 atm->
p[ip] =
LIN(rhobot, pbot, rhotop, ptop, rho);
3544 dd_sort(ctl, *met, atm, dd, &nparticles, &dd->
rank);
3578 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3581 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,clim,atm)") {
3590 const double aux = exp(-cache->
dt[ip] / tdec);
3591 if (ctl->
qnt_m >= 0) {
3594 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
3595 atm->
q[ctl->
qnt_m][ip] *= aux;
3620 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3628 float umean = 0, usig = 0, vmean = 0, vsig = 0, wmean = 0, wsig = 0;
3629 for (
int i = 0; i < 2; i++)
3630 for (
int j = 0; j < 2; j++)
3631 for (
int k = 0; k < 2; k++) {
3632 umean += met0->
u[ix + i][iy + j][iz + k];
3633 usig +=
SQR(met0->
u[ix + i][iy + j][iz + k]);
3634 vmean += met0->
v[ix + i][iy + j][iz + k];
3635 vsig +=
SQR(met0->
v[ix + i][iy + j][iz + k]);
3636 wmean += met0->
w[ix + i][iy + j][iz + k];
3637 wsig +=
SQR(met0->
w[ix + i][iy + j][iz + k]);
3639 umean += met1->
u[ix + i][iy + j][iz + k];
3640 usig +=
SQR(met1->
u[ix + i][iy + j][iz + k]);
3641 vmean += met1->
v[ix + i][iy + j][iz + k];
3642 vsig +=
SQR(met1->
v[ix + i][iy + j][iz + k]);
3643 wmean += met1->
w[ix + i][iy + j][iz + k];
3644 wsig +=
SQR(met1->
w[ix + i][iy + j][iz + k]);
3646 usig = usig / 16.f -
SQR(umean / 16.f);
3647 usig = (usig > 0 ? sqrtf(usig) : 0);
3648 vsig = vsig / 16.f -
SQR(vmean / 16.f);
3649 vsig = (vsig > 0 ? sqrtf(vsig) : 0);
3650 wsig = wsig / 16.f -
SQR(wmean / 16.f);
3651 wsig = (wsig > 0 ? sqrtf(wsig) : 0);
3654 const double r = 1 - 2 * fabs(cache->
dt[ip]) / ctl->
dt_met;
3655 const double r2 = sqrt(1 - r * r);
3659 cache->
uvwp[ip][0] =
3660 (float) (r * cache->
uvwp[ip][0] +
3665 cache->
uvwp[ip][1] =
3666 (float) (r * cache->
uvwp[ip][1] +
3673 cache->
uvwp[ip][2] =
3674 (float) (r * cache->
uvwp[ip][2] +
3676 atm->
p[ip] += cache->
uvwp[ip][2] * cache->
dt[ip];
3697 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3699 double dsigw_dz = 0.0, sig_u = 0.25, sig_w = 0.1,
3700 tau_u = 300., tau_w = 100.;
3709 if (atm->
p[ip] >= pbl) {
3712 const double p =
MIN(atm->
p[ip], ps);
3713 const double zs =
Z(ps);
3714 const double z = 1e3 * (
Z(p) - zs);
3715 const double zi = 1e3 * (
Z(pbl) - zs);
3716 const double zratio = z / zi;
3719 double ess, nss, h2o, t;
3724 const double rho =
RHO(p,
TVIRT(t, h2o));
3725 const double tau = sqrt(
SQR(ess) +
SQR(nss));
3726 const double ustar = sqrt(tau / rho);
3736 sig_u = 1e-2 + 2.0 * ustar * (1.0 - zratio);
3737 sig_w = 1e-2 + 1.3 * ustar * (1.0 - zratio);
3740 dsigw_dz = -1.3 * ustar / zi;
3743 tau_u = 0.07 * zi / sig_u * sqrt(zratio);
3744 tau_w = 0.1 * zi / sig_w * pow(zratio, 0.8);
3751 const double wstar =
3752 pow(
G0 /
THETAVIRT(p, t, h2o) * shf / (rho *
CPD) * zi, 1. / 3.);
3756 + sqrt(0.4 *
SQR(wstar) + (5.0 - 4.0 * zratio) *
SQR(ustar));
3757 sig_w = 1e-2 + sqrt(1.2 *
SQR(wstar) * (1.0 - 0.9 * zratio)
3758 * pow(zratio, 2.0 / 3.0)
3759 + (1.8 - 1.4 * zratio) *
SQR(ustar));
3762 dsigw_dz = 0.5 / sig_w / zi * (-1.4 *
SQR(ustar) +
SQR(wstar)
3764 pow(
MAX(zratio, 1e-3), -1.0 / 3.0)
3765 - 1.8 * pow(zratio, 2.0 / 3.0)));
3768 const double C0 = 3.0;
3770 (1.5 - 1.2 * pow(zratio, 1.0 / 3.0)) *
SQR(wstar) * wstar / zi
3771 +
SQR(ustar) * ustar * (1.0 - 0.8 * zratio) / (
KARMAN * z);
3772 tau_u = 2 *
SQR(sig_u) / (C0 * eps);
3773 tau_w = 2 *
SQR(sig_w) / (C0 * eps);
3778 sig_u =
MAX(sig_u, 0.25);
3779 sig_w =
MAX(sig_w, 0.1);
3780 tau_u =
MAX(tau_u, 300.);
3781 tau_w =
MAX(tau_w, 100.);
3784 const double ru = exp(-fabs(cache->
dt[ip]) / tau_u);
3785 const double ru2 = sqrt(1.0 -
SQR(ru));
3787 = (float) (cache->
uvwp[ip][0] * ru + ru2 * cache->
rs[3 * ip]);
3789 = (float) (cache->
uvwp[ip][1] * ru + ru2 * cache->
rs[3 * ip + 1]);
3791 const double rw = exp(-fabs(cache->
dt[ip]) / tau_w);
3792 const double rw2 = sqrt(1.0 -
SQR(rw));
3794 = (float) (cache->
uvwp[ip][2] * rw + rw2 * cache->
rs[3 * ip + 2]
3795 + sig_w * dsigw_dz * cache->
dt[ip]);
3802 DZ2DP(cache->
uvwp[ip][2] * cache->
dt[ip] / 1000., atm->
p[ip]);
3824 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3833 const double wpbl =
pbl_weight(ctl, atm, ip, pbl, ps);
3834 const double wtrop =
tropo_weight(clim, atm, ip) * (1.0 - wpbl);
3835 const double wstrat = 1.0 - wpbl - wtrop;
3845 const double sigma = sqrt(2.0 * dx * fabs(cache->
dt[ip])) / 1000.;
3847 atm->
lat[ip] +=
DY2DEG(cache->
rs[3 * ip + 1] * sigma);
3852 const double sigma = sqrt(2.0 * dz * fabs(cache->
dt[ip])) / 1000.;
3853 atm->
p[ip] +=
DZ2DP(cache->
rs[3 * ip + 2] * sigma, atm->
p[ip]);
3872 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3875 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3887 const double dz = 1000. * (
Z(ps - ctl->
dry_depo_dp) -
Z(ps));
3907 const double aux = exp(-cache->
dt[ip] * v_dep / dz);
3908 if (ctl->
qnt_m >= 0) {
3911 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
3912 atm->
q[ctl->
qnt_m][ip] *= aux;
3936 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3939 const double a = 3.12541941e-06;
3940 const double b = -5.72532259e-01;
3941 const double low = pow(1. / a, 1. / b);
3944 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3951 if (!(lwc > 0 || rwc > 0))
3962 const double k = 9.1e7 * exp(-29700. /
RI * (1. / t - 1. / 298.15));
3965 const double H_SO2 =
3966 1.3e-2 * exp(2900. * (1. / t - 1. / 298.15)) *
RI * t;
3967 const double K_1S = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
3970 const double H_h2o2 =
3971 8.3e2 * exp(7600. * (1. / t - 1. / 298.15)) *
RI * t;
3977 cor = atm->
q[ctl->
qnt_Cx][ip] >
3978 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
3980 const double h2o2 = H_h2o2
3982 * M * cor * 1000. /
AVO;
3985 const double rho_air = atm->
p[ip] / (
RI * t) *
MA / 10.;
3986 const double CWC = (lwc + rwc) * rho_air / 1e3;
3989 const double rate_coef = k * K_1S * h2o2 * H_SO2 * CWC;
3990 const double aux = exp(-cache->
dt[ip] * rate_coef);
3991 if (ctl->
qnt_m >= 0) {
3994 atm->
q[ctl->
qnt_m][ip] *= aux;
4015 SELECT_TIMER(
"MODULE_ISOSURF_INIT",
"PHYSICS", NVTX_GPU);
4026 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
4029 cache->
iso_var[ip] = atm->
p[ip] / t;
4035 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
4046 LOG(1,
"Read balloon pressure data: %s", ctl->
balloon);
4050 if (!(in = fopen(ctl->
balloon,
"r")))
4051 ERRMSG(
"Cannot open file!");
4055 while (fgets(line,
LEN, in))
4056 if (sscanf(line,
"%lg %lg", &(cache->
iso_ts[cache->
iso_n]),
4059 ERRMSG(
"Too many data points!");
4062 if (cache->
iso_n < 1)
4063 ERRMSG(
"Could not read any data!");
4086 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,met1,atm)") {
4099 atm->
p[ip] = cache->
iso_var[ip] * t;
4105 atm->
p[ip] = 1000. * pow(cache->
iso_var[ip] / t, -1. / 0.286);
4111 atm->
p[ip] = cache->
iso_ps[0];
4139 const int nvar = NVAR, nfix = NFIX, nreact = NREACT;
4140 double rtol[1] = { 1.0e-3 };
4141 double atol[1] = { 1.0 };
4145#pragma acc data copy(rtol,atol,nvar,nfix,nreact)
4148 "acc data present(ctl,cache,clim,met0,met1,atm) ") {
4151 double var[nvar], fix[nfix], rconst[nreact];
4152 for (
int i = 0; i < nvar; i++)
4154 for (
int i = 0; i < nfix; i++)
4156 for (
int i = 0; i < nreact; i++)
4158 kpp_chem_initialize(ctl, clim, met0, met1, atm, var, fix, rconst, ip);
4163 for (
int i = 0; i < 20; i++) {
4170 Rosenbrock(var, fix, rconst, 0, ctl->
dt_kpp,
4171 atol, rtol, &FunTemplate, &JacTemplate, rpar, ipar);
4174 kpp_chem_output2atm(atm, ctl, met0, met1, var, ip);
4195 ERRMSG(
"Need T_ice and T_NAT to calculate T_STS!");
4199 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4201 double ps, ts, zs, us, vs, ess, nss, shf, lsm, sst, pbl, pt, pct, pcb,
4202 cl, plcl, plfc, pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot,
4203 o3, lwc, rwc, iwc, swc, cc, z, zt;
4251 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
4253 atm->
lat[ip], atm->
p[ip]));
4255 atm->
lat[ip], atm->
p[ip]));
4257 atm->
lat[ip], atm->
p[ip]));
4258 SET_ATM(qnt_vh, sqrt(u * u + v * v));
4280 atm->
lat[ip], atm->
p[ip])));
4298 const int np = atm->
np;
4299 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
4300 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
4301 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
4309 const double t0 = t - 0.5 * ctl->
dt_mod;
4310 const double t1 = t + 0.5 * ctl->
dt_mod;
4314#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
4315#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
4316#pragma acc parallel loop independent gang vector
4318#pragma omp parallel for default(shared)
4320 for (
int ip = 0; ip < np; ip++) {
4323 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
mixing_z0) / dz);
4324 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
4325 || ixs[ip] < 0 || ixs[ip] >= ctl->
mixing_nx
4326 || iys[ip] < 0 || iys[ip] >= ctl->
mixing_ny
4327 || izs[ip] < 0 || izs[ip] >= ctl->
mixing_nz)
4332 const int use_ensemble = (ctl->
nens > 0);
4334 const int quantities[] = {
4341 const int n_qnt =
sizeof(quantities) /
sizeof(quantities[0]);
4343 for (
int i = 0; i < n_qnt; i++)
4344 if (quantities[i] >= 0)
4350#pragma acc exit data delete(ixs,iys,izs)
4367 const int use_ensemble) {
4369 const int np = atm->
np;
4371 const int nens = use_ensemble ? ctl->
nens : 1;
4372 const int total_grid = ngrid * nens;
4374 double *restrict
const cmean =
4375 (
double *) malloc((
size_t) total_grid *
sizeof(double));
4376 int *restrict
const count =
4377 (
int *) malloc((
size_t) total_grid *
sizeof(int));
4381#pragma acc enter data create(cmean[0:total_grid],count[0:total_grid])
4382#pragma acc data present(ctl,clim,atm,ixs,iys,izs,cmean,count)
4383#pragma acc parallel loop independent gang vector
4388#pragma omp parallel for
4390 for (
int i = 0; i < total_grid; i++) {
4397#pragma acc parallel loop independent gang vector
4399 for (
int ip = 0; ip < np; ip++)
4401 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
4406#pragma acc atomic update
4408 cmean[idx] += atm->
q[qnt_idx][ip];
4410#pragma acc atomic update
4417#pragma acc parallel loop independent gang vector
4422#pragma omp parallel for
4424 for (
int i = 0; i < total_grid; i++)
4426 cmean[i] /= count[i];
4430#pragma acc parallel loop independent gang vector
4432#pragma omp parallel for
4434 for (
int ip = 0; ip < np; ip++) {
4436 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
4438 double mixparam = 1.0;
4447 atm->
q[qnt_idx][ip] += (cmean[idx] - atm->
q[qnt_idx][ip]) * mixparam;
4453#pragma acc exit data delete(cmean,count)
4474 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4477 const double a = 4.71572206e-08;
4478 const double b = -8.28782867e-01;
4479 const double low = pow(1. / a, 1. / b);
4483 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4509 0 ? pow(298. / t, ctl->
oh_chem[1]) : 1.);
4512 0 ? pow(298. / t, ctl->
oh_chem[3]) : 1.);
4513 const double c = log10(k0 * M / ki);
4514 k = k0 * M / (1. + k0 * M / ki) * pow(0.6, 1. / (1. + c * c));
4523 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
4526 const double rate_coef =
4528 atm->
lat[ip], atm->
p[ip]) * M * cor;
4529 const double aux = exp(-cache->
dt[ip] * rate_coef);
4530 if (ctl->
qnt_m >= 0) {
4533 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
4534 atm->
q[ctl->
qnt_m][ip] *= aux;
4555 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(cache,met0,met1,atm)") {
4566 while (atm->
lat[ip] < -90 || atm->
lat[ip] > 90) {
4567 if (atm->
lat[ip] > 90) {
4568 atm->
lat[ip] = 180 - atm->
lat[ip];
4569 atm->
lon[ip] += 180;
4571 if (atm->
lat[ip] < -90) {
4572 atm->
lat[ip] = -180 - atm->
lat[ip];
4573 atm->
lon[ip] += 180;
4578 while (atm->
lon[ip] < -180)
4579 atm->
lon[ip] += 360;
4580 while (atm->
lon[ip] >= 180)
4581 atm->
lon[ip] -= 360;
4584 if (atm->
p[ip] < met0->
p[met0->
np - 1]) {
4585 atm->
p[ip] = met0->
p[met0->
np - 1];
4586 }
else if (atm->
p[ip] > 300.) {
4588 if (atm->
p[ip] > ps)
4600 gsl_rng_env_setup();
4601 if (omp_get_max_threads() >
NTHREADS)
4602 ERRMSG(
"Too many threads!");
4603 for (
int i = 0; i <
NTHREADS; i++) {
4604 rng[i] = gsl_rng_alloc(gsl_rng_default);
4605 gsl_rng_set(rng[i], gsl_rng_default_seed
4606 + (
long unsigned) (ntask *
NTHREADS + i));
4611 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
4612 CURAND_STATUS_SUCCESS)
4613 ERRMSG(
"Cannot create random number generator!");
4614 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
4615 CURAND_STATUS_SUCCESS)
4616 ERRMSG(
"Cannot set seed for random number generator!");
4619 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
4620 CURAND_STATUS_SUCCESS)
4621 ERRMSG(
"Cannot set stream for random number generator!");
4638#pragma omp parallel for default(shared)
4639 for (
size_t i = 0; i < n; ++i)
4640 rs[i] = gsl_rng_uniform(rng[omp_get_thread_num()]);
4644 else if (method == 1) {
4645#pragma omp parallel for default(shared)
4646 for (
size_t i = 0; i < n; ++i)
4647 rs[i] = gsl_ran_gaussian_ziggurat(rng[omp_get_thread_num()], 1.0);
4653#pragma acc update device(rs[:n])
4661 const uint64_t key = 0xc8e4fd154ce32f6d;
4665#pragma acc data present(rs)
4666#pragma acc parallel loop independent gang vector
4668#pragma omp parallel for default(shared)
4670 for (
size_t i = 0; i < n + 1; ++i) {
4671 uint64_t r, t, x, y, z;
4672 y = x = (rng_ctr + i) * key;
4675 x = (x >> 32) | (x << 32);
4677 x = (x >> 32) | (x << 32);
4679 x = (x >> 32) | (x << 32);
4681 x = (x >> 32) | (x << 32);
4682 r = t ^ ((x * x + y) >> 32);
4683 rs[i] = (double) r / (
double) UINT64_MAX;
4690#pragma acc parallel loop independent gang vector
4692#pragma omp parallel for default(shared)
4694 for (
size_t i = 0; i < n; i += 2) {
4695 const double r = sqrt(-2.0 * log(rs[i]));
4696 const double phi = 2.0 * M_PI * rs[i + 1];
4697 rs[i] = r * cosf((
float) phi);
4698 rs[i + 1] = r * sinf((
float) phi);
4706#pragma acc host_data use_device(rs)
4711 if (curandGenerateUniformDouble(rng_curand, rs, (n < 4 ? 4 : n)) !=
4712 CURAND_STATUS_SUCCESS)
4713 ERRMSG(
"Cannot create random numbers!");
4717 else if (method == 1) {
4718 if (curandGenerateNormalDouble
4719 (rng_curand, rs, (n < 4 ? 4 : n), 0.0,
4720 1.0) != CURAND_STATUS_SUCCESS)
4721 ERRMSG(
"Cannot create random numbers!");
4725 ERRMSG(
"MPTRAC was compiled without cuRAND!");
4743 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4751 const double v_s =
sedi(atm->
p[ip], t, atm->
q[ctl->
qnt_rp][ip],
4755 atm->
p[ip] +=
DZ2DP(v_s * cache->
dt[ip] / 1000., atm->
p[ip]);
4770 const int np = atm->
np;
4771 double *restrict
const a = (
double *) malloc((
size_t) np *
sizeof(double));
4772 int *restrict
const p = (
int *) malloc((
size_t) np *
sizeof(int));
4773 if (a == NULL || p == NULL)
4774 ERRMSG(
"Out of memory!");
4777#pragma acc enter data create(a[0:np],p[0:np])
4778#pragma acc data present(ctl,met0,atm,a,p)
4783#pragma acc parallel loop independent gang vector
4785#pragma omp parallel for default(shared)
4787 for (
int ip = 0; ip < np; ip++) {
4798#pragma acc host_data use_device(a,p)
4800 thrustSortWrapper(a, np, p);
4803 ERRMSG(
"GSL sort fallback not available on GPU, use THRUST!");
4805 gsl_sort_index((
size_t *) p, a, 1, (
size_t) np);
4813 for (
int iq = 0; iq < ctl->
nq; iq++)
4818#pragma acc exit data delete(a,p)
4832 double *restrict
const help =
4833 (
double *) malloc((
size_t) np *
sizeof(double));
4835 ERRMSG(
"Out of memory!");
4839#pragma acc enter data create(help[0:np])
4840#pragma acc data present(a,p,help)
4841#pragma acc parallel loop independent gang vector
4843#pragma omp parallel for default(shared)
4845 for (
int ip = 0; ip < np; ip++)
4846 help[ip] = a[p[ip]];
4848#pragma acc parallel loop independent gang vector
4850#pragma omp parallel for default(shared)
4852 for (
int ip = 0; ip < np; ip++)
4857#pragma acc exit data delete(help)
4874 const double latmin = gsl_stats_min(met0->
lat, 1, (
size_t) met0->
ny),
4875 latmax = gsl_stats_max(met0->
lat, 1, (
size_t) met0->
ny);
4878 (fabs(met0->
lon[met0->
nx - 1] - met0->
lon[0] - 360.0) >= 0.01);
4881 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,atm)") {
4887 cache->
dt[ip] = t - atm->
time[ip];
4889 cache->
dt[ip] = 0.0;
4898 if (local && (atm->
lon[ip] <= met0->
lon[0]
4899 || atm->
lon[ip] >= met0->
lon[met0->
nx - 1]
4900 || atm->
lat[ip] <= latmin || atm->
lat[ip] >= latmax))
4901 cache->
dt[ip] = 0.0;
4916 SELECT_TIMER(
"MODULE_TIMESTEPS_INIT",
"PHYSICS", NVTX_GPU);
4920 ctl->
t_start = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
4922 ctl->
t_stop = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
4924 ctl->
t_start = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
4926 ctl->
t_stop = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
4931 ERRMSG(
"Nothing to do! Check T_STOP and DIRECTION!");
4951 SELECT_TIMER(
"MODULE_TRACER_CHEM",
"PHYSICS", NVTX_GPU);
4955 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4979 const double K_o1d =
ARRHENIUS(3.30e-10, 0, t) * o1d * M;
4981 atm->
p[ip], sza, o3c);
4982 atm->
q[ctl->
qnt_Cccl4][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4987 const double K_o1d =
ARRHENIUS(2.30e-10, 0, t) * o1d * M;
4989 atm->
p[ip], sza, o3c);
4990 atm->
q[ctl->
qnt_Cccl3f][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4995 const double K_o1d =
ARRHENIUS(1.40e-10, -25, t) * o1d * M;
4997 atm->
p[ip], sza, o3c);
4998 atm->
q[ctl->
qnt_Cccl2f2][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5003 const double K_o1d =
ARRHENIUS(1.19e-10, -20, t) * o1d * M;
5005 atm->
p[ip], sza, o3c);
5006 atm->
q[ctl->
qnt_Cn2o][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5025 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
5028 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
5034 if (!isfinite(pct) || atm->
p[ip] <= pct)
5050 double lwc, rwc, iwc, swc;
5055 const int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
5069 else if (t <= 238.15)
5089 const double K_1 = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
5090 const double K_2 = 6e-8 * exp(1.12e3 * (1. / t - 1. / 298.15));
5091 h *= (1. + K_1 / H_ion + K_1 * K_2 /
SQR(H_ion));
5095 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
5098 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
5124 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
5127 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
5132 const double aux = exp(-cache->
dt[ip] * lambda);
5133 if (ctl->
qnt_m >= 0) {
5136 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
5137 atm->
q[ctl->
qnt_m][ip] *= aux;
5162 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
5164 if (acc_get_num_devices(acc_device_nvidia) <= 0)
5165 ERRMSG(
"Not running on a GPU device!");
5166 acc_set_device_num(rank % acc_get_num_devices(acc_device_nvidia),
5168 acc_device_t device_type = acc_get_device_type();
5169 acc_init(device_type);
5184 SELECT_TIMER(
"CREATE_DATA_REGION",
"MEMORY", NVTX_GPU);
5185 ctl_t *ctlup = *ctl;
5188 met_t *met0up = *met0;
5189 met_t *met1up = *met1;
5190 atm_t *atmup = *atm;
5191#pragma acc enter data create(ctlup[:1],cacheup[:1],climup[:1],met0up[:1],met1up[:1],atmup[:1])
5194#pragma acc enter data create(ddup[:1])
5212 SELECT_TIMER(
"DELETE_DATA_REGION",
"MEMORY", NVTX_GPU);
5213#pragma acc exit data delete (ctl,cache,clim,met0,met1,atm)
5227 MPI_Type_free(&dd->MPI_Particle);
5246 char cachefile[
LEN], cmd[2 *
LEN], filename[
LEN];
5252 if (t == ctl->
t_start || !init) {
5259 ERRMSG(
"Cannot open file!");
5264 ERRMSG(
"Cannot open file!");
5274 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5275 LOG(1,
"Caching: %s", cachefile);
5276 if (system(cmd) != 0)
5277 WARN(
"Caching command failed!");
5282 if (t > (*met1)->time) {
5292 ERRMSG(
"Cannot open file!");
5302 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5303 LOG(1,
"Caching: %s", cachefile);
5304 if (system(cmd) != 0)
5305 WARN(
"Caching command failed!");
5310 if (t < (*met0)->time) {
5320 ERRMSG(
"Cannot open file!");
5330 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5331 LOG(1,
"Caching: %s", cachefile);
5332 if (system(cmd) != 0)
5333 WARN(
"Caching command failed!");
5338 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
5339 if ((*met0)->nx != (*met1)->nx
5340 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
5341 ERRMSG(
"Meteo grid dimensions do not match!");
5342 for (
int ix = 0; ix < (*met0)->nx; ix++)
5343 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
5344 ERRMSG(
"Meteo grid longitudes do not match!");
5345 for (
int iy = 0; iy < (*met0)->ny; iy++)
5346 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
5347 ERRMSG(
"Meteo grid latitudes do not match!");
5348 for (
int ip = 0; ip < (*met0)->np; ip++)
5349 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
5350 ERRMSG(
"Meteo grid pressure levels do not match!");
5376 const char *filename,
5389 LOG(1,
"Read atmospheric data: %s", filename);
5409 ERRMSG(
"Atmospheric data type not supported!");
5417 ERRMSG(
"Can not read any data!");
5421 LOG(2,
"Number of particles: %d", atm->
np);
5422 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
5423 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
5424 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
5425 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
5426 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
5427 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
5428 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
5429 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
5430 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
5431 for (
int iq = 0; iq < ctl->
nq; iq++) {
5433 sprintf(msg,
"Quantity %s range: %s ... %s %s",
5436 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
5437 LOG(2, msg, mini, maxi);
5507 const char *filename,
5516 LOG(1,
"\nMassive-Parallel Trajectory Calculations (MPTRAC)\n"
5517 "(executable: %s | version: %s | compiled: %s, %s)\n",
5518 argv[0], VERSION, __DATE__, __TIME__);
5622 ctl->
nq = (int)
scan_ctl(filename, argc, argv,
"NQ", -1,
"0", NULL);
5624 ERRMSG(
"Too many quantities!");
5625 for (
int iq = 0; iq < ctl->
nq; iq++) {
5631 scan_ctl(filename, argc, argv,
"QNT_FORMAT", iq,
"%g",
5633 if (strcasecmp(ctl->
qnt_name[iq],
"aoa") == 0)
5637 SET_QNT(qnt_idx,
"idx",
"particle index",
"-")
5638 SET_QNT(qnt_ens,
"ens",
"ensemble index",
"-")
5639 SET_QNT(qnt_stat,
"stat",
"station flag",
"-")
5640 SET_QNT(qnt_m,
"m",
"mass",
"kg")
5641 SET_QNT(qnt_vmr,
"vmr",
"volume mixing ratio",
"ppv")
5642 SET_QNT(qnt_rp,
"rp",
"particle radius",
"microns")
5643 SET_QNT(qnt_rhop,
"rhop",
"particle density",
"kg/m^3")
5644 SET_QNT(qnt_ps,
"ps",
"surface pressure",
"hPa")
5645 SET_QNT(qnt_ts,
"ts",
"surface temperature",
"K")
5646 SET_QNT(qnt_zs,
"zs",
"surface height",
"km")
5647 SET_QNT(qnt_us,
"us",
"surface zonal wind",
"m/s")
5648 SET_QNT(qnt_vs,
"vs",
"surface meridional wind",
"m/s")
5649 SET_QNT(qnt_ess,
"ess",
"eastward turbulent surface stress",
"N/m^2")
5650 SET_QNT(qnt_nss,
"nss",
"northward turbulent surface stress",
"N/m^2")
5651 SET_QNT(qnt_shf,
"shf",
"surface sensible heat flux",
"W/m^2")
5652 SET_QNT(qnt_lsm,
"lsm",
"land-sea mask",
"1")
5653 SET_QNT(qnt_sst,
"sst",
"sea surface temperature",
"K")
5654 SET_QNT(qnt_pbl,
"pbl",
"planetary boundary layer",
"hPa")
5655 SET_QNT(qnt_pt,
"pt",
"tropopause pressure",
"hPa")
5656 SET_QNT(qnt_tt,
"tt",
"tropopause temperature",
"K")
5657 SET_QNT(qnt_zt,
"zt",
"tropopause geopotential height",
"km")
5658 SET_QNT(qnt_h2ot,
"h2ot",
"tropopause water vapor",
"ppv")
5659 SET_QNT(qnt_zg,
"zg",
"geopotential height",
"km")
5660 SET_QNT(qnt_p,
"p",
"pressure",
"hPa")
5661 SET_QNT(qnt_t,
"t",
"temperature",
"K")
5662 SET_QNT(qnt_rho,
"rho",
"air density",
"kg/m^3")
5663 SET_QNT(qnt_u,
"u",
"zonal wind",
"m/s")
5664 SET_QNT(qnt_v,
"v",
"meridional wind",
"m/s")
5665 SET_QNT(qnt_w,
"w",
"vertical velocity",
"hPa/s")
5666 SET_QNT(qnt_h2o,
"h2o",
"water vapor",
"ppv")
5667 SET_QNT(qnt_o3,
"o3",
"ozone",
"ppv")
5668 SET_QNT(qnt_lwc,
"lwc",
"cloud liquid water content",
"kg/kg")
5669 SET_QNT(qnt_rwc,
"rwc",
"cloud rain water content",
"kg/kg")
5670 SET_QNT(qnt_iwc,
"iwc",
"cloud ice water content",
"kg/kg")
5671 SET_QNT(qnt_swc,
"swc",
"cloud snow water content",
"kg/kg")
5672 SET_QNT(qnt_cc,
"cc",
"cloud cover",
"1")
5673 SET_QNT(qnt_pct,
"pct",
"cloud top pressure",
"hPa")
5674 SET_QNT(qnt_pcb,
"pcb",
"cloud bottom pressure",
"hPa")
5675 SET_QNT(qnt_cl,
"cl",
"total column cloud water",
"kg/m^2")
5676 SET_QNT(qnt_plcl,
"plcl",
"lifted condensation level",
"hPa")
5677 SET_QNT(qnt_plfc,
"plfc",
"level of free convection",
"hPa")
5678 SET_QNT(qnt_pel,
"pel",
"equilibrium level",
"hPa")
5679 SET_QNT(qnt_cape,
"cape",
"convective available potential energy",
5681 SET_QNT(qnt_cin,
"cin",
"convective inhibition",
"J/kg")
5682 SET_QNT(qnt_o3c,
"o3c",
"total column ozone",
"DU")
5683 SET_QNT(qnt_hno3,
"hno3",
"nitric acid",
"ppv")
5684 SET_QNT(qnt_oh,
"oh",
"hydroxyl radical",
"ppv")
5685 SET_QNT(qnt_h2o2,
"h2o2",
"hydrogen peroxide",
"ppv")
5686 SET_QNT(qnt_ho2,
"ho2",
"hydroperoxyl radical",
"ppv")
5687 SET_QNT(qnt_o1d,
"o1d",
"atomic oxygen",
"ppv")
5688 SET_QNT(qnt_mloss_oh,
"mloss_oh",
"mass loss due to OH chemistry",
"kg")
5689 SET_QNT(qnt_mloss_h2o2,
"mloss_h2o2",
5690 "mass loss due to H2O2 chemistry",
"kg")
5691 SET_QNT(qnt_mloss_kpp,
"mloss_kpp",
"mass loss due to kpp chemistry",
5693 SET_QNT(qnt_mloss_wet,
"mloss_wet",
"mass loss due to wet deposition",
5695 SET_QNT(qnt_mloss_dry,
"mloss_dry",
"mass loss due to dry deposition",
5697 SET_QNT(qnt_mloss_decay,
"mloss_decay",
5698 "mass loss due to exponential decay",
"kg")
5699 SET_QNT(qnt_loss_rate,
"loss_rate",
"total loss rate",
"s^-1")
5700 SET_QNT(qnt_psat,
"psat",
"saturation pressure over water",
"hPa")
5701 SET_QNT(qnt_psice,
"psice",
"saturation pressure over ice",
"hPa")
5702 SET_QNT(qnt_pw,
"pw",
"partial water vapor pressure",
"hPa")
5703 SET_QNT(qnt_sh,
"sh",
"specific humidity",
"kg/kg")
5704 SET_QNT(qnt_rh,
"rh",
"relative humidity",
"%%")
5705 SET_QNT(qnt_rhice,
"rhice",
"relative humidity over ice",
"%%")
5706 SET_QNT(qnt_theta,
"theta",
"potential temperature",
"K")
5707 SET_QNT(qnt_zeta,
"zeta",
"zeta coordinate",
"K")
5708 SET_QNT(qnt_zeta_d,
"zeta_d",
"diagnosed zeta coordinate",
"K")
5709 SET_QNT(qnt_zeta_dot,
"zeta_dot",
"velocity of zeta coordinate",
5711 SET_QNT(qnt_eta,
"eta",
"eta coordinate",
"1")
5712 SET_QNT(qnt_eta_dot,
"eta_dot",
"velocity of eta coordinate",
"1/s")
5713 SET_QNT(qnt_tvirt,
"tvirt",
"virtual temperature",
"K")
5714 SET_QNT(qnt_lapse,
"lapse",
"temperature lapse rate",
"K/km")
5715 SET_QNT(qnt_vh,
"vh",
"horizontal velocity",
"m/s")
5716 SET_QNT(qnt_vz,
"vz",
"vertical velocity",
"m/s")
5717 SET_QNT(qnt_pv,
"pv",
"potential vorticity",
"PVU")
5718 SET_QNT(qnt_tdew,
"tdew",
"dew point temperature",
"K")
5719 SET_QNT(qnt_tice,
"tice",
"frost point temperature",
"K")
5720 SET_QNT(qnt_tsts,
"tsts",
"STS existence temperature",
"K")
5721 SET_QNT(qnt_tnat,
"tnat",
"NAT existence temperature",
"K")
5722 SET_QNT(qnt_Cx,
"Cx",
"Trace species x volume mixing ratio",
"ppv")
5723 SET_QNT(qnt_Ch2o,
"Ch2o",
"H2O volume mixing ratio",
"ppv")
5724 SET_QNT(qnt_Co3,
"Co3",
"O3 volume mixing ratio",
"ppv")
5725 SET_QNT(qnt_Cco,
"Cco",
"CO volume mixing ratio",
"ppv")
5726 SET_QNT(qnt_Coh,
"Coh",
"HO volume mixing ratio",
"ppv")
5727 SET_QNT(qnt_Ch,
"Ch",
"H radical volume mixing ratio",
"ppv")
5728 SET_QNT(qnt_Cho2,
"Cho2",
"HO2 volume mixing ratio",
"ppv")
5729 SET_QNT(qnt_Ch2o2,
"Ch2o2",
"H2O2 volume mixing ratio",
"ppv")
5730 SET_QNT(qnt_Co1d,
"Co1d",
"O(1D) volume mixing ratio",
"ppv")
5731 SET_QNT(qnt_Co3p,
"Co3p",
"O(3P) radical volume mixing ratio",
"ppv")
5732 SET_QNT(qnt_Cccl4,
"Cccl4",
"CCl4 (CFC-10) volume mixing ratio",
"ppv")
5733 SET_QNT(qnt_Cccl3f,
"Cccl3f",
"CCl3F (CFC-11) volume mixing ratio",
5735 SET_QNT(qnt_Cccl2f2,
"Cccl2f2",
"CCl2F2 (CFC-12) volume mixing ratio",
5737 SET_QNT(qnt_Cn2o,
"Cn2o",
"N2O volume mixing ratio",
"ppv")
5738 SET_QNT(qnt_Csf6,
"Csf6",
"SF6 volume mixing ratio",
"ppv")
5739 SET_QNT(qnt_aoa,
"aoa",
"age of air",
"s")
5741 SET_QNT(qnt_destination,
"destination",
5742 "subdomain index of destination",
"-")
5743 SET_QNT(qnt_subdomain,
"subdomain",
"current subdomain index",
"-")
5750 (int)
scan_ctl(filename, argc, argv,
"ADVECT_VERT_COORD", -1,
"0", NULL);
5752 ERRMSG(
"ADVECT_VERT_COORD must be 0, 1, 2, or 3!");
5755 ERRMSG(
"Add quantity zeta for diabatic advection!");
5757 ERRMSG(
"Add quantity eta for etadot avection!");
5760 (int)
scan_ctl(filename, argc, argv,
"MET_VERT_COORD", -1,
"0", NULL);
5762 ERRMSG(
"MET_VERT_COORD must be 0, 1, 2, 3, or 4!");
5766 (
"Using ADVECT_VERT_COORD = 2 requires meteo data on model levels!");
5769 (
"Using ADVECT_VERT_COORD = 3 requires A and B model level coefficients!");
5773 (int)
scan_ctl(filename, argc, argv,
"DIRECTION", -1,
"1", NULL);
5775 ERRMSG(
"Set DIRECTION to -1 or 1!");
5776 ctl->
t_stop =
scan_ctl(filename, argc, argv,
"T_STOP", -1,
"1e100", NULL);
5777 ctl->
dt_mod =
scan_ctl(filename, argc, argv,
"DT_MOD", -1,
"180", NULL);
5781 ctl->
dt_met =
scan_ctl(filename, argc, argv,
"DT_MET", -1,
"3600", NULL);
5783 (int)
scan_ctl(filename, argc, argv,
"MET_CONVENTION", -1,
"0", NULL);
5785 (int)
scan_ctl(filename, argc, argv,
"MET_TYPE", -1,
"0", NULL);
5788 (
"Please use meteo files in netcdf format for diabatic calculations.");
5791 (
"Please use meteo files in netcdf format for etadot calculations.");
5793 (int)
scan_ctl(filename, argc, argv,
"MET_CLAMS", -1,
"0", NULL);
5795 (int)
scan_ctl(filename, argc, argv,
"MET_NC_SCALE", -1,
"1", NULL);
5797 (int)
scan_ctl(filename, argc, argv,
"MET_NC_LEVEL", -1,
"0", NULL);
5799 (int)
scan_ctl(filename, argc, argv,
"MET_NC_QUANT", -1,
"0", NULL);
5801 (int)
scan_ctl(filename, argc, argv,
"MET_ZSTD_LEVEL", -1,
"0", NULL);
5802 for (
int i = 0; i <
METVAR; i++) {
5803 char defprec[
LEN] =
"0", deftol[
LEN] =
"0.0";
5805 sprintf(deftol,
"0.5");
5807 sprintf(deftol,
"5.0");
5809 sprintf(defprec,
"8");
5811 (int)
scan_ctl(filename, argc, argv,
"MET_COMP_PREC", i, defprec, NULL);
5813 scan_ctl(filename, argc, argv,
"MET_COMP_TOL", i, deftol, NULL);
5816 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_BATCH", -1,
"-1", NULL);
5818 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ZSTD", -1,
"1", NULL);
5820 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_HEUR", -1,
"1", NULL);
5822 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_Z", -1,
"1.0", NULL);
5824 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_T", -1,
"0.05", NULL);
5826 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_U", -1,
"0.05", NULL);
5828 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_V", -1,
"0.05", NULL);
5830 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_W", -1,
"1.0", NULL);
5832 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_PV", -1,
"1.0", NULL);
5834 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_H2O", -1,
"1.0", NULL);
5836 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_O3", -1,
"1.0", NULL);
5838 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_LWC", -1,
"1.0", NULL);
5840 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_RWC", -1,
"1.0", NULL);
5842 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_IWC", -1,
"1.0", NULL);
5844 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_SWC", -1,
"1.0", NULL);
5846 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_CC", -1,
"1.0", NULL);
5847 ctl->
met_dx = (int)
scan_ctl(filename, argc, argv,
"MET_DX", -1,
"1", NULL);
5848 ctl->
met_dy = (int)
scan_ctl(filename, argc, argv,
"MET_DY", -1,
"1", NULL);
5849 ctl->
met_dp = (int)
scan_ctl(filename, argc, argv,
"MET_DP", -1,
"1", NULL);
5851 ERRMSG(
"MET_DX, MET_DY, and MET_DP need to be greater than zero!");
5852 ctl->
met_sx = (int)
scan_ctl(filename, argc, argv,
"MET_SX", -1,
"1", NULL);
5853 ctl->
met_sy = (int)
scan_ctl(filename, argc, argv,
"MET_SY", -1,
"1", NULL);
5854 ctl->
met_sp = (int)
scan_ctl(filename, argc, argv,
"MET_SP", -1,
"1", NULL);
5856 ERRMSG(
"MET_SX, MET_SY, and MET_SP need to be greater than zero!");
5858 scan_ctl(filename, argc, argv,
"MET_DETREND", -1,
"-999", NULL);
5859 ctl->
met_np = (int)
scan_ctl(filename, argc, argv,
"MET_NP", -1,
"0", NULL);
5861 ERRMSG(
"Too many pressure levels!");
5863 (int)
scan_ctl(filename, argc, argv,
"MET_PRESS_LEVEL_DEF", -1,
"-1",
5869 for (
int ip = 0; ip < ctl->
met_np; ip++)
5871 scan_ctl(filename, argc, argv,
"MET_P", ip,
"", NULL);
5875 (int)
scan_ctl(filename, argc, argv,
"MET_NLEV", -1,
"0", NULL);
5877 ERRMSG(
"Too many model levels!");
5878 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
5880 scan_ctl(filename, argc, argv,
"MET_LEV_HYAM", ip,
"", NULL);
5881 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
5883 scan_ctl(filename, argc, argv,
"MET_LEV_HYBM", ip,
"", NULL);
5885 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SX", -1,
"-1", NULL);
5887 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SY", -1,
"-1", NULL);
5889 (int)
scan_ctl(filename, argc, argv,
"MET_RELHUM", -1,
"0", NULL);
5891 (int)
scan_ctl(filename, argc, argv,
"MET_CAPE", -1,
"1", NULL);
5893 ERRMSG(
"Set MET_CAPE to 0 or 1!");
5895 (int)
scan_ctl(filename, argc, argv,
"MET_PBL", -1,
"3", NULL);
5897 ERRMSG(
"Set MET_PBL to 0 ... 3!");
5899 scan_ctl(filename, argc, argv,
"MET_PBL_MIN", -1,
"0.1", NULL);
5901 scan_ctl(filename, argc, argv,
"MET_PBL_MAX", -1,
"5.0", NULL);
5903 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO", -1,
"3", NULL);
5905 ERRMSG(
"Set MET_TROPO to 0 ... 5!");
5907 scan_ctl(filename, argc, argv,
"MET_TROPO_PV", -1,
"3.5", NULL);
5909 scan_ctl(filename, argc, argv,
"MET_TROPO_THETA", -1,
"380", NULL);
5911 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO_SPLINE", -1,
"1", NULL);
5913 scan_ctl(filename, argc, argv,
"MET_DT_OUT", -1,
"0.1", NULL);
5915 (int)
scan_ctl(filename, argc, argv,
"MET_CACHE", -1,
"0", NULL);
5917 (int)
scan_ctl(filename, argc, argv,
"MET_MPI_SHARE", -1,
"0", NULL);
5920 ctl->
sort_dt =
scan_ctl(filename, argc, argv,
"SORT_DT", -1,
"-999", NULL);
5924 (int)
scan_ctl(filename, argc, argv,
"ISOSURF", -1,
"0", NULL);
5929 (int)
scan_ctl(filename, argc, argv,
"RNG_TYPE", -1,
"1", NULL);
5931 ERRMSG(
"Set RNG_TYPE to 0, 1, or 2!");
5934 ctl->
advect = (int)
scan_ctl(filename, argc, argv,
"ADVECT", -1,
"2", NULL);
5938 ERRMSG(
"Set ADVECT to 0, 1, 2, or 4!");
5942 = (int)
scan_ctl(filename, argc, argv,
"DIFFUSION", -1,
"0", NULL);
5944 ERRMSG(
"Set DIFFUSION to 0, 1 or 2!");
5946 scan_ctl(filename, argc, argv,
"TURB_DX_PBL", -1,
"50", NULL);
5948 scan_ctl(filename, argc, argv,
"TURB_DX_TROP", -1,
"50", NULL);
5950 scan_ctl(filename, argc, argv,
"TURB_DX_STRAT", -1,
"0", NULL);
5952 scan_ctl(filename, argc, argv,
"TURB_DZ_PBL", -1,
"0", NULL);
5954 scan_ctl(filename, argc, argv,
"TURB_DZ_TROP", -1,
"0", NULL);
5956 scan_ctl(filename, argc, argv,
"TURB_DZ_STRAT", -1,
"0.1", NULL);
5958 scan_ctl(filename, argc, argv,
"TURB_MESOX", -1,
"0.16", NULL);
5960 scan_ctl(filename, argc, argv,
"TURB_MESOZ", -1,
"0.16", NULL);
5964 = (int)
scan_ctl(filename, argc, argv,
"CONV_MIX_PBL", -1,
"0", NULL);
5966 =
scan_ctl(filename, argc, argv,
"CONV_PBL_TRANS", -1,
"0", NULL);
5968 =
scan_ctl(filename, argc, argv,
"CONV_CAPE", -1,
"-999", NULL);
5970 =
scan_ctl(filename, argc, argv,
"CONV_CIN", -1,
"-999", NULL);
5971 ctl->
conv_dt =
scan_ctl(filename, argc, argv,
"CONV_DT", -1,
"-999", NULL);
5975 scan_ctl(filename, argc, argv,
"BOUND_MASS", -1,
"-999", NULL);
5977 scan_ctl(filename, argc, argv,
"BOUND_MASS_TREND", -1,
"0", NULL);
5979 scan_ctl(filename, argc, argv,
"BOUND_VMR", -1,
"-999", NULL);
5981 scan_ctl(filename, argc, argv,
"BOUND_VMR_TREND", -1,
"0", NULL);
5983 scan_ctl(filename, argc, argv,
"BOUND_LAT0", -1,
"-999", NULL);
5985 scan_ctl(filename, argc, argv,
"BOUND_LAT1", -1,
"-999", NULL);
5987 scan_ctl(filename, argc, argv,
"BOUND_P0", -1,
"-999", NULL);
5989 scan_ctl(filename, argc, argv,
"BOUND_P1", -1,
"-999", NULL);
5991 scan_ctl(filename, argc, argv,
"BOUND_DPS", -1,
"-999", NULL);
5993 scan_ctl(filename, argc, argv,
"BOUND_DZS", -1,
"-999", NULL);
5995 scan_ctl(filename, argc, argv,
"BOUND_ZETAS", -1,
"-999", NULL);
5997 (int)
scan_ctl(filename, argc, argv,
"BOUND_PBL", -1,
"0", NULL);
6001 if (strcasecmp(ctl->
species,
"CF2Cl2") == 0) {
6005 }
else if (strcasecmp(ctl->
species,
"CFCl3") == 0) {
6009 }
else if (strcasecmp(ctl->
species,
"CH4") == 0) {
6016 }
else if (strcasecmp(ctl->
species,
"CO") == 0) {
6025 }
else if (strcasecmp(ctl->
species,
"CO2") == 0) {
6029 }
else if (strcasecmp(ctl->
species,
"H2O") == 0) {
6031 }
else if (strcasecmp(ctl->
species,
"N2O") == 0) {
6035 }
else if (strcasecmp(ctl->
species,
"NH3") == 0) {
6042 }
else if (strcasecmp(ctl->
species,
"HNO3") == 0) {
6046 }
else if (strcasecmp(ctl->
species,
"NO") == 0) {
6055 }
else if (strcasecmp(ctl->
species,
"NO2") == 0) {
6064 }
else if (strcasecmp(ctl->
species,
"O3") == 0) {
6071 }
else if (strcasecmp(ctl->
species,
"SF6") == 0) {
6075 }
else if (strcasecmp(ctl->
species,
"SO2") == 0) {
6088 sprintf(defstr,
"%g", ctl->
molmass);
6089 ctl->
molmass =
scan_ctl(filename, argc, argv,
"MOLMASS", -1, defstr, NULL);
6094 (int)
scan_ctl(filename, argc, argv,
"OH_CHEM_REACTION", -1, defstr,
6096 for (
int ip = 0; ip < 4; ip++) {
6097 sprintf(defstr,
"%g", ctl->
oh_chem[ip]);
6099 scan_ctl(filename, argc, argv,
"OH_CHEM", ip, defstr, NULL);
6102 scan_ctl(filename, argc, argv,
"OH_CHEM_BETA", -1,
"0", NULL);
6106 (int)
scan_ctl(filename, argc, argv,
"H2O2_CHEM_REACTION", -1,
"0", NULL);
6110 (int)
scan_ctl(filename, argc, argv,
"KPP_CHEM", -1,
"0", NULL);
6111 ctl->
dt_kpp =
scan_ctl(filename, argc, argv,
"DT_KPP", -1,
"1800", NULL);
6115 (int)
scan_ctl(filename, argc, argv,
"TRACER_CHEM", -1,
"0", NULL);
6118 for (
int ip = 0; ip < 2; ip++) {
6121 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_H", ip, defstr, NULL);
6123 for (
int ip = 0; ip < 1; ip++) {
6126 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_H", ip, defstr, NULL);
6129 scan_ctl(filename, argc, argv,
"WET_DEPO_SO2_PH", -1,
"0", NULL);
6131 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_A", -1,
"0", NULL);
6133 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_B", -1,
"0", NULL);
6135 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_A", -1,
"0", NULL);
6137 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_B", -1,
"0", NULL);
6139 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 0,
"0.5", NULL);
6141 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 1,
"0.36", NULL);
6143 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_RET_RATIO", -1,
"1", NULL);
6145 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_RET_RATIO", -1,
"1", NULL);
6149 scan_ctl(filename, argc, argv,
"DRY_DEPO_VDEP", -1,
"0", NULL);
6151 scan_ctl(filename, argc, argv,
"DRY_DEPO_DP", -1,
"30", NULL);
6154 scan_ctl(filename, argc, argv,
"CLIM_PHOTO", -1,
6155 "../../data/clams_photolysis_rates.nc", ctl->
clim_photo);
6156 scan_ctl(filename, argc, argv,
"CLIM_HNO3_FILENAME", -1,
6158 scan_ctl(filename, argc, argv,
"CLIM_OH_FILENAME", -1,
6160 scan_ctl(filename, argc, argv,
"CLIM_H2O2_FILENAME", -1,
6162 scan_ctl(filename, argc, argv,
"CLIM_HO2_FILENAME", -1,
6164 scan_ctl(filename, argc, argv,
"CLIM_O1D_FILENAME", -1,
6166 scan_ctl(filename, argc, argv,
"CLIM_CCL4_TIMESERIES", -1,
6168 scan_ctl(filename, argc, argv,
"CLIM_CCL3F_TIMESERIES", -1,
6170 scan_ctl(filename, argc, argv,
"CLIM_CCL2F2_TIMESERIES", -1,
6172 scan_ctl(filename, argc, argv,
"CLIM_N2O_TIMESERIES", -1,
6174 scan_ctl(filename, argc, argv,
"CLIM_SF6_TIMESERIES", -1,
6179 scan_ctl(filename, argc, argv,
"MIXING_DT", -1,
"3600.", NULL);
6181 scan_ctl(filename, argc, argv,
"MIXING_TROP", -1,
"-999", NULL);
6183 scan_ctl(filename, argc, argv,
"MIXING_STRAT", -1,
"-999", NULL);
6185 scan_ctl(filename, argc, argv,
"MIXING_Z0", -1,
"-5", NULL);
6187 scan_ctl(filename, argc, argv,
"MIXING_Z1", -1,
"85", NULL);
6189 (int)
scan_ctl(filename, argc, argv,
"MIXING_NZ", -1,
"90", NULL);
6191 scan_ctl(filename, argc, argv,
"MIXING_LON0", -1,
"-180", NULL);
6193 scan_ctl(filename, argc, argv,
"MIXING_LON1", -1,
"180", NULL);
6195 (int)
scan_ctl(filename, argc, argv,
"MIXING_NX", -1,
"360", NULL);
6197 scan_ctl(filename, argc, argv,
"MIXING_LAT0", -1,
"-90", NULL);
6199 scan_ctl(filename, argc, argv,
"MIXING_LAT1", -1,
"90", NULL);
6201 (int)
scan_ctl(filename, argc, argv,
"MIXING_NY", -1,
"180", NULL);
6205 scan_ctl(filename, argc, argv,
"CHEMGRID_Z0", -1,
"-5", NULL);
6207 scan_ctl(filename, argc, argv,
"CHEMGRID_Z1", -1,
"85", NULL);
6209 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NZ", -1,
"90", NULL);
6211 scan_ctl(filename, argc, argv,
"CHEMGRID_LON0", -1,
"-180", NULL);
6213 scan_ctl(filename, argc, argv,
"CHEMGRID_LON1", -1,
"180", NULL);
6215 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NX", -1,
"360", NULL);
6217 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT0", -1,
"-90", NULL);
6219 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT1", -1,
"90", NULL);
6221 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NY", -1,
"180", NULL);
6226 scan_ctl(filename, argc, argv,
"TDEC_STRAT", -1,
"0", NULL);
6229 ctl->
psc_h2o =
scan_ctl(filename, argc, argv,
"PSC_H2O", -1,
"4e-6", NULL);
6231 scan_ctl(filename, argc, argv,
"PSC_HNO3", -1,
"9e-9", NULL);
6237 scan_ctl(filename, argc, argv,
"ATM_DT_OUT", -1,
"86400", NULL);
6239 (int)
scan_ctl(filename, argc, argv,
"ATM_FILTER", -1,
"0", NULL);
6241 (int)
scan_ctl(filename, argc, argv,
"ATM_STRIDE", -1,
"1", NULL);
6243 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE", -1,
"0", NULL);
6245 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE_OUT", -1,
"-1", NULL);
6249 (int)
scan_ctl(filename, argc, argv,
"ATM_NC_LEVEL", -1,
"0", NULL);
6250 for (
int iq = 0; iq < ctl->
nq; iq++)
6252 (
int)
scan_ctl(filename, argc, argv,
"ATM_NC_QUANT", iq,
"0", NULL);
6254 (int)
scan_ctl(filename, argc, argv,
"OBS_TYPE", -1,
"0", NULL);
6260 scan_ctl(filename, argc, argv,
"CSI_DT_OUT", -1,
"86400", NULL);
6263 scan_ctl(filename, argc, argv,
"CSI_OBSMIN", -1,
"0", NULL);
6265 scan_ctl(filename, argc, argv,
"CSI_MODMIN", -1,
"0", NULL);
6266 ctl->
csi_z0 =
scan_ctl(filename, argc, argv,
"CSI_Z0", -1,
"-5", NULL);
6267 ctl->
csi_z1 =
scan_ctl(filename, argc, argv,
"CSI_Z1", -1,
"85", NULL);
6268 ctl->
csi_nz = (int)
scan_ctl(filename, argc, argv,
"CSI_NZ", -1,
"1", NULL);
6270 scan_ctl(filename, argc, argv,
"CSI_LON0", -1,
"-180", NULL);
6271 ctl->
csi_lon1 =
scan_ctl(filename, argc, argv,
"CSI_LON1", -1,
"180", NULL);
6273 (int)
scan_ctl(filename, argc, argv,
"CSI_NX", -1,
"360", NULL);
6274 ctl->
csi_lat0 =
scan_ctl(filename, argc, argv,
"CSI_LAT0", -1,
"-90", NULL);
6275 ctl->
csi_lat1 =
scan_ctl(filename, argc, argv,
"CSI_LAT1", -1,
"90", NULL);
6277 (int)
scan_ctl(filename, argc, argv,
"CSI_NY", -1,
"180", NULL);
6280 ctl->
nens = (int)
scan_ctl(filename, argc, argv,
"NENS", -1,
"0", NULL);
6283 scan_ctl(filename, argc, argv,
"ENS_DT_OUT", -1,
"86400", NULL);
6286 scan_ctl(filename, argc, argv,
"GRID_BASENAME", -1,
"-",
6291 scan_ctl(filename, argc, argv,
"GRID_DT_OUT", -1,
"86400", NULL);
6293 (int)
scan_ctl(filename, argc, argv,
"GRID_SPARSE", -1,
"0", NULL);
6295 (int)
scan_ctl(filename, argc, argv,
"GRID_NC_LEVEL", -1,
"0", NULL);
6296 for (
int iq = 0; iq < ctl->
nq; iq++)
6298 (
int)
scan_ctl(filename, argc, argv,
"GRID_NC_QUANT", iq,
"0", NULL);
6300 (int)
scan_ctl(filename, argc, argv,
"GRID_STDDEV", -1,
"0", NULL);
6301 ctl->
grid_z0 =
scan_ctl(filename, argc, argv,
"GRID_Z0", -1,
"-5", NULL);
6302 ctl->
grid_z1 =
scan_ctl(filename, argc, argv,
"GRID_Z1", -1,
"85", NULL);
6304 (int)
scan_ctl(filename, argc, argv,
"GRID_NZ", -1,
"1", NULL);
6306 scan_ctl(filename, argc, argv,
"GRID_LON0", -1,
"-180", NULL);
6308 scan_ctl(filename, argc, argv,
"GRID_LON1", -1,
"180", NULL);
6310 (int)
scan_ctl(filename, argc, argv,
"GRID_NX", -1,
"360", NULL);
6312 scan_ctl(filename, argc, argv,
"GRID_LAT0", -1,
"-90", NULL);
6314 scan_ctl(filename, argc, argv,
"GRID_LAT1", -1,
"90", NULL);
6316 (int)
scan_ctl(filename, argc, argv,
"GRID_NY", -1,
"180", NULL);
6318 (int)
scan_ctl(filename, argc, argv,
"GRID_TYPE", -1,
"0", NULL);
6321 scan_ctl(filename, argc, argv,
"PROF_BASENAME", -1,
"-",
6324 ctl->
prof_z0 =
scan_ctl(filename, argc, argv,
"PROF_Z0", -1,
"0", NULL);
6325 ctl->
prof_z1 =
scan_ctl(filename, argc, argv,
"PROF_Z1", -1,
"60", NULL);
6327 (int)
scan_ctl(filename, argc, argv,
"PROF_NZ", -1,
"60", NULL);
6329 scan_ctl(filename, argc, argv,
"PROF_LON0", -1,
"-180", NULL);
6331 scan_ctl(filename, argc, argv,
"PROF_LON1", -1,
"180", NULL);
6333 (int)
scan_ctl(filename, argc, argv,
"PROF_NX", -1,
"360", NULL);
6335 scan_ctl(filename, argc, argv,
"PROF_LAT0", -1,
"-90", NULL);
6337 scan_ctl(filename, argc, argv,
"PROF_LAT1", -1,
"90", NULL);
6339 (int)
scan_ctl(filename, argc, argv,
"PROF_NY", -1,
"180", NULL);
6342 scan_ctl(filename, argc, argv,
"SAMPLE_BASENAME", -1,
"-",
6344 scan_ctl(filename, argc, argv,
"SAMPLE_KERNEL", -1,
"-",
6346 scan_ctl(filename, argc, argv,
"SAMPLE_OBSFILE", -1,
"-",
6349 scan_ctl(filename, argc, argv,
"SAMPLE_DX", -1,
"50", NULL);
6351 scan_ctl(filename, argc, argv,
"SAMPLE_DZ", -1,
"-999", NULL);
6354 scan_ctl(filename, argc, argv,
"STAT_BASENAME", -1,
"-",
6358 ctl->
stat_r =
scan_ctl(filename, argc, argv,
"STAT_R", -1,
"50", NULL);
6360 scan_ctl(filename, argc, argv,
"STAT_T0", -1,
"-1e100", NULL);
6361 ctl->
stat_t1 =
scan_ctl(filename, argc, argv,
"STAT_T1", -1,
"1e100", NULL);
6366 scan_ctl(filename, argc, argv,
"VTK_DT_OUT", -1,
"86400", NULL);
6368 (int)
scan_ctl(filename, argc, argv,
"VTK_STRIDE", -1,
"1", NULL);
6370 scan_ctl(filename, argc, argv,
"VTK_SCALE", -1,
"1.0", NULL);
6372 scan_ctl(filename, argc, argv,
"VTK_OFFSET", -1,
"0.0", NULL);
6374 (int)
scan_ctl(filename, argc, argv,
"VTK_SPHERE", -1,
"0", NULL);
6377 ctl->
dd = (int)
scan_ctl(filename, argc, argv,
"DD", -1,
"0", NULL);
6379 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_MERIDIONAL", -1,
6380 (ctl->
dd == 1) ?
"2" :
"1", NULL);
6382 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_ZONAL", -1,
6383 (ctl->
dd == 1) ?
"2" :
"1", NULL);
6386 else if (ctl->
dd == 1)
6387 ERRMSG(
"Please provide zonal and meridional subdomain numbers!")
6389 (int)
scan_ctl(filename, argc, argv,
"DD_NBR_NEIGHBOURS", -1,
"8",
6392 (int)
scan_ctl(filename, argc, argv,
"DD_HALOS_SIZE", -1,
"1", NULL);
6398 const char *filename,
6405 LOG(1,
"Read meteo data: %s", filename);
6411 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
6439 ERRMSG(
"MET_TYPE not implemented!");
6493 LOG(2,
"Broadcast data on rank %d...", rank);
6624 ERRMSG(
"DD initialized, but model is compiled without DD.")
6633 ERRMSG(
"Code was compiled without KPP!");
6666#pragma acc update device(ctl[:1])
6670 if (cache != NULL) {
6673#pragma acc update device(cache[:1])
6680#pragma acc update device(clim[:1])
6687 met_t *met0up = *met0;
6688#pragma acc update device(met0up[:1])
6695 met_t *met1up = *met1;
6696#pragma acc update device(met1up[:1])
6703#pragma acc update device(atm[:1])
6722#pragma acc update host(ctl[:1])
6726 if (cache != NULL) {
6729#pragma acc update host(cache[:1])
6736#pragma acc update host(clim[:1])
6743 met_t *met0up = *met0;
6744#pragma acc update host(met0up[:1])
6751 met_t *met1up = *met1;
6752#pragma acc update host(met1up[:1])
6759#pragma acc update host(atm[:1])
6767 const char *filename,
6776 LOG(1,
"Write atmospheric data: %s", filename);
6800 ERRMSG(
"Atmospheric data type not supported!");
6804 LOG(2,
"Number of particles: %d", atm->
np);
6805 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
6806 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
6807 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
6808 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
6809 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
6810 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
6811 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
6812 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
6813 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
6814 for (
int iq = 0; iq < ctl->
nq; iq++) {
6816 sprintf(msg,
"Quantity %s range: %s ... %s %s",
6819 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
6820 LOG(2, msg, mini, maxi);
6827 const char *filename,
6835 LOG(1,
"Write meteo data: %s", filename);
6840 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
6844 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
6848 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
6852 ERRMSG(
"MPTRAC was compiled without SZ3 compression!");
6865 ERRMSG(
"MET_TYPE not implemented!");
6871 const char *dirname,
6878 char ext[10], filename[2 *
LEN];
6882 int year, mon, day, hour, min, sec;
6885 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
6900 sprintf(ext,
"tab");
6902 sprintf(ext,
"bin");
6905 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6906 dirname, ctl->
atm_basename, year, mon, day, hour, min, ext);
6912 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6915 write_grid(filename, ctl, met0, met1, atm, t);
6920 sprintf(filename,
"%s/%s.tab", dirname, ctl->
csi_basename);
6926 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.tab",
6927 dirname, ctl->
ens_basename, year, mon, day, hour, min);
6933 sprintf(filename,
"%s/%s.tab", dirname, ctl->
prof_basename);
6934 write_prof(filename, ctl, met0, met1, atm, t);
6945 sprintf(filename,
"%s/%s.tab", dirname, ctl->
stat_basename);
6954 sprintf(filename,
"%s/%s_%05d.vtk", dirname, ctl->
vtk_basename, ++nvtk);
6964 const double hno3) {
6967 const double h2o_help =
MAX(h2o, 0.1e-6);
6970 const double p_hno3 = hno3 * p / 1.333224;
6971 const double p_h2o = h2o_help * p / 1.333224;
6972 const double a = 0.009179 - 0.00088 * log10(p_h2o);
6973 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
6974 const double c = -11397.0 / a;
6975 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
6976 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
6994 const double p0 = pbl;
6997 if (atm->
p[ip] > p0)
6999 else if (atm->
p[ip] < p1)
7002 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
7008 const char *filename,
7014 if (!(in = fopen(filename,
"r"))) {
7015 WARN(
"Cannot open file!");
7021 while (fgets(line,
LEN, in)) {
7025 TOK(line, tok,
"%lg", atm->
time[atm->
np]);
7026 TOK(NULL, tok,
"%lg", atm->
p[atm->
np]);
7027 TOK(NULL, tok,
"%lg", atm->
lon[atm->
np]);
7028 TOK(NULL, tok,
"%lg", atm->
lat[atm->
np]);
7029 for (
int iq = 0; iq < ctl->
nq; iq++)
7030 TOK(NULL, tok,
"%lg", atm->
q[iq][atm->
np]);
7033 atm->
p[atm->
np] =
P(atm->
p[atm->
np]);
7036 if ((++atm->
np) >
NP)
7037 ERRMSG(
"Too many data points!");
7050 const char *filename,
7056 if (!(in = fopen(filename,
"r")))
7061 FREAD(&version,
int,
7065 ERRMSG(
"Wrong version of binary data!");
7083 for (
int iq = 0; iq < ctl->
nq; iq++)
7084 FREAD(atm->
q[iq],
double,
7094 ERRMSG(
"Error while reading binary data!");
7106 const char *filename,
7113 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
7120 if (nc_inq_varid(ncid,
"TIME_INIT", &varid) == NC_NOERR) {
7121 NC(nc_get_var_double(ncid, varid, atm->
time));
7123 WARN(
"TIME_INIT not found use time instead!");
7126 for (
int ip = 0; ip < atm->
np; ip++) {
7127 atm->
time[ip] = time_init;
7139 if (nc_inq_varid(ncid,
"PRESS_INIT", &varid) == NC_NOERR) {
7140 NC(nc_get_var_double(ncid, varid, atm->
p));
7142 WARN(
"PRESS_INIT not found use PRESS instead!");
7143 nc_inq_varid(ncid,
"PRESS", &varid);
7144 NC(nc_get_var_double(ncid, varid, atm->
p));
7149 for (
int iq = 0; iq < ctl->
nq; iq++)
7166 const char *filename,
7173 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
7186 for (
int iq = 0; iq < ctl->
nq; iq++)
7199 const char *filename,
7205 LOG(1,
"Read photolysis rates: %s", filename);
7208 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
7209 WARN(
"Photolysis rate data are missing!");
7216 if (photo->
p[0] < photo->
p[1])
7217 ERRMSG(
"Pressure data are not descending!");
7222 if (photo->
o3c[0] > photo->
o3c[1])
7223 ERRMSG(
"Total column ozone data are not ascending!");
7228 if (photo->
sza[0] > photo->
sza[1])
7229 ERRMSG(
"Solar zenith angle data are not ascending!");
7246 LOG(2,
"Number of pressure levels: %d", photo->
np);
7247 LOG(2,
"Altitude levels: %g, %g ... %g km",
7248 Z(photo->
p[0]),
Z(photo->
p[1]),
Z(photo->
p[photo->
np - 1]));
7249 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
7250 photo->
p[0], photo->
p[1], photo->
p[photo->
np - 1]);
7251 LOG(2,
"Number of solar zenith angles: %d", photo->
nsza);
7252 LOG(2,
"Solar zenith angles: %g, %g ... %g deg",
7255 LOG(2,
"Number of total column ozone values: %d", photo->
no3c);
7256 LOG(2,
"Total column ozone: %g, %g ... %g DU",
7258 LOG(2,
"N2O photolysis rate: %g, %g ... %g s**-1",
7259 photo->
n2o[0][0][0], photo->
n2o[1][0][0],
7260 photo->
n2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7261 LOG(2,
"CCl4 photolysis rate: %g, %g ... %g s**-1",
7262 photo->
ccl4[0][0][0], photo->
ccl4[1][0][0],
7264 LOG(2,
"CFC-11 photolysis rate: %g, %g ... %g s**-1",
7265 photo->
ccl3f[0][0][0], photo->
ccl3f[1][0][0],
7267 LOG(2,
"CFC-12 photolysis rate: %g, %g ... %g s**-1",
7270 LOG(2,
"O2 photolysis rate: %g, %g ... %g s**-1",
7271 photo->
o2[0][0][0], photo->
o2[1][0][0],
7272 photo->
o2[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7273 LOG(2,
"O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
7274 photo->
o3_1[0][0][0], photo->
o3_1[1][0][0],
7276 LOG(2,
"O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
7277 photo->
o3_2[0][0][0], photo->
o3_2[1][0][0],
7279 LOG(2,
"H2O2 photolysis rate: %g, %g ... %g s**-1",
7280 photo->
h2o2[0][0][0], photo->
h2o2[1][0][0],
7282 LOG(2,
"H2O photolysis rate: %g, %g ... %g s**-1",
7283 photo->
h2o[0][0][0], photo->
h2o[1][0][0],
7284 photo->
h2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7291 const char *varname,
7305 for (
int ip = 0; ip < photo->
np; ip++)
7306 for (
int is = 0; is < photo->
nsza; is++)
7307 for (
int io = 0; io < photo->
no3c; io++)
7318 const char *filename,
7322 LOG(1,
"Read climatological time series: %s", filename);
7326 if (!(in = fopen(filename,
"r"))) {
7327 WARN(
"Cannot open file!");
7334 while (fgets(line,
LEN, in))
7335 if (sscanf(line,
"%lg %lg", &ts->
time[nh], &ts->
vmr[nh]) == 2) {
7338 ts->
time[nh] = (ts->
time[nh] - 2000.0) * 365.25 * 86400.;
7341 if (nh > 0 && ts->
time[nh] <= ts->
time[nh - 1])
7342 ERRMSG(
"Time series must be ascending!");
7346 ERRMSG(
"Too many data points!");
7355 ERRMSG(
"Not enough data points!");
7358 LOG(2,
"Number of time steps: %d", ts->
ntime);
7359 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s", ts->
time[0], ts->
time[1],
7361 LOG(2,
"Volume mixing ratio range: %g ... %g ppv",
7362 gsl_stats_min(ts->
vmr, 1, (
size_t) nh), gsl_stats_max(ts->
vmr, 1,
7372 const char *filename,
7373 const char *varname,
7376 int ncid, varid, it, iy, iz, iz2, nt;
7378 double *help, varmin = 1e99, varmax = -1e99;
7381 LOG(1,
"Read %s data: %s", varname, filename);
7384 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
7385 WARN(
"%s climatology data are missing!", varname);
7392 if (zm->
p[0] < zm->
p[1])
7393 ERRMSG(
"Pressure data are not descending!");
7398 if (zm->
lat[0] > zm->
lat[1])
7399 ERRMSG(
"Latitude data are not ascending!");
7403 zm->
time[0] = 1209600.00;
7404 zm->
time[1] = 3888000.00;
7405 zm->
time[2] = 6393600.00;
7406 zm->
time[3] = 9072000.00;
7407 zm->
time[4] = 11664000.00;
7408 zm->
time[5] = 14342400.00;
7409 zm->
time[6] = 16934400.00;
7410 zm->
time[7] = 19612800.00;
7411 zm->
time[8] = 22291200.00;
7412 zm->
time[9] = 24883200.00;
7413 zm->
time[10] = 27561600.00;
7414 zm->
time[11] = 30153600.00;
7423 for (it = 0; it < zm->
ntime; it++)
7424 for (iz = 0; iz < zm->
np; iz++)
7425 for (iy = 0; iy < zm->
nlat; iy++)
7430 for (it = 0; it < zm->
ntime; it++)
7431 for (iy = 0; iy < zm->
nlat; iy++)
7432 for (iz = 0; iz < zm->
np; iz++) {
7433 if (zm->
vmr[it][iz][iy] < 0) {
7434 for (iz2 = 0; iz2 < zm->
np; iz2++)
7435 if (zm->
vmr[it][iz2][iy] >= 0) {
7436 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
7439 for (iz2 = zm->
np - 1; iz2 >= 0; iz2--)
7440 if (zm->
vmr[it][iz2][iy] >= 0) {
7441 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
7445 varmin =
MIN(varmin, zm->
vmr[it][iz][iy]);
7446 varmax =
MAX(varmax, zm->
vmr[it][iz][iy]);
7453 LOG(2,
"Number of time steps: %d", zm->
ntime);
7454 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
7456 LOG(2,
"Number of pressure levels: %d", zm->
np);
7457 LOG(2,
"Altitude levels: %g, %g ... %g km",
7458 Z(zm->
p[0]),
Z(zm->
p[1]),
Z(zm->
p[zm->
np - 1]));
7459 LOG(2,
"Pressure levels: %g, %g ... %g hPa", zm->
p[0],
7460 zm->
p[1], zm->
p[zm->
np - 1]);
7461 LOG(2,
"Number of latitudes: %d", zm->
nlat);
7462 LOG(2,
"Latitudes: %g, %g ... %g deg",
7464 LOG(2,
"%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
7471 const char *filename,
7477 LOG(1,
"Read kernel function: %s", filename);
7481 if (!(in = fopen(filename,
"r")))
7482 ERRMSG(
"Cannot open file!");
7487 while (fgets(line,
LEN, in))
7488 if (sscanf(line,
"%lg %lg", &kz[n], &kw[n]) == 2) {
7489 if (n > 0 && kz[n] < kz[n - 1])
7490 ERRMSG(
"Height levels must be ascending!");
7492 ERRMSG(
"Too many height levels!");
7501 ERRMSG(
"Not enough height levels!");
7504 const double kmax = gsl_stats_max(kw, 1, (
size_t) n);
7505 for (
int iz = 0; iz < n; iz++)
7512 const char *filename,
7520 int year, mon, day, hour, min, sec;
7526 if (!(in = fopen(filename,
"r"))) {
7527 WARN(
"Cannot open file!");
7533 FREAD(&met_type,
int,
7537 ERRMSG(
"Wrong MET_TYPE of binary data!");
7541 FREAD(&version,
int,
7545 ERRMSG(
"Wrong version of binary data!");
7551 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
7552 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
7553 met->
time, year, mon, day, hour, min);
7554 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
7555 || day < 1 || day > 31 || hour < 0 || hour > 23)
7556 ERRMSG(
"Error while reading time!");
7562 LOG(2,
"Number of longitudes: %d", met->
nx);
7563 if (met->
nx < 2 || met->
nx >
EX)
7564 ERRMSG(
"Number of longitudes out of range!");
7569 LOG(2,
"Number of latitudes: %d", met->
ny);
7570 if (met->
ny < 2 || met->
ny >
EY)
7571 ERRMSG(
"Number of latitudes out of range!");
7576 LOG(2,
"Number of levels: %d", met->
np);
7577 if (met->
np < 2 || met->
np >
EP)
7578 ERRMSG(
"Number of levels out of range!");
7584 LOG(2,
"Longitudes: %g, %g ... %g deg",
7590 LOG(2,
"Latitudes: %g, %g ... %g deg",
7596 LOG(2,
"Altitude levels: %g, %g ... %g km",
7597 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
7598 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
7599 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
7648 ERRMSG(
"Error while reading binary data!");
7663 const char *varname) {
7672 LOG(2,
"Read 2-D variable: %s (uncompressed)", varname);
7674 (
size_t) (met->
nx * met->
ny),
7678 for (
int ix = 0; ix < met->
nx; ix++)
7679 for (
int iy = 0; iy < met->
ny; iy++)
7680 var[ix][iy] = help[
ARRAY_2D(ix, iy, met->
ny)];
7693 const char *varname,
7694 const float bound_min,
7695 const float bound_max) {
7705 LOG(2,
"Read 3-D variable: %s (uncompressed)", varname);
7707 (
size_t) (met->
nx * met->
ny * met->
np),
7714 (
size_t) met->
np, 1, in);
7720 FREAD(&precision,
int,
7725 FREAD(&tolerance,
double,
7732 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
7742 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
7750 (
size_t) met->
np, 1, in);
7752 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
7760 FREAD(&precision,
int,
7765 FREAD(&tolerance,
double,
7772 ERRMSG(
"MPTRAC was compiled without sz3 compression!");
7777#pragma omp parallel for default(shared) collapse(2)
7778 for (
int ix = 0; ix < met->
nx; ix++)
7779 for (
int iy = 0; iy < met->
ny; iy++)
7780 for (
int ip = 0; ip < met->
np; ip++) {
7781 var[ix][iy][ip] = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
7782 if (var[ix][iy][ip] < bound_min)
7783 var[ix][iy][ip] = bound_min;
7784 else if (var[ix][iy][ip] > bound_max)
7785 var[ix][iy][ip] = bound_max;
7805 LOG(2,
"Calculate CAPE...");
7808 const double pfac = 1.01439, dz0 =
RI /
MA /
G0 * log(pfac);
7811#pragma omp parallel for default(shared) collapse(2)
7812 for (
int ix = 0; ix < met->
nx; ix++)
7813 for (
int iy = 0; iy < met->
ny; iy++) {
7817 double h2o = 0, t, theta = 0;
7818 double pbot =
MIN(met->
ps[ix][iy], met->
p[0]);
7819 double ptop = pbot - 50.;
7820 for (
int ip = 0; ip < met->
np; ip++) {
7821 if (met->
p[ip] <= pbot) {
7822 theta +=
THETA(met->
p[ip], met->
t[ix][iy][ip]);
7823 h2o += met->
h2o[ix][iy][ip];
7826 if (met->
p[ip] < ptop && n > 0)
7833 met->
plcl[ix][iy] = NAN;
7834 met->
plfc[ix][iy] = NAN;
7835 met->
pel[ix][iy] = NAN;
7836 met->
cape[ix][iy] = NAN;
7837 met->
cin[ix][iy] = NAN;
7843 pbot = met->
ps[ix][iy];
7845 met->
plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
7846 t = theta / pow(1000. / met->
plcl[ix][iy], 0.286);
7847 if (
RH(met->
plcl[ix][iy], t, h2o) > 100.)
7848 ptop = met->
plcl[ix][iy];
7850 pbot = met->
plcl[ix][iy];
7851 }
while (pbot - ptop > 0.1);
7855 double dcape, dz, h2o_env, t_env;
7856 double p = met->
ps[ix][iy];
7857 met->
cape[ix][iy] = met->
cin[ix][iy] = 0;
7859 dz = dz0 *
TVIRT(t, h2o);
7861 t = theta / pow(1000. / p, 0.286);
7865 &h2o_env, ci, cw, 0);
7866 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
7867 TVIRT(t_env, h2o_env) * dz;
7869 met->
cin[ix][iy] += fabsf((
float) dcape);
7870 }
while (p > met->
plcl[ix][iy]);
7875 p = met->
plcl[ix][iy];
7876 t = theta / pow(1000. / p, 0.286);
7879 dz = dz0 *
TVIRT(t, h2o);
7882 double psat =
PSAT(t);
7883 h2o = psat / (p - (1. -
EPS) * psat);
7887 &h2o_env, ci, cw, 0);
7888 double dcape_old = dcape;
7889 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
7890 TVIRT(t_env, h2o_env) * dz;
7892 met->
cape[ix][iy] += (float) dcape;
7893 if (!isfinite(met->
plfc[ix][iy]))
7894 met->
plfc[ix][iy] = (
float) p;
7895 }
else if (dcape_old > 0)
7896 met->
pel[ix][iy] = (float) p;
7897 if (dcape < 0 && !isfinite(met->
plfc[ix][iy]))
7898 met->
cin[ix][iy] += fabsf((
float) dcape);
7902 if (!isfinite(met->
plfc[ix][iy]))
7903 met->
cin[ix][iy] = NAN;
7914 LOG(2,
"Calculate cloud data...");
7917 const double ccmin = 0.01, cwmin = 1e-6;
7920#pragma omp parallel for default(shared) collapse(2)
7921 for (
int ix = 0; ix < met->
nx; ix++)
7922 for (
int iy = 0; iy < met->
ny; iy++) {
7925 met->
pct[ix][iy] = NAN;
7926 met->
pcb[ix][iy] = NAN;
7927 met->
cl[ix][iy] = 0;
7930 for (
int ip = 0; ip < met->
np - 1; ip++) {
7933 if (met->
p[ip] > met->
ps[ix][iy] || met->
p[ip] <
P(20.))
7937 if (met->
cc[ix][iy][ip] > ccmin
7938 && (met->
lwc[ix][iy][ip] > cwmin
7939 || met->
rwc[ix][iy][ip] > cwmin
7940 || met->
iwc[ix][iy][ip] > cwmin
7941 || met->
swc[ix][iy][ip] > cwmin)) {
7945 = (float) (0.5 * (met->
p[ip] + (
float) met->
p[ip + 1]));
7948 if (!isfinite(met->
pcb[ix][iy]))
7950 = (
float) (0.5 * (met->
p[ip] + met->
p[
MAX(ip - 1, 0)]));
7954 met->
cl[ix][iy] += (float)
7955 (0.5 * (met->
lwc[ix][iy][ip] + met->
lwc[ix][iy][ip + 1]
7956 + met->
rwc[ix][iy][ip] + met->
rwc[ix][iy][ip + 1]
7957 + met->
iwc[ix][iy][ip] + met->
iwc[ix][iy][ip + 1]
7958 + met->
swc[ix][iy][ip] + met->
swc[ix][iy][ip + 1])
7959 * 100. * (met->
p[ip] - met->
p[ip + 1]) /
G0);
7977 SELECT_TIMER(
"READ_MET_DETREND",
"METPROC", NVTX_READ);
7978 LOG(2,
"Detrend meteo data...");
7985 const double tssq = 2. *
SQR(sigma);
7988 int sy = (int) (3. *
DY2DEG(sigma) / fabs(met->
lat[1] - met->
lat[0]));
7992#pragma omp parallel for default(shared) collapse(2)
7993 for (
int ix = 0; ix < met->
nx; ix++) {
7994 for (
int iy = 0; iy < met->
ny; iy++) {
8002 (int) (3. *
DX2DEG(sigma, met->
lat[iy]) /
8003 fabs(met->
lon[1] - met->
lon[0]));
8008 for (
int ip = 0; ip < met->
np; ip++) {
8009 help->
t[ix][iy][ip] = 0;
8010 help->
u[ix][iy][ip] = 0;
8011 help->
v[ix][iy][ip] = 0;
8012 help->
w[ix][iy][ip] = 0;
8016 for (
int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
8020 else if (ix3 >= met->
nx)
8022 for (
int iy2 =
MAX(iy - sy, 0);
8023 iy2 <=
MIN(iy + sy, met->
ny - 1); iy2++) {
8030 const float w = (float) exp(-
DIST2(x0, x1) / tssq);
8034 for (
int ip = 0; ip < met->
np; ip++) {
8035 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip];
8036 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip];
8037 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip];
8038 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip];
8044 for (
int ip = 0; ip < met->
np; ip++) {
8045 help->
t[ix][iy][ip] /= wsum;
8046 help->
u[ix][iy][ip] /= wsum;
8047 help->
v[ix][iy][ip] /= wsum;
8048 help->
w[ix][iy][ip] /= wsum;
8054#pragma omp parallel for default(shared) collapse(3)
8055 for (
int ix = 0; ix < met->
nx; ix++)
8056 for (
int iy = 0; iy < met->
ny; iy++)
8057 for (
int ip = 0; ip < met->
np; ip++) {
8058 met->
t[ix][iy][ip] -= help->
t[ix][iy][ip];
8059 met->
u[ix][iy][ip] -= help->
u[ix][iy][ip];
8060 met->
v[ix][iy][ip] -= help->
v[ix][iy][ip];
8061 met->
w[ix][iy][ip] -= help->
w[ix][iy][ip];
8074 SELECT_TIMER(
"READ_MET_EXTRAPOLATE",
"METPROC", NVTX_READ);
8075 LOG(2,
"Extrapolate meteo data...");
8078#pragma omp parallel for default(shared) collapse(2)
8079 for (
int ix = 0; ix < met->
nx; ix++)
8080 for (
int iy = 0; iy < met->
ny; iy++) {
8084 for (ip0 = met->
np - 1; ip0 >= 0; ip0--)
8085 if (!isfinite(met->
t[ix][iy][ip0])
8086 || !isfinite(met->
u[ix][iy][ip0])
8087 || !isfinite(met->
v[ix][iy][ip0])
8088 || !isfinite(met->
w[ix][iy][ip0]))
8092 for (
int ip = ip0; ip >= 0; ip--) {
8093 met->
t[ix][iy][ip] = met->
t[ix][iy][ip + 1];
8094 met->
u[ix][iy][ip] = met->
u[ix][iy][ip + 1];
8095 met->
v[ix][iy][ip] = met->
v[ix][iy][ip + 1];
8096 met->
w[ix][iy][ip] = met->
w[ix][iy][ip + 1];
8097 met->
h2o[ix][iy][ip] = met->
h2o[ix][iy][ip + 1];
8098 met->
o3[ix][iy][ip] = met->
o3[ix][iy][ip + 1];
8099 met->
lwc[ix][iy][ip] = met->
lwc[ix][iy][ip + 1];
8100 met->
rwc[ix][iy][ip] = met->
rwc[ix][iy][ip + 1];
8101 met->
iwc[ix][iy][ip] = met->
iwc[ix][iy][ip + 1];
8102 met->
swc[ix][iy][ip] = met->
swc[ix][iy][ip + 1];
8103 met->
cc[ix][iy][ip] = met->
cc[ix][iy][ip + 1];
8122 LOG(2,
"Calculate geopotential heights...");
8129#pragma omp parallel for default(shared)
8130 for (
int ip = 0; ip < met->
np; ip++)
8131 logp[ip] = log(met->
p[ip]);
8134#pragma omp parallel for default(shared) collapse(2)
8135 for (
int ix = 0; ix < met->
nx; ix++)
8136 for (
int iy = 0; iy < met->
ny; iy++) {
8139 const double zs = met->
zs[ix][iy];
8140 const double lnps = log(met->
ps[ix][iy]);
8144 const double ts =
LIN(met->
p[ip0], met->
t[ix][iy][ip0], met->
p[ip0 + 1],
8145 met->
t[ix][iy][ip0 + 1], met->
ps[ix][iy]);
8147 LIN(met->
p[ip0], met->
h2o[ix][iy][ip0], met->
p[ip0 + 1],
8148 met->
h2o[ix][iy][ip0 + 1], met->
ps[ix][iy]);
8151 met->
z[ix][iy][ip0 + 1]
8153 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
8154 met->
t[ix][iy][ip0 + 1], met->
h2o[ix][iy][ip0 + 1]));
8155 for (
int ip = ip0 + 2; ip < met->
np; ip++)
8157 = (
float) (met->
z[ix][iy][ip - 1] +
8158 ZDIFF(logp[ip - 1], met->
t[ix][iy][ip - 1],
8159 met->
h2o[ix][iy][ip - 1], logp[ip],
8160 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
8165 ZDIFF(lnps, ts, h2os, logp[ip0],
8166 met->
t[ix][iy][ip0], met->
h2o[ix][iy][ip0]));
8167 for (
int ip = ip0 - 1; ip >= 0; ip--)
8169 = (
float) (met->
z[ix][iy][ip + 1] +
8170 ZDIFF(logp[ip + 1], met->
t[ix][iy][ip + 1],
8171 met->
h2o[ix][iy][ip + 1], logp[ip],
8172 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
8176 if (dx == 0 || dy == 0)
8180 if (dx < 0 || dy < 0) {
8181 if (fabs(met->
lon[1] - met->
lon[0]) < 0.5) {
8191 float ws[dx + 1][dy + 1];
8192#pragma omp parallel for default(shared) collapse(2)
8193 for (
int ix = 0; ix <= dx; ix++)
8194 for (
int iy = 0; iy < dy; iy++)
8195 ws[ix][iy] = (1.0f - (
float) ix / (float) dx)
8196 * (1.0f - (float) iy / (
float) dy);
8199#pragma omp parallel for default(shared) collapse(3)
8200 for (
int ix = 0; ix < met->
nx; ix++)
8201 for (
int iy = 0; iy < met->
ny; iy++)
8202 for (
int ip = 0; ip < met->
np; ip++)
8203 help[
ARRAY_3D(ip, ix, met->
nx, iy, met->
ny)] = met->
z[ix][iy][ip];
8206#pragma omp parallel for default(shared) collapse(3)
8207 for (
int ip = 0; ip < met->
np; ip++)
8208 for (
int ix = 0; ix < met->
nx; ix++)
8209 for (
int iy = 0; iy < met->
ny; iy++) {
8210 float res = 0, wsum = 0;
8211 int iy0 =
MAX(iy - dy + 1, 0);
8212 int iy1 =
MIN(iy + dy - 1, met->
ny - 1);
8213 for (
int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
8217 else if (ix3 >= met->
nx)
8219 for (
int iy2 = iy0; iy2 <= iy1; ++iy2)
8220 if (isfinite(help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)])) {
8221 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
8222 res += w * help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)];
8227 met->
z[ix][iy][ip] = res / wsum;
8229 met->
z[ix][iy][ip] = NAN;
8239 const char *filename,
8245 char levname[
LEN], tstr[10];
8247 double rtime = 0, r, r2;
8249 int varid, ndims, dimids[NC_MAX_DIMS], year2, mon2, day2, hour2, min2, sec2,
8250 year, mon, day, hour, min, sec;
8256 LOG(2,
"Read meteo grid information...");
8265 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
8266 if (nc_inq_varid(ncid,
"time", &varid) == NC_NOERR) {
8267 NC(nc_get_var_double(ncid, varid, &rtime));
8268 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
8269 WARN(
"Time information in meteo file does not match filename!");
8271 WARN(
"Time information in meteo file is missing!");
8282 sprintf(tstr,
"19%.2s", &filename[strlen(filename) - 11]);
8284 sprintf(tstr,
"20%.2s", &filename[strlen(filename) - 11]);
8286 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 9]);
8288 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 7]);
8290 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 5]);
8296 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
8297 || day < 1 || day > 31 || hour < 0 || hour > 23)
8298 ERRMSG(
"Cannot read time from filename!");
8299 jsec2time(met->
time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
8300 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
8301 met->
time, year2, mon2, day2, hour2, min2);
8304 if (nc_inq_varid(ncid,
"u", &varid) != NC_NOERR)
8305 if (nc_inq_varid(ncid,
"U", &varid) != NC_NOERR)
8307 (
"Variable 'u' or 'U' not found, cannot determine vertical dimension!");
8309 NC(nc_inq_varndims(ncid, varid, &ndims));
8310 NC(nc_inq_vardimid(ncid, varid, dimids));
8314 (ncid, dimids[ctl->
met_convention == 0 ? 1 : 3], levname, &dimlen));
8315 }
else if (ndims == 3) {
8317 (ncid, dimids[ctl->
met_convention == 0 ? 0 : 2], levname, &dimlen));
8319 ERRMSG(
"Cannot determine vertical dimension!")
8320 met->
np = (int) dimlen;
8322 LOG(2,
"Number of levels: %d", met->
np);
8323 if (met->
np < 2 || met->
np >
EP)
8324 ERRMSG(
"Number of levels out of range!");
8330 LOG(2,
"Number of longitudes: %d", met->
nx);
8333 LOG(2,
"Number of latitudes: %d", met->
ny);
8337 LOG(2,
"Longitudes: %g, %g ... %g deg",
8340 LOG(2,
"Latitudes: %g, %g ... %g deg",
8353 for (
int ip = 0; ip < met->
np; ip++)
8355 LOG(2,
"Altitude levels: %g, %g ... %g km",
8356 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
8357 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
8358 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
8362 if (strcasecmp(levname,
"hybrid") == 0)
8374 ERRMSG(
"You need to specify MET_NLEV, MET_LEV_HYAM, and MET_LEV_HYBM!");
8375 for (
int ip = 0; ip < ctl->
met_nlev; ip++) {
8383 met->
eta[k] = met->
hyam[k] / 100000.0 + met->
hybm[k];
8385 ERRMSG(
"Eta levels must be ascending!");
8389 for (
int ix = 2; ix < met->
nx; ix++)
8391 (fabs(met->
lon[ix] - met->
lon[ix - 1]) -
8392 fabs(met->
lon[1] - met->
lon[0])) > 0.001)
8393 ERRMSG(
"No regular grid spacing in longitudes!");
8394 for (
int iy = 2; iy < met->
ny; iy++)
8396 (fabs(met->
lat[iy] - met->
lat[iy - 1]) -
8397 fabs(met->
lat[1] - met->
lat[0])) > 0.001) {
8398 WARN(
"No regular grid spacing in latitudes!");
8413 LOG(2,
"Read surface data...");
8417 (ncid,
"lnsp",
"LNSP", NULL, NULL, NULL, NULL, ctl, met, dd, met->
ps,
8419 for (
int ix = 0; ix < met->
nx; ix++)
8420 for (
int iy = 0; iy < met->
ny; iy++)
8421 met->
ps[ix][iy] = (
float) (exp(met->
ps[ix][iy]) / 100.);
8424 (ncid,
"ps",
"PS",
"sp",
"SP", NULL, NULL, ctl, met, dd, met->
ps,
8426 WARN(
"Cannot not read surface pressure data (use lowest level)!");
8427 for (
int ix = 0; ix < met->
nx; ix++)
8428 for (
int iy = 0; iy < met->
ny; iy++)
8430 = (ctl->
met_np > 0 ? (
float) ctl->
met_p[0] : (
float) met->
p[0]);
8438 (ncid,
"z",
"Z", NULL, NULL, NULL, NULL, ctl, met, dd, met->
zs,
8439 (
float) (1. / (1000. *
G0)), 1))
8441 (ncid,
"zm",
"ZM", NULL, NULL, NULL, NULL, ctl, met, dd, met->
zs,
8442 (
float) (1. / 1000.), 1))
8443 WARN(
"Cannot read surface geopotential height!");
8454 memcpy(help, met->
pl,
sizeof(met->
pl));
8456 (ncid,
"gph",
"GPH", NULL, NULL, ctl, met, dd, met->
pl,
8457 (
float) (1e-3 /
G0)))
8458 ERRMSG(
"Cannot read geopotential height!");
8459 for (
int ix = 0; ix < met->
nx; ix++)
8460 for (
int iy = 0; iy < met->
ny; iy++)
8461 met->
zs[ix][iy] = met->
pl[ix][iy][0];
8462 memcpy(met->
pl, help,
sizeof(met->
pl));
8468 (ncid,
"t2m",
"T2M",
"2t",
"2T",
"t2",
"T2", ctl, met, dd, met->
ts, 1.0,
8470 WARN(
"Cannot read surface temperature!");
8474 (ncid,
"u10m",
"U10M",
"10u",
"10U",
"u10",
"U10", ctl, met, dd,
8476 WARN(
"Cannot read surface zonal wind!");
8480 (ncid,
"v10m",
"V10M",
"10v",
"10V",
"v10",
"V10", ctl, met, dd,
8482 WARN(
"Cannot read surface meridional wind!");
8486 (ncid,
"iews",
"IEWS", NULL, NULL, NULL, NULL, ctl, met, dd, met->
ess,
8488 WARN(
"Cannot read eastward turbulent surface stress!");
8492 (ncid,
"inss",
"INSS", NULL, NULL, NULL, NULL, ctl, met, dd, met->
nss,
8494 WARN(
"Cannot read nothward turbulent surface stress!");
8498 (ncid,
"ishf",
"ISHF", NULL, NULL, NULL, NULL, ctl, met, dd, met->
shf,
8500 WARN(
"Cannot read surface sensible heat flux!");
8504 (ncid,
"lsm",
"LSM", NULL, NULL, NULL, NULL, ctl, met, dd, met->
lsm,
8506 WARN(
"Cannot read land-sea mask!");
8510 (ncid,
"sstk",
"SSTK",
"sst",
"SST", NULL, NULL, ctl, met, dd, met->
sst,
8512 WARN(
"Cannot read sea surface temperature!");
8517 (ncid,
"blp",
"BLP", NULL, NULL, NULL, NULL, ctl, met, dd, met->
pbl,
8519 WARN(
"Cannot read planetary boundary layer pressure!");
8522 (ncid,
"blh",
"BLH", NULL, NULL, NULL, NULL, ctl, met, dd, met->
pbl,
8524 WARN(
"Cannot read planetary boundary layer height!");
8529 (ncid,
"cape",
"CAPE", NULL, NULL, NULL, NULL, ctl, met, dd,
8531 WARN(
"Cannot read CAPE!");
8536 (ncid,
"cin",
"CIN", NULL, NULL, NULL, NULL, ctl, met, dd, met->
cin,
8538 WARN(
"Cannot read convective inhibition!");
8550 SELECT_TIMER(
"READ_MET_NC_LEVELS",
"INPUT", NVTX_READ);
8551 LOG(2,
"Read level data...");
8555 (ncid,
"t",
"T",
"temp",
"TEMP", ctl, met, dd, met->
t, 1.0))
8556 ERRMSG(
"Cannot read temperature!");
8559 if (!
read_met_nc_3d(ncid,
"u",
"U", NULL, NULL, ctl, met, dd, met->
u, 1.0))
8560 ERRMSG(
"Cannot read zonal wind!");
8561 if (!
read_met_nc_3d(ncid,
"v",
"V", NULL, NULL, ctl, met, dd, met->
v, 1.0))
8562 ERRMSG(
"Cannot read meridional wind!");
8564 (ncid,
"w",
"W",
"omega",
"OMEGA", ctl, met, dd, met->
w, 0.01f))
8565 WARN(
"Cannot read vertical velocity!");
8570 (ncid,
"q",
"Q",
"sh",
"SH", ctl, met, dd, met->
h2o,
8572 WARN(
"Cannot read specific humidity!");
8575 (ncid,
"rh",
"RH", NULL, NULL, ctl, met, dd, met->
h2o, 0.01f))
8576 WARN(
"Cannot read relative humidity!");
8577#pragma omp parallel for default(shared) collapse(2)
8578 for (
int ix = 0; ix < met->
nx; ix++)
8579 for (
int iy = 0; iy < met->
ny; iy++)
8580 for (
int ip = 0; ip < met->
np; ip++) {
8581 double pw = met->
h2o[ix][iy][ip] *
PSAT(met->
t[ix][iy][ip]);
8582 met->
h2o[ix][iy][ip] =
8583 (float) (pw / (met->
p[ip] - (1.0 -
EPS) * pw));
8589 (ncid,
"o3",
"O3", NULL, NULL, ctl, met, dd, met->
o3,
8590 (
float) (
MA /
MO3)))
8591 WARN(
"Cannot read ozone data!");
8595 (ncid,
"clwc",
"CLWC", NULL, NULL, ctl, met, dd, met->
lwc, 1.0))
8596 WARN(
"Cannot read cloud liquid water content!");
8598 (ncid,
"crwc",
"CRWC", NULL, NULL, ctl, met, dd, met->
rwc, 1.0))
8599 WARN(
"Cannot read cloud rain water content!");
8601 (ncid,
"ciwc",
"CIWC", NULL, NULL, ctl, met, dd, met->
iwc, 1.0))
8602 WARN(
"Cannot read cloud ice water content!");
8604 (ncid,
"cswc",
"CSWC", NULL, NULL, ctl, met, dd, met->
swc, 1.0))
8605 WARN(
"Cannot read cloud snow water content!");
8607 (ncid,
"cc",
"CC", NULL, NULL, ctl, met, dd, met->
cc, 1.0))
8608 WARN(
"Cannot read cloud cover!");
8613 (ncid,
"ZETA",
"zeta", NULL, NULL, ctl, met, dd, met->
zetal, 1.0))
8614 WARN(
"Cannot read ZETA!");
8616 (ncid,
"ZETA_DOT_TOT",
"ZETA_DOT_clr",
"zeta_dot_clr",
8617 NULL, ctl, met, dd, met->
zeta_dotl, 0.00001157407f))
8618 WARN(
"Cannot read ZETA_DOT!");
8623#pragma omp parallel for default(shared)
8624 for (
int ix = 0; ix < met->
nx; ix++)
8625 for (
int iy = 0; iy < met->
ny; iy++)
8626 for (
int ip = 0; ip < met->
np; ip++)
8627 met->
zetal[ix][iy][ip] =
8628 (
float) (met->
hyam[ip] / 100000.0 + met->
hybm[ip]);
8630 (ncid,
"etadot",
"ETADOT", NULL, NULL, ctl, met, dd, met->
zeta_dotl,
8632 WARN(
"Cannot read eta vertical velocity!");
8637#pragma omp parallel for default(shared)
8638 for (
int ix = 0; ix < met->
nx; ix++)
8639 for (
int iy = 0; iy < met->
ny; iy++)
8640 for (
int ip = 0; ip < met->
np; ip++) {
8641 met->
ul[ix][iy][ip] = met->
u[ix][iy][ip];
8642 met->
vl[ix][iy][ip] = met->
v[ix][iy][ip];
8643 met->
wl[ix][iy][ip] = met->
w[ix][iy][ip];
8656 (ncid,
"pl",
"PL",
"pressure",
"PRESSURE", ctl, met, dd, met->
pl,
8659 (ncid,
"press",
"PRESS", NULL, NULL, ctl, met, dd, met->
pl, 1.0))
8660 ERRMSG(
"Cannot read pressure on model levels!");
8668 ERRMSG(
"Mismatch in number of model levels!");
8671 for (
int ix = 0; ix < met->
nx; ix++)
8672 for (
int iy = 0; iy < met->
ny; iy++)
8673 for (
int ip = 0; ip < met->
np; ip++)
8674 met->
pl[ix][iy][ip] =
8675 (
float) (met->
hyam[ip] / 100. +
8676 met->
hybm[ip] * met->
ps[ix][iy]);
8684 ERRMSG(
"Mismatch in number of model levels!");
8687#pragma omp parallel for default(shared) collapse(2)
8688 for (
int ix = 0; ix < met->
nx; ix++)
8689 for (
int iy = 0; iy < met->
ny; iy++)
8690 for (
int ip = 0; ip < met->
np; ip++) {
8692 met->
hyam[ip] / 100. + met->
hybm[ip] * met->
ps[ix][iy];
8694 met->
hyam[ip + 1] / 100. + met->
hybm[ip + 1] * met->
ps[ix][iy];
8695 met->
pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
8700 for (
int ix = 0; ix < met->
nx; ix++)
8701 for (
int iy = 0; iy < met->
ny; iy++)
8702 for (
int ip = 1; ip < met->
np; ip++)
8703 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
8704 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
8705 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
8706 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip]))
8707 ERRMSG(
"Pressure profiles are not monotonic!");
8728 for (
int ip = 0; ip < met->
np; ip++)
8729 met->
p[ip] = ctl->
met_p[ip];
8733 for (
int ip = 1; ip < met->
np; ip++)
8734 if (met->
p[ip - 1] < met->
p[ip])
8735 ERRMSG(
"Pressure levels must be descending!");
8742 const char *varname,
8743 const char *varname2,
8744 const char *varname3,
8745 const char *varname4,
8746 const char *varname5,
8747 const char *varname6,
8757 float offset, scalfac;
8762 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
8763 sprintf(varsel,
"%s", varname);
8764 else if (varname2 != NULL
8765 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
8766 sprintf(varsel,
"%s", varname2);
8767 else if (varname3 != NULL
8768 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
8769 sprintf(varsel,
"%s", varname3);
8770 else if (varname4 != NULL
8771 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
8772 sprintf(varsel,
"%s", varname4);
8773 else if (varname5 != NULL
8774 && nc_inq_varid(ncid, varname5, &varid) == NC_NOERR)
8775 sprintf(varsel,
"%s", varname5);
8776 else if (varname6 != NULL
8777 && nc_inq_varid(ncid, varname6, &varid) == NC_NOERR)
8778 sprintf(varsel,
"%s", varname6);
8784 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
8785 && nc_get_att_float(ncid, varid,
"scale_factor",
8786 &scalfac) == NC_NOERR) {
8794 short fillval, missval;
8795 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8797 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8801 LOG(2,
"Read 2-D variable: %s"
8802 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
8803 varsel, fillval, missval, scalfac, offset);
8806 NC(nc_get_var_short(ncid, varid, help));
8810 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
8814#pragma omp parallel for default(shared)
8815 for (
int ix = 0; ix < met->
nx; ix++)
8816 for (
int iy = 0; iy < met->
ny; iy++) {
8819 const short aux = help[
ARRAY_2D(iy, ix, met->
nx)];
8820 if ((fillval == 0 || aux != fillval)
8821 && (missval == 0 || aux != missval)
8822 && fabsf(aux * scalfac + offset) < 1e14f)
8823 dest[ix][iy] += scl * (aux * scalfac + offset);
8834 else if (!ctl->
dd) {
8842 float fillval, missval;
8843 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8845 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8849 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
8850 varsel, fillval, missval);
8853 NC(nc_get_var_float(ncid, varid, help));
8860#pragma omp parallel for default(shared)
8861 for (
int ix = 0; ix < met->
nx; ix++)
8862 for (
int iy = 0; iy < met->
ny; iy++) {
8865 const float aux = help[
ARRAY_2D(iy, ix, met->
nx)];
8866 if ((fillval == 0 || aux != fillval)
8867 && (missval == 0 || aux != missval)
8868 && fabsf(aux) < 1e14f)
8869 dest[ix][iy] += scl * aux;
8879#pragma omp parallel for default(shared)
8880 for (
int iy = 0; iy < met->
ny; iy++)
8881 for (
int ix = 0; ix < met->
nx; ix++) {
8884 const float aux = help[
ARRAY_2D(ix, iy, met->
ny)];
8885 if ((fillval == 0 || aux != fillval)
8886 && (missval == 0 || aux != missval)
8887 && fabsf(aux) < 1e14f)
8888 dest[ix][iy] += scl * aux;
8903 float fillval, missval;
8904 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8906 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8910 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
8911 varsel, fillval, missval);
8915 size_t help_subdomain_start[3];
8916 size_t help_subdomain_count[3];
8918 help_subdomain_start[0] = 0;
8922 help_subdomain_count[0] = 1;
8931 NC(nc_get_vara_float
8932 (ncid, varid, help_subdomain_start, help_subdomain_count, help));
8935 size_t help_halo_bnd_start[3];
8936 size_t help_halo_bnd_count[3];
8938 help_halo_bnd_start[0] = 0;
8942 help_halo_bnd_count[0] = 1;
8947 ALLOC(help_halo,
float,
8948 help_halo_bnd_count[1] * help_halo_bnd_count[2]);
8949 NC(nc_get_vara_float
8950 (ncid, varid, help_halo_bnd_start, help_halo_bnd_count, help_halo));
8955#pragma omp parallel for default(shared) num_threads(12)
8956 for (
int ix = 0; ix < (int) help_subdomain_count[2]; ix++)
8957 for (
int iy = 0; iy < (int) help_subdomain_count[1]; iy++) {
8961 help[
ARRAY_2D(iy, ix, (
int) help_subdomain_count[2])];
8962 if ((fillval == 0 || aux != fillval)
8963 && (missval == 0 || aux != missval)
8964 && fabsf(aux) < 1e14f) {
8971#pragma omp parallel for default(shared) num_threads(12)
8972 for (
int ix = 0; ix < (int) help_halo_bnd_count[2]; ix++)
8973 for (
int iy = 0; iy < (int) help_halo_bnd_count[1]; iy++) {
8977 help_halo[
ARRAY_2D(iy, ix, (
int) help_halo_bnd_count[2])];
8978 if ((fillval == 0 || aux != fillval)
8979 && (missval == 0 || aux != missval)
8980 && fabsf(aux) < 1e14f)
8988 ERRMSG(
"Domain decomposition with data convection incompatible!");
9004 const char *varname,
9005 const char *varname2,
9006 const char *varname3,
9007 const char *varname4,
9018 float offset, scalfac;
9023 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
9024 sprintf(varsel,
"%s", varname);
9025 else if (varname2 != NULL
9026 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
9027 sprintf(varsel,
"%s", varname2);
9028 else if (varname3 != NULL
9029 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
9030 sprintf(varsel,
"%s", varname3);
9031 else if (varname4 != NULL
9032 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
9033 sprintf(varsel,
"%s", varname4);
9038 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
9039 && nc_get_att_float(ncid, varid,
"scale_factor",
9040 &scalfac) == NC_NOERR) {
9048 short fillval, missval;
9049 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9051 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9055 LOG(2,
"Read 3-D variable: %s "
9056 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
9057 varsel, fillval, missval, scalfac, offset);
9060 NC(nc_get_var_short(ncid, varid, help));
9064 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
9068#pragma omp parallel for default(shared)
9069 for (
int ix = 0; ix < met->
nx; ix++)
9070 for (
int iy = 0; iy < met->
ny; iy++)
9071 for (
int ip = 0; ip < met->
np; ip++) {
9072 const short aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
9073 if ((fillval == 0 || aux != fillval)
9074 && (missval == 0 || aux != missval)
9075 && fabsf(aux * scalfac + offset) < 1e14f)
9076 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
9078 dest[ix][iy][ip] = NAN;
9087 else if (!ctl->
dd) {
9095 float fillval, missval;
9096 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9098 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9102 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
9103 varsel, fillval, missval);
9106 NC(nc_get_var_float(ncid, varid, help));
9113#pragma omp parallel for default(shared)
9114 for (
int ix = 0; ix < met->
nx; ix++)
9115 for (
int iy = 0; iy < met->
ny; iy++)
9116 for (
int ip = 0; ip < met->
np; ip++) {
9117 const float aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
9118 if ((fillval == 0 || aux != fillval)
9119 && (missval == 0 || aux != missval)
9120 && fabsf(aux) < 1e14f)
9121 dest[ix][iy][ip] = scl * aux;
9123 dest[ix][iy][ip] = NAN;
9131#pragma omp parallel for default(shared)
9132 for (
int ip = 0; ip < met->
np; ip++)
9133 for (
int iy = 0; iy < met->
ny; iy++)
9134 for (
int ix = 0; ix < met->
nx; ix++) {
9135 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9136 if ((fillval == 0 || aux != fillval)
9137 && (missval == 0 || aux != missval)
9138 && fabsf(aux) < 1e14f)
9139 dest[ix][iy][ip] = scl * aux;
9141 dest[ix][iy][ip] = NAN;
9154 float fillval, missval;
9155 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9157 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9161 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
9162 varsel, fillval, missval);
9164 SELECT_TIMER(
"read_met_nc_3d_CP1",
"INPUT", NVTX_READ);
9174 SELECT_TIMER(
"read_met_nc_3d_CP2",
"INPUT", NVTX_READ);
9177 NC(nc_get_vara_float
9182 ALLOC(help_halo,
float,
9186 SELECT_TIMER(
"read_met_nc_3d_CP3",
"INPUT", NVTX_READ);
9189 NC(nc_get_vara_float(ncid,
9193 SELECT_TIMER(
"read_met_nc_3d_CP4",
"INPUT", NVTX_READ);
9198#pragma omp parallel for default(shared) num_threads(12)
9201 for (
int ip = 0; ip < met->
np; ip++) {
9205 if ((fillval == 0 || aux != fillval)
9206 && (missval == 0 || aux != missval)
9207 && fabsf(aux) < 1e14f)
9213#pragma omp parallel for default(shared) num_threads(12)
9216 for (
int ip = 0; ip < met->
np; ip++) {
9220 if ((fillval == 0 || aux != fillval)
9221 && (missval == 0 || aux != missval)
9222 && fabsf(aux) < 1e14f)
9231#pragma omp parallel for default(shared) num_threads(12)
9232 for (
int ip = 0; ip < met->
np; ip++)
9235 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9236 if ((fillval == 0 || aux != fillval)
9237 && (missval == 0 || aux != missval)
9238 && fabsf(aux) < 1e14f)
9244#pragma omp parallel for default(shared) num_threads(12)
9245 for (
int ip = 0; ip < met->
np; ip++)
9248 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9249 if ((fillval == 0 || aux != fillval)
9250 && (missval == 0 || aux != missval)
9251 && fabsf(aux) < 1e14f)
9271 const char *filename,
9276 size_t filename_len = strlen(filename) + 1;
9277 char sf_filename[filename_len];
9278 char ml_filename[filename_len];
9279 strcpy(sf_filename, filename);
9280 strcpy(ml_filename, filename);
9285 FILE *ml_file = fopen(ml_filename,
"rb");
9286 FILE *sf_file = fopen(sf_filename,
"rb");
9287 if (ml_file == NULL || sf_file == NULL) {
9288 if (ml_file != NULL) {
9290 WARN(
"Cannot open file: %s", sf_filename);
9292 if (sf_file != NULL) {
9294 WARN(
"Cannot open file: %s", ml_filename);
9300 int ml_num_messages = 0, err = 0;
9301 ECC(codes_count_in_file(0, ml_file, &ml_num_messages));
9304 (size_t) ml_num_messages);
9305 for (
int i = 0; i < ml_num_messages; i++) {
9307 if ((h = codes_grib_handle_new_from_file(0, ml_file, &err)) != NULL)
9312 int sf_num_messages = 0;
9313 ECC(codes_count_in_file(0, sf_file, &sf_num_messages));
9316 (size_t) sf_num_messages);
9317 for (
int i = 0; i < sf_num_messages; i++) {
9319 if ((h = codes_grib_handle_new_from_file(0, sf_file, &err)) != NULL)
9332 for (
int i = 0; i < sf_num_messages; i++)
9333 codes_handle_delete(sf_handles[i]);
9337 size_t value_count = 0;
9338 ECC(codes_get_size(ml_handles[0],
"pv", &value_count));
9339 if (value_count % 2 != 0)
9340 ERRMSG(
"Unexpected pv array length!");
9341 size_t nlevels = value_count / 2 - 1;
9343 ALLOC(values,
double,
9345 ECC(codes_get_double_array(ml_handles[0],
"pv", values, &value_count));
9346 double *a_vals = values;
9347 double *b_vals = values + nlevels;
9348 if (met->
npl > (
int) nlevels)
9349 ERRMSG(
"met->npl exceeds number of pressure levels in GRIB!");
9350 for (
int nx = 0; nx < met->
nx; nx++)
9351 for (
int ny = 0; ny < met->
ny; ny++)
9352 for (
int level = 0; level <= met->
npl; level++) {
9353 const float p1 = (float) (a_vals[level] * 0.01f +
9354 met->
ps[nx][ny] * b_vals[level]);
9355 const float p2 = (float) (a_vals[level + 1] * 0.01f +
9356 met->
ps[nx][ny] * b_vals[level + 1]);
9357 met->
pl[nx][ny][level] = 0.5f * (p1 + p2);
9363 for (
int i = 0; i < ml_num_messages; i++)
9364 codes_handle_delete(ml_handles[i]);
9381 SELECT_TIMER(
"READ_MET_GRIB_GRID",
"INPUT", NVTX_READ);
9382 LOG(2,
"Read meteo grid information...");
9385 char datestr[
LEN], timestr[
LEN];
9386 size_t s_date =
sizeof(datestr);
9387 ECC(codes_get_string(handles[0],
"dataDate", datestr, &s_date));
9388 size_t s_time =
sizeof(timestr);
9389 ECC(codes_get_string(handles[0],
"dataTime", timestr, &s_time));
9390 int year, month, day, hour;
9391 if (sscanf(datestr,
"%4d%2d%2d", &year, &month, &day) != 3)
9392 ERRMSG(
"Failed to parse dataDate: %s", datestr);
9393 if (sscanf(timestr,
"%2d", &hour) != 1)
9394 ERRMSG(
"Failed to parse dataTime: %s", timestr);
9396 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)", met->
time, year, month,
9400 long count_lat = 0, count_lon = 0;
9401 ECC(codes_get_long(handles[0],
"Nj", &count_lat));
9402 ECC(codes_get_long(handles[0],
"Ni", &count_lon));
9403 met->
ny = (int) count_lat;
9404 met->
nx = (int) count_lon;
9407 LOG(2,
"Number of longitudes: %d", met->
nx);
9408 if (met->
nx < 2 || met->
nx >
EX)
9409 ERRMSG(
"Number of longitudes out of range!");
9410 LOG(2,
"Number of latitudes: %d", met->
ny);
9411 if (met->
ny < 2 || met->
ny >
EY)
9412 ERRMSG(
"Number of latitudes out of range!");
9414 double first_lon, last_lon, first_lat, last_lat, inc_lon, inc_lat;
9415 ECC(codes_get_double
9416 (handles[0],
"longitudeOfFirstGridPointInDegrees", &first_lon));
9417 ECC(codes_get_double
9418 (handles[0],
"latitudeOfFirstGridPointInDegrees", &first_lat));
9419 ECC(codes_get_double
9420 (handles[0],
"longitudeOfLastGridPointInDegrees", &last_lon));
9421 ECC(codes_get_double
9422 (handles[0],
"latitudeOfLastGridPointInDegrees", &last_lat));
9423 ECC(codes_get_double(handles[0],
"iDirectionIncrementInDegrees", &inc_lon));
9424 ECC(codes_get_double(handles[0],
"jDirectionIncrementInDegrees", &inc_lat));
9426 long jscanpos, iscanneg;
9427 ECC(codes_get_long(handles[0],
"iScansNegatively", &iscanneg));
9428 ECC(codes_get_long(handles[0],
"jScansPositively", &jscanpos));
9433 for (
double i = first_lon; i <= last_lon + 1e-6; i += inc_lon) {
9434 met->
lon[counter] = i;
9437 for (
double i = first_lon; i > last_lon - 1e-6; i -= inc_lon) {
9438 met->
lon[counter] = i;
9444 for (
double i = first_lat; i > last_lat - 1e-6; i -= inc_lat) {
9445 met->
lat[counter] = i;
9448 for (
double i = first_lat; i <= last_lat + 1e-6; i += inc_lat) {
9449 met->
lat[counter] = i;
9454 LOG(2,
"Longitudes: %g, %g ... %g deg",
9456 LOG(2,
"Latitudes: %g, %g ... %g deg",
9461 for (
int i = 0; i < count_handles; i++) {
9463 ECC(codes_get_long(handles[i],
"level", &level));
9464 if (level > max_level)
9465 max_level = (int) level;
9467 met->
npl = max_level;
9470 LOG(2,
"Number of levels: %d", met->
npl);
9472 ERRMSG(
"Number of levels out of range!");
9481 const int num_messages,
9486 SELECT_TIMER(
"READ_MET_GRIB_LEVELS",
"INPUT", NVTX_READ);
9487 LOG(2,
"Read level data...");
9490 int t_flag = 0, u_flag = 0, v_flag = 0, w_flag = 0, o3_flag = 0, h2o_flag =
9491 0, lwc_flag = 0, rwc_flag = 0, iwc_flag = 0, swc_flag = 0, cc_flag = 0;
9494 for (
int i = 0; i < num_messages; i++) {
9496 size_t max_size =
LEN;
9497 char short_name[max_size];
9503 ECC(codes_get_long(handles[i],
"level", ¤t_level));
9507 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
9508 ECC(codes_get_size(handles[i],
"values", &value_count));
9509 ALLOC(values,
double,
9511 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
9519 ECC_READ_3D(
"w", current_level, met->
w, 0.01f, w_flag);
9537 if (t_flag != met->
npl)
9538 ERRMSG(
"Cannot read temperature!");
9539 if (u_flag != met->
npl)
9540 ERRMSG(
"Cannot read zonal wind!");
9541 if (v_flag != met->
npl)
9542 ERRMSG(
"Cannot read meridional wind!");
9543 if (w_flag != met->
npl)
9544 WARN(
"Cannot read vertical velocity!");
9545 if (h2o_flag != met->
npl)
9546 WARN(
"Cannot read specific humidity!");
9547 if (o3_flag != met->
npl)
9548 WARN(
"Cannot read ozone data!");
9549 if (lwc_flag != met->
npl)
9550 WARN(
"Cannot read cloud liquid water content!");
9551 if (rwc_flag != met->
npl)
9552 WARN(
"Cannot read cloud rain water content!");
9553 if (iwc_flag != met->
npl)
9554 WARN(
"Cannot read cloud ice water content!");
9555 if (swc_flag != met->
npl)
9556 WARN(
"Cannot read cloud snow water content!");
9557 if (cc_flag != met->
npl)
9558 WARN(
"Cannot read cloud cover!");
9561 for (
int ix = 0; ix < met->
nx; ix++)
9562 for (
int iy = 0; iy < met->
ny; iy++)
9563 for (
int ip = 1; ip < met->
np; ip++)
9564 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
9565 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
9566 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
9567 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip])) {
9568 LOG(1,
"%f %f %f %f", met->
pl[ix][iy][0], met->
pl[ix][iy][1],
9569 met->
pl[ix][iy][ip - 1], met->
pl[ix][iy][ip]);
9570 ERRMSG(
"Pressure profiles are not monotonic!");
9591 for (
int ip = 0; ip < met->
np; ip++)
9592 met->
p[ip] = ctl->
met_p[ip];
9596 for (
int ip = 1; ip < met->
np; ip++)
9597 if (met->
p[ip - 1] < met->
p[ip])
9598 ERRMSG(
"Pressure levels must be descending!");
9607 const int num_messages,
9612 SELECT_TIMER(
"READ_MET_GRIB_SURFACE",
"INPUT", NVTX_READ);
9613 LOG(2,
"Read surface data...");
9616 int sp_flag = 0, z_flag = 0, t_flag = 0, u_flag = 0, v_flag = 0, lsm_flag =
9617 0, sst_flag = 0, cape_flag = 0, cin_flag = 0, pbl_flag = 0;
9620 for (
int i = 0; i < num_messages; i++) {
9622 size_t max_size =
LEN, value_count;
9624 char short_name[max_size];
9627 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
9628 ECC(codes_get_size(handles[i],
"values", &value_count));
9629 double *values = (
double *) malloc(value_count *
sizeof(
double));
9630 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
9668 WARN(
"Cannot read surface pressure data!");
9670 WARN(
"Cannot read surface geopotential height!");
9672 WARN(
"Cannot read surface temperature!");
9674 WARN(
"Cannot read surface zonal wind!");
9676 WARN(
"Cannot read surface meridional wind!");
9678 WARN(
"Cannot read land-sea mask!");
9680 WARN(
"Cannot read sea surface temperature!");
9683 WARN(
"Cannot read CAPE!");
9685 WARN(
"Cannot read convective inhibition!");
9687 if (ctl->
met_pbl == 0 && pbl_flag == 0)
9688 WARN(
"Cannot read planetary boundary layer!");
9698 const char *varname) {
9700 double aux[
EP], p[
EP];
9704 LOG(2,
"Interpolate meteo data to pressure levels: %s", varname);
9707#pragma omp parallel for default(shared) private(aux,p) collapse(2)
9708 for (
int ix = 0; ix < met->
nx; ix++)
9709 for (
int iy = 0; iy < met->
ny; iy++) {
9712 for (
int ip = 0; ip < met->
np; ip++)
9713 p[ip] = met->
pl[ix][iy][ip];
9716 for (
int ip = 0; ip < ctl->
met_np; ip++) {
9717 double pt = ctl->
met_p[ip];
9718 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
9720 else if ((pt > p[met->
np - 1] && p[1] > p[0])
9721 || (pt < p[met->
np - 1] && p[1] < p[0]))
9722 pt = p[met->
np - 1];
9724 aux[ip] =
LIN(p[ip2], var[ix][iy][ip2],
9725 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
9729 for (
int ip = 0; ip < ctl->
met_np; ip++)
9730 var[ix][iy][ip] = (
float) aux[ip];
9745 SELECT_TIMER(
"READ_MET_MONOTONIZE",
"METPROC", NVTX_READ);
9746 LOG(2,
"Make zeta profiles monotone...");
9749#pragma omp parallel for default(shared) collapse(2)
9750 for (
int i = 0; i < met->
nx; i++)
9751 for (
int j = 0; j < met->
ny; j++) {
9754 while (k < met->npl) {
9755 if ((met->
zetal[i][j][k - 1] >= met->
zetal[i][j][k])) {
9761 while ((met->
zetal[i][j][k - 1] >=
9762 met->
zetal[i][j][k + l]) & (k + l < met->npl));
9767 (float) (met->
zetal[i][j][k + l] - met->
zetal[i][j][k - 1])
9770 for (
int m = k; m < k + l; m++) {
9771 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
9772 met->
zetal[i][j][m] = s * d + met->
zetal[i][j][k - 1];
9784#pragma omp parallel for default(shared) collapse(2)
9785 for (
int i = 0; i < met->
nx; i++)
9786 for (
int j = 0; j < met->
ny; j++) {
9789 while (k < met->npl) {
9790 if ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k])) {
9797 while ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k + l]) & (k + l <
9802 float s = (float) (met->
pl[i][j][k + l] - met->
pl[i][j][k - 1])
9805 for (
int m = k; m < k + l; m++) {
9806 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
9807 met->
pl[i][j][m] = s * d + met->
pl[i][j][k - 1];
9822 const char *filename,
9833 (filename, NC_NOWRITE | NC_SHARE, MPI_COMM_WORLD, MPI_INFO_NULL,
9837 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
9838 WARN(
"Cannot open file!");
9871 MPI_Comm_rank(MPI_COMM_WORLD, &dd->
rank);
9872 MPI_Comm_size(MPI_COMM_WORLD, &dd->
size);
9880 LOG(2,
"Number of longitudes: %d", help_nx_glob);
9884 LOG(2,
"Number of latitudes: %d", help_ny_glob);
9887 double *help_lon_glob;
9888 double *help_lat_glob;
9889 ALLOC(help_lon_glob,
double,
9891 ALLOC(help_lat_glob,
double,
9896 LOG(2,
"Longitudes: %g, %g ... %g deg",
9897 help_lon_glob[0], help_lon_glob[1], help_lon_glob[help_nx_glob - 1]);
9899 LOG(2,
"Latitudes: %g, %g ... %g deg",
9900 help_lat_glob[0], help_lat_glob[1], help_lat_glob[help_ny_glob - 1]);
9924 met->
nx = met->
nx + gap;
9925 WARN(
"Extended subdomains at the right to fit to full domain.");
9931 met->
ny = met->
ny + gap;
9932 WARN(
"Extended subdomains at the bottom to fit to full domain.");
9943 if (!left && !right) {
9960 if (!top && !bottom) {
9978 double lon_shift = 0;
9979 if (left || right) {
9997 lon_shift = (left ? -360 : 360);
10014 double lon_range = 360;
10025 double lat_range = help_lat_glob[help_ny_glob - 1] - help_lat_glob[0];
10052 if (lat_range < 0) {
10059 (
"lat_range > 0, but is expected to be negative, i.e. latitudes should range from 90 to -90")
10066 LOG(2,
"Total longitude range: %g deg", lon_range);
10067 LOG(2,
"Total latitude range: %g deg", lat_range);
10069 LOG(2,
"Define subdomain properties.");
10070 LOG(2,
"MPI information: Rank %d, Size %d", dd->
rank, dd->
size);
10071 LOG(2,
"Edge position: l=%d,r=%d,t=%d, b=%d", (
int) left, (
int) right,
10072 (
int) top, (
int) bottom);
10073 LOG(2,
"Sizes for limits: EX %d EY %d EP %d",
EX,
EY,
EP);
10074 LOG(2,
"Total size for subdomain meteo data: nx %d ny %d np %d", met->
nx,
10076 LOG(2,
"Hyperslab sizes for boundary halos: nx %d ny %d np %d",
10079 LOG(2,
"Hyperslab sizes for subdomain and inner halos: nx %d ny %d np %d",
10088 LOG(2,
" %d Subdomain longitudes: %g, %g ... %g deg (edges: %g to %g)",
10091 LOG(2,
" %d Subdomain latitudes: %g, %g ... %g deg (edges: %g to %g)",
10095 free(help_lon_glob);
10096 free(help_lat_glob);
10107 LOG(2,
"Calculate planetary boundary layer...");
10113#pragma omp parallel for default(shared) collapse(2)
10114 for (
int ix = 0; ix < met->
nx; ix++)
10115 for (
int iy = 0; iy < met->
ny; iy++) {
10118 const float z = met->
zs[ix][iy] + met->
pbl[ix][iy];
10121 (float) (
LIN(met->
z[ix][iy][ip], met->
p[ip],
10122 met->
z[ix][iy][ip + 1], met->
p[ip + 1], z));
10127 else if (ctl->
met_pbl == 2) {
10131 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
10134#pragma omp parallel for default(shared) collapse(2)
10135 for (
int ix = 0; ix < met->
nx; ix++)
10136 for (
int iy = 0; iy < met->
ny; iy++) {
10139 const double pbl_bot = met->
ps[ix][iy] * exp(-dz /
H0);
10143 for (ip = 1; ip < met->
np; ip++)
10144 if (met->
p[ip] < pbl_bot)
10148 const double h2os =
LIN(met->
p[ip - 1], met->
h2o[ix][iy][ip - 1],
10149 met->
p[ip], met->
h2o[ix][iy][ip], pbl_bot);
10150 const double tvs =
THETAVIRT(pbl_bot, met->
ts[ix][iy], h2os);
10153 double rib_old = 0;
10156 for (; ip < met->
np; ip++) {
10159 double vh2 =
SQR(met->
u[ix][iy][ip] - met->
us[ix][iy])
10160 +
SQR(met->
v[ix][iy][ip] - met->
vs[ix][iy]);
10161 vh2 =
MAX(vh2,
SQR(umin));
10165 G0 * 1e3 * (met->
z[ix][iy][ip] - met->
zs[ix][iy]) / tvs
10167 met->
h2o[ix][iy][ip]) - tvs) / vh2;
10170 if (rib >= rib_crit) {
10171 met->
pbl[ix][iy] = (float) (
LIN(rib_old, met->
p[ip - 1],
10172 rib, met->
p[ip], rib_crit));
10173 if (met->
pbl[ix][iy] > pbl_bot)
10174 met->
pbl[ix][iy] = (float) pbl_bot;
10189 const double dtheta = 2.0, zmin = 0.1;
10192#pragma omp parallel for default(shared) collapse(2)
10193 for (
int ix = 0; ix < met->
nx; ix++)
10194 for (
int iy = 0; iy < met->
ny; iy++) {
10197 const double theta0 =
THETA(met->
ps[ix][iy], met->
ts[ix][iy]);
10201 for (ip = met->
np - 2; ip > 0; ip--)
10202 if (met->
p[ip] >= 300.)
10203 if (met->
p[ip] > met->
ps[ix][iy]
10204 ||
THETA(met->
p[ip], met->
t[ix][iy][ip]) <= theta0 + dtheta)
10209 = (float) (
LIN(
THETA(met->
p[ip + 1], met->
t[ix][iy][ip + 1]),
10211 THETA(met->
p[ip], met->
t[ix][iy][ip]),
10212 met->
p[ip], theta0 + dtheta));
10215 double pbl_min = met->
ps[ix][iy] * exp(-zmin /
H0);
10216 if (met->
pbl[ix][iy] > pbl_min || met->
p[ip] > met->
ps[ix][iy])
10217 met->
pbl[ix][iy] = (float) pbl_min;
10222#pragma omp parallel for default(shared) collapse(2)
10223 for (
int ix = 0; ix < met->
nx; ix++)
10224 for (
int iy = 0; iy < met->
ny; iy++) {
10228 met->
pbl[ix][iy] =
MIN(met->
pbl[ix][iy], (
float) pbl_min);
10232 met->
pbl[ix][iy] =
MAX(met->
pbl[ix][iy], (
float) pbl_max);
10242 SELECT_TIMER(
"READ_MET_PERIODIC",
"METPROC", NVTX_READ);
10243 LOG(2,
"Apply periodic boundary conditions...");
10246 if (!(fabs(met->
lon[met->
nx - 1] - met->
lon[0]
10247 + met->
lon[1] - met->
lon[0] - 360) < 0.01))
10251 if ((++met->
nx) >=
EX)
10252 ERRMSG(
"Cannot create periodic boundary conditions!");
10255 met->
lon[met->
nx - 1] = met->
lon[met->
nx - 2] + met->
lon[1] - met->
lon[0];
10258#pragma omp parallel for default(shared)
10259 for (
int iy = 0; iy < met->
ny; iy++) {
10260 met->
ps[met->
nx - 1][iy] = met->
ps[0][iy];
10261 met->
zs[met->
nx - 1][iy] = met->
zs[0][iy];
10262 met->
ts[met->
nx - 1][iy] = met->
ts[0][iy];
10263 met->
us[met->
nx - 1][iy] = met->
us[0][iy];
10264 met->
vs[met->
nx - 1][iy] = met->
vs[0][iy];
10265 met->
ess[met->
nx - 1][iy] = met->
ess[0][iy];
10266 met->
nss[met->
nx - 1][iy] = met->
nss[0][iy];
10267 met->
shf[met->
nx - 1][iy] = met->
shf[0][iy];
10268 met->
lsm[met->
nx - 1][iy] = met->
lsm[0][iy];
10269 met->
sst[met->
nx - 1][iy] = met->
sst[0][iy];
10270 met->
pbl[met->
nx - 1][iy] = met->
pbl[0][iy];
10271 met->
cape[met->
nx - 1][iy] = met->
cape[0][iy];
10272 met->
cin[met->
nx - 1][iy] = met->
cin[0][iy];
10273 for (
int ip = 0; ip < met->
np; ip++) {
10274 met->
t[met->
nx - 1][iy][ip] = met->
t[0][iy][ip];
10275 met->
u[met->
nx - 1][iy][ip] = met->
u[0][iy][ip];
10276 met->
v[met->
nx - 1][iy][ip] = met->
v[0][iy][ip];
10277 met->
w[met->
nx - 1][iy][ip] = met->
w[0][iy][ip];
10278 met->
h2o[met->
nx - 1][iy][ip] = met->
h2o[0][iy][ip];
10279 met->
o3[met->
nx - 1][iy][ip] = met->
o3[0][iy][ip];
10280 met->
lwc[met->
nx - 1][iy][ip] = met->
lwc[0][iy][ip];
10281 met->
rwc[met->
nx - 1][iy][ip] = met->
rwc[0][iy][ip];
10282 met->
iwc[met->
nx - 1][iy][ip] = met->
iwc[0][iy][ip];
10283 met->
swc[met->
nx - 1][iy][ip] = met->
swc[0][iy][ip];
10284 met->
cc[met->
nx - 1][iy][ip] = met->
cc[0][iy][ip];
10286 for (
int ip = 0; ip < met->
npl; ip++) {
10287 met->
ul[met->
nx - 1][iy][ip] = met->
ul[0][iy][ip];
10288 met->
vl[met->
nx - 1][iy][ip] = met->
vl[0][iy][ip];
10289 met->
wl[met->
nx - 1][iy][ip] = met->
wl[0][iy][ip];
10290 met->
pl[met->
nx - 1][iy][ip] = met->
pl[0][iy][ip];
10291 met->
zetal[met->
nx - 1][iy][ip] = met->
zetal[0][iy][ip];
10303 SELECT_TIMER(
"READ_MET_POLAR_WINDS",
"METPROC", NVTX_READ);
10304 LOG(2,
"Apply fix for polar winds...");
10307 if (fabs(met->
lat[0]) < 89.999 || fabs(met->
lat[met->
ny - 1]) < 89.999)
10311 for (
int ihem = 0; ihem < 2; ihem++) {
10314 int i89 = 1, i90 = 0, sign = 1;
10319 if (met->
lat[i90] < 0)
10323 double clon[
EX], slon[
EX];
10324#pragma omp parallel for default(shared)
10325 for (
int ix = 0; ix < met->
nx; ix++) {
10326 clon[ix] = cos(sign *
DEG2RAD(met->
lon[ix]));
10327 slon[ix] = sin(sign *
DEG2RAD(met->
lon[ix]));
10331#pragma omp parallel for default(shared)
10332 for (
int ip = 0; ip < met->
np; ip++) {
10335 double vel89x = 0, vel89y = 0;
10336 for (
int ix = 0; ix < met->
nx; ix++) {
10338 (met->
u[ix][i89][ip] * clon[ix] -
10339 met->
v[ix][i89][ip] * slon[ix]) / met->
nx;
10341 (met->
u[ix][i89][ip] * slon[ix] +
10342 met->
v[ix][i89][ip] * clon[ix]) / met->
nx;
10346 for (
int ix = 0; ix < met->
nx; ix++) {
10347 met->
u[ix][i90][ip]
10348 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
10349 met->
v[ix][i90][ip]
10350 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
10365 LOG(2,
"Calculate potential vorticity...");
10368#pragma omp parallel for default(shared)
10369 for (
int ip = 0; ip < met->
np; ip++)
10370 pows[ip] = pow(1000. / met->
p[ip], 0.286);
10373#pragma omp parallel for default(shared)
10374 for (
int ix = 0; ix < met->
nx; ix++) {
10377 const int ix0 =
MAX(ix - 1, 0);
10378 const int ix1 =
MIN(ix + 1, met->
nx - 1);
10381 for (
int iy = 0; iy < met->
ny; iy++) {
10384 const int iy0 =
MAX(iy - 1, 0);
10385 const int iy1 =
MIN(iy + 1, met->
ny - 1);
10388 const double latr = 0.5 * (met->
lat[iy1] + met->
lat[iy0]);
10389 const double dx = 1000. *
DEG2DX(met->
lon[ix1] - met->
lon[ix0], latr);
10390 const double dy = 1000. *
DEG2DY(met->
lat[iy1] - met->
lat[iy0]);
10391 const double c0 = cos(
DEG2RAD(met->
lat[iy0]));
10392 const double c1 = cos(
DEG2RAD(met->
lat[iy1]));
10393 const double cr = cos(
DEG2RAD(latr));
10394 const double vort = 2 * 7.2921e-5 * sin(
DEG2RAD(latr));
10397 for (
int ip = 0; ip < met->
np; ip++) {
10401 = (met->
t[ix1][iy][ip] - met->
t[ix0][iy][ip]) * pows[ip] / dx;
10402 const double dvdx = (met->
v[ix1][iy][ip] - met->
v[ix0][iy][ip]) / dx;
10406 = (met->
t[ix][iy1][ip] - met->
t[ix][iy0][ip]) * pows[ip] / dy;
10408 = (met->
u[ix][iy1][ip] * c1 - met->
u[ix][iy0][ip] * c0) / dy;
10411 const int ip0 =
MAX(ip - 1, 0);
10412 const int ip1 =
MIN(ip + 1, met->
np - 1);
10415 double dtdp, dudp, dvdp;
10416 const double dp0 = 100. * (met->
p[ip] - met->
p[ip0]);
10417 const double dp1 = 100. * (met->
p[ip1] - met->
p[ip]);
10418 if (ip != ip0 && ip != ip1) {
10419 double denom = dp0 * dp1 * (dp0 + dp1);
10420 dtdp = (dp0 * dp0 * met->
t[ix][iy][ip1] * pows[ip1]
10421 - dp1 * dp1 * met->
t[ix][iy][ip0] * pows[ip0]
10422 + (dp1 * dp1 - dp0 * dp0) * met->
t[ix][iy][ip] * pows[ip])
10424 dudp = (dp0 * dp0 * met->
u[ix][iy][ip1]
10425 - dp1 * dp1 * met->
u[ix][iy][ip0]
10426 + (dp1 * dp1 - dp0 * dp0) * met->
u[ix][iy][ip])
10428 dvdp = (dp0 * dp0 * met->
v[ix][iy][ip1]
10429 - dp1 * dp1 * met->
v[ix][iy][ip0]
10430 + (dp1 * dp1 - dp0 * dp0) * met->
v[ix][iy][ip])
10433 const double denom = dp0 + dp1;
10435 (met->
t[ix][iy][ip1] * pows[ip1] -
10436 met->
t[ix][iy][ip0] * pows[ip0]) / denom;
10437 dudp = (met->
u[ix][iy][ip1] - met->
u[ix][iy][ip0]) / denom;
10438 dvdp = (met->
v[ix][iy][ip1] - met->
v[ix][iy][ip0]) / denom;
10442 met->
pv[ix][iy][ip] = (float)
10444 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
10450#pragma omp parallel for default(shared)
10451 for (
int ix = 0; ix < met->
nx; ix++)
10452 for (
int ip = 0; ip < met->
np; ip++) {
10454 = met->
pv[ix][1][ip]
10455 = met->
pv[ix][2][ip];
10456 met->
pv[ix][met->
ny - 1][ip]
10457 = met->
pv[ix][met->
ny - 2][ip]
10458 = met->
pv[ix][met->
ny - 3][ip];
10469 LOG(2,
"Calculate total column ozone...");
10472#pragma omp parallel for default(shared) collapse(2)
10473 for (
int ix = 0; ix < met->
nx; ix++)
10474 for (
int iy = 0; iy < met->
ny; iy++) {
10478 for (
int ip = 1; ip < met->
np; ip++)
10479 if (met->
p[ip - 1] <= met->
ps[ix][iy]) {
10481 0.5 * (met->
o3[ix][iy][ip - 1] + met->
o3[ix][iy][ip]);
10482 const double dp = met->
p[ip - 1] - met->
p[ip];
10483 cd += vmr *
MO3 /
MA * dp * 1e2 /
G0;
10487 met->
o3c[ix][iy] = (float) (cd / 2.1415e-5);
10505 SELECT_TIMER(
"READ_MET_SAMPLE",
"METPROC", NVTX_READ);
10506 LOG(2,
"Downsampling of meteo data...");
10512 help->
nx = met->
nx;
10513 help->
ny = met->
ny;
10514 help->
np = met->
np;
10515 memcpy(help->
lon, met->
lon,
sizeof(met->
lon));
10516 memcpy(help->
lat, met->
lat,
sizeof(met->
lat));
10517 memcpy(help->
p, met->
p,
sizeof(met->
p));
10520 for (
int ix = 0; ix < met->
nx; ix += ctl->
met_dx) {
10521 for (
int iy = 0; iy < met->
ny; iy += ctl->
met_dy) {
10522 for (
int ip = 0; ip < met->
np; ip += ctl->
met_dp) {
10523 help->
ps[ix][iy] = 0;
10524 help->
zs[ix][iy] = 0;
10525 help->
ts[ix][iy] = 0;
10526 help->
us[ix][iy] = 0;
10527 help->
vs[ix][iy] = 0;
10528 help->
ess[ix][iy] = 0;
10529 help->
nss[ix][iy] = 0;
10530 help->
shf[ix][iy] = 0;
10531 help->
lsm[ix][iy] = 0;
10532 help->
sst[ix][iy] = 0;
10533 help->
pbl[ix][iy] = 0;
10534 help->
cape[ix][iy] = 0;
10535 help->
cin[ix][iy] = 0;
10536 help->
t[ix][iy][ip] = 0;
10537 help->
u[ix][iy][ip] = 0;
10538 help->
v[ix][iy][ip] = 0;
10539 help->
w[ix][iy][ip] = 0;
10540 help->
h2o[ix][iy][ip] = 0;
10541 help->
o3[ix][iy][ip] = 0;
10542 help->
lwc[ix][iy][ip] = 0;
10543 help->
rwc[ix][iy][ip] = 0;
10544 help->
iwc[ix][iy][ip] = 0;
10545 help->
swc[ix][iy][ip] = 0;
10546 help->
cc[ix][iy][ip] = 0;
10548 for (
int ix2 = ix - ctl->
met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
10553 else if (ix3 >= met->
nx)
10556 for (
int iy2 =
MAX(iy - ctl->
met_sy + 1, 0);
10557 iy2 <=
MIN(iy + ctl->
met_sy - 1, met->
ny - 1); iy2++)
10558 for (
int ip2 =
MAX(ip - ctl->
met_sp + 1, 0);
10559 ip2 <=
MIN(ip + ctl->
met_sp - 1, met->
np - 1); ip2++) {
10561 (1.0f - (float) abs(ix - ix2) / (float) ctl->
met_sx)
10562 * (1.0f - (float) abs(iy - iy2) / (float) ctl->
met_sy)
10563 * (1.0f - (float) abs(ip - ip2) / (float) ctl->
met_sp);
10564 help->
ps[ix][iy] += w * met->
ps[ix3][iy2];
10565 help->
zs[ix][iy] += w * met->
zs[ix3][iy2];
10566 help->
ts[ix][iy] += w * met->
ts[ix3][iy2];
10567 help->
us[ix][iy] += w * met->
us[ix3][iy2];
10568 help->
vs[ix][iy] += w * met->
vs[ix3][iy2];
10569 help->
ess[ix][iy] += w * met->
ess[ix3][iy2];
10570 help->
nss[ix][iy] += w * met->
nss[ix3][iy2];
10571 help->
shf[ix][iy] += w * met->
shf[ix3][iy2];
10572 help->
lsm[ix][iy] += w * met->
lsm[ix3][iy2];
10573 help->
sst[ix][iy] += w * met->
sst[ix3][iy2];
10574 help->
pbl[ix][iy] += w * met->
pbl[ix3][iy2];
10575 help->
cape[ix][iy] += w * met->
cape[ix3][iy2];
10576 help->
cin[ix][iy] += w * met->
cin[ix3][iy2];
10577 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip2];
10578 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip2];
10579 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip2];
10580 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip2];
10581 help->
h2o[ix][iy][ip] += w * met->
h2o[ix3][iy2][ip2];
10582 help->
o3[ix][iy][ip] += w * met->
o3[ix3][iy2][ip2];
10583 help->
lwc[ix][iy][ip] += w * met->
lwc[ix3][iy2][ip2];
10584 help->
rwc[ix][iy][ip] += w * met->
rwc[ix3][iy2][ip2];
10585 help->
iwc[ix][iy][ip] += w * met->
iwc[ix3][iy2][ip2];
10586 help->
swc[ix][iy][ip] += w * met->
swc[ix3][iy2][ip2];
10587 help->
cc[ix][iy][ip] += w * met->
cc[ix3][iy2][ip2];
10591 help->
ps[ix][iy] /= wsum;
10592 help->
zs[ix][iy] /= wsum;
10593 help->
ts[ix][iy] /= wsum;
10594 help->
us[ix][iy] /= wsum;
10595 help->
vs[ix][iy] /= wsum;
10596 help->
ess[ix][iy] /= wsum;
10597 help->
nss[ix][iy] /= wsum;
10598 help->
shf[ix][iy] /= wsum;
10599 help->
lsm[ix][iy] /= wsum;
10600 help->
sst[ix][iy] /= wsum;
10601 help->
pbl[ix][iy] /= wsum;
10602 help->
cape[ix][iy] /= wsum;
10603 help->
cin[ix][iy] /= wsum;
10604 help->
t[ix][iy][ip] /= wsum;
10605 help->
u[ix][iy][ip] /= wsum;
10606 help->
v[ix][iy][ip] /= wsum;
10607 help->
w[ix][iy][ip] /= wsum;
10608 help->
h2o[ix][iy][ip] /= wsum;
10609 help->
o3[ix][iy][ip] /= wsum;
10610 help->
lwc[ix][iy][ip] /= wsum;
10611 help->
rwc[ix][iy][ip] /= wsum;
10612 help->
iwc[ix][iy][ip] /= wsum;
10613 help->
swc[ix][iy][ip] /= wsum;
10614 help->
cc[ix][iy][ip] /= wsum;
10621 for (
int ix = 0; ix < help->
nx; ix += ctl->
met_dx) {
10622 met->
lon[met->
nx] = help->
lon[ix];
10624 for (
int iy = 0; iy < help->
ny; iy += ctl->
met_dy) {
10625 met->
lat[met->
ny] = help->
lat[iy];
10626 met->
ps[met->
nx][met->
ny] = help->
ps[ix][iy];
10627 met->
zs[met->
nx][met->
ny] = help->
zs[ix][iy];
10628 met->
ts[met->
nx][met->
ny] = help->
ts[ix][iy];
10629 met->
us[met->
nx][met->
ny] = help->
us[ix][iy];
10630 met->
vs[met->
nx][met->
ny] = help->
vs[ix][iy];
10631 met->
ess[met->
nx][met->
ny] = help->
ess[ix][iy];
10632 met->
nss[met->
nx][met->
ny] = help->
nss[ix][iy];
10633 met->
shf[met->
nx][met->
ny] = help->
shf[ix][iy];
10634 met->
lsm[met->
nx][met->
ny] = help->
lsm[ix][iy];
10635 met->
sst[met->
nx][met->
ny] = help->
sst[ix][iy];
10636 met->
pbl[met->
nx][met->
ny] = help->
pbl[ix][iy];
10638 met->
cin[met->
nx][met->
ny] = help->
cin[ix][iy];
10640 for (
int ip = 0; ip < help->
np; ip += ctl->
met_dp) {
10641 met->
p[met->
np] = help->
p[ip];
10642 met->
t[met->
nx][met->
ny][met->
np] = help->
t[ix][iy][ip];
10643 met->
u[met->
nx][met->
ny][met->
np] = help->
u[ix][iy][ip];
10644 met->
v[met->
nx][met->
ny][met->
np] = help->
v[ix][iy][ip];
10645 met->
w[met->
nx][met->
ny][met->
np] = help->
w[ix][iy][ip];
10646 met->
h2o[met->
nx][met->
ny][met->
np] = help->
h2o[ix][iy][ip];
10647 met->
o3[met->
nx][met->
ny][met->
np] = help->
o3[ix][iy][ip];
10648 met->
lwc[met->
nx][met->
ny][met->
np] = help->
lwc[ix][iy][ip];
10649 met->
rwc[met->
nx][met->
ny][met->
np] = help->
rwc[ix][iy][ip];
10650 met->
iwc[met->
nx][met->
ny][met->
np] = help->
iwc[ix][iy][ip];
10651 met->
swc[met->
nx][met->
ny][met->
np] = help->
swc[ix][iy][ip];
10652 met->
cc[met->
nx][met->
ny][met->
np] = help->
cc[ix][iy][ip];
10671 double p2[200], pv[
EP], pv2[200], t[
EP], t2[200], th[
EP],
10672 th2[200], z[
EP], z2[200];
10676 LOG(2,
"Calculate tropopause...");
10679#pragma omp parallel for default(shared)
10680 for (
int iz = 0; iz < met->
np; iz++)
10681 z[iz] =
Z(met->
p[iz]);
10682#pragma omp parallel for default(shared)
10683 for (
int iz = 0; iz <= 190; iz++) {
10684 z2[iz] = 4.5 + 0.1 * iz;
10685 p2[iz] =
P(z2[iz]);
10690#pragma omp parallel for default(shared) collapse(2)
10691 for (
int ix = 0; ix < met->
nx; ix++)
10692 for (
int iy = 0; iy < met->
ny; iy++)
10693 met->
pt[ix][iy] = NAN;
10697#pragma omp parallel for default(shared) collapse(2)
10698 for (
int ix = 0; ix < met->
nx; ix++)
10699 for (
int iy = 0; iy < met->
ny; iy++)
10707#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10708 for (
int ix = 0; ix < met->
nx; ix++)
10709 for (
int iy = 0; iy < met->
ny; iy++) {
10712 for (
int iz = 0; iz < met->
np; iz++)
10713 t[iz] = met->
t[ix][iy][iz];
10717 int iz = (int) gsl_stats_min_index(t2, 1, 171);
10718 if (iz > 0 && iz < 170)
10719 met->
pt[ix][iy] = (float) p2[iz];
10721 met->
pt[ix][iy] = NAN;
10729#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10730 for (
int ix = 0; ix < met->
nx; ix++)
10731 for (
int iy = 0; iy < met->
ny; iy++) {
10735 for (iz = 0; iz < met->
np; iz++)
10736 t[iz] = met->
t[ix][iy][iz];
10740 met->
pt[ix][iy] = NAN;
10741 for (iz = 0; iz <= 170; iz++) {
10743 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10744 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10749 if (iz > 0 && iz < 170)
10750 met->
pt[ix][iy] = (float) p2[iz];
10757 met->
pt[ix][iy] = NAN;
10758 for (; iz <= 170; iz++) {
10760 for (
int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
10761 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
10768 for (; iz <= 170; iz++) {
10770 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10771 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10776 if (iz > 0 && iz < 170)
10777 met->
pt[ix][iy] = (float) p2[iz];
10789#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
10790 for (
int ix = 0; ix < met->
nx; ix++)
10791 for (
int iy = 0; iy < met->
ny; iy++) {
10794 for (
int iz = 0; iz < met->
np; iz++)
10795 pv[iz] = met->
pv[ix][iy][iz];
10799 for (
int iz = 0; iz < met->
np; iz++)
10800 th[iz] =
THETA(met->
p[iz], met->
t[ix][iy][iz]);
10804 met->
pt[ix][iy] = NAN;
10805 for (
int iz = 0; iz <= 170; iz++)
10808 if (iz > 0 && iz < 170)
10809 met->
pt[ix][iy] = (float) p2[iz];
10816 ERRMSG(
"Cannot calculate tropopause!");
10819#pragma omp parallel for default(shared) collapse(2)
10820 for (
int ix = 0; ix < met->
nx; ix++)
10821 for (
int iy = 0; iy < met->
ny; iy++) {
10822 double h2ot, tt, zt;
10825 met->
lat[iy], &tt, ci, cw, 1);
10827 met->
lat[iy], &zt, ci, cw, 0);
10829 met->
lat[iy], &h2ot, ci, cw, 0);
10830 met->
tt[ix][iy] = (float) tt;
10831 met->
zt[ix][iy] = (float) zt;
10832 met->
h2ot[ix][iy] = (float) h2ot;
10839 const char *filename,
10849 LOG(1,
"Read observation data: %s", filename);
10853 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
10855 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
10857 ERRMSG(
"Set OBS_TYPE to 0 or 1!");
10860 for (
int i = 1; i < *nobs; i++)
10861 if (rt[i] < rt[i - 1])
10862 ERRMSG(
"Time must be ascending!");
10867 LOG(2,
"Number of observations: %d", *nobs);
10868 gsl_stats_minmax(&mini, &maxi, rt, 1, (
size_t) n);
10869 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
10870 gsl_stats_minmax(&mini, &maxi, rz, 1, (
size_t) n);
10871 LOG(2,
"Altitude range: %g ... %g km", mini, maxi);
10872 gsl_stats_minmax(&mini, &maxi, rlon, 1, (
size_t) n);
10873 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
10874 gsl_stats_minmax(&mini, &maxi, rlat, 1, (
size_t) n);
10875 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
10876 gsl_stats_minmax(&mini, &maxi, robs, 1, (
size_t) n);
10877 LOG(2,
"Observation range: %g ... %g", mini, maxi);
10883 const char *filename,
10893 if (!(in = fopen(filename,
"r")))
10894 ERRMSG(
"Cannot open file!");
10898 while (fgets(line,
LEN, in))
10899 if (sscanf(line,
"%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
10900 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
10901 if ((++(*nobs)) >=
NOBS)
10902 ERRMSG(
"Too many observations!");
10911 const char *filename,
10922 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
10923 ERRMSG(
"Cannot open file!");
10934 NC(nc_close(ncid));
10940 const char *filename,
10943 const char *varname,
10945 const char *defvalue,
10950 char fullname1[
LEN], fullname2[
LEN], rval[
LEN];
10952 int contain = 0, i;
10955 if (filename[strlen(filename) - 1] !=
'-')
10956 if (!(in = fopen(filename,
"r")))
10957 ERRMSG(
"Cannot open file!");
10961 sprintf(fullname1,
"%s[%d]", varname, arridx);
10962 sprintf(fullname2,
"%s[*]", varname);
10964 sprintf(fullname1,
"%s", varname);
10965 sprintf(fullname2,
"%s", varname);
10970 char dummy[
LEN], line[
LEN], rvarname[
LEN];
10971 while (fgets(line,
LEN, in)) {
10972 if (sscanf(line,
"%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
10973 if (strcasecmp(rvarname, fullname1) == 0 ||
10974 strcasecmp(rvarname, fullname2) == 0) {
10980 for (i = 1; i < argc - 1; i++)
10981 if (strcasecmp(argv[i], fullname1) == 0 ||
10982 strcasecmp(argv[i], fullname2) == 0) {
10983 sprintf(rval,
"%s", argv[i + 1]);
10994 if (strlen(defvalue) > 0)
10995 sprintf(rval,
"%s", defvalue);
10997 ERRMSG(
"Missing variable %s!\n", fullname1);
11001 LOG(1,
"%s = %s", fullname1, rval);
11005 sprintf(value,
"%s", rval);
11015 const double rhop) {
11018 const double rp_help = rp * 1e-6;
11021 const double rho =
RHO(p, T);
11024 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
11027 const double v = sqrt(8. *
KB * T / (M_PI * 4.8096e-26));
11030 const double lambda = 2. * eta / (rho * v);
11033 const double K = lambda / rp_help;
11036 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
11039 return 2. *
SQR(rp_help) * (rhop - rho) *
G0 / (9. * eta) * G;
11051 const int method) {
11057 gsl_interp_accel *acc = gsl_interp_accel_alloc();
11058 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (
size_t) n);
11061 gsl_spline_init(s, x, y, (
size_t) n);
11062 for (
int i = 0; i < n2; i++)
11065 else if (x2[i] >= x[n - 1])
11068 y2[i] = gsl_spline_eval(s, x2[i], acc);
11071 gsl_spline_free(s);
11072 gsl_interp_accel_free(acc);
11077 for (
int i = 0; i < n2; i++)
11080 else if (x2[i] >= x[n - 1])
11084 y2[i] =
LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
11098 float mean = 0, var = 0;
11100 for (
int i = 0; i < n; ++i) {
11102 var +=
SQR(data[i]);
11105 var = var / (float) n -
SQR(mean / (
float) n);
11107 return (var > 0 ? sqrtf(var) : 0);
11119 const double remain,
11131 t1.tm_year = year - 1900;
11132 t1.tm_mon = mon - 1;
11138 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
11146 const int output) {
11153 static int iname = -1, igroup = -1, nname, ngroup, ct_name[
NTIMER];
11156 t1 = omp_get_wtime();
11161 rt_name[iname] += dt;
11162 rt_min[iname] = (ct_name[iname] <= 0 ? dt :
MIN(rt_min[iname], dt));
11163 rt_max[iname] = (ct_name[iname] <= 0 ? dt :
MAX(rt_max[iname], dt));
11167 rt_group[igroup] += t1 - t0;
11171 for (
int i = 0; i < nname; i++)
11172 LOG(1,
"TIMER_%s = %.3f s (min= %g s, mean= %g s,"
11173 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
11174 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
11175 for (
int i = 0; i < ngroup; i++)
11176 LOG(1,
"TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
11177 double total = 0.0;
11178 for (
int i = 0; i < nname; i++)
11179 total += rt_name[i];
11180 LOG(1,
"TIMER_TOTAL = %.3f s", total);
11184 for (iname = 0; iname < nname; iname++)
11185 if (strcasecmp(name, names[iname]) == 0)
11187 for (igroup = 0; igroup < ngroup; igroup++)
11188 if (strcasecmp(group, groups[igroup]) == 0)
11192 if (iname >= nname) {
11193 sprintf(names[iname],
"%s", name);
11194 if ((++nname) >=
NTIMER)
11195 ERRMSG(
"Too many timers!");
11199 if (igroup >= ngroup) {
11200 sprintf(groups[igroup],
"%s", group);
11201 if ((++ngroup) >=
NTIMER)
11202 ERRMSG(
"Too many groups!");
11212 const char *filename,
11213 const int offset) {
11220 int len = (int) strlen(filename);
11221 sprintf(tstr,
"%.4s", &filename[len - offset]);
11222 int year = atoi(tstr);
11223 sprintf(tstr,
"%.2s", &filename[len - offset + 5]);
11224 int mon = atoi(tstr);
11225 sprintf(tstr,
"%.2s", &filename[len - offset + 8]);
11226 int day = atoi(tstr);
11227 sprintf(tstr,
"%.2s", &filename[len - offset + 11]);
11228 int hour = atoi(tstr);
11229 sprintf(tstr,
"%.2s", &filename[len - offset + 14]);
11230 int min = atoi(tstr);
11233 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
11234 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
11235 ERRMSG(
"Cannot read time from filename!");
11238 time2jsec(year, mon, day, hour, min, 0, 0.0, &t);
11255 const double p1 = pt * 0.866877899;
11256 const double p0 = pt / 0.866877899;
11259 if (atm->
p[ip] > p0)
11261 else if (atm->
p[ip] < p1)
11264 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
11270 const char *filename,
11278 const double t0 = t - 0.5 * ctl->
dt_mod;
11279 const double t1 = t + 0.5 * ctl->
dt_mod;
11285 if (!(out = popen(
"gnuplot",
"w")))
11286 ERRMSG(
"Cannot create pipe to gnuplot!");
11289 fprintf(out,
"set out \"%s.png\"\n", filename);
11293 int year, mon, day, hour, min, sec;
11294 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11295 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
11296 year, mon, day, hour, min);
11301 ERRMSG(
"Cannot open file!");
11303 while (fgets(line,
LEN, in))
11304 fprintf(out,
"%s", line);
11311 if (!(out = fopen(filename,
"w")))
11312 ERRMSG(
"Cannot create file!");
11317 "# $1 = time [s]\n"
11318 "# $2 = altitude [km]\n"
11319 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
11320 for (
int iq = 0; iq < ctl->
nq; iq++)
11321 fprintf(out,
"# $%i = %s [%s]\n", iq + 5, ctl->
qnt_name[iq],
11323 fprintf(out,
"\n");
11326 for (
int ip = 0; ip < atm->
np; ip += ctl->
atm_stride) {
11333 fprintf(out,
"%.2f %g %g %g", atm->
time[ip],
Z(atm->
p[ip]),
11334 atm->
lon[ip], atm->
lat[ip]);
11335 for (
int iq = 0; iq < ctl->
nq; iq++) {
11340 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
11342 fprintf(out,
"\n");
11352 const char *filename,
11354 const atm_t *atm) {
11359 if (!(out = fopen(filename,
"w")))
11360 ERRMSG(
"Cannot create file!");
11384 for (
int iq = 0; iq < ctl->
nq; iq++)
11402 const char *filename,
11404 const atm_t *atm) {
11406 int tid, pid, ncid, varid;
11407 size_t start[2], count[2];
11410 NC(nc_create(filename, NC_NETCDF4, &ncid));
11413 NC(nc_def_dim(ncid,
"time", 1, &tid));
11414 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11417 int dim_ids[2] = { tid, pid };
11418 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11419 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11420 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
11422 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
11424 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
11427 for (
int iq = 0; iq < ctl->
nq; iq++)
11437 NC(nc_enddef(ncid));
11445 for (
int iq = 0; iq < ctl->
nq; iq++)
11449 NC(nc_close(ncid));
11455 const char *dirname,
11461 static size_t out_cnt = 0;
11463 double r, r_start, r_stop;
11464 int year, mon, day, hour, min, sec;
11465 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
11466 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
11467 char filename_out[2 *
LEN] =
"traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
11469 int ncid, varid, tid, pid, cid;
11477 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11479 &min_start, &sec_start, &r_start);
11481 &min_stop, &sec_stop, &r_stop);
11483 sprintf(filename_out,
11484 "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc", dirname,
11485 year_start % 100, mon_start, day_start, hour_start,
11486 year_stop % 100, mon_stop, day_stop, hour_stop);
11487 LOG(1,
"Write traj file: %s", filename_out);
11490 start[0] = out_cnt;
11493 count[1] = (size_t) atm->
np;
11496 if (out_cnt == 0) {
11499 NC(nc_create(filename_out, NC_NETCDF4, &ncid));
11502 NC(nc_def_dim(ncid,
"time", NC_UNLIMITED, &tid));
11503 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11504 NC(nc_def_dim(ncid,
"TMDT", 7, &cid));
11509 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11510 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11511 NC_DEF_VAR(
"LAT", NC_DOUBLE, 2, dim_ids,
"Latitude",
"deg",
11513 NC_DEF_VAR(
"LON", NC_DOUBLE, 2, dim_ids,
"Longitude",
"deg",
11515 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 2, dim_ids,
"Pressure",
"hPa",
11517 NC_DEF_VAR(
"ZETA", NC_DOUBLE, 2, dim_ids,
"Zeta",
"K",
11519 for (
int iq = 0; iq < ctl->
nq; iq++)
11529 NC(nc_enddef(ncid));
11530 NC(nc_close(ncid));
11537 NC(nc_open(filename_out, NC_WRITE, &ncid));
11549 for (
int iq = 0; iq < ctl->
nq; iq++)
11553 NC(nc_close(ncid));
11556 if ((year == year_stop) && (mon == mon_stop)
11557 && (day == day_stop) && (hour == hour_stop)) {
11560 char filename_init[2 *
LEN] =
"./init_fix_YYYYMMDDHH.nc";
11561 sprintf(filename_init,
"%s/init_fix_%02d%02d%02d%02d.nc",
11562 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
11563 LOG(1,
"Write init file: %s", filename_init);
11566 NC(nc_create(filename_init, NC_NETCDF4, &ncid));
11569 NC(nc_def_dim(ncid,
"time", 1, &tid));
11570 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11575 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11576 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11577 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
11579 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
11581 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
11584 for (
int iq = 0; iq < ctl->
nq; iq++)
11594 NC(nc_enddef(ncid));
11602 for (
int iq = 0; iq < ctl->
nq; iq++)
11606 NC(nc_close(ncid));
11613 const char *filename,
11615 const atm_t *atm) {
11617 int ncid, obsid, varid;
11619 size_t start[2], count[2];
11622 NC(nc_create(filename, NC_NETCDF4, &ncid));
11625 NC(nc_def_dim(ncid,
"obs", (
size_t) atm->
np, &obsid));
11628 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &obsid,
"time",
11629 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11630 NC_DEF_VAR(
"press", NC_DOUBLE, 1, &obsid,
"pressure",
"hPa",
11632 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &obsid,
"longitude",
"degrees_east",
11634 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &obsid,
"latitude",
"degrees_north",
11636 for (
int iq = 0; iq < ctl->
nq; iq++)
11645 NC(nc_enddef(ncid));
11652 for (
int iq = 0; iq < ctl->
nq; iq++)
11656 NC(nc_close(ncid));
11662 const char *filename,
11669 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
11672 static int *obscount, nobs, nk;
11676 const int ensemble = (ctl->
nens > 0);
11682 if (ctl->
qnt_m < 0)
11683 ERRMSG(
"Need quantity mass!");
11686 ERRMSG(
"Missing ensemble IDs!");
11688 ERRMSG(
"Too many ensembles!");
11695 ALLOC(area,
double,
11701 ALLOC(rlon,
double,
11703 ALLOC(rlat,
double,
11705 ALLOC(robs,
double,
11716 LOG(1,
"Write CSI%s data: %s", ensemble ?
" ensemble" :
"", filename);
11717 if (!(out = fopen(filename,
"w")))
11718 ERRMSG(
"Cannot create file!");
11722 "# $1 = time [s]\n"
11723 "# $2 = ensemble ID\n"
11724 "# $3 = number of hits (cx)\n"
11725 "# $4 = number of misses (cy)\n"
11726 "# $5 = number of false alarms (cz)\n"
11727 "# $6 = number of observations (cx + cy)\n"
11728 "# $7 = number of forecasts (cx + cz)\n"
11729 "# $8 = bias (%%)\n"
11730 "# $9 = POD (%%)\n"
11731 "# $10 = FAR (%%)\n"
11732 "# $11 = CSI (%%)\n"
11733 "# $12 = hits by random chance\n"
11734 "# $13 = ETS (%%)\n"
11735 "# $14 = Pearson R\n"
11736 "# $15 = Spearman R\n"
11737 "# $16 = mean error [kg/m²]\n"
11738 "# $17 = RMSE [kg/m²]\n"
11739 "# $18 = MAE [kg/m²]\n"
11740 "# $19 = log-likelihood\n" "# $20 = number of points\n\n");
11748 for (
int iy = 0; iy < ctl->
csi_ny; iy++) {
11749 const double lat = ctl->
csi_lat0 + dlat * (iy + 0.5);
11750 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.0) * cos(
DEG2RAD(lat));
11755 const double t0 = t - 0.5 * ctl->
dt_mod;
11756 const double t1 = t + 0.5 * ctl->
dt_mod;
11760 ALLOC(modmean,
double,
11761 (ensemble ? ctl->
nens : 1) * grid_size);
11762 ALLOC(obsmean,
double,
11764 ALLOC(obscount,
int,
11766 ALLOC(obsstd,
double,
11770 for (
int i = 0; i < (ensemble ? ctl->
nens : 1); i++)
11771 ct[i] = cx[i] = cy[i] = cz[i] = n[i] = 0;
11774 for (
int i = 0; i < nobs; i++) {
11775 if (rt[i] < t0 || rt[i] >= t1 || !isfinite(robs[i]))
11779 const int ix = (int) ((rlon[i] - ctl->
csi_lon0) / dlon);
11780 const int iy = (int) ((rlat[i] - ctl->
csi_lat0) / dlat);
11781 const int iz = (int) ((rz[i] - ctl->
csi_z0) / dz);
11782 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
11788 obsmean[idx] += robs[i];
11789 obsstd[idx] +=
SQR(robs[i]);
11794 for (
int ip = 0; ip < atm->
np; ip++) {
11797 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11801 int ens_id = ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
11802 if (ens_id < 0 || ens_id >= (ensemble ? ctl->
nens : 1))
11803 ERRMSG(
"Ensemble ID out of range!");
11806 const int ix = (int) ((atm->
lon[ip] - ctl->
csi_lon0) / dlon);
11807 const int iy = (int) ((atm->
lat[ip] - ctl->
csi_lat0) / dlat);
11808 const int iz = (int) ((
Z(atm->
p[ip]) - ctl->
csi_z0) / dz);
11809 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
11819 for (
int e = 0; e < (ensemble ? ctl->
nens : 1); e++) {
11821 for (
int ix = 0; ix < ctl->
csi_nx; ix++)
11822 for (
int iy = 0; iy < ctl->
csi_ny; iy++)
11823 for (
int iz = 0; iz < ctl->
csi_nz; iz++) {
11828 if (obscount[idx]) {
11829 obsmean[idx] /= obscount[idx];
11831 sqrt(obsstd[idx] / obscount[idx] -
SQR(obsmean[idx]));
11835 const int midx = e * grid_size + idx;
11836 if (modmean[midx] > 0)
11837 modmean[midx] /= (1e6 * area[iy]);
11840 if (obscount[idx]) {
11855 x[n[e]] = modmean[midx];
11856 y[n[e]] = obsmean[idx];
11858 obsstdn[n[e]] = obsstd[idx];
11859 if ((++n[e]) >=
NCSI)
11860 ERRMSG(
"Too many points for statistics!");
11872 static double work[2 *
NCSI], work2[2 *
NCSI];
11873 const int n_obs = cx[e] + cy[e];
11874 const int n_for = cx[e] + cz[e];
11875 const double cx_rd = (ct[e] > 0) ? (1. * n_obs * n_for) / ct[e] : NAN;
11876 const double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
11877 const double pod = (n_obs > 0) ? 100. * cx[e] / n_obs : NAN;
11878 const double far = (n_for > 0) ? 100. * cz[e] / n_for : NAN;
11880 (cx[e] + cy[e] + cz[e] >
11881 0) ? 100. * cx[e] / (cx[e] + cy[e] + cz[e]) : NAN;
11883 (cx[e] + cy[e] + cz[e] - cx_rd >
11884 0) ? 100. * (cx[e] - cx_rd) / (cx[e] + cy[e] + cz[e] - cx_rd) : NAN;
11885 const double rho_p = gsl_stats_correlation(x, 1, y, 1, (
size_t) n[e]);
11886 const double rho_s =
11887 gsl_stats_spearman(x, 1, y, 1, (
size_t) n[e], work);
11888 for (
int i = 0; i < n[e]; i++) {
11889 work[i] = x[i] - y[i];
11890 work2[i] = (obsstdn[i] != 0) ? work[i] / obsstdn[i] : 0;
11892 const double mean = gsl_stats_mean(work, 1, (
size_t) n[e]);
11893 const double rmse =
11894 gsl_stats_sd_with_fixed_mean(work, 1, (
size_t) n[e], 0.0);
11895 const double absdev = gsl_stats_absdev_m(work, 1, (
size_t) n[e], 0.0);
11896 const double loglikelihood =
11897 gsl_stats_tss_m(work2, 1, (
size_t) n[e], 0.0) * -0.5;
11901 "%.2f %d %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n",
11902 t, ensemble ? e : -999, cx[e], cy[e], cz[e], n_obs, n_for, bias,
11903 pod, far, csi, cx_rd, ets, rho_p, rho_s, mean, rmse, absdev,
11904 loglikelihood, n[e]);
11907 for (
int i = 0; i < n[e]; i++)
11908 work[i] = work2[i] = x[i] = y[i] = obsstdn[i] = 0;
11909 ct[e] = cx[e] = cy[e] = cz[e] = n[e] = 0;
11937 const char *filename,
11947 static int n[
NENS];
11954 ERRMSG(
"Missing ensemble IDs!");
11957 const double t0 = t - 0.5 * ctl->
dt_mod;
11958 const double t1 = t + 0.5 * ctl->
dt_mod;
11961 for (
int i = 0; i <
NENS; i++) {
11962 for (
int iq = 0; iq < ctl->
nq; iq++)
11963 qm[iq][i] = qs[iq][i] = 0;
11964 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
11969 for (
int ip = 0; ip < atm->
np; ip++) {
11972 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11977 ERRMSG(
"Ensemble ID is out of range!");
11981 for (
int iq = 0; iq < ctl->
nq; iq++) {
11982 qm[iq][ctl->
qnt_ens] += atm->
q[iq][ip];
11993 LOG(1,
"Write ensemble data: %s", filename);
11994 if (!(out = fopen(filename,
"w")))
11995 ERRMSG(
"Cannot create file!");
11999 "# $1 = time [s]\n"
12000 "# $2 = altitude [km]\n"
12001 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
12002 for (
int iq = 0; iq < ctl->
nq; iq++)
12003 fprintf(out,
"# $%d = %s (mean) [%s]\n", 5 + iq,
12005 for (
int iq = 0; iq < ctl->
nq; iq++)
12006 fprintf(out,
"# $%d = %s (sigma) [%s]\n", 5 + ctl->
nq + iq,
12008 fprintf(out,
"# $%d = number of members\n\n", 5 + 2 * ctl->
nq);
12011 for (
int i = 0; i <
NENS; i++)
12013 cart2geo(xm[i], &dummy, &lon, &lat);
12014 fprintf(out,
"%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
12015 for (
int iq = 0; iq < ctl->
nq; iq++) {
12017 fprintf(out, ctl->
qnt_format[iq], qm[iq][i] / n[i]);
12019 for (
int iq = 0; iq < ctl->
nq; iq++) {
12021 double var = qs[iq][i] / n[i] -
SQR(qm[iq][i] / n[i]);
12022 fprintf(out, ctl->
qnt_format[iq], (var > 0 ? sqrt(var) : 0));
12024 fprintf(out,
" %d\n", n[i]);
12034 const char *filename,
12041 static double kz[
EP], kw[
EP];
12045 double *cd, *mean[
NQ], *sigma[
NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
12047 int *ixs, *iys, *izs, *np;
12053 LOG(1,
"Write grid data: %s", filename);
12066 for (
int iq = 0; iq < ctl->
nq; iq++) {
12067 ALLOC(mean[iq],
double,
12069 ALLOC(sigma[iq],
double,
12072 ALLOC(vmr_impl,
double,
12080 ALLOC(area,
double,
12082 ALLOC(press,
double,
12099#pragma omp parallel
for default(shared)
12100 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
12101 z[iz] = ctl->
grid_z0 + dz * (iz + 0.5);
12102 press[iz] =
P(z[iz]);
12106 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12107 lon[ix] = ctl->
grid_lon0 + dlon * (ix + 0.5);
12108#pragma omp parallel for default(shared)
12109 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
12110 lat[iy] = ctl->
grid_lat0 + dlat * (iy + 0.5);
12111 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
12115 const double t0 = t - 0.5 * ctl->
dt_mod;
12116 const double t1 = t + 0.5 * ctl->
dt_mod;
12119#pragma omp parallel for default(shared)
12120 for (
int ip = 0; ip < atm->
np; ip++) {
12121 ixs[ip] = (int) ((atm->
lon[ip] - ctl->
grid_lon0) / dlon);
12122 iys[ip] = (int) ((atm->
lat[ip] - ctl->
grid_lat0) / dlat);
12123 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
grid_z0) / dz);
12124 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
12125 || ixs[ip] < 0 || ixs[ip] >= ctl->
grid_nx
12126 || iys[ip] < 0 || iys[ip] >= ctl->
grid_ny
12127 || izs[ip] < 0 || izs[ip] >= ctl->
grid_nz)
12132 for (
int ip = 0; ip < atm->
np; ip++)
12133 if (izs[ip] >= 0) {
12138 for (
int iq = 0; iq < ctl->
nq; iq++) {
12139 mean[iq][idx] += kernel * atm->
q[iq][ip];
12140 sigma[iq][idx] +=
SQR(kernel * atm->
q[iq][ip]);
12145#pragma omp parallel for default(shared)
12146 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12147 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12148 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
12155 if (ctl->
qnt_m >= 0)
12156 cd[idx] = mean[ctl->
qnt_m][idx] / (1e6 * area[iy]);
12159 vmr_impl[idx] = NAN;
12160 if (ctl->
qnt_m >= 0 && ctl->
molmass > 0 && met0 != NULL
12163 if (mean[ctl->
qnt_m][idx] > 0) {
12169 lon[ix], lat[iy], &temp, ci, cw, 1);
12173 MA / ctl->
molmass * cd[idx] / (
RHO(press[iz], temp) * dz * 1e3);
12179 for (
int iq = 0; iq < ctl->
nq; iq++) {
12180 mean[iq][idx] /= np[idx];
12181 const double var = sigma[iq][idx] / np[idx] -
SQR(mean[iq][idx]);
12182 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
12184 for (
int iq = 0; iq < ctl->
nq; iq++) {
12185 mean[iq][idx] = NAN;
12186 sigma[iq][idx] = NAN;
12193 t, z, lon, lat, area, dz, np);
12198 t, z, lon, lat, area, dz, np);
12202 ERRMSG(
"Grid data format GRID_TYPE unknown!");
12206 for (
int iq = 0; iq < ctl->
nq; iq++) {
12225 const char *filename,
12230 const double *vmr_impl,
12235 const double *area,
12245 if (!(out = popen(
"gnuplot",
"w")))
12246 ERRMSG(
"Cannot create pipe to gnuplot!");
12249 fprintf(out,
"set out \"%s.png\"\n", filename);
12253 int year, mon, day, hour, min, sec;
12254 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
12255 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
12256 year, mon, day, hour, min);
12262 ERRMSG(
"Cannot open file!");
12263 while (fgets(line,
LEN, in))
12264 fprintf(out,
"%s", line);
12271 if (!(out = fopen(filename,
"w")))
12272 ERRMSG(
"Cannot create file!");
12277 "# $1 = time [s]\n"
12278 "# $2 = altitude [km]\n"
12279 "# $3 = longitude [deg]\n"
12280 "# $4 = latitude [deg]\n"
12281 "# $5 = surface area [km^2]\n"
12282 "# $6 = layer depth [km]\n"
12283 "# $7 = column density (implicit) [kg/m^2]\n"
12284 "# $8 = volume mixing ratio (implicit) [ppv]\n"
12285 "# $9 = number of particles [1]\n");
12286 for (
int iq = 0; iq < ctl->
nq; iq++)
12287 fprintf(out,
"# $%i = %s (mean) [%s]\n", 10 + iq, ctl->
qnt_name[iq],
12290 for (
int iq = 0; iq < ctl->
nq; iq++)
12291 fprintf(out,
"# $%i = %s (stddev) [%s]\n", 10 + ctl->
nq + iq,
12293 fprintf(out,
"\n");
12296 for (
int ix = 0; ix < ctl->
grid_nx; ix++) {
12298 fprintf(out,
"\n");
12299 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
12301 fprintf(out,
"\n");
12302 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
12305 fprintf(out,
"%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
12306 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
12307 for (
int iq = 0; iq < ctl->
nq; iq++) {
12309 fprintf(out, ctl->
qnt_format[iq], mean[iq][idx]);
12312 for (
int iq = 0; iq < ctl->
nq; iq++) {
12314 fprintf(out, ctl->
qnt_format[iq], sigma[iq][idx]);
12316 fprintf(out,
"\n");
12329 const char *filename,
12334 const double *vmr_impl,
12339 const double *area,
12343 char longname[2 *
LEN], varname[2 *
LEN];
12347 int *help2, ncid, dimid[10], varid;
12349 size_t start[2], count[2];
12352 ALLOC(help,
double,
12358 NC(nc_create(filename, NC_NETCDF4, &ncid));
12361 NC(nc_def_dim(ncid,
"time", 1, &dimid[0]));
12362 NC(nc_def_dim(ncid,
"z", (
size_t) ctl->
grid_nz, &dimid[1]));
12363 NC(nc_def_dim(ncid,
"lat", (
size_t) ctl->
grid_ny, &dimid[2]));
12364 NC(nc_def_dim(ncid,
"lon", (
size_t) ctl->
grid_nx, &dimid[3]));
12365 NC(nc_def_dim(ncid,
"dz", 1, &dimid[4]));
12368 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &dimid[0],
"time",
12369 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
12370 NC_DEF_VAR(
"z", NC_DOUBLE, 1, &dimid[1],
"altitude",
"km", 0, 0);
12371 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &dimid[2],
"latitude",
"degrees_north", 0,
12373 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &dimid[3],
"longitude",
"degrees_east", 0,
12375 NC_DEF_VAR(
"dz", NC_DOUBLE, 1, &dimid[1],
"layer depth",
"km", 0, 0);
12376 NC_DEF_VAR(
"area", NC_DOUBLE, 1, &dimid[2],
"surface area",
"km**2", 0, 0);
12378 NC_DEF_VAR(
"cd", NC_FLOAT, 4, dimid,
"column density",
"kg m**-2",
12381 "volume mixing ratio (implicit)",
"ppv", ctl->
grid_nc_level, 0);
12382 NC_DEF_VAR(
"np", NC_INT, 4, dimid,
"number of particles",
"1", 0, 0);
12383 for (
int iq = 0; iq < ctl->
nq; iq++) {
12384 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
12385 sprintf(longname,
"%s (mean)", ctl->
qnt_longname[iq]);
12389 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
12390 sprintf(longname,
"%s (stddev)", ctl->
qnt_longname[iq]);
12396 NC(nc_enddef(ncid));
12406 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12407 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12408 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12413 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12414 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12415 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12420 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12421 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12422 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12427 for (
int iq = 0; iq < ctl->
nq; iq++) {
12428 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
12429 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12430 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12431 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12438 for (
int iq = 0; iq < ctl->
nq; iq++) {
12439 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
12440 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12441 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12442 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12449 NC(nc_close(ncid));
12459 const char *filename,
12465 if (!(out = fopen(filename,
"w")))
12466 ERRMSG(
"Cannot create file!");
12556 ERRMSG(
"Number of meteo variables doesn't match!");
12574 const char *varname) {
12583 for (
int ix = 0; ix < met->
nx; ix++)
12584 for (
int iy = 0; iy < met->
ny; iy++)
12585 help[
ARRAY_2D(ix, iy, met->
ny)] = var[ix][iy];
12588 LOG(2,
"Write 2-D variable: %s (uncompressed)", varname);
12590 (
size_t) (met->
nx * met->
ny),
12604 const char *varname,
12605 const int precision,
12606 const double tolerance) {
12615#pragma omp parallel for default(shared) collapse(2)
12616 for (
int ix = 0; ix < met->
nx; ix++)
12617 for (
int iy = 0; iy < met->
ny; iy++)
12618 for (
int ip = 0; ip < met->
np; ip++)
12619 help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)] = var[ix][iy][ip];
12623 LOG(2,
"Write 3-D variable: %s (uncompressed)", varname);
12625 (
size_t) (met->
nx * met->
ny * met->
np),
12632 (
size_t) met->
np, 0, out);
12640 FWRITE(&tolerance,
double,
12644 tolerance, 0, out);
12659 (
size_t) met->
np, 0, out);
12669 FWRITE(&tolerance,
double,
12673 tolerance, 0, out);
12679 ERRMSG(
"MET_TYPE not supported!");
12680 LOG(3,
"%d %g", precision, tolerance);
12690 const char *filename,
12696 size_t start[4], count[4];
12697 NC(nc_create(filename, NC_NETCDF4, &ncid));
12700 int tid, lonid, latid, levid;
12701 NC(nc_def_dim(ncid,
"time", 1, &tid));
12702 NC(nc_def_dim(ncid,
"lon", (
size_t) met->
nx, &lonid));
12703 NC(nc_def_dim(ncid,
"lat", (
size_t) met->
ny, &latid));
12704 NC(nc_def_dim(ncid,
"lev", (
size_t) met->
np, &levid));
12707 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"time",
12708 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
12709 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &lonid,
"longitude",
"degrees_east", 0, 0);
12710 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &latid,
"latitude",
"degrees_north", 0, 0);
12711 NC_DEF_VAR(
"lev", NC_DOUBLE, 1, &levid,
"pressure",
"Pa", 0, 0);
12714 int dimid2[2] = { latid, lonid };
12715 NC_DEF_VAR(
"sp", NC_FLOAT, 2, dimid2,
"Surface pressure",
"Pa",
12717 NC_DEF_VAR(
"z", NC_FLOAT, 2, dimid2,
"Geopotential",
"m**2 s**-2",
12719 NC_DEF_VAR(
"t2m", NC_FLOAT, 2, dimid2,
"2 metre temperature",
"K",
12721 NC_DEF_VAR(
"u10m", NC_FLOAT, 2, dimid2,
"10 metre U wind component",
12723 NC_DEF_VAR(
"v10m", NC_FLOAT, 2, dimid2,
"10 metre V wind component",
12726 "Instantaneous eastward turbulent surface stress",
"N m**-2",
12729 "Instantaneous northward turbulent surface stress",
"N m**-2",
12732 "Instantaneous surface sensible heat flux",
"W m**-1",
12734 NC_DEF_VAR(
"lsm", NC_FLOAT, 2, dimid2,
"Land/sea mask",
"-",
12736 NC_DEF_VAR(
"sstk", NC_FLOAT, 2, dimid2,
"Sea surface temperature",
"K",
12738 NC_DEF_VAR(
"blp", NC_FLOAT, 2, dimid2,
"Boundary layer pressure",
"Pa",
12740 NC_DEF_VAR(
"pt", NC_FLOAT, 2, dimid2,
"Tropopause pressure",
"Pa",
12742 NC_DEF_VAR(
"tt", NC_FLOAT, 2, dimid2,
"Tropopause temperature",
"K",
12744 NC_DEF_VAR(
"zt", NC_FLOAT, 2, dimid2,
"Tropopause height",
"m",
12746 NC_DEF_VAR(
"h2ot", NC_FLOAT, 2, dimid2,
"Tropopause water vapor",
"ppv",
12748 NC_DEF_VAR(
"pct", NC_FLOAT, 2, dimid2,
"Cloud top pressure",
"Pa",
12750 NC_DEF_VAR(
"pcb", NC_FLOAT, 2, dimid2,
"Cloud bottom pressure",
"Pa",
12752 NC_DEF_VAR(
"cl", NC_FLOAT, 2, dimid2,
"Total column cloud water",
12755 "Pressure at lifted condensation level (LCL)",
"Pa",
12758 "Pressure at level of free convection (LFC)",
"Pa",
12761 "Pressure at equilibrium level (EL)",
"Pa", ctl->
met_nc_level,
12764 "Convective available potential energy",
"J kg**-1",
12766 NC_DEF_VAR(
"cin", NC_FLOAT, 2, dimid2,
"Convective inhibition",
12768 NC_DEF_VAR(
"o3c", NC_FLOAT, 2, dimid2,
"Total column ozone",
"DU",
12772 int dimid3[3] = { levid, latid, lonid };
12773 NC_DEF_VAR(
"t", NC_FLOAT, 3, dimid3,
"Temperature",
"K",
12775 NC_DEF_VAR(
"u", NC_FLOAT, 3, dimid3,
"U velocity",
"m s**-1",
12777 NC_DEF_VAR(
"v", NC_FLOAT, 3, dimid3,
"V velocity",
"m s**-1",
12779 NC_DEF_VAR(
"w", NC_FLOAT, 3, dimid3,
"Vertical velocity",
"Pa s**-1",
12781 NC_DEF_VAR(
"q", NC_FLOAT, 3, dimid3,
"Specific humidity",
"kg kg**-1",
12783 NC_DEF_VAR(
"o3", NC_FLOAT, 3, dimid3,
"Ozone mass mixing ratio",
12785 NC_DEF_VAR(
"clwc", NC_FLOAT, 3, dimid3,
"Cloud liquid water content",
12787 NC_DEF_VAR(
"crwc", NC_FLOAT, 3, dimid3,
"Cloud rain water content",
12789 NC_DEF_VAR(
"ciwc", NC_FLOAT, 3, dimid3,
"Cloud ice water content",
12791 NC_DEF_VAR(
"cswc", NC_FLOAT, 3, dimid3,
"Cloud snow water content",
12793 NC_DEF_VAR(
"cc", NC_FLOAT, 3, dimid3,
"Cloud cover",
"-",
12797 NC(nc_enddef(ncid));
12804 for (
int ip = 0; ip < met->
np; ip++)
12805 phelp[ip] = 100. * met->
p[ip];
12848 NC(nc_close(ncid));
12855 const char *varname,
12861 size_t start[4], count[4];
12869 for (
int ix = 0; ix < met->
nx; ix++)
12870 for (
int iy = 0; iy < met->
ny; iy++)
12871 help[
ARRAY_2D(iy, ix, met->
nx)] = scl * var[ix][iy];
12884 const char *varname,
12890 size_t start[4], count[4];
12898 for (
int ix = 0; ix < met->
nx; ix++)
12899 for (
int iy = 0; iy < met->
ny; iy++)
12900 for (
int ip = 0; ip < met->
np; ip++)
12901 help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)] = scl * var[ix][iy][ip];
12913 const char *filename,
12922 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
12923 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
12925 static int nobs, *obscount, ip, okay;
12934 if (ctl->
qnt_m < 0)
12935 ERRMSG(
"Need quantity mass!");
12939 ERRMSG(
"Specify molar mass!");
12946 ALLOC(area,
double,
12950 ALLOC(press,
double,
12956 ALLOC(rlon,
double,
12958 ALLOC(rlat,
double,
12960 ALLOC(robs,
double,
12967 LOG(1,
"Write profile data: %s", filename);
12968 if (!(out = fopen(filename,
"w")))
12969 ERRMSG(
"Cannot create file!");
12973 "# $1 = time [s]\n"
12974 "# $2 = altitude [km]\n"
12975 "# $3 = longitude [deg]\n"
12976 "# $4 = latitude [deg]\n"
12977 "# $5 = pressure [hPa]\n"
12978 "# $6 = temperature [K]\n"
12979 "# $7 = volume mixing ratio [ppv]\n"
12980 "# $8 = H2O volume mixing ratio [ppv]\n"
12981 "# $9 = O3 volume mixing ratio [ppv]\n"
12982 "# $10 = observed BT index [K]\n"
12983 "# $11 = number of observations\n");
12991 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
12992 z[iz] = ctl->
prof_z0 + dz * (iz + 0.5);
12993 press[iz] =
P(z[iz]);
12997 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
12998 lon[ix] = ctl->
prof_lon0 + dlon * (ix + 0.5);
12999 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
13000 lat[iy] = ctl->
prof_lat0 + dlat * (iy + 0.5);
13001 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
13006 const double t0 = t - 0.5 * ctl->
dt_mod;
13007 const double t1 = t + 0.5 * ctl->
dt_mod;
13010 ALLOC(mass,
double,
13012 ALLOC(obsmean,
double,
13014 ALLOC(obscount,
int,
13018 for (
int i = 0; i < nobs; i++) {
13023 else if (rt[i] >= t1)
13027 if (!isfinite(robs[i]))
13031 const int ix = (int) ((rlon[i] - ctl->
prof_lon0) / dlon);
13032 const int iy = (int) ((rlat[i] - ctl->
prof_lat0) / dlat);
13035 if (ix < 0 || ix >= ctl->
prof_nx || iy < 0 || iy >= ctl->
prof_ny)
13040 obsmean[idx] += robs[i];
13045 for (ip = 0; ip < atm->
np; ip++) {
13048 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13052 const int ix = (int) ((atm->
lon[ip] - ctl->
prof_lon0) / dlon);
13053 const int iy = (int) ((atm->
lat[ip] - ctl->
prof_lat0) / dlat);
13054 const int iz = (int) ((
Z(atm->
p[ip]) - ctl->
prof_z0) / dz);
13057 if (ix < 0 || ix >= ctl->
prof_nx ||
13063 mass[idx] += atm->
q[ctl->
qnt_m][ip];
13067 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
13068 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
13070 if (obscount[idx2] > 0) {
13074 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
13076 if (mass[idx3] > 0) {
13085 fprintf(out,
"\n");
13088 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
13093 lon[ix], lat[iy], &temp, ci, cw, 1);
13095 lon[ix], lat[iy], &h2o, ci, cw, 0);
13097 lon[ix], lat[iy], &o3, ci, cw, 0);
13102 / (
RHO(press[iz], temp) * area[iy] * dz * 1e9);
13105 fprintf(out,
"%.2f %g %g %g %g %g %g %g %g %g %d\n",
13106 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
13107 obsmean[idx2] / obscount[idx2], obscount[idx2]);
13140 const char *filename,
13149 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[
EP],
13152 static int nobs, nk;
13165 ALLOC(rlon,
double,
13167 ALLOC(rlat,
double,
13169 ALLOC(robs,
double,
13180 LOG(1,
"Write sample data: %s", filename);
13181 if (!(out = fopen(filename,
"w")))
13182 ERRMSG(
"Cannot create file!");
13186 "# $1 = time [s]\n"
13187 "# $2 = altitude [km]\n"
13188 "# $3 = longitude [deg]\n"
13189 "# $4 = latitude [deg]\n"
13190 "# $5 = surface area [km^2]\n"
13191 "# $6 = layer depth [km]\n"
13192 "# $7 = number of particles [1]\n"
13193 "# $8 = column density [kg/m^2]\n"
13194 "# $9 = volume mixing ratio [ppv]\n"
13195 "# $10 = observed BT index [K]\n\n");
13200 area = M_PI * rmax2;
13204 const double t0 = t - 0.5 * ctl->
dt_mod;
13205 const double t1 = t + 0.5 * ctl->
dt_mod;
13208 for (
int i = 0; i < nobs; i++) {
13213 else if (rt[i] >= t1)
13218 geo2cart(0, rlon[i], rlat[i], x0);
13221 const double rp =
P(rz[i]);
13222 const double ptop =
P(rz[i] + ctl->
sample_dz);
13223 const double pbot =
P(rz[i] - ctl->
sample_dz);
13231 for (
int ip = 0; ip < atm->
np; ip++) {
13234 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13238 if (fabs(rlat[i] - atm->
lat[ip]) > dlat)
13244 if (
DIST2(x0, x1) > rmax2)
13249 if (atm->
p[ip] > pbot || atm->
p[ip] < ptop)
13253 if (ctl->
qnt_m >= 0)
13260 const double cd = mass / (1e6 * area);
13271 rlon[i], rlat[i], &temp, ci, cw, 1);
13280 fprintf(out,
"%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
13281 rlon[i], rlat[i], area, ctl->
sample_dz, np, cd, vmr, robs[i]);
13302 const char *filename,
13309 static double rmax2, x0[3], x1[3];
13318 LOG(1,
"Write station data: %s", filename);
13321 if (!(out = fopen(filename,
"w")))
13322 ERRMSG(
"Cannot create file!");
13326 "# $1 = time [s]\n"
13327 "# $2 = altitude [km]\n"
13328 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
13329 for (
int iq = 0; iq < ctl->
nq; iq++)
13330 fprintf(out,
"# $%i = %s [%s]\n", (iq + 5),
13332 fprintf(out,
"\n");
13340 const double t0 = t - 0.5 * ctl->
dt_mod;
13341 const double t1 = t + 0.5 * ctl->
dt_mod;
13344 for (
int ip = 0; ip < atm->
np; ip++) {
13347 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13363 if (
DIST2(x0, x1) > rmax2)
13371 fprintf(out,
"%.2f %g %g %g",
13372 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]);
13373 for (
int iq = 0; iq < ctl->
nq; iq++) {
13375 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
13377 fprintf(out,
"\n");
13388 const char *filename,
13399 LOG(1,
"Write VTK data: %s", filename);
13402 const double t0 = t - 0.5 * ctl->
dt_mod;
13403 const double t1 = t + 0.5 * ctl->
dt_mod;
13406 if (!(out = fopen(filename,
"w")))
13407 ERRMSG(
"Cannot create file!");
13411 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13412 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13419 "# vtk DataFile Version 3.0\n"
13420 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
13423 fprintf(out,
"POINTS %d float\n", np);
13425 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13426 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13430 const double coslat = cos(
DEG2RAD(atm->
lat[ip]));
13431 const double x = radius * coslat * cos(
DEG2RAD(atm->
lon[ip]));
13432 const double y = radius * coslat * sin(
DEG2RAD(atm->
lon[ip]));
13433 const double z = radius * sin(
DEG2RAD(atm->
lat[ip]));
13434 fprintf(out,
"%g %g %g\n", x, y, z);
13437 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13438 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13440 fprintf(out,
"%g %g %g\n", atm->
lon[ip], atm->
lat[ip],
13445 fprintf(out,
"POINT_DATA %d\n", np);
13446 for (
int iq = 0; iq < ctl->
nq; iq++) {
13447 fprintf(out,
"SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
13449 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13450 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13452 fprintf(out,
"%g\n", atm->
q[iq][ip]);
void read_met_geopot(const ctl_t *ctl, met_t *met)
Calculates geopotential heights from meteorological data.
void mptrac_alloc(ctl_t **ctl, cache_t **cache, clim_t **clim, met_t **met0, met_t **met1, atm_t **atm, dd_t **dd)
Allocates and initializes memory resources for MPTRAC.
void mptrac_write_atm(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes air parcel data to a file in various formats.
void day2doy(const int year, const int mon, const int day, int *doy)
Get day of year from date.
void read_met_extrapolate(met_t *met)
Extrapolates meteorological data.
void write_atm_clams_traj(const char *dirname, const ctl_t *ctl, const atm_t *atm, const double t)
Writes CLaMS trajectory data to a NetCDF file.
int read_met_nc_2d(const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const char *varname5, const char *varname6, const ctl_t *ctl, const met_t *met, dd_t *dd, float dest[EX][EY], const float scl, const int init)
Reads a 2-dimensional meteorological variable from a NetCDF file.
void write_met_nc_2d(const int ncid, const char *varname, met_t *met, float var[EX][EY], const float scl)
Writes a 2D meteorological variable to a NetCDF file.
void read_met_sample(const ctl_t *ctl, met_t *met)
Downsamples meteorological data based on specified parameters.
void write_met_bin_3d(FILE *out, const ctl_t *ctl, met_t *met, float var[EX][EY][EP], const char *varname, const int precision, const double tolerance)
Writes a 3-dimensional meteorological variable to a binary 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_timesteps(const ctl_t *ctl, cache_t *cache, met_t *met0, atm_t *atm, const double t)
Calculate time steps for air parcels based on specified conditions.
void module_meteo(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Update atmospheric properties using meteorological data.
void read_clim_photo(const char *filename, clim_photo_t *photo)
Reads photolysis rates from a NetCDF file and populates the given photolysis structure.
void read_met_cloud(met_t *met)
Calculates cloud-related variables for each grid point.
void module_decay(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, atm_t *atm)
Simulate exponential decay processes for atmospheric particles.
double sedi(const double p, const double T, const double rp, const double rhop)
Calculates the sedimentation velocity of a particle in air.
double cos_sza(const double sec, const double lon, const double lat)
Calculates the cosine of the solar zenith angle.
void intpol_met_space_2d(const met_t *met, float array[EX][EY], const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables in 2D space.
int read_met_nc_3d(const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const ctl_t *ctl, const met_t *met, dd_t *dd, float dest[EX][EY][EP], const float scl)
Reads a 3-dimensional meteorological variable from a NetCDF file.
int read_atm_nc(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a generic netCDF file and populates the given atmospheric structure.
void read_met_pbl(const ctl_t *ctl, met_t *met)
Computes the planetary boundary layer (PBL) pressure based on meteorological data.
void read_met_detrend(const ctl_t *ctl, met_t *met)
Detrends meteorological data.
void read_met_tropo(const ctl_t *ctl, const clim_t *clim, met_t *met)
Calculates the tropopause and related meteorological variables based on various methods and stores th...
void read_obs_asc(const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from an ASCII file.
void module_chem_init(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Initializes the chemistry modules by setting atmospheric composition.
int locate_reg(const double *xx, const int n, const double x)
Locate the index of the interval containing a given value in a regular grid.
void get_tropo(const int met_tropo, ctl_t *ctl, 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.
void read_met_nc_levels(const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads and processes meteorological level data from NetCDF files with domain decomposition.
void read_met_monotonize(const ctl_t *ctl, met_t *met)
Makes zeta and pressure profiles monotone.
int read_clim_ts(const char *filename, clim_ts_t *ts)
Reads a climatological time series from a file and populates the given time series structure.
void read_met_periodic(met_t *met)
Applies periodic boundary conditions to meteorological data along longitudinal axis.
void mptrac_run_timestep(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t **met0, met_t **met1, atm_t *atm, double t, dd_t *dd)
Executes a single timestep of the MPTRAC model simulation.
void module_timesteps_init(ctl_t *ctl, const atm_t *atm)
Initialize start time and time interval for time-stepping.
void write_ens(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes ensemble data to a file.
void module_mixing(const ctl_t *ctl, const clim_t *clim, atm_t *atm, const double t)
Update atmospheric properties through interparcel mixing.
double clim_zm(const clim_zm_t *zm, const double t, const double lat, const double p)
Interpolates monthly mean zonal mean climatological variables.
void module_mixing_help(const ctl_t *ctl, const clim_t *clim, atm_t *atm, const int *ixs, const int *iys, const int *izs, const int qnt_idx, const int use_ensemble)
Perform subgrid-scale interparcel mixing of a given quantity.
void read_clim_photo_help(const int ncid, const char *varname, const clim_photo_t *photo, double var[CP][CSZA][CO3])
Reads a 3D climatological photochemistry variable from a NetCDF file.
void read_met_ml2pl(const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname)
Interpolates meteorological data to specified pressure levels.
double clim_tropo(const clim_t *clim, const double t, const double lat)
Calculates the tropopause pressure based on climatological data.
void read_obs_nc(const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from a NetCDF file.
void read_met_bin_2d(FILE *in, const met_t *met, float var[EX][EY], const char *varname)
Reads a 2-dimensional meteorological variable from a binary file and stores it in the provided array.
int locate_irr(const double *xx, const int n, const double x)
Locate the index of the interval containing a given value in a sorted array.
void module_isosurf_init(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Initialize the isosurface module based on atmospheric data.
void level_definitions(ctl_t *ctl)
Defines pressure levels for meteorological data.
void write_grid_asc(const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
Writes grid data to an ASCII file.
void mptrac_update_device(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
Updates device memory for specified data structures.
void time2jsec(const int year, const int mon, const int day, const int hour, const int min, const int sec, const double remain, double *jsec)
Converts time components to seconds since January 1, 2000, 12:00:00 UTC.
void mptrac_init(ctl_t *ctl, cache_t *cache, clim_t *clim, atm_t *atm, const int ntask)
Initializes the MPTRAC model and its associated components.
void intpol_met_time_3d(const met_t *met0, float array0[EX][EY][EP], const met_t *met1, float array1[EX][EY][EP], const double ts, const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological data in 3D space and time.
void 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.
void compress_pck(const char *varname, float *array, const size_t nxy, const size_t nz, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats.
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 read_met_nc_grid_dd_naive(dd_t *dd, const ctl_t *ctl, met_t *met, const int ncid)
Read meteorological grid data from a NetCDF file and set up subdomain decomposition with halos.
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_convection(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Performs convective mixing of atmospheric particles.
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 mptrac_get_met(ctl_t *ctl, clim_t *clim, const double t, met_t **met0, met_t **met1, dd_t *dd)
Retrieves meteorological data for the specified time.
void module_sort_help(double *a, const int *p, const int np)
Reorder an array based on a given permutation.
float stddev(const float *data, const int n)
Calculates the standard deviation of a set of data.
void intpol_tropo_3d(const double time0, float array0[EX][EY], const double time1, float array1[EX][EY], const double lons[EX], const double lats[EY], const int nlon, const int nlat, const double time, const double lon, const double lat, const int method, double *var, double *sigma)
Interpolates tropopause data in 3D (latitude, longitude, and time).
void read_met_bin_3d(FILE *in, const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname, const float bound_min, const float bound_max)
Reads 3D meteorological data from a binary file, potentially using different compression methods.
int locate_irr_float(const float *xx, const int n, const double x, const int ig)
Locate the index of the interval containing a given value in an irregularly spaced array.
double time_from_filename(const char *filename, const int offset)
Extracts and converts a timestamp from a filename to Julian seconds.
void write_prof(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes profile data to a specified file.
void mptrac_read_clim(const ctl_t *ctl, clim_t *clim)
Reads various climatological data and populates the given climatology structure.
double tropo_weight(const clim_t *clim, const atm_t *atm, const int ip)
Computes a weighting factor based on tropopause pressure.
void write_met_nc(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a NetCDF file.
void module_rng_init(const int ntask)
Initialize random number generators for parallel tasks.
int mptrac_read_atm(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a specified file into the given atmospheric structure.
void mptrac_update_host(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
Updates host memory for specified data structures.
void mptrac_write_output(const char *dirname, const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double t)
Writes various types of output data to files in a specified directory.
double clim_oh(const ctl_t *ctl, const clim_t *clim, const double t, const double lon, const double lat, const double p)
Calculates the hydroxyl radical (OH) concentration from climatology data, with an optional diurnal co...
void read_met_ozone(met_t *met)
Calculates the total column ozone from meteorological ozone data.
void read_met_nc_surface(const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads and processes surface meteorological data from NetCDF files with domain decomposition.
void clim_tropo_init(clim_t *clim)
Initializes the tropopause data in the climatology structure.
void module_rng(const ctl_t *ctl, double *rs, const size_t n, const int method)
Generate random numbers using various methods and distributions.
void get_met_help(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 write_station(const char *filename, const ctl_t *ctl, atm_t *atm, const double t)
Writes station data to a specified file.
void cart2geo(const double *x, double *z, double *lon, double *lat)
State variables of cuRAND random number generator.
void doy2day(const int year, const int doy, int *mon, int *day)
Converts a given day of the year (DOY) to a date (month and day).
void intpol_met_4d_zeta(const met_t *met0, float heights0[EX][EY][EP], float array0[EX][EY][EP], const met_t *met1, float heights1[EX][EY][EP], float array1[EX][EY][EP], const double ts, const double height, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables to a given position and time.
void intpol_met_time_2d(const met_t *met0, float array0[EX][EY], const met_t *met1, float array1[EX][EY], const double ts, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological data in 2D space and time.
void module_position(const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Update the positions and pressure levels of atmospheric particles.
void clim_oh_diurnal_correction(const ctl_t *ctl, clim_t *clim)
Applies a diurnal correction to the hydroxyl radical (OH) concentration in climatology data.
void locate_vert(float profiles[EX][EY][EP], const int np, const int lon_ap_ind, const int lat_ap_ind, const double height_ap, int *ind)
Locate the four vertical indizes of a box for a given height value.
void write_met_bin_2d(FILE *out, met_t *met, float var[EX][EY], const char *varname)
Writes a 2-dimensional meteorological variable to a binary file.
void read_met_pv(met_t *met)
Calculates potential vorticity (PV) from meteorological data.
int read_atm_bin(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a binary file and populates the given atmospheric structure.
void get_met_replace(char *orig, char *search, char *repl)
Replaces occurrences of a substring in a string with another substring.
void module_diff_meso(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate mesoscale diffusion for atmospheric particles.
void module_sort(const ctl_t *ctl, met_t *met0, atm_t *atm)
Sort particles according to box index.
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 module_diff_turb(const ctl_t *ctl, cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Applies turbulent diffusion processes to atmospheric particles.
int read_atm_clams(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads atmospheric data from a CLAMS NetCDF file.
int mptrac_read_met(const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met, dd_t *dd)
Reads meteorological data from a file, supporting multiple formats and MPI broadcasting.
void write_vtk(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes VTK (Visualization Toolkit) data to a specified file.
void module_tracer_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Simulate chemical reactions involving long-lived atmospheric tracers.
void mptrac_read_ctl(const char *filename, int argc, char *argv[], ctl_t *ctl)
Reads control parameters from a configuration file and populates the given structure.
void mptrac_free(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm, dd_t *dd)
Frees memory resources allocated for MPTRAC.
void read_met_polar_winds(met_t *met)
Applies a fix for polar winds in meteorological data.
void module_h2o2_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Perform chemical reactions involving H2O2 within cloud particles.
void write_grid_nc(const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
Writes grid data to a NetCDF file.
double pbl_weight(const ctl_t *ctl, const atm_t *atm, const int ip, const double pbl, const double ps)
Computes a weighting factor based on planetary boundary layer pressure.
void module_diff_pbl(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Computes particle diffusion within the planetary boundary layer (PBL).
void write_met_nc_3d(const int ncid, const char *varname, met_t *met, float var[EX][EY][EP], const float scl)
Writes a 3D meteorological variable to a NetCDF file.
void module_isosurf(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Apply the isosurface module to adjust atmospheric properties.
void module_oh_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Perform hydroxyl chemistry calculations for atmospheric particles.
void geo2cart(const double z, const double lon, const double lat, double *x)
Converts geographic coordinates (longitude, latitude, altitude) to Cartesian coordinates.
void read_met_nc_grid(const char *filename, const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads meteorological grid data from NetCDF files with domain decomposition.
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.
int read_atm_asc(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from an ASCII file and populates the given atmospheric structure.
void intpol_check_lon_lat(const double *lons, const int nlon, const double *lats, const int nlat, const double lon, const double lat, double *lon2, double *lat2)
Adjusts longitude and latitude to ensure they fall within valid bounds.
void write_sample(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes sample data to a specified file.
void write_grid(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes grid data to a file in ASCII or netCDF format.
void module_dry_depo(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate dry deposition of atmospheric particles.
void write_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data in binary format to a specified file.
void write_atm_bin(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a binary file.
void read_met_cape(const ctl_t *ctl, const clim_t *clim, met_t *met)
Calculates Convective Available Potential Energy (CAPE) for each grid point.
void mptrac_write_met(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a file, supporting multiple formats and compression options.
double lapse_rate(const double t, const double h2o)
Calculates the moist adiabatic lapse rate in Kelvin per kilometer.
void write_csi(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes Critical Success Index (CSI) data to a file.
void write_atm_nc(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a NetCDF file.
MPTRAC library declarations.
#define NN(x0, y0, x1, y1, x)
Perform nearest-neighbor interpolation.
int dd_init(ctl_t *ctl, dd_t *dd, atm_t *atm)
Initializes domain decomposition for parallel processing.
void compress_zstd(const char *varname, float *array, const size_t n, const int decompress, const int level, FILE *inout)
Compresses or decompresses a float array using Zstandard (ZSTD).
#define LEN
Maximum length of ASCII data lines.
#define RE
Mean radius of Earth [km].
#define TVIRT(t, h2o)
Compute virtual temperature.
#define DD_NPOLE
Constant indicating the North pole [-].
void read_met_grib_surface(codes_handle **handles, const int num_messages, const ctl_t *ctl, met_t *met)
Reads surface meteorological data from a grib file and stores it in the meteorological data structure...
#define ARRAY_3D(ix, iy, ny, iz, nz)
Compute the linear index of a 3D array element.
#define PARTICLE_LOOP(ip0, ip1, check_dt,...)
Loop over particle indices with OpenACC acceleration.
#define MA
Molar mass of dry air [g/mol].
#define AVO
Avogadro constant [1/mol].
#define KB
Boltzmann constant [kg m^2/(K s^2)].
#define MH2O
Molar mass of water vapor [g/mol].
#define METVAR
Number of 3-D meteorological variables.
#define NENS
Maximum number of data points for ensemble analysis.
#define FWRITE(ptr, type, size, out)
Write data from memory to a file stream.
#define PW(p, h2o)
Calculate partial water vapor pressure.
#define H0
Scale height [km].
#define NC_PUT_ATT_GLOBAL(attname, text)
Add a global text attribute to a NetCDF file.
#define MOLEC_DENS(p, t)
Calculate the density of a gas molecule.
void dd_sort(const ctl_t *ctl, met_t *met0, atm_t *atm, dd_t *dd, int *nparticles, int *rank)
Sort particles according to box index and target rank for neighbours.
#define DD_SPOLE
Constant indicating the South pole [-].
#define LAPSE(p1, t1, p2, t2)
Calculate lapse rate.
#define NC(cmd)
Execute a NetCDF command and check for errors.
#define ECC_READ_3D(variable, level, target, scaling_factor, found_flag)
Writes 3D data from a grib message into the meteo struct.
#define DOTP(a, b)
Calculate the dot product of two vectors.
#define RA
Specific gas constant of dry air [J/(kg K)].
#define KARMAN
Karman's constant.
#define INTPOL_INIT
Initialize arrays for interpolation.
#define MIN(a, b)
Macro to determine the minimum of two values.
#define ERRMSG(...)
Print an error message with contextual information and terminate the program.
#define NC_PUT_INT(varname, ptr, hyperslab)
Write integer data to a NetCDF variable.
void compress_cms(const ctl_t *ctl, const char *varname, float *array, const size_t nx, const size_t ny, const size_t np, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using a custom multiscale compression algorithm.
void compress_zfp(const char *varname, float *array, const int nx, const int ny, const int nz, const int precision, const double tolerance, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using the ZFP library.
#define EY
Maximum number of latitudes for meteo data.
void dd_particles2atm(atm_t *atm, particle_t *particles, ctl_t *ctl, int *nparticles, cache_t *cache)
Converts particle data to atmospheric data.
#define SH(h2o)
Compute specific humidity from water vapor volume mixing ratio.
#define INTPOL_3D(var, init)
Perform 3D interpolation for a meteorological variable.
#define NOBS
Maximum number of observation data points.
#define NTHREADS
Maximum number of OpenMP threads.
#define ARRAY_2D(ix, iy, ny)
Macro for computing the linear index of a 2D array element.
#define Z(p)
Convert pressure to altitude.
#define codes_handle
Placeholder when ECCODES is not available.
#define P(z)
Compute pressure at given altitude.
#define LV
Latent heat of vaporization of water [J/kg].
#define G0
Standard gravity [m/s^2].
#define CP
Maximum number of pressure levels for climatological data.
#define NQ
Maximum number of quantities per data point.
#define FREAD(ptr, type, size, in)
Read data from a file stream and store it in memory.
#define DX2DEG(dx, lat)
Convert a distance in kilometers to degrees longitude at a given latitude.
#define DEG2DY(dlat)
Convert a latitude difference to a distance in the y-direction (north-south).
#define EX
Maximum number of longitudes for meteo data.
#define EPS
Ratio of the specific gas constant of dry air and water vapor [1].
#define PSICE(t)
Compute saturation pressure over ice (WMO, 2018).
#define THETA(p, t)
Compute potential temperature.
#define RI
Ideal gas constant [J/(mol K)].
int dd_is_periodic_longitude(met_t *met, int nx_glob)
Check whether the longitude grid is periodic (global coverage).
int read_met_grib(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a grib file and processes it.
#define SET_QNT(qnt, name, longname, unit)
Set atmospheric quantity index.
#define TICE(p, h2o)
Calculate frost point temperature (WMO, 2018).
#define TOK(line, tok, format, var)
Get string tokens.
void dd_get_rect_neighbour(const ctl_t ctl, dd_t *dd)
Determines rectangular neighbouring ranks for MPI processes.
#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.
void dd_atm2particles(atm_t *atm, particle_t *particles, ctl_t *ctl, int *nparticles, cache_t *cache, int rank)
Extracts particles from an atmospheric state and prepares them for inter-domain transfer.
#define WARN(...)
Print a warning message with contextual information.
#define ZETA(ps, p, t)
Computes the value of the zeta vertical coordinate.
#define RHICE(p, t, h2o)
Compute relative humidity over ice.
#define INTPOL_TIME_ALL(time, p, lon, lat)
Interpolate multiple meteorological variables in time.
#define ALLOC(ptr, type, n)
Allocate memory for a pointer with error handling.
void read_met_grib_levels(codes_handle **handles, const int num_messages, const ctl_t *ctl, met_t *met)
Reads meteorological variables at different vertical levels from a grib file.
#define SET_ATM(qnt, val)
Set atmospheric quantity value.
#define CTS
Maximum number of data points of climatological time series.
#define ECC_READ_2D(variable, target, scaling_factor, found_flag)
Writes 2-D data from a grib message into the meteo struct.
int dd_calc_subdomain_from_coords(double lon, double lat, met_t *met, ctl_t *ctl, int mpi_size, int nx_glob, int ny_glob)
Computes the destination subdomain (MPI rank) for a particle based on its geographic coordinates.
#define DEG2RAD(deg)
Converts degrees to radians.
void broadcast_large_data(void *data, size_t N)
Broadcasts large data across all processes in an MPI communicator.
#define MO3
Molar mass of ozone [g/mol].
#define SQR(x)
Compute the square of a value.
#define RAD2DEG(rad)
Converts radians to degrees.
#define NP
Maximum number of atmospheric data points.
#define NTIMER
Maximum number of timers.
#define SELECT_TIMER(id, group, color)
Select and start a timer with specific attributes.
#define INTPOL_2D(var, init)
Perform 2D interpolation for a meteorological variable.
void dd_communicate_particles(particle_t *particles, int *nparticles, MPI_Datatype MPI_Particle, int *neighbours, int nneighbours, ctl_t ctl)
Communicates particles between MPI processes.
#define RH(p, t, h2o)
Compute relative humidity over water.
#define NC_PUT_FLOAT(varname, ptr, hyperslab)
Write a float array to a NetCDF file.
#define CY
Maximum number of latitudes for climatological data.
void module_dd(ctl_t *ctl, atm_t *atm, cache_t *cache, dd_t *dd, met_t **met)
Manages domain decomposition and particle communication in parallel processing.
void dd_sort_help(double *a, dd_t *dd, const int np)
Reorder an array according to a permutation vector.
#define LOG(level,...)
Print a log message with a specified logging level.
#define NC_DEF_VAR(varname, type, ndims, dims, long_name, units, level, quant)
Define a NetCDF variable with attributes.
#define TDEW(p, h2o)
Calculate dew point temperature.
#define ARRHENIUS(a, b, t)
Calculate the Arrhenius rate constant.
void dd_assign_rect_subdomains_atm(atm_t *atm, ctl_t *ctl, dd_t *dd, int init)
Assign atmospheric particles to rectangular subdomains.
#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 MPI_Datatype
Placeholder when MPI is not available.
#define EP
Maximum number of pressure levels for meteo data.
#define PSAT(t)
Compute saturation pressure over water.
#define DD_NPART
Maximum number of particles to send and recieve in domain decomposition.
#define RHO(p, t)
Compute density of air.
void module_kpp_chem(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
KPP chemistry module.
#define CO3
Maximum number of total column ozone data for climatological data.
void read_met_grib_grid(codes_handle **handles, int count_handles, met_t *met)
Reads global meteorological information from a grib file.
void compress_sz3(const char *varname, float *array, const int nx, const int ny, const int nz, const int precision, const double tolerance, const int decompress, FILE *inout)
Compresses or decompresses a 3-D float array using the SZ3 library.
void dd_register_MPI_type_particle(MPI_Datatype *MPI_Particle)
Registers a custom MPI datatype for particle structures.
#define NC_PUT_DOUBLE(varname, ptr, hyperslab)
Write double precision data to a NetCDF variable.
#define ECC(cmd)
Execute an ECCODES command and check for errors.
#define LIN(x0, y0, x1, y1, x)
Linear interpolation.
#define DIST2(a, b)
Calculate the squared Euclidean distance between two points in Cartesian coordinates.
#define NC_INQ_DIM(dimname, ptr, min, max, check)
Inquire the length of a dimension in a NetCDF file.
#define DEG2DX(dlon, lat)
Convert a longitude difference to a distance in the x-direction (east-west) at a specific latitude.
#define CPD
Specific heat of dry air at constant pressure [J/(kg K)].
#define CSZA
Maximum number of solar zenith angles for climatological data.
#define DY2DEG(dy)
Convert a distance in kilometers to degrees latitude.
#define MAX(a, b)
Macro to determine the maximum of two values.
#define DD_NNMAX
Maximum number of neighbours to communicate with in domain decomposition.
#define FMOD(x, y)
Calculate the floating-point remainder of dividing x by y.
double lat[NP]
Latitude [deg].
double lon[NP]
Longitude [deg].
int np
Number of air parcels.
double q[NQ][NP]
Quantity data (for various, user-defined attributes).
double p[NP]
Pressure [hPa].
double dt[NP]
Timesteps [s].
double iso_ts[NP]
Isosurface balloon time [s].
int iso_n
Isosurface balloon number of data points.
double iso_ps[NP]
Isosurface balloon pressure [hPa].
double rs[3 *NP+1]
Random numbers.
float uvwp[NP][3]
Wind perturbations [m/s].
double iso_var[NP]
Isosurface variables.
Climatological data in the form of photolysis rates.
int nsza
Number of solar zenith angles.
double sza[CSZA]
Solar zenith angle [rad].
double o3_1[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O1d + O2) [1/s].
double p[CP]
Pressure [hPa].
double ccl2f2[CP][CSZA][CO3]
CCl2F2 photolysis rate [1/s].
double o2[CP][CSZA][CO3]
O2 photolysis rate [1/s].
double ccl3f[CP][CSZA][CO3]
CCl3F photolysis rate [1/s].
double n2o[CP][CSZA][CO3]
N2O photolysis rate [1/s].
double h2o2[CP][CSZA][CO3]
H2O2 photolysis rate [1/s].
double h2o[CP][CSZA][CO3]
H2O photolysis rate [1/s].
double ccl4[CP][CSZA][CO3]
CCl4 photolysis rate [1/s].
double o3_2[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O3p + O2) [1/s].
double o3c[CO3]
Total column ozone [DU].
int np
Number of pressure levels.
int no3c
Number of total ozone columns.
clim_ts_t ccl2f2
CFC-12 time series.
clim_photo_t photo
Photolysis rates.
clim_zm_t ho2
HO2 zonal means.
clim_zm_t hno3
HNO3 zonal means.
int tropo_ntime
Number of tropopause timesteps.
clim_ts_t sf6
SF6 time series.
clim_ts_t ccl4
CFC-10 time series.
clim_ts_t ccl3f
CFC-11 time series.
clim_zm_t o1d
O(1D) zonal means.
double tropo_lat[73]
Tropopause latitudes [deg].
clim_zm_t h2o2
H2O2 zonal means.
int tropo_nlat
Number of tropopause latitudes.
clim_zm_t oh
OH zonal means.
double tropo[12][73]
Tropopause pressure values [hPa].
double tropo_time[12]
Tropopause time steps [s].
clim_ts_t n2o
N2O time series.
Climatological data in the form of time series.
double vmr[CTS]
Volume mixing ratio [ppv].
double time[CTS]
Time [s].
int ntime
Number of timesteps.
Climatological data in the form of zonal means.
int np
Number of pressure levels.
double p[CP]
Pressure [hPa].
double vmr[CT][CP][CY]
Volume mixing ratio [ppv].
int ntime
Number of timesteps.
int nlat
Number of latitudes.
double lat[CY]
Latitude [deg].
double grid_z0
Lower altitude of gridded data [km].
int qnt_o3
Quantity array index for ozone volume mixing ratio.
double csi_lat1
Upper latitude of gridded CSI data [deg].
char csi_obsfile[LEN]
Observation data file for CSI analysis.
int qnt_Coh
Quantity array index for OH volume mixing ratio (chemistry code).
double wet_depo_ic_a
Coefficient A for wet deposition in cloud (exponential form).
int met_nc_scale
Check netCDF scaling factors (0=no, 1=yes).
int qnt_pel
Quantity array index for pressure at equilibrium level (EL).
int csi_nz
Number of altitudes of gridded CSI data.
double molmass
Molar mass [g/mol].
int qnt_p
Quantity array index for pressure.
int qnt_Cccl2f2
Quantity array index for CFC-12 volume mixing ratio (chemistry code).
int dd_halos_size
Domain decomposition size of halos given in grid-points.
char atm_gpfile[LEN]
Gnuplot file for atmospheric data.
int mixing_nx
Number of longitudes of mixing grid.
double chemgrid_z1
Upper altitude of chemistry grid [km].
char qnt_format[NQ][LEN]
Quantity output format.
int qnt_m
Quantity array index for mass.
int qnt_aoa
Quantity array index for age of air.
int qnt_rhop
Quantity array index for particle density.
int qnt_swc
Quantity array index for cloud snow water content.
double csi_obsmin
Minimum observation index to trigger detection.
int qnt_pcb
Quantity array index for cloud bottom pressure.
char clim_n2o_timeseries[LEN]
Filename of N2O time series.
double bound_dzs
Boundary conditions surface layer depth [km].
double csi_lon1
Upper longitude of gridded CSI data [deg].
int qnt_u
Quantity array index for zonal wind.
double stat_lon
Longitude of station [deg].
double mixing_trop
Interparcel exchange parameter for mixing in the troposphere.
double sort_dt
Time step for sorting of particle data [s].
double mixing_z1
Upper altitude of mixing grid [km].
double stat_r
Search radius around station [km].
double wet_depo_bc_a
Coefficient A for wet deposition below cloud (exponential form).
int met_zstd_level
ZSTD compression level (from -5 to 22).
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).
double met_cms_eps_pv
cmultiscale compression epsilon for potential vorticity.
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).
double met_comp_tol[METVAR]
Compression tolerance for SZ3 or ZFP.
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.
double met_cms_eps_h2o
cmultiscale compression epsilon for water vapor.
int qnt_plfc
Quantity array index for pressure at level of free convection (LCF).
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 met_cms_eps_u
cmultiscale compression epsilon for zonal wind.
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 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 isosurf
Isosurface parameter (0=none, 1=pressure, 2=density, 3=theta, 4=balloon).
double bound_p1
Boundary conditions top pressure [hPa].
int qnt_zs
Quantity array index for surface geopotential height.
int prof_nz
Number of altitudes of gridded profile data.
double csi_dt_out
Time step for CSI output [s].
int met_cape
Convective available potential energy data (0=file, 1=calculate).
double csi_modmin
Minimum column density to trigger detection [kg/m^2].
int met_sx
Smoothing for longitudes.
double chemgrid_lon1
Upper longitude of chemistry grid [deg].
double turb_mesox
Horizontal scaling factor for mesoscale wind fluctuations.
double met_cms_eps_iwc
cmultiscale compression epsilon for cloud ice water content.
double met_cms_eps_swc
cmultiscale compression epsilon for cloud snow water content.
char grid_kernel[LEN]
Kernel data file for grid output.
double met_cms_eps_v
cmultiscale compression epsilon for meridional wind.
double prof_z0
Lower altitude of gridded profile data [km].
int qnt_w
Quantity array index for vertical velocity.
double bound_vmr
Boundary conditions volume mixing ratio [ppv].
double met_tropo_pv
Dynamical tropopause potential vorticity threshold [PVU].
int prof_nx
Number of longitudes of gridded profile data.
int qnt_stat
Quantity array index for station flag.
int met_tropo
Tropopause definition (0=none, 1=clim, 2=cold point, 3=WMO_1st, 4=WMO_2nd, 5=dynamical).
int qnt_rp
Quantity array index for particle radius.
int met_mpi_share
Use MPI to share meteo (0=no, 1=yes).
double mixing_strat
Interparcel exchange parameter for mixing in the stratosphere.
int qnt_vz
Quantity array index for vertical velocity.
int qnt_ho2
Quantity array index for HO2 volume mixing ratio (climatology).
double csi_z1
Upper altitude of gridded CSI data [km].
double stat_t0
Start time for station output [s].
double oh_chem_beta
Beta parameter for diurnal variablity of OH.
int dd
Domain decomposition (0=no, 1=yes, with 2x2 if not specified).
char clim_o1d_filename[LEN]
Filename of O(1D) climatology.
int qnt_eta
Quantity array index for eta vertical coordinate.
char clim_photo[LEN]
Filename of photolysis rates climatology.
double wet_depo_so2_ph
pH value used to calculate effective Henry constant of SO2.
double mixing_z0
Lower altitude of mixing grid [km].
int qnt_mloss_decay
Quantity array index for total mass loss due to exponential decay.
int atm_type_out
Type of atmospheric data files for output (-1=same as ATM_TYPE, 0=ASCII, 1=binary,...
int met_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).
int met_comp_prec[METVAR]
Compression precision for SZ3 or ZFP.
int qnt_h2ot
Quantity array index for tropopause water vapor volume mixing ratio.
int qnt_rh
Quantity array index for relative humidity over water.
double met_cms_eps_cc
cmultiscale compression epsilon for cloud cover.
double bound_lat0
Boundary conditions minimum longitude [deg].
double met_pbl_max
Maximum depth of planetary boundary layer [km].
int met_dx
Stride for longitudes.
int qnt_destination
Quantity array index for destination subdomain in domain decomposition.
int mixing_ny
Number of latitudes of mixing grid.
int met_convention
Meteo data layout (0=[lev, lat, lon], 1=[lon, lat, lev]).
int qnt_zeta_d
Quantity array index for diagnosed zeta vertical coordinate.
char clim_h2o2_filename[LEN]
Filename of H2O2 climatology.
int tracer_chem
Switch for first order tracer chemistry module (0=off, 1=on).
double dt_mod
Time step of simulation [s].
int diffusion
Diffusion scheme (0=off, 1=fixed-K, 2=PBL).
int qnt_tnat
Quantity array index for T_NAT.
int qnt_eta_dot
Quantity array index for velocity of eta vertical coordinate.
int qnt_tice
Quantity array index for T_ice.
int qnt_zg
Quantity array index for geopotential height.
double vtk_offset
Vertical offset for VTK data [km].
int qnt_v
Quantity array index for meridional wind.
int qnt_mloss_dry
Quantity array index for total mass loss due to dry deposition.
double bound_vmr_trend
Boundary conditions volume mixing ratio trend [ppv/s].
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).
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).
double met_cms_eps_lwc
cmultiscale compression epsilon for cloud liquid water content.
int qnt_us
Quantity array index for surface zonal wind.
double met_cms_eps_z
cmultiscale compression epsilon for geopotential height.
double grid_lon1
Upper longitude of gridded data [deg].
int qnt_Cn2o
Quantity array index for N2O volume mixing ratio (chemistry code).
int qnt_Cccl3f
Quantity array index for CFC-11 volume mixing ratio (chemistry code).
char qnt_name[NQ][LEN]
Quantity names.
char atm_basename[LEN]
Basename of atmospheric data files.
double mixing_lat0
Lower latitude of mixing grid [deg].
int nens
Number of ensembles.
int qnt_pt
Quantity array index for tropopause pressure.
int qnt_cl
Quantity array index for total column cloud water.
int advect
Advection scheme (0=off, 1=Euler, 2=midpoint, 4=Runge-Kutta).
double prof_z1
Upper altitude of gridded profile data [km].
double met_lev_hyam[EP]
Meteo data model level a coefficients.
int qnt_t
Quantity array index for temperature.
int atm_filter
Time filter for atmospheric data output (0=none, 1=missval, 2=remove).
int kpp_chem
Switch for KPP chemistry module (0=off, 1=on).
int qnt_zeta
Quantity array index for zeta vertical coordinate.
double conv_pbl_trans
Depth of PBL transition layer (fraction of PBL depth).
char ens_basename[LEN]
Basename of ensemble data file.
double wet_depo_pre[2]
Coefficients for precipitation calculation.
int met_vert_coord
Vertical coordinate of input meteo data (0=plev, 1=mlev_p_file, 2=mlev_ab_file, 3=mlev_ab_full,...
double csi_z0
Lower altitude of gridded CSI data [km].
int qnt_lapse
Quantity array index for lapse rate.
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].
int dd_nbr_neighbours
Domain decomposition number of neighbours to communicate with.
double met_cms_eps_t
cmultiscale compression epsilon for temperature.
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 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.
double prof_lat1
Upper latitude of gridded profile data [deg].
int met_cms_batch
cmultiscale batch size.
double psc_h2o
H2O volume mixing ratio for PSC analysis.
int met_sp
Smoothing for pressure levels.
double prof_lon0
Lower longitude of gridded profile data [deg].
int chemgrid_nx
Number of longitudes of chemistry grid.
int qnt_pct
Quantity array index for cloud top pressure.
int qnt_mloss_kpp
Quantity array index for total mass loss due to KPP chemistry.
int qnt_psat
Quantity array index for saturation pressure over water.
int qnt_subdomain
Quantity array index for current subdomain in domain decomposition.
double met_lev_hybm[EP]
Meteo data model level b coefficients.
double prof_lat0
Lower latitude of gridded profile data [deg].
int qnt_cin
Quantity array index for convective inhibition (CIN).
double psc_hno3
HNO3 volume mixing ratio for PSC analysis.
double prof_lon1
Upper longitude of gridded profile data [deg].
double met_cms_eps_rwc
cmultiscale compression epsilon for cloud rain water content.
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.
char clim_ccl3f_timeseries[LEN]
Filename of CFC-11 time series.
double met_cms_eps_o3
cmultiscale compression epsilon for ozone.
int met_cms_zstd
cmultiscale ZSTD compression (0=off, 1=on).
int grid_sparse
Sparse output in grid data files (0=no, 1=yes).
char vtk_basename[LEN]
Basename of VTK data files.
double dry_depo_vdep
Dry deposition velocity [m/s].
int qnt_tt
Quantity array index for tropopause temperature.
int met_np
Number of target pressure levels.
int qnt_ens
Quantity array index for ensemble IDs.
int met_nc_level
zlib compression level of netCDF meteo files (0=off).
double mixing_dt
Time interval for mixing [s].
int qnt_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 met_cms_eps_w
cmultiscale compression epsilon for vertical velocity.
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.
int met_cms_heur
cmultiscale coarsening heuristics (0=default, 1=mean diff, 2=median diff, 3=max diff).
double wet_depo_ic_ret_ratio
Coefficients for wet deposition in cloud: retention ratio.
int qnt_sh
Quantity array index for specific humidity.
int qnt_ess
Quantity array index for eastward turbulent surface stress.
double wet_depo_ic_b
Coefficient B for wet deposition in cloud (exponential form).
double wet_depo_bc_b
Coefficient B for wet deposition below cloud (exponential form).
int met_dy
Stride for latitudes.
int qnt_Cx
Quantity array index for trace species x volume mixing ratio (chemistry code).
double turb_dz_strat
Vertical turbulent diffusion coefficient (stratosphere) [m^2/s].
double bound_zetas
Boundary conditions surface layer zeta [K].
int dd_subdomains_zonal
Domain decomposition zonal subdomain number.
int qnt_idx
Quantity array index for air parcel IDs.
double met_tropo_theta
Dynamical tropopause potential temperature threshold [K].
int qnt_rwc
Quantity array index for cloud rain water content.
double t_start
Start time of simulation [s].
char qnt_longname[NQ][LEN]
Quantity long names.
double met_p[EP]
Target pressure levels [hPa].
int nq
Number of quantities.
double tdec_trop
Life time of particles in the troposphere [s].
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]
Hyperslab of boundary halos count.
int halo_offset_end
Hyperslab of boundary halos count.
int neighbours[DD_NNMAX]
Rank of neighbouring nodes.
double subdomain_lon_min
Rectangular grid limit of subdomain.
size_t halo_bnd_start[4]
Hyperslab of boundary halos start.
double subdomain_lat_max
Rectangular grid limit of subdomain.
int init
Shows if domain decomposition was initialized.
double subdomain_lon_max
Rectangular grid limit of subdomain.
int halo_offset_start
Hyperslab of boundary halos count.
size_t subdomain_count[4]
Hyperslab start and count for subdomain.
size_t subdomain_start[4]
Hyperslab start and count for subdomain.
double subdomain_lat_min
Rectangular grid limit of subdomain.
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).