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);
467 const int decompress,
471 const size_t nxy = nx * ny;
472 double lon[
EX], lat[
EY];
473 for (
size_t ix = 0; ix < nx; ix++)
474 lon[ix] = 360. * (
double) ix / ((double) nx - 1.);
475 for (
size_t iy = 0; iy < ny; iy++)
476 lat[iy] = 90. - 180. * (
double) iy / ((double) ny - 1.);
479 const char domain[] =
"[0.0, 360.0]x[-90.0, 90.0]";
483 cms_param_t *cms_param
484 = cms_set_parameters(nx, ny, max_level_grid, Nd0_x, Nd0_y, domain);
487 double cr = 0, t_coars = 0, t_eval = 0;
493 for (
size_t ip = 0; ip < np; ip++) {
496 cms_module_t *cms_ptr = cms_init(cms_param);
501 cms_sol = cms_read_zstd_sol(cms_ptr, inout);
503 cms_sol = cms_read_sol(cms_ptr, inout);
506#pragma omp parallel for collapse(2) default(shared)
507 for (
size_t ix = 0; ix < nx; ix++)
508 for (
size_t iy = 0; iy < ny; iy++) {
510 const double x[] = { lon[ix], lat[iy] };
511 cms_eval(cms_ptr, cms_sol, x, &val);
512 array[
ARRAY_3D(ix, iy, ny, ip, np)] = (float) val;
516 cr += cms_compression_rate(cms_ptr, cms_sol) / (double) np;
519 cms_delete_sol(cms_sol);
520 cms_delete_module(cms_ptr);
524 LOG(2,
"Read 3-D variable: %s (CMS, RATIO= %g)", varname, cr);
531 cms_module_t *cms_ptr[
EP];
532 cms_sol_t *cms_sol[
EP];
536 ? (size_t) omp_get_max_threads()
538 for (
size_t ip0 = 0; ip0 < np; ip0 += dip) {
541 double t0 = omp_get_wtime();
544#pragma omp parallel for default(shared)
545 for (
size_t ip = ip0; ip <
MIN(ip0 + dip, np); ip++) {
549 ALLOC(tmp_arr,
float,
553 for (
size_t ix = 0; ix < nx; ++ix)
554 for (
size_t iy = 0; iy < ny; ++iy)
556 array[
ARRAY_3D(ix, iy, ny, ip, np)];
559 double c_thresh_test;
560 if (strcasecmp(varname,
"Z") == 0)
562 else if (strcasecmp(varname,
"T") == 0)
564 else if (strcasecmp(varname,
"U") == 0)
566 else if (strcasecmp(varname,
"V") == 0)
568 else if (strcasecmp(varname,
"W") == 0)
570 else if (strcasecmp(varname,
"PV") == 0)
572 else if (strcasecmp(varname,
"H2O") == 0)
574 else if (strcasecmp(varname,
"O3") == 0)
576 else if (strcasecmp(varname,
"LWC") == 0)
578 else if (strcasecmp(varname,
"RWC") == 0)
580 else if (strcasecmp(varname,
"IWC") == 0)
582 else if (strcasecmp(varname,
"SWC") == 0)
584 else if (strcasecmp(varname,
"CC") == 0)
587 ERRMSG(
"Variable name unknown!");
590 cms_ptr[ip] = cms_init(cms_param);
594 cms_read_arr_new(cms_ptr[ip], tmp_arr, lon, lat,
595 nx, ny, c_thresh_test);
602 t_coars += (omp_get_wtime() - t0);
605 for (
size_t ip = ip0; ip <
MIN(ip0 + dip, np); ip++) {
608 double *tmp_cms, *tmp_org, *tmp_diff;
609 ALLOC(tmp_cms,
double,
611 ALLOC(tmp_org,
double,
613 ALLOC(tmp_diff,
double,
617 t0 = omp_get_wtime();
620#pragma omp parallel for collapse(2) default(shared)
621 for (
size_t ix = 0; ix < nx; ix++)
622 for (
size_t iy = 0; iy < ny; iy++) {
623 const size_t idx =
ARRAY_2D(ix, iy, ny);
624 const double x[] = { lon[ix], lat[iy] };
625 cms_eval(cms_ptr[ip], cms_sol[ip], x, &tmp_cms[idx]);
626 tmp_org[idx] = array[
ARRAY_3D(ix, iy, ny, ip, np)];
627 tmp_diff[idx] = tmp_cms[idx] - tmp_org[idx];
631 t_eval += (omp_get_wtime() - t0);
634 const double bias = gsl_stats_mean(tmp_diff, 1, nxy);
635 const double stddev = gsl_stats_sd_m(tmp_diff, 1, nxy, bias);
637 const double nrmse = rmse / gsl_stats_sd(tmp_org, 1, nxy);
639 "cmultiscale: var= %s / lev= %lu / plev= %g / ratio= %g / rho= %g"
640 " / mean= %g / sd= %g / min= %g / max= %g / NRMSE= %g", varname,
641 ip, plev[ip], cms_compression_rate(cms_ptr[ip], cms_sol[ip]),
642 gsl_stats_correlation(tmp_cms, 1, tmp_org, 1, nxy), bias,
stddev,
643 gsl_stats_min(tmp_diff, 1, nxy), gsl_stats_max(tmp_diff, 1, nxy),
647 cr += cms_compression_rate(cms_ptr[ip], cms_sol[ip]) / (double) np;
651 cms_save_zstd_sol(cms_sol[ip], inout, 3);
653 cms_save_sol(cms_sol[ip], inout);
656 cms_delete_sol(cms_sol[ip]);
657 cms_delete_module(cms_ptr[ip]);
665 LOG(2,
"Write 3-D variable: %s"
666 " (CMS, RATIO= %g, T_COARS= %g s, T_EVAL= %g s)",
667 varname, cr, t_coars, t_eval);
671 cms_delete_param(cms_param);
682 const int decompress,
685 double min[
EP], max[
EP], off[
EP], scl[
EP];
687 unsigned short *sarray;
690 ALLOC(sarray,
unsigned short,
697 LOG(2,
"Read 3-D variable: %s (pck, RATIO= %g)",
698 varname, (
double)
sizeof(
float) / (
double)
sizeof(
unsigned short));
707 FREAD(sarray,
unsigned short,
712#pragma omp parallel for default(shared)
713 for (
size_t ixy = 0; ixy < nxy; ixy++)
714 for (
size_t iz = 0; iz < nz; iz++)
716 = (
float) (sarray[ixy * nz + iz] * scl[iz] + off[iz]);
723 LOG(2,
"Write 3-D variable: %s (pck, RATIO= %g)",
724 varname, (
double)
sizeof(
float) / (
double)
sizeof(
unsigned short));
727 for (
size_t iz = 0; iz < nz; iz++) {
731 for (
size_t ixy = 1; ixy < nxy; ixy++)
732 for (
size_t iz = 0; iz < nz; iz++) {
733 if (array[ixy * nz + iz] < min[iz])
734 min[iz] = array[ixy * nz + iz];
735 if (array[ixy * nz + iz] > max[iz])
736 max[iz] = array[ixy * nz + iz];
740 for (
size_t iz = 0; iz < nz; iz++) {
741 scl[iz] = (max[iz] - min[iz]) / 65533.;
746#pragma omp parallel for default(shared)
747 for (
size_t ixy = 0; ixy < nxy; ixy++)
748 for (
size_t iz = 0; iz < nz; iz++)
750 sarray[ixy * nz + iz] = (
unsigned short)
751 ((array[ixy * nz + iz] - off[iz]) / scl[iz] + .5);
753 sarray[ixy * nz + iz] = 0;
762 FWRITE(sarray,
unsigned short,
784 if ((precision > 0) == (tolerance > 0.0))
785 ERRMSG(
"Exactly one of precision or tolerance must be set for SZ3!");
787 size_t r1 = (size_t) nx, r2 = (
size_t) ny, r3 = (size_t) nz,
788 outSize = 0, total_elems = r1 * r2 * r3;
790 unsigned char *bytes = NULL;
796 FREAD(&sz3size,
size_t,
801 FREAD(bytes,
unsigned char,
805 void *outData = SZ_decompress(SZ_FLOAT, bytes, sz3size, 0, 0, r3, r2, r1);
807 ERRMSG(
"Decompression failed!");
809 memcpy(array, outData, total_elems *
sizeof(
float));
814 LOG(2,
"Read 3-D variable: %s (SZ3, PREC=%d, TOL=%g, RATIO=%g)",
815 varname, precision, tolerance,
816 (
double) (total_elems *
sizeof(
float)) / (
double) sz3size);
822 const int errBoundMode = (precision > 0) ? REL : ABS;
823 const double absBound = (errBoundMode == ABS) ? tolerance : 0.0;
824 const double relBound =
825 (errBoundMode == REL) ? pow(2.0, -(
double) precision) : 0.0;
827 bytes = SZ_compress_args(SZ_FLOAT, array, &outSize,
828 errBoundMode, absBound, relBound, 0.0,
830 if (!bytes || outSize == 0)
831 ERRMSG(
"Compression failed!");
836 FWRITE(bytes,
unsigned char,
842 LOG(2,
"Write 3-D variable: %s (SZ3, PREC=%d, TOL=%g, RATIO=%g)",
843 varname, precision, tolerance,
844 (
double) (total_elems *
sizeof(
float)) / (
double) outSize);
859 const double tolerance,
860 const int decompress,
864 const size_t snx = (size_t) nx;
865 const size_t sny = (size_t) ny;
866 const size_t snz = (size_t) nz;
867 const zfp_type type = zfp_type_float;
868 zfp_field *field = zfp_field_3d(array, type, snx, sny, snz);
871 zfp_stream *zfp = zfp_stream_open(NULL);
873 ERRMSG(
"Failed to allocate zfp structures!");
877 double actual_tol = 0;
878 if ((precision > 0 && tolerance > 0) || (precision <= 0 && tolerance <= 0)) {
879 ERRMSG(
"Exactly one of precision or tolerance must be set for zfp!");
880 }
else if (precision > 0)
882 (int) zfp_stream_set_precision(zfp, (
unsigned int) precision);
883 else if (tolerance > 0)
884 actual_tol = zfp_stream_set_accuracy(zfp, tolerance);
887 const size_t bufsize = zfp_stream_maximum_size(zfp, field);
893 bitstream *stream = stream_open(buffer, bufsize);
894 zfp_stream_set_bit_stream(zfp, stream);
895 zfp_stream_rewind(zfp);
900 FREAD(&zfpsize,
size_t,
903 if (zfpsize > bufsize)
904 ERRMSG(
"Compressed data size exceeds allocated buffer!");
905 FREAD(buffer,
unsigned char,
908 if (!zfp_decompress(zfp, field)) {
909 ERRMSG(
"Decompression failed!");
912 ((double) (snx * sny * snz *
sizeof(
float))) / (double) zfpsize;
913 const double bpv = (8.0 * (double) zfpsize) / (double) (snx * sny * snz);
915 "Read 3-D variable: %s (ZFP, PREC= %d, TOL= %g, RATIO= %g, BPV= %g)",
916 varname, actual_prec, actual_tol, cr, bpv);
921 zfpsize = zfp_compress(zfp, field);
923 ERRMSG(
"Compression failed!");
928 FWRITE(buffer,
unsigned char,
933 ((double) (snx * sny * snz *
sizeof(
float))) / (double) zfpsize;
934 const double bpv = (8.0 * (double) zfpsize) / (double) (snx * sny * snz);
936 "Write 3-D variable: %s (ZFP, PREC= %d, TOL= %g, RATIO= %g, BPV= %g)",
937 varname, actual_prec, actual_tol, cr, bpv);
941 zfp_field_free(field);
942 stream_close(stream);
943 zfp_stream_close(zfp);
955 const int decompress,
960 const size_t uncomprLen = n *
sizeof(float);
961 size_t compsize, comprLen = ZSTD_compressBound(uncomprLen);
964 char *compr = calloc(comprLen, 1);
966 ERRMSG(
"Memory allocation failed!");
967 char *uncompr = (
char *) array;
971 FREAD(&comprLen,
size_t,
974 FREAD(compr,
unsigned char,
977 compsize = ZSTD_decompress(uncompr, uncomprLen, compr, comprLen);
978 if (ZSTD_isError(compsize) || compsize != uncomprLen)
979 ERRMSG(
"Decompression failed or size mismatch!");
980 LOG(2,
"Read 3-D variable: %s (ZSTD, RATIO= %g)",
981 varname, ((
double) uncomprLen) / (
double) comprLen);
986 compsize = ZSTD_compress(compr, comprLen, uncompr, uncomprLen, level);
987 if (ZSTD_isError(compsize)) {
988 ERRMSG(
"Compression failed!");
993 FWRITE(compr,
unsigned char,
997 LOG(2,
"Write 3-D variable: %s (ZSTD, RATIO= %g)",
998 varname, ((
double) uncomprLen) / (
double) compsize);
1014 const double D = sec / 86400 - 0.5;
1017 const double g =
DEG2RAD(357.529 + 0.98560028 * D);
1018 const double q = 280.459 + 0.98564736 * D;
1019 const double L =
DEG2RAD(q + 1.915 * sin(g) + 0.020 * sin(2 * g));
1022 const double e =
DEG2RAD(23.439 - 0.00000036 * D);
1025 const double sindec = sin(e) * sin(L);
1028 const double ra = atan2(cos(e) * sin(L), cos(L));
1031 const double GMST = 18.697374558 + 24.06570982441908 * D;
1034 const double LST = GMST + lon / 15;
1037 const double h = LST / 12 * M_PI - ra;
1040 const double lat_help =
DEG2RAD(lat);
1043 return sin(lat_help) * sindec + cos(lat_help) * sqrt(1 -
1044 SQR(sindec)) * cos(h);
1056 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
1057 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
1060 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
1061 *doy = d0l[mon - 1] + day - 1;
1063 *doy = d0[mon - 1] + day - 1;
1075 SELECT_TIMER(
"DD_ASSIGN_RECT_SUBDOMAINS",
"DD", NVTX_GPU);
1079#pragma acc enter data create(dd)
1080#pragma acc update device(dd->rank, dd->subdomain_lon_min, dd->subdomain_lon_max, dd->subdomain_lat_min, dd->subdomain_lat_max)
1081#pragma acc data present(atm, ctl, dd)
1082#pragma acc parallel loop independent gang vector
1084 for (
int ip = 0; ip < atm->
np; ip++) {
1086 double lont = atm->
lon[ip];
1098 (
"DD: Particle is outside the domain (lon: %f, lat: %f, subdomain: %d, subdomain bounds: [%f, %f], [%f, %f])",
1107#pragma acc exit data delete(dd)
1113#pragma acc enter data create(dd)
1114#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)
1115#pragma acc data present(atm, ctl, dd)
1116#pragma acc parallel loop independent gang vector
1118 for (
int ip = 0; ip < atm->
np; ip++) {
1124 double lont = atm->
lon[ip];
1125 double latt = atm->
lat[ip];
1140 bound = (lont - lon_max > 90) ? 1 : 0;
1142 bound = (lon_min - lont > 90) ? 1 : 0;
1145 if ((lont >= lon_max) && (latt >= lat_max)) {
1149 "DD: Particle crossing to upper right: from rank %d to rank %d (lon: %f, lat: %f)",
1151 }
else if ((lont >= lon_max) && (latt <= lat_min)) {
1155 "DD: Particle crossing to lower right: from rank %d to rank %d (lon: %f, lat: %f)",
1157 }
else if ((lont <= lon_min) && (latt >= lat_max)) {
1161 "DD: Particle crossing to upper left: from rank %d to rank %d (lon: %f, lat: %f)",
1163 }
else if ((lont <= lon_min) && (latt <= lat_min)) {
1167 "DD: Particle crossing to lower left: from rank %d to rank %d (lon: %f, lat: %f)",
1169 }
else if (lont >= lon_max) {
1173 "DD: Particle crossing to right: from rank %d to rank %d (lon: %f, lat: %f)",
1175 }
else if (lont <= lon_min) {
1179 "DD: Particle crossing to left: from rank %d to rank %d (lon: %f, lat: %f)",
1181 }
else if (latt <= lat_min) {
1185 "DD: Particle crossing downward: from rank %d to rank %d (lon: %f, lat: %f)",
1187 }
else if (latt >= lat_max) {
1191 "DD: Particle crossing upward: from rank %d to rank %d (lon: %f, lat: %f)",
1198 if ((lont >= lon_max) && (latt >= lat_max)) {
1202 "DD: Particle crossing to upper left (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1204 }
else if ((lont >= lon_max) && (latt <= lat_min)) {
1208 "DD: Particle crossing to lower left (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1210 }
else if ((lont <= lon_min) && (latt >= lat_max)) {
1214 "DD: Particle crossing to upper right (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1216 }
else if ((lont <= lon_min) && (latt <= lat_min)) {
1220 "DD: Particle crossing to lower right (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1222 }
else if (lont >= lon_max) {
1226 "DD: Particle crossing to left (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1228 }
else if (lont <= lon_min) {
1232 "DD: Particle crossing to right (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1234 }
else if (latt <= lat_min) {
1238 "DD: Particle crossing downward (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1240 }
else if (latt >= lat_max) {
1244 "DD: Particle crossing upward (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1273#pragma acc exit data delete(dd)
1294 int npart = *nparticles;
1295#pragma acc enter data create( nparticles, particles[:DD_NPART])
1296#pragma acc update device( nparticles)
1297#pragma acc parallel loop present( atm, ctl, particles, cache, nparticles)
1299 for (
int ip = atm->
np; ip < atm->np + *nparticles; ip++)
1304 particles[ip - atm->
np].
time = atm->
time[ip];
1305 particles[ip - atm->
np].
lon = atm->
lon[ip];
1306 particles[ip - atm->
np].
lat = atm->
lat[ip];
1307 particles[ip - atm->
np].
p = atm->
p[ip];
1309 for (
int iq = 0; iq < ctl->
nq; iq++)
1310 particles[ip - atm->
np].q[iq] = atm->
q[iq][ip];
1313 "DD: Particle being prepared for transfer: subdomain %d -> destination %d (lon: %f, lat: %f)",
1320#pragma acc update host( particles[:npart])
1321#pragma acc exit data delete( nparticles, particles)
1339 double wrapped_lon = lon;
1340 while (wrapped_lon < 0)
1342 while (wrapped_lon >= 360)
1346 double wrapped_lat = lat;
1349 wrapped_lat = 180 - lat;
1350 wrapped_lon = fmod(wrapped_lon + 180, 360);
1351 }
else if (lat < -90) {
1353 wrapped_lat = -180 - lat;
1354 wrapped_lon = fmod(wrapped_lon + 180, 360);
1359 double lon_range = 360.0;
1370 LOG(2,
"nx_glob: %d", nx_glob);
1372 double lat_range = met->
lat[ny_glob - 1] - met->
lat[0];
1373 double global_lon_min = met->
lon[0];
1374 double global_lat_min = met->
lat[0];
1378 (int) ((wrapped_lon -
1381 (int) ((wrapped_lat -
1386 (
"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",
1387 lon, lat, wrapped_lon, wrapped_lat, lon_range, lat_range, global_lon_min,
1388 global_lat_min, lon_idx, lat_idx);
1393 0) ? 0 : ((lon_idx >=
1398 0) ? 0 : ((lat_idx >=
1400 dd_subdomains_meridional - 1 : lat_idx);
1406 if (target_rank >= mpi_size)
1407 target_rank = mpi_size - 1;
1408 if (target_rank < 0)
1438 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
1441 MPI_Request *requests_snd_nbr =
1442 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1443 MPI_Request *requests_rcv_nbr =
1444 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1445 MPI_Request *requests_snd_part =
1446 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1447 MPI_Request *requests_rcv_part =
1448 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1449 MPI_Status *states =
1450 (MPI_Status *) calloc((
size_t) nneighbours,
sizeof(MPI_Status));
1453 for (
int i = 0; i < nneighbours; i++) {
1454 requests_snd_nbr[i] = MPI_REQUEST_NULL;
1455 requests_rcv_nbr[i] = MPI_REQUEST_NULL;
1456 requests_snd_part[i] = MPI_REQUEST_NULL;
1457 requests_rcv_part[i] = MPI_REQUEST_NULL;
1461 for (
int idest = 0; idest < nneighbours; idest++) {
1464 if (neighbours[idest] < 0)
1470 for (
int ip = 0; ip < *nparticles; ip++)
1473 nbs[idest] = help_sum;
1476 LOG(3,
"DD: Rank %d sending %d particles to neighbour %d (rank %d)",
1477 rank, help_sum, idest, neighbours[idest]);
1482 MPI_Isend(&nbs[idest], 1, MPI_INT,
1483 neighbours[idest], 0, MPI_COMM_WORLD, &requests_snd_nbr[idest]);
1486 if (nbs[idest] == 0)
1495 for (
int ip = 0; ip < *nparticles; ip++) {
1496 if ((
int) particles[ip].q[ctl.
qnt_destination] == neighbours[idest]) {
1497 memcpy(&send_buffers[idest][ibs], &particles[ip],
sizeof(
particle_t));
1501 if (ibs == nbs[idest])
1508 MPI_Isend(send_buffers[idest], nbs[idest], MPI_Particle,
1509 neighbours[idest], 1, MPI_COMM_WORLD,
1510 &requests_snd_part[idest]);
1516 for (
int isourc = 0; isourc < nneighbours; isourc++) {
1519 if (neighbours[isourc] < 0) {
1520 requests_rcv_nbr[isourc] = MPI_REQUEST_NULL;
1525 MPI_Irecv(&nbr[isourc], 1, MPI_INT, neighbours[isourc], 0, MPI_COMM_WORLD,
1526 &requests_rcv_nbr[isourc]);
1530 MPI_Waitall(nneighbours, requests_rcv_nbr, states);
1533 for (
int isourc = 0; isourc < nneighbours; isourc++) {
1536 if ((neighbours[isourc] < 0) || (nbr[isourc] == 0)) {
1537 requests_rcv_part[isourc] = MPI_REQUEST_NULL;
1545 MPI_Irecv(recieve_buffers[isourc], nbr[isourc], MPI_Particle,
1546 neighbours[isourc], 1, MPI_COMM_WORLD,
1547 &requests_rcv_part[isourc]);
1551 MPI_Waitall(nneighbours, requests_rcv_part, states);
1559 for (
int isourc = 0; isourc < nneighbours; isourc++) {
1562 if (neighbours[isourc] < 0)
1565 if (nbr[isourc] > 0) {
1566 LOG(3,
"DD: Rank %d receiving %d particles from neighbour %d (rank %d)",
1567 rank, nbr[isourc], isourc, neighbours[isourc]);
1571 for (
int ip = 0; ip < nbr[isourc]; ip++) {
1572 memcpy(&particles[ip + api], &recieve_buffers[isourc][ip],
1586 MPI_Waitall(nneighbours, requests_snd_part, states);
1587 MPI_Waitall(nneighbours, requests_snd_nbr, states);
1590 for (
int i = 0; i < nneighbours; i++) {
1592 if ((send_buffers[i] != NULL) && (nbs[i] != 0)) {
1593 free(send_buffers[i]);
1594 send_buffers[i] = NULL;
1597 if ((recieve_buffers[i] != NULL) && (nbr[i] != 0)) {
1598 free(recieve_buffers[i]);
1599 recieve_buffers[i] = NULL;
1616 const int rank = dd->
rank;
1617 const int size = dd->
size;
1621 nb[0] = (size + rank - m) % size;
1622 nb[3] = (rank + m) % size;
1623 nb[1] = ((rank + 1) % m == 0) ?
DD_SPOLE : (size + rank - m + 1) % size;
1624 nb[2] = (rank % m == 0) ?
DD_NPOLE : (size + rank - m - 1) % size;
1625 nb[4] = ((rank + 1) % m == 0) ?
DD_SPOLE : (rank + m + 1) % size;
1626 nb[5] = (rank % m == 0) ?
DD_NPOLE : (rank + m - 1) % size;
1627 nb[6] = (rank % m == 0) ?
DD_NPOLE : rank - 1;
1628 nb[7] = ((rank + 1) % m == 0) ?
DD_SPOLE : rank + 1;
1644 double lon_spacing = met->
lon[1] - met->
lon[0];
1648 double total_range = met->
lon[nx_glob - 1] - met->
lon[0] + lon_spacing;
1651 return (fabs(total_range - 360.0) < 0.01);
1665 ERRMSG(
"The number of tasks and subdomains is not identical.");
1696 int npart = *nparticles;
1697#pragma acc enter data create(nparticles, particles[:DD_NPART])
1698#pragma acc update device(particles[:npart], nparticles)
1699#pragma acc data present(atm, ctl, cache, particles, nparticles)
1700#pragma acc parallel loop
1702 for (
int ip = atm->
np; ip < atm->np + *nparticles; ip++) {
1703 atm->
time[ip] = particles[ip - atm->
np].
time;
1704 atm->
lon[ip] = particles[ip - atm->
np].
lon;
1705 atm->
lat[ip] = particles[ip - atm->
np].
lat;
1706 atm->
p[ip] = particles[ip - atm->
np].
p;
1707 for (
int iq = 0; iq < ctl->
nq; iq++)
1708 atm->
q[iq][ip] = particles[ip - atm->
np].q[iq];
1712#pragma acc exit data delete(nparticles, particles)
1716 atm->
np += *nparticles;
1718#pragma acc update device(atm->np)
1721 ERRMSG(
"Number of particles to high. Increase NP!");
1730 MPI_Datatype types[5] = { MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE,
1731 MPI_DOUBLE, MPI_DOUBLE
1733 int blocklengths[5] = { 1, 1, 1, 1,
NQ };
1734 MPI_Aint displacements[5] = { offsetof(
particle_t, time),
1740 MPI_Type_create_struct(5, blocklengths, displacements, types, MPI_Particle);
1741 MPI_Type_commit(MPI_Particle);
1760 const int np = atm->
np;
1761 double amax = (met0->
nx * met0->
ny + met0->
ny) * met0->
np + met0->
np;
1763#pragma acc enter data create(amax, rank)
1764#pragma acc update device(rank, amax)
1765#pragma acc data present(ctl,met0,atm,dd,amax,rank)
1770#pragma acc parallel loop independent gang vector
1772#pragma omp parallel for default(shared)
1774 for (
int ip = 0; ip < np; ip++) {
1782 dd->a[ip] = amax + 1;
1784 dd->a[ip] = amax + 2;
1792#pragma acc host_data use_device(dd->a,dd->p)
1794 thrustSortWrapper(dd->a, np, dd->p);
1797 ERRMSG(
"GSL sort fallback not available on GPU, use THRUST!");
1799 gsl_sort_index((
size_t *) (dd->p), (dd->a), 1, (
size_t) np);
1807 for (
int iq = 0; iq < ctl->
nq; iq++)
1813#pragma acc parallel loop reduction(+:npt) present(atm, rank, ctl)
1815 for (
int ip = 0; ip < np; ip++)
1821 int nparticlest = 0;
1823#pragma acc parallel loop reduction(+:nparticlest) present(atm, rank, ctl)
1825 for (
int ip = npt; ip < np; ip++)
1831 *nparticles = nparticlest;
1835 for (
int ip = 0; ip < np; ip++)
1841 (
"DD: Rank %d: %d particles have subdomain index -1 and will be lost (kept: %d, to_send: %d, total_before: %d)",
1842 *rank, nlost, npt, nparticlest, np);
1847#pragma acc update device(atm->np)
1852 (
"Number of particles to send and recieve to small. Increase DD_NPART!");
1856#pragma acc exit data delete(amax, rank)
1871#pragma acc data present(dd,a)
1872#pragma acc parallel loop independent gang vector
1874#pragma omp parallel for default(shared)
1876 for (
int ip = 0; ip < np; ip++)
1877 dd->help[ip] = a[dd->p[ip]];
1879#pragma acc parallel loop independent gang vector
1881#pragma omp parallel
for default(shared)
1883 for (
int ip = 0; ip < np; ip++)
1884 a[ip] = dd->help[ip];
1897 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
1898 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
1903 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
1904 for (i = 11; i > 0; i--)
1908 *day = doy - d0l[i] + 1;
1910 for (i = 11; i > 0; i--)
1914 *day = doy - d0[i] + 1;
1925 double data[2 *
EX];
1929 ERRMSG(
"Too many data points!");
1932 gsl_fft_complex_wavetable *wavetable =
1933 gsl_fft_complex_wavetable_alloc((
size_t) n);
1934 gsl_fft_complex_workspace *workspace =
1935 gsl_fft_complex_workspace_alloc((
size_t) n);
1938 for (
int i = 0; i < n; i++) {
1939 data[2 * i] = fcReal[i];
1940 data[2 * i + 1] = fcImag[i];
1944 gsl_fft_complex_forward(data, 1, (
size_t) n, wavetable, workspace);
1947 for (
int i = 0; i < n; i++) {
1948 fcReal[i] = data[2 * i];
1949 fcImag[i] = data[2 * i + 1];
1953 gsl_fft_complex_wavetable_free(wavetable);
1954 gsl_fft_complex_workspace_free(workspace);
1965 const double radius = z +
RE;
1966 const double latrad =
DEG2RAD(lat);
1967 const double lonrad =
DEG2RAD(lon);
1968 const double coslat = cos(latrad);
1970 x[0] = radius * coslat * cos(lonrad);
1971 x[1] = radius * coslat * sin(lonrad);
1972 x[2] = radius * sin(latrad);
1981 const char *metbase,
1982 const double dt_met,
1989 int year, mon, day, hour, min, sec;
1993 t6 = floor(t / dt_met) * dt_met;
1995 t6 = ceil(t / dt_met) * dt_met;
1998 jsec2time(t6, &year, &mon, &day, &hour, &min, &sec, &r);
2003 sprintf(filename,
"%s_YYYY_MM_DD_HH.nc", metbase);
2005 sprintf(filename,
"%s_YYYY_MM_DD_HH.bin", metbase);
2007 sprintf(filename,
"%s_YYYY_MM_DD_HH.pck", metbase);
2009 sprintf(filename,
"%s_YYYY_MM_DD_HH.zfp", metbase);
2011 sprintf(filename,
"%s_YYYY_MM_DD_HH.zstd", metbase);
2013 sprintf(filename,
"%s_YYYY_MM_DD_HH.cms", metbase);
2015 sprintf(filename,
"%s_YYYY_MM_DD_HH.sz3", metbase);
2016 sprintf(repl,
"%d", year);
2018 sprintf(repl,
"%02d", mon);
2020 sprintf(repl,
"%02d", day);
2022 sprintf(repl,
"%02d", hour);
2028 sprintf(filename,
"%s_YYMMDDHH.nc", metbase);
2029 sprintf(repl,
"%d", year);
2031 sprintf(repl,
"%02d", year % 100);
2033 sprintf(repl,
"%02d", mon);
2035 sprintf(repl,
"%02d", day);
2037 sprintf(repl,
"%02d", hour);
2052 for (
int i = 0; i < 3; i++) {
2056 if (!(ch = strstr(orig, search)))
2058 strncpy(buffer, orig, (
size_t) (ch - orig));
2059 buffer[ch - orig] = 0;
2060 sprintf(buffer + (ch - orig),
"%s%s", repl, ch + strlen(search));
2062 strcpy(orig, buffer);
2069 const int met_tropo,
2089#pragma omp parallel for default(shared) private(ci,cw)
2090 for (
int ix = 0; ix < nx; ix++)
2091 for (
int iy = 0; iy < ny; iy++) {
2093 &pt[iy * nx + ix], ci, cw, 1);
2095 &ps[iy * nx + ix], ci, cw, 0);
2097 &zs[iy * nx + ix], ci, cw, 0);
2099 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
2101 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
2103 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
2105 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
2122 *lon2 =
FMOD(lon, 360.);
2123 if (*lon2 < lons[0])
2125 else if (*lon2 > lons[nlon - 1])
2130 if (lats[0] < lats[nlat - 1])
2131 *lat2 =
MIN(
MAX(*lat2, lats[0]), lats[nlat - 1]);
2133 *lat2 =
MIN(
MAX(*lat2, lats[nlat - 1]), lats[0]);
2140 float heights0[
EX][
EY][
EP],
2141 float array0[
EX][
EY][
EP],
2143 float heights1[
EX][
EY][
EP],
2144 float array1[
EX][
EY][
EP],
2146 const double height,
2172 int k_max = ind[0][0];
2173 for (
int i = 0; i < 2; i++)
2174 for (
int j = 0; j < 4; j++) {
2175 if (ci[2] > ind[i][j])
2177 if (k_max < ind[i][j])
2183 cw[0] = (lon2 - met0->
lon[ci[0]]) /
2184 (met0->
lon[ci[0] + 1] - met0->
lon[ci[0]]);
2185 cw[1] = (lat2 - met0->
lat[ci[1]]) /
2186 (met0->
lat[ci[1] + 1] - met0->
lat[ci[1]]);
2189 double height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2]]
2190 - heights0[ci[0]][ci[1]][ci[2]])
2191 + heights0[ci[0]][ci[1]][ci[2]];
2192 double height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2]]
2193 - heights0[ci[0]][ci[1] + 1][ci[2]])
2194 + heights0[ci[0]][ci[1] + 1][ci[2]];
2195 double height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2]]
2196 - heights0[ci[0] + 1][ci[1]][ci[2]])
2197 + heights0[ci[0] + 1][ci[1]][ci[2]];
2198 double height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2]]
2199 - heights0[ci[0] + 1][ci[1] + 1][ci[2]])
2200 + heights0[ci[0] + 1][ci[1] + 1][ci[2]];
2203 double height0 = cw[1] * (height01 - height00) + height00;
2204 double height1 = cw[1] * (height11 - height10) + height10;
2207 double height_bot = cw[0] * (height1 - height0) + height0;
2210 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
2211 - heights0[ci[0]][ci[1]][ci[2] + 1])
2212 + heights0[ci[0]][ci[1]][ci[2] + 1];
2213 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
2214 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
2215 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
2216 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
2217 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
2218 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
2219 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2220 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2221 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2224 height0 = cw[1] * (height01 - height00) + height00;
2225 height1 = cw[1] * (height11 - height10) + height10;
2228 double height_top = cw[0] * (height1 - height0) + height0;
2231 while (((heights0[0][0][0] > heights0[0][0][1]) &&
2232 ((height_bot <= height) || (height_top > height))
2233 && (height_bot >= height) && (ci[2] < k_max))
2235 ((heights0[0][0][0] < heights0[0][0][1]) &&
2236 ((height_bot >= height) || (height_top < height))
2237 && (height_bot <= height) && (ci[2] < k_max))
2241 height_bot = height_top;
2244 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
2245 - heights0[ci[0]][ci[1]][ci[2] + 1])
2246 + heights0[ci[0]][ci[1]][ci[2] + 1];
2247 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
2248 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
2249 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
2250 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
2251 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
2252 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
2253 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2254 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2255 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2258 height0 = cw[1] * (height01 - height00) + height00;
2259 height1 = cw[1] * (height11 - height10) + height10;
2262 height_top = cw[0] * (height1 - height0) + height0;
2266 cw[2] = (height - height_bot)
2267 / (height_top - height_bot);
2271 const double array000 = cw[3] * (array1[ci[0]][ci[1]][ci[2]]
2272 - array0[ci[0]][ci[1]][ci[2]])
2273 + array0[ci[0]][ci[1]][ci[2]];
2274 const double array100 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2]]
2275 - array0[ci[0] + 1][ci[1]][ci[2]])
2276 + array0[ci[0] + 1][ci[1]][ci[2]];
2277 const double array010 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2]]
2278 - array0[ci[0]][ci[1] + 1][ci[2]])
2279 + array0[ci[0]][ci[1] + 1][ci[2]];
2280 const double array110 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2]]
2281 - array0[ci[0] + 1][ci[1] + 1][ci[2]])
2282 + array0[ci[0] + 1][ci[1] + 1][ci[2]];
2283 const double array001 = cw[3] * (array1[ci[0]][ci[1]][ci[2] + 1]
2284 - array0[ci[0]][ci[1]][ci[2] + 1])
2285 + array0[ci[0]][ci[1]][ci[2] + 1];
2286 const double array101 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2] + 1]
2287 - array0[ci[0] + 1][ci[1]][ci[2] + 1])
2288 + array0[ci[0] + 1][ci[1]][ci[2] + 1];
2289 const double array011 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2] + 1]
2290 - array0[ci[0]][ci[1] + 1][ci[2] + 1])
2291 + array0[ci[0]][ci[1] + 1][ci[2] + 1];
2292 const double array111 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2293 - array0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2294 + array0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2296 const double array00 = cw[0] * (array100 - array000) + array000;
2297 const double array10 = cw[0] * (array110 - array010) + array010;
2298 const double array01 = cw[0] * (array101 - array001) + array001;
2299 const double array11 = cw[0] * (array111 - array011) + array011;
2301 const double aux0 = cw[1] * (array10 - array00) + array00;
2302 const double aux1 = cw[1] * (array11 - array01) + array01;
2305 *var = cw[2] * (aux1 - aux0) + aux0;
2335 cw[0] = (met->
p[ci[0] + 1] - p)
2336 / (met->
p[ci[0] + 1] - met->
p[ci[0]]);
2337 cw[1] = (met->
lon[ci[1] + 1] - lon2)
2338 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
2339 cw[2] = (met->
lat[ci[2] + 1] - lat2)
2340 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
2344 const double aux00 =
2345 cw[0] * (array[ci[1]][ci[2]][ci[0]] - array[ci[1]][ci[2]][ci[0] + 1])
2346 + array[ci[1]][ci[2]][ci[0] + 1];
2347 const double aux01 =
2348 cw[0] * (array[ci[1]][ci[2] + 1][ci[0]] -
2349 array[ci[1]][ci[2] + 1][ci[0] + 1])
2350 + array[ci[1]][ci[2] + 1][ci[0] + 1];
2351 const double aux10 =
2352 cw[0] * (array[ci[1] + 1][ci[2]][ci[0]] -
2353 array[ci[1] + 1][ci[2]][ci[0] + 1])
2354 + array[ci[1] + 1][ci[2]][ci[0] + 1];
2355 const double aux11 =
2356 cw[0] * (array[ci[1] + 1][ci[2] + 1][ci[0]] -
2357 array[ci[1] + 1][ci[2] + 1][ci[0] + 1])
2358 + array[ci[1] + 1][ci[2] + 1][ci[0] + 1];
2361 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
2362 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
2363 *var = cw[1] * (aux0 - aux1) + aux1;
2370 float array[
EX][
EY],
2391 cw[1] = (met->
lon[ci[1] + 1] - lon2)
2392 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
2393 cw[2] = (met->
lat[ci[2] + 1] - lat2)
2394 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
2398 const double aux00 = array[ci[1]][ci[2]];
2399 const double aux01 = array[ci[1]][ci[2] + 1];
2400 const double aux10 = array[ci[1] + 1][ci[2]];
2401 const double aux11 = array[ci[1] + 1][ci[2] + 1];
2404 if (isfinite(aux00) && isfinite(aux01)
2405 && isfinite(aux10) && isfinite(aux11)) {
2406 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
2407 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
2408 *var = cw[1] * (aux0 - aux1) + aux1;
2428 float array0[
EX][
EY][
EP],
2430 float array1[
EX][
EY][
EP],
2447 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
2450 *var = wt * (var0 - var1) + var1;
2457 float array0[
EX][
EY],
2459 float array1[
EX][
EY],
2475 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
2478 if (isfinite(var0) && isfinite(var1))
2479 *var = wt * (var0 - var1) + var1;
2490 float array0[
EX][
EY],
2492 float array1[
EX][
EY],
2493 const double lons[
EX],
2494 const double lats[
EY],
2513 const int ix =
locate_reg(lons, (
int) nlon, lon2);
2514 const int iy =
locate_irr(lats, (
int) nlat, lat2);
2518 for (
int dx = 0; dx < 2; dx++)
2519 for (
int dy = 0; dy < 2; dy++) {
2520 if (isfinite(array0[ix + dx][iy + dy])) {
2521 mean += array0[ix + dx][iy + dy];
2522 *sigma +=
SQR(array0[ix + dx][iy + dy]);
2525 if (isfinite(array1[ix + dx][iy + dy])) {
2526 mean += array1[ix + dx][iy + dy];
2527 *sigma +=
SQR(array1[ix + dx][iy + dy]);
2532 *sigma = sqrt(
MAX(*sigma / n -
SQR(mean / n), 0.0));
2535 if (method == 1 && isfinite(array0[ix][iy])
2536 && isfinite(array0[ix][iy + 1])
2537 && isfinite(array0[ix + 1][iy])
2538 && isfinite(array0[ix + 1][iy + 1])
2539 && isfinite(array1[ix][iy])
2540 && isfinite(array1[ix][iy + 1])
2541 && isfinite(array1[ix + 1][iy])
2542 && isfinite(array1[ix + 1][iy + 1])) {
2544 const double aux00 =
LIN(lons[ix], array0[ix][iy],
2545 lons[ix + 1], array0[ix + 1][iy], lon2);
2546 const double aux01 =
LIN(lons[ix], array0[ix][iy + 1],
2547 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
2548 const double aux0 =
LIN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
2550 const double aux10 =
LIN(lons[ix], array1[ix][iy],
2551 lons[ix + 1], array1[ix + 1][iy], lon2);
2552 const double aux11 =
LIN(lons[ix], array1[ix][iy + 1],
2553 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
2554 const double aux1 =
LIN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
2556 *var =
LIN(time0, aux0, time1, aux1, time);
2561 const double aux00 =
NN(lons[ix], array0[ix][iy],
2562 lons[ix + 1], array0[ix + 1][iy], lon2);
2563 const double aux01 =
NN(lons[ix], array0[ix][iy + 1],
2564 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
2565 const double aux0 =
NN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
2567 const double aux10 =
NN(lons[ix], array1[ix][iy],
2568 lons[ix + 1], array1[ix + 1][iy], lon2);
2569 const double aux11 =
NN(lons[ix], array1[ix][iy + 1],
2570 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
2571 const double aux1 =
NN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
2573 *var =
NN(time0, aux0, time1, aux1, time);
2598 const time_t jsec0 = (time_t) jsec + timegm(&t0);
2599 t1 = gmtime(&jsec0);
2601 *year = t1->tm_year + 1900;
2602 *mon = t1->tm_mon + 1;
2604 *hour = t1->tm_hour;
2607 *remain = jsec - floor(jsec);
2613 const double kz[
EP],
2614 const double kw[
EP],
2623 const double z =
Z(p);
2628 else if (z > kz[nk - 1])
2632 return LIN(kz[idx], kw[idx], kz[idx + 1], kw[idx + 1], z);
2649 const double a =
RA *
SQR(t), r =
SH(h2o) / (1. -
SH(h2o));
2663 const double press[138] = {
2664 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
2665 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
2666 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
2667 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
2668 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2669 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
2670 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
2671 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
2672 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
2673 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
2674 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
2675 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
2676 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
2677 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
2678 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
2679 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
2680 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
2681 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
2682 1010.8487, 1013.2500, 1044.45
2685 for (
int ip = 0; ip < ctl->
met_np; ip++)
2692 const double press[92] = {
2693 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
2694 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
2695 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
2696 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
2697 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
2699 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
2700 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
2701 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
2702 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
2703 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
2704 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
2705 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
2706 1007.4431, 1010.8487, 1013.2500, 1044.45
2709 for (
int ip = 0; ip < ctl->
met_np; ip++)
2716 const double press[60] = {
2717 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
2718 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
2719 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
2720 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
2721 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
2722 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
2723 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
2724 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1044.45
2727 for (
int ip = 0; ip < ctl->
met_np; ip++)
2734 const double press[147] = {
2735 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
2736 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
2737 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
2738 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
2739 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2740 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
2741 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
2742 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
2743 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
2744 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
2745 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
2746 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
2747 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
2748 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
2749 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
2750 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
2751 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
2752 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
2753 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73, 1028.85,
2755 1035.09, 1038.21, 1041.33, 1044.45
2758 for (
int ip = 0; ip < ctl->
met_np; ip++)
2765 const double press[101] = {
2766 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
2767 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
2768 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
2769 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
2770 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
2772 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
2773 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
2774 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
2775 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
2776 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
2777 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
2778 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
2779 1007.4431, 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73,
2781 1035.09, 1038.21, 1041.33, 1044.45
2784 for (
int ip = 0; ip < ctl->
met_np; ip++)
2791 const double press[62] = {
2792 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
2793 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
2794 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
2795 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
2796 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
2797 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
2798 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
2799 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1034.86, 1039.65,
2803 for (
int ip = 0; ip < ctl->
met_np; ip++)
2810 const double press[137] = {
2811 0.01, 0.02, 0.031, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861,
2812 0.2499, 0.3299, 0.4288, 0.5496, 0.6952, 0.869, 1.0742,
2813 1.3143, 1.5928, 1.9134, 2.2797, 2.6954, 3.1642, 3.6898,
2814 4.2759, 4.9262, 5.6441, 6.4334, 7.2974, 8.2397, 9.2634,
2815 10.372, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945, 18.9752,
2816 20.761, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2817 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.199, 54.5299,
2818 57.9834, 61.5607, 65.2695, 69.1187, 73.1187, 77.281, 81.6182,
2819 86.145, 90.8774, 95.828, 101.005, 106.415, 112.068, 117.971,
2820 124.134, 130.564, 137.27, 144.262, 151.549, 159.14, 167.045,
2821 175.273, 183.834, 192.739, 201.997, 211.619, 221.615, 231.995,
2822 242.772, 253.955, 265.556, 277.585, 290.055, 302.976, 316.361,
2823 330.22, 344.566, 359.411, 374.767, 390.645, 407.058, 424.019,
2824 441.539, 459.632, 478.31, 497.584, 517.42, 537.72, 558.343,
2825 579.193, 600.167, 621.162, 642.076, 662.808, 683.262, 703.347,
2826 722.979, 742.086, 760.6, 778.466, 795.64, 812.085, 827.776,
2827 842.696, 856.838, 870.2, 882.791, 894.622, 905.712, 916.081,
2828 925.757, 934.767, 943.14, 950.908, 958.104, 965.299, 972.495,
2829 979.69, 986.886, 994.081, 1001.28, 1008.47, 1015.67, 1022.86,
2830 1030.06, 1037.25, 1044.45
2833 for (
int ip = 0; ip < ctl->
met_np; ip++)
2840 const double press[59] = {
2841 0.1, 0.2, 0.3843, 0.6365, 0.9564, 1.3448, 1.8058, 2.3478,
2842 2.985, 3.7397, 4.6462, 5.7565, 7.1322, 8.8366, 10.9483,
2843 13.5647, 16.8064, 20.8227, 25.7989, 31.9642, 39.6029, 49.0671,
2844 60.1802, 73.0663, 87.7274, 104.229, 122.614, 142.902, 165.089,
2845 189.147, 215.025, 242.652, 272.059, 303.217, 336.044, 370.407,
2846 406.133, 443.009, 480.791, 519.209, 557.973, 596.777, 635.306,
2847 673.24, 710.263, 746.063, 780.346, 812.83, 843.263, 871.42,
2848 897.112, 920.189, 940.551, 958.148, 975.744, 993.341, 1010.94,
2852 for (
int ip = 0; ip < ctl->
met_np; ip++)
2856 ERRMSG(
"Use 0 for l137, 1 for l91, 2 for l60 or values between 3 and 7.");
2860 ERRMSG(
"Recompile with larger EP to use this pressure level definition.");
2873 int i = (ihi + ilo) >> 1;
2875 if (xx[i] < xx[i + 1])
2876 while (ihi > ilo + 1) {
2877 i = (ihi + ilo) >> 1;
2883 while (ihi > ilo + 1) {
2884 i = (ihi + ilo) >> 1;
2904 int i = (ihi + ilo) >> 1;
2906 if ((xx[ig] <= x && x < xx[ig + 1]) || (xx[ig] >= x && x > xx[ig + 1]))
2909 if (xx[i] < xx[i + 1])
2910 while (ihi > ilo + 1) {
2911 i = (ihi + ilo) >> 1;
2917 while (ihi > ilo + 1) {
2918 i = (ihi + ilo) >> 1;
2936 const int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
2950 float profiles[
EX][
EY][
EP],
2952 const int lon_ap_ind,
2953 const int lat_ap_ind,
2954 const double height_ap,
2960 np, height_ap, ind[0]);
2962 np, height_ap, ind[1]);
2964 np, height_ap, ind[2]);
2983 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2987 double dts, u[4], um = 0, v[4], vm = 0, w[4], wm = 0,
2991 for (
int i = 0; i < ctl->
advect; i++) {
2996 x[0] = atm->
lon[ip];
2997 x[1] = atm->
lat[ip];
3000 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
3001 x[0] = atm->
lon[ip] +
DX2DEG(dts * u[i - 1] / 1000., atm->
lat[ip]);
3002 x[1] = atm->
lat[ip] +
DY2DEG(dts * v[i - 1] / 1000.);
3003 x[2] = atm->
p[ip] + dts * w[i - 1];
3005 const double tm = atm->
time[ip] + dts;
3010 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3012 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3014 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
3020 met1, met1->
pl, met1->
ul,
3021 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3023 met1, met1->
pl, met1->
vl,
3024 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3026 met1, met1->
pl, met1->
wl,
3027 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
3033 k = (i == 0 ? 0.0 : 1.0);
3034 else if (ctl->
advect == 4)
3035 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
3042 atm->
time[ip] += cache->
dt[ip];
3043 atm->
lon[ip] +=
DX2DEG(cache->
dt[ip] * um / 1000.,
3044 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
3045 atm->
lat[ip] +=
DY2DEG(cache->
dt[ip] * vm / 1000.);
3046 atm->
p[ip] += cache->
dt[ip] * wm;
3058 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3064 atm->
time[ip], atm->
p[ip],
3065 atm->
lon[ip], atm->
lat[ip],
3066 &atm->
q[qnt][ip], ci, cw, 1);
3069 double dts, u[4], um = 0, v[4], vm = 0, wdot[4],
3070 wdotm = 0, x[3] = { 0, 0, 0 };
3073 for (
int i = 0; i < ctl->
advect; i++) {
3078 x[0] = atm->
lon[ip];
3079 x[1] = atm->
lat[ip];
3080 x[2] = atm->
q[qnt][ip];
3082 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
3083 x[0] = atm->
lon[ip] +
DX2DEG(dts * u[i - 1] / 1000., atm->
lat[ip]);
3084 x[1] = atm->
lat[ip] +
DY2DEG(dts * v[i - 1] / 1000.);
3085 x[2] = atm->
q[qnt][ip] + dts * wdot[i - 1];
3088 const double tm = atm->
time[ip] + dts;
3093 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3096 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3099 tm, x[2], x[0], x[1], &wdot[i], ci, cw, 0);
3104 k = (i == 0 ? 0.0 : 1.0);
3105 else if (ctl->
advect == 4)
3106 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
3110 wdotm += k * wdot[i];
3114 atm->
time[ip] += cache->
dt[ip];
3115 atm->
lon[ip] +=
DX2DEG(cache->
dt[ip] * um / 1000.,
3116 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
3117 atm->
lat[ip] +=
DY2DEG(cache->
dt[ip] * vm / 1000.);
3118 atm->
q[qnt][ip] += cache->
dt[ip] * wdotm;
3124 atm->
q[qnt][ip], atm->
lon[ip], atm->
lat[ip],
3125 &atm->
p[ip], ci, cw, 1);
3144 SELECT_TIMER(
"MODULE_ADVECT_INIT",
"PHYSICS", NVTX_GPU);
3153 atm->
lon[ip], atm->
lat[ip], &atm->
p[ip], ci, cw, 1);
3168 SELECT_TIMER(
"MODULE_BOUND_COND",
"PHYSICS", NVTX_GPU);
3178 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3214 if (atm->
p[ip] < pbl)
3266 ERRMSG(
"Molar mass is not defined!");
3272 const int ensemble_mode = (ctl->
nens > 0);
3273 const int np = atm->
np;
3277 const int ngrid = nx * ny * nz;
3278 const int nens = ensemble_mode ? ctl->
nens : 1;
3280 double *restrict
const z = (
double *) malloc((
size_t) nz *
sizeof(double));
3281 double *restrict
const press =
3282 (
double *) malloc((
size_t) nz *
sizeof(double));
3283 double *restrict
const mass =
3284 (
double *) calloc((
size_t) ngrid * (size_t) nens,
sizeof(
double));
3285 double *restrict
const area =
3286 (
double *) malloc((
size_t) ny *
sizeof(double));
3287 double *restrict
const lon =
3288 (
double *) malloc((
size_t) nx *
sizeof(double));
3289 double *restrict
const lat =
3290 (
double *) malloc((
size_t) ny *
sizeof(double));
3292 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
3293 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
3294 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
3303#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])
3304#pragma acc data present(ctl,met0,met1,atm,ixs,iys,izs,z,press,mass,area,lon,lat)
3305#pragma acc parallel loop independent gang vector
3307#pragma omp parallel for default(shared)
3309 for (
int iz = 0; iz < nz; iz++) {
3311 press[iz] =
P(z[iz]);
3315 const double t0 = tt - 0.5 * ctl->
dt_mod;
3316 const double t1 = tt + 0.5 * ctl->
dt_mod;
3320#pragma acc parallel loop independent gang vector
3322#pragma omp parallel for default(shared)
3324 for (
int ip = 0; ip < np; ip++) {
3328 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
3329 || ixs[ip] < 0 || ixs[ip] >= nx
3330 || iys[ip] < 0 || iys[ip] >= ny || izs[ip] < 0 || izs[ip] >= nz)
3336#pragma acc parallel loop independent gang vector
3338#pragma omp parallel for default(shared)
3340 for (
int ix = 0; ix < nx; ix++)
3344#pragma acc parallel loop independent gang vector
3346#pragma omp parallel for default(shared)
3348 for (
int iy = 0; iy < ny; iy++) {
3350 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
3355#pragma acc parallel loop independent gang vector
3357 for (
int ip = 0; ip < np; ip++) {
3359 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
3360 if (ensemble_mode) {
3361 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
3362 mass_idx += ens * ngrid;
3365#pragma acc atomic update
3367 mass[mass_idx] += atm->
q[ctl->
qnt_m][ip];
3373#pragma acc parallel loop independent gang vector
3375#pragma omp parallel for default(shared)
3377 for (
int ip = 0; ip < np; ip++)
3385 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
3388 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
3389 if (ensemble_mode) {
3390 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
3391 mass_idx += ens * ngrid;
3395 const double m = mass[mass_idx];
3397 / (
RHO(press[izs[ip]], temp) * area[iys[ip]] * dz * 1e9);
3402#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
3430 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3447 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
3449 atm->
lat[ip], atm->
p[ip]));
3451 atm->
lat[ip], atm->
p[ip]));
3453 atm->
lat[ip], atm->
p[ip]));
3467 SELECT_TIMER(
"MODULE_CONVECTION",
"PHYSICS", NVTX_GPU);
3473 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3481 double pbot = ps, ptop = ps;
3498 double cape, cin, pel;
3504 if (isfinite(cape) && cape >= ctl->
conv_cape
3506 ptop = GSL_MIN(ptop, pel);
3510 if (ptop != pbot && atm->
p[ip] >= ptop) {
3515 pbot, atm->
lon[ip], atm->
lat[ip], &tbot, ci, cw, 1);
3517 atm->
lon[ip], atm->
lat[ip], &ttop, ci, cw, 1);
3518 const double rhobot = pbot / tbot;
3519 const double rhotop = ptop / ttop;
3522 const double rho = rhobot + (rhotop - rhobot) * cache->
rs[ip];
3525 atm->
p[ip] =
LIN(rhobot, pbot, rhotop, ptop, rho);
3549 dd_sort(ctl, *met, atm, dd, &nparticles, &dd->
rank);
3583 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3586 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,clim,atm)") {
3595 const double aux = exp(-cache->
dt[ip] / tdec);
3596 if (ctl->
qnt_m >= 0) {
3599 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
3600 atm->
q[ctl->
qnt_m][ip] *= aux;
3625 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3633 float umean = 0, usig = 0, vmean = 0, vsig = 0, wmean = 0, wsig = 0;
3634 for (
int i = 0; i < 2; i++)
3635 for (
int j = 0; j < 2; j++)
3636 for (
int k = 0; k < 2; k++) {
3637 umean += met0->
u[ix + i][iy + j][iz + k];
3638 usig +=
SQR(met0->
u[ix + i][iy + j][iz + k]);
3639 vmean += met0->
v[ix + i][iy + j][iz + k];
3640 vsig +=
SQR(met0->
v[ix + i][iy + j][iz + k]);
3641 wmean += met0->
w[ix + i][iy + j][iz + k];
3642 wsig +=
SQR(met0->
w[ix + i][iy + j][iz + k]);
3644 umean += met1->
u[ix + i][iy + j][iz + k];
3645 usig +=
SQR(met1->
u[ix + i][iy + j][iz + k]);
3646 vmean += met1->
v[ix + i][iy + j][iz + k];
3647 vsig +=
SQR(met1->
v[ix + i][iy + j][iz + k]);
3648 wmean += met1->
w[ix + i][iy + j][iz + k];
3649 wsig +=
SQR(met1->
w[ix + i][iy + j][iz + k]);
3651 usig = usig / 16.f -
SQR(umean / 16.f);
3652 usig = (usig > 0 ? sqrtf(usig) : 0);
3653 vsig = vsig / 16.f -
SQR(vmean / 16.f);
3654 vsig = (vsig > 0 ? sqrtf(vsig) : 0);
3655 wsig = wsig / 16.f -
SQR(wmean / 16.f);
3656 wsig = (wsig > 0 ? sqrtf(wsig) : 0);
3659 const double r = 1 - 2 * fabs(cache->
dt[ip]) / ctl->
dt_met;
3660 const double r2 = sqrt(1 - r * r);
3664 cache->
uvwp[ip][0] =
3665 (float) (r * cache->
uvwp[ip][0] +
3670 cache->
uvwp[ip][1] =
3671 (float) (r * cache->
uvwp[ip][1] +
3678 cache->
uvwp[ip][2] =
3679 (float) (r * cache->
uvwp[ip][2] +
3681 atm->
p[ip] += cache->
uvwp[ip][2] * cache->
dt[ip];
3702 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3704 double dsigw_dz = 0.0, sig_u = 0.25, sig_w = 0.1,
3705 tau_u = 300., tau_w = 100.;
3714 if (atm->
p[ip] >= pbl) {
3717 const double p =
MIN(atm->
p[ip], ps);
3718 const double zs =
Z(ps);
3719 const double z = 1e3 * (
Z(p) - zs);
3720 const double zi = 1e3 * (
Z(pbl) - zs);
3721 const double zratio = z / zi;
3724 double ess, nss, h2o, t;
3729 const double rho =
RHO(p,
TVIRT(t, h2o));
3730 const double tau = sqrt(
SQR(ess) +
SQR(nss));
3731 const double ustar = sqrt(tau / rho);
3741 sig_u = 1e-2 + 2.0 * ustar * (1.0 - zratio);
3742 sig_w = 1e-2 + 1.3 * ustar * (1.0 - zratio);
3745 dsigw_dz = -1.3 * ustar / zi;
3748 tau_u = 0.07 * zi / sig_u * sqrt(zratio);
3749 tau_w = 0.1 * zi / sig_w * pow(zratio, 0.8);
3756 const double wstar =
3757 pow(
G0 /
THETAVIRT(p, t, h2o) * shf / (rho *
CPD) * zi, 1. / 3.);
3761 + sqrt(0.4 *
SQR(wstar) + (5.0 - 4.0 * zratio) *
SQR(ustar));
3762 sig_w = 1e-2 + sqrt(1.2 *
SQR(wstar) * (1.0 - 0.9 * zratio)
3763 * pow(zratio, 2.0 / 3.0)
3764 + (1.8 - 1.4 * zratio) *
SQR(ustar));
3767 dsigw_dz = 0.5 / sig_w / zi * (-1.4 *
SQR(ustar) +
SQR(wstar)
3769 pow(
MAX(zratio, 1e-3), -1.0 / 3.0)
3770 - 1.8 * pow(zratio, 2.0 / 3.0)));
3773 const double C0 = 3.0;
3775 (1.5 - 1.2 * pow(zratio, 1.0 / 3.0)) *
SQR(wstar) * wstar / zi
3776 +
SQR(ustar) * ustar * (1.0 - 0.8 * zratio) / (
KARMAN * z);
3777 tau_u = 2 *
SQR(sig_u) / (C0 * eps);
3778 tau_w = 2 *
SQR(sig_w) / (C0 * eps);
3783 sig_u =
MAX(sig_u, 0.25);
3784 sig_w =
MAX(sig_w, 0.1);
3785 tau_u =
MAX(tau_u, 300.);
3786 tau_w =
MAX(tau_w, 100.);
3789 const double ru = exp(-fabs(cache->
dt[ip]) / tau_u);
3790 const double ru2 = sqrt(1.0 -
SQR(ru));
3792 = (float) (cache->
uvwp[ip][0] * ru + ru2 * cache->
rs[3 * ip]);
3794 = (float) (cache->
uvwp[ip][1] * ru + ru2 * cache->
rs[3 * ip + 1]);
3796 const double rw = exp(-fabs(cache->
dt[ip]) / tau_w);
3797 const double rw2 = sqrt(1.0 -
SQR(rw));
3799 = (float) (cache->
uvwp[ip][2] * rw + rw2 * cache->
rs[3 * ip + 2]
3800 + sig_w * dsigw_dz * cache->
dt[ip]);
3807 DZ2DP(cache->
uvwp[ip][2] * cache->
dt[ip] / 1000., atm->
p[ip]);
3829 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3838 const double wpbl =
pbl_weight(ctl, atm, ip, pbl, ps);
3839 const double wtrop =
tropo_weight(clim, atm, ip) * (1.0 - wpbl);
3840 const double wstrat = 1.0 - wpbl - wtrop;
3850 const double sigma = sqrt(2.0 * dx * fabs(cache->
dt[ip])) / 1000.;
3852 atm->
lat[ip] +=
DY2DEG(cache->
rs[3 * ip + 1] * sigma);
3857 const double sigma = sqrt(2.0 * dz * fabs(cache->
dt[ip])) / 1000.;
3858 atm->
p[ip] +=
DZ2DP(cache->
rs[3 * ip + 2] * sigma, atm->
p[ip]);
3877 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3880 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3892 const double dz = 1000. * (
Z(ps - ctl->
dry_depo_dp) -
Z(ps));
3912 const double aux = exp(-cache->
dt[ip] * v_dep / dz);
3913 if (ctl->
qnt_m >= 0) {
3916 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
3917 atm->
q[ctl->
qnt_m][ip] *= aux;
3941 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3944 const double a = 3.12541941e-06;
3945 const double b = -5.72532259e-01;
3946 const double low = pow(1. / a, 1. / b);
3949 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3956 if (!(lwc > 0 || rwc > 0))
3967 const double k = 9.1e7 * exp(-29700. /
RI * (1. / t - 1. / 298.15));
3970 const double H_SO2 =
3971 1.3e-2 * exp(2900. * (1. / t - 1. / 298.15)) *
RI * t;
3972 const double K_1S = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
3975 const double H_h2o2 =
3976 8.3e2 * exp(7600. * (1. / t - 1. / 298.15)) *
RI * t;
3982 cor = atm->
q[ctl->
qnt_Cx][ip] >
3983 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
3985 const double h2o2 = H_h2o2
3987 * M * cor * 1000. /
AVO;
3990 const double rho_air = atm->
p[ip] / (
RI * t) *
MA / 10.;
3991 const double CWC = (lwc + rwc) * rho_air / 1e3;
3994 const double rate_coef = k * K_1S * h2o2 * H_SO2 * CWC;
3995 const double aux = exp(-cache->
dt[ip] * rate_coef);
3996 if (ctl->
qnt_m >= 0) {
3999 atm->
q[ctl->
qnt_m][ip] *= aux;
4020 SELECT_TIMER(
"MODULE_ISOSURF_INIT",
"PHYSICS", NVTX_GPU);
4031 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
4034 cache->
iso_var[ip] = atm->
p[ip] / t;
4040 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
4051 LOG(1,
"Read balloon pressure data: %s", ctl->
balloon);
4055 if (!(in = fopen(ctl->
balloon,
"r")))
4056 ERRMSG(
"Cannot open file!");
4060 while (fgets(line,
LEN, in))
4061 if (sscanf(line,
"%lg %lg", &(cache->
iso_ts[cache->
iso_n]),
4064 ERRMSG(
"Too many data points!");
4067 if (cache->
iso_n < 1)
4068 ERRMSG(
"Could not read any data!");
4091 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,met1,atm)") {
4104 atm->
p[ip] = cache->
iso_var[ip] * t;
4110 atm->
p[ip] = 1000. * pow(cache->
iso_var[ip] / t, -1. / 0.286);
4116 atm->
p[ip] = cache->
iso_ps[0];
4144 const int nvar = NVAR, nfix = NFIX, nreact = NREACT;
4145 double rtol[1] = { 1.0e-3 };
4146 double atol[1] = { 1.0 };
4150#pragma acc data copy(rtol,atol,nvar,nfix,nreact)
4153 "acc data present(ctl,cache,clim,met0,met1,atm) ") {
4156 double var[nvar], fix[nfix], rconst[nreact];
4157 for (
int i = 0; i < nvar; i++)
4159 for (
int i = 0; i < nfix; i++)
4161 for (
int i = 0; i < nreact; i++)
4163 kpp_chem_initialize(ctl, clim, met0, met1, atm, var, fix, rconst, ip);
4168 for (
int i = 0; i < 20; i++) {
4175 Rosenbrock(var, fix, rconst, 0, ctl->
dt_kpp,
4176 atol, rtol, &FunTemplate, &JacTemplate, rpar, ipar);
4179 kpp_chem_output2atm(atm, ctl, met0, met1, var, ip);
4200 ERRMSG(
"Need T_ice and T_NAT to calculate T_STS!");
4204 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4206 double ps, ts, zs, us, vs, ess, nss, shf, lsm, sst, pbl, pt, pct, pcb,
4207 cl, plcl, plfc, pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot,
4208 o3, lwc, rwc, iwc, swc, cc, z, zt;
4256 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
4258 atm->
lat[ip], atm->
p[ip]));
4260 atm->
lat[ip], atm->
p[ip]));
4262 atm->
lat[ip], atm->
p[ip]));
4263 SET_ATM(qnt_vh, sqrt(u * u + v * v));
4285 atm->
lat[ip], atm->
p[ip])));
4303 const int np = atm->
np;
4304 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
4305 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
4306 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
4314 const double t0 = t - 0.5 * ctl->
dt_mod;
4315 const double t1 = t + 0.5 * ctl->
dt_mod;
4319#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
4320#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
4321#pragma acc parallel loop independent gang vector
4323#pragma omp parallel for default(shared)
4325 for (
int ip = 0; ip < np; ip++) {
4328 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
mixing_z0) / dz);
4329 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
4330 || ixs[ip] < 0 || ixs[ip] >= ctl->
mixing_nx
4331 || iys[ip] < 0 || iys[ip] >= ctl->
mixing_ny
4332 || izs[ip] < 0 || izs[ip] >= ctl->
mixing_nz)
4337 const int use_ensemble = (ctl->
nens > 0);
4339 const int quantities[] = {
4346 const int n_qnt =
sizeof(quantities) /
sizeof(quantities[0]);
4348 for (
int i = 0; i < n_qnt; i++)
4349 if (quantities[i] >= 0)
4355#pragma acc exit data delete(ixs,iys,izs)
4372 const int use_ensemble) {
4374 const int np = atm->
np;
4376 const int nens = use_ensemble ? ctl->
nens : 1;
4377 const int total_grid = ngrid * nens;
4379 double *restrict
const cmean =
4380 (
double *) malloc((
size_t) total_grid *
sizeof(double));
4381 int *restrict
const count =
4382 (
int *) malloc((
size_t) total_grid *
sizeof(int));
4386#pragma acc enter data create(cmean[0:total_grid],count[0:total_grid])
4387#pragma acc data present(ctl,clim,atm,ixs,iys,izs,cmean,count)
4388#pragma acc parallel loop independent gang vector
4393#pragma omp parallel for
4395 for (
int i = 0; i < total_grid; i++) {
4402#pragma acc parallel loop independent gang vector
4404 for (
int ip = 0; ip < np; ip++)
4406 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
4411#pragma acc atomic update
4413 cmean[idx] += atm->
q[qnt_idx][ip];
4415#pragma acc atomic update
4422#pragma acc parallel loop independent gang vector
4427#pragma omp parallel for
4429 for (
int i = 0; i < total_grid; i++)
4431 cmean[i] /= count[i];
4435#pragma acc parallel loop independent gang vector
4437#pragma omp parallel for
4439 for (
int ip = 0; ip < np; ip++) {
4441 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
4443 double mixparam = 1.0;
4452 atm->
q[qnt_idx][ip] += (cmean[idx] - atm->
q[qnt_idx][ip]) * mixparam;
4458#pragma acc exit data delete(cmean,count)
4479 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4482 const double a = 4.71572206e-08;
4483 const double b = -8.28782867e-01;
4484 const double low = pow(1. / a, 1. / b);
4488 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4514 0 ? pow(298. / t, ctl->
oh_chem[1]) : 1.);
4517 0 ? pow(298. / t, ctl->
oh_chem[3]) : 1.);
4518 const double c = log10(k0 * M / ki);
4519 k = k0 * M / (1. + k0 * M / ki) * pow(0.6, 1. / (1. + c * c));
4528 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
4531 const double rate_coef =
4533 atm->
lat[ip], atm->
p[ip]) * M * cor;
4534 const double aux = exp(-cache->
dt[ip] * rate_coef);
4535 if (ctl->
qnt_m >= 0) {
4538 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
4539 atm->
q[ctl->
qnt_m][ip] *= aux;
4560 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(cache,met0,met1,atm)") {
4571 while (atm->
lat[ip] < -90 || atm->
lat[ip] > 90) {
4572 if (atm->
lat[ip] > 90) {
4573 atm->
lat[ip] = 180 - atm->
lat[ip];
4574 atm->
lon[ip] += 180;
4576 if (atm->
lat[ip] < -90) {
4577 atm->
lat[ip] = -180 - atm->
lat[ip];
4578 atm->
lon[ip] += 180;
4583 while (atm->
lon[ip] < -180)
4584 atm->
lon[ip] += 360;
4585 while (atm->
lon[ip] >= 180)
4586 atm->
lon[ip] -= 360;
4589 if (atm->
p[ip] < met0->
p[met0->
np - 1]) {
4590 atm->
p[ip] = met0->
p[met0->
np - 1];
4591 }
else if (atm->
p[ip] > 300.) {
4593 if (atm->
p[ip] > ps)
4605 gsl_rng_env_setup();
4606 if (omp_get_max_threads() >
NTHREADS)
4607 ERRMSG(
"Too many threads!");
4608 for (
int i = 0; i <
NTHREADS; i++) {
4609 rng[i] = gsl_rng_alloc(gsl_rng_default);
4610 gsl_rng_set(rng[i], gsl_rng_default_seed
4611 + (
long unsigned) (ntask *
NTHREADS + i));
4616 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
4617 CURAND_STATUS_SUCCESS)
4618 ERRMSG(
"Cannot create random number generator!");
4619 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
4620 CURAND_STATUS_SUCCESS)
4621 ERRMSG(
"Cannot set seed for random number generator!");
4624 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
4625 CURAND_STATUS_SUCCESS)
4626 ERRMSG(
"Cannot set stream for random number generator!");
4643#pragma omp parallel for default(shared)
4644 for (
size_t i = 0; i < n; ++i)
4645 rs[i] = gsl_rng_uniform(rng[omp_get_thread_num()]);
4649 else if (method == 1) {
4650#pragma omp parallel for default(shared)
4651 for (
size_t i = 0; i < n; ++i)
4652 rs[i] = gsl_ran_gaussian_ziggurat(rng[omp_get_thread_num()], 1.0);
4658#pragma acc update device(rs[:n])
4666 const uint64_t key = 0xc8e4fd154ce32f6d;
4670#pragma acc data present(rs)
4671#pragma acc parallel loop independent gang vector
4673#pragma omp parallel for default(shared)
4675 for (
size_t i = 0; i < n + 1; ++i) {
4676 uint64_t r, t, x, y, z;
4677 y = x = (rng_ctr + i) * key;
4680 x = (x >> 32) | (x << 32);
4682 x = (x >> 32) | (x << 32);
4684 x = (x >> 32) | (x << 32);
4686 x = (x >> 32) | (x << 32);
4687 r = t ^ ((x * x + y) >> 32);
4688 rs[i] = (double) r / (
double) UINT64_MAX;
4695#pragma acc parallel loop independent gang vector
4697#pragma omp parallel for default(shared)
4699 for (
size_t i = 0; i < n; i += 2) {
4700 const double r = sqrt(-2.0 * log(rs[i]));
4701 const double phi = 2.0 * M_PI * rs[i + 1];
4702 rs[i] = r * cosf((
float) phi);
4703 rs[i + 1] = r * sinf((
float) phi);
4711#pragma acc host_data use_device(rs)
4716 if (curandGenerateUniformDouble(rng_curand, rs, (n < 4 ? 4 : n)) !=
4717 CURAND_STATUS_SUCCESS)
4718 ERRMSG(
"Cannot create random numbers!");
4722 else if (method == 1) {
4723 if (curandGenerateNormalDouble
4724 (rng_curand, rs, (n < 4 ? 4 : n), 0.0,
4725 1.0) != CURAND_STATUS_SUCCESS)
4726 ERRMSG(
"Cannot create random numbers!");
4730 ERRMSG(
"MPTRAC was compiled without cuRAND!");
4748 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4756 const double v_s =
sedi(atm->
p[ip], t, atm->
q[ctl->
qnt_rp][ip],
4760 atm->
p[ip] +=
DZ2DP(v_s * cache->
dt[ip] / 1000., atm->
p[ip]);
4775 const int np = atm->
np;
4776 double *restrict
const a = (
double *) malloc((
size_t) np *
sizeof(double));
4777 int *restrict
const p = (
int *) malloc((
size_t) np *
sizeof(int));
4778 if (a == NULL || p == NULL)
4779 ERRMSG(
"Out of memory!");
4782#pragma acc enter data create(a[0:np],p[0:np])
4783#pragma acc data present(ctl,met0,atm,a,p)
4788#pragma acc parallel loop independent gang vector
4790#pragma omp parallel for default(shared)
4792 for (
int ip = 0; ip < np; ip++) {
4803#pragma acc host_data use_device(a,p)
4805 thrustSortWrapper(a, np, p);
4808 ERRMSG(
"GSL sort fallback not available on GPU, use THRUST!");
4810 gsl_sort_index((
size_t *) p, a, 1, (
size_t) np);
4818 for (
int iq = 0; iq < ctl->
nq; iq++)
4823#pragma acc exit data delete(a,p)
4837 double *restrict
const help =
4838 (
double *) malloc((
size_t) np *
sizeof(double));
4840 ERRMSG(
"Out of memory!");
4844#pragma acc enter data create(help[0:np])
4845#pragma acc data present(a,p,help)
4846#pragma acc parallel loop independent gang vector
4848#pragma omp parallel for default(shared)
4850 for (
int ip = 0; ip < np; ip++)
4851 help[ip] = a[p[ip]];
4853#pragma acc parallel loop independent gang vector
4855#pragma omp parallel for default(shared)
4857 for (
int ip = 0; ip < np; ip++)
4862#pragma acc exit data delete(help)
4879 const double latmin = gsl_stats_min(met0->
lat, 1, (
size_t) met0->
ny),
4880 latmax = gsl_stats_max(met0->
lat, 1, (
size_t) met0->
ny);
4883 (fabs(met0->
lon[met0->
nx - 1] - met0->
lon[0] - 360.0) >= 0.01);
4886 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,atm)") {
4892 cache->
dt[ip] = t - atm->
time[ip];
4894 cache->
dt[ip] = 0.0;
4903 if (local && (atm->
lon[ip] <= met0->
lon[0]
4904 || atm->
lon[ip] >= met0->
lon[met0->
nx - 1]
4905 || atm->
lat[ip] <= latmin || atm->
lat[ip] >= latmax))
4906 cache->
dt[ip] = 0.0;
4921 SELECT_TIMER(
"MODULE_TIMESTEPS_INIT",
"PHYSICS", NVTX_GPU);
4925 ctl->
t_start = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
4927 ctl->
t_stop = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
4929 ctl->
t_start = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
4931 ctl->
t_stop = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
4936 ERRMSG(
"Nothing to do! Check T_STOP and DIRECTION!");
4956 SELECT_TIMER(
"MODULE_TRACER_CHEM",
"PHYSICS", NVTX_GPU);
4960 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4984 const double K_o1d =
ARRHENIUS(3.30e-10, 0, t) * o1d * M;
4986 atm->
p[ip], sza, o3c);
4987 atm->
q[ctl->
qnt_Cccl4][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4992 const double K_o1d =
ARRHENIUS(2.30e-10, 0, t) * o1d * M;
4994 atm->
p[ip], sza, o3c);
4995 atm->
q[ctl->
qnt_Cccl3f][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5000 const double K_o1d =
ARRHENIUS(1.40e-10, -25, t) * o1d * M;
5002 atm->
p[ip], sza, o3c);
5003 atm->
q[ctl->
qnt_Cccl2f2][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5008 const double K_o1d =
ARRHENIUS(1.19e-10, -20, t) * o1d * M;
5010 atm->
p[ip], sza, o3c);
5011 atm->
q[ctl->
qnt_Cn2o][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5030 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
5033 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
5039 if (!isfinite(pct) || atm->
p[ip] <= pct)
5055 double lwc, rwc, iwc, swc;
5060 const int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
5074 else if (t <= 238.15)
5094 const double K_1 = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
5095 const double K_2 = 6e-8 * exp(1.12e3 * (1. / t - 1. / 298.15));
5096 h *= (1. + K_1 / H_ion + K_1 * K_2 /
SQR(H_ion));
5100 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
5103 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
5129 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
5132 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
5137 const double aux = exp(-cache->
dt[ip] * lambda);
5138 if (ctl->
qnt_m >= 0) {
5141 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
5142 atm->
q[ctl->
qnt_m][ip] *= aux;
5167 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
5169 if (acc_get_num_devices(acc_device_nvidia) <= 0)
5170 ERRMSG(
"Not running on a GPU device!");
5171 acc_set_device_num(rank % acc_get_num_devices(acc_device_nvidia),
5173 acc_device_t device_type = acc_get_device_type();
5174 acc_init(device_type);
5189 SELECT_TIMER(
"CREATE_DATA_REGION",
"MEMORY", NVTX_GPU);
5190 ctl_t *ctlup = *ctl;
5193 met_t *met0up = *met0;
5194 met_t *met1up = *met1;
5195 atm_t *atmup = *atm;
5196#pragma acc enter data create(ctlup[:1],cacheup[:1],climup[:1],met0up[:1],met1up[:1],atmup[:1])
5199#pragma acc enter data create(ddup[:1])
5217 SELECT_TIMER(
"DELETE_DATA_REGION",
"MEMORY", NVTX_GPU);
5218#pragma acc exit data delete (ctl,cache,clim,met0,met1,atm)
5232 MPI_Type_free(&dd->MPI_Particle);
5251 char cachefile[
LEN], cmd[2 *
LEN], filename[
LEN];
5257 if (t == ctl->
t_start || !init) {
5264 ERRMSG(
"Cannot open file!");
5269 ERRMSG(
"Cannot open file!");
5279 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5280 LOG(1,
"Caching: %s", cachefile);
5281 if (system(cmd) != 0)
5282 WARN(
"Caching command failed!");
5287 if (t > (*met1)->time) {
5297 ERRMSG(
"Cannot open file!");
5307 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5308 LOG(1,
"Caching: %s", cachefile);
5309 if (system(cmd) != 0)
5310 WARN(
"Caching command failed!");
5315 if (t < (*met0)->time) {
5325 ERRMSG(
"Cannot open file!");
5335 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5336 LOG(1,
"Caching: %s", cachefile);
5337 if (system(cmd) != 0)
5338 WARN(
"Caching command failed!");
5343 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
5344 if ((*met0)->nx != (*met1)->nx
5345 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
5346 ERRMSG(
"Meteo grid dimensions do not match!");
5347 for (
int ix = 0; ix < (*met0)->nx; ix++)
5348 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
5349 ERRMSG(
"Meteo grid longitudes do not match!");
5350 for (
int iy = 0; iy < (*met0)->ny; iy++)
5351 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
5352 ERRMSG(
"Meteo grid latitudes do not match!");
5353 for (
int ip = 0; ip < (*met0)->np; ip++)
5354 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
5355 ERRMSG(
"Meteo grid pressure levels do not match!");
5381 const char *filename,
5394 LOG(1,
"Read atmospheric data: %s", filename);
5414 ERRMSG(
"Atmospheric data type not supported!");
5422 ERRMSG(
"Can not read any data!");
5426 LOG(2,
"Number of particles: %d", atm->
np);
5427 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
5428 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
5429 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
5430 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
5431 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
5432 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
5433 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
5434 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
5435 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
5436 for (
int iq = 0; iq < ctl->
nq; iq++) {
5438 sprintf(msg,
"Quantity %s range: %s ... %s %s",
5441 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
5442 LOG(2, msg, mini, maxi);
5512 const char *filename,
5521 LOG(1,
"\nMassive-Parallel Trajectory Calculations (MPTRAC)\n"
5522 "(executable: %s | version: %s | compiled: %s, %s)\n",
5523 argv[0], VERSION, __DATE__, __TIME__);
5627 ctl->
nq = (int)
scan_ctl(filename, argc, argv,
"NQ", -1,
"0", NULL);
5629 ERRMSG(
"Too many quantities!");
5630 for (
int iq = 0; iq < ctl->
nq; iq++) {
5636 scan_ctl(filename, argc, argv,
"QNT_FORMAT", iq,
"%g",
5638 if (strcasecmp(ctl->
qnt_name[iq],
"aoa") == 0)
5642 SET_QNT(qnt_idx,
"idx",
"particle index",
"-")
5643 SET_QNT(qnt_ens,
"ens",
"ensemble index",
"-")
5644 SET_QNT(qnt_stat,
"stat",
"station flag",
"-")
5645 SET_QNT(qnt_m,
"m",
"mass",
"kg")
5646 SET_QNT(qnt_vmr,
"vmr",
"volume mixing ratio",
"ppv")
5647 SET_QNT(qnt_rp,
"rp",
"particle radius",
"microns")
5648 SET_QNT(qnt_rhop,
"rhop",
"particle density",
"kg/m^3")
5649 SET_QNT(qnt_ps,
"ps",
"surface pressure",
"hPa")
5650 SET_QNT(qnt_ts,
"ts",
"surface temperature",
"K")
5651 SET_QNT(qnt_zs,
"zs",
"surface height",
"km")
5652 SET_QNT(qnt_us,
"us",
"surface zonal wind",
"m/s")
5653 SET_QNT(qnt_vs,
"vs",
"surface meridional wind",
"m/s")
5654 SET_QNT(qnt_ess,
"ess",
"eastward turbulent surface stress",
"N/m^2")
5655 SET_QNT(qnt_nss,
"nss",
"northward turbulent surface stress",
"N/m^2")
5656 SET_QNT(qnt_shf,
"shf",
"surface sensible heat flux",
"W/m^2")
5657 SET_QNT(qnt_lsm,
"lsm",
"land-sea mask",
"1")
5658 SET_QNT(qnt_sst,
"sst",
"sea surface temperature",
"K")
5659 SET_QNT(qnt_pbl,
"pbl",
"planetary boundary layer",
"hPa")
5660 SET_QNT(qnt_pt,
"pt",
"tropopause pressure",
"hPa")
5661 SET_QNT(qnt_tt,
"tt",
"tropopause temperature",
"K")
5662 SET_QNT(qnt_zt,
"zt",
"tropopause geopotential height",
"km")
5663 SET_QNT(qnt_h2ot,
"h2ot",
"tropopause water vapor",
"ppv")
5664 SET_QNT(qnt_zg,
"zg",
"geopotential height",
"km")
5665 SET_QNT(qnt_p,
"p",
"pressure",
"hPa")
5666 SET_QNT(qnt_t,
"t",
"temperature",
"K")
5667 SET_QNT(qnt_rho,
"rho",
"air density",
"kg/m^3")
5668 SET_QNT(qnt_u,
"u",
"zonal wind",
"m/s")
5669 SET_QNT(qnt_v,
"v",
"meridional wind",
"m/s")
5670 SET_QNT(qnt_w,
"w",
"vertical velocity",
"hPa/s")
5671 SET_QNT(qnt_h2o,
"h2o",
"water vapor",
"ppv")
5672 SET_QNT(qnt_o3,
"o3",
"ozone",
"ppv")
5673 SET_QNT(qnt_lwc,
"lwc",
"cloud liquid water content",
"kg/kg")
5674 SET_QNT(qnt_rwc,
"rwc",
"cloud rain water content",
"kg/kg")
5675 SET_QNT(qnt_iwc,
"iwc",
"cloud ice water content",
"kg/kg")
5676 SET_QNT(qnt_swc,
"swc",
"cloud snow water content",
"kg/kg")
5677 SET_QNT(qnt_cc,
"cc",
"cloud cover",
"1")
5678 SET_QNT(qnt_pct,
"pct",
"cloud top pressure",
"hPa")
5679 SET_QNT(qnt_pcb,
"pcb",
"cloud bottom pressure",
"hPa")
5680 SET_QNT(qnt_cl,
"cl",
"total column cloud water",
"kg/m^2")
5681 SET_QNT(qnt_plcl,
"plcl",
"lifted condensation level",
"hPa")
5682 SET_QNT(qnt_plfc,
"plfc",
"level of free convection",
"hPa")
5683 SET_QNT(qnt_pel,
"pel",
"equilibrium level",
"hPa")
5684 SET_QNT(qnt_cape,
"cape",
"convective available potential energy",
5686 SET_QNT(qnt_cin,
"cin",
"convective inhibition",
"J/kg")
5687 SET_QNT(qnt_o3c,
"o3c",
"total column ozone",
"DU")
5688 SET_QNT(qnt_hno3,
"hno3",
"nitric acid",
"ppv")
5689 SET_QNT(qnt_oh,
"oh",
"hydroxyl radical",
"ppv")
5690 SET_QNT(qnt_h2o2,
"h2o2",
"hydrogen peroxide",
"ppv")
5691 SET_QNT(qnt_ho2,
"ho2",
"hydroperoxyl radical",
"ppv")
5692 SET_QNT(qnt_o1d,
"o1d",
"atomic oxygen",
"ppv")
5693 SET_QNT(qnt_mloss_oh,
"mloss_oh",
"mass loss due to OH chemistry",
"kg")
5694 SET_QNT(qnt_mloss_h2o2,
"mloss_h2o2",
5695 "mass loss due to H2O2 chemistry",
"kg")
5696 SET_QNT(qnt_mloss_kpp,
"mloss_kpp",
"mass loss due to kpp chemistry",
5698 SET_QNT(qnt_mloss_wet,
"mloss_wet",
"mass loss due to wet deposition",
5700 SET_QNT(qnt_mloss_dry,
"mloss_dry",
"mass loss due to dry deposition",
5702 SET_QNT(qnt_mloss_decay,
"mloss_decay",
5703 "mass loss due to exponential decay",
"kg")
5704 SET_QNT(qnt_loss_rate,
"loss_rate",
"total loss rate",
"s^-1")
5705 SET_QNT(qnt_psat,
"psat",
"saturation pressure over water",
"hPa")
5706 SET_QNT(qnt_psice,
"psice",
"saturation pressure over ice",
"hPa")
5707 SET_QNT(qnt_pw,
"pw",
"partial water vapor pressure",
"hPa")
5708 SET_QNT(qnt_sh,
"sh",
"specific humidity",
"kg/kg")
5709 SET_QNT(qnt_rh,
"rh",
"relative humidity",
"%%")
5710 SET_QNT(qnt_rhice,
"rhice",
"relative humidity over ice",
"%%")
5711 SET_QNT(qnt_theta,
"theta",
"potential temperature",
"K")
5712 SET_QNT(qnt_zeta,
"zeta",
"zeta coordinate",
"K")
5713 SET_QNT(qnt_zeta_d,
"zeta_d",
"diagnosed zeta coordinate",
"K")
5714 SET_QNT(qnt_zeta_dot,
"zeta_dot",
"velocity of zeta coordinate",
5716 SET_QNT(qnt_eta,
"eta",
"eta coordinate",
"1")
5717 SET_QNT(qnt_eta_dot,
"eta_dot",
"velocity of eta coordinate",
"1/s")
5718 SET_QNT(qnt_tvirt,
"tvirt",
"virtual temperature",
"K")
5719 SET_QNT(qnt_lapse,
"lapse",
"temperature lapse rate",
"K/km")
5720 SET_QNT(qnt_vh,
"vh",
"horizontal velocity",
"m/s")
5721 SET_QNT(qnt_vz,
"vz",
"vertical velocity",
"m/s")
5722 SET_QNT(qnt_pv,
"pv",
"potential vorticity",
"PVU")
5723 SET_QNT(qnt_tdew,
"tdew",
"dew point temperature",
"K")
5724 SET_QNT(qnt_tice,
"tice",
"frost point temperature",
"K")
5725 SET_QNT(qnt_tsts,
"tsts",
"STS existence temperature",
"K")
5726 SET_QNT(qnt_tnat,
"tnat",
"NAT existence temperature",
"K")
5727 SET_QNT(qnt_Cx,
"Cx",
"Trace species x volume mixing ratio",
"ppv")
5728 SET_QNT(qnt_Ch2o,
"Ch2o",
"H2O volume mixing ratio",
"ppv")
5729 SET_QNT(qnt_Co3,
"Co3",
"O3 volume mixing ratio",
"ppv")
5730 SET_QNT(qnt_Cco,
"Cco",
"CO volume mixing ratio",
"ppv")
5731 SET_QNT(qnt_Coh,
"Coh",
"HO volume mixing ratio",
"ppv")
5732 SET_QNT(qnt_Ch,
"Ch",
"H radical volume mixing ratio",
"ppv")
5733 SET_QNT(qnt_Cho2,
"Cho2",
"HO2 volume mixing ratio",
"ppv")
5734 SET_QNT(qnt_Ch2o2,
"Ch2o2",
"H2O2 volume mixing ratio",
"ppv")
5735 SET_QNT(qnt_Co1d,
"Co1d",
"O(1D) volume mixing ratio",
"ppv")
5736 SET_QNT(qnt_Co3p,
"Co3p",
"O(3P) radical volume mixing ratio",
"ppv")
5737 SET_QNT(qnt_Cccl4,
"Cccl4",
"CCl4 (CFC-10) volume mixing ratio",
"ppv")
5738 SET_QNT(qnt_Cccl3f,
"Cccl3f",
"CCl3F (CFC-11) volume mixing ratio",
5740 SET_QNT(qnt_Cccl2f2,
"Cccl2f2",
"CCl2F2 (CFC-12) volume mixing ratio",
5742 SET_QNT(qnt_Cn2o,
"Cn2o",
"N2O volume mixing ratio",
"ppv")
5743 SET_QNT(qnt_Csf6,
"Csf6",
"SF6 volume mixing ratio",
"ppv")
5744 SET_QNT(qnt_aoa,
"aoa",
"age of air",
"s")
5746 SET_QNT(qnt_destination,
"destination",
5747 "subdomain index of destination",
"-")
5748 SET_QNT(qnt_subdomain,
"subdomain",
"current subdomain index",
"-")
5755 (int)
scan_ctl(filename, argc, argv,
"ADVECT_VERT_COORD", -1,
"0", NULL);
5757 ERRMSG(
"ADVECT_VERT_COORD must be 0, 1, 2, or 3!");
5760 ERRMSG(
"Add quantity zeta for diabatic advection!");
5762 ERRMSG(
"Add quantity eta for etadot avection!");
5765 (int)
scan_ctl(filename, argc, argv,
"MET_VERT_COORD", -1,
"0", NULL);
5767 ERRMSG(
"MET_VERT_COORD must be 0, 1, 2, 3, or 4!");
5771 (
"Using ADVECT_VERT_COORD = 2 requires meteo data on model levels!");
5774 (
"Using ADVECT_VERT_COORD = 3 requires A and B model level coefficients!");
5778 (int)
scan_ctl(filename, argc, argv,
"DIRECTION", -1,
"1", NULL);
5780 ERRMSG(
"Set DIRECTION to -1 or 1!");
5781 ctl->
t_stop =
scan_ctl(filename, argc, argv,
"T_STOP", -1,
"1e100", NULL);
5782 ctl->
dt_mod =
scan_ctl(filename, argc, argv,
"DT_MOD", -1,
"180", NULL);
5786 ctl->
dt_met =
scan_ctl(filename, argc, argv,
"DT_MET", -1,
"3600", NULL);
5788 (int)
scan_ctl(filename, argc, argv,
"MET_CONVENTION", -1,
"0", NULL);
5790 (int)
scan_ctl(filename, argc, argv,
"MET_TYPE", -1,
"0", NULL);
5793 (
"Please use meteo files in netcdf format for diabatic calculations.");
5796 (
"Please use meteo files in netcdf format for etadot calculations.");
5798 (int)
scan_ctl(filename, argc, argv,
"MET_CLAMS", -1,
"0", NULL);
5800 (int)
scan_ctl(filename, argc, argv,
"MET_NC_SCALE", -1,
"1", NULL);
5802 (int)
scan_ctl(filename, argc, argv,
"MET_NC_LEVEL", -1,
"0", NULL);
5804 (int)
scan_ctl(filename, argc, argv,
"MET_NC_QUANT", -1,
"0", NULL);
5806 (int)
scan_ctl(filename, argc, argv,
"MET_ZSTD_LEVEL", -1,
"0", NULL);
5807 for (
int i = 0; i <
METVAR; i++) {
5808 char defprec[
LEN] =
"0", deftol[
LEN] =
"0.0";
5810 sprintf(deftol,
"0.5");
5812 sprintf(deftol,
"5.0");
5814 sprintf(defprec,
"8");
5816 (int)
scan_ctl(filename, argc, argv,
"MET_COMP_PREC", i, defprec, NULL);
5818 scan_ctl(filename, argc, argv,
"MET_COMP_TOL", i, deftol, NULL);
5821 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_BATCH", -1,
"-1", NULL);
5823 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ZSTD", -1,
"1", NULL);
5825 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ND0X", -1,
"48", NULL);
5827 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ND0Y", -1,
"24", NULL);
5829 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_MAXLEV", -1,
"6", NULL);
5831 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_Z", -1,
"1.0", NULL);
5833 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_T", -1,
"0.05", NULL);
5835 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_U", -1,
"0.05", NULL);
5837 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_V", -1,
"0.05", NULL);
5839 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_W", -1,
"1.0", NULL);
5841 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_PV", -1,
"1.0", NULL);
5843 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_H2O", -1,
"1.0", NULL);
5845 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_O3", -1,
"1.0", NULL);
5847 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_LWC", -1,
"1.0", NULL);
5849 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_RWC", -1,
"1.0", NULL);
5851 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_IWC", -1,
"1.0", NULL);
5853 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_SWC", -1,
"1.0", NULL);
5855 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_CC", -1,
"1.0", NULL);
5856 ctl->
met_dx = (int)
scan_ctl(filename, argc, argv,
"MET_DX", -1,
"1", NULL);
5857 ctl->
met_dy = (int)
scan_ctl(filename, argc, argv,
"MET_DY", -1,
"1", NULL);
5858 ctl->
met_dp = (int)
scan_ctl(filename, argc, argv,
"MET_DP", -1,
"1", NULL);
5860 ERRMSG(
"MET_DX, MET_DY, and MET_DP need to be greater than zero!");
5861 ctl->
met_sx = (int)
scan_ctl(filename, argc, argv,
"MET_SX", -1,
"1", NULL);
5862 ctl->
met_sy = (int)
scan_ctl(filename, argc, argv,
"MET_SY", -1,
"1", NULL);
5863 ctl->
met_sp = (int)
scan_ctl(filename, argc, argv,
"MET_SP", -1,
"1", NULL);
5865 ERRMSG(
"MET_SX, MET_SY, and MET_SP need to be greater than zero!");
5867 scan_ctl(filename, argc, argv,
"MET_DETREND", -1,
"-999", NULL);
5868 ctl->
met_np = (int)
scan_ctl(filename, argc, argv,
"MET_NP", -1,
"0", NULL);
5870 ERRMSG(
"Too many pressure levels!");
5872 (int)
scan_ctl(filename, argc, argv,
"MET_PRESS_LEVEL_DEF", -1,
"-1",
5878 for (
int ip = 0; ip < ctl->
met_np; ip++)
5880 scan_ctl(filename, argc, argv,
"MET_P", ip,
"", NULL);
5884 (int)
scan_ctl(filename, argc, argv,
"MET_NLEV", -1,
"0", NULL);
5886 ERRMSG(
"Too many model levels!");
5887 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
5889 scan_ctl(filename, argc, argv,
"MET_LEV_HYAM", ip,
"", NULL);
5890 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
5892 scan_ctl(filename, argc, argv,
"MET_LEV_HYBM", ip,
"", NULL);
5894 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SX", -1,
"-1", NULL);
5896 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SY", -1,
"-1", NULL);
5898 (int)
scan_ctl(filename, argc, argv,
"MET_RELHUM", -1,
"0", NULL);
5900 (int)
scan_ctl(filename, argc, argv,
"MET_CAPE", -1,
"1", NULL);
5902 ERRMSG(
"Set MET_CAPE to 0 or 1!");
5904 (int)
scan_ctl(filename, argc, argv,
"MET_PBL", -1,
"3", NULL);
5906 ERRMSG(
"Set MET_PBL to 0 ... 3!");
5908 scan_ctl(filename, argc, argv,
"MET_PBL_MIN", -1,
"0.1", NULL);
5910 scan_ctl(filename, argc, argv,
"MET_PBL_MAX", -1,
"5.0", NULL);
5912 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO", -1,
"3", NULL);
5914 ERRMSG(
"Set MET_TROPO to 0 ... 5!");
5916 scan_ctl(filename, argc, argv,
"MET_TROPO_PV", -1,
"3.5", NULL);
5918 scan_ctl(filename, argc, argv,
"MET_TROPO_THETA", -1,
"380", NULL);
5920 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO_SPLINE", -1,
"1", NULL);
5922 scan_ctl(filename, argc, argv,
"MET_DT_OUT", -1,
"0.1", NULL);
5924 (int)
scan_ctl(filename, argc, argv,
"MET_CACHE", -1,
"0", NULL);
5926 (int)
scan_ctl(filename, argc, argv,
"MET_MPI_SHARE", -1,
"0", NULL);
5929 ctl->
sort_dt =
scan_ctl(filename, argc, argv,
"SORT_DT", -1,
"-999", NULL);
5933 (int)
scan_ctl(filename, argc, argv,
"ISOSURF", -1,
"0", NULL);
5938 (int)
scan_ctl(filename, argc, argv,
"RNG_TYPE", -1,
"1", NULL);
5940 ERRMSG(
"Set RNG_TYPE to 0, 1, or 2!");
5943 ctl->
advect = (int)
scan_ctl(filename, argc, argv,
"ADVECT", -1,
"2", NULL);
5947 ERRMSG(
"Set ADVECT to 0, 1, 2, or 4!");
5951 = (int)
scan_ctl(filename, argc, argv,
"DIFFUSION", -1,
"0", NULL);
5953 ERRMSG(
"Set DIFFUSION to 0, 1 or 2!");
5955 scan_ctl(filename, argc, argv,
"TURB_DX_PBL", -1,
"50", NULL);
5957 scan_ctl(filename, argc, argv,
"TURB_DX_TROP", -1,
"50", NULL);
5959 scan_ctl(filename, argc, argv,
"TURB_DX_STRAT", -1,
"0", NULL);
5961 scan_ctl(filename, argc, argv,
"TURB_DZ_PBL", -1,
"0", NULL);
5963 scan_ctl(filename, argc, argv,
"TURB_DZ_TROP", -1,
"0", NULL);
5965 scan_ctl(filename, argc, argv,
"TURB_DZ_STRAT", -1,
"0.1", NULL);
5967 scan_ctl(filename, argc, argv,
"TURB_MESOX", -1,
"0.16", NULL);
5969 scan_ctl(filename, argc, argv,
"TURB_MESOZ", -1,
"0.16", NULL);
5973 = (int)
scan_ctl(filename, argc, argv,
"CONV_MIX_PBL", -1,
"0", NULL);
5975 =
scan_ctl(filename, argc, argv,
"CONV_PBL_TRANS", -1,
"0", NULL);
5977 =
scan_ctl(filename, argc, argv,
"CONV_CAPE", -1,
"-999", NULL);
5979 =
scan_ctl(filename, argc, argv,
"CONV_CIN", -1,
"-999", NULL);
5980 ctl->
conv_dt =
scan_ctl(filename, argc, argv,
"CONV_DT", -1,
"-999", NULL);
5984 scan_ctl(filename, argc, argv,
"BOUND_MASS", -1,
"-999", NULL);
5986 scan_ctl(filename, argc, argv,
"BOUND_MASS_TREND", -1,
"0", NULL);
5988 scan_ctl(filename, argc, argv,
"BOUND_VMR", -1,
"-999", NULL);
5990 scan_ctl(filename, argc, argv,
"BOUND_VMR_TREND", -1,
"0", NULL);
5992 scan_ctl(filename, argc, argv,
"BOUND_LAT0", -1,
"-999", NULL);
5994 scan_ctl(filename, argc, argv,
"BOUND_LAT1", -1,
"-999", NULL);
5996 scan_ctl(filename, argc, argv,
"BOUND_P0", -1,
"-999", NULL);
5998 scan_ctl(filename, argc, argv,
"BOUND_P1", -1,
"-999", NULL);
6000 scan_ctl(filename, argc, argv,
"BOUND_DPS", -1,
"-999", NULL);
6002 scan_ctl(filename, argc, argv,
"BOUND_DZS", -1,
"-999", NULL);
6004 scan_ctl(filename, argc, argv,
"BOUND_ZETAS", -1,
"-999", NULL);
6006 (int)
scan_ctl(filename, argc, argv,
"BOUND_PBL", -1,
"0", NULL);
6010 if (strcasecmp(ctl->
species,
"CF2Cl2") == 0) {
6014 }
else if (strcasecmp(ctl->
species,
"CFCl3") == 0) {
6018 }
else if (strcasecmp(ctl->
species,
"CH4") == 0) {
6025 }
else if (strcasecmp(ctl->
species,
"CO") == 0) {
6034 }
else if (strcasecmp(ctl->
species,
"CO2") == 0) {
6038 }
else if (strcasecmp(ctl->
species,
"H2O") == 0) {
6040 }
else if (strcasecmp(ctl->
species,
"N2O") == 0) {
6044 }
else if (strcasecmp(ctl->
species,
"NH3") == 0) {
6051 }
else if (strcasecmp(ctl->
species,
"HNO3") == 0) {
6055 }
else if (strcasecmp(ctl->
species,
"NO") == 0) {
6064 }
else if (strcasecmp(ctl->
species,
"NO2") == 0) {
6073 }
else if (strcasecmp(ctl->
species,
"O3") == 0) {
6080 }
else if (strcasecmp(ctl->
species,
"SF6") == 0) {
6084 }
else if (strcasecmp(ctl->
species,
"SO2") == 0) {
6097 sprintf(defstr,
"%g", ctl->
molmass);
6098 ctl->
molmass =
scan_ctl(filename, argc, argv,
"MOLMASS", -1, defstr, NULL);
6103 (int)
scan_ctl(filename, argc, argv,
"OH_CHEM_REACTION", -1, defstr,
6105 for (
int ip = 0; ip < 4; ip++) {
6106 sprintf(defstr,
"%g", ctl->
oh_chem[ip]);
6108 scan_ctl(filename, argc, argv,
"OH_CHEM", ip, defstr, NULL);
6111 scan_ctl(filename, argc, argv,
"OH_CHEM_BETA", -1,
"0", NULL);
6115 (int)
scan_ctl(filename, argc, argv,
"H2O2_CHEM_REACTION", -1,
"0", NULL);
6119 (int)
scan_ctl(filename, argc, argv,
"KPP_CHEM", -1,
"0", NULL);
6120 ctl->
dt_kpp =
scan_ctl(filename, argc, argv,
"DT_KPP", -1,
"1800", NULL);
6124 (int)
scan_ctl(filename, argc, argv,
"TRACER_CHEM", -1,
"0", NULL);
6127 for (
int ip = 0; ip < 2; ip++) {
6130 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_H", ip, defstr, NULL);
6132 for (
int ip = 0; ip < 1; ip++) {
6135 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_H", ip, defstr, NULL);
6138 scan_ctl(filename, argc, argv,
"WET_DEPO_SO2_PH", -1,
"0", NULL);
6140 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_A", -1,
"0", NULL);
6142 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_B", -1,
"0", NULL);
6144 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_A", -1,
"0", NULL);
6146 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_B", -1,
"0", NULL);
6148 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 0,
"0.5", NULL);
6150 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 1,
"0.36", NULL);
6152 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_RET_RATIO", -1,
"1", NULL);
6154 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_RET_RATIO", -1,
"1", NULL);
6158 scan_ctl(filename, argc, argv,
"DRY_DEPO_VDEP", -1,
"0", NULL);
6160 scan_ctl(filename, argc, argv,
"DRY_DEPO_DP", -1,
"30", NULL);
6163 scan_ctl(filename, argc, argv,
"CLIM_PHOTO", -1,
6164 "../../data/clams_photolysis_rates.nc", ctl->
clim_photo);
6165 scan_ctl(filename, argc, argv,
"CLIM_HNO3_FILENAME", -1,
6167 scan_ctl(filename, argc, argv,
"CLIM_OH_FILENAME", -1,
6169 scan_ctl(filename, argc, argv,
"CLIM_H2O2_FILENAME", -1,
6171 scan_ctl(filename, argc, argv,
"CLIM_HO2_FILENAME", -1,
6173 scan_ctl(filename, argc, argv,
"CLIM_O1D_FILENAME", -1,
6175 scan_ctl(filename, argc, argv,
"CLIM_CCL4_TIMESERIES", -1,
6177 scan_ctl(filename, argc, argv,
"CLIM_CCL3F_TIMESERIES", -1,
6179 scan_ctl(filename, argc, argv,
"CLIM_CCL2F2_TIMESERIES", -1,
6181 scan_ctl(filename, argc, argv,
"CLIM_N2O_TIMESERIES", -1,
6183 scan_ctl(filename, argc, argv,
"CLIM_SF6_TIMESERIES", -1,
6188 scan_ctl(filename, argc, argv,
"MIXING_DT", -1,
"3600.", NULL);
6190 scan_ctl(filename, argc, argv,
"MIXING_TROP", -1,
"-999", NULL);
6192 scan_ctl(filename, argc, argv,
"MIXING_STRAT", -1,
"-999", NULL);
6194 scan_ctl(filename, argc, argv,
"MIXING_Z0", -1,
"-5", NULL);
6196 scan_ctl(filename, argc, argv,
"MIXING_Z1", -1,
"85", NULL);
6198 (int)
scan_ctl(filename, argc, argv,
"MIXING_NZ", -1,
"90", NULL);
6200 scan_ctl(filename, argc, argv,
"MIXING_LON0", -1,
"-180", NULL);
6202 scan_ctl(filename, argc, argv,
"MIXING_LON1", -1,
"180", NULL);
6204 (int)
scan_ctl(filename, argc, argv,
"MIXING_NX", -1,
"360", NULL);
6206 scan_ctl(filename, argc, argv,
"MIXING_LAT0", -1,
"-90", NULL);
6208 scan_ctl(filename, argc, argv,
"MIXING_LAT1", -1,
"90", NULL);
6210 (int)
scan_ctl(filename, argc, argv,
"MIXING_NY", -1,
"180", NULL);
6214 scan_ctl(filename, argc, argv,
"CHEMGRID_Z0", -1,
"-5", NULL);
6216 scan_ctl(filename, argc, argv,
"CHEMGRID_Z1", -1,
"85", NULL);
6218 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NZ", -1,
"90", NULL);
6220 scan_ctl(filename, argc, argv,
"CHEMGRID_LON0", -1,
"-180", NULL);
6222 scan_ctl(filename, argc, argv,
"CHEMGRID_LON1", -1,
"180", NULL);
6224 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NX", -1,
"360", NULL);
6226 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT0", -1,
"-90", NULL);
6228 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT1", -1,
"90", NULL);
6230 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NY", -1,
"180", NULL);
6235 scan_ctl(filename, argc, argv,
"TDEC_STRAT", -1,
"0", NULL);
6238 ctl->
psc_h2o =
scan_ctl(filename, argc, argv,
"PSC_H2O", -1,
"4e-6", NULL);
6240 scan_ctl(filename, argc, argv,
"PSC_HNO3", -1,
"9e-9", NULL);
6246 scan_ctl(filename, argc, argv,
"ATM_DT_OUT", -1,
"86400", NULL);
6248 (int)
scan_ctl(filename, argc, argv,
"ATM_FILTER", -1,
"0", NULL);
6250 (int)
scan_ctl(filename, argc, argv,
"ATM_STRIDE", -1,
"1", NULL);
6252 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE", -1,
"0", NULL);
6254 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE_OUT", -1,
"-1", NULL);
6258 (int)
scan_ctl(filename, argc, argv,
"ATM_NC_LEVEL", -1,
"0", NULL);
6259 for (
int iq = 0; iq < ctl->
nq; iq++)
6261 (
int)
scan_ctl(filename, argc, argv,
"ATM_NC_QUANT", iq,
"0", NULL);
6263 (int)
scan_ctl(filename, argc, argv,
"OBS_TYPE", -1,
"0", NULL);
6269 scan_ctl(filename, argc, argv,
"CSI_DT_OUT", -1,
"86400", NULL);
6272 scan_ctl(filename, argc, argv,
"CSI_OBSMIN", -1,
"0", NULL);
6274 scan_ctl(filename, argc, argv,
"CSI_MODMIN", -1,
"0", NULL);
6275 ctl->
csi_z0 =
scan_ctl(filename, argc, argv,
"CSI_Z0", -1,
"-5", NULL);
6276 ctl->
csi_z1 =
scan_ctl(filename, argc, argv,
"CSI_Z1", -1,
"85", NULL);
6277 ctl->
csi_nz = (int)
scan_ctl(filename, argc, argv,
"CSI_NZ", -1,
"1", NULL);
6279 scan_ctl(filename, argc, argv,
"CSI_LON0", -1,
"-180", NULL);
6280 ctl->
csi_lon1 =
scan_ctl(filename, argc, argv,
"CSI_LON1", -1,
"180", NULL);
6282 (int)
scan_ctl(filename, argc, argv,
"CSI_NX", -1,
"360", NULL);
6283 ctl->
csi_lat0 =
scan_ctl(filename, argc, argv,
"CSI_LAT0", -1,
"-90", NULL);
6284 ctl->
csi_lat1 =
scan_ctl(filename, argc, argv,
"CSI_LAT1", -1,
"90", NULL);
6286 (int)
scan_ctl(filename, argc, argv,
"CSI_NY", -1,
"180", NULL);
6289 ctl->
nens = (int)
scan_ctl(filename, argc, argv,
"NENS", -1,
"0", NULL);
6292 scan_ctl(filename, argc, argv,
"ENS_DT_OUT", -1,
"86400", NULL);
6295 scan_ctl(filename, argc, argv,
"GRID_BASENAME", -1,
"-",
6300 scan_ctl(filename, argc, argv,
"GRID_DT_OUT", -1,
"86400", NULL);
6302 (int)
scan_ctl(filename, argc, argv,
"GRID_SPARSE", -1,
"0", NULL);
6304 (int)
scan_ctl(filename, argc, argv,
"GRID_NC_LEVEL", -1,
"0", NULL);
6305 for (
int iq = 0; iq < ctl->
nq; iq++)
6307 (
int)
scan_ctl(filename, argc, argv,
"GRID_NC_QUANT", iq,
"0", NULL);
6309 (int)
scan_ctl(filename, argc, argv,
"GRID_STDDEV", -1,
"0", NULL);
6310 ctl->
grid_z0 =
scan_ctl(filename, argc, argv,
"GRID_Z0", -1,
"-5", NULL);
6311 ctl->
grid_z1 =
scan_ctl(filename, argc, argv,
"GRID_Z1", -1,
"85", NULL);
6313 (int)
scan_ctl(filename, argc, argv,
"GRID_NZ", -1,
"1", NULL);
6315 scan_ctl(filename, argc, argv,
"GRID_LON0", -1,
"-180", NULL);
6317 scan_ctl(filename, argc, argv,
"GRID_LON1", -1,
"180", NULL);
6319 (int)
scan_ctl(filename, argc, argv,
"GRID_NX", -1,
"360", NULL);
6321 scan_ctl(filename, argc, argv,
"GRID_LAT0", -1,
"-90", NULL);
6323 scan_ctl(filename, argc, argv,
"GRID_LAT1", -1,
"90", NULL);
6325 (int)
scan_ctl(filename, argc, argv,
"GRID_NY", -1,
"180", NULL);
6327 (int)
scan_ctl(filename, argc, argv,
"GRID_TYPE", -1,
"0", NULL);
6330 scan_ctl(filename, argc, argv,
"PROF_BASENAME", -1,
"-",
6333 ctl->
prof_z0 =
scan_ctl(filename, argc, argv,
"PROF_Z0", -1,
"0", NULL);
6334 ctl->
prof_z1 =
scan_ctl(filename, argc, argv,
"PROF_Z1", -1,
"60", NULL);
6336 (int)
scan_ctl(filename, argc, argv,
"PROF_NZ", -1,
"60", NULL);
6338 scan_ctl(filename, argc, argv,
"PROF_LON0", -1,
"-180", NULL);
6340 scan_ctl(filename, argc, argv,
"PROF_LON1", -1,
"180", NULL);
6342 (int)
scan_ctl(filename, argc, argv,
"PROF_NX", -1,
"360", NULL);
6344 scan_ctl(filename, argc, argv,
"PROF_LAT0", -1,
"-90", NULL);
6346 scan_ctl(filename, argc, argv,
"PROF_LAT1", -1,
"90", NULL);
6348 (int)
scan_ctl(filename, argc, argv,
"PROF_NY", -1,
"180", NULL);
6351 scan_ctl(filename, argc, argv,
"SAMPLE_BASENAME", -1,
"-",
6353 scan_ctl(filename, argc, argv,
"SAMPLE_KERNEL", -1,
"-",
6355 scan_ctl(filename, argc, argv,
"SAMPLE_OBSFILE", -1,
"-",
6358 scan_ctl(filename, argc, argv,
"SAMPLE_DX", -1,
"50", NULL);
6360 scan_ctl(filename, argc, argv,
"SAMPLE_DZ", -1,
"-999", NULL);
6363 scan_ctl(filename, argc, argv,
"STAT_BASENAME", -1,
"-",
6367 ctl->
stat_r =
scan_ctl(filename, argc, argv,
"STAT_R", -1,
"50", NULL);
6369 scan_ctl(filename, argc, argv,
"STAT_T0", -1,
"-1e100", NULL);
6370 ctl->
stat_t1 =
scan_ctl(filename, argc, argv,
"STAT_T1", -1,
"1e100", NULL);
6375 scan_ctl(filename, argc, argv,
"VTK_DT_OUT", -1,
"86400", NULL);
6377 (int)
scan_ctl(filename, argc, argv,
"VTK_STRIDE", -1,
"1", NULL);
6379 scan_ctl(filename, argc, argv,
"VTK_SCALE", -1,
"1.0", NULL);
6381 scan_ctl(filename, argc, argv,
"VTK_OFFSET", -1,
"0.0", NULL);
6383 (int)
scan_ctl(filename, argc, argv,
"VTK_SPHERE", -1,
"0", NULL);
6386 ctl->
dd = (int)
scan_ctl(filename, argc, argv,
"DD", -1,
"0", NULL);
6388 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_MERIDIONAL", -1,
6389 (ctl->
dd == 1) ?
"2" :
"1", NULL);
6391 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_ZONAL", -1,
6392 (ctl->
dd == 1) ?
"2" :
"1", NULL);
6395 else if (ctl->
dd == 1)
6396 ERRMSG(
"Please provide zonal and meridional subdomain numbers!")
6398 (int)
scan_ctl(filename, argc, argv,
"DD_NBR_NEIGHBOURS", -1,
"8",
6401 (int)
scan_ctl(filename, argc, argv,
"DD_HALOS_SIZE", -1,
"1", NULL);
6407 const char *filename,
6414 LOG(1,
"Read meteo data: %s", filename);
6420 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
6448 ERRMSG(
"MET_TYPE not implemented!");
6502 LOG(2,
"Broadcast data on rank %d...", rank);
6633 ERRMSG(
"DD initialized, but model is compiled without DD.")
6642 ERRMSG(
"Code was compiled without KPP!");
6675#pragma acc update device(ctl[:1])
6679 if (cache != NULL) {
6682#pragma acc update device(cache[:1])
6689#pragma acc update device(clim[:1])
6696 met_t *met0up = *met0;
6697#pragma acc update device(met0up[:1])
6704 met_t *met1up = *met1;
6705#pragma acc update device(met1up[:1])
6712#pragma acc update device(atm[:1])
6731#pragma acc update host(ctl[:1])
6735 if (cache != NULL) {
6738#pragma acc update host(cache[:1])
6745#pragma acc update host(clim[:1])
6752 met_t *met0up = *met0;
6753#pragma acc update host(met0up[:1])
6760 met_t *met1up = *met1;
6761#pragma acc update host(met1up[:1])
6768#pragma acc update host(atm[:1])
6776 const char *filename,
6785 LOG(1,
"Write atmospheric data: %s", filename);
6809 ERRMSG(
"Atmospheric data type not supported!");
6813 LOG(2,
"Number of particles: %d", atm->
np);
6814 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
6815 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
6816 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
6817 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
6818 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
6819 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
6820 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
6821 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
6822 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
6823 for (
int iq = 0; iq < ctl->
nq; iq++) {
6825 sprintf(msg,
"Quantity %s range: %s ... %s %s",
6828 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
6829 LOG(2, msg, mini, maxi);
6836 const char *filename,
6844 LOG(1,
"Write meteo data: %s", filename);
6849 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
6853 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
6857 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
6861 ERRMSG(
"MPTRAC was compiled without SZ3 compression!");
6874 ERRMSG(
"MET_TYPE not implemented!");
6880 const char *dirname,
6887 char ext[10], filename[2 *
LEN];
6891 int year, mon, day, hour, min, sec;
6894 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
6909 sprintf(ext,
"tab");
6911 sprintf(ext,
"bin");
6914 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6915 dirname, ctl->
atm_basename, year, mon, day, hour, min, ext);
6921 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6924 write_grid(filename, ctl, met0, met1, atm, t);
6929 sprintf(filename,
"%s/%s.tab", dirname, ctl->
csi_basename);
6935 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.tab",
6936 dirname, ctl->
ens_basename, year, mon, day, hour, min);
6942 sprintf(filename,
"%s/%s.tab", dirname, ctl->
prof_basename);
6943 write_prof(filename, ctl, met0, met1, atm, t);
6954 sprintf(filename,
"%s/%s.tab", dirname, ctl->
stat_basename);
6963 sprintf(filename,
"%s/%s_%05d.vtk", dirname, ctl->
vtk_basename, ++nvtk);
6973 const double hno3) {
6976 const double h2o_help =
MAX(h2o, 0.1e-6);
6979 const double p_hno3 = hno3 * p / 1.333224;
6980 const double p_h2o = h2o_help * p / 1.333224;
6981 const double a = 0.009179 - 0.00088 * log10(p_h2o);
6982 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
6983 const double c = -11397.0 / a;
6984 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
6985 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
7003 const double p0 = pbl;
7006 if (atm->
p[ip] > p0)
7008 else if (atm->
p[ip] < p1)
7011 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
7017 const char *filename,
7023 if (!(in = fopen(filename,
"r"))) {
7024 WARN(
"Cannot open file!");
7030 while (fgets(line,
LEN, in)) {
7034 TOK(line, tok,
"%lg", atm->
time[atm->
np]);
7035 TOK(NULL, tok,
"%lg", atm->
p[atm->
np]);
7036 TOK(NULL, tok,
"%lg", atm->
lon[atm->
np]);
7037 TOK(NULL, tok,
"%lg", atm->
lat[atm->
np]);
7038 for (
int iq = 0; iq < ctl->
nq; iq++)
7039 TOK(NULL, tok,
"%lg", atm->
q[iq][atm->
np]);
7042 atm->
p[atm->
np] =
P(atm->
p[atm->
np]);
7045 if ((++atm->
np) >
NP)
7046 ERRMSG(
"Too many data points!");
7059 const char *filename,
7065 if (!(in = fopen(filename,
"r")))
7070 FREAD(&version,
int,
7074 ERRMSG(
"Wrong version of binary data!");
7092 for (
int iq = 0; iq < ctl->
nq; iq++)
7093 FREAD(atm->
q[iq],
double,
7103 ERRMSG(
"Error while reading binary data!");
7115 const char *filename,
7122 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
7129 if (nc_inq_varid(ncid,
"TIME_INIT", &varid) == NC_NOERR) {
7130 NC(nc_get_var_double(ncid, varid, atm->
time));
7132 WARN(
"TIME_INIT not found use time instead!");
7135 for (
int ip = 0; ip < atm->
np; ip++) {
7136 atm->
time[ip] = time_init;
7148 if (nc_inq_varid(ncid,
"PRESS_INIT", &varid) == NC_NOERR) {
7149 NC(nc_get_var_double(ncid, varid, atm->
p));
7151 WARN(
"PRESS_INIT not found use PRESS instead!");
7152 nc_inq_varid(ncid,
"PRESS", &varid);
7153 NC(nc_get_var_double(ncid, varid, atm->
p));
7158 for (
int iq = 0; iq < ctl->
nq; iq++)
7175 const char *filename,
7182 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
7195 for (
int iq = 0; iq < ctl->
nq; iq++)
7208 const char *filename,
7214 LOG(1,
"Read photolysis rates: %s", filename);
7217 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
7218 WARN(
"Photolysis rate data are missing!");
7225 if (photo->
p[0] < photo->
p[1])
7226 ERRMSG(
"Pressure data are not descending!");
7231 if (photo->
o3c[0] > photo->
o3c[1])
7232 ERRMSG(
"Total column ozone data are not ascending!");
7237 if (photo->
sza[0] > photo->
sza[1])
7238 ERRMSG(
"Solar zenith angle data are not ascending!");
7255 LOG(2,
"Number of pressure levels: %d", photo->
np);
7256 LOG(2,
"Altitude levels: %g, %g ... %g km",
7257 Z(photo->
p[0]),
Z(photo->
p[1]),
Z(photo->
p[photo->
np - 1]));
7258 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
7259 photo->
p[0], photo->
p[1], photo->
p[photo->
np - 1]);
7260 LOG(2,
"Number of solar zenith angles: %d", photo->
nsza);
7261 LOG(2,
"Solar zenith angles: %g, %g ... %g deg",
7264 LOG(2,
"Number of total column ozone values: %d", photo->
no3c);
7265 LOG(2,
"Total column ozone: %g, %g ... %g DU",
7267 LOG(2,
"N2O photolysis rate: %g, %g ... %g s**-1",
7268 photo->
n2o[0][0][0], photo->
n2o[1][0][0],
7269 photo->
n2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7270 LOG(2,
"CCl4 photolysis rate: %g, %g ... %g s**-1",
7271 photo->
ccl4[0][0][0], photo->
ccl4[1][0][0],
7273 LOG(2,
"CFC-11 photolysis rate: %g, %g ... %g s**-1",
7274 photo->
ccl3f[0][0][0], photo->
ccl3f[1][0][0],
7276 LOG(2,
"CFC-12 photolysis rate: %g, %g ... %g s**-1",
7279 LOG(2,
"O2 photolysis rate: %g, %g ... %g s**-1",
7280 photo->
o2[0][0][0], photo->
o2[1][0][0],
7281 photo->
o2[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7282 LOG(2,
"O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
7283 photo->
o3_1[0][0][0], photo->
o3_1[1][0][0],
7285 LOG(2,
"O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
7286 photo->
o3_2[0][0][0], photo->
o3_2[1][0][0],
7288 LOG(2,
"H2O2 photolysis rate: %g, %g ... %g s**-1",
7289 photo->
h2o2[0][0][0], photo->
h2o2[1][0][0],
7291 LOG(2,
"H2O photolysis rate: %g, %g ... %g s**-1",
7292 photo->
h2o[0][0][0], photo->
h2o[1][0][0],
7293 photo->
h2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7300 const char *varname,
7314 for (
int ip = 0; ip < photo->
np; ip++)
7315 for (
int is = 0; is < photo->
nsza; is++)
7316 for (
int io = 0; io < photo->
no3c; io++)
7327 const char *filename,
7331 LOG(1,
"Read climatological time series: %s", filename);
7335 if (!(in = fopen(filename,
"r"))) {
7336 WARN(
"Cannot open file!");
7343 while (fgets(line,
LEN, in))
7344 if (sscanf(line,
"%lg %lg", &ts->
time[nh], &ts->
vmr[nh]) == 2) {
7347 ts->
time[nh] = (ts->
time[nh] - 2000.0) * 365.25 * 86400.;
7350 if (nh > 0 && ts->
time[nh] <= ts->
time[nh - 1])
7351 ERRMSG(
"Time series must be ascending!");
7355 ERRMSG(
"Too many data points!");
7364 ERRMSG(
"Not enough data points!");
7367 LOG(2,
"Number of time steps: %d", ts->
ntime);
7368 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s", ts->
time[0], ts->
time[1],
7370 LOG(2,
"Volume mixing ratio range: %g ... %g ppv",
7371 gsl_stats_min(ts->
vmr, 1, (
size_t) nh), gsl_stats_max(ts->
vmr, 1,
7381 const char *filename,
7382 const char *varname,
7385 int ncid, varid, it, iy, iz, iz2, nt;
7387 double *help, varmin = 1e99, varmax = -1e99;
7390 LOG(1,
"Read %s data: %s", varname, filename);
7393 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
7394 WARN(
"%s climatology data are missing!", varname);
7401 if (zm->
p[0] < zm->
p[1])
7402 ERRMSG(
"Pressure data are not descending!");
7407 if (zm->
lat[0] > zm->
lat[1])
7408 ERRMSG(
"Latitude data are not ascending!");
7412 zm->
time[0] = 1209600.00;
7413 zm->
time[1] = 3888000.00;
7414 zm->
time[2] = 6393600.00;
7415 zm->
time[3] = 9072000.00;
7416 zm->
time[4] = 11664000.00;
7417 zm->
time[5] = 14342400.00;
7418 zm->
time[6] = 16934400.00;
7419 zm->
time[7] = 19612800.00;
7420 zm->
time[8] = 22291200.00;
7421 zm->
time[9] = 24883200.00;
7422 zm->
time[10] = 27561600.00;
7423 zm->
time[11] = 30153600.00;
7432 for (it = 0; it < zm->
ntime; it++)
7433 for (iz = 0; iz < zm->
np; iz++)
7434 for (iy = 0; iy < zm->
nlat; iy++)
7439 for (it = 0; it < zm->
ntime; it++)
7440 for (iy = 0; iy < zm->
nlat; iy++)
7441 for (iz = 0; iz < zm->
np; iz++) {
7442 if (zm->
vmr[it][iz][iy] < 0) {
7443 for (iz2 = 0; iz2 < zm->
np; iz2++)
7444 if (zm->
vmr[it][iz2][iy] >= 0) {
7445 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
7448 for (iz2 = zm->
np - 1; iz2 >= 0; iz2--)
7449 if (zm->
vmr[it][iz2][iy] >= 0) {
7450 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
7454 varmin =
MIN(varmin, zm->
vmr[it][iz][iy]);
7455 varmax =
MAX(varmax, zm->
vmr[it][iz][iy]);
7462 LOG(2,
"Number of time steps: %d", zm->
ntime);
7463 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
7465 LOG(2,
"Number of pressure levels: %d", zm->
np);
7466 LOG(2,
"Altitude levels: %g, %g ... %g km",
7467 Z(zm->
p[0]),
Z(zm->
p[1]),
Z(zm->
p[zm->
np - 1]));
7468 LOG(2,
"Pressure levels: %g, %g ... %g hPa", zm->
p[0],
7469 zm->
p[1], zm->
p[zm->
np - 1]);
7470 LOG(2,
"Number of latitudes: %d", zm->
nlat);
7471 LOG(2,
"Latitudes: %g, %g ... %g deg",
7473 LOG(2,
"%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
7480 const char *filename,
7486 LOG(1,
"Read kernel function: %s", filename);
7490 if (!(in = fopen(filename,
"r")))
7491 ERRMSG(
"Cannot open file!");
7496 while (fgets(line,
LEN, in))
7497 if (sscanf(line,
"%lg %lg", &kz[n], &kw[n]) == 2) {
7498 if (n > 0 && kz[n] < kz[n - 1])
7499 ERRMSG(
"Height levels must be ascending!");
7501 ERRMSG(
"Too many height levels!");
7510 ERRMSG(
"Not enough height levels!");
7513 const double kmax = gsl_stats_max(kw, 1, (
size_t) n);
7514 for (
int iz = 0; iz < n; iz++)
7521 const char *filename,
7529 int year, mon, day, hour, min, sec;
7535 if (!(in = fopen(filename,
"r"))) {
7536 WARN(
"Cannot open file!");
7542 FREAD(&met_type,
int,
7546 ERRMSG(
"Wrong MET_TYPE of binary data!");
7550 FREAD(&version,
int,
7554 ERRMSG(
"Wrong version of binary data!");
7560 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
7561 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
7562 met->
time, year, mon, day, hour, min);
7563 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
7564 || day < 1 || day > 31 || hour < 0 || hour > 23)
7565 ERRMSG(
"Error while reading time!");
7571 LOG(2,
"Number of longitudes: %d", met->
nx);
7572 if (met->
nx < 2 || met->
nx >
EX)
7573 ERRMSG(
"Number of longitudes out of range!");
7578 LOG(2,
"Number of latitudes: %d", met->
ny);
7579 if (met->
ny < 2 || met->
ny >
EY)
7580 ERRMSG(
"Number of latitudes out of range!");
7585 LOG(2,
"Number of levels: %d", met->
np);
7586 if (met->
np < 2 || met->
np >
EP)
7587 ERRMSG(
"Number of levels out of range!");
7593 LOG(2,
"Longitudes: %g, %g ... %g deg",
7599 LOG(2,
"Latitudes: %g, %g ... %g deg",
7605 LOG(2,
"Altitude levels: %g, %g ... %g km",
7606 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
7607 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
7608 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
7657 ERRMSG(
"Error while reading binary data!");
7672 const char *varname) {
7681 LOG(2,
"Read 2-D variable: %s (uncompressed)", varname);
7683 (
size_t) (met->
nx * met->
ny),
7687 for (
int ix = 0; ix < met->
nx; ix++)
7688 for (
int iy = 0; iy < met->
ny; iy++)
7689 var[ix][iy] = help[
ARRAY_2D(ix, iy, met->
ny)];
7702 const char *varname,
7703 const float bound_min,
7704 const float bound_max) {
7714 LOG(2,
"Read 3-D variable: %s (uncompressed)", varname);
7716 (
size_t) (met->
nx * met->
ny * met->
np),
7723 (
size_t) met->
np, 1, in);
7729 FREAD(&precision,
int,
7734 FREAD(&tolerance,
double,
7741 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
7751 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
7759 (
size_t) met->
np, met->
p, 1, in);
7761 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
7769 FREAD(&precision,
int,
7774 FREAD(&tolerance,
double,
7781 ERRMSG(
"MPTRAC was compiled without sz3 compression!");
7786#pragma omp parallel for default(shared) collapse(2)
7787 for (
int ix = 0; ix < met->
nx; ix++)
7788 for (
int iy = 0; iy < met->
ny; iy++)
7789 for (
int ip = 0; ip < met->
np; ip++) {
7790 var[ix][iy][ip] = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
7791 if (var[ix][iy][ip] < bound_min)
7792 var[ix][iy][ip] = bound_min;
7793 else if (var[ix][iy][ip] > bound_max)
7794 var[ix][iy][ip] = bound_max;
7814 LOG(2,
"Calculate CAPE...");
7817 const double pfac = 1.01439, dz0 =
RI /
MA /
G0 * log(pfac);
7820#pragma omp parallel for default(shared) collapse(2)
7821 for (
int ix = 0; ix < met->
nx; ix++)
7822 for (
int iy = 0; iy < met->
ny; iy++) {
7826 double h2o = 0, t, theta = 0;
7827 double pbot =
MIN(met->
ps[ix][iy], met->
p[0]);
7828 double ptop = pbot - 50.;
7829 for (
int ip = 0; ip < met->
np; ip++) {
7830 if (met->
p[ip] <= pbot) {
7831 theta +=
THETA(met->
p[ip], met->
t[ix][iy][ip]);
7832 h2o += met->
h2o[ix][iy][ip];
7835 if (met->
p[ip] < ptop && n > 0)
7842 met->
plcl[ix][iy] = NAN;
7843 met->
plfc[ix][iy] = NAN;
7844 met->
pel[ix][iy] = NAN;
7845 met->
cape[ix][iy] = NAN;
7846 met->
cin[ix][iy] = NAN;
7852 pbot = met->
ps[ix][iy];
7854 met->
plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
7855 t = theta / pow(1000. / met->
plcl[ix][iy], 0.286);
7856 if (
RH(met->
plcl[ix][iy], t, h2o) > 100.)
7857 ptop = met->
plcl[ix][iy];
7859 pbot = met->
plcl[ix][iy];
7860 }
while (pbot - ptop > 0.1);
7864 double dcape, dz, h2o_env, t_env;
7865 double p = met->
ps[ix][iy];
7866 met->
cape[ix][iy] = met->
cin[ix][iy] = 0;
7868 dz = dz0 *
TVIRT(t, h2o);
7870 t = theta / pow(1000. / p, 0.286);
7874 &h2o_env, ci, cw, 0);
7875 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
7876 TVIRT(t_env, h2o_env) * dz;
7878 met->
cin[ix][iy] += fabsf((
float) dcape);
7879 }
while (p > met->
plcl[ix][iy]);
7884 p = met->
plcl[ix][iy];
7885 t = theta / pow(1000. / p, 0.286);
7888 dz = dz0 *
TVIRT(t, h2o);
7891 double psat =
PSAT(t);
7892 h2o = psat / (p - (1. -
EPS) * psat);
7896 &h2o_env, ci, cw, 0);
7897 double dcape_old = dcape;
7898 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
7899 TVIRT(t_env, h2o_env) * dz;
7901 met->
cape[ix][iy] += (float) dcape;
7902 if (!isfinite(met->
plfc[ix][iy]))
7903 met->
plfc[ix][iy] = (
float) p;
7904 }
else if (dcape_old > 0)
7905 met->
pel[ix][iy] = (float) p;
7906 if (dcape < 0 && !isfinite(met->
plfc[ix][iy]))
7907 met->
cin[ix][iy] += fabsf((
float) dcape);
7911 if (!isfinite(met->
plfc[ix][iy]))
7912 met->
cin[ix][iy] = NAN;
7923 LOG(2,
"Calculate cloud data...");
7926 const double ccmin = 0.01, cwmin = 1e-6;
7929#pragma omp parallel for default(shared) collapse(2)
7930 for (
int ix = 0; ix < met->
nx; ix++)
7931 for (
int iy = 0; iy < met->
ny; iy++) {
7934 met->
pct[ix][iy] = NAN;
7935 met->
pcb[ix][iy] = NAN;
7936 met->
cl[ix][iy] = 0;
7939 for (
int ip = 0; ip < met->
np - 1; ip++) {
7942 if (met->
p[ip] > met->
ps[ix][iy] || met->
p[ip] <
P(20.))
7946 if (met->
cc[ix][iy][ip] > ccmin
7947 && (met->
lwc[ix][iy][ip] > cwmin
7948 || met->
rwc[ix][iy][ip] > cwmin
7949 || met->
iwc[ix][iy][ip] > cwmin
7950 || met->
swc[ix][iy][ip] > cwmin)) {
7954 = (float) (0.5 * (met->
p[ip] + (
float) met->
p[ip + 1]));
7957 if (!isfinite(met->
pcb[ix][iy]))
7959 = (
float) (0.5 * (met->
p[ip] + met->
p[
MAX(ip - 1, 0)]));
7963 met->
cl[ix][iy] += (float)
7964 (0.5 * (met->
lwc[ix][iy][ip] + met->
lwc[ix][iy][ip + 1]
7965 + met->
rwc[ix][iy][ip] + met->
rwc[ix][iy][ip + 1]
7966 + met->
iwc[ix][iy][ip] + met->
iwc[ix][iy][ip + 1]
7967 + met->
swc[ix][iy][ip] + met->
swc[ix][iy][ip + 1])
7968 * 100. * (met->
p[ip] - met->
p[ip + 1]) /
G0);
7986 SELECT_TIMER(
"READ_MET_DETREND",
"METPROC", NVTX_READ);
7987 LOG(2,
"Detrend meteo data...");
7994 const double tssq = 2. *
SQR(sigma);
7997 int sy = (int) (3. *
DY2DEG(sigma) / fabs(met->
lat[1] - met->
lat[0]));
8001#pragma omp parallel for default(shared) collapse(2)
8002 for (
int ix = 0; ix < met->
nx; ix++) {
8003 for (
int iy = 0; iy < met->
ny; iy++) {
8011 (int) (3. *
DX2DEG(sigma, met->
lat[iy]) /
8012 fabs(met->
lon[1] - met->
lon[0]));
8017 for (
int ip = 0; ip < met->
np; ip++) {
8018 help->
t[ix][iy][ip] = 0;
8019 help->
u[ix][iy][ip] = 0;
8020 help->
v[ix][iy][ip] = 0;
8021 help->
w[ix][iy][ip] = 0;
8025 for (
int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
8029 else if (ix3 >= met->
nx)
8031 for (
int iy2 =
MAX(iy - sy, 0);
8032 iy2 <=
MIN(iy + sy, met->
ny - 1); iy2++) {
8039 const float w = (float) exp(-
DIST2(x0, x1) / tssq);
8043 for (
int ip = 0; ip < met->
np; ip++) {
8044 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip];
8045 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip];
8046 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip];
8047 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip];
8053 for (
int ip = 0; ip < met->
np; ip++) {
8054 help->
t[ix][iy][ip] /= wsum;
8055 help->
u[ix][iy][ip] /= wsum;
8056 help->
v[ix][iy][ip] /= wsum;
8057 help->
w[ix][iy][ip] /= wsum;
8063#pragma omp parallel for default(shared) collapse(3)
8064 for (
int ix = 0; ix < met->
nx; ix++)
8065 for (
int iy = 0; iy < met->
ny; iy++)
8066 for (
int ip = 0; ip < met->
np; ip++) {
8067 met->
t[ix][iy][ip] -= help->
t[ix][iy][ip];
8068 met->
u[ix][iy][ip] -= help->
u[ix][iy][ip];
8069 met->
v[ix][iy][ip] -= help->
v[ix][iy][ip];
8070 met->
w[ix][iy][ip] -= help->
w[ix][iy][ip];
8083 SELECT_TIMER(
"READ_MET_EXTRAPOLATE",
"METPROC", NVTX_READ);
8084 LOG(2,
"Extrapolate meteo data...");
8087#pragma omp parallel for default(shared) collapse(2)
8088 for (
int ix = 0; ix < met->
nx; ix++)
8089 for (
int iy = 0; iy < met->
ny; iy++) {
8093 for (ip0 = met->
np - 1; ip0 >= 0; ip0--)
8094 if (!isfinite(met->
t[ix][iy][ip0])
8095 || !isfinite(met->
u[ix][iy][ip0])
8096 || !isfinite(met->
v[ix][iy][ip0])
8097 || !isfinite(met->
w[ix][iy][ip0]))
8101 for (
int ip = ip0; ip >= 0; ip--) {
8102 met->
t[ix][iy][ip] = met->
t[ix][iy][ip + 1];
8103 met->
u[ix][iy][ip] = met->
u[ix][iy][ip + 1];
8104 met->
v[ix][iy][ip] = met->
v[ix][iy][ip + 1];
8105 met->
w[ix][iy][ip] = met->
w[ix][iy][ip + 1];
8106 met->
h2o[ix][iy][ip] = met->
h2o[ix][iy][ip + 1];
8107 met->
o3[ix][iy][ip] = met->
o3[ix][iy][ip + 1];
8108 met->
lwc[ix][iy][ip] = met->
lwc[ix][iy][ip + 1];
8109 met->
rwc[ix][iy][ip] = met->
rwc[ix][iy][ip + 1];
8110 met->
iwc[ix][iy][ip] = met->
iwc[ix][iy][ip + 1];
8111 met->
swc[ix][iy][ip] = met->
swc[ix][iy][ip + 1];
8112 met->
cc[ix][iy][ip] = met->
cc[ix][iy][ip + 1];
8131 LOG(2,
"Calculate geopotential heights...");
8138#pragma omp parallel for default(shared)
8139 for (
int ip = 0; ip < met->
np; ip++)
8140 logp[ip] = log(met->
p[ip]);
8143#pragma omp parallel for default(shared) collapse(2)
8144 for (
int ix = 0; ix < met->
nx; ix++)
8145 for (
int iy = 0; iy < met->
ny; iy++) {
8148 const double zs = met->
zs[ix][iy];
8149 const double lnps = log(met->
ps[ix][iy]);
8153 const double ts =
LIN(met->
p[ip0], met->
t[ix][iy][ip0], met->
p[ip0 + 1],
8154 met->
t[ix][iy][ip0 + 1], met->
ps[ix][iy]);
8156 LIN(met->
p[ip0], met->
h2o[ix][iy][ip0], met->
p[ip0 + 1],
8157 met->
h2o[ix][iy][ip0 + 1], met->
ps[ix][iy]);
8160 met->
z[ix][iy][ip0 + 1]
8162 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
8163 met->
t[ix][iy][ip0 + 1], met->
h2o[ix][iy][ip0 + 1]));
8164 for (
int ip = ip0 + 2; ip < met->
np; ip++)
8166 = (
float) (met->
z[ix][iy][ip - 1] +
8167 ZDIFF(logp[ip - 1], met->
t[ix][iy][ip - 1],
8168 met->
h2o[ix][iy][ip - 1], logp[ip],
8169 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
8174 ZDIFF(lnps, ts, h2os, logp[ip0],
8175 met->
t[ix][iy][ip0], met->
h2o[ix][iy][ip0]));
8176 for (
int ip = ip0 - 1; ip >= 0; ip--)
8178 = (
float) (met->
z[ix][iy][ip + 1] +
8179 ZDIFF(logp[ip + 1], met->
t[ix][iy][ip + 1],
8180 met->
h2o[ix][iy][ip + 1], logp[ip],
8181 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
8185 if (dx == 0 || dy == 0)
8189 if (dx < 0 || dy < 0) {
8190 if (fabs(met->
lon[1] - met->
lon[0]) < 0.5) {
8200 float ws[dx + 1][dy + 1];
8201#pragma omp parallel for default(shared) collapse(2)
8202 for (
int ix = 0; ix <= dx; ix++)
8203 for (
int iy = 0; iy < dy; iy++)
8204 ws[ix][iy] = (1.0f - (
float) ix / (float) dx)
8205 * (1.0f - (float) iy / (
float) dy);
8208#pragma omp parallel for default(shared) collapse(3)
8209 for (
int ix = 0; ix < met->
nx; ix++)
8210 for (
int iy = 0; iy < met->
ny; iy++)
8211 for (
int ip = 0; ip < met->
np; ip++)
8212 help[
ARRAY_3D(ip, ix, met->
nx, iy, met->
ny)] = met->
z[ix][iy][ip];
8215#pragma omp parallel for default(shared) collapse(3)
8216 for (
int ip = 0; ip < met->
np; ip++)
8217 for (
int ix = 0; ix < met->
nx; ix++)
8218 for (
int iy = 0; iy < met->
ny; iy++) {
8219 float res = 0, wsum = 0;
8220 int iy0 =
MAX(iy - dy + 1, 0);
8221 int iy1 =
MIN(iy + dy - 1, met->
ny - 1);
8222 for (
int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
8226 else if (ix3 >= met->
nx)
8228 for (
int iy2 = iy0; iy2 <= iy1; ++iy2)
8229 if (isfinite(help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)])) {
8230 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
8231 res += w * help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)];
8236 met->
z[ix][iy][ip] = res / wsum;
8238 met->
z[ix][iy][ip] = NAN;
8248 const char *filename,
8254 char levname[
LEN], tstr[10];
8256 double rtime = 0, r, r2;
8258 int varid, ndims, dimids[NC_MAX_DIMS], year2, mon2, day2, hour2, min2, sec2,
8259 year, mon, day, hour, min, sec;
8265 LOG(2,
"Read meteo grid information...");
8274 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
8275 if (nc_inq_varid(ncid,
"time", &varid) == NC_NOERR) {
8276 NC(nc_get_var_double(ncid, varid, &rtime));
8277 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
8278 WARN(
"Time information in meteo file does not match filename!");
8280 WARN(
"Time information in meteo file is missing!");
8291 sprintf(tstr,
"19%.2s", &filename[strlen(filename) - 11]);
8293 sprintf(tstr,
"20%.2s", &filename[strlen(filename) - 11]);
8295 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 9]);
8297 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 7]);
8299 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 5]);
8305 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
8306 || day < 1 || day > 31 || hour < 0 || hour > 23)
8307 ERRMSG(
"Cannot read time from filename!");
8308 jsec2time(met->
time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
8309 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
8310 met->
time, year2, mon2, day2, hour2, min2);
8313 if (nc_inq_varid(ncid,
"u", &varid) != NC_NOERR)
8314 if (nc_inq_varid(ncid,
"U", &varid) != NC_NOERR)
8316 (
"Variable 'u' or 'U' not found, cannot determine vertical dimension!");
8318 NC(nc_inq_varndims(ncid, varid, &ndims));
8319 NC(nc_inq_vardimid(ncid, varid, dimids));
8323 (ncid, dimids[ctl->
met_convention == 0 ? 1 : 3], levname, &dimlen));
8324 }
else if (ndims == 3) {
8326 (ncid, dimids[ctl->
met_convention == 0 ? 0 : 2], levname, &dimlen));
8328 ERRMSG(
"Cannot determine vertical dimension!")
8329 met->
np = (int) dimlen;
8331 LOG(2,
"Number of levels: %d", met->
np);
8332 if (met->
np < 2 || met->
np >
EP)
8333 ERRMSG(
"Number of levels out of range!");
8339 LOG(2,
"Number of longitudes: %d", met->
nx);
8342 LOG(2,
"Number of latitudes: %d", met->
ny);
8346 LOG(2,
"Longitudes: %g, %g ... %g deg",
8349 LOG(2,
"Latitudes: %g, %g ... %g deg",
8362 for (
int ip = 0; ip < met->
np; ip++)
8364 LOG(2,
"Altitude levels: %g, %g ... %g km",
8365 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
8366 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
8367 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
8371 if (strcasecmp(levname,
"hybrid") == 0)
8383 ERRMSG(
"You need to specify MET_NLEV, MET_LEV_HYAM, and MET_LEV_HYBM!");
8384 for (
int ip = 0; ip < ctl->
met_nlev; ip++) {
8392 met->
eta[k] = met->
hyam[k] / 100000.0 + met->
hybm[k];
8394 ERRMSG(
"Eta levels must be ascending!");
8398 for (
int ix = 2; ix < met->
nx; ix++)
8400 (fabs(met->
lon[ix] - met->
lon[ix - 1]) -
8401 fabs(met->
lon[1] - met->
lon[0])) > 0.001)
8402 ERRMSG(
"No regular grid spacing in longitudes!");
8403 for (
int iy = 2; iy < met->
ny; iy++)
8405 (fabs(met->
lat[iy] - met->
lat[iy - 1]) -
8406 fabs(met->
lat[1] - met->
lat[0])) > 0.001) {
8407 WARN(
"No regular grid spacing in latitudes!");
8422 LOG(2,
"Read surface data...");
8426 (ncid,
"lnsp",
"LNSP", NULL, NULL, NULL, NULL, ctl, met, dd, met->
ps,
8428 for (
int ix = 0; ix < met->
nx; ix++)
8429 for (
int iy = 0; iy < met->
ny; iy++)
8430 met->
ps[ix][iy] = (
float) (exp(met->
ps[ix][iy]) / 100.);
8433 (ncid,
"ps",
"PS",
"sp",
"SP", NULL, NULL, ctl, met, dd, met->
ps,
8435 WARN(
"Cannot not read surface pressure data (use lowest level)!");
8436 for (
int ix = 0; ix < met->
nx; ix++)
8437 for (
int iy = 0; iy < met->
ny; iy++)
8439 = (ctl->
met_np > 0 ? (
float) ctl->
met_p[0] : (
float) met->
p[0]);
8447 (ncid,
"z",
"Z", NULL, NULL, NULL, NULL, ctl, met, dd, met->
zs,
8448 (
float) (1. / (1000. *
G0)), 1))
8450 (ncid,
"zm",
"ZM", NULL, NULL, NULL, NULL, ctl, met, dd, met->
zs,
8451 (
float) (1. / 1000.), 1))
8452 WARN(
"Cannot read surface geopotential height!");
8463 memcpy(help, met->
pl,
sizeof(met->
pl));
8465 (ncid,
"gph",
"GPH", NULL, NULL, ctl, met, dd, met->
pl,
8466 (
float) (1e-3 /
G0)))
8467 ERRMSG(
"Cannot read geopotential height!");
8468 for (
int ix = 0; ix < met->
nx; ix++)
8469 for (
int iy = 0; iy < met->
ny; iy++)
8470 met->
zs[ix][iy] = met->
pl[ix][iy][0];
8471 memcpy(met->
pl, help,
sizeof(met->
pl));
8477 (ncid,
"t2m",
"T2M",
"2t",
"2T",
"t2",
"T2", ctl, met, dd, met->
ts, 1.0,
8479 WARN(
"Cannot read surface temperature!");
8483 (ncid,
"u10m",
"U10M",
"10u",
"10U",
"u10",
"U10", ctl, met, dd,
8485 WARN(
"Cannot read surface zonal wind!");
8489 (ncid,
"v10m",
"V10M",
"10v",
"10V",
"v10",
"V10", ctl, met, dd,
8491 WARN(
"Cannot read surface meridional wind!");
8495 (ncid,
"iews",
"IEWS", NULL, NULL, NULL, NULL, ctl, met, dd, met->
ess,
8497 WARN(
"Cannot read eastward turbulent surface stress!");
8501 (ncid,
"inss",
"INSS", NULL, NULL, NULL, NULL, ctl, met, dd, met->
nss,
8503 WARN(
"Cannot read nothward turbulent surface stress!");
8507 (ncid,
"ishf",
"ISHF", NULL, NULL, NULL, NULL, ctl, met, dd, met->
shf,
8509 WARN(
"Cannot read surface sensible heat flux!");
8513 (ncid,
"lsm",
"LSM", NULL, NULL, NULL, NULL, ctl, met, dd, met->
lsm,
8515 WARN(
"Cannot read land-sea mask!");
8519 (ncid,
"sstk",
"SSTK",
"sst",
"SST", NULL, NULL, ctl, met, dd, met->
sst,
8521 WARN(
"Cannot read sea surface temperature!");
8526 (ncid,
"blp",
"BLP", NULL, NULL, NULL, NULL, ctl, met, dd, met->
pbl,
8528 WARN(
"Cannot read planetary boundary layer pressure!");
8531 (ncid,
"blh",
"BLH", NULL, NULL, NULL, NULL, ctl, met, dd, met->
pbl,
8533 WARN(
"Cannot read planetary boundary layer height!");
8538 (ncid,
"cape",
"CAPE", NULL, NULL, NULL, NULL, ctl, met, dd,
8540 WARN(
"Cannot read CAPE!");
8545 (ncid,
"cin",
"CIN", NULL, NULL, NULL, NULL, ctl, met, dd, met->
cin,
8547 WARN(
"Cannot read convective inhibition!");
8559 SELECT_TIMER(
"READ_MET_NC_LEVELS",
"INPUT", NVTX_READ);
8560 LOG(2,
"Read level data...");
8564 (ncid,
"t",
"T",
"temp",
"TEMP", ctl, met, dd, met->
t, 1.0))
8565 ERRMSG(
"Cannot read temperature!");
8568 if (!
read_met_nc_3d(ncid,
"u",
"U", NULL, NULL, ctl, met, dd, met->
u, 1.0))
8569 ERRMSG(
"Cannot read zonal wind!");
8570 if (!
read_met_nc_3d(ncid,
"v",
"V", NULL, NULL, ctl, met, dd, met->
v, 1.0))
8571 ERRMSG(
"Cannot read meridional wind!");
8573 (ncid,
"w",
"W",
"omega",
"OMEGA", ctl, met, dd, met->
w, 0.01f))
8574 WARN(
"Cannot read vertical velocity!");
8579 (ncid,
"q",
"Q",
"sh",
"SH", ctl, met, dd, met->
h2o,
8581 WARN(
"Cannot read specific humidity!");
8584 (ncid,
"rh",
"RH", NULL, NULL, ctl, met, dd, met->
h2o, 0.01f))
8585 WARN(
"Cannot read relative humidity!");
8586#pragma omp parallel for default(shared) collapse(2)
8587 for (
int ix = 0; ix < met->
nx; ix++)
8588 for (
int iy = 0; iy < met->
ny; iy++)
8589 for (
int ip = 0; ip < met->
np; ip++) {
8590 double pw = met->
h2o[ix][iy][ip] *
PSAT(met->
t[ix][iy][ip]);
8591 met->
h2o[ix][iy][ip] =
8592 (float) (pw / (met->
p[ip] - (1.0 -
EPS) * pw));
8598 (ncid,
"o3",
"O3", NULL, NULL, ctl, met, dd, met->
o3,
8599 (
float) (
MA /
MO3)))
8600 WARN(
"Cannot read ozone data!");
8604 (ncid,
"clwc",
"CLWC", NULL, NULL, ctl, met, dd, met->
lwc, 1.0))
8605 WARN(
"Cannot read cloud liquid water content!");
8607 (ncid,
"crwc",
"CRWC", NULL, NULL, ctl, met, dd, met->
rwc, 1.0))
8608 WARN(
"Cannot read cloud rain water content!");
8610 (ncid,
"ciwc",
"CIWC", NULL, NULL, ctl, met, dd, met->
iwc, 1.0))
8611 WARN(
"Cannot read cloud ice water content!");
8613 (ncid,
"cswc",
"CSWC", NULL, NULL, ctl, met, dd, met->
swc, 1.0))
8614 WARN(
"Cannot read cloud snow water content!");
8616 (ncid,
"cc",
"CC", NULL, NULL, ctl, met, dd, met->
cc, 1.0))
8617 WARN(
"Cannot read cloud cover!");
8622 (ncid,
"ZETA",
"zeta", NULL, NULL, ctl, met, dd, met->
zetal, 1.0))
8623 WARN(
"Cannot read ZETA!");
8625 (ncid,
"ZETA_DOT_TOT",
"ZETA_DOT_clr",
"zeta_dot_clr",
8626 NULL, ctl, met, dd, met->
zeta_dotl, 0.00001157407f))
8627 WARN(
"Cannot read ZETA_DOT!");
8632#pragma omp parallel for default(shared)
8633 for (
int ix = 0; ix < met->
nx; ix++)
8634 for (
int iy = 0; iy < met->
ny; iy++)
8635 for (
int ip = 0; ip < met->
np; ip++)
8636 met->
zetal[ix][iy][ip] =
8637 (
float) (met->
hyam[ip] / 100000.0 + met->
hybm[ip]);
8639 (ncid,
"etadot",
"ETADOT", NULL, NULL, ctl, met, dd, met->
zeta_dotl,
8641 WARN(
"Cannot read eta vertical velocity!");
8646#pragma omp parallel for default(shared)
8647 for (
int ix = 0; ix < met->
nx; ix++)
8648 for (
int iy = 0; iy < met->
ny; iy++)
8649 for (
int ip = 0; ip < met->
np; ip++) {
8650 met->
ul[ix][iy][ip] = met->
u[ix][iy][ip];
8651 met->
vl[ix][iy][ip] = met->
v[ix][iy][ip];
8652 met->
wl[ix][iy][ip] = met->
w[ix][iy][ip];
8665 (ncid,
"pl",
"PL",
"pressure",
"PRESSURE", ctl, met, dd, met->
pl,
8668 (ncid,
"press",
"PRESS", NULL, NULL, ctl, met, dd, met->
pl, 1.0))
8669 ERRMSG(
"Cannot read pressure on model levels!");
8677 ERRMSG(
"Mismatch in number of model levels!");
8680 for (
int ix = 0; ix < met->
nx; ix++)
8681 for (
int iy = 0; iy < met->
ny; iy++)
8682 for (
int ip = 0; ip < met->
np; ip++)
8683 met->
pl[ix][iy][ip] =
8684 (
float) (met->
hyam[ip] / 100. +
8685 met->
hybm[ip] * met->
ps[ix][iy]);
8693 ERRMSG(
"Mismatch in number of model levels!");
8696#pragma omp parallel for default(shared) collapse(2)
8697 for (
int ix = 0; ix < met->
nx; ix++)
8698 for (
int iy = 0; iy < met->
ny; iy++)
8699 for (
int ip = 0; ip < met->
np; ip++) {
8701 met->
hyam[ip] / 100. + met->
hybm[ip] * met->
ps[ix][iy];
8703 met->
hyam[ip + 1] / 100. + met->
hybm[ip + 1] * met->
ps[ix][iy];
8704 met->
pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
8709 for (
int ix = 0; ix < met->
nx; ix++)
8710 for (
int iy = 0; iy < met->
ny; iy++)
8711 for (
int ip = 1; ip < met->
np; ip++)
8712 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
8713 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
8714 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
8715 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip]))
8716 ERRMSG(
"Pressure profiles are not monotonic!");
8737 for (
int ip = 0; ip < met->
np; ip++)
8738 met->
p[ip] = ctl->
met_p[ip];
8742 for (
int ip = 1; ip < met->
np; ip++)
8743 if (met->
p[ip - 1] < met->
p[ip])
8744 ERRMSG(
"Pressure levels must be descending!");
8751 const char *varname,
8752 const char *varname2,
8753 const char *varname3,
8754 const char *varname4,
8755 const char *varname5,
8756 const char *varname6,
8766 float offset, scalfac;
8771 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
8772 sprintf(varsel,
"%s", varname);
8773 else if (varname2 != NULL
8774 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
8775 sprintf(varsel,
"%s", varname2);
8776 else if (varname3 != NULL
8777 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
8778 sprintf(varsel,
"%s", varname3);
8779 else if (varname4 != NULL
8780 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
8781 sprintf(varsel,
"%s", varname4);
8782 else if (varname5 != NULL
8783 && nc_inq_varid(ncid, varname5, &varid) == NC_NOERR)
8784 sprintf(varsel,
"%s", varname5);
8785 else if (varname6 != NULL
8786 && nc_inq_varid(ncid, varname6, &varid) == NC_NOERR)
8787 sprintf(varsel,
"%s", varname6);
8793 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
8794 && nc_get_att_float(ncid, varid,
"scale_factor",
8795 &scalfac) == NC_NOERR) {
8803 short fillval, missval;
8804 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8806 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8810 LOG(2,
"Read 2-D variable: %s"
8811 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
8812 varsel, fillval, missval, scalfac, offset);
8815 NC(nc_get_var_short(ncid, varid, help));
8819 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
8823#pragma omp parallel for default(shared)
8824 for (
int ix = 0; ix < met->
nx; ix++)
8825 for (
int iy = 0; iy < met->
ny; iy++) {
8828 const short aux = help[
ARRAY_2D(iy, ix, met->
nx)];
8829 if ((fillval == 0 || aux != fillval)
8830 && (missval == 0 || aux != missval)
8831 && fabsf(aux * scalfac + offset) < 1e14f)
8832 dest[ix][iy] += scl * (aux * scalfac + offset);
8843 else if (!ctl->
dd) {
8851 float fillval, missval;
8852 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8854 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8858 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
8859 varsel, fillval, missval);
8862 NC(nc_get_var_float(ncid, varid, help));
8869#pragma omp parallel for default(shared)
8870 for (
int ix = 0; ix < met->
nx; ix++)
8871 for (
int iy = 0; iy < met->
ny; iy++) {
8874 const float aux = help[
ARRAY_2D(iy, ix, met->
nx)];
8875 if ((fillval == 0 || aux != fillval)
8876 && (missval == 0 || aux != missval)
8877 && fabsf(aux) < 1e14f)
8878 dest[ix][iy] += scl * aux;
8888#pragma omp parallel for default(shared)
8889 for (
int iy = 0; iy < met->
ny; iy++)
8890 for (
int ix = 0; ix < met->
nx; ix++) {
8893 const float aux = help[
ARRAY_2D(ix, iy, met->
ny)];
8894 if ((fillval == 0 || aux != fillval)
8895 && (missval == 0 || aux != missval)
8896 && fabsf(aux) < 1e14f)
8897 dest[ix][iy] += scl * aux;
8912 float fillval, missval;
8913 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8915 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8919 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
8920 varsel, fillval, missval);
8924 size_t help_subdomain_start[3];
8925 size_t help_subdomain_count[3];
8927 help_subdomain_start[0] = 0;
8931 help_subdomain_count[0] = 1;
8940 NC(nc_get_vara_float
8941 (ncid, varid, help_subdomain_start, help_subdomain_count, help));
8944 size_t help_halo_bnd_start[3];
8945 size_t help_halo_bnd_count[3];
8947 help_halo_bnd_start[0] = 0;
8951 help_halo_bnd_count[0] = 1;
8956 ALLOC(help_halo,
float,
8957 help_halo_bnd_count[1] * help_halo_bnd_count[2]);
8958 NC(nc_get_vara_float
8959 (ncid, varid, help_halo_bnd_start, help_halo_bnd_count, help_halo));
8964#pragma omp parallel for default(shared) num_threads(12)
8965 for (
int ix = 0; ix < (int) help_subdomain_count[2]; ix++)
8966 for (
int iy = 0; iy < (int) help_subdomain_count[1]; iy++) {
8970 help[
ARRAY_2D(iy, ix, (
int) help_subdomain_count[2])];
8971 if ((fillval == 0 || aux != fillval)
8972 && (missval == 0 || aux != missval)
8973 && fabsf(aux) < 1e14f) {
8980#pragma omp parallel for default(shared) num_threads(12)
8981 for (
int ix = 0; ix < (int) help_halo_bnd_count[2]; ix++)
8982 for (
int iy = 0; iy < (int) help_halo_bnd_count[1]; iy++) {
8986 help_halo[
ARRAY_2D(iy, ix, (
int) help_halo_bnd_count[2])];
8987 if ((fillval == 0 || aux != fillval)
8988 && (missval == 0 || aux != missval)
8989 && fabsf(aux) < 1e14f)
8997 ERRMSG(
"Domain decomposition with data convection incompatible!");
9013 const char *varname,
9014 const char *varname2,
9015 const char *varname3,
9016 const char *varname4,
9027 float offset, scalfac;
9032 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
9033 sprintf(varsel,
"%s", varname);
9034 else if (varname2 != NULL
9035 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
9036 sprintf(varsel,
"%s", varname2);
9037 else if (varname3 != NULL
9038 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
9039 sprintf(varsel,
"%s", varname3);
9040 else if (varname4 != NULL
9041 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
9042 sprintf(varsel,
"%s", varname4);
9047 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
9048 && nc_get_att_float(ncid, varid,
"scale_factor",
9049 &scalfac) == NC_NOERR) {
9057 short fillval, missval;
9058 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9060 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9064 LOG(2,
"Read 3-D variable: %s "
9065 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
9066 varsel, fillval, missval, scalfac, offset);
9069 NC(nc_get_var_short(ncid, varid, help));
9073 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
9077#pragma omp parallel for default(shared)
9078 for (
int ix = 0; ix < met->
nx; ix++)
9079 for (
int iy = 0; iy < met->
ny; iy++)
9080 for (
int ip = 0; ip < met->
np; ip++) {
9081 const short aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
9082 if ((fillval == 0 || aux != fillval)
9083 && (missval == 0 || aux != missval)
9084 && fabsf(aux * scalfac + offset) < 1e14f)
9085 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
9087 dest[ix][iy][ip] = NAN;
9096 else if (!ctl->
dd) {
9104 float fillval, missval;
9105 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9107 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9111 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
9112 varsel, fillval, missval);
9115 NC(nc_get_var_float(ncid, varid, help));
9122#pragma omp parallel for default(shared)
9123 for (
int ix = 0; ix < met->
nx; ix++)
9124 for (
int iy = 0; iy < met->
ny; iy++)
9125 for (
int ip = 0; ip < met->
np; ip++) {
9126 const float aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
9127 if ((fillval == 0 || aux != fillval)
9128 && (missval == 0 || aux != missval)
9129 && fabsf(aux) < 1e14f)
9130 dest[ix][iy][ip] = scl * aux;
9132 dest[ix][iy][ip] = NAN;
9140#pragma omp parallel for default(shared)
9141 for (
int ip = 0; ip < met->
np; ip++)
9142 for (
int iy = 0; iy < met->
ny; iy++)
9143 for (
int ix = 0; ix < met->
nx; ix++) {
9144 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9145 if ((fillval == 0 || aux != fillval)
9146 && (missval == 0 || aux != missval)
9147 && fabsf(aux) < 1e14f)
9148 dest[ix][iy][ip] = scl * aux;
9150 dest[ix][iy][ip] = NAN;
9163 float fillval, missval;
9164 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9166 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9170 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
9171 varsel, fillval, missval);
9173 SELECT_TIMER(
"read_met_nc_3d_CP1",
"INPUT", NVTX_READ);
9183 SELECT_TIMER(
"read_met_nc_3d_CP2",
"INPUT", NVTX_READ);
9186 NC(nc_get_vara_float
9191 ALLOC(help_halo,
float,
9195 SELECT_TIMER(
"read_met_nc_3d_CP3",
"INPUT", NVTX_READ);
9198 NC(nc_get_vara_float(ncid,
9202 SELECT_TIMER(
"read_met_nc_3d_CP4",
"INPUT", NVTX_READ);
9207#pragma omp parallel for default(shared) num_threads(12)
9210 for (
int ip = 0; ip < met->
np; ip++) {
9214 if ((fillval == 0 || aux != fillval)
9215 && (missval == 0 || aux != missval)
9216 && fabsf(aux) < 1e14f)
9222#pragma omp parallel for default(shared) num_threads(12)
9225 for (
int ip = 0; ip < met->
np; ip++) {
9229 if ((fillval == 0 || aux != fillval)
9230 && (missval == 0 || aux != missval)
9231 && fabsf(aux) < 1e14f)
9240#pragma omp parallel for default(shared) num_threads(12)
9241 for (
int ip = 0; ip < met->
np; ip++)
9244 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9245 if ((fillval == 0 || aux != fillval)
9246 && (missval == 0 || aux != missval)
9247 && fabsf(aux) < 1e14f)
9253#pragma omp parallel for default(shared) num_threads(12)
9254 for (
int ip = 0; ip < met->
np; ip++)
9257 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9258 if ((fillval == 0 || aux != fillval)
9259 && (missval == 0 || aux != missval)
9260 && fabsf(aux) < 1e14f)
9280 const char *filename,
9285 size_t filename_len = strlen(filename) + 1;
9286 char sf_filename[filename_len];
9287 char ml_filename[filename_len];
9288 strcpy(sf_filename, filename);
9289 strcpy(ml_filename, filename);
9294 FILE *ml_file = fopen(ml_filename,
"rb");
9295 FILE *sf_file = fopen(sf_filename,
"rb");
9296 if (ml_file == NULL || sf_file == NULL) {
9297 if (ml_file != NULL) {
9299 WARN(
"Cannot open file: %s", sf_filename);
9301 if (sf_file != NULL) {
9303 WARN(
"Cannot open file: %s", ml_filename);
9309 int ml_num_messages = 0, err = 0;
9310 ECC(codes_count_in_file(0, ml_file, &ml_num_messages));
9313 (size_t) ml_num_messages);
9314 for (
int i = 0; i < ml_num_messages; i++) {
9316 if ((h = codes_grib_handle_new_from_file(0, ml_file, &err)) != NULL)
9321 int sf_num_messages = 0;
9322 ECC(codes_count_in_file(0, sf_file, &sf_num_messages));
9325 (size_t) sf_num_messages);
9326 for (
int i = 0; i < sf_num_messages; i++) {
9328 if ((h = codes_grib_handle_new_from_file(0, sf_file, &err)) != NULL)
9341 for (
int i = 0; i < sf_num_messages; i++)
9342 codes_handle_delete(sf_handles[i]);
9346 size_t value_count = 0;
9347 ECC(codes_get_size(ml_handles[0],
"pv", &value_count));
9348 if (value_count % 2 != 0)
9349 ERRMSG(
"Unexpected pv array length!");
9350 size_t nlevels = value_count / 2 - 1;
9352 ALLOC(values,
double,
9354 ECC(codes_get_double_array(ml_handles[0],
"pv", values, &value_count));
9355 double *a_vals = values;
9356 double *b_vals = values + nlevels;
9357 if (met->
npl > (
int) nlevels)
9358 ERRMSG(
"met->npl exceeds number of pressure levels in GRIB!");
9359 for (
int nx = 0; nx < met->
nx; nx++)
9360 for (
int ny = 0; ny < met->
ny; ny++)
9361 for (
int level = 0; level <= met->
npl; level++) {
9362 const float p1 = (float) (a_vals[level] * 0.01f +
9363 met->
ps[nx][ny] * b_vals[level]);
9364 const float p2 = (float) (a_vals[level + 1] * 0.01f +
9365 met->
ps[nx][ny] * b_vals[level + 1]);
9366 met->
pl[nx][ny][level] = 0.5f * (p1 + p2);
9372 for (
int i = 0; i < ml_num_messages; i++)
9373 codes_handle_delete(ml_handles[i]);
9390 SELECT_TIMER(
"READ_MET_GRIB_GRID",
"INPUT", NVTX_READ);
9391 LOG(2,
"Read meteo grid information...");
9394 char datestr[
LEN], timestr[
LEN];
9395 size_t s_date =
sizeof(datestr);
9396 ECC(codes_get_string(handles[0],
"dataDate", datestr, &s_date));
9397 size_t s_time =
sizeof(timestr);
9398 ECC(codes_get_string(handles[0],
"dataTime", timestr, &s_time));
9399 int year, month, day, hour;
9400 if (sscanf(datestr,
"%4d%2d%2d", &year, &month, &day) != 3)
9401 ERRMSG(
"Failed to parse dataDate: %s", datestr);
9402 if (sscanf(timestr,
"%2d", &hour) != 1)
9403 ERRMSG(
"Failed to parse dataTime: %s", timestr);
9405 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)", met->
time, year, month,
9409 long count_lat = 0, count_lon = 0;
9410 ECC(codes_get_long(handles[0],
"Nj", &count_lat));
9411 ECC(codes_get_long(handles[0],
"Ni", &count_lon));
9412 met->
ny = (int) count_lat;
9413 met->
nx = (int) count_lon;
9416 LOG(2,
"Number of longitudes: %d", met->
nx);
9417 if (met->
nx < 2 || met->
nx >
EX)
9418 ERRMSG(
"Number of longitudes out of range!");
9419 LOG(2,
"Number of latitudes: %d", met->
ny);
9420 if (met->
ny < 2 || met->
ny >
EY)
9421 ERRMSG(
"Number of latitudes out of range!");
9423 double first_lon, last_lon, first_lat, last_lat, inc_lon, inc_lat;
9424 ECC(codes_get_double
9425 (handles[0],
"longitudeOfFirstGridPointInDegrees", &first_lon));
9426 ECC(codes_get_double
9427 (handles[0],
"latitudeOfFirstGridPointInDegrees", &first_lat));
9428 ECC(codes_get_double
9429 (handles[0],
"longitudeOfLastGridPointInDegrees", &last_lon));
9430 ECC(codes_get_double
9431 (handles[0],
"latitudeOfLastGridPointInDegrees", &last_lat));
9432 ECC(codes_get_double(handles[0],
"iDirectionIncrementInDegrees", &inc_lon));
9433 ECC(codes_get_double(handles[0],
"jDirectionIncrementInDegrees", &inc_lat));
9435 long jscanpos, iscanneg;
9436 ECC(codes_get_long(handles[0],
"iScansNegatively", &iscanneg));
9437 ECC(codes_get_long(handles[0],
"jScansPositively", &jscanpos));
9442 for (
double i = first_lon; i <= last_lon + 1e-6; i += inc_lon) {
9443 met->
lon[counter] = i;
9446 for (
double i = first_lon; i > last_lon - 1e-6; i -= inc_lon) {
9447 met->
lon[counter] = i;
9453 for (
double i = first_lat; i > last_lat - 1e-6; i -= inc_lat) {
9454 met->
lat[counter] = i;
9457 for (
double i = first_lat; i <= last_lat + 1e-6; i += inc_lat) {
9458 met->
lat[counter] = i;
9463 LOG(2,
"Longitudes: %g, %g ... %g deg",
9465 LOG(2,
"Latitudes: %g, %g ... %g deg",
9470 for (
int i = 0; i < count_handles; i++) {
9472 ECC(codes_get_long(handles[i],
"level", &level));
9473 if (level > max_level)
9474 max_level = (int) level;
9476 met->
npl = max_level;
9479 LOG(2,
"Number of levels: %d", met->
npl);
9481 ERRMSG(
"Number of levels out of range!");
9490 const int num_messages,
9495 SELECT_TIMER(
"READ_MET_GRIB_LEVELS",
"INPUT", NVTX_READ);
9496 LOG(2,
"Read level data...");
9499 int t_flag = 0, u_flag = 0, v_flag = 0, w_flag = 0, o3_flag = 0, h2o_flag =
9500 0, lwc_flag = 0, rwc_flag = 0, iwc_flag = 0, swc_flag = 0, cc_flag = 0;
9503 for (
int i = 0; i < num_messages; i++) {
9505 size_t max_size =
LEN;
9506 char short_name[max_size];
9512 ECC(codes_get_long(handles[i],
"level", ¤t_level));
9516 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
9517 ECC(codes_get_size(handles[i],
"values", &value_count));
9518 ALLOC(values,
double,
9520 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
9528 ECC_READ_3D(
"w", current_level, met->
w, 0.01f, w_flag);
9546 if (t_flag != met->
npl)
9547 ERRMSG(
"Cannot read temperature!");
9548 if (u_flag != met->
npl)
9549 ERRMSG(
"Cannot read zonal wind!");
9550 if (v_flag != met->
npl)
9551 ERRMSG(
"Cannot read meridional wind!");
9552 if (w_flag != met->
npl)
9553 WARN(
"Cannot read vertical velocity!");
9554 if (h2o_flag != met->
npl)
9555 WARN(
"Cannot read specific humidity!");
9556 if (o3_flag != met->
npl)
9557 WARN(
"Cannot read ozone data!");
9558 if (lwc_flag != met->
npl)
9559 WARN(
"Cannot read cloud liquid water content!");
9560 if (rwc_flag != met->
npl)
9561 WARN(
"Cannot read cloud rain water content!");
9562 if (iwc_flag != met->
npl)
9563 WARN(
"Cannot read cloud ice water content!");
9564 if (swc_flag != met->
npl)
9565 WARN(
"Cannot read cloud snow water content!");
9566 if (cc_flag != met->
npl)
9567 WARN(
"Cannot read cloud cover!");
9570 for (
int ix = 0; ix < met->
nx; ix++)
9571 for (
int iy = 0; iy < met->
ny; iy++)
9572 for (
int ip = 1; ip < met->
np; ip++)
9573 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
9574 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
9575 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
9576 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip])) {
9577 LOG(1,
"%f %f %f %f", met->
pl[ix][iy][0], met->
pl[ix][iy][1],
9578 met->
pl[ix][iy][ip - 1], met->
pl[ix][iy][ip]);
9579 ERRMSG(
"Pressure profiles are not monotonic!");
9600 for (
int ip = 0; ip < met->
np; ip++)
9601 met->
p[ip] = ctl->
met_p[ip];
9605 for (
int ip = 1; ip < met->
np; ip++)
9606 if (met->
p[ip - 1] < met->
p[ip])
9607 ERRMSG(
"Pressure levels must be descending!");
9616 const int num_messages,
9621 SELECT_TIMER(
"READ_MET_GRIB_SURFACE",
"INPUT", NVTX_READ);
9622 LOG(2,
"Read surface data...");
9625 int sp_flag = 0, z_flag = 0, t_flag = 0, u_flag = 0, v_flag = 0, lsm_flag =
9626 0, sst_flag = 0, cape_flag = 0, cin_flag = 0, pbl_flag = 0;
9629 for (
int i = 0; i < num_messages; i++) {
9631 size_t max_size =
LEN, value_count;
9633 char short_name[max_size];
9636 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
9637 ECC(codes_get_size(handles[i],
"values", &value_count));
9638 double *values = (
double *) malloc(value_count *
sizeof(
double));
9639 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
9677 WARN(
"Cannot read surface pressure data!");
9679 WARN(
"Cannot read surface geopotential height!");
9681 WARN(
"Cannot read surface temperature!");
9683 WARN(
"Cannot read surface zonal wind!");
9685 WARN(
"Cannot read surface meridional wind!");
9687 WARN(
"Cannot read land-sea mask!");
9689 WARN(
"Cannot read sea surface temperature!");
9692 WARN(
"Cannot read CAPE!");
9694 WARN(
"Cannot read convective inhibition!");
9696 if (ctl->
met_pbl == 0 && pbl_flag == 0)
9697 WARN(
"Cannot read planetary boundary layer!");
9707 const char *varname) {
9709 double aux[
EP], p[
EP];
9713 LOG(2,
"Interpolate meteo data to pressure levels: %s", varname);
9716#pragma omp parallel for default(shared) private(aux,p) collapse(2)
9717 for (
int ix = 0; ix < met->
nx; ix++)
9718 for (
int iy = 0; iy < met->
ny; iy++) {
9721 for (
int ip = 0; ip < met->
np; ip++)
9722 p[ip] = met->
pl[ix][iy][ip];
9725 for (
int ip = 0; ip < ctl->
met_np; ip++) {
9726 double pt = ctl->
met_p[ip];
9727 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
9729 else if ((pt > p[met->
np - 1] && p[1] > p[0])
9730 || (pt < p[met->
np - 1] && p[1] < p[0]))
9731 pt = p[met->
np - 1];
9733 aux[ip] =
LIN(p[ip2], var[ix][iy][ip2],
9734 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
9738 for (
int ip = 0; ip < ctl->
met_np; ip++)
9739 var[ix][iy][ip] = (
float) aux[ip];
9754 SELECT_TIMER(
"READ_MET_MONOTONIZE",
"METPROC", NVTX_READ);
9755 LOG(2,
"Make zeta profiles monotone...");
9758#pragma omp parallel for default(shared) collapse(2)
9759 for (
int i = 0; i < met->
nx; i++)
9760 for (
int j = 0; j < met->
ny; j++) {
9763 while (k < met->npl) {
9764 if ((met->
zetal[i][j][k - 1] >= met->
zetal[i][j][k])) {
9770 while ((met->
zetal[i][j][k - 1] >=
9771 met->
zetal[i][j][k + l]) & (k + l < met->npl));
9776 (float) (met->
zetal[i][j][k + l] - met->
zetal[i][j][k - 1])
9779 for (
int m = k; m < k + l; m++) {
9780 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
9781 met->
zetal[i][j][m] = s * d + met->
zetal[i][j][k - 1];
9793#pragma omp parallel for default(shared) collapse(2)
9794 for (
int i = 0; i < met->
nx; i++)
9795 for (
int j = 0; j < met->
ny; j++) {
9798 while (k < met->npl) {
9799 if ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k])) {
9806 while ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k + l]) & (k + l <
9811 float s = (float) (met->
pl[i][j][k + l] - met->
pl[i][j][k - 1])
9814 for (
int m = k; m < k + l; m++) {
9815 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
9816 met->
pl[i][j][m] = s * d + met->
pl[i][j][k - 1];
9831 const char *filename,
9842 (filename, NC_NOWRITE | NC_SHARE, MPI_COMM_WORLD, MPI_INFO_NULL,
9846 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
9847 WARN(
"Cannot open file!");
9880 MPI_Comm_rank(MPI_COMM_WORLD, &dd->
rank);
9881 MPI_Comm_size(MPI_COMM_WORLD, &dd->
size);
9889 LOG(2,
"Number of longitudes: %d", help_nx_glob);
9893 LOG(2,
"Number of latitudes: %d", help_ny_glob);
9896 double *help_lon_glob;
9897 double *help_lat_glob;
9898 ALLOC(help_lon_glob,
double,
9900 ALLOC(help_lat_glob,
double,
9905 LOG(2,
"Longitudes: %g, %g ... %g deg",
9906 help_lon_glob[0], help_lon_glob[1], help_lon_glob[help_nx_glob - 1]);
9908 LOG(2,
"Latitudes: %g, %g ... %g deg",
9909 help_lat_glob[0], help_lat_glob[1], help_lat_glob[help_ny_glob - 1]);
9933 met->
nx = met->
nx + gap;
9934 WARN(
"Extended subdomains at the right to fit to full domain.");
9940 met->
ny = met->
ny + gap;
9941 WARN(
"Extended subdomains at the bottom to fit to full domain.");
9952 if (!left && !right) {
9969 if (!top && !bottom) {
9987 double lon_shift = 0;
9988 if (left || right) {
10006 lon_shift = (left ? -360 : 360);
10023 double lon_range = 360;
10034 double lat_range = help_lat_glob[help_ny_glob - 1] - help_lat_glob[0];
10061 if (lat_range < 0) {
10068 (
"lat_range > 0, but is expected to be negative, i.e. latitudes should range from 90 to -90")
10075 LOG(2,
"Total longitude range: %g deg", lon_range);
10076 LOG(2,
"Total latitude range: %g deg", lat_range);
10078 LOG(2,
"Define subdomain properties.");
10079 LOG(2,
"MPI information: Rank %d, Size %d", dd->
rank, dd->
size);
10080 LOG(2,
"Edge position: l=%d,r=%d,t=%d, b=%d", (
int) left, (
int) right,
10081 (
int) top, (
int) bottom);
10082 LOG(2,
"Sizes for limits: EX %d EY %d EP %d",
EX,
EY,
EP);
10083 LOG(2,
"Total size for subdomain meteo data: nx %d ny %d np %d", met->
nx,
10085 LOG(2,
"Hyperslab sizes for boundary halos: nx %d ny %d np %d",
10088 LOG(2,
"Hyperslab sizes for subdomain and inner halos: nx %d ny %d np %d",
10097 LOG(2,
" %d Subdomain longitudes: %g, %g ... %g deg (edges: %g to %g)",
10100 LOG(2,
" %d Subdomain latitudes: %g, %g ... %g deg (edges: %g to %g)",
10104 free(help_lon_glob);
10105 free(help_lat_glob);
10116 LOG(2,
"Calculate planetary boundary layer...");
10122#pragma omp parallel for default(shared) collapse(2)
10123 for (
int ix = 0; ix < met->
nx; ix++)
10124 for (
int iy = 0; iy < met->
ny; iy++) {
10127 const float z = met->
zs[ix][iy] + met->
pbl[ix][iy];
10130 (float) (
LIN(met->
z[ix][iy][ip], met->
p[ip],
10131 met->
z[ix][iy][ip + 1], met->
p[ip + 1], z));
10136 else if (ctl->
met_pbl == 2) {
10140 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
10143#pragma omp parallel for default(shared) collapse(2)
10144 for (
int ix = 0; ix < met->
nx; ix++)
10145 for (
int iy = 0; iy < met->
ny; iy++) {
10148 const double pbl_bot = met->
ps[ix][iy] * exp(-dz /
H0);
10152 for (ip = 1; ip < met->
np; ip++)
10153 if (met->
p[ip] < pbl_bot)
10157 const double h2os =
LIN(met->
p[ip - 1], met->
h2o[ix][iy][ip - 1],
10158 met->
p[ip], met->
h2o[ix][iy][ip], pbl_bot);
10159 const double tvs =
THETAVIRT(pbl_bot, met->
ts[ix][iy], h2os);
10162 double rib_old = 0;
10165 for (; ip < met->
np; ip++) {
10168 double vh2 =
SQR(met->
u[ix][iy][ip] - met->
us[ix][iy])
10169 +
SQR(met->
v[ix][iy][ip] - met->
vs[ix][iy]);
10170 vh2 =
MAX(vh2,
SQR(umin));
10174 G0 * 1e3 * (met->
z[ix][iy][ip] - met->
zs[ix][iy]) / tvs
10176 met->
h2o[ix][iy][ip]) - tvs) / vh2;
10179 if (rib >= rib_crit) {
10180 met->
pbl[ix][iy] = (float) (
LIN(rib_old, met->
p[ip - 1],
10181 rib, met->
p[ip], rib_crit));
10182 if (met->
pbl[ix][iy] > pbl_bot)
10183 met->
pbl[ix][iy] = (float) pbl_bot;
10198 const double dtheta = 2.0, zmin = 0.1;
10201#pragma omp parallel for default(shared) collapse(2)
10202 for (
int ix = 0; ix < met->
nx; ix++)
10203 for (
int iy = 0; iy < met->
ny; iy++) {
10206 const double theta0 =
THETA(met->
ps[ix][iy], met->
ts[ix][iy]);
10210 for (ip = met->
np - 2; ip > 0; ip--)
10211 if (met->
p[ip] >= 300.)
10212 if (met->
p[ip] > met->
ps[ix][iy]
10213 ||
THETA(met->
p[ip], met->
t[ix][iy][ip]) <= theta0 + dtheta)
10218 = (float) (
LIN(
THETA(met->
p[ip + 1], met->
t[ix][iy][ip + 1]),
10220 THETA(met->
p[ip], met->
t[ix][iy][ip]),
10221 met->
p[ip], theta0 + dtheta));
10224 double pbl_min = met->
ps[ix][iy] * exp(-zmin /
H0);
10225 if (met->
pbl[ix][iy] > pbl_min || met->
p[ip] > met->
ps[ix][iy])
10226 met->
pbl[ix][iy] = (float) pbl_min;
10231#pragma omp parallel for default(shared) collapse(2)
10232 for (
int ix = 0; ix < met->
nx; ix++)
10233 for (
int iy = 0; iy < met->
ny; iy++) {
10237 met->
pbl[ix][iy] =
MIN(met->
pbl[ix][iy], (
float) pbl_min);
10241 met->
pbl[ix][iy] =
MAX(met->
pbl[ix][iy], (
float) pbl_max);
10251 SELECT_TIMER(
"READ_MET_PERIODIC",
"METPROC", NVTX_READ);
10252 LOG(2,
"Apply periodic boundary conditions...");
10255 if (!(fabs(met->
lon[met->
nx - 1] - met->
lon[0]
10256 + met->
lon[1] - met->
lon[0] - 360) < 0.01))
10260 if ((++met->
nx) >=
EX)
10261 ERRMSG(
"Cannot create periodic boundary conditions!");
10264 met->
lon[met->
nx - 1] = met->
lon[met->
nx - 2] + met->
lon[1] - met->
lon[0];
10267#pragma omp parallel for default(shared)
10268 for (
int iy = 0; iy < met->
ny; iy++) {
10269 met->
ps[met->
nx - 1][iy] = met->
ps[0][iy];
10270 met->
zs[met->
nx - 1][iy] = met->
zs[0][iy];
10271 met->
ts[met->
nx - 1][iy] = met->
ts[0][iy];
10272 met->
us[met->
nx - 1][iy] = met->
us[0][iy];
10273 met->
vs[met->
nx - 1][iy] = met->
vs[0][iy];
10274 met->
ess[met->
nx - 1][iy] = met->
ess[0][iy];
10275 met->
nss[met->
nx - 1][iy] = met->
nss[0][iy];
10276 met->
shf[met->
nx - 1][iy] = met->
shf[0][iy];
10277 met->
lsm[met->
nx - 1][iy] = met->
lsm[0][iy];
10278 met->
sst[met->
nx - 1][iy] = met->
sst[0][iy];
10279 met->
pbl[met->
nx - 1][iy] = met->
pbl[0][iy];
10280 met->
cape[met->
nx - 1][iy] = met->
cape[0][iy];
10281 met->
cin[met->
nx - 1][iy] = met->
cin[0][iy];
10282 for (
int ip = 0; ip < met->
np; ip++) {
10283 met->
t[met->
nx - 1][iy][ip] = met->
t[0][iy][ip];
10284 met->
u[met->
nx - 1][iy][ip] = met->
u[0][iy][ip];
10285 met->
v[met->
nx - 1][iy][ip] = met->
v[0][iy][ip];
10286 met->
w[met->
nx - 1][iy][ip] = met->
w[0][iy][ip];
10287 met->
h2o[met->
nx - 1][iy][ip] = met->
h2o[0][iy][ip];
10288 met->
o3[met->
nx - 1][iy][ip] = met->
o3[0][iy][ip];
10289 met->
lwc[met->
nx - 1][iy][ip] = met->
lwc[0][iy][ip];
10290 met->
rwc[met->
nx - 1][iy][ip] = met->
rwc[0][iy][ip];
10291 met->
iwc[met->
nx - 1][iy][ip] = met->
iwc[0][iy][ip];
10292 met->
swc[met->
nx - 1][iy][ip] = met->
swc[0][iy][ip];
10293 met->
cc[met->
nx - 1][iy][ip] = met->
cc[0][iy][ip];
10295 for (
int ip = 0; ip < met->
npl; ip++) {
10296 met->
ul[met->
nx - 1][iy][ip] = met->
ul[0][iy][ip];
10297 met->
vl[met->
nx - 1][iy][ip] = met->
vl[0][iy][ip];
10298 met->
wl[met->
nx - 1][iy][ip] = met->
wl[0][iy][ip];
10299 met->
pl[met->
nx - 1][iy][ip] = met->
pl[0][iy][ip];
10300 met->
zetal[met->
nx - 1][iy][ip] = met->
zetal[0][iy][ip];
10312 SELECT_TIMER(
"READ_MET_POLAR_WINDS",
"METPROC", NVTX_READ);
10313 LOG(2,
"Apply fix for polar winds...");
10316 if (fabs(met->
lat[0]) < 89.999 || fabs(met->
lat[met->
ny - 1]) < 89.999)
10320 for (
int ihem = 0; ihem < 2; ihem++) {
10323 int i89 = 1, i90 = 0, sign = 1;
10328 if (met->
lat[i90] < 0)
10332 double clon[
EX], slon[
EX];
10333#pragma omp parallel for default(shared)
10334 for (
int ix = 0; ix < met->
nx; ix++) {
10335 clon[ix] = cos(sign *
DEG2RAD(met->
lon[ix]));
10336 slon[ix] = sin(sign *
DEG2RAD(met->
lon[ix]));
10340#pragma omp parallel for default(shared)
10341 for (
int ip = 0; ip < met->
np; ip++) {
10344 double vel89x = 0, vel89y = 0;
10345 for (
int ix = 0; ix < met->
nx; ix++) {
10347 (met->
u[ix][i89][ip] * clon[ix] -
10348 met->
v[ix][i89][ip] * slon[ix]) / met->
nx;
10350 (met->
u[ix][i89][ip] * slon[ix] +
10351 met->
v[ix][i89][ip] * clon[ix]) / met->
nx;
10355 for (
int ix = 0; ix < met->
nx; ix++) {
10356 met->
u[ix][i90][ip]
10357 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
10358 met->
v[ix][i90][ip]
10359 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
10374 LOG(2,
"Calculate potential vorticity...");
10377#pragma omp parallel for default(shared)
10378 for (
int ip = 0; ip < met->
np; ip++)
10379 pows[ip] = pow(1000. / met->
p[ip], 0.286);
10382#pragma omp parallel for default(shared)
10383 for (
int ix = 0; ix < met->
nx; ix++) {
10386 const int ix0 =
MAX(ix - 1, 0);
10387 const int ix1 =
MIN(ix + 1, met->
nx - 1);
10390 for (
int iy = 0; iy < met->
ny; iy++) {
10393 const int iy0 =
MAX(iy - 1, 0);
10394 const int iy1 =
MIN(iy + 1, met->
ny - 1);
10397 const double latr = 0.5 * (met->
lat[iy1] + met->
lat[iy0]);
10398 const double dx = 1000. *
DEG2DX(met->
lon[ix1] - met->
lon[ix0], latr);
10399 const double dy = 1000. *
DEG2DY(met->
lat[iy1] - met->
lat[iy0]);
10400 const double c0 = cos(
DEG2RAD(met->
lat[iy0]));
10401 const double c1 = cos(
DEG2RAD(met->
lat[iy1]));
10402 const double cr = cos(
DEG2RAD(latr));
10403 const double vort = 2 * 7.2921e-5 * sin(
DEG2RAD(latr));
10406 for (
int ip = 0; ip < met->
np; ip++) {
10410 = (met->
t[ix1][iy][ip] - met->
t[ix0][iy][ip]) * pows[ip] / dx;
10411 const double dvdx = (met->
v[ix1][iy][ip] - met->
v[ix0][iy][ip]) / dx;
10415 = (met->
t[ix][iy1][ip] - met->
t[ix][iy0][ip]) * pows[ip] / dy;
10417 = (met->
u[ix][iy1][ip] * c1 - met->
u[ix][iy0][ip] * c0) / dy;
10420 const int ip0 =
MAX(ip - 1, 0);
10421 const int ip1 =
MIN(ip + 1, met->
np - 1);
10424 double dtdp, dudp, dvdp;
10425 const double dp0 = 100. * (met->
p[ip] - met->
p[ip0]);
10426 const double dp1 = 100. * (met->
p[ip1] - met->
p[ip]);
10427 if (ip != ip0 && ip != ip1) {
10428 double denom = dp0 * dp1 * (dp0 + dp1);
10429 dtdp = (dp0 * dp0 * met->
t[ix][iy][ip1] * pows[ip1]
10430 - dp1 * dp1 * met->
t[ix][iy][ip0] * pows[ip0]
10431 + (dp1 * dp1 - dp0 * dp0) * met->
t[ix][iy][ip] * pows[ip])
10433 dudp = (dp0 * dp0 * met->
u[ix][iy][ip1]
10434 - dp1 * dp1 * met->
u[ix][iy][ip0]
10435 + (dp1 * dp1 - dp0 * dp0) * met->
u[ix][iy][ip])
10437 dvdp = (dp0 * dp0 * met->
v[ix][iy][ip1]
10438 - dp1 * dp1 * met->
v[ix][iy][ip0]
10439 + (dp1 * dp1 - dp0 * dp0) * met->
v[ix][iy][ip])
10442 const double denom = dp0 + dp1;
10444 (met->
t[ix][iy][ip1] * pows[ip1] -
10445 met->
t[ix][iy][ip0] * pows[ip0]) / denom;
10446 dudp = (met->
u[ix][iy][ip1] - met->
u[ix][iy][ip0]) / denom;
10447 dvdp = (met->
v[ix][iy][ip1] - met->
v[ix][iy][ip0]) / denom;
10451 met->
pv[ix][iy][ip] = (float)
10453 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
10459#pragma omp parallel for default(shared)
10460 for (
int ix = 0; ix < met->
nx; ix++)
10461 for (
int ip = 0; ip < met->
np; ip++) {
10463 = met->
pv[ix][1][ip]
10464 = met->
pv[ix][2][ip];
10465 met->
pv[ix][met->
ny - 1][ip]
10466 = met->
pv[ix][met->
ny - 2][ip]
10467 = met->
pv[ix][met->
ny - 3][ip];
10478 LOG(2,
"Calculate total column ozone...");
10481#pragma omp parallel for default(shared) collapse(2)
10482 for (
int ix = 0; ix < met->
nx; ix++)
10483 for (
int iy = 0; iy < met->
ny; iy++) {
10487 for (
int ip = 1; ip < met->
np; ip++)
10488 if (met->
p[ip - 1] <= met->
ps[ix][iy]) {
10490 0.5 * (met->
o3[ix][iy][ip - 1] + met->
o3[ix][iy][ip]);
10491 const double dp = met->
p[ip - 1] - met->
p[ip];
10492 cd += vmr *
MO3 /
MA * dp * 1e2 /
G0;
10496 met->
o3c[ix][iy] = (float) (cd / 2.1415e-5);
10514 SELECT_TIMER(
"READ_MET_SAMPLE",
"METPROC", NVTX_READ);
10515 LOG(2,
"Downsampling of meteo data...");
10521 help->
nx = met->
nx;
10522 help->
ny = met->
ny;
10523 help->
np = met->
np;
10524 memcpy(help->
lon, met->
lon,
sizeof(met->
lon));
10525 memcpy(help->
lat, met->
lat,
sizeof(met->
lat));
10526 memcpy(help->
p, met->
p,
sizeof(met->
p));
10529 for (
int ix = 0; ix < met->
nx; ix += ctl->
met_dx) {
10530 for (
int iy = 0; iy < met->
ny; iy += ctl->
met_dy) {
10531 for (
int ip = 0; ip < met->
np; ip += ctl->
met_dp) {
10532 help->
ps[ix][iy] = 0;
10533 help->
zs[ix][iy] = 0;
10534 help->
ts[ix][iy] = 0;
10535 help->
us[ix][iy] = 0;
10536 help->
vs[ix][iy] = 0;
10537 help->
ess[ix][iy] = 0;
10538 help->
nss[ix][iy] = 0;
10539 help->
shf[ix][iy] = 0;
10540 help->
lsm[ix][iy] = 0;
10541 help->
sst[ix][iy] = 0;
10542 help->
pbl[ix][iy] = 0;
10543 help->
cape[ix][iy] = 0;
10544 help->
cin[ix][iy] = 0;
10545 help->
t[ix][iy][ip] = 0;
10546 help->
u[ix][iy][ip] = 0;
10547 help->
v[ix][iy][ip] = 0;
10548 help->
w[ix][iy][ip] = 0;
10549 help->
h2o[ix][iy][ip] = 0;
10550 help->
o3[ix][iy][ip] = 0;
10551 help->
lwc[ix][iy][ip] = 0;
10552 help->
rwc[ix][iy][ip] = 0;
10553 help->
iwc[ix][iy][ip] = 0;
10554 help->
swc[ix][iy][ip] = 0;
10555 help->
cc[ix][iy][ip] = 0;
10557 for (
int ix2 = ix - ctl->
met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
10562 else if (ix3 >= met->
nx)
10565 for (
int iy2 =
MAX(iy - ctl->
met_sy + 1, 0);
10566 iy2 <=
MIN(iy + ctl->
met_sy - 1, met->
ny - 1); iy2++)
10567 for (
int ip2 =
MAX(ip - ctl->
met_sp + 1, 0);
10568 ip2 <=
MIN(ip + ctl->
met_sp - 1, met->
np - 1); ip2++) {
10570 (1.0f - (float) abs(ix - ix2) / (float) ctl->
met_sx)
10571 * (1.0f - (float) abs(iy - iy2) / (float) ctl->
met_sy)
10572 * (1.0f - (float) abs(ip - ip2) / (float) ctl->
met_sp);
10573 help->
ps[ix][iy] += w * met->
ps[ix3][iy2];
10574 help->
zs[ix][iy] += w * met->
zs[ix3][iy2];
10575 help->
ts[ix][iy] += w * met->
ts[ix3][iy2];
10576 help->
us[ix][iy] += w * met->
us[ix3][iy2];
10577 help->
vs[ix][iy] += w * met->
vs[ix3][iy2];
10578 help->
ess[ix][iy] += w * met->
ess[ix3][iy2];
10579 help->
nss[ix][iy] += w * met->
nss[ix3][iy2];
10580 help->
shf[ix][iy] += w * met->
shf[ix3][iy2];
10581 help->
lsm[ix][iy] += w * met->
lsm[ix3][iy2];
10582 help->
sst[ix][iy] += w * met->
sst[ix3][iy2];
10583 help->
pbl[ix][iy] += w * met->
pbl[ix3][iy2];
10584 help->
cape[ix][iy] += w * met->
cape[ix3][iy2];
10585 help->
cin[ix][iy] += w * met->
cin[ix3][iy2];
10586 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip2];
10587 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip2];
10588 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip2];
10589 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip2];
10590 help->
h2o[ix][iy][ip] += w * met->
h2o[ix3][iy2][ip2];
10591 help->
o3[ix][iy][ip] += w * met->
o3[ix3][iy2][ip2];
10592 help->
lwc[ix][iy][ip] += w * met->
lwc[ix3][iy2][ip2];
10593 help->
rwc[ix][iy][ip] += w * met->
rwc[ix3][iy2][ip2];
10594 help->
iwc[ix][iy][ip] += w * met->
iwc[ix3][iy2][ip2];
10595 help->
swc[ix][iy][ip] += w * met->
swc[ix3][iy2][ip2];
10596 help->
cc[ix][iy][ip] += w * met->
cc[ix3][iy2][ip2];
10600 help->
ps[ix][iy] /= wsum;
10601 help->
zs[ix][iy] /= wsum;
10602 help->
ts[ix][iy] /= wsum;
10603 help->
us[ix][iy] /= wsum;
10604 help->
vs[ix][iy] /= wsum;
10605 help->
ess[ix][iy] /= wsum;
10606 help->
nss[ix][iy] /= wsum;
10607 help->
shf[ix][iy] /= wsum;
10608 help->
lsm[ix][iy] /= wsum;
10609 help->
sst[ix][iy] /= wsum;
10610 help->
pbl[ix][iy] /= wsum;
10611 help->
cape[ix][iy] /= wsum;
10612 help->
cin[ix][iy] /= wsum;
10613 help->
t[ix][iy][ip] /= wsum;
10614 help->
u[ix][iy][ip] /= wsum;
10615 help->
v[ix][iy][ip] /= wsum;
10616 help->
w[ix][iy][ip] /= wsum;
10617 help->
h2o[ix][iy][ip] /= wsum;
10618 help->
o3[ix][iy][ip] /= wsum;
10619 help->
lwc[ix][iy][ip] /= wsum;
10620 help->
rwc[ix][iy][ip] /= wsum;
10621 help->
iwc[ix][iy][ip] /= wsum;
10622 help->
swc[ix][iy][ip] /= wsum;
10623 help->
cc[ix][iy][ip] /= wsum;
10630 for (
int ix = 0; ix < help->
nx; ix += ctl->
met_dx) {
10631 met->
lon[met->
nx] = help->
lon[ix];
10633 for (
int iy = 0; iy < help->
ny; iy += ctl->
met_dy) {
10634 met->
lat[met->
ny] = help->
lat[iy];
10635 met->
ps[met->
nx][met->
ny] = help->
ps[ix][iy];
10636 met->
zs[met->
nx][met->
ny] = help->
zs[ix][iy];
10637 met->
ts[met->
nx][met->
ny] = help->
ts[ix][iy];
10638 met->
us[met->
nx][met->
ny] = help->
us[ix][iy];
10639 met->
vs[met->
nx][met->
ny] = help->
vs[ix][iy];
10640 met->
ess[met->
nx][met->
ny] = help->
ess[ix][iy];
10641 met->
nss[met->
nx][met->
ny] = help->
nss[ix][iy];
10642 met->
shf[met->
nx][met->
ny] = help->
shf[ix][iy];
10643 met->
lsm[met->
nx][met->
ny] = help->
lsm[ix][iy];
10644 met->
sst[met->
nx][met->
ny] = help->
sst[ix][iy];
10645 met->
pbl[met->
nx][met->
ny] = help->
pbl[ix][iy];
10647 met->
cin[met->
nx][met->
ny] = help->
cin[ix][iy];
10649 for (
int ip = 0; ip < help->
np; ip += ctl->
met_dp) {
10650 met->
p[met->
np] = help->
p[ip];
10651 met->
t[met->
nx][met->
ny][met->
np] = help->
t[ix][iy][ip];
10652 met->
u[met->
nx][met->
ny][met->
np] = help->
u[ix][iy][ip];
10653 met->
v[met->
nx][met->
ny][met->
np] = help->
v[ix][iy][ip];
10654 met->
w[met->
nx][met->
ny][met->
np] = help->
w[ix][iy][ip];
10655 met->
h2o[met->
nx][met->
ny][met->
np] = help->
h2o[ix][iy][ip];
10656 met->
o3[met->
nx][met->
ny][met->
np] = help->
o3[ix][iy][ip];
10657 met->
lwc[met->
nx][met->
ny][met->
np] = help->
lwc[ix][iy][ip];
10658 met->
rwc[met->
nx][met->
ny][met->
np] = help->
rwc[ix][iy][ip];
10659 met->
iwc[met->
nx][met->
ny][met->
np] = help->
iwc[ix][iy][ip];
10660 met->
swc[met->
nx][met->
ny][met->
np] = help->
swc[ix][iy][ip];
10661 met->
cc[met->
nx][met->
ny][met->
np] = help->
cc[ix][iy][ip];
10680 double p2[200], pv[
EP], pv2[200], t[
EP], t2[200], th[
EP],
10681 th2[200], z[
EP], z2[200];
10685 LOG(2,
"Calculate tropopause...");
10688#pragma omp parallel for default(shared)
10689 for (
int iz = 0; iz < met->
np; iz++)
10690 z[iz] =
Z(met->
p[iz]);
10691#pragma omp parallel for default(shared)
10692 for (
int iz = 0; iz <= 190; iz++) {
10693 z2[iz] = 4.5 + 0.1 * iz;
10694 p2[iz] =
P(z2[iz]);
10699#pragma omp parallel for default(shared) collapse(2)
10700 for (
int ix = 0; ix < met->
nx; ix++)
10701 for (
int iy = 0; iy < met->
ny; iy++)
10702 met->
pt[ix][iy] = NAN;
10706#pragma omp parallel for default(shared) collapse(2)
10707 for (
int ix = 0; ix < met->
nx; ix++)
10708 for (
int iy = 0; iy < met->
ny; iy++)
10716#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10717 for (
int ix = 0; ix < met->
nx; ix++)
10718 for (
int iy = 0; iy < met->
ny; iy++) {
10721 for (
int iz = 0; iz < met->
np; iz++)
10722 t[iz] = met->
t[ix][iy][iz];
10726 int iz = (int) gsl_stats_min_index(t2, 1, 171);
10727 if (iz > 0 && iz < 170)
10728 met->
pt[ix][iy] = (float) p2[iz];
10730 met->
pt[ix][iy] = NAN;
10738#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10739 for (
int ix = 0; ix < met->
nx; ix++)
10740 for (
int iy = 0; iy < met->
ny; iy++) {
10744 for (iz = 0; iz < met->
np; iz++)
10745 t[iz] = met->
t[ix][iy][iz];
10749 met->
pt[ix][iy] = NAN;
10750 for (iz = 0; iz <= 170; iz++) {
10752 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10753 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10758 if (iz > 0 && iz < 170)
10759 met->
pt[ix][iy] = (float) p2[iz];
10766 met->
pt[ix][iy] = NAN;
10767 for (; iz <= 170; iz++) {
10769 for (
int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
10770 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
10777 for (; iz <= 170; iz++) {
10779 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10780 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10785 if (iz > 0 && iz < 170)
10786 met->
pt[ix][iy] = (float) p2[iz];
10798#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
10799 for (
int ix = 0; ix < met->
nx; ix++)
10800 for (
int iy = 0; iy < met->
ny; iy++) {
10803 for (
int iz = 0; iz < met->
np; iz++)
10804 pv[iz] = met->
pv[ix][iy][iz];
10808 for (
int iz = 0; iz < met->
np; iz++)
10809 th[iz] =
THETA(met->
p[iz], met->
t[ix][iy][iz]);
10813 met->
pt[ix][iy] = NAN;
10814 for (
int iz = 0; iz <= 170; iz++)
10817 if (iz > 0 && iz < 170)
10818 met->
pt[ix][iy] = (float) p2[iz];
10825 ERRMSG(
"Cannot calculate tropopause!");
10828#pragma omp parallel for default(shared) collapse(2)
10829 for (
int ix = 0; ix < met->
nx; ix++)
10830 for (
int iy = 0; iy < met->
ny; iy++) {
10831 double h2ot, tt, zt;
10834 met->
lat[iy], &tt, ci, cw, 1);
10836 met->
lat[iy], &zt, ci, cw, 0);
10838 met->
lat[iy], &h2ot, ci, cw, 0);
10839 met->
tt[ix][iy] = (float) tt;
10840 met->
zt[ix][iy] = (float) zt;
10841 met->
h2ot[ix][iy] = (float) h2ot;
10848 const char *filename,
10858 LOG(1,
"Read observation data: %s", filename);
10862 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
10864 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
10866 ERRMSG(
"Set OBS_TYPE to 0 or 1!");
10869 for (
int i = 1; i < *nobs; i++)
10870 if (rt[i] < rt[i - 1])
10871 ERRMSG(
"Time must be ascending!");
10876 LOG(2,
"Number of observations: %d", *nobs);
10877 gsl_stats_minmax(&mini, &maxi, rt, 1, (
size_t) n);
10878 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
10879 gsl_stats_minmax(&mini, &maxi, rz, 1, (
size_t) n);
10880 LOG(2,
"Altitude range: %g ... %g km", mini, maxi);
10881 gsl_stats_minmax(&mini, &maxi, rlon, 1, (
size_t) n);
10882 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
10883 gsl_stats_minmax(&mini, &maxi, rlat, 1, (
size_t) n);
10884 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
10885 gsl_stats_minmax(&mini, &maxi, robs, 1, (
size_t) n);
10886 LOG(2,
"Observation range: %g ... %g", mini, maxi);
10892 const char *filename,
10902 if (!(in = fopen(filename,
"r")))
10903 ERRMSG(
"Cannot open file!");
10907 while (fgets(line,
LEN, in))
10908 if (sscanf(line,
"%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
10909 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
10910 if ((++(*nobs)) >=
NOBS)
10911 ERRMSG(
"Too many observations!");
10920 const char *filename,
10931 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
10932 ERRMSG(
"Cannot open file!");
10943 NC(nc_close(ncid));
10949 const char *filename,
10952 const char *varname,
10954 const char *defvalue,
10959 char fullname1[
LEN], fullname2[
LEN], rval[
LEN];
10961 int contain = 0, i;
10964 if (filename[strlen(filename) - 1] !=
'-')
10965 if (!(in = fopen(filename,
"r")))
10966 ERRMSG(
"Cannot open file!");
10970 sprintf(fullname1,
"%s[%d]", varname, arridx);
10971 sprintf(fullname2,
"%s[*]", varname);
10973 sprintf(fullname1,
"%s", varname);
10974 sprintf(fullname2,
"%s", varname);
10979 char dummy[
LEN], line[
LEN], rvarname[
LEN];
10980 while (fgets(line,
LEN, in)) {
10981 if (sscanf(line,
"%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
10982 if (strcasecmp(rvarname, fullname1) == 0 ||
10983 strcasecmp(rvarname, fullname2) == 0) {
10989 for (i = 1; i < argc - 1; i++)
10990 if (strcasecmp(argv[i], fullname1) == 0 ||
10991 strcasecmp(argv[i], fullname2) == 0) {
10992 sprintf(rval,
"%s", argv[i + 1]);
11003 if (strlen(defvalue) > 0)
11004 sprintf(rval,
"%s", defvalue);
11006 ERRMSG(
"Missing variable %s!\n", fullname1);
11010 LOG(1,
"%s = %s", fullname1, rval);
11014 sprintf(value,
"%s", rval);
11024 const double rhop) {
11027 const double rp_help = rp * 1e-6;
11030 const double rho =
RHO(p, T);
11033 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
11036 const double v = sqrt(8. *
KB * T / (M_PI * 4.8096e-26));
11039 const double lambda = 2. * eta / (rho * v);
11042 const double K = lambda / rp_help;
11045 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
11048 return 2. *
SQR(rp_help) * (rhop - rho) *
G0 / (9. * eta) * G;
11060 const int method) {
11066 gsl_interp_accel *acc = gsl_interp_accel_alloc();
11067 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (
size_t) n);
11070 gsl_spline_init(s, x, y, (
size_t) n);
11071 for (
int i = 0; i < n2; i++)
11074 else if (x2[i] >= x[n - 1])
11077 y2[i] = gsl_spline_eval(s, x2[i], acc);
11080 gsl_spline_free(s);
11081 gsl_interp_accel_free(acc);
11086 for (
int i = 0; i < n2; i++)
11089 else if (x2[i] >= x[n - 1])
11093 y2[i] =
LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
11107 float mean = 0, var = 0;
11109 for (
int i = 0; i < n; ++i) {
11111 var +=
SQR(data[i]);
11114 var = var / (float) n -
SQR(mean / (
float) n);
11116 return (var > 0 ? sqrtf(var) : 0);
11128 const double remain,
11140 t1.tm_year = year - 1900;
11141 t1.tm_mon = mon - 1;
11147 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
11155 const int output) {
11162 static int iname = -1, igroup = -1, nname, ngroup, ct_name[
NTIMER];
11165 t1 = omp_get_wtime();
11170 rt_name[iname] += dt;
11171 rt_min[iname] = (ct_name[iname] <= 0 ? dt :
MIN(rt_min[iname], dt));
11172 rt_max[iname] = (ct_name[iname] <= 0 ? dt :
MAX(rt_max[iname], dt));
11176 rt_group[igroup] += t1 - t0;
11180 for (
int i = 0; i < nname; i++)
11181 LOG(1,
"TIMER_%s = %.3f s (min= %g s, mean= %g s,"
11182 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
11183 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
11184 for (
int i = 0; i < ngroup; i++)
11185 LOG(1,
"TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
11186 double total = 0.0;
11187 for (
int i = 0; i < nname; i++)
11188 total += rt_name[i];
11189 LOG(1,
"TIMER_TOTAL = %.3f s", total);
11193 for (iname = 0; iname < nname; iname++)
11194 if (strcasecmp(name, names[iname]) == 0)
11196 for (igroup = 0; igroup < ngroup; igroup++)
11197 if (strcasecmp(group, groups[igroup]) == 0)
11201 if (iname >= nname) {
11202 sprintf(names[iname],
"%s", name);
11203 if ((++nname) >=
NTIMER)
11204 ERRMSG(
"Too many timers!");
11208 if (igroup >= ngroup) {
11209 sprintf(groups[igroup],
"%s", group);
11210 if ((++ngroup) >=
NTIMER)
11211 ERRMSG(
"Too many groups!");
11221 const char *filename,
11222 const int offset) {
11229 int len = (int) strlen(filename);
11230 sprintf(tstr,
"%.4s", &filename[len - offset]);
11231 int year = atoi(tstr);
11232 sprintf(tstr,
"%.2s", &filename[len - offset + 5]);
11233 int mon = atoi(tstr);
11234 sprintf(tstr,
"%.2s", &filename[len - offset + 8]);
11235 int day = atoi(tstr);
11236 sprintf(tstr,
"%.2s", &filename[len - offset + 11]);
11237 int hour = atoi(tstr);
11238 sprintf(tstr,
"%.2s", &filename[len - offset + 14]);
11239 int min = atoi(tstr);
11242 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
11243 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
11244 ERRMSG(
"Cannot read time from filename!");
11247 time2jsec(year, mon, day, hour, min, 0, 0.0, &t);
11264 const double p1 = pt * 0.866877899;
11265 const double p0 = pt / 0.866877899;
11268 if (atm->
p[ip] > p0)
11270 else if (atm->
p[ip] < p1)
11273 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
11279 const char *filename,
11287 const double t0 = t - 0.5 * ctl->
dt_mod;
11288 const double t1 = t + 0.5 * ctl->
dt_mod;
11294 if (!(out = popen(
"gnuplot",
"w")))
11295 ERRMSG(
"Cannot create pipe to gnuplot!");
11298 fprintf(out,
"set out \"%s.png\"\n", filename);
11302 int year, mon, day, hour, min, sec;
11303 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11304 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
11305 year, mon, day, hour, min);
11310 ERRMSG(
"Cannot open file!");
11312 while (fgets(line,
LEN, in))
11313 fprintf(out,
"%s", line);
11320 if (!(out = fopen(filename,
"w")))
11321 ERRMSG(
"Cannot create file!");
11326 "# $1 = time [s]\n"
11327 "# $2 = altitude [km]\n"
11328 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
11329 for (
int iq = 0; iq < ctl->
nq; iq++)
11330 fprintf(out,
"# $%i = %s [%s]\n", iq + 5, ctl->
qnt_name[iq],
11332 fprintf(out,
"\n");
11335 for (
int ip = 0; ip < atm->
np; ip += ctl->
atm_stride) {
11342 fprintf(out,
"%.2f %g %g %g", atm->
time[ip],
Z(atm->
p[ip]),
11343 atm->
lon[ip], atm->
lat[ip]);
11344 for (
int iq = 0; iq < ctl->
nq; iq++) {
11349 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
11351 fprintf(out,
"\n");
11361 const char *filename,
11363 const atm_t *atm) {
11368 if (!(out = fopen(filename,
"w")))
11369 ERRMSG(
"Cannot create file!");
11393 for (
int iq = 0; iq < ctl->
nq; iq++)
11411 const char *filename,
11413 const atm_t *atm) {
11415 int tid, pid, ncid, varid;
11416 size_t start[2], count[2];
11419 NC(nc_create(filename, NC_NETCDF4, &ncid));
11422 NC(nc_def_dim(ncid,
"time", 1, &tid));
11423 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11426 int dim_ids[2] = { tid, pid };
11427 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11428 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11429 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
11431 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
11433 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
11436 for (
int iq = 0; iq < ctl->
nq; iq++)
11446 NC(nc_enddef(ncid));
11454 for (
int iq = 0; iq < ctl->
nq; iq++)
11458 NC(nc_close(ncid));
11464 const char *dirname,
11470 static size_t out_cnt = 0;
11472 double r, r_start, r_stop;
11473 int year, mon, day, hour, min, sec;
11474 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
11475 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
11476 char filename_out[2 *
LEN] =
"traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
11478 int ncid, varid, tid, pid, cid;
11486 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11488 &min_start, &sec_start, &r_start);
11490 &min_stop, &sec_stop, &r_stop);
11492 sprintf(filename_out,
11493 "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc", dirname,
11494 year_start % 100, mon_start, day_start, hour_start,
11495 year_stop % 100, mon_stop, day_stop, hour_stop);
11496 LOG(1,
"Write traj file: %s", filename_out);
11499 start[0] = out_cnt;
11502 count[1] = (size_t) atm->
np;
11505 if (out_cnt == 0) {
11508 NC(nc_create(filename_out, NC_NETCDF4, &ncid));
11511 NC(nc_def_dim(ncid,
"time", NC_UNLIMITED, &tid));
11512 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11513 NC(nc_def_dim(ncid,
"TMDT", 7, &cid));
11518 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11519 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11520 NC_DEF_VAR(
"LAT", NC_DOUBLE, 2, dim_ids,
"Latitude",
"deg",
11522 NC_DEF_VAR(
"LON", NC_DOUBLE, 2, dim_ids,
"Longitude",
"deg",
11524 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 2, dim_ids,
"Pressure",
"hPa",
11526 NC_DEF_VAR(
"ZETA", NC_DOUBLE, 2, dim_ids,
"Zeta",
"K",
11528 for (
int iq = 0; iq < ctl->
nq; iq++)
11538 NC(nc_enddef(ncid));
11539 NC(nc_close(ncid));
11546 NC(nc_open(filename_out, NC_WRITE, &ncid));
11558 for (
int iq = 0; iq < ctl->
nq; iq++)
11562 NC(nc_close(ncid));
11565 if ((year == year_stop) && (mon == mon_stop)
11566 && (day == day_stop) && (hour == hour_stop)) {
11569 char filename_init[2 *
LEN] =
"./init_fix_YYYYMMDDHH.nc";
11570 sprintf(filename_init,
"%s/init_fix_%02d%02d%02d%02d.nc",
11571 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
11572 LOG(1,
"Write init file: %s", filename_init);
11575 NC(nc_create(filename_init, NC_NETCDF4, &ncid));
11578 NC(nc_def_dim(ncid,
"time", 1, &tid));
11579 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11584 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11585 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11586 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
11588 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
11590 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
11593 for (
int iq = 0; iq < ctl->
nq; iq++)
11603 NC(nc_enddef(ncid));
11611 for (
int iq = 0; iq < ctl->
nq; iq++)
11615 NC(nc_close(ncid));
11622 const char *filename,
11624 const atm_t *atm) {
11626 int ncid, obsid, varid;
11628 size_t start[2], count[2];
11631 NC(nc_create(filename, NC_NETCDF4, &ncid));
11634 NC(nc_def_dim(ncid,
"obs", (
size_t) atm->
np, &obsid));
11637 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &obsid,
"time",
11638 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11639 NC_DEF_VAR(
"press", NC_DOUBLE, 1, &obsid,
"pressure",
"hPa",
11641 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &obsid,
"longitude",
"degrees_east",
11643 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &obsid,
"latitude",
"degrees_north",
11645 for (
int iq = 0; iq < ctl->
nq; iq++)
11654 NC(nc_enddef(ncid));
11661 for (
int iq = 0; iq < ctl->
nq; iq++)
11665 NC(nc_close(ncid));
11671 const char *filename,
11678 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
11681 static int *obscount, nobs, nk;
11685 const int ensemble = (ctl->
nens > 0);
11691 if (ctl->
qnt_m < 0)
11692 ERRMSG(
"Need quantity mass!");
11695 ERRMSG(
"Missing ensemble IDs!");
11697 ERRMSG(
"Too many ensembles!");
11704 ALLOC(area,
double,
11710 ALLOC(rlon,
double,
11712 ALLOC(rlat,
double,
11714 ALLOC(robs,
double,
11725 LOG(1,
"Write CSI%s data: %s", ensemble ?
" ensemble" :
"", filename);
11726 if (!(out = fopen(filename,
"w")))
11727 ERRMSG(
"Cannot create file!");
11731 "# $1 = time [s]\n"
11732 "# $2 = ensemble ID\n"
11733 "# $3 = number of hits (cx)\n"
11734 "# $4 = number of misses (cy)\n"
11735 "# $5 = number of false alarms (cz)\n"
11736 "# $6 = number of observations (cx + cy)\n"
11737 "# $7 = number of forecasts (cx + cz)\n"
11738 "# $8 = bias (%%)\n"
11739 "# $9 = POD (%%)\n"
11740 "# $10 = FAR (%%)\n"
11741 "# $11 = CSI (%%)\n"
11742 "# $12 = hits by random chance\n"
11743 "# $13 = ETS (%%)\n"
11744 "# $14 = Pearson R\n"
11745 "# $15 = Spearman R\n"
11746 "# $16 = mean error [kg/m²]\n"
11747 "# $17 = RMSE [kg/m²]\n"
11748 "# $18 = MAE [kg/m²]\n"
11749 "# $19 = log-likelihood\n" "# $20 = number of points\n\n");
11757 for (
int iy = 0; iy < ctl->
csi_ny; iy++) {
11758 const double lat = ctl->
csi_lat0 + dlat * (iy + 0.5);
11759 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.0) * cos(
DEG2RAD(lat));
11764 const double t0 = t - 0.5 * ctl->
dt_mod;
11765 const double t1 = t + 0.5 * ctl->
dt_mod;
11769 ALLOC(modmean,
double,
11770 (ensemble ? ctl->
nens : 1) * grid_size);
11771 ALLOC(obsmean,
double,
11773 ALLOC(obscount,
int,
11775 ALLOC(obsstd,
double,
11779 for (
int i = 0; i < (ensemble ? ctl->
nens : 1); i++)
11780 ct[i] = cx[i] = cy[i] = cz[i] = n[i] = 0;
11783 for (
int i = 0; i < nobs; i++) {
11784 if (rt[i] < t0 || rt[i] >= t1 || !isfinite(robs[i]))
11788 const int ix = (int) ((rlon[i] - ctl->
csi_lon0) / dlon);
11789 const int iy = (int) ((rlat[i] - ctl->
csi_lat0) / dlat);
11790 const int iz = (int) ((rz[i] - ctl->
csi_z0) / dz);
11791 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
11797 obsmean[idx] += robs[i];
11798 obsstd[idx] +=
SQR(robs[i]);
11803 for (
int ip = 0; ip < atm->
np; ip++) {
11806 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11810 int ens_id = ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
11811 if (ens_id < 0 || ens_id >= (ensemble ? ctl->
nens : 1))
11812 ERRMSG(
"Ensemble ID out of range!");
11815 const int ix = (int) ((atm->
lon[ip] - ctl->
csi_lon0) / dlon);
11816 const int iy = (int) ((atm->
lat[ip] - ctl->
csi_lat0) / dlat);
11817 const int iz = (int) ((
Z(atm->
p[ip]) - ctl->
csi_z0) / dz);
11818 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
11828 for (
int e = 0; e < (ensemble ? ctl->
nens : 1); e++) {
11830 for (
int ix = 0; ix < ctl->
csi_nx; ix++)
11831 for (
int iy = 0; iy < ctl->
csi_ny; iy++)
11832 for (
int iz = 0; iz < ctl->
csi_nz; iz++) {
11837 if (obscount[idx]) {
11838 obsmean[idx] /= obscount[idx];
11840 sqrt(obsstd[idx] / obscount[idx] -
SQR(obsmean[idx]));
11844 const int midx = e * grid_size + idx;
11845 if (modmean[midx] > 0)
11846 modmean[midx] /= (1e6 * area[iy]);
11849 if (obscount[idx]) {
11864 x[n[e]] = modmean[midx];
11865 y[n[e]] = obsmean[idx];
11867 obsstdn[n[e]] = obsstd[idx];
11868 if ((++n[e]) >=
NCSI)
11869 ERRMSG(
"Too many points for statistics!");
11881 static double work[2 *
NCSI], work2[2 *
NCSI];
11882 const int n_obs = cx[e] + cy[e];
11883 const int n_for = cx[e] + cz[e];
11884 const double cx_rd = (ct[e] > 0) ? (1. * n_obs * n_for) / ct[e] : NAN;
11885 const double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
11886 const double pod = (n_obs > 0) ? 100. * cx[e] / n_obs : NAN;
11887 const double far = (n_for > 0) ? 100. * cz[e] / n_for : NAN;
11889 (cx[e] + cy[e] + cz[e] >
11890 0) ? 100. * cx[e] / (cx[e] + cy[e] + cz[e]) : NAN;
11892 (cx[e] + cy[e] + cz[e] - cx_rd >
11893 0) ? 100. * (cx[e] - cx_rd) / (cx[e] + cy[e] + cz[e] - cx_rd) : NAN;
11894 const double rho_p = gsl_stats_correlation(x, 1, y, 1, (
size_t) n[e]);
11895 const double rho_s =
11896 gsl_stats_spearman(x, 1, y, 1, (
size_t) n[e], work);
11897 for (
int i = 0; i < n[e]; i++) {
11898 work[i] = x[i] - y[i];
11899 work2[i] = (obsstdn[i] != 0) ? work[i] / obsstdn[i] : 0;
11901 const double mean = gsl_stats_mean(work, 1, (
size_t) n[e]);
11902 const double rmse =
11903 gsl_stats_sd_with_fixed_mean(work, 1, (
size_t) n[e], 0.0);
11904 const double absdev = gsl_stats_absdev_m(work, 1, (
size_t) n[e], 0.0);
11905 const double loglikelihood =
11906 gsl_stats_tss_m(work2, 1, (
size_t) n[e], 0.0) * -0.5;
11910 "%.2f %d %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n",
11911 t, ensemble ? e : -999, cx[e], cy[e], cz[e], n_obs, n_for, bias,
11912 pod, far, csi, cx_rd, ets, rho_p, rho_s, mean, rmse, absdev,
11913 loglikelihood, n[e]);
11916 for (
int i = 0; i < n[e]; i++)
11917 work[i] = work2[i] = x[i] = y[i] = obsstdn[i] = 0;
11918 ct[e] = cx[e] = cy[e] = cz[e] = n[e] = 0;
11946 const char *filename,
11956 static int n[
NENS];
11963 ERRMSG(
"Missing ensemble IDs!");
11966 const double t0 = t - 0.5 * ctl->
dt_mod;
11967 const double t1 = t + 0.5 * ctl->
dt_mod;
11970 for (
int i = 0; i <
NENS; i++) {
11971 for (
int iq = 0; iq < ctl->
nq; iq++)
11972 qm[iq][i] = qs[iq][i] = 0;
11973 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
11978 for (
int ip = 0; ip < atm->
np; ip++) {
11981 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11986 ERRMSG(
"Ensemble ID is out of range!");
11990 for (
int iq = 0; iq < ctl->
nq; iq++) {
11991 qm[iq][ctl->
qnt_ens] += atm->
q[iq][ip];
12002 LOG(1,
"Write ensemble data: %s", filename);
12003 if (!(out = fopen(filename,
"w")))
12004 ERRMSG(
"Cannot create file!");
12008 "# $1 = time [s]\n"
12009 "# $2 = altitude [km]\n"
12010 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
12011 for (
int iq = 0; iq < ctl->
nq; iq++)
12012 fprintf(out,
"# $%d = %s (mean) [%s]\n", 5 + iq,
12014 for (
int iq = 0; iq < ctl->
nq; iq++)
12015 fprintf(out,
"# $%d = %s (sigma) [%s]\n", 5 + ctl->
nq + iq,
12017 fprintf(out,
"# $%d = number of members\n\n", 5 + 2 * ctl->
nq);
12020 for (
int i = 0; i <
NENS; i++)
12022 cart2geo(xm[i], &dummy, &lon, &lat);
12023 fprintf(out,
"%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
12024 for (
int iq = 0; iq < ctl->
nq; iq++) {
12026 fprintf(out, ctl->
qnt_format[iq], qm[iq][i] / n[i]);
12028 for (
int iq = 0; iq < ctl->
nq; iq++) {
12030 double var = qs[iq][i] / n[i] -
SQR(qm[iq][i] / n[i]);
12031 fprintf(out, ctl->
qnt_format[iq], (var > 0 ? sqrt(var) : 0));
12033 fprintf(out,
" %d\n", n[i]);
12043 const char *filename,
12050 static double kz[
EP], kw[
EP];
12054 double *cd, *mean[
NQ], *sigma[
NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
12056 int *ixs, *iys, *izs, *np;
12062 LOG(1,
"Write grid data: %s", filename);
12075 for (
int iq = 0; iq < ctl->
nq; iq++) {
12076 ALLOC(mean[iq],
double,
12078 ALLOC(sigma[iq],
double,
12081 ALLOC(vmr_impl,
double,
12089 ALLOC(area,
double,
12091 ALLOC(press,
double,
12108#pragma omp parallel
for default(shared)
12109 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
12110 z[iz] = ctl->
grid_z0 + dz * (iz + 0.5);
12111 press[iz] =
P(z[iz]);
12115 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12116 lon[ix] = ctl->
grid_lon0 + dlon * (ix + 0.5);
12117#pragma omp parallel for default(shared)
12118 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
12119 lat[iy] = ctl->
grid_lat0 + dlat * (iy + 0.5);
12120 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
12124 const double t0 = t - 0.5 * ctl->
dt_mod;
12125 const double t1 = t + 0.5 * ctl->
dt_mod;
12128#pragma omp parallel for default(shared)
12129 for (
int ip = 0; ip < atm->
np; ip++) {
12130 ixs[ip] = (int) ((atm->
lon[ip] - ctl->
grid_lon0) / dlon);
12131 iys[ip] = (int) ((atm->
lat[ip] - ctl->
grid_lat0) / dlat);
12132 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
grid_z0) / dz);
12133 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
12134 || ixs[ip] < 0 || ixs[ip] >= ctl->
grid_nx
12135 || iys[ip] < 0 || iys[ip] >= ctl->
grid_ny
12136 || izs[ip] < 0 || izs[ip] >= ctl->
grid_nz)
12141 for (
int ip = 0; ip < atm->
np; ip++)
12142 if (izs[ip] >= 0) {
12147 for (
int iq = 0; iq < ctl->
nq; iq++) {
12148 mean[iq][idx] += kernel * atm->
q[iq][ip];
12149 sigma[iq][idx] +=
SQR(kernel * atm->
q[iq][ip]);
12154#pragma omp parallel for default(shared)
12155 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12156 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12157 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
12164 if (ctl->
qnt_m >= 0)
12165 cd[idx] = mean[ctl->
qnt_m][idx] / (1e6 * area[iy]);
12168 vmr_impl[idx] = NAN;
12169 if (ctl->
qnt_m >= 0 && ctl->
molmass > 0 && met0 != NULL
12172 if (mean[ctl->
qnt_m][idx] > 0) {
12178 lon[ix], lat[iy], &temp, ci, cw, 1);
12182 MA / ctl->
molmass * cd[idx] / (
RHO(press[iz], temp) * dz * 1e3);
12188 for (
int iq = 0; iq < ctl->
nq; iq++) {
12189 mean[iq][idx] /= np[idx];
12190 const double var = sigma[iq][idx] / np[idx] -
SQR(mean[iq][idx]);
12191 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
12193 for (
int iq = 0; iq < ctl->
nq; iq++) {
12194 mean[iq][idx] = NAN;
12195 sigma[iq][idx] = NAN;
12202 t, z, lon, lat, area, dz, np);
12207 t, z, lon, lat, area, dz, np);
12211 ERRMSG(
"Grid data format GRID_TYPE unknown!");
12215 for (
int iq = 0; iq < ctl->
nq; iq++) {
12234 const char *filename,
12239 const double *vmr_impl,
12244 const double *area,
12254 if (!(out = popen(
"gnuplot",
"w")))
12255 ERRMSG(
"Cannot create pipe to gnuplot!");
12258 fprintf(out,
"set out \"%s.png\"\n", filename);
12262 int year, mon, day, hour, min, sec;
12263 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
12264 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
12265 year, mon, day, hour, min);
12271 ERRMSG(
"Cannot open file!");
12272 while (fgets(line,
LEN, in))
12273 fprintf(out,
"%s", line);
12280 if (!(out = fopen(filename,
"w")))
12281 ERRMSG(
"Cannot create file!");
12286 "# $1 = time [s]\n"
12287 "# $2 = altitude [km]\n"
12288 "# $3 = longitude [deg]\n"
12289 "# $4 = latitude [deg]\n"
12290 "# $5 = surface area [km^2]\n"
12291 "# $6 = layer depth [km]\n"
12292 "# $7 = column density (implicit) [kg/m^2]\n"
12293 "# $8 = volume mixing ratio (implicit) [ppv]\n"
12294 "# $9 = number of particles [1]\n");
12295 for (
int iq = 0; iq < ctl->
nq; iq++)
12296 fprintf(out,
"# $%i = %s (mean) [%s]\n", 10 + iq, ctl->
qnt_name[iq],
12299 for (
int iq = 0; iq < ctl->
nq; iq++)
12300 fprintf(out,
"# $%i = %s (stddev) [%s]\n", 10 + ctl->
nq + iq,
12302 fprintf(out,
"\n");
12305 for (
int ix = 0; ix < ctl->
grid_nx; ix++) {
12307 fprintf(out,
"\n");
12308 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
12310 fprintf(out,
"\n");
12311 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
12314 fprintf(out,
"%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
12315 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
12316 for (
int iq = 0; iq < ctl->
nq; iq++) {
12318 fprintf(out, ctl->
qnt_format[iq], mean[iq][idx]);
12321 for (
int iq = 0; iq < ctl->
nq; iq++) {
12323 fprintf(out, ctl->
qnt_format[iq], sigma[iq][idx]);
12325 fprintf(out,
"\n");
12338 const char *filename,
12343 const double *vmr_impl,
12348 const double *area,
12352 char longname[2 *
LEN], varname[2 *
LEN];
12356 int *help2, ncid, dimid[10], varid;
12358 size_t start[2], count[2];
12361 ALLOC(help,
double,
12367 NC(nc_create(filename, NC_NETCDF4, &ncid));
12370 NC(nc_def_dim(ncid,
"time", 1, &dimid[0]));
12371 NC(nc_def_dim(ncid,
"z", (
size_t) ctl->
grid_nz, &dimid[1]));
12372 NC(nc_def_dim(ncid,
"lat", (
size_t) ctl->
grid_ny, &dimid[2]));
12373 NC(nc_def_dim(ncid,
"lon", (
size_t) ctl->
grid_nx, &dimid[3]));
12374 NC(nc_def_dim(ncid,
"dz", 1, &dimid[4]));
12377 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &dimid[0],
"time",
12378 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
12379 NC_DEF_VAR(
"z", NC_DOUBLE, 1, &dimid[1],
"altitude",
"km", 0, 0);
12380 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &dimid[2],
"latitude",
"degrees_north", 0,
12382 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &dimid[3],
"longitude",
"degrees_east", 0,
12384 NC_DEF_VAR(
"dz", NC_DOUBLE, 1, &dimid[1],
"layer depth",
"km", 0, 0);
12385 NC_DEF_VAR(
"area", NC_DOUBLE, 1, &dimid[2],
"surface area",
"km**2", 0, 0);
12387 NC_DEF_VAR(
"cd", NC_FLOAT, 4, dimid,
"column density",
"kg m**-2",
12390 "volume mixing ratio (implicit)",
"ppv", ctl->
grid_nc_level, 0);
12391 NC_DEF_VAR(
"np", NC_INT, 4, dimid,
"number of particles",
"1", 0, 0);
12392 for (
int iq = 0; iq < ctl->
nq; iq++) {
12393 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
12394 sprintf(longname,
"%s (mean)", ctl->
qnt_longname[iq]);
12398 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
12399 sprintf(longname,
"%s (stddev)", ctl->
qnt_longname[iq]);
12405 NC(nc_enddef(ncid));
12415 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12416 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12417 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12422 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12423 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12424 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
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++)
12436 for (
int iq = 0; iq < ctl->
nq; iq++) {
12437 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
12438 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12439 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12440 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12447 for (
int iq = 0; iq < ctl->
nq; iq++) {
12448 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
12449 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12450 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12451 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12458 NC(nc_close(ncid));
12468 const char *filename,
12474 if (!(out = fopen(filename,
"w")))
12475 ERRMSG(
"Cannot create file!");
12565 ERRMSG(
"Number of meteo variables doesn't match!");
12583 const char *varname) {
12592 for (
int ix = 0; ix < met->
nx; ix++)
12593 for (
int iy = 0; iy < met->
ny; iy++)
12594 help[
ARRAY_2D(ix, iy, met->
ny)] = var[ix][iy];
12597 LOG(2,
"Write 2-D variable: %s (uncompressed)", varname);
12599 (
size_t) (met->
nx * met->
ny),
12613 const char *varname,
12614 const int precision,
12615 const double tolerance) {
12624#pragma omp parallel for default(shared) collapse(2)
12625 for (
int ix = 0; ix < met->
nx; ix++)
12626 for (
int iy = 0; iy < met->
ny; iy++)
12627 for (
int ip = 0; ip < met->
np; ip++)
12628 help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)] = var[ix][iy][ip];
12632 LOG(2,
"Write 3-D variable: %s (uncompressed)", varname);
12634 (
size_t) (met->
nx * met->
ny * met->
np),
12641 (
size_t) met->
np, 0, out);
12649 FWRITE(&tolerance,
double,
12653 tolerance, 0, out);
12668 (
size_t) met->
np, met->
p, 0, out);
12678 FWRITE(&tolerance,
double,
12682 tolerance, 0, out);
12688 ERRMSG(
"MET_TYPE not supported!");
12689 LOG(3,
"%d %g", precision, tolerance);
12699 const char *filename,
12705 size_t start[4], count[4];
12706 NC(nc_create(filename, NC_NETCDF4, &ncid));
12709 int tid, lonid, latid, levid;
12710 NC(nc_def_dim(ncid,
"time", 1, &tid));
12711 NC(nc_def_dim(ncid,
"lon", (
size_t) met->
nx, &lonid));
12712 NC(nc_def_dim(ncid,
"lat", (
size_t) met->
ny, &latid));
12713 NC(nc_def_dim(ncid,
"lev", (
size_t) met->
np, &levid));
12716 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"time",
12717 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
12718 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &lonid,
"longitude",
"degrees_east", 0, 0);
12719 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &latid,
"latitude",
"degrees_north", 0, 0);
12720 NC_DEF_VAR(
"lev", NC_DOUBLE, 1, &levid,
"pressure",
"Pa", 0, 0);
12723 int dimid2[2] = { latid, lonid };
12724 NC_DEF_VAR(
"sp", NC_FLOAT, 2, dimid2,
"Surface pressure",
"Pa",
12726 NC_DEF_VAR(
"z", NC_FLOAT, 2, dimid2,
"Geopotential",
"m**2 s**-2",
12728 NC_DEF_VAR(
"t2m", NC_FLOAT, 2, dimid2,
"2 metre temperature",
"K",
12730 NC_DEF_VAR(
"u10m", NC_FLOAT, 2, dimid2,
"10 metre U wind component",
12732 NC_DEF_VAR(
"v10m", NC_FLOAT, 2, dimid2,
"10 metre V wind component",
12735 "Instantaneous eastward turbulent surface stress",
"N m**-2",
12738 "Instantaneous northward turbulent surface stress",
"N m**-2",
12741 "Instantaneous surface sensible heat flux",
"W m**-1",
12743 NC_DEF_VAR(
"lsm", NC_FLOAT, 2, dimid2,
"Land/sea mask",
"-",
12745 NC_DEF_VAR(
"sstk", NC_FLOAT, 2, dimid2,
"Sea surface temperature",
"K",
12747 NC_DEF_VAR(
"blp", NC_FLOAT, 2, dimid2,
"Boundary layer pressure",
"Pa",
12749 NC_DEF_VAR(
"pt", NC_FLOAT, 2, dimid2,
"Tropopause pressure",
"Pa",
12751 NC_DEF_VAR(
"tt", NC_FLOAT, 2, dimid2,
"Tropopause temperature",
"K",
12753 NC_DEF_VAR(
"zt", NC_FLOAT, 2, dimid2,
"Tropopause height",
"m",
12755 NC_DEF_VAR(
"h2ot", NC_FLOAT, 2, dimid2,
"Tropopause water vapor",
"ppv",
12757 NC_DEF_VAR(
"pct", NC_FLOAT, 2, dimid2,
"Cloud top pressure",
"Pa",
12759 NC_DEF_VAR(
"pcb", NC_FLOAT, 2, dimid2,
"Cloud bottom pressure",
"Pa",
12761 NC_DEF_VAR(
"cl", NC_FLOAT, 2, dimid2,
"Total column cloud water",
12764 "Pressure at lifted condensation level (LCL)",
"Pa",
12767 "Pressure at level of free convection (LFC)",
"Pa",
12770 "Pressure at equilibrium level (EL)",
"Pa", ctl->
met_nc_level,
12773 "Convective available potential energy",
"J kg**-1",
12775 NC_DEF_VAR(
"cin", NC_FLOAT, 2, dimid2,
"Convective inhibition",
12777 NC_DEF_VAR(
"o3c", NC_FLOAT, 2, dimid2,
"Total column ozone",
"DU",
12781 int dimid3[3] = { levid, latid, lonid };
12782 NC_DEF_VAR(
"t", NC_FLOAT, 3, dimid3,
"Temperature",
"K",
12784 NC_DEF_VAR(
"u", NC_FLOAT, 3, dimid3,
"U velocity",
"m s**-1",
12786 NC_DEF_VAR(
"v", NC_FLOAT, 3, dimid3,
"V velocity",
"m s**-1",
12788 NC_DEF_VAR(
"w", NC_FLOAT, 3, dimid3,
"Vertical velocity",
"Pa s**-1",
12790 NC_DEF_VAR(
"q", NC_FLOAT, 3, dimid3,
"Specific humidity",
"kg kg**-1",
12792 NC_DEF_VAR(
"o3", NC_FLOAT, 3, dimid3,
"Ozone mass mixing ratio",
12794 NC_DEF_VAR(
"clwc", NC_FLOAT, 3, dimid3,
"Cloud liquid water content",
12796 NC_DEF_VAR(
"crwc", NC_FLOAT, 3, dimid3,
"Cloud rain water content",
12798 NC_DEF_VAR(
"ciwc", NC_FLOAT, 3, dimid3,
"Cloud ice water content",
12800 NC_DEF_VAR(
"cswc", NC_FLOAT, 3, dimid3,
"Cloud snow water content",
12802 NC_DEF_VAR(
"cc", NC_FLOAT, 3, dimid3,
"Cloud cover",
"-",
12806 NC(nc_enddef(ncid));
12813 for (
int ip = 0; ip < met->
np; ip++)
12814 phelp[ip] = 100. * met->
p[ip];
12857 NC(nc_close(ncid));
12864 const char *varname,
12870 size_t start[4], count[4];
12878 for (
int ix = 0; ix < met->
nx; ix++)
12879 for (
int iy = 0; iy < met->
ny; iy++)
12880 help[
ARRAY_2D(iy, ix, met->
nx)] = scl * var[ix][iy];
12893 const char *varname,
12899 size_t start[4], count[4];
12907 for (
int ix = 0; ix < met->
nx; ix++)
12908 for (
int iy = 0; iy < met->
ny; iy++)
12909 for (
int ip = 0; ip < met->
np; ip++)
12910 help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)] = scl * var[ix][iy][ip];
12922 const char *filename,
12931 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
12932 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
12934 static int nobs, *obscount, ip, okay;
12943 if (ctl->
qnt_m < 0)
12944 ERRMSG(
"Need quantity mass!");
12948 ERRMSG(
"Specify molar mass!");
12955 ALLOC(area,
double,
12959 ALLOC(press,
double,
12965 ALLOC(rlon,
double,
12967 ALLOC(rlat,
double,
12969 ALLOC(robs,
double,
12976 LOG(1,
"Write profile data: %s", filename);
12977 if (!(out = fopen(filename,
"w")))
12978 ERRMSG(
"Cannot create file!");
12982 "# $1 = time [s]\n"
12983 "# $2 = altitude [km]\n"
12984 "# $3 = longitude [deg]\n"
12985 "# $4 = latitude [deg]\n"
12986 "# $5 = pressure [hPa]\n"
12987 "# $6 = temperature [K]\n"
12988 "# $7 = volume mixing ratio [ppv]\n"
12989 "# $8 = H2O volume mixing ratio [ppv]\n"
12990 "# $9 = O3 volume mixing ratio [ppv]\n"
12991 "# $10 = observed BT index [K]\n"
12992 "# $11 = number of observations\n");
13000 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
13001 z[iz] = ctl->
prof_z0 + dz * (iz + 0.5);
13002 press[iz] =
P(z[iz]);
13006 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
13007 lon[ix] = ctl->
prof_lon0 + dlon * (ix + 0.5);
13008 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
13009 lat[iy] = ctl->
prof_lat0 + dlat * (iy + 0.5);
13010 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
13015 const double t0 = t - 0.5 * ctl->
dt_mod;
13016 const double t1 = t + 0.5 * ctl->
dt_mod;
13019 ALLOC(mass,
double,
13021 ALLOC(obsmean,
double,
13023 ALLOC(obscount,
int,
13027 for (
int i = 0; i < nobs; i++) {
13032 else if (rt[i] >= t1)
13036 if (!isfinite(robs[i]))
13040 const int ix = (int) ((rlon[i] - ctl->
prof_lon0) / dlon);
13041 const int iy = (int) ((rlat[i] - ctl->
prof_lat0) / dlat);
13044 if (ix < 0 || ix >= ctl->
prof_nx || iy < 0 || iy >= ctl->
prof_ny)
13049 obsmean[idx] += robs[i];
13054 for (ip = 0; ip < atm->
np; ip++) {
13057 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13061 const int ix = (int) ((atm->
lon[ip] - ctl->
prof_lon0) / dlon);
13062 const int iy = (int) ((atm->
lat[ip] - ctl->
prof_lat0) / dlat);
13063 const int iz = (int) ((
Z(atm->
p[ip]) - ctl->
prof_z0) / dz);
13066 if (ix < 0 || ix >= ctl->
prof_nx ||
13072 mass[idx] += atm->
q[ctl->
qnt_m][ip];
13076 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
13077 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
13079 if (obscount[idx2] > 0) {
13083 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
13085 if (mass[idx3] > 0) {
13094 fprintf(out,
"\n");
13097 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
13102 lon[ix], lat[iy], &temp, ci, cw, 1);
13104 lon[ix], lat[iy], &h2o, ci, cw, 0);
13106 lon[ix], lat[iy], &o3, ci, cw, 0);
13111 / (
RHO(press[iz], temp) * area[iy] * dz * 1e9);
13114 fprintf(out,
"%.2f %g %g %g %g %g %g %g %g %g %d\n",
13115 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
13116 obsmean[idx2] / obscount[idx2], obscount[idx2]);
13149 const char *filename,
13158 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[
EP],
13161 static int nobs, nk;
13174 ALLOC(rlon,
double,
13176 ALLOC(rlat,
double,
13178 ALLOC(robs,
double,
13189 LOG(1,
"Write sample data: %s", filename);
13190 if (!(out = fopen(filename,
"w")))
13191 ERRMSG(
"Cannot create file!");
13195 "# $1 = time [s]\n"
13196 "# $2 = altitude [km]\n"
13197 "# $3 = longitude [deg]\n"
13198 "# $4 = latitude [deg]\n"
13199 "# $5 = surface area [km^2]\n"
13200 "# $6 = layer depth [km]\n"
13201 "# $7 = number of particles [1]\n"
13202 "# $8 = column density [kg/m^2]\n"
13203 "# $9 = volume mixing ratio [ppv]\n"
13204 "# $10 = observed BT index [K]\n\n");
13209 area = M_PI * rmax2;
13213 const double t0 = t - 0.5 * ctl->
dt_mod;
13214 const double t1 = t + 0.5 * ctl->
dt_mod;
13217 for (
int i = 0; i < nobs; i++) {
13222 else if (rt[i] >= t1)
13227 geo2cart(0, rlon[i], rlat[i], x0);
13230 const double rp =
P(rz[i]);
13231 const double ptop =
P(rz[i] + ctl->
sample_dz);
13232 const double pbot =
P(rz[i] - ctl->
sample_dz);
13240 for (
int ip = 0; ip < atm->
np; ip++) {
13243 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13247 if (fabs(rlat[i] - atm->
lat[ip]) > dlat)
13253 if (
DIST2(x0, x1) > rmax2)
13258 if (atm->
p[ip] > pbot || atm->
p[ip] < ptop)
13262 if (ctl->
qnt_m >= 0)
13269 const double cd = mass / (1e6 * area);
13280 rlon[i], rlat[i], &temp, ci, cw, 1);
13289 fprintf(out,
"%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
13290 rlon[i], rlat[i], area, ctl->
sample_dz, np, cd, vmr, robs[i]);
13311 const char *filename,
13318 static double rmax2, x0[3], x1[3];
13327 LOG(1,
"Write station data: %s", filename);
13330 if (!(out = fopen(filename,
"w")))
13331 ERRMSG(
"Cannot create file!");
13335 "# $1 = time [s]\n"
13336 "# $2 = altitude [km]\n"
13337 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
13338 for (
int iq = 0; iq < ctl->
nq; iq++)
13339 fprintf(out,
"# $%i = %s [%s]\n", (iq + 5),
13341 fprintf(out,
"\n");
13349 const double t0 = t - 0.5 * ctl->
dt_mod;
13350 const double t1 = t + 0.5 * ctl->
dt_mod;
13353 for (
int ip = 0; ip < atm->
np; ip++) {
13356 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13372 if (
DIST2(x0, x1) > rmax2)
13380 fprintf(out,
"%.2f %g %g %g",
13381 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]);
13382 for (
int iq = 0; iq < ctl->
nq; iq++) {
13384 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
13386 fprintf(out,
"\n");
13397 const char *filename,
13408 LOG(1,
"Write VTK data: %s", filename);
13411 const double t0 = t - 0.5 * ctl->
dt_mod;
13412 const double t1 = t + 0.5 * ctl->
dt_mod;
13415 if (!(out = fopen(filename,
"w")))
13416 ERRMSG(
"Cannot create file!");
13420 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13421 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13428 "# vtk DataFile Version 3.0\n"
13429 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
13432 fprintf(out,
"POINTS %d float\n", np);
13434 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13435 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13439 const double coslat = cos(
DEG2RAD(atm->
lat[ip]));
13440 const double x = radius * coslat * cos(
DEG2RAD(atm->
lon[ip]));
13441 const double y = radius * coslat * sin(
DEG2RAD(atm->
lon[ip]));
13442 const double z = radius * sin(
DEG2RAD(atm->
lat[ip]));
13443 fprintf(out,
"%g %g %g\n", x, y, z);
13446 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13447 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13449 fprintf(out,
"%g %g %g\n", atm->
lon[ip], atm->
lat[ip],
13454 fprintf(out,
"POINT_DATA %d\n", np);
13455 for (
int iq = 0; iq < ctl->
nq; iq++) {
13456 fprintf(out,
"SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
13458 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13459 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13461 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.
void compress_cms(const ctl_t *ctl, const char *varname, float *array, const size_t nx, const size_t ny, const size_t np, const double *plev, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using a custom multiscale compression algorithm.
#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_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_cms_nd0x
cmultiscale number of cells of coarsest grid in x-direction.
int met_nlev
Number of meteo data model levels.
double dt_kpp
Time step for KPP chemistry [s].
char csi_basename[LEN]
Basename of CSI data files.
double dry_depo_dp
Dry deposition surface layer [hPa].
int qnt_shf
Quantity array index for surface sensible heat flux.
int qnt_vs
Quantity array index for surface meridional wind.
int qnt_Cco
Quantity array index for CO volume mixing ratio (chemistry code).
double vtk_dt_out
Time step for VTK data output [s].
double t_stop
Stop time of simulation [s].
double conv_dt
Time interval for convection module [s].
char sample_obsfile[LEN]
Observation data file for sample output.
int qnt_hno3
Quantity array index for HNO3 volume mixing ratio (climatology).
char grid_basename[LEN]
Basename of grid data files.
int met_clams
Read MPTRAC or CLaMS meteo data (0=MPTRAC, 1=CLaMS).
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 met_cms_nd0y
cmultiscale number of cells of coarsest grid in y-direction.
int mixing_nz
Number of altitudes of mixing grid.
int qnt_o3c
Quantity array index for total column ozone.
double bound_p0
Boundary conditions bottom pressure [hPa].
double mixing_lon0
Lower longitude of mixing grid [deg].
char clim_ccl4_timeseries[LEN]
Filename of CFC-10 time series.
int qnt_Co3
Quantity array index for O3 volume mixing ratio (chemistry code).
int qnt_tsts
Quantity array index for T_STS.
int grid_nz
Number of altitudes of gridded data.
char clim_oh_filename[LEN]
Filename of OH climatology.
int qnt_nss
Quantity array index for northward turbulent surface stress.
double ens_dt_out
Time step for ensemble output [s].
char sample_basename[LEN]
Basename of sample data file.
int atm_stride
Particle index stride for atmospheric data files.
int met_relhum
Try to read relative humidity (0=no, 1=yes).
double mixing_lat1
Upper latitude of mixing grid [deg].
double atm_dt_out
Time step for atmospheric data output [s].
char clim_sf6_timeseries[LEN]
Filename of SF6 time series.
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 met_cms_maxlev
cmultiscale maximum refinement level.
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.
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).