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 += 1.0 / cms_compression_rate(cms_ptr, cms_sol);
519 cms_delete_sol(cms_sol);
520 cms_delete_module(cms_ptr);
524 LOG(2,
"Read 3-D variable: %s (CMS, RATIO= %g)", varname,
532 cms_module_t *cms_ptr[
EP];
533 cms_sol_t *cms_sol[
EP];
537 ? (size_t) omp_get_max_threads()
539 for (
size_t ip0 = 0; ip0 < np; ip0 += dip) {
542 double t0 = omp_get_wtime();
545#pragma omp parallel for default(shared)
546 for (
size_t ip = ip0; ip <
MIN(ip0 + dip, np); ip++) {
550 ALLOC(tmp_arr,
float,
554 for (
size_t ix = 0; ix < nx; ++ix)
555 for (
size_t iy = 0; iy < ny; ++iy)
557 array[
ARRAY_3D(ix, iy, ny, ip, np)];
560 double c_thresh_test;
561 if (strcasecmp(varname,
"Z") == 0)
563 else if (strcasecmp(varname,
"T") == 0)
565 else if (strcasecmp(varname,
"U") == 0)
567 else if (strcasecmp(varname,
"V") == 0)
569 else if (strcasecmp(varname,
"W") == 0)
571 else if (strcasecmp(varname,
"PV") == 0)
573 else if (strcasecmp(varname,
"H2O") == 0)
575 else if (strcasecmp(varname,
"O3") == 0)
577 else if (strcasecmp(varname,
"LWC") == 0)
579 else if (strcasecmp(varname,
"RWC") == 0)
581 else if (strcasecmp(varname,
"IWC") == 0)
583 else if (strcasecmp(varname,
"SWC") == 0)
585 else if (strcasecmp(varname,
"CC") == 0)
588 ERRMSG(
"Variable name unknown!");
591 cms_ptr[ip] = cms_init(cms_param);
595 cms_read_arr_new(cms_ptr[ip], tmp_arr, lon, lat,
596 nx, ny, c_thresh_test);
603 t_coars += (omp_get_wtime() - t0);
606 for (
size_t ip = ip0; ip <
MIN(ip0 + dip, np); ip++) {
609 double *tmp_cms, *tmp_org, *tmp_diff;
610 ALLOC(tmp_cms,
double,
612 ALLOC(tmp_org,
double,
614 ALLOC(tmp_diff,
double,
618 t0 = omp_get_wtime();
621#pragma omp parallel for collapse(2) default(shared)
622 for (
size_t ix = 0; ix < nx; ix++)
623 for (
size_t iy = 0; iy < ny; iy++) {
624 const size_t idx =
ARRAY_2D(ix, iy, ny);
625 const double x[] = { lon[ix], lat[iy] };
626 cms_eval(cms_ptr[ip], cms_sol[ip], x, &tmp_cms[idx]);
627 tmp_org[idx] = array[
ARRAY_3D(ix, iy, ny, ip, np)];
628 tmp_diff[idx] = tmp_cms[idx] - tmp_org[idx];
632 t_eval += (omp_get_wtime() - t0);
635 const double bias = gsl_stats_mean(tmp_diff, 1, nxy);
636 const double stddev = gsl_stats_sd_m(tmp_diff, 1, nxy, bias);
639 gsl_stats_max(tmp_org, 1, nxy) - gsl_stats_min(tmp_org, 1, nxy);
640 const double nrmse = (range > 0 ? rmse / range : NAN);
642 "cmultiscale: var= %s / lev= %lu / plev= %g / ratio= %g / rho= %g"
643 " / mean= %g / sd= %g / min= %g / max= %g / NRMSE= %g", varname,
644 ip, plev[ip], cms_compression_rate(cms_ptr[ip], cms_sol[ip]),
645 gsl_stats_correlation(tmp_cms, 1, tmp_org, 1, nxy), bias,
stddev,
646 gsl_stats_min(tmp_diff, 1, nxy), gsl_stats_max(tmp_diff, 1, nxy),
650 cr += 1.0 / cms_compression_rate(cms_ptr[ip], cms_sol[ip]);
654 cms_save_zstd_sol(cms_sol[ip], inout, 3);
656 cms_save_sol(cms_sol[ip], inout);
659 cms_delete_sol(cms_sol[ip]);
660 cms_delete_module(cms_ptr[ip]);
668 LOG(2,
"Write 3-D variable: %s"
669 " (CMS, RATIO= %g, T_COARS= %g s, T_EVAL= %g s)",
670 varname, (
double) np / cr, t_coars, t_eval);
674 cms_delete_param(cms_param);
685 const int decompress,
688 double min[
EP], max[
EP], off[
EP], scl[
EP];
690 unsigned short *sarray;
693 ALLOC(sarray,
unsigned short,
700 LOG(2,
"Read 3-D variable: %s (pck, RATIO= %g)",
701 varname, (
double)
sizeof(
float) / (
double)
sizeof(
unsigned short));
710 FREAD(sarray,
unsigned short,
715#pragma omp parallel for default(shared)
716 for (
size_t ixy = 0; ixy < nxy; ixy++)
717 for (
size_t iz = 0; iz < nz; iz++)
719 = (
float) (sarray[ixy * nz + iz] * scl[iz] + off[iz]);
726 LOG(2,
"Write 3-D variable: %s (pck, RATIO= %g)",
727 varname, (
double)
sizeof(
float) / (
double)
sizeof(
unsigned short));
730 for (
size_t iz = 0; iz < nz; iz++) {
734 for (
size_t ixy = 1; ixy < nxy; ixy++)
735 for (
size_t iz = 0; iz < nz; iz++) {
736 if (array[ixy * nz + iz] < min[iz])
737 min[iz] = array[ixy * nz + iz];
738 if (array[ixy * nz + iz] > max[iz])
739 max[iz] = array[ixy * nz + iz];
743 for (
size_t iz = 0; iz < nz; iz++) {
744 scl[iz] = (max[iz] - min[iz]) / 65533.;
749#pragma omp parallel for default(shared)
750 for (
size_t ixy = 0; ixy < nxy; ixy++)
751 for (
size_t iz = 0; iz < nz; iz++)
753 sarray[ixy * nz + iz] = (
unsigned short)
754 ((array[ixy * nz + iz] - off[iz]) / scl[iz] + .5);
756 sarray[ixy * nz + iz] = 0;
765 FWRITE(sarray,
unsigned short,
787 if ((precision > 0) == (tolerance > 0.0))
788 ERRMSG(
"Exactly one of precision or tolerance must be set for SZ3!");
790 size_t r1 = (size_t) nx, r2 = (
size_t) ny, r3 = (size_t) nz,
791 outSize = 0, total_elems = r1 * r2 * r3;
793 unsigned char *bytes = NULL;
799 FREAD(&sz3size,
size_t,
804 FREAD(bytes,
unsigned char,
808 void *outData = SZ_decompress(SZ_FLOAT, bytes, sz3size, 0, 0, r3, r2, r1);
810 ERRMSG(
"Decompression failed!");
812 memcpy(array, outData, total_elems *
sizeof(
float));
817 LOG(2,
"Read 3-D variable: %s (SZ3, PREC=%d, TOL=%g, RATIO=%g)",
818 varname, precision, tolerance,
819 (
double) (total_elems *
sizeof(
float)) / (
double) sz3size);
825 const int errBoundMode = (precision > 0) ? REL : ABS;
826 const double absBound = (errBoundMode == ABS) ? tolerance : 0.0;
827 const double relBound =
828 (errBoundMode == REL) ? pow(2.0, -(
double) precision) : 0.0;
830 bytes = SZ_compress_args(SZ_FLOAT, array, &outSize,
831 errBoundMode, absBound, relBound, 0.0,
833 if (!bytes || outSize == 0)
834 ERRMSG(
"Compression failed!");
839 FWRITE(bytes,
unsigned char,
845 LOG(2,
"Write 3-D variable: %s (SZ3, PREC=%d, TOL=%g, RATIO=%g)",
846 varname, precision, tolerance,
847 (
double) (total_elems *
sizeof(
float)) / (
double) outSize);
862 const double tolerance,
863 const int decompress,
867 const size_t snx = (size_t) nx;
868 const size_t sny = (size_t) ny;
869 const size_t snz = (size_t) nz;
870 const zfp_type type = zfp_type_float;
871 zfp_field *field = zfp_field_3d(array, type, snx, sny, snz);
874 zfp_stream *zfp = zfp_stream_open(NULL);
876 ERRMSG(
"Failed to allocate zfp structures!");
880 double actual_tol = 0;
881 if ((precision > 0 && tolerance > 0) || (precision <= 0 && tolerance <= 0)) {
882 ERRMSG(
"Exactly one of precision or tolerance must be set for zfp!");
883 }
else if (precision > 0)
885 (int) zfp_stream_set_precision(zfp, (
unsigned int) precision);
886 else if (tolerance > 0)
887 actual_tol = zfp_stream_set_accuracy(zfp, tolerance);
890 const size_t bufsize = zfp_stream_maximum_size(zfp, field);
896 bitstream *stream = stream_open(buffer, bufsize);
897 zfp_stream_set_bit_stream(zfp, stream);
898 zfp_stream_rewind(zfp);
903 FREAD(&zfpsize,
size_t,
906 if (zfpsize > bufsize)
907 ERRMSG(
"Compressed data size exceeds allocated buffer!");
908 FREAD(buffer,
unsigned char,
911 if (!zfp_decompress(zfp, field)) {
912 ERRMSG(
"Decompression failed!");
915 ((double) (snx * sny * snz *
sizeof(
float))) / (double) zfpsize;
916 const double bpv = (8.0 * (double) zfpsize) / (double) (snx * sny * snz);
918 "Read 3-D variable: %s (ZFP, PREC= %d, TOL= %g, RATIO= %g, BPV= %g)",
919 varname, actual_prec, actual_tol, cr, bpv);
924 zfpsize = zfp_compress(zfp, field);
926 ERRMSG(
"Compression failed!");
931 FWRITE(buffer,
unsigned char,
936 ((double) (snx * sny * snz *
sizeof(
float))) / (double) zfpsize;
937 const double bpv = (8.0 * (double) zfpsize) / (double) (snx * sny * snz);
939 "Write 3-D variable: %s (ZFP, PREC= %d, TOL= %g, RATIO= %g, BPV= %g)",
940 varname, actual_prec, actual_tol, cr, bpv);
944 zfp_field_free(field);
945 stream_close(stream);
946 zfp_stream_close(zfp);
958 const int decompress,
963 const size_t uncomprLen = n *
sizeof(float);
964 size_t compsize, comprLen = ZSTD_compressBound(uncomprLen);
967 char *compr = calloc(comprLen, 1);
969 ERRMSG(
"Memory allocation failed!");
970 char *uncompr = (
char *) array;
974 FREAD(&comprLen,
size_t,
977 FREAD(compr,
unsigned char,
980 compsize = ZSTD_decompress(uncompr, uncomprLen, compr, comprLen);
981 if (ZSTD_isError(compsize) || compsize != uncomprLen)
982 ERRMSG(
"Decompression failed or size mismatch!");
983 LOG(2,
"Read 3-D variable: %s (ZSTD, RATIO= %g)",
984 varname, ((
double) uncomprLen) / (
double) comprLen);
989 compsize = ZSTD_compress(compr, comprLen, uncompr, uncomprLen, level);
990 if (ZSTD_isError(compsize)) {
991 ERRMSG(
"Compression failed!");
996 FWRITE(compr,
unsigned char,
1000 LOG(2,
"Write 3-D variable: %s (ZSTD, RATIO= %g)",
1001 varname, ((
double) uncomprLen) / (
double) compsize);
1017 const double D = sec / 86400 - 0.5;
1020 const double g =
DEG2RAD(357.529 + 0.98560028 * D);
1021 const double q = 280.459 + 0.98564736 * D;
1022 const double L =
DEG2RAD(q + 1.915 * sin(g) + 0.020 * sin(2 * g));
1025 const double e =
DEG2RAD(23.439 - 0.00000036 * D);
1028 const double sindec = sin(e) * sin(L);
1031 const double ra = atan2(cos(e) * sin(L), cos(L));
1034 const double GMST = 18.697374558 + 24.06570982441908 * D;
1037 const double LST = GMST + lon / 15;
1040 const double h = LST / 12 * M_PI - ra;
1043 const double lat_help =
DEG2RAD(lat);
1046 return sin(lat_help) * sindec + cos(lat_help) * sqrt(1 -
1047 SQR(sindec)) * cos(h);
1059 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
1060 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
1063 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
1064 *doy = d0l[mon - 1] + day - 1;
1066 *doy = d0[mon - 1] + day - 1;
1078 SELECT_TIMER(
"DD_ASSIGN_RECT_SUBDOMAINS",
"DD", NVTX_GPU);
1082#pragma acc enter data create(dd)
1083#pragma acc update device(dd->rank, dd->subdomain_lon_min, dd->subdomain_lon_max, dd->subdomain_lat_min, dd->subdomain_lat_max)
1084#pragma acc data present(atm, ctl, dd)
1085#pragma acc parallel loop independent gang vector
1087 for (
int ip = 0; ip < atm->
np; ip++) {
1089 double lont = atm->
lon[ip];
1101 (
"DD: Particle is outside the domain (lon: %f, lat: %f, subdomain: %d, subdomain bounds: [%f, %f], [%f, %f])",
1110#pragma acc exit data delete(dd)
1116#pragma acc enter data create(dd)
1117#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)
1118#pragma acc data present(atm, ctl, dd)
1119#pragma acc parallel loop independent gang vector
1121 for (
int ip = 0; ip < atm->
np; ip++) {
1127 double lont = atm->
lon[ip];
1128 double latt = atm->
lat[ip];
1143 bound = (lont - lon_max > 90) ? 1 : 0;
1145 bound = (lon_min - lont > 90) ? 1 : 0;
1148 if ((lont >= lon_max) && (latt >= lat_max)) {
1152 "DD: Particle crossing to upper right: from rank %d to rank %d (lon: %f, lat: %f)",
1154 }
else if ((lont >= lon_max) && (latt <= lat_min)) {
1158 "DD: Particle crossing to lower right: from rank %d to rank %d (lon: %f, lat: %f)",
1160 }
else if ((lont <= lon_min) && (latt >= lat_max)) {
1164 "DD: Particle crossing to upper left: from rank %d to rank %d (lon: %f, lat: %f)",
1166 }
else if ((lont <= lon_min) && (latt <= lat_min)) {
1170 "DD: Particle crossing to lower left: from rank %d to rank %d (lon: %f, lat: %f)",
1172 }
else if (lont >= lon_max) {
1176 "DD: Particle crossing to right: from rank %d to rank %d (lon: %f, lat: %f)",
1178 }
else if (lont <= lon_min) {
1182 "DD: Particle crossing to left: from rank %d to rank %d (lon: %f, lat: %f)",
1184 }
else if (latt <= lat_min) {
1188 "DD: Particle crossing downward: from rank %d to rank %d (lon: %f, lat: %f)",
1190 }
else if (latt >= lat_max) {
1194 "DD: Particle crossing upward: from rank %d to rank %d (lon: %f, lat: %f)",
1201 if ((lont >= lon_max) && (latt >= lat_max)) {
1205 "DD: Particle crossing to upper left (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1207 }
else if ((lont >= lon_max) && (latt <= lat_min)) {
1211 "DD: Particle crossing to lower left (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1213 }
else if ((lont <= lon_min) && (latt >= lat_max)) {
1217 "DD: Particle crossing to upper right (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1219 }
else if ((lont <= lon_min) && (latt <= lat_min)) {
1223 "DD: Particle crossing to lower right (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1225 }
else if (lont >= lon_max) {
1229 "DD: Particle crossing to left (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1231 }
else if (lont <= lon_min) {
1235 "DD: Particle crossing to right (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1237 }
else if (latt <= lat_min) {
1241 "DD: Particle crossing downward (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1243 }
else if (latt >= lat_max) {
1247 "DD: Particle crossing upward (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1276#pragma acc exit data delete(dd)
1297 int npart = *nparticles;
1298#pragma acc enter data create( nparticles, particles[:DD_NPART])
1299#pragma acc update device( nparticles)
1300#pragma acc parallel loop present( atm, ctl, particles, cache, nparticles)
1302 for (
int ip = atm->
np; ip < atm->np + *nparticles; ip++)
1307 particles[ip - atm->
np].
time = atm->
time[ip];
1308 particles[ip - atm->
np].
lon = atm->
lon[ip];
1309 particles[ip - atm->
np].
lat = atm->
lat[ip];
1310 particles[ip - atm->
np].
p = atm->
p[ip];
1312 for (
int iq = 0; iq < ctl->
nq; iq++)
1313 particles[ip - atm->
np].q[iq] = atm->
q[iq][ip];
1316 "DD: Particle being prepared for transfer: subdomain %d -> destination %d (lon: %f, lat: %f)",
1323#pragma acc update host( particles[:npart])
1324#pragma acc exit data delete( nparticles, particles)
1342 double wrapped_lon = lon;
1343 while (wrapped_lon < 0)
1345 while (wrapped_lon >= 360)
1349 double wrapped_lat = lat;
1352 wrapped_lat = 180 - lat;
1353 wrapped_lon = fmod(wrapped_lon + 180, 360);
1354 }
else if (lat < -90) {
1356 wrapped_lat = -180 - lat;
1357 wrapped_lon = fmod(wrapped_lon + 180, 360);
1362 double lon_range = 360.0;
1373 LOG(2,
"nx_glob: %d", nx_glob);
1375 double lat_range = met->
lat[ny_glob - 1] - met->
lat[0];
1376 double global_lon_min = met->
lon[0];
1377 double global_lat_min = met->
lat[0];
1381 (int) ((wrapped_lon -
1384 (int) ((wrapped_lat -
1389 (
"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",
1390 lon, lat, wrapped_lon, wrapped_lat, lon_range, lat_range, global_lon_min,
1391 global_lat_min, lon_idx, lat_idx);
1396 0) ? 0 : ((lon_idx >=
1401 0) ? 0 : ((lat_idx >=
1403 dd_subdomains_meridional - 1 : lat_idx);
1409 if (target_rank >= mpi_size)
1410 target_rank = mpi_size - 1;
1411 if (target_rank < 0)
1441 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
1444 MPI_Request *requests_snd_nbr =
1445 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1446 MPI_Request *requests_rcv_nbr =
1447 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1448 MPI_Request *requests_snd_part =
1449 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1450 MPI_Request *requests_rcv_part =
1451 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1452 MPI_Status *states =
1453 (MPI_Status *) calloc((
size_t) nneighbours,
sizeof(MPI_Status));
1456 for (
int i = 0; i < nneighbours; i++) {
1457 requests_snd_nbr[i] = MPI_REQUEST_NULL;
1458 requests_rcv_nbr[i] = MPI_REQUEST_NULL;
1459 requests_snd_part[i] = MPI_REQUEST_NULL;
1460 requests_rcv_part[i] = MPI_REQUEST_NULL;
1464 for (
int idest = 0; idest < nneighbours; idest++) {
1467 if (neighbours[idest] < 0)
1473 for (
int ip = 0; ip < *nparticles; ip++)
1476 nbs[idest] = help_sum;
1479 LOG(3,
"DD: Rank %d sending %d particles to neighbour %d (rank %d)",
1480 rank, help_sum, idest, neighbours[idest]);
1485 MPI_Isend(&nbs[idest], 1, MPI_INT,
1486 neighbours[idest], 0, MPI_COMM_WORLD, &requests_snd_nbr[idest]);
1489 if (nbs[idest] == 0)
1498 for (
int ip = 0; ip < *nparticles; ip++) {
1499 if ((
int) particles[ip].q[ctl.
qnt_destination] == neighbours[idest]) {
1500 memcpy(&send_buffers[idest][ibs], &particles[ip],
sizeof(
particle_t));
1504 if (ibs == nbs[idest])
1511 MPI_Isend(send_buffers[idest], nbs[idest], MPI_Particle,
1512 neighbours[idest], 1, MPI_COMM_WORLD,
1513 &requests_snd_part[idest]);
1519 for (
int isourc = 0; isourc < nneighbours; isourc++) {
1522 if (neighbours[isourc] < 0) {
1523 requests_rcv_nbr[isourc] = MPI_REQUEST_NULL;
1528 MPI_Irecv(&nbr[isourc], 1, MPI_INT, neighbours[isourc], 0, MPI_COMM_WORLD,
1529 &requests_rcv_nbr[isourc]);
1533 MPI_Waitall(nneighbours, requests_rcv_nbr, states);
1536 for (
int isourc = 0; isourc < nneighbours; isourc++) {
1539 if ((neighbours[isourc] < 0) || (nbr[isourc] == 0)) {
1540 requests_rcv_part[isourc] = MPI_REQUEST_NULL;
1548 MPI_Irecv(recieve_buffers[isourc], nbr[isourc], MPI_Particle,
1549 neighbours[isourc], 1, MPI_COMM_WORLD,
1550 &requests_rcv_part[isourc]);
1554 MPI_Waitall(nneighbours, requests_rcv_part, states);
1562 for (
int isourc = 0; isourc < nneighbours; isourc++) {
1565 if (neighbours[isourc] < 0)
1568 if (nbr[isourc] > 0) {
1569 LOG(3,
"DD: Rank %d receiving %d particles from neighbour %d (rank %d)",
1570 rank, nbr[isourc], isourc, neighbours[isourc]);
1574 for (
int ip = 0; ip < nbr[isourc]; ip++) {
1575 memcpy(&particles[ip + api], &recieve_buffers[isourc][ip],
1589 MPI_Waitall(nneighbours, requests_snd_part, states);
1590 MPI_Waitall(nneighbours, requests_snd_nbr, states);
1593 for (
int i = 0; i < nneighbours; i++) {
1595 if ((send_buffers[i] != NULL) && (nbs[i] != 0)) {
1596 free(send_buffers[i]);
1597 send_buffers[i] = NULL;
1600 if ((recieve_buffers[i] != NULL) && (nbr[i] != 0)) {
1601 free(recieve_buffers[i]);
1602 recieve_buffers[i] = NULL;
1619 const int rank = dd->
rank;
1620 const int size = dd->
size;
1624 nb[0] = (size + rank - m) % size;
1625 nb[3] = (rank + m) % size;
1626 nb[1] = ((rank + 1) % m == 0) ?
DD_SPOLE : (size + rank - m + 1) % size;
1627 nb[2] = (rank % m == 0) ?
DD_NPOLE : (size + rank - m - 1) % size;
1628 nb[4] = ((rank + 1) % m == 0) ?
DD_SPOLE : (rank + m + 1) % size;
1629 nb[5] = (rank % m == 0) ?
DD_NPOLE : (rank + m - 1) % size;
1630 nb[6] = (rank % m == 0) ?
DD_NPOLE : rank - 1;
1631 nb[7] = ((rank + 1) % m == 0) ?
DD_SPOLE : rank + 1;
1647 double lon_spacing = met->
lon[1] - met->
lon[0];
1651 double total_range = met->
lon[nx_glob - 1] - met->
lon[0] + lon_spacing;
1654 return (fabs(total_range - 360.0) < 0.01);
1668 ERRMSG(
"The number of tasks and subdomains is not identical.");
1699 int npart = *nparticles;
1700#pragma acc enter data create(nparticles, particles[:DD_NPART])
1701#pragma acc update device(particles[:npart], nparticles)
1702#pragma acc data present(atm, ctl, cache, particles, nparticles)
1703#pragma acc parallel loop
1705 for (
int ip = atm->
np; ip < atm->np + *nparticles; ip++) {
1706 atm->
time[ip] = particles[ip - atm->
np].
time;
1707 atm->
lon[ip] = particles[ip - atm->
np].
lon;
1708 atm->
lat[ip] = particles[ip - atm->
np].
lat;
1709 atm->
p[ip] = particles[ip - atm->
np].
p;
1710 for (
int iq = 0; iq < ctl->
nq; iq++)
1711 atm->
q[iq][ip] = particles[ip - atm->
np].q[iq];
1715#pragma acc exit data delete(nparticles, particles)
1719 atm->
np += *nparticles;
1721#pragma acc update device(atm->np)
1724 ERRMSG(
"Number of particles to high. Increase NP!");
1733 MPI_Datatype types[5] = { MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE,
1734 MPI_DOUBLE, MPI_DOUBLE
1736 int blocklengths[5] = { 1, 1, 1, 1,
NQ };
1737 MPI_Aint displacements[5] = { offsetof(
particle_t, time),
1743 MPI_Type_create_struct(5, blocklengths, displacements, types, MPI_Particle);
1744 MPI_Type_commit(MPI_Particle);
1763 const int np = atm->
np;
1764 double amax = (met0->
nx * met0->
ny + met0->
ny) * met0->
np + met0->
np;
1766#pragma acc enter data create(amax, rank)
1767#pragma acc update device(rank, amax)
1768#pragma acc data present(ctl,met0,atm,dd,amax,rank)
1773#pragma acc parallel loop independent gang vector
1775#pragma omp parallel for default(shared)
1777 for (
int ip = 0; ip < np; ip++) {
1785 dd->a[ip] = amax + 1;
1787 dd->a[ip] = amax + 2;
1795#pragma acc host_data use_device(dd->a,dd->p)
1797 thrustSortWrapper(dd->a, np, dd->p);
1800 ERRMSG(
"GSL sort fallback not available on GPU, use THRUST!");
1802 gsl_sort_index((
size_t *) (dd->p), (dd->a), 1, (
size_t) np);
1810 for (
int iq = 0; iq < ctl->
nq; iq++)
1816#pragma acc parallel loop reduction(+:npt) present(atm, rank, ctl)
1818 for (
int ip = 0; ip < np; ip++)
1824 int nparticlest = 0;
1826#pragma acc parallel loop reduction(+:nparticlest) present(atm, rank, ctl)
1828 for (
int ip = npt; ip < np; ip++)
1834 *nparticles = nparticlest;
1838 for (
int ip = 0; ip < np; ip++)
1844 (
"DD: Rank %d: %d particles have subdomain index -1 and will be lost (kept: %d, to_send: %d, total_before: %d)",
1845 *rank, nlost, npt, nparticlest, np);
1850#pragma acc update device(atm->np)
1855 (
"Number of particles to send and recieve to small. Increase DD_NPART!");
1859#pragma acc exit data delete(amax, rank)
1874#pragma acc data present(dd,a)
1875#pragma acc parallel loop independent gang vector
1877#pragma omp parallel for default(shared)
1879 for (
int ip = 0; ip < np; ip++)
1880 dd->help[ip] = a[dd->p[ip]];
1882#pragma acc parallel loop independent gang vector
1884#pragma omp parallel
for default(shared)
1886 for (
int ip = 0; ip < np; ip++)
1887 a[ip] = dd->help[ip];
1900 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
1901 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
1906 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
1907 for (i = 11; i > 0; i--)
1911 *day = doy - d0l[i] + 1;
1913 for (i = 11; i > 0; i--)
1917 *day = doy - d0[i] + 1;
1928 double data[2 *
EX];
1932 ERRMSG(
"Too many data points!");
1935 gsl_fft_complex_wavetable *wavetable =
1936 gsl_fft_complex_wavetable_alloc((
size_t) n);
1937 gsl_fft_complex_workspace *workspace =
1938 gsl_fft_complex_workspace_alloc((
size_t) n);
1941 for (
int i = 0; i < n; i++) {
1942 data[2 * i] = fcReal[i];
1943 data[2 * i + 1] = fcImag[i];
1947 gsl_fft_complex_forward(data, 1, (
size_t) n, wavetable, workspace);
1950 for (
int i = 0; i < n; i++) {
1951 fcReal[i] = data[2 * i];
1952 fcImag[i] = data[2 * i + 1];
1956 gsl_fft_complex_wavetable_free(wavetable);
1957 gsl_fft_complex_workspace_free(workspace);
1968 const double radius = z +
RE;
1969 const double latrad =
DEG2RAD(lat);
1970 const double lonrad =
DEG2RAD(lon);
1971 const double coslat = cos(latrad);
1973 x[0] = radius * coslat * cos(lonrad);
1974 x[1] = radius * coslat * sin(lonrad);
1975 x[2] = radius * sin(latrad);
1984 const char *metbase,
1985 const double dt_met,
1992 int year, mon, day, hour, min, sec;
1996 t6 = floor(t / dt_met) * dt_met;
1998 t6 = ceil(t / dt_met) * dt_met;
2001 jsec2time(t6, &year, &mon, &day, &hour, &min, &sec, &r);
2006 sprintf(filename,
"%s_YYYY_MM_DD_HH.nc", metbase);
2008 sprintf(filename,
"%s_YYYY_MM_DD_HH.bin", metbase);
2010 sprintf(filename,
"%s_YYYY_MM_DD_HH.pck", metbase);
2012 sprintf(filename,
"%s_YYYY_MM_DD_HH.zfp", metbase);
2014 sprintf(filename,
"%s_YYYY_MM_DD_HH.zstd", metbase);
2016 sprintf(filename,
"%s_YYYY_MM_DD_HH.cms", metbase);
2018 sprintf(filename,
"%s_YYYY_MM_DD_HH.sz3", metbase);
2019 sprintf(repl,
"%d", year);
2021 sprintf(repl,
"%02d", mon);
2023 sprintf(repl,
"%02d", day);
2025 sprintf(repl,
"%02d", hour);
2031 sprintf(filename,
"%s_YYMMDDHH.nc", metbase);
2032 sprintf(repl,
"%d", year);
2034 sprintf(repl,
"%02d", year % 100);
2036 sprintf(repl,
"%02d", mon);
2038 sprintf(repl,
"%02d", day);
2040 sprintf(repl,
"%02d", hour);
2055 for (
int i = 0; i < 3; i++) {
2059 if (!(ch = strstr(orig, search)))
2061 strncpy(buffer, orig, (
size_t) (ch - orig));
2062 buffer[ch - orig] = 0;
2063 sprintf(buffer + (ch - orig),
"%s%s", repl, ch + strlen(search));
2065 strcpy(orig, buffer);
2072 const int met_tropo,
2092#pragma omp parallel for default(shared) private(ci,cw)
2093 for (
int ix = 0; ix < nx; ix++)
2094 for (
int iy = 0; iy < ny; iy++) {
2096 &pt[iy * nx + ix], ci, cw, 1);
2098 &ps[iy * nx + ix], ci, cw, 0);
2100 &zs[iy * nx + ix], ci, cw, 0);
2102 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
2104 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
2106 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
2108 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
2125 *lon2 =
FMOD(lon, 360.);
2126 if (*lon2 < lons[0])
2128 else if (*lon2 > lons[nlon - 1])
2133 if (lats[0] < lats[nlat - 1])
2134 *lat2 =
MIN(
MAX(*lat2, lats[0]), lats[nlat - 1]);
2136 *lat2 =
MIN(
MAX(*lat2, lats[nlat - 1]), lats[0]);
2143 float heights0[
EX][
EY][
EP],
2144 float array0[
EX][
EY][
EP],
2146 float heights1[
EX][
EY][
EP],
2147 float array1[
EX][
EY][
EP],
2149 const double height,
2175 int k_max = ind[0][0];
2176 for (
int i = 0; i < 2; i++)
2177 for (
int j = 0; j < 4; j++) {
2178 if (ci[2] > ind[i][j])
2180 if (k_max < ind[i][j])
2186 cw[0] = (lon2 - met0->
lon[ci[0]]) /
2187 (met0->
lon[ci[0] + 1] - met0->
lon[ci[0]]);
2188 cw[1] = (lat2 - met0->
lat[ci[1]]) /
2189 (met0->
lat[ci[1] + 1] - met0->
lat[ci[1]]);
2192 double height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2]]
2193 - heights0[ci[0]][ci[1]][ci[2]])
2194 + heights0[ci[0]][ci[1]][ci[2]];
2195 double height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2]]
2196 - heights0[ci[0]][ci[1] + 1][ci[2]])
2197 + heights0[ci[0]][ci[1] + 1][ci[2]];
2198 double height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2]]
2199 - heights0[ci[0] + 1][ci[1]][ci[2]])
2200 + heights0[ci[0] + 1][ci[1]][ci[2]];
2201 double height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2]]
2202 - heights0[ci[0] + 1][ci[1] + 1][ci[2]])
2203 + heights0[ci[0] + 1][ci[1] + 1][ci[2]];
2206 double height0 = cw[1] * (height01 - height00) + height00;
2207 double height1 = cw[1] * (height11 - height10) + height10;
2210 double height_bot = cw[0] * (height1 - height0) + height0;
2213 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
2214 - heights0[ci[0]][ci[1]][ci[2] + 1])
2215 + heights0[ci[0]][ci[1]][ci[2] + 1];
2216 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
2217 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
2218 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
2219 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
2220 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
2221 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
2222 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2223 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2224 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2227 height0 = cw[1] * (height01 - height00) + height00;
2228 height1 = cw[1] * (height11 - height10) + height10;
2231 double height_top = cw[0] * (height1 - height0) + height0;
2234 while (((heights0[0][0][0] > heights0[0][0][1]) &&
2235 ((height_bot <= height) || (height_top > height))
2236 && (height_bot >= height) && (ci[2] < k_max))
2238 ((heights0[0][0][0] < heights0[0][0][1]) &&
2239 ((height_bot >= height) || (height_top < height))
2240 && (height_bot <= height) && (ci[2] < k_max))
2244 height_bot = height_top;
2247 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
2248 - heights0[ci[0]][ci[1]][ci[2] + 1])
2249 + heights0[ci[0]][ci[1]][ci[2] + 1];
2250 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
2251 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
2252 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
2253 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
2254 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
2255 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
2256 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2257 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2258 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2261 height0 = cw[1] * (height01 - height00) + height00;
2262 height1 = cw[1] * (height11 - height10) + height10;
2265 height_top = cw[0] * (height1 - height0) + height0;
2269 cw[2] = (height - height_bot)
2270 / (height_top - height_bot);
2274 const double array000 = cw[3] * (array1[ci[0]][ci[1]][ci[2]]
2275 - array0[ci[0]][ci[1]][ci[2]])
2276 + array0[ci[0]][ci[1]][ci[2]];
2277 const double array100 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2]]
2278 - array0[ci[0] + 1][ci[1]][ci[2]])
2279 + array0[ci[0] + 1][ci[1]][ci[2]];
2280 const double array010 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2]]
2281 - array0[ci[0]][ci[1] + 1][ci[2]])
2282 + array0[ci[0]][ci[1] + 1][ci[2]];
2283 const double array110 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2]]
2284 - array0[ci[0] + 1][ci[1] + 1][ci[2]])
2285 + array0[ci[0] + 1][ci[1] + 1][ci[2]];
2286 const double array001 = cw[3] * (array1[ci[0]][ci[1]][ci[2] + 1]
2287 - array0[ci[0]][ci[1]][ci[2] + 1])
2288 + array0[ci[0]][ci[1]][ci[2] + 1];
2289 const double array101 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2] + 1]
2290 - array0[ci[0] + 1][ci[1]][ci[2] + 1])
2291 + array0[ci[0] + 1][ci[1]][ci[2] + 1];
2292 const double array011 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2] + 1]
2293 - array0[ci[0]][ci[1] + 1][ci[2] + 1])
2294 + array0[ci[0]][ci[1] + 1][ci[2] + 1];
2295 const double array111 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2296 - array0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2297 + array0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2299 const double array00 = cw[0] * (array100 - array000) + array000;
2300 const double array10 = cw[0] * (array110 - array010) + array010;
2301 const double array01 = cw[0] * (array101 - array001) + array001;
2302 const double array11 = cw[0] * (array111 - array011) + array011;
2304 const double aux0 = cw[1] * (array10 - array00) + array00;
2305 const double aux1 = cw[1] * (array11 - array01) + array01;
2308 *var = cw[2] * (aux1 - aux0) + aux0;
2338 cw[0] = (met->
p[ci[0] + 1] - p)
2339 / (met->
p[ci[0] + 1] - met->
p[ci[0]]);
2340 cw[1] = (met->
lon[ci[1] + 1] - lon2)
2341 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
2342 cw[2] = (met->
lat[ci[2] + 1] - lat2)
2343 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
2347 const double aux00 =
2348 cw[0] * (array[ci[1]][ci[2]][ci[0]] - array[ci[1]][ci[2]][ci[0] + 1])
2349 + array[ci[1]][ci[2]][ci[0] + 1];
2350 const double aux01 =
2351 cw[0] * (array[ci[1]][ci[2] + 1][ci[0]] -
2352 array[ci[1]][ci[2] + 1][ci[0] + 1])
2353 + array[ci[1]][ci[2] + 1][ci[0] + 1];
2354 const double aux10 =
2355 cw[0] * (array[ci[1] + 1][ci[2]][ci[0]] -
2356 array[ci[1] + 1][ci[2]][ci[0] + 1])
2357 + array[ci[1] + 1][ci[2]][ci[0] + 1];
2358 const double aux11 =
2359 cw[0] * (array[ci[1] + 1][ci[2] + 1][ci[0]] -
2360 array[ci[1] + 1][ci[2] + 1][ci[0] + 1])
2361 + array[ci[1] + 1][ci[2] + 1][ci[0] + 1];
2364 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
2365 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
2366 *var = cw[1] * (aux0 - aux1) + aux1;
2373 float array[
EX][
EY],
2394 cw[1] = (met->
lon[ci[1] + 1] - lon2)
2395 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
2396 cw[2] = (met->
lat[ci[2] + 1] - lat2)
2397 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
2401 const double aux00 = array[ci[1]][ci[2]];
2402 const double aux01 = array[ci[1]][ci[2] + 1];
2403 const double aux10 = array[ci[1] + 1][ci[2]];
2404 const double aux11 = array[ci[1] + 1][ci[2] + 1];
2407 if (isfinite(aux00) && isfinite(aux01)
2408 && isfinite(aux10) && isfinite(aux11)) {
2409 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
2410 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
2411 *var = cw[1] * (aux0 - aux1) + aux1;
2431 float array0[
EX][
EY][
EP],
2433 float array1[
EX][
EY][
EP],
2450 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
2453 *var = wt * (var0 - var1) + var1;
2460 float array0[
EX][
EY],
2462 float array1[
EX][
EY],
2478 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
2481 if (isfinite(var0) && isfinite(var1))
2482 *var = wt * (var0 - var1) + var1;
2493 float array0[
EX][
EY],
2495 float array1[
EX][
EY],
2496 const double lons[
EX],
2497 const double lats[
EY],
2516 const int ix =
locate_reg(lons, (
int) nlon, lon2);
2517 const int iy =
locate_irr(lats, (
int) nlat, lat2);
2521 for (
int dx = 0; dx < 2; dx++)
2522 for (
int dy = 0; dy < 2; dy++) {
2523 if (isfinite(array0[ix + dx][iy + dy])) {
2524 mean += array0[ix + dx][iy + dy];
2525 *sigma +=
SQR(array0[ix + dx][iy + dy]);
2528 if (isfinite(array1[ix + dx][iy + dy])) {
2529 mean += array1[ix + dx][iy + dy];
2530 *sigma +=
SQR(array1[ix + dx][iy + dy]);
2535 *sigma = sqrt(
MAX(*sigma / n -
SQR(mean / n), 0.0));
2538 if (method == 1 && isfinite(array0[ix][iy])
2539 && isfinite(array0[ix][iy + 1])
2540 && isfinite(array0[ix + 1][iy])
2541 && isfinite(array0[ix + 1][iy + 1])
2542 && isfinite(array1[ix][iy])
2543 && isfinite(array1[ix][iy + 1])
2544 && isfinite(array1[ix + 1][iy])
2545 && isfinite(array1[ix + 1][iy + 1])) {
2547 const double aux00 =
LIN(lons[ix], array0[ix][iy],
2548 lons[ix + 1], array0[ix + 1][iy], lon2);
2549 const double aux01 =
LIN(lons[ix], array0[ix][iy + 1],
2550 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
2551 const double aux0 =
LIN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
2553 const double aux10 =
LIN(lons[ix], array1[ix][iy],
2554 lons[ix + 1], array1[ix + 1][iy], lon2);
2555 const double aux11 =
LIN(lons[ix], array1[ix][iy + 1],
2556 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
2557 const double aux1 =
LIN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
2559 *var =
LIN(time0, aux0, time1, aux1, time);
2564 const double aux00 =
NN(lons[ix], array0[ix][iy],
2565 lons[ix + 1], array0[ix + 1][iy], lon2);
2566 const double aux01 =
NN(lons[ix], array0[ix][iy + 1],
2567 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
2568 const double aux0 =
NN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
2570 const double aux10 =
NN(lons[ix], array1[ix][iy],
2571 lons[ix + 1], array1[ix + 1][iy], lon2);
2572 const double aux11 =
NN(lons[ix], array1[ix][iy + 1],
2573 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
2574 const double aux1 =
NN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
2576 *var =
NN(time0, aux0, time1, aux1, time);
2601 const time_t jsec0 = (time_t) jsec + timegm(&t0);
2602 t1 = gmtime(&jsec0);
2604 *year = t1->tm_year + 1900;
2605 *mon = t1->tm_mon + 1;
2607 *hour = t1->tm_hour;
2610 *remain = jsec - floor(jsec);
2616 const double kz[
EP],
2617 const double kw[
EP],
2626 const double z =
Z(p);
2631 else if (z > kz[nk - 1])
2635 return LIN(kz[idx], kw[idx], kz[idx + 1], kw[idx + 1], z);
2652 const double a =
RA *
SQR(t), r =
SH(h2o) / (1. -
SH(h2o));
2666 const double press[138] = {
2667 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
2668 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
2669 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
2670 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
2671 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2672 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
2673 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
2674 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
2675 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
2676 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
2677 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
2678 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
2679 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
2680 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
2681 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
2682 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
2683 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
2684 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
2685 1010.8487, 1013.2500, 1044.45
2688 for (
int ip = 0; ip < ctl->
met_np; ip++)
2695 const double press[92] = {
2696 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
2697 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
2698 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
2699 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
2700 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
2702 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
2703 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
2704 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
2705 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
2706 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
2707 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
2708 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
2709 1007.4431, 1010.8487, 1013.2500, 1044.45
2712 for (
int ip = 0; ip < ctl->
met_np; ip++)
2719 const double press[60] = {
2720 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
2721 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
2722 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
2723 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
2724 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
2725 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
2726 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
2727 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1044.45
2730 for (
int ip = 0; ip < ctl->
met_np; ip++)
2737 const double press[147] = {
2738 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
2739 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
2740 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
2741 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
2742 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2743 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
2744 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
2745 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
2746 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
2747 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
2748 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
2749 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
2750 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
2751 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
2752 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
2753 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
2754 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
2755 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
2756 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73, 1028.85,
2758 1035.09, 1038.21, 1041.33, 1044.45
2761 for (
int ip = 0; ip < ctl->
met_np; ip++)
2768 const double press[101] = {
2769 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
2770 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
2771 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
2772 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
2773 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
2775 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
2776 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
2777 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
2778 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
2779 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
2780 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
2781 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
2782 1007.4431, 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73,
2784 1035.09, 1038.21, 1041.33, 1044.45
2787 for (
int ip = 0; ip < ctl->
met_np; ip++)
2794 const double press[62] = {
2795 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
2796 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
2797 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
2798 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
2799 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
2800 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
2801 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
2802 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1034.86, 1039.65,
2806 for (
int ip = 0; ip < ctl->
met_np; ip++)
2813 const double press[137] = {
2814 0.01, 0.02, 0.031, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861,
2815 0.2499, 0.3299, 0.4288, 0.5496, 0.6952, 0.869, 1.0742,
2816 1.3143, 1.5928, 1.9134, 2.2797, 2.6954, 3.1642, 3.6898,
2817 4.2759, 4.9262, 5.6441, 6.4334, 7.2974, 8.2397, 9.2634,
2818 10.372, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945, 18.9752,
2819 20.761, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2820 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.199, 54.5299,
2821 57.9834, 61.5607, 65.2695, 69.1187, 73.1187, 77.281, 81.6182,
2822 86.145, 90.8774, 95.828, 101.005, 106.415, 112.068, 117.971,
2823 124.134, 130.564, 137.27, 144.262, 151.549, 159.14, 167.045,
2824 175.273, 183.834, 192.739, 201.997, 211.619, 221.615, 231.995,
2825 242.772, 253.955, 265.556, 277.585, 290.055, 302.976, 316.361,
2826 330.22, 344.566, 359.411, 374.767, 390.645, 407.058, 424.019,
2827 441.539, 459.632, 478.31, 497.584, 517.42, 537.72, 558.343,
2828 579.193, 600.167, 621.162, 642.076, 662.808, 683.262, 703.347,
2829 722.979, 742.086, 760.6, 778.466, 795.64, 812.085, 827.776,
2830 842.696, 856.838, 870.2, 882.791, 894.622, 905.712, 916.081,
2831 925.757, 934.767, 943.14, 950.908, 958.104, 965.299, 972.495,
2832 979.69, 986.886, 994.081, 1001.28, 1008.47, 1015.67, 1022.86,
2833 1030.06, 1037.25, 1044.45
2836 for (
int ip = 0; ip < ctl->
met_np; ip++)
2843 const double press[59] = {
2844 0.1, 0.2, 0.3843, 0.6365, 0.9564, 1.3448, 1.8058, 2.3478,
2845 2.985, 3.7397, 4.6462, 5.7565, 7.1322, 8.8366, 10.9483,
2846 13.5647, 16.8064, 20.8227, 25.7989, 31.9642, 39.6029, 49.0671,
2847 60.1802, 73.0663, 87.7274, 104.229, 122.614, 142.902, 165.089,
2848 189.147, 215.025, 242.652, 272.059, 303.217, 336.044, 370.407,
2849 406.133, 443.009, 480.791, 519.209, 557.973, 596.777, 635.306,
2850 673.24, 710.263, 746.063, 780.346, 812.83, 843.263, 871.42,
2851 897.112, 920.189, 940.551, 958.148, 975.744, 993.341, 1010.94,
2855 for (
int ip = 0; ip < ctl->
met_np; ip++)
2859 ERRMSG(
"Use 0 for l137, 1 for l91, 2 for l60 or values between 3 and 7.");
2863 ERRMSG(
"Recompile with larger EP to use this pressure level definition.");
2876 int i = (ihi + ilo) >> 1;
2878 if (xx[i] < xx[i + 1])
2879 while (ihi > ilo + 1) {
2880 i = (ihi + ilo) >> 1;
2886 while (ihi > ilo + 1) {
2887 i = (ihi + ilo) >> 1;
2907 int i = (ihi + ilo) >> 1;
2909 if ((xx[ig] <= x && x < xx[ig + 1]) || (xx[ig] >= x && x > xx[ig + 1]))
2912 if (xx[i] < xx[i + 1])
2913 while (ihi > ilo + 1) {
2914 i = (ihi + ilo) >> 1;
2920 while (ihi > ilo + 1) {
2921 i = (ihi + ilo) >> 1;
2939 const int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
2953 float profiles[
EX][
EY][
EP],
2955 const int lon_ap_ind,
2956 const int lat_ap_ind,
2957 const double height_ap,
2963 np, height_ap, ind[0]);
2965 np, height_ap, ind[1]);
2967 np, height_ap, ind[2]);
2986 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2990 double dts, u[4], um = 0, v[4], vm = 0, w[4], wm = 0,
2994 for (
int i = 0; i < ctl->
advect; i++) {
2999 x[0] = atm->
lon[ip];
3000 x[1] = atm->
lat[ip];
3003 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
3004 x[0] = atm->
lon[ip] +
DX2DEG(dts * u[i - 1] / 1000., atm->
lat[ip]);
3005 x[1] = atm->
lat[ip] +
DY2DEG(dts * v[i - 1] / 1000.);
3006 x[2] = atm->
p[ip] + dts * w[i - 1];
3008 const double tm = atm->
time[ip] + dts;
3013 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3015 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3017 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
3023 met1, met1->
pl, met1->
ul,
3024 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3026 met1, met1->
pl, met1->
vl,
3027 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3029 met1, met1->
pl, met1->
wl,
3030 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
3036 k = (i == 0 ? 0.0 : 1.0);
3037 else if (ctl->
advect == 4)
3038 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
3045 atm->
time[ip] += cache->
dt[ip];
3046 atm->
lon[ip] +=
DX2DEG(cache->
dt[ip] * um / 1000.,
3047 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
3048 atm->
lat[ip] +=
DY2DEG(cache->
dt[ip] * vm / 1000.);
3049 atm->
p[ip] += cache->
dt[ip] * wm;
3061 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3067 atm->
time[ip], atm->
p[ip],
3068 atm->
lon[ip], atm->
lat[ip],
3069 &atm->
q[qnt][ip], ci, cw, 1);
3072 double dts, u[4], um = 0, v[4], vm = 0, wdot[4],
3073 wdotm = 0, x[3] = { 0, 0, 0 };
3076 for (
int i = 0; i < ctl->
advect; i++) {
3081 x[0] = atm->
lon[ip];
3082 x[1] = atm->
lat[ip];
3083 x[2] = atm->
q[qnt][ip];
3085 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
3086 x[0] = atm->
lon[ip] +
DX2DEG(dts * u[i - 1] / 1000., atm->
lat[ip]);
3087 x[1] = atm->
lat[ip] +
DY2DEG(dts * v[i - 1] / 1000.);
3088 x[2] = atm->
q[qnt][ip] + dts * wdot[i - 1];
3091 const double tm = atm->
time[ip] + dts;
3096 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3099 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3102 tm, x[2], x[0], x[1], &wdot[i], ci, cw, 0);
3107 k = (i == 0 ? 0.0 : 1.0);
3108 else if (ctl->
advect == 4)
3109 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
3113 wdotm += k * wdot[i];
3117 atm->
time[ip] += cache->
dt[ip];
3118 atm->
lon[ip] +=
DX2DEG(cache->
dt[ip] * um / 1000.,
3119 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
3120 atm->
lat[ip] +=
DY2DEG(cache->
dt[ip] * vm / 1000.);
3121 atm->
q[qnt][ip] += cache->
dt[ip] * wdotm;
3127 atm->
q[qnt][ip], atm->
lon[ip], atm->
lat[ip],
3128 &atm->
p[ip], ci, cw, 1);
3147 SELECT_TIMER(
"MODULE_ADVECT_INIT",
"PHYSICS", NVTX_GPU);
3156 atm->
lon[ip], atm->
lat[ip], &atm->
p[ip], ci, cw, 1);
3171 SELECT_TIMER(
"MODULE_BOUND_COND",
"PHYSICS", NVTX_GPU);
3181 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3217 if (atm->
p[ip] < pbl)
3269 ERRMSG(
"Molar mass is not defined!");
3275 const int ensemble_mode = (ctl->
nens > 0);
3276 const int np = atm->
np;
3280 const int ngrid = nx * ny * nz;
3281 const int nens = ensemble_mode ? ctl->
nens : 1;
3283 double *restrict
const z = (
double *) malloc((
size_t) nz *
sizeof(double));
3284 double *restrict
const press =
3285 (
double *) malloc((
size_t) nz *
sizeof(double));
3286 double *restrict
const mass =
3287 (
double *) calloc((
size_t) ngrid * (size_t) nens,
sizeof(
double));
3288 double *restrict
const area =
3289 (
double *) malloc((
size_t) ny *
sizeof(double));
3290 double *restrict
const lon =
3291 (
double *) malloc((
size_t) nx *
sizeof(double));
3292 double *restrict
const lat =
3293 (
double *) malloc((
size_t) ny *
sizeof(double));
3295 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
3296 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
3297 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
3306#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])
3307#pragma acc data present(ctl,met0,met1,atm,ixs,iys,izs,z,press,mass,area,lon,lat)
3308#pragma acc parallel loop independent gang vector
3310#pragma omp parallel for default(shared)
3312 for (
int iz = 0; iz < nz; iz++) {
3314 press[iz] =
P(z[iz]);
3318 const double t0 = tt - 0.5 * ctl->
dt_mod;
3319 const double t1 = tt + 0.5 * ctl->
dt_mod;
3323#pragma acc parallel loop independent gang vector
3325#pragma omp parallel for default(shared)
3327 for (
int ip = 0; ip < np; ip++) {
3331 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
3332 || ixs[ip] < 0 || ixs[ip] >= nx
3333 || iys[ip] < 0 || iys[ip] >= ny || izs[ip] < 0 || izs[ip] >= nz)
3339#pragma acc parallel loop independent gang vector
3341#pragma omp parallel for default(shared)
3343 for (
int ix = 0; ix < nx; ix++)
3347#pragma acc parallel loop independent gang vector
3349#pragma omp parallel for default(shared)
3351 for (
int iy = 0; iy < ny; iy++) {
3353 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
3358#pragma acc parallel loop independent gang vector
3360 for (
int ip = 0; ip < np; ip++) {
3362 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
3363 if (ensemble_mode) {
3364 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
3365 mass_idx += ens * ngrid;
3368#pragma acc atomic update
3370 mass[mass_idx] += atm->
q[ctl->
qnt_m][ip];
3376#pragma acc parallel loop independent gang vector
3378#pragma omp parallel for default(shared)
3380 for (
int ip = 0; ip < np; ip++)
3388 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
3391 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
3392 if (ensemble_mode) {
3393 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
3394 mass_idx += ens * ngrid;
3398 const double m = mass[mass_idx];
3400 / (
RHO(press[izs[ip]], temp) * area[iys[ip]] * dz * 1e9);
3405#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
3433 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3450 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
3452 atm->
lat[ip], atm->
p[ip]));
3454 atm->
lat[ip], atm->
p[ip]));
3456 atm->
lat[ip], atm->
p[ip]));
3470 SELECT_TIMER(
"MODULE_CONVECTION",
"PHYSICS", NVTX_GPU);
3476 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3484 double pbot = ps, ptop = ps;
3501 double cape, cin, pel;
3507 if (isfinite(cape) && cape >= ctl->
conv_cape
3509 ptop = GSL_MIN(ptop, pel);
3513 if (ptop != pbot && atm->
p[ip] >= ptop) {
3518 pbot, atm->
lon[ip], atm->
lat[ip], &tbot, ci, cw, 1);
3520 atm->
lon[ip], atm->
lat[ip], &ttop, ci, cw, 1);
3521 const double rhobot = pbot / tbot;
3522 const double rhotop = ptop / ttop;
3525 const double rho = rhobot + (rhotop - rhobot) * cache->
rs[ip];
3528 atm->
p[ip] =
LIN(rhobot, pbot, rhotop, ptop, rho);
3552 dd_sort(ctl, *met, atm, dd, &nparticles, &dd->
rank);
3586 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3589 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,clim,atm)") {
3598 const double aux = exp(-cache->
dt[ip] / tdec);
3599 if (ctl->
qnt_m >= 0) {
3602 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
3603 atm->
q[ctl->
qnt_m][ip] *= aux;
3628 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3636 float umean = 0, usig = 0, vmean = 0, vsig = 0, wmean = 0, wsig = 0;
3637 for (
int i = 0; i < 2; i++)
3638 for (
int j = 0; j < 2; j++)
3639 for (
int k = 0; k < 2; k++) {
3640 umean += met0->
u[ix + i][iy + j][iz + k];
3641 usig +=
SQR(met0->
u[ix + i][iy + j][iz + k]);
3642 vmean += met0->
v[ix + i][iy + j][iz + k];
3643 vsig +=
SQR(met0->
v[ix + i][iy + j][iz + k]);
3644 wmean += met0->
w[ix + i][iy + j][iz + k];
3645 wsig +=
SQR(met0->
w[ix + i][iy + j][iz + k]);
3647 umean += met1->
u[ix + i][iy + j][iz + k];
3648 usig +=
SQR(met1->
u[ix + i][iy + j][iz + k]);
3649 vmean += met1->
v[ix + i][iy + j][iz + k];
3650 vsig +=
SQR(met1->
v[ix + i][iy + j][iz + k]);
3651 wmean += met1->
w[ix + i][iy + j][iz + k];
3652 wsig +=
SQR(met1->
w[ix + i][iy + j][iz + k]);
3654 usig = usig / 16.f -
SQR(umean / 16.f);
3655 usig = (usig > 0 ? sqrtf(usig) : 0);
3656 vsig = vsig / 16.f -
SQR(vmean / 16.f);
3657 vsig = (vsig > 0 ? sqrtf(vsig) : 0);
3658 wsig = wsig / 16.f -
SQR(wmean / 16.f);
3659 wsig = (wsig > 0 ? sqrtf(wsig) : 0);
3662 const double r = 1 - 2 * fabs(cache->
dt[ip]) / ctl->
dt_met;
3663 const double r2 = sqrt(1 - r * r);
3667 cache->
uvwp[ip][0] =
3668 (float) (r * cache->
uvwp[ip][0] +
3673 cache->
uvwp[ip][1] =
3674 (float) (r * cache->
uvwp[ip][1] +
3681 cache->
uvwp[ip][2] =
3682 (float) (r * cache->
uvwp[ip][2] +
3684 atm->
p[ip] += cache->
uvwp[ip][2] * cache->
dt[ip];
3705 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3707 double dsigw_dz = 0.0, sig_u = 0.25, sig_w = 0.1,
3708 tau_u = 300., tau_w = 100.;
3717 if (atm->
p[ip] >= pbl) {
3720 const double p =
MIN(atm->
p[ip], ps);
3721 const double zs =
Z(ps);
3722 const double z = 1e3 * (
Z(p) - zs);
3723 const double zi = 1e3 * (
Z(pbl) - zs);
3724 const double zratio = z / zi;
3727 double ess, nss, h2o, t;
3732 const double rho =
RHO(p,
TVIRT(t, h2o));
3733 const double tau = sqrt(
SQR(ess) +
SQR(nss));
3734 const double ustar = sqrt(tau / rho);
3744 sig_u = 1e-2 + 2.0 * ustar * (1.0 - zratio);
3745 sig_w = 1e-2 + 1.3 * ustar * (1.0 - zratio);
3748 dsigw_dz = -1.3 * ustar / zi;
3751 tau_u = 0.07 * zi / sig_u * sqrt(zratio);
3752 tau_w = 0.1 * zi / sig_w * pow(zratio, 0.8);
3759 const double wstar =
3760 pow(
G0 /
THETAVIRT(p, t, h2o) * shf / (rho *
CPD) * zi, 1. / 3.);
3764 + sqrt(0.4 *
SQR(wstar) + (5.0 - 4.0 * zratio) *
SQR(ustar));
3765 sig_w = 1e-2 + sqrt(1.2 *
SQR(wstar) * (1.0 - 0.9 * zratio)
3766 * pow(zratio, 2.0 / 3.0)
3767 + (1.8 - 1.4 * zratio) *
SQR(ustar));
3770 dsigw_dz = 0.5 / sig_w / zi * (-1.4 *
SQR(ustar) +
SQR(wstar)
3772 pow(
MAX(zratio, 1e-3), -1.0 / 3.0)
3773 - 1.8 * pow(zratio, 2.0 / 3.0)));
3776 const double C0 = 3.0;
3778 (1.5 - 1.2 * pow(zratio, 1.0 / 3.0)) *
SQR(wstar) * wstar / zi
3779 +
SQR(ustar) * ustar * (1.0 - 0.8 * zratio) / (
KARMAN * z);
3780 tau_u = 2 *
SQR(sig_u) / (C0 * eps);
3781 tau_w = 2 *
SQR(sig_w) / (C0 * eps);
3786 sig_u =
MAX(sig_u, 0.25);
3787 sig_w =
MAX(sig_w, 0.1);
3788 tau_u =
MAX(tau_u, 300.);
3789 tau_w =
MAX(tau_w, 100.);
3792 const double ru = exp(-fabs(cache->
dt[ip]) / tau_u);
3793 const double ru2 = sqrt(1.0 -
SQR(ru));
3795 = (float) (cache->
uvwp[ip][0] * ru + ru2 * cache->
rs[3 * ip]);
3797 = (float) (cache->
uvwp[ip][1] * ru + ru2 * cache->
rs[3 * ip + 1]);
3799 const double rw = exp(-fabs(cache->
dt[ip]) / tau_w);
3800 const double rw2 = sqrt(1.0 -
SQR(rw));
3802 = (float) (cache->
uvwp[ip][2] * rw + rw2 * cache->
rs[3 * ip + 2]
3803 + sig_w * dsigw_dz * cache->
dt[ip]);
3810 DZ2DP(cache->
uvwp[ip][2] * cache->
dt[ip] / 1000., atm->
p[ip]);
3832 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3841 const double wpbl =
pbl_weight(ctl, atm, ip, pbl, ps);
3842 const double wtrop =
tropo_weight(clim, atm, ip) * (1.0 - wpbl);
3843 const double wstrat = 1.0 - wpbl - wtrop;
3853 const double sigma = sqrt(2.0 * dx * fabs(cache->
dt[ip])) / 1000.;
3855 atm->
lat[ip] +=
DY2DEG(cache->
rs[3 * ip + 1] * sigma);
3860 const double sigma = sqrt(2.0 * dz * fabs(cache->
dt[ip])) / 1000.;
3861 atm->
p[ip] +=
DZ2DP(cache->
rs[3 * ip + 2] * sigma, atm->
p[ip]);
3880 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3883 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3895 const double dz = 1000. * (
Z(ps - ctl->
dry_depo_dp) -
Z(ps));
3915 const double aux = exp(-cache->
dt[ip] * v_dep / dz);
3916 if (ctl->
qnt_m >= 0) {
3919 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
3920 atm->
q[ctl->
qnt_m][ip] *= aux;
3944 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3947 const double a = 3.12541941e-06;
3948 const double b = -5.72532259e-01;
3949 const double low = pow(1. / a, 1. / b);
3952 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3959 if (!(lwc > 0 || rwc > 0))
3970 const double k = 9.1e7 * exp(-29700. /
RI * (1. / t - 1. / 298.15));
3973 const double H_SO2 =
3974 1.3e-2 * exp(2900. * (1. / t - 1. / 298.15)) *
RI * t;
3975 const double K_1S = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
3978 const double H_h2o2 =
3979 8.3e2 * exp(7600. * (1. / t - 1. / 298.15)) *
RI * t;
3985 cor = atm->
q[ctl->
qnt_Cx][ip] >
3986 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
3988 const double h2o2 = H_h2o2
3990 * M * cor * 1000. /
AVO;
3993 const double rho_air = atm->
p[ip] / (
RI * t) *
MA / 10.;
3994 const double CWC = (lwc + rwc) * rho_air / 1e3;
3997 const double rate_coef = k * K_1S * h2o2 * H_SO2 * CWC;
3998 const double aux = exp(-cache->
dt[ip] * rate_coef);
3999 if (ctl->
qnt_m >= 0) {
4002 atm->
q[ctl->
qnt_m][ip] *= aux;
4023 SELECT_TIMER(
"MODULE_ISOSURF_INIT",
"PHYSICS", NVTX_GPU);
4034 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
4037 cache->
iso_var[ip] = atm->
p[ip] / t;
4043 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
4054 LOG(1,
"Read balloon pressure data: %s", ctl->
balloon);
4058 if (!(in = fopen(ctl->
balloon,
"r")))
4059 ERRMSG(
"Cannot open file!");
4063 while (fgets(line,
LEN, in))
4064 if (sscanf(line,
"%lg %lg", &(cache->
iso_ts[cache->
iso_n]),
4067 ERRMSG(
"Too many data points!");
4070 if (cache->
iso_n < 1)
4071 ERRMSG(
"Could not read any data!");
4094 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,met1,atm)") {
4107 atm->
p[ip] = cache->
iso_var[ip] * t;
4113 atm->
p[ip] = 1000. * pow(cache->
iso_var[ip] / t, -1. / 0.286);
4119 atm->
p[ip] = cache->
iso_ps[0];
4147 const int nvar = NVAR, nfix = NFIX, nreact = NREACT;
4148 double rtol[1] = { 1.0e-3 };
4149 double atol[1] = { 1.0 };
4153#pragma acc data copy(rtol,atol,nvar,nfix,nreact)
4156 "acc data present(ctl,cache,clim,met0,met1,atm) ") {
4159 double var[nvar], fix[nfix], rconst[nreact];
4160 for (
int i = 0; i < nvar; i++)
4162 for (
int i = 0; i < nfix; i++)
4164 for (
int i = 0; i < nreact; i++)
4166 kpp_chem_initialize(ctl, clim, met0, met1, atm, var, fix, rconst, ip);
4171 for (
int i = 0; i < 20; i++) {
4178 Rosenbrock(var, fix, rconst, 0, ctl->
dt_kpp,
4179 atol, rtol, &FunTemplate, &JacTemplate, rpar, ipar);
4182 kpp_chem_output2atm(atm, ctl, met0, met1, var, ip);
4203 ERRMSG(
"Need T_ice and T_NAT to calculate T_STS!");
4207 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4209 double ps, ts, zs, us, vs, ess, nss, shf, lsm, sst, pbl, pt, pct, pcb,
4210 cl, plcl, plfc, pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot,
4211 o3, lwc, rwc, iwc, swc, cc, z, zt;
4259 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
4261 atm->
lat[ip], atm->
p[ip]));
4263 atm->
lat[ip], atm->
p[ip]));
4265 atm->
lat[ip], atm->
p[ip]));
4266 SET_ATM(qnt_vh, sqrt(u * u + v * v));
4288 atm->
lat[ip], atm->
p[ip])));
4306 const int np = atm->
np;
4307 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
4308 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
4309 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
4317 const double t0 = t - 0.5 * ctl->
dt_mod;
4318 const double t1 = t + 0.5 * ctl->
dt_mod;
4322#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
4323#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
4324#pragma acc parallel loop independent gang vector
4326#pragma omp parallel for default(shared)
4328 for (
int ip = 0; ip < np; ip++) {
4331 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
mixing_z0) / dz);
4332 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
4333 || ixs[ip] < 0 || ixs[ip] >= ctl->
mixing_nx
4334 || iys[ip] < 0 || iys[ip] >= ctl->
mixing_ny
4335 || izs[ip] < 0 || izs[ip] >= ctl->
mixing_nz)
4340 const int use_ensemble = (ctl->
nens > 0);
4342 const int quantities[] = {
4349 const int n_qnt =
sizeof(quantities) /
sizeof(quantities[0]);
4351 for (
int i = 0; i < n_qnt; i++)
4352 if (quantities[i] >= 0)
4358#pragma acc exit data delete(ixs,iys,izs)
4375 const int use_ensemble) {
4377 const int np = atm->
np;
4379 const int nens = use_ensemble ? ctl->
nens : 1;
4380 const int total_grid = ngrid * nens;
4382 double *restrict
const cmean =
4383 (
double *) malloc((
size_t) total_grid *
sizeof(double));
4384 int *restrict
const count =
4385 (
int *) malloc((
size_t) total_grid *
sizeof(int));
4389#pragma acc enter data create(cmean[0:total_grid],count[0:total_grid])
4390#pragma acc data present(ctl,clim,atm,ixs,iys,izs,cmean,count)
4391#pragma acc parallel loop independent gang vector
4396#pragma omp parallel for
4398 for (
int i = 0; i < total_grid; i++) {
4405#pragma acc parallel loop independent gang vector
4407 for (
int ip = 0; ip < np; ip++)
4409 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
4414#pragma acc atomic update
4416 cmean[idx] += atm->
q[qnt_idx][ip];
4418#pragma acc atomic update
4425#pragma acc parallel loop independent gang vector
4430#pragma omp parallel for
4432 for (
int i = 0; i < total_grid; i++)
4434 cmean[i] /= count[i];
4438#pragma acc parallel loop independent gang vector
4440#pragma omp parallel for
4442 for (
int ip = 0; ip < np; ip++) {
4444 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
4446 double mixparam = 1.0;
4455 atm->
q[qnt_idx][ip] += (cmean[idx] - atm->
q[qnt_idx][ip]) * mixparam;
4461#pragma acc exit data delete(cmean,count)
4482 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4485 const double a = 4.71572206e-08;
4486 const double b = -8.28782867e-01;
4487 const double low = pow(1. / a, 1. / b);
4491 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4517 0 ? pow(298. / t, ctl->
oh_chem[1]) : 1.);
4520 0 ? pow(298. / t, ctl->
oh_chem[3]) : 1.);
4521 const double c = log10(k0 * M / ki);
4522 k = k0 * M / (1. + k0 * M / ki) * pow(0.6, 1. / (1. + c * c));
4531 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
4534 const double rate_coef =
4536 atm->
lat[ip], atm->
p[ip]) * M * cor;
4537 const double aux = exp(-cache->
dt[ip] * rate_coef);
4538 if (ctl->
qnt_m >= 0) {
4541 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
4542 atm->
q[ctl->
qnt_m][ip] *= aux;
4563 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(cache,met0,met1,atm)") {
4574 while (atm->
lat[ip] < -90 || atm->
lat[ip] > 90) {
4575 if (atm->
lat[ip] > 90) {
4576 atm->
lat[ip] = 180 - atm->
lat[ip];
4577 atm->
lon[ip] += 180;
4579 if (atm->
lat[ip] < -90) {
4580 atm->
lat[ip] = -180 - atm->
lat[ip];
4581 atm->
lon[ip] += 180;
4586 while (atm->
lon[ip] < -180)
4587 atm->
lon[ip] += 360;
4588 while (atm->
lon[ip] >= 180)
4589 atm->
lon[ip] -= 360;
4592 if (atm->
p[ip] < met0->
p[met0->
np - 1]) {
4593 atm->
p[ip] = met0->
p[met0->
np - 1];
4594 }
else if (atm->
p[ip] > 300.) {
4596 if (atm->
p[ip] > ps)
4608 gsl_rng_env_setup();
4609 if (omp_get_max_threads() >
NTHREADS)
4610 ERRMSG(
"Too many threads!");
4611 for (
int i = 0; i <
NTHREADS; i++) {
4612 rng[i] = gsl_rng_alloc(gsl_rng_default);
4613 gsl_rng_set(rng[i], gsl_rng_default_seed
4614 + (
long unsigned) (ntask *
NTHREADS + i));
4619 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
4620 CURAND_STATUS_SUCCESS)
4621 ERRMSG(
"Cannot create random number generator!");
4622 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
4623 CURAND_STATUS_SUCCESS)
4624 ERRMSG(
"Cannot set seed for random number generator!");
4627 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
4628 CURAND_STATUS_SUCCESS)
4629 ERRMSG(
"Cannot set stream for random number generator!");
4646#pragma omp parallel for default(shared)
4647 for (
size_t i = 0; i < n; ++i)
4648 rs[i] = gsl_rng_uniform(rng[omp_get_thread_num()]);
4652 else if (method == 1) {
4653#pragma omp parallel for default(shared)
4654 for (
size_t i = 0; i < n; ++i)
4655 rs[i] = gsl_ran_gaussian_ziggurat(rng[omp_get_thread_num()], 1.0);
4661#pragma acc update device(rs[:n])
4669 const uint64_t key = 0xc8e4fd154ce32f6d;
4673#pragma acc data present(rs)
4674#pragma acc parallel loop independent gang vector
4676#pragma omp parallel for default(shared)
4678 for (
size_t i = 0; i < n + 1; ++i) {
4679 uint64_t r, t, x, y, z;
4680 y = x = (rng_ctr + i) * key;
4683 x = (x >> 32) | (x << 32);
4685 x = (x >> 32) | (x << 32);
4687 x = (x >> 32) | (x << 32);
4689 x = (x >> 32) | (x << 32);
4690 r = t ^ ((x * x + y) >> 32);
4691 rs[i] = (double) r / (
double) UINT64_MAX;
4698#pragma acc parallel loop independent gang vector
4700#pragma omp parallel for default(shared)
4702 for (
size_t i = 0; i < n; i += 2) {
4703 const double r = sqrt(-2.0 * log(rs[i]));
4704 const double phi = 2.0 * M_PI * rs[i + 1];
4705 rs[i] = r * cosf((
float) phi);
4706 rs[i + 1] = r * sinf((
float) phi);
4714#pragma acc host_data use_device(rs)
4719 if (curandGenerateUniformDouble(rng_curand, rs, (n < 4 ? 4 : n)) !=
4720 CURAND_STATUS_SUCCESS)
4721 ERRMSG(
"Cannot create random numbers!");
4725 else if (method == 1) {
4726 if (curandGenerateNormalDouble
4727 (rng_curand, rs, (n < 4 ? 4 : n), 0.0,
4728 1.0) != CURAND_STATUS_SUCCESS)
4729 ERRMSG(
"Cannot create random numbers!");
4733 ERRMSG(
"MPTRAC was compiled without cuRAND!");
4751 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4759 const double v_s =
sedi(atm->
p[ip], t, atm->
q[ctl->
qnt_rp][ip],
4763 atm->
p[ip] +=
DZ2DP(v_s * cache->
dt[ip] / 1000., atm->
p[ip]);
4778 const int np = atm->
np;
4779 double *restrict
const a = (
double *) malloc((
size_t) np *
sizeof(double));
4780 int *restrict
const p = (
int *) malloc((
size_t) np *
sizeof(int));
4781 if (a == NULL || p == NULL)
4782 ERRMSG(
"Out of memory!");
4785#pragma acc enter data create(a[0:np],p[0:np])
4786#pragma acc data present(ctl,met0,atm,a,p)
4791#pragma acc parallel loop independent gang vector
4793#pragma omp parallel for default(shared)
4795 for (
int ip = 0; ip < np; ip++) {
4806#pragma acc host_data use_device(a,p)
4808 thrustSortWrapper(a, np, p);
4811 ERRMSG(
"GSL sort fallback not available on GPU, use THRUST!");
4813 gsl_sort_index((
size_t *) p, a, 1, (
size_t) np);
4821 for (
int iq = 0; iq < ctl->
nq; iq++)
4826#pragma acc exit data delete(a,p)
4840 double *restrict
const help =
4841 (
double *) malloc((
size_t) np *
sizeof(double));
4843 ERRMSG(
"Out of memory!");
4847#pragma acc enter data create(help[0:np])
4848#pragma acc data present(a,p,help)
4849#pragma acc parallel loop independent gang vector
4851#pragma omp parallel for default(shared)
4853 for (
int ip = 0; ip < np; ip++)
4854 help[ip] = a[p[ip]];
4856#pragma acc parallel loop independent gang vector
4858#pragma omp parallel for default(shared)
4860 for (
int ip = 0; ip < np; ip++)
4865#pragma acc exit data delete(help)
4882 const double latmin = gsl_stats_min(met0->
lat, 1, (
size_t) met0->
ny),
4883 latmax = gsl_stats_max(met0->
lat, 1, (
size_t) met0->
ny);
4886 (fabs(met0->
lon[met0->
nx - 1] - met0->
lon[0] - 360.0) >= 0.01);
4889 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,atm)") {
4895 cache->
dt[ip] = t - atm->
time[ip];
4897 cache->
dt[ip] = 0.0;
4906 if (local && (atm->
lon[ip] <= met0->
lon[0]
4907 || atm->
lon[ip] >= met0->
lon[met0->
nx - 1]
4908 || atm->
lat[ip] <= latmin || atm->
lat[ip] >= latmax))
4909 cache->
dt[ip] = 0.0;
4924 SELECT_TIMER(
"MODULE_TIMESTEPS_INIT",
"PHYSICS", NVTX_GPU);
4928 ctl->
t_start = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
4930 ctl->
t_stop = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
4932 ctl->
t_start = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
4934 ctl->
t_stop = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
4939 ERRMSG(
"Nothing to do! Check T_STOP and DIRECTION!");
4959 SELECT_TIMER(
"MODULE_TRACER_CHEM",
"PHYSICS", NVTX_GPU);
4963 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4987 const double K_o1d =
ARRHENIUS(3.30e-10, 0, t) * o1d * M;
4989 atm->
p[ip], sza, o3c);
4990 atm->
q[ctl->
qnt_Cccl4][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4995 const double K_o1d =
ARRHENIUS(2.30e-10, 0, t) * o1d * M;
4997 atm->
p[ip], sza, o3c);
4998 atm->
q[ctl->
qnt_Cccl3f][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5003 const double K_o1d =
ARRHENIUS(1.40e-10, -25, t) * o1d * M;
5005 atm->
p[ip], sza, o3c);
5006 atm->
q[ctl->
qnt_Cccl2f2][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5011 const double K_o1d =
ARRHENIUS(1.19e-10, -20, t) * o1d * M;
5013 atm->
p[ip], sza, o3c);
5014 atm->
q[ctl->
qnt_Cn2o][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5033 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
5036 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
5042 if (!isfinite(pct) || atm->
p[ip] <= pct)
5058 double lwc, rwc, iwc, swc;
5063 const int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
5077 else if (t <= 238.15)
5097 const double K_1 = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
5098 const double K_2 = 6e-8 * exp(1.12e3 * (1. / t - 1. / 298.15));
5099 h *= (1. + K_1 / H_ion + K_1 * K_2 /
SQR(H_ion));
5103 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
5106 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
5132 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
5135 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
5140 const double aux = exp(-cache->
dt[ip] * lambda);
5141 if (ctl->
qnt_m >= 0) {
5144 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
5145 atm->
q[ctl->
qnt_m][ip] *= aux;
5170 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
5172 if (acc_get_num_devices(acc_device_nvidia) <= 0)
5173 ERRMSG(
"Not running on a GPU device!");
5174 acc_set_device_num(rank % acc_get_num_devices(acc_device_nvidia),
5176 acc_device_t device_type = acc_get_device_type();
5177 acc_init(device_type);
5192 SELECT_TIMER(
"CREATE_DATA_REGION",
"MEMORY", NVTX_GPU);
5193 ctl_t *ctlup = *ctl;
5196 met_t *met0up = *met0;
5197 met_t *met1up = *met1;
5198 atm_t *atmup = *atm;
5199#pragma acc enter data create(ctlup[:1],cacheup[:1],climup[:1],met0up[:1],met1up[:1],atmup[:1])
5202#pragma acc enter data create(ddup[:1])
5220 SELECT_TIMER(
"DELETE_DATA_REGION",
"MEMORY", NVTX_GPU);
5221#pragma acc exit data delete (ctl,cache,clim,met0,met1,atm)
5235 MPI_Type_free(&dd->MPI_Particle);
5254 char cachefile[
LEN], cmd[2 *
LEN], filename[
LEN];
5260 if (t == ctl->
t_start || !init) {
5267 ERRMSG(
"Cannot open file!");
5272 ERRMSG(
"Cannot open file!");
5282 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5283 LOG(1,
"Caching: %s", cachefile);
5284 if (system(cmd) != 0)
5285 WARN(
"Caching command failed!");
5290 if (t > (*met1)->time) {
5300 ERRMSG(
"Cannot open file!");
5310 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5311 LOG(1,
"Caching: %s", cachefile);
5312 if (system(cmd) != 0)
5313 WARN(
"Caching command failed!");
5318 if (t < (*met0)->time) {
5328 ERRMSG(
"Cannot open file!");
5338 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5339 LOG(1,
"Caching: %s", cachefile);
5340 if (system(cmd) != 0)
5341 WARN(
"Caching command failed!");
5346 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
5347 if ((*met0)->nx != (*met1)->nx
5348 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
5349 ERRMSG(
"Meteo grid dimensions do not match!");
5350 for (
int ix = 0; ix < (*met0)->nx; ix++)
5351 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
5352 ERRMSG(
"Meteo grid longitudes do not match!");
5353 for (
int iy = 0; iy < (*met0)->ny; iy++)
5354 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
5355 ERRMSG(
"Meteo grid latitudes do not match!");
5356 for (
int ip = 0; ip < (*met0)->np; ip++)
5357 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
5358 ERRMSG(
"Meteo grid pressure levels do not match!");
5384 const char *filename,
5397 LOG(1,
"Read atmospheric data: %s", filename);
5417 ERRMSG(
"Atmospheric data type not supported!");
5425 ERRMSG(
"Can not read any data!");
5429 LOG(2,
"Number of particles: %d", atm->
np);
5430 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
5431 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
5432 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
5433 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
5434 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
5435 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
5436 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
5437 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
5438 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
5439 for (
int iq = 0; iq < ctl->
nq; iq++) {
5441 sprintf(msg,
"Quantity %s range: %s ... %s %s",
5444 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
5445 LOG(2, msg, mini, maxi);
5515 const char *filename,
5524 LOG(1,
"\nMassive-Parallel Trajectory Calculations (MPTRAC)\n"
5525 "(executable: %s | version: %s | compiled: %s, %s)\n",
5526 argv[0], VERSION, __DATE__, __TIME__);
5630 ctl->
nq = (int)
scan_ctl(filename, argc, argv,
"NQ", -1,
"0", NULL);
5632 ERRMSG(
"Too many quantities!");
5633 for (
int iq = 0; iq < ctl->
nq; iq++) {
5639 scan_ctl(filename, argc, argv,
"QNT_FORMAT", iq,
"%g",
5641 if (strcasecmp(ctl->
qnt_name[iq],
"aoa") == 0)
5645 SET_QNT(qnt_idx,
"idx",
"particle index",
"-")
5646 SET_QNT(qnt_ens,
"ens",
"ensemble index",
"-")
5647 SET_QNT(qnt_stat,
"stat",
"station flag",
"-")
5648 SET_QNT(qnt_m,
"m",
"mass",
"kg")
5649 SET_QNT(qnt_vmr,
"vmr",
"volume mixing ratio",
"ppv")
5650 SET_QNT(qnt_rp,
"rp",
"particle radius",
"microns")
5651 SET_QNT(qnt_rhop,
"rhop",
"particle density",
"kg/m^3")
5652 SET_QNT(qnt_ps,
"ps",
"surface pressure",
"hPa")
5653 SET_QNT(qnt_ts,
"ts",
"surface temperature",
"K")
5654 SET_QNT(qnt_zs,
"zs",
"surface height",
"km")
5655 SET_QNT(qnt_us,
"us",
"surface zonal wind",
"m/s")
5656 SET_QNT(qnt_vs,
"vs",
"surface meridional wind",
"m/s")
5657 SET_QNT(qnt_ess,
"ess",
"eastward turbulent surface stress",
"N/m^2")
5658 SET_QNT(qnt_nss,
"nss",
"northward turbulent surface stress",
"N/m^2")
5659 SET_QNT(qnt_shf,
"shf",
"surface sensible heat flux",
"W/m^2")
5660 SET_QNT(qnt_lsm,
"lsm",
"land-sea mask",
"1")
5661 SET_QNT(qnt_sst,
"sst",
"sea surface temperature",
"K")
5662 SET_QNT(qnt_pbl,
"pbl",
"planetary boundary layer",
"hPa")
5663 SET_QNT(qnt_pt,
"pt",
"tropopause pressure",
"hPa")
5664 SET_QNT(qnt_tt,
"tt",
"tropopause temperature",
"K")
5665 SET_QNT(qnt_zt,
"zt",
"tropopause geopotential height",
"km")
5666 SET_QNT(qnt_h2ot,
"h2ot",
"tropopause water vapor",
"ppv")
5667 SET_QNT(qnt_zg,
"zg",
"geopotential height",
"km")
5668 SET_QNT(qnt_p,
"p",
"pressure",
"hPa")
5669 SET_QNT(qnt_t,
"t",
"temperature",
"K")
5670 SET_QNT(qnt_rho,
"rho",
"air density",
"kg/m^3")
5671 SET_QNT(qnt_u,
"u",
"zonal wind",
"m/s")
5672 SET_QNT(qnt_v,
"v",
"meridional wind",
"m/s")
5673 SET_QNT(qnt_w,
"w",
"vertical velocity",
"hPa/s")
5674 SET_QNT(qnt_h2o,
"h2o",
"water vapor",
"ppv")
5675 SET_QNT(qnt_o3,
"o3",
"ozone",
"ppv")
5676 SET_QNT(qnt_lwc,
"lwc",
"cloud liquid water content",
"kg/kg")
5677 SET_QNT(qnt_rwc,
"rwc",
"cloud rain water content",
"kg/kg")
5678 SET_QNT(qnt_iwc,
"iwc",
"cloud ice water content",
"kg/kg")
5679 SET_QNT(qnt_swc,
"swc",
"cloud snow water content",
"kg/kg")
5680 SET_QNT(qnt_cc,
"cc",
"cloud cover",
"1")
5681 SET_QNT(qnt_pct,
"pct",
"cloud top pressure",
"hPa")
5682 SET_QNT(qnt_pcb,
"pcb",
"cloud bottom pressure",
"hPa")
5683 SET_QNT(qnt_cl,
"cl",
"total column cloud water",
"kg/m^2")
5684 SET_QNT(qnt_plcl,
"plcl",
"lifted condensation level",
"hPa")
5685 SET_QNT(qnt_plfc,
"plfc",
"level of free convection",
"hPa")
5686 SET_QNT(qnt_pel,
"pel",
"equilibrium level",
"hPa")
5687 SET_QNT(qnt_cape,
"cape",
"convective available potential energy",
5689 SET_QNT(qnt_cin,
"cin",
"convective inhibition",
"J/kg")
5690 SET_QNT(qnt_o3c,
"o3c",
"total column ozone",
"DU")
5691 SET_QNT(qnt_hno3,
"hno3",
"nitric acid",
"ppv")
5692 SET_QNT(qnt_oh,
"oh",
"hydroxyl radical",
"ppv")
5693 SET_QNT(qnt_h2o2,
"h2o2",
"hydrogen peroxide",
"ppv")
5694 SET_QNT(qnt_ho2,
"ho2",
"hydroperoxyl radical",
"ppv")
5695 SET_QNT(qnt_o1d,
"o1d",
"atomic oxygen",
"ppv")
5696 SET_QNT(qnt_mloss_oh,
"mloss_oh",
"mass loss due to OH chemistry",
"kg")
5697 SET_QNT(qnt_mloss_h2o2,
"mloss_h2o2",
5698 "mass loss due to H2O2 chemistry",
"kg")
5699 SET_QNT(qnt_mloss_kpp,
"mloss_kpp",
"mass loss due to kpp chemistry",
5701 SET_QNT(qnt_mloss_wet,
"mloss_wet",
"mass loss due to wet deposition",
5703 SET_QNT(qnt_mloss_dry,
"mloss_dry",
"mass loss due to dry deposition",
5705 SET_QNT(qnt_mloss_decay,
"mloss_decay",
5706 "mass loss due to exponential decay",
"kg")
5707 SET_QNT(qnt_loss_rate,
"loss_rate",
"total loss rate",
"s^-1")
5708 SET_QNT(qnt_psat,
"psat",
"saturation pressure over water",
"hPa")
5709 SET_QNT(qnt_psice,
"psice",
"saturation pressure over ice",
"hPa")
5710 SET_QNT(qnt_pw,
"pw",
"partial water vapor pressure",
"hPa")
5711 SET_QNT(qnt_sh,
"sh",
"specific humidity",
"kg/kg")
5712 SET_QNT(qnt_rh,
"rh",
"relative humidity",
"%%")
5713 SET_QNT(qnt_rhice,
"rhice",
"relative humidity over ice",
"%%")
5714 SET_QNT(qnt_theta,
"theta",
"potential temperature",
"K")
5715 SET_QNT(qnt_zeta,
"zeta",
"zeta coordinate",
"K")
5716 SET_QNT(qnt_zeta_d,
"zeta_d",
"diagnosed zeta coordinate",
"K")
5717 SET_QNT(qnt_zeta_dot,
"zeta_dot",
"velocity of zeta coordinate",
5719 SET_QNT(qnt_eta,
"eta",
"eta coordinate",
"1")
5720 SET_QNT(qnt_eta_dot,
"eta_dot",
"velocity of eta coordinate",
"1/s")
5721 SET_QNT(qnt_tvirt,
"tvirt",
"virtual temperature",
"K")
5722 SET_QNT(qnt_lapse,
"lapse",
"temperature lapse rate",
"K/km")
5723 SET_QNT(qnt_vh,
"vh",
"horizontal velocity",
"m/s")
5724 SET_QNT(qnt_vz,
"vz",
"vertical velocity",
"m/s")
5725 SET_QNT(qnt_pv,
"pv",
"potential vorticity",
"PVU")
5726 SET_QNT(qnt_tdew,
"tdew",
"dew point temperature",
"K")
5727 SET_QNT(qnt_tice,
"tice",
"frost point temperature",
"K")
5728 SET_QNT(qnt_tsts,
"tsts",
"STS existence temperature",
"K")
5729 SET_QNT(qnt_tnat,
"tnat",
"NAT existence temperature",
"K")
5730 SET_QNT(qnt_Cx,
"Cx",
"Trace species x volume mixing ratio",
"ppv")
5731 SET_QNT(qnt_Ch2o,
"Ch2o",
"H2O volume mixing ratio",
"ppv")
5732 SET_QNT(qnt_Co3,
"Co3",
"O3 volume mixing ratio",
"ppv")
5733 SET_QNT(qnt_Cco,
"Cco",
"CO volume mixing ratio",
"ppv")
5734 SET_QNT(qnt_Coh,
"Coh",
"HO volume mixing ratio",
"ppv")
5735 SET_QNT(qnt_Ch,
"Ch",
"H radical volume mixing ratio",
"ppv")
5736 SET_QNT(qnt_Cho2,
"Cho2",
"HO2 volume mixing ratio",
"ppv")
5737 SET_QNT(qnt_Ch2o2,
"Ch2o2",
"H2O2 volume mixing ratio",
"ppv")
5738 SET_QNT(qnt_Co1d,
"Co1d",
"O(1D) volume mixing ratio",
"ppv")
5739 SET_QNT(qnt_Co3p,
"Co3p",
"O(3P) radical volume mixing ratio",
"ppv")
5740 SET_QNT(qnt_Cccl4,
"Cccl4",
"CCl4 (CFC-10) volume mixing ratio",
"ppv")
5741 SET_QNT(qnt_Cccl3f,
"Cccl3f",
"CCl3F (CFC-11) volume mixing ratio",
5743 SET_QNT(qnt_Cccl2f2,
"Cccl2f2",
"CCl2F2 (CFC-12) volume mixing ratio",
5745 SET_QNT(qnt_Cn2o,
"Cn2o",
"N2O volume mixing ratio",
"ppv")
5746 SET_QNT(qnt_Csf6,
"Csf6",
"SF6 volume mixing ratio",
"ppv")
5747 SET_QNT(qnt_aoa,
"aoa",
"age of air",
"s")
5749 SET_QNT(qnt_destination,
"destination",
5750 "subdomain index of destination",
"-")
5751 SET_QNT(qnt_subdomain,
"subdomain",
"current subdomain index",
"-")
5758 (int)
scan_ctl(filename, argc, argv,
"ADVECT_VERT_COORD", -1,
"0", NULL);
5760 ERRMSG(
"ADVECT_VERT_COORD must be 0, 1, 2, or 3!");
5763 ERRMSG(
"Add quantity zeta for diabatic advection!");
5765 ERRMSG(
"Add quantity eta for etadot avection!");
5768 (int)
scan_ctl(filename, argc, argv,
"MET_VERT_COORD", -1,
"0", NULL);
5770 ERRMSG(
"MET_VERT_COORD must be 0, 1, 2, 3, or 4!");
5774 (
"Using ADVECT_VERT_COORD = 2 requires meteo data on model levels!");
5777 (
"Using ADVECT_VERT_COORD = 3 requires A and B model level coefficients!");
5781 (int)
scan_ctl(filename, argc, argv,
"DIRECTION", -1,
"1", NULL);
5783 ERRMSG(
"Set DIRECTION to -1 or 1!");
5784 ctl->
t_stop =
scan_ctl(filename, argc, argv,
"T_STOP", -1,
"1e100", NULL);
5785 ctl->
dt_mod =
scan_ctl(filename, argc, argv,
"DT_MOD", -1,
"180", NULL);
5789 ctl->
dt_met =
scan_ctl(filename, argc, argv,
"DT_MET", -1,
"3600", NULL);
5791 (int)
scan_ctl(filename, argc, argv,
"MET_CONVENTION", -1,
"0", NULL);
5793 (int)
scan_ctl(filename, argc, argv,
"MET_TYPE", -1,
"0", NULL);
5796 (
"Please use meteo files in netcdf format for diabatic calculations.");
5799 (
"Please use meteo files in netcdf format for etadot calculations.");
5801 (int)
scan_ctl(filename, argc, argv,
"MET_CLAMS", -1,
"0", NULL);
5803 (int)
scan_ctl(filename, argc, argv,
"MET_NC_SCALE", -1,
"1", NULL);
5805 (int)
scan_ctl(filename, argc, argv,
"MET_NC_LEVEL", -1,
"0", NULL);
5807 (int)
scan_ctl(filename, argc, argv,
"MET_NC_QUANT", -1,
"0", NULL);
5809 (int)
scan_ctl(filename, argc, argv,
"MET_ZSTD_LEVEL", -1,
"0", NULL);
5810 for (
int i = 0; i <
METVAR; i++) {
5811 char defprec[
LEN] =
"0", deftol[
LEN] =
"0.0";
5813 sprintf(deftol,
"0.5");
5815 sprintf(deftol,
"5.0");
5817 sprintf(defprec,
"8");
5819 (int)
scan_ctl(filename, argc, argv,
"MET_COMP_PREC", i, defprec, NULL);
5821 scan_ctl(filename, argc, argv,
"MET_COMP_TOL", i, deftol, NULL);
5824 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_BATCH", -1,
"-1", NULL);
5826 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ZSTD", -1,
"1", NULL);
5828 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ND0X", -1,
"48", NULL);
5830 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ND0Y", -1,
"24", NULL);
5832 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_MAXLEV", -1,
"6", NULL);
5834 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_Z", -1,
"1.0", NULL);
5836 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_T", -1,
"0.05", NULL);
5838 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_U", -1,
"0.05", NULL);
5840 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_V", -1,
"0.05", NULL);
5842 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_W", -1,
"1.0", NULL);
5844 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_PV", -1,
"1.0", NULL);
5846 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_H2O", -1,
"1.0", NULL);
5848 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_O3", -1,
"1.0", NULL);
5850 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_LWC", -1,
"1.0", NULL);
5852 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_RWC", -1,
"1.0", NULL);
5854 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_IWC", -1,
"1.0", NULL);
5856 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_SWC", -1,
"1.0", NULL);
5858 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_CC", -1,
"1.0", NULL);
5859 ctl->
met_dx = (int)
scan_ctl(filename, argc, argv,
"MET_DX", -1,
"1", NULL);
5860 ctl->
met_dy = (int)
scan_ctl(filename, argc, argv,
"MET_DY", -1,
"1", NULL);
5861 ctl->
met_dp = (int)
scan_ctl(filename, argc, argv,
"MET_DP", -1,
"1", NULL);
5863 ERRMSG(
"MET_DX, MET_DY, and MET_DP need to be greater than zero!");
5864 ctl->
met_sx = (int)
scan_ctl(filename, argc, argv,
"MET_SX", -1,
"1", NULL);
5865 ctl->
met_sy = (int)
scan_ctl(filename, argc, argv,
"MET_SY", -1,
"1", NULL);
5866 ctl->
met_sp = (int)
scan_ctl(filename, argc, argv,
"MET_SP", -1,
"1", NULL);
5868 ERRMSG(
"MET_SX, MET_SY, and MET_SP need to be greater than zero!");
5870 scan_ctl(filename, argc, argv,
"MET_DETREND", -1,
"-999", NULL);
5871 ctl->
met_np = (int)
scan_ctl(filename, argc, argv,
"MET_NP", -1,
"0", NULL);
5873 ERRMSG(
"Too many pressure levels!");
5875 (int)
scan_ctl(filename, argc, argv,
"MET_PRESS_LEVEL_DEF", -1,
"-1",
5881 for (
int ip = 0; ip < ctl->
met_np; ip++)
5883 scan_ctl(filename, argc, argv,
"MET_P", ip,
"", NULL);
5887 (int)
scan_ctl(filename, argc, argv,
"MET_NLEV", -1,
"0", NULL);
5889 ERRMSG(
"Too many model levels!");
5890 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
5892 scan_ctl(filename, argc, argv,
"MET_LEV_HYAM", ip,
"", NULL);
5893 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
5895 scan_ctl(filename, argc, argv,
"MET_LEV_HYBM", ip,
"", NULL);
5897 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SX", -1,
"-1", NULL);
5899 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SY", -1,
"-1", NULL);
5901 (int)
scan_ctl(filename, argc, argv,
"MET_RELHUM", -1,
"0", NULL);
5903 (int)
scan_ctl(filename, argc, argv,
"MET_CAPE", -1,
"1", NULL);
5905 ERRMSG(
"Set MET_CAPE to 0 or 1!");
5907 (int)
scan_ctl(filename, argc, argv,
"MET_PBL", -1,
"3", NULL);
5909 ERRMSG(
"Set MET_PBL to 0 ... 3!");
5911 scan_ctl(filename, argc, argv,
"MET_PBL_MIN", -1,
"0.1", NULL);
5913 scan_ctl(filename, argc, argv,
"MET_PBL_MAX", -1,
"5.0", NULL);
5915 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO", -1,
"3", NULL);
5917 ERRMSG(
"Set MET_TROPO to 0 ... 5!");
5919 scan_ctl(filename, argc, argv,
"MET_TROPO_PV", -1,
"3.5", NULL);
5921 scan_ctl(filename, argc, argv,
"MET_TROPO_THETA", -1,
"380", NULL);
5923 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO_SPLINE", -1,
"1", NULL);
5925 scan_ctl(filename, argc, argv,
"MET_DT_OUT", -1,
"0.1", NULL);
5927 (int)
scan_ctl(filename, argc, argv,
"MET_CACHE", -1,
"0", NULL);
5929 (int)
scan_ctl(filename, argc, argv,
"MET_MPI_SHARE", -1,
"0", NULL);
5932 ctl->
sort_dt =
scan_ctl(filename, argc, argv,
"SORT_DT", -1,
"-999", NULL);
5936 (int)
scan_ctl(filename, argc, argv,
"ISOSURF", -1,
"0", NULL);
5941 (int)
scan_ctl(filename, argc, argv,
"RNG_TYPE", -1,
"1", NULL);
5943 ERRMSG(
"Set RNG_TYPE to 0, 1, or 2!");
5946 ctl->
advect = (int)
scan_ctl(filename, argc, argv,
"ADVECT", -1,
"2", NULL);
5950 ERRMSG(
"Set ADVECT to 0, 1, 2, or 4!");
5954 = (int)
scan_ctl(filename, argc, argv,
"DIFFUSION", -1,
"0", NULL);
5956 ERRMSG(
"Set DIFFUSION to 0, 1 or 2!");
5958 scan_ctl(filename, argc, argv,
"TURB_DX_PBL", -1,
"50", NULL);
5960 scan_ctl(filename, argc, argv,
"TURB_DX_TROP", -1,
"50", NULL);
5962 scan_ctl(filename, argc, argv,
"TURB_DX_STRAT", -1,
"0", NULL);
5964 scan_ctl(filename, argc, argv,
"TURB_DZ_PBL", -1,
"0", NULL);
5966 scan_ctl(filename, argc, argv,
"TURB_DZ_TROP", -1,
"0", NULL);
5968 scan_ctl(filename, argc, argv,
"TURB_DZ_STRAT", -1,
"0.1", NULL);
5970 scan_ctl(filename, argc, argv,
"TURB_MESOX", -1,
"0.16", NULL);
5972 scan_ctl(filename, argc, argv,
"TURB_MESOZ", -1,
"0.16", NULL);
5976 = (int)
scan_ctl(filename, argc, argv,
"CONV_MIX_PBL", -1,
"0", NULL);
5978 =
scan_ctl(filename, argc, argv,
"CONV_PBL_TRANS", -1,
"0", NULL);
5980 =
scan_ctl(filename, argc, argv,
"CONV_CAPE", -1,
"-999", NULL);
5982 =
scan_ctl(filename, argc, argv,
"CONV_CIN", -1,
"-999", NULL);
5983 ctl->
conv_dt =
scan_ctl(filename, argc, argv,
"CONV_DT", -1,
"-999", NULL);
5987 scan_ctl(filename, argc, argv,
"BOUND_MASS", -1,
"-999", NULL);
5989 scan_ctl(filename, argc, argv,
"BOUND_MASS_TREND", -1,
"0", NULL);
5991 scan_ctl(filename, argc, argv,
"BOUND_VMR", -1,
"-999", NULL);
5993 scan_ctl(filename, argc, argv,
"BOUND_VMR_TREND", -1,
"0", NULL);
5995 scan_ctl(filename, argc, argv,
"BOUND_LAT0", -1,
"-999", NULL);
5997 scan_ctl(filename, argc, argv,
"BOUND_LAT1", -1,
"-999", NULL);
5999 scan_ctl(filename, argc, argv,
"BOUND_P0", -1,
"-999", NULL);
6001 scan_ctl(filename, argc, argv,
"BOUND_P1", -1,
"-999", NULL);
6003 scan_ctl(filename, argc, argv,
"BOUND_DPS", -1,
"-999", NULL);
6005 scan_ctl(filename, argc, argv,
"BOUND_DZS", -1,
"-999", NULL);
6007 scan_ctl(filename, argc, argv,
"BOUND_ZETAS", -1,
"-999", NULL);
6009 (int)
scan_ctl(filename, argc, argv,
"BOUND_PBL", -1,
"0", NULL);
6013 if (strcasecmp(ctl->
species,
"CF2Cl2") == 0) {
6017 }
else if (strcasecmp(ctl->
species,
"CFCl3") == 0) {
6021 }
else if (strcasecmp(ctl->
species,
"CH4") == 0) {
6028 }
else if (strcasecmp(ctl->
species,
"CO") == 0) {
6037 }
else if (strcasecmp(ctl->
species,
"CO2") == 0) {
6041 }
else if (strcasecmp(ctl->
species,
"H2O") == 0) {
6043 }
else if (strcasecmp(ctl->
species,
"N2O") == 0) {
6047 }
else if (strcasecmp(ctl->
species,
"NH3") == 0) {
6054 }
else if (strcasecmp(ctl->
species,
"HNO3") == 0) {
6058 }
else if (strcasecmp(ctl->
species,
"NO") == 0) {
6067 }
else if (strcasecmp(ctl->
species,
"NO2") == 0) {
6076 }
else if (strcasecmp(ctl->
species,
"O3") == 0) {
6083 }
else if (strcasecmp(ctl->
species,
"SF6") == 0) {
6087 }
else if (strcasecmp(ctl->
species,
"SO2") == 0) {
6100 sprintf(defstr,
"%g", ctl->
molmass);
6101 ctl->
molmass =
scan_ctl(filename, argc, argv,
"MOLMASS", -1, defstr, NULL);
6106 (int)
scan_ctl(filename, argc, argv,
"OH_CHEM_REACTION", -1, defstr,
6108 for (
int ip = 0; ip < 4; ip++) {
6109 sprintf(defstr,
"%g", ctl->
oh_chem[ip]);
6111 scan_ctl(filename, argc, argv,
"OH_CHEM", ip, defstr, NULL);
6114 scan_ctl(filename, argc, argv,
"OH_CHEM_BETA", -1,
"0", NULL);
6118 (int)
scan_ctl(filename, argc, argv,
"H2O2_CHEM_REACTION", -1,
"0", NULL);
6122 (int)
scan_ctl(filename, argc, argv,
"KPP_CHEM", -1,
"0", NULL);
6123 ctl->
dt_kpp =
scan_ctl(filename, argc, argv,
"DT_KPP", -1,
"1800", NULL);
6127 (int)
scan_ctl(filename, argc, argv,
"TRACER_CHEM", -1,
"0", NULL);
6130 for (
int ip = 0; ip < 2; ip++) {
6133 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_H", ip, defstr, NULL);
6135 for (
int ip = 0; ip < 1; ip++) {
6138 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_H", ip, defstr, NULL);
6141 scan_ctl(filename, argc, argv,
"WET_DEPO_SO2_PH", -1,
"0", NULL);
6143 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_A", -1,
"0", NULL);
6145 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_B", -1,
"0", NULL);
6147 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_A", -1,
"0", NULL);
6149 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_B", -1,
"0", NULL);
6151 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 0,
"0.5", NULL);
6153 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 1,
"0.36", NULL);
6155 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_RET_RATIO", -1,
"1", NULL);
6157 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_RET_RATIO", -1,
"1", NULL);
6161 scan_ctl(filename, argc, argv,
"DRY_DEPO_VDEP", -1,
"0", NULL);
6163 scan_ctl(filename, argc, argv,
"DRY_DEPO_DP", -1,
"30", NULL);
6166 scan_ctl(filename, argc, argv,
"CLIM_PHOTO", -1,
6167 "../../data/clams_photolysis_rates.nc", ctl->
clim_photo);
6168 scan_ctl(filename, argc, argv,
"CLIM_HNO3_FILENAME", -1,
6170 scan_ctl(filename, argc, argv,
"CLIM_OH_FILENAME", -1,
6172 scan_ctl(filename, argc, argv,
"CLIM_H2O2_FILENAME", -1,
6174 scan_ctl(filename, argc, argv,
"CLIM_HO2_FILENAME", -1,
6176 scan_ctl(filename, argc, argv,
"CLIM_O1D_FILENAME", -1,
6178 scan_ctl(filename, argc, argv,
"CLIM_CCL4_TIMESERIES", -1,
6180 scan_ctl(filename, argc, argv,
"CLIM_CCL3F_TIMESERIES", -1,
6182 scan_ctl(filename, argc, argv,
"CLIM_CCL2F2_TIMESERIES", -1,
6184 scan_ctl(filename, argc, argv,
"CLIM_N2O_TIMESERIES", -1,
6186 scan_ctl(filename, argc, argv,
"CLIM_SF6_TIMESERIES", -1,
6191 scan_ctl(filename, argc, argv,
"MIXING_DT", -1,
"3600.", NULL);
6193 scan_ctl(filename, argc, argv,
"MIXING_TROP", -1,
"-999", NULL);
6195 scan_ctl(filename, argc, argv,
"MIXING_STRAT", -1,
"-999", NULL);
6197 scan_ctl(filename, argc, argv,
"MIXING_Z0", -1,
"-5", NULL);
6199 scan_ctl(filename, argc, argv,
"MIXING_Z1", -1,
"85", NULL);
6201 (int)
scan_ctl(filename, argc, argv,
"MIXING_NZ", -1,
"90", NULL);
6203 scan_ctl(filename, argc, argv,
"MIXING_LON0", -1,
"-180", NULL);
6205 scan_ctl(filename, argc, argv,
"MIXING_LON1", -1,
"180", NULL);
6207 (int)
scan_ctl(filename, argc, argv,
"MIXING_NX", -1,
"360", NULL);
6209 scan_ctl(filename, argc, argv,
"MIXING_LAT0", -1,
"-90", NULL);
6211 scan_ctl(filename, argc, argv,
"MIXING_LAT1", -1,
"90", NULL);
6213 (int)
scan_ctl(filename, argc, argv,
"MIXING_NY", -1,
"180", NULL);
6217 scan_ctl(filename, argc, argv,
"CHEMGRID_Z0", -1,
"-5", NULL);
6219 scan_ctl(filename, argc, argv,
"CHEMGRID_Z1", -1,
"85", NULL);
6221 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NZ", -1,
"90", NULL);
6223 scan_ctl(filename, argc, argv,
"CHEMGRID_LON0", -1,
"-180", NULL);
6225 scan_ctl(filename, argc, argv,
"CHEMGRID_LON1", -1,
"180", NULL);
6227 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NX", -1,
"360", NULL);
6229 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT0", -1,
"-90", NULL);
6231 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT1", -1,
"90", NULL);
6233 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NY", -1,
"180", NULL);
6238 scan_ctl(filename, argc, argv,
"TDEC_STRAT", -1,
"0", NULL);
6241 ctl->
psc_h2o =
scan_ctl(filename, argc, argv,
"PSC_H2O", -1,
"4e-6", NULL);
6243 scan_ctl(filename, argc, argv,
"PSC_HNO3", -1,
"9e-9", NULL);
6249 scan_ctl(filename, argc, argv,
"ATM_DT_OUT", -1,
"86400", NULL);
6251 (int)
scan_ctl(filename, argc, argv,
"ATM_FILTER", -1,
"0", NULL);
6253 (int)
scan_ctl(filename, argc, argv,
"ATM_STRIDE", -1,
"1", NULL);
6255 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE", -1,
"0", NULL);
6257 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE_OUT", -1,
"-1", NULL);
6261 (int)
scan_ctl(filename, argc, argv,
"ATM_NC_LEVEL", -1,
"0", NULL);
6262 for (
int iq = 0; iq < ctl->
nq; iq++)
6264 (
int)
scan_ctl(filename, argc, argv,
"ATM_NC_QUANT", iq,
"0", NULL);
6266 (int)
scan_ctl(filename, argc, argv,
"OBS_TYPE", -1,
"0", NULL);
6272 scan_ctl(filename, argc, argv,
"CSI_DT_OUT", -1,
"86400", NULL);
6275 scan_ctl(filename, argc, argv,
"CSI_OBSMIN", -1,
"0", NULL);
6277 scan_ctl(filename, argc, argv,
"CSI_MODMIN", -1,
"0", NULL);
6278 ctl->
csi_z0 =
scan_ctl(filename, argc, argv,
"CSI_Z0", -1,
"-5", NULL);
6279 ctl->
csi_z1 =
scan_ctl(filename, argc, argv,
"CSI_Z1", -1,
"85", NULL);
6280 ctl->
csi_nz = (int)
scan_ctl(filename, argc, argv,
"CSI_NZ", -1,
"1", NULL);
6282 scan_ctl(filename, argc, argv,
"CSI_LON0", -1,
"-180", NULL);
6283 ctl->
csi_lon1 =
scan_ctl(filename, argc, argv,
"CSI_LON1", -1,
"180", NULL);
6285 (int)
scan_ctl(filename, argc, argv,
"CSI_NX", -1,
"360", NULL);
6286 ctl->
csi_lat0 =
scan_ctl(filename, argc, argv,
"CSI_LAT0", -1,
"-90", NULL);
6287 ctl->
csi_lat1 =
scan_ctl(filename, argc, argv,
"CSI_LAT1", -1,
"90", NULL);
6289 (int)
scan_ctl(filename, argc, argv,
"CSI_NY", -1,
"180", NULL);
6292 ctl->
nens = (int)
scan_ctl(filename, argc, argv,
"NENS", -1,
"0", NULL);
6295 scan_ctl(filename, argc, argv,
"ENS_DT_OUT", -1,
"86400", NULL);
6298 scan_ctl(filename, argc, argv,
"GRID_BASENAME", -1,
"-",
6303 scan_ctl(filename, argc, argv,
"GRID_DT_OUT", -1,
"86400", NULL);
6305 (int)
scan_ctl(filename, argc, argv,
"GRID_SPARSE", -1,
"0", NULL);
6307 (int)
scan_ctl(filename, argc, argv,
"GRID_NC_LEVEL", -1,
"0", NULL);
6308 for (
int iq = 0; iq < ctl->
nq; iq++)
6310 (
int)
scan_ctl(filename, argc, argv,
"GRID_NC_QUANT", iq,
"0", NULL);
6312 (int)
scan_ctl(filename, argc, argv,
"GRID_STDDEV", -1,
"0", NULL);
6313 ctl->
grid_z0 =
scan_ctl(filename, argc, argv,
"GRID_Z0", -1,
"-5", NULL);
6314 ctl->
grid_z1 =
scan_ctl(filename, argc, argv,
"GRID_Z1", -1,
"85", NULL);
6316 (int)
scan_ctl(filename, argc, argv,
"GRID_NZ", -1,
"1", NULL);
6318 scan_ctl(filename, argc, argv,
"GRID_LON0", -1,
"-180", NULL);
6320 scan_ctl(filename, argc, argv,
"GRID_LON1", -1,
"180", NULL);
6322 (int)
scan_ctl(filename, argc, argv,
"GRID_NX", -1,
"360", NULL);
6324 scan_ctl(filename, argc, argv,
"GRID_LAT0", -1,
"-90", NULL);
6326 scan_ctl(filename, argc, argv,
"GRID_LAT1", -1,
"90", NULL);
6328 (int)
scan_ctl(filename, argc, argv,
"GRID_NY", -1,
"180", NULL);
6330 (int)
scan_ctl(filename, argc, argv,
"GRID_TYPE", -1,
"0", NULL);
6333 scan_ctl(filename, argc, argv,
"PROF_BASENAME", -1,
"-",
6336 ctl->
prof_z0 =
scan_ctl(filename, argc, argv,
"PROF_Z0", -1,
"0", NULL);
6337 ctl->
prof_z1 =
scan_ctl(filename, argc, argv,
"PROF_Z1", -1,
"60", NULL);
6339 (int)
scan_ctl(filename, argc, argv,
"PROF_NZ", -1,
"60", NULL);
6341 scan_ctl(filename, argc, argv,
"PROF_LON0", -1,
"-180", NULL);
6343 scan_ctl(filename, argc, argv,
"PROF_LON1", -1,
"180", NULL);
6345 (int)
scan_ctl(filename, argc, argv,
"PROF_NX", -1,
"360", NULL);
6347 scan_ctl(filename, argc, argv,
"PROF_LAT0", -1,
"-90", NULL);
6349 scan_ctl(filename, argc, argv,
"PROF_LAT1", -1,
"90", NULL);
6351 (int)
scan_ctl(filename, argc, argv,
"PROF_NY", -1,
"180", NULL);
6354 scan_ctl(filename, argc, argv,
"SAMPLE_BASENAME", -1,
"-",
6356 scan_ctl(filename, argc, argv,
"SAMPLE_KERNEL", -1,
"-",
6358 scan_ctl(filename, argc, argv,
"SAMPLE_OBSFILE", -1,
"-",
6361 scan_ctl(filename, argc, argv,
"SAMPLE_DX", -1,
"50", NULL);
6363 scan_ctl(filename, argc, argv,
"SAMPLE_DZ", -1,
"-999", NULL);
6366 scan_ctl(filename, argc, argv,
"STAT_BASENAME", -1,
"-",
6370 ctl->
stat_r =
scan_ctl(filename, argc, argv,
"STAT_R", -1,
"50", NULL);
6372 scan_ctl(filename, argc, argv,
"STAT_T0", -1,
"-1e100", NULL);
6373 ctl->
stat_t1 =
scan_ctl(filename, argc, argv,
"STAT_T1", -1,
"1e100", NULL);
6378 scan_ctl(filename, argc, argv,
"VTK_DT_OUT", -1,
"86400", NULL);
6380 (int)
scan_ctl(filename, argc, argv,
"VTK_STRIDE", -1,
"1", NULL);
6382 scan_ctl(filename, argc, argv,
"VTK_SCALE", -1,
"1.0", NULL);
6384 scan_ctl(filename, argc, argv,
"VTK_OFFSET", -1,
"0.0", NULL);
6386 (int)
scan_ctl(filename, argc, argv,
"VTK_SPHERE", -1,
"0", NULL);
6389 ctl->
dd = (int)
scan_ctl(filename, argc, argv,
"DD", -1,
"0", NULL);
6391 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_MERIDIONAL", -1,
6392 (ctl->
dd == 1) ?
"2" :
"1", NULL);
6394 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_ZONAL", -1,
6395 (ctl->
dd == 1) ?
"2" :
"1", NULL);
6398 else if (ctl->
dd == 1)
6399 ERRMSG(
"Please provide zonal and meridional subdomain numbers!")
6401 (int)
scan_ctl(filename, argc, argv,
"DD_NBR_NEIGHBOURS", -1,
"8",
6404 (int)
scan_ctl(filename, argc, argv,
"DD_HALOS_SIZE", -1,
"1", NULL);
6410 const char *filename,
6417 LOG(1,
"Read meteo data: %s", filename);
6423 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
6451 ERRMSG(
"MET_TYPE not implemented!");
6505 LOG(2,
"Broadcast data on rank %d...", rank);
6636 ERRMSG(
"DD initialized, but model is compiled without DD.")
6645 ERRMSG(
"Code was compiled without KPP!");
6678#pragma acc update device(ctl[:1])
6682 if (cache != NULL) {
6685#pragma acc update device(cache[:1])
6692#pragma acc update device(clim[:1])
6699 met_t *met0up = *met0;
6700#pragma acc update device(met0up[:1])
6707 met_t *met1up = *met1;
6708#pragma acc update device(met1up[:1])
6715#pragma acc update device(atm[:1])
6734#pragma acc update host(ctl[:1])
6738 if (cache != NULL) {
6741#pragma acc update host(cache[:1])
6748#pragma acc update host(clim[:1])
6755 met_t *met0up = *met0;
6756#pragma acc update host(met0up[:1])
6763 met_t *met1up = *met1;
6764#pragma acc update host(met1up[:1])
6771#pragma acc update host(atm[:1])
6779 const char *filename,
6788 LOG(1,
"Write atmospheric data: %s", filename);
6812 ERRMSG(
"Atmospheric data type not supported!");
6816 LOG(2,
"Number of particles: %d", atm->
np);
6817 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
6818 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
6819 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
6820 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
6821 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
6822 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
6823 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
6824 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
6825 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
6826 for (
int iq = 0; iq < ctl->
nq; iq++) {
6828 sprintf(msg,
"Quantity %s range: %s ... %s %s",
6831 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
6832 LOG(2, msg, mini, maxi);
6839 const char *filename,
6847 LOG(1,
"Write meteo data: %s", filename);
6852 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
6856 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
6860 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
6864 ERRMSG(
"MPTRAC was compiled without SZ3 compression!");
6877 ERRMSG(
"MET_TYPE not implemented!");
6883 const char *dirname,
6890 char ext[10], filename[2 *
LEN];
6894 int year, mon, day, hour, min, sec;
6897 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
6912 sprintf(ext,
"tab");
6914 sprintf(ext,
"bin");
6917 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6918 dirname, ctl->
atm_basename, year, mon, day, hour, min, ext);
6924 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6927 write_grid(filename, ctl, met0, met1, atm, t);
6932 sprintf(filename,
"%s/%s.tab", dirname, ctl->
csi_basename);
6938 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.tab",
6939 dirname, ctl->
ens_basename, year, mon, day, hour, min);
6945 sprintf(filename,
"%s/%s.tab", dirname, ctl->
prof_basename);
6946 write_prof(filename, ctl, met0, met1, atm, t);
6957 sprintf(filename,
"%s/%s.tab", dirname, ctl->
stat_basename);
6966 sprintf(filename,
"%s/%s_%05d.vtk", dirname, ctl->
vtk_basename, ++nvtk);
6976 const double hno3) {
6979 const double h2o_help =
MAX(h2o, 0.1e-6);
6982 const double p_hno3 = hno3 * p / 1.333224;
6983 const double p_h2o = h2o_help * p / 1.333224;
6984 const double a = 0.009179 - 0.00088 * log10(p_h2o);
6985 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
6986 const double c = -11397.0 / a;
6987 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
6988 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
7006 const double p0 = pbl;
7009 if (atm->
p[ip] > p0)
7011 else if (atm->
p[ip] < p1)
7014 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
7020 const char *filename,
7026 if (!(in = fopen(filename,
"r"))) {
7027 WARN(
"Cannot open file!");
7033 while (fgets(line,
LEN, in)) {
7037 TOK(line, tok,
"%lg", atm->
time[atm->
np]);
7038 TOK(NULL, tok,
"%lg", atm->
p[atm->
np]);
7039 TOK(NULL, tok,
"%lg", atm->
lon[atm->
np]);
7040 TOK(NULL, tok,
"%lg", atm->
lat[atm->
np]);
7041 for (
int iq = 0; iq < ctl->
nq; iq++)
7042 TOK(NULL, tok,
"%lg", atm->
q[iq][atm->
np]);
7045 atm->
p[atm->
np] =
P(atm->
p[atm->
np]);
7048 if ((++atm->
np) >
NP)
7049 ERRMSG(
"Too many data points!");
7062 const char *filename,
7068 if (!(in = fopen(filename,
"r")))
7073 FREAD(&version,
int,
7077 ERRMSG(
"Wrong version of binary data!");
7095 for (
int iq = 0; iq < ctl->
nq; iq++)
7096 FREAD(atm->
q[iq],
double,
7106 ERRMSG(
"Error while reading binary data!");
7118 const char *filename,
7125 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
7132 if (nc_inq_varid(ncid,
"TIME_INIT", &varid) == NC_NOERR) {
7133 NC(nc_get_var_double(ncid, varid, atm->
time));
7135 WARN(
"TIME_INIT not found use time instead!");
7138 for (
int ip = 0; ip < atm->
np; ip++) {
7139 atm->
time[ip] = time_init;
7151 if (nc_inq_varid(ncid,
"PRESS_INIT", &varid) == NC_NOERR) {
7152 NC(nc_get_var_double(ncid, varid, atm->
p));
7154 WARN(
"PRESS_INIT not found use PRESS instead!");
7155 nc_inq_varid(ncid,
"PRESS", &varid);
7156 NC(nc_get_var_double(ncid, varid, atm->
p));
7161 for (
int iq = 0; iq < ctl->
nq; iq++)
7178 const char *filename,
7185 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
7198 for (
int iq = 0; iq < ctl->
nq; iq++)
7211 const char *filename,
7217 LOG(1,
"Read photolysis rates: %s", filename);
7220 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
7221 WARN(
"Photolysis rate data are missing!");
7228 if (photo->
p[0] < photo->
p[1])
7229 ERRMSG(
"Pressure data are not descending!");
7234 if (photo->
o3c[0] > photo->
o3c[1])
7235 ERRMSG(
"Total column ozone data are not ascending!");
7240 if (photo->
sza[0] > photo->
sza[1])
7241 ERRMSG(
"Solar zenith angle data are not ascending!");
7258 LOG(2,
"Number of pressure levels: %d", photo->
np);
7259 LOG(2,
"Altitude levels: %g, %g ... %g km",
7260 Z(photo->
p[0]),
Z(photo->
p[1]),
Z(photo->
p[photo->
np - 1]));
7261 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
7262 photo->
p[0], photo->
p[1], photo->
p[photo->
np - 1]);
7263 LOG(2,
"Number of solar zenith angles: %d", photo->
nsza);
7264 LOG(2,
"Solar zenith angles: %g, %g ... %g deg",
7267 LOG(2,
"Number of total column ozone values: %d", photo->
no3c);
7268 LOG(2,
"Total column ozone: %g, %g ... %g DU",
7270 LOG(2,
"N2O photolysis rate: %g, %g ... %g s**-1",
7271 photo->
n2o[0][0][0], photo->
n2o[1][0][0],
7272 photo->
n2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7273 LOG(2,
"CCl4 photolysis rate: %g, %g ... %g s**-1",
7274 photo->
ccl4[0][0][0], photo->
ccl4[1][0][0],
7276 LOG(2,
"CFC-11 photolysis rate: %g, %g ... %g s**-1",
7277 photo->
ccl3f[0][0][0], photo->
ccl3f[1][0][0],
7279 LOG(2,
"CFC-12 photolysis rate: %g, %g ... %g s**-1",
7282 LOG(2,
"O2 photolysis rate: %g, %g ... %g s**-1",
7283 photo->
o2[0][0][0], photo->
o2[1][0][0],
7284 photo->
o2[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7285 LOG(2,
"O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
7286 photo->
o3_1[0][0][0], photo->
o3_1[1][0][0],
7288 LOG(2,
"O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
7289 photo->
o3_2[0][0][0], photo->
o3_2[1][0][0],
7291 LOG(2,
"H2O2 photolysis rate: %g, %g ... %g s**-1",
7292 photo->
h2o2[0][0][0], photo->
h2o2[1][0][0],
7294 LOG(2,
"H2O photolysis rate: %g, %g ... %g s**-1",
7295 photo->
h2o[0][0][0], photo->
h2o[1][0][0],
7296 photo->
h2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7303 const char *varname,
7317 for (
int ip = 0; ip < photo->
np; ip++)
7318 for (
int is = 0; is < photo->
nsza; is++)
7319 for (
int io = 0; io < photo->
no3c; io++)
7330 const char *filename,
7334 LOG(1,
"Read climatological time series: %s", filename);
7338 if (!(in = fopen(filename,
"r"))) {
7339 WARN(
"Cannot open file!");
7346 while (fgets(line,
LEN, in))
7347 if (sscanf(line,
"%lg %lg", &ts->
time[nh], &ts->
vmr[nh]) == 2) {
7350 ts->
time[nh] = (ts->
time[nh] - 2000.0) * 365.25 * 86400.;
7353 if (nh > 0 && ts->
time[nh] <= ts->
time[nh - 1])
7354 ERRMSG(
"Time series must be ascending!");
7358 ERRMSG(
"Too many data points!");
7367 ERRMSG(
"Not enough data points!");
7370 LOG(2,
"Number of time steps: %d", ts->
ntime);
7371 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s", ts->
time[0], ts->
time[1],
7373 LOG(2,
"Volume mixing ratio range: %g ... %g ppv",
7374 gsl_stats_min(ts->
vmr, 1, (
size_t) nh), gsl_stats_max(ts->
vmr, 1,
7384 const char *filename,
7385 const char *varname,
7388 int ncid, varid, it, iy, iz, iz2, nt;
7390 double *help, varmin = 1e99, varmax = -1e99;
7393 LOG(1,
"Read %s data: %s", varname, filename);
7396 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
7397 WARN(
"%s climatology data are missing!", varname);
7404 if (zm->
p[0] < zm->
p[1])
7405 ERRMSG(
"Pressure data are not descending!");
7410 if (zm->
lat[0] > zm->
lat[1])
7411 ERRMSG(
"Latitude data are not ascending!");
7415 zm->
time[0] = 1209600.00;
7416 zm->
time[1] = 3888000.00;
7417 zm->
time[2] = 6393600.00;
7418 zm->
time[3] = 9072000.00;
7419 zm->
time[4] = 11664000.00;
7420 zm->
time[5] = 14342400.00;
7421 zm->
time[6] = 16934400.00;
7422 zm->
time[7] = 19612800.00;
7423 zm->
time[8] = 22291200.00;
7424 zm->
time[9] = 24883200.00;
7425 zm->
time[10] = 27561600.00;
7426 zm->
time[11] = 30153600.00;
7435 for (it = 0; it < zm->
ntime; it++)
7436 for (iz = 0; iz < zm->
np; iz++)
7437 for (iy = 0; iy < zm->
nlat; iy++)
7442 for (it = 0; it < zm->
ntime; it++)
7443 for (iy = 0; iy < zm->
nlat; iy++)
7444 for (iz = 0; iz < zm->
np; iz++) {
7445 if (zm->
vmr[it][iz][iy] < 0) {
7446 for (iz2 = 0; iz2 < zm->
np; iz2++)
7447 if (zm->
vmr[it][iz2][iy] >= 0) {
7448 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
7451 for (iz2 = zm->
np - 1; iz2 >= 0; iz2--)
7452 if (zm->
vmr[it][iz2][iy] >= 0) {
7453 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
7457 varmin =
MIN(varmin, zm->
vmr[it][iz][iy]);
7458 varmax =
MAX(varmax, zm->
vmr[it][iz][iy]);
7465 LOG(2,
"Number of time steps: %d", zm->
ntime);
7466 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
7468 LOG(2,
"Number of pressure levels: %d", zm->
np);
7469 LOG(2,
"Altitude levels: %g, %g ... %g km",
7470 Z(zm->
p[0]),
Z(zm->
p[1]),
Z(zm->
p[zm->
np - 1]));
7471 LOG(2,
"Pressure levels: %g, %g ... %g hPa", zm->
p[0],
7472 zm->
p[1], zm->
p[zm->
np - 1]);
7473 LOG(2,
"Number of latitudes: %d", zm->
nlat);
7474 LOG(2,
"Latitudes: %g, %g ... %g deg",
7476 LOG(2,
"%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
7483 const char *filename,
7489 LOG(1,
"Read kernel function: %s", filename);
7493 if (!(in = fopen(filename,
"r")))
7494 ERRMSG(
"Cannot open file!");
7499 while (fgets(line,
LEN, in))
7500 if (sscanf(line,
"%lg %lg", &kz[n], &kw[n]) == 2) {
7501 if (n > 0 && kz[n] < kz[n - 1])
7502 ERRMSG(
"Height levels must be ascending!");
7504 ERRMSG(
"Too many height levels!");
7513 ERRMSG(
"Not enough height levels!");
7516 const double kmax = gsl_stats_max(kw, 1, (
size_t) n);
7517 for (
int iz = 0; iz < n; iz++)
7524 const char *filename,
7532 int year, mon, day, hour, min, sec;
7538 if (!(in = fopen(filename,
"r"))) {
7539 WARN(
"Cannot open file!");
7545 FREAD(&met_type,
int,
7549 ERRMSG(
"Wrong MET_TYPE of binary data!");
7553 FREAD(&version,
int,
7557 ERRMSG(
"Wrong version of binary data!");
7563 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
7564 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
7565 met->
time, year, mon, day, hour, min);
7566 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
7567 || day < 1 || day > 31 || hour < 0 || hour > 23)
7568 ERRMSG(
"Error while reading time!");
7574 LOG(2,
"Number of longitudes: %d", met->
nx);
7575 if (met->
nx < 2 || met->
nx >
EX)
7576 ERRMSG(
"Number of longitudes out of range!");
7581 LOG(2,
"Number of latitudes: %d", met->
ny);
7582 if (met->
ny < 2 || met->
ny >
EY)
7583 ERRMSG(
"Number of latitudes out of range!");
7588 LOG(2,
"Number of levels: %d", met->
np);
7589 if (met->
np < 2 || met->
np >
EP)
7590 ERRMSG(
"Number of levels out of range!");
7596 LOG(2,
"Longitudes: %g, %g ... %g deg",
7602 LOG(2,
"Latitudes: %g, %g ... %g deg",
7608 LOG(2,
"Altitude levels: %g, %g ... %g km",
7609 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
7610 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
7611 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
7660 ERRMSG(
"Error while reading binary data!");
7675 const char *varname) {
7684 LOG(2,
"Read 2-D variable: %s (uncompressed)", varname);
7686 (
size_t) (met->
nx * met->
ny),
7690 for (
int ix = 0; ix < met->
nx; ix++)
7691 for (
int iy = 0; iy < met->
ny; iy++)
7692 var[ix][iy] = help[
ARRAY_2D(ix, iy, met->
ny)];
7705 const char *varname,
7706 const float bound_min,
7707 const float bound_max) {
7717 LOG(2,
"Read 3-D variable: %s (uncompressed)", varname);
7719 (
size_t) (met->
nx * met->
ny * met->
np),
7726 (
size_t) met->
np, 1, in);
7732 FREAD(&precision,
int,
7737 FREAD(&tolerance,
double,
7744 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
7754 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
7762 (
size_t) met->
np, met->
p, 1, in);
7764 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
7772 FREAD(&precision,
int,
7777 FREAD(&tolerance,
double,
7784 ERRMSG(
"MPTRAC was compiled without sz3 compression!");
7789#pragma omp parallel for default(shared) collapse(2)
7790 for (
int ix = 0; ix < met->
nx; ix++)
7791 for (
int iy = 0; iy < met->
ny; iy++)
7792 for (
int ip = 0; ip < met->
np; ip++) {
7793 var[ix][iy][ip] = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
7794 if (var[ix][iy][ip] < bound_min)
7795 var[ix][iy][ip] = bound_min;
7796 else if (var[ix][iy][ip] > bound_max)
7797 var[ix][iy][ip] = bound_max;
7817 LOG(2,
"Calculate CAPE...");
7820 const double pfac = 1.01439, dz0 =
RI /
MA /
G0 * log(pfac);
7823#pragma omp parallel for default(shared) collapse(2)
7824 for (
int ix = 0; ix < met->
nx; ix++)
7825 for (
int iy = 0; iy < met->
ny; iy++) {
7829 double h2o = 0, t, theta = 0;
7830 double pbot =
MIN(met->
ps[ix][iy], met->
p[0]);
7831 double ptop = pbot - 50.;
7832 for (
int ip = 0; ip < met->
np; ip++) {
7833 if (met->
p[ip] <= pbot) {
7834 theta +=
THETA(met->
p[ip], met->
t[ix][iy][ip]);
7835 h2o += met->
h2o[ix][iy][ip];
7838 if (met->
p[ip] < ptop && n > 0)
7845 met->
plcl[ix][iy] = NAN;
7846 met->
plfc[ix][iy] = NAN;
7847 met->
pel[ix][iy] = NAN;
7848 met->
cape[ix][iy] = NAN;
7849 met->
cin[ix][iy] = NAN;
7855 pbot = met->
ps[ix][iy];
7857 met->
plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
7858 t = theta / pow(1000. / met->
plcl[ix][iy], 0.286);
7859 if (
RH(met->
plcl[ix][iy], t, h2o) > 100.)
7860 ptop = met->
plcl[ix][iy];
7862 pbot = met->
plcl[ix][iy];
7863 }
while (pbot - ptop > 0.1);
7867 double dcape, dz, h2o_env, t_env;
7868 double p = met->
ps[ix][iy];
7869 met->
cape[ix][iy] = met->
cin[ix][iy] = 0;
7871 dz = dz0 *
TVIRT(t, h2o);
7873 t = theta / pow(1000. / p, 0.286);
7877 &h2o_env, ci, cw, 0);
7878 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
7879 TVIRT(t_env, h2o_env) * dz;
7881 met->
cin[ix][iy] += fabsf((
float) dcape);
7882 }
while (p > met->
plcl[ix][iy]);
7887 p = met->
plcl[ix][iy];
7888 t = theta / pow(1000. / p, 0.286);
7891 dz = dz0 *
TVIRT(t, h2o);
7894 double psat =
PSAT(t);
7895 h2o = psat / (p - (1. -
EPS) * psat);
7899 &h2o_env, ci, cw, 0);
7900 double dcape_old = dcape;
7901 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
7902 TVIRT(t_env, h2o_env) * dz;
7904 met->
cape[ix][iy] += (float) dcape;
7905 if (!isfinite(met->
plfc[ix][iy]))
7906 met->
plfc[ix][iy] = (
float) p;
7907 }
else if (dcape_old > 0)
7908 met->
pel[ix][iy] = (float) p;
7909 if (dcape < 0 && !isfinite(met->
plfc[ix][iy]))
7910 met->
cin[ix][iy] += fabsf((
float) dcape);
7914 if (!isfinite(met->
plfc[ix][iy]))
7915 met->
cin[ix][iy] = NAN;
7926 LOG(2,
"Calculate cloud data...");
7929 const double ccmin = 0.01, cwmin = 1e-6;
7932#pragma omp parallel for default(shared) collapse(2)
7933 for (
int ix = 0; ix < met->
nx; ix++)
7934 for (
int iy = 0; iy < met->
ny; iy++) {
7937 met->
pct[ix][iy] = NAN;
7938 met->
pcb[ix][iy] = NAN;
7939 met->
cl[ix][iy] = 0;
7942 for (
int ip = 0; ip < met->
np - 1; ip++) {
7945 if (met->
p[ip] > met->
ps[ix][iy] || met->
p[ip] <
P(20.))
7949 if (met->
cc[ix][iy][ip] > ccmin
7950 && (met->
lwc[ix][iy][ip] > cwmin
7951 || met->
rwc[ix][iy][ip] > cwmin
7952 || met->
iwc[ix][iy][ip] > cwmin
7953 || met->
swc[ix][iy][ip] > cwmin)) {
7957 = (float) (0.5 * (met->
p[ip] + (
float) met->
p[ip + 1]));
7960 if (!isfinite(met->
pcb[ix][iy]))
7962 = (
float) (0.5 * (met->
p[ip] + met->
p[
MAX(ip - 1, 0)]));
7966 met->
cl[ix][iy] += (float)
7967 (0.5 * (met->
lwc[ix][iy][ip] + met->
lwc[ix][iy][ip + 1]
7968 + met->
rwc[ix][iy][ip] + met->
rwc[ix][iy][ip + 1]
7969 + met->
iwc[ix][iy][ip] + met->
iwc[ix][iy][ip + 1]
7970 + met->
swc[ix][iy][ip] + met->
swc[ix][iy][ip + 1])
7971 * 100. * (met->
p[ip] - met->
p[ip + 1]) /
G0);
7989 SELECT_TIMER(
"READ_MET_DETREND",
"METPROC", NVTX_READ);
7990 LOG(2,
"Detrend meteo data...");
7997 const double tssq = 2. *
SQR(sigma);
8000 int sy = (int) (3. *
DY2DEG(sigma) / fabs(met->
lat[1] - met->
lat[0]));
8004#pragma omp parallel for default(shared) collapse(2)
8005 for (
int ix = 0; ix < met->
nx; ix++) {
8006 for (
int iy = 0; iy < met->
ny; iy++) {
8014 (int) (3. *
DX2DEG(sigma, met->
lat[iy]) /
8015 fabs(met->
lon[1] - met->
lon[0]));
8020 for (
int ip = 0; ip < met->
np; ip++) {
8021 help->
t[ix][iy][ip] = 0;
8022 help->
u[ix][iy][ip] = 0;
8023 help->
v[ix][iy][ip] = 0;
8024 help->
w[ix][iy][ip] = 0;
8028 for (
int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
8032 else if (ix3 >= met->
nx)
8034 for (
int iy2 =
MAX(iy - sy, 0);
8035 iy2 <=
MIN(iy + sy, met->
ny - 1); iy2++) {
8042 const float w = (float) exp(-
DIST2(x0, x1) / tssq);
8046 for (
int ip = 0; ip < met->
np; ip++) {
8047 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip];
8048 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip];
8049 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip];
8050 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip];
8056 for (
int ip = 0; ip < met->
np; ip++) {
8057 help->
t[ix][iy][ip] /= wsum;
8058 help->
u[ix][iy][ip] /= wsum;
8059 help->
v[ix][iy][ip] /= wsum;
8060 help->
w[ix][iy][ip] /= wsum;
8066#pragma omp parallel for default(shared) collapse(3)
8067 for (
int ix = 0; ix < met->
nx; ix++)
8068 for (
int iy = 0; iy < met->
ny; iy++)
8069 for (
int ip = 0; ip < met->
np; ip++) {
8070 met->
t[ix][iy][ip] -= help->
t[ix][iy][ip];
8071 met->
u[ix][iy][ip] -= help->
u[ix][iy][ip];
8072 met->
v[ix][iy][ip] -= help->
v[ix][iy][ip];
8073 met->
w[ix][iy][ip] -= help->
w[ix][iy][ip];
8086 SELECT_TIMER(
"READ_MET_EXTRAPOLATE",
"METPROC", NVTX_READ);
8087 LOG(2,
"Extrapolate meteo data...");
8090#pragma omp parallel for default(shared) collapse(2)
8091 for (
int ix = 0; ix < met->
nx; ix++)
8092 for (
int iy = 0; iy < met->
ny; iy++) {
8096 for (ip0 = met->
np - 1; ip0 >= 0; ip0--)
8097 if (!isfinite(met->
t[ix][iy][ip0])
8098 || !isfinite(met->
u[ix][iy][ip0])
8099 || !isfinite(met->
v[ix][iy][ip0])
8100 || !isfinite(met->
w[ix][iy][ip0]))
8104 for (
int ip = ip0; ip >= 0; ip--) {
8105 met->
t[ix][iy][ip] = met->
t[ix][iy][ip + 1];
8106 met->
u[ix][iy][ip] = met->
u[ix][iy][ip + 1];
8107 met->
v[ix][iy][ip] = met->
v[ix][iy][ip + 1];
8108 met->
w[ix][iy][ip] = met->
w[ix][iy][ip + 1];
8109 met->
h2o[ix][iy][ip] = met->
h2o[ix][iy][ip + 1];
8110 met->
o3[ix][iy][ip] = met->
o3[ix][iy][ip + 1];
8111 met->
lwc[ix][iy][ip] = met->
lwc[ix][iy][ip + 1];
8112 met->
rwc[ix][iy][ip] = met->
rwc[ix][iy][ip + 1];
8113 met->
iwc[ix][iy][ip] = met->
iwc[ix][iy][ip + 1];
8114 met->
swc[ix][iy][ip] = met->
swc[ix][iy][ip + 1];
8115 met->
cc[ix][iy][ip] = met->
cc[ix][iy][ip + 1];
8134 LOG(2,
"Calculate geopotential heights...");
8141#pragma omp parallel for default(shared)
8142 for (
int ip = 0; ip < met->
np; ip++)
8143 logp[ip] = log(met->
p[ip]);
8146#pragma omp parallel for default(shared) collapse(2)
8147 for (
int ix = 0; ix < met->
nx; ix++)
8148 for (
int iy = 0; iy < met->
ny; iy++) {
8151 const double zs = met->
zs[ix][iy];
8152 const double lnps = log(met->
ps[ix][iy]);
8156 const double ts =
LIN(met->
p[ip0], met->
t[ix][iy][ip0], met->
p[ip0 + 1],
8157 met->
t[ix][iy][ip0 + 1], met->
ps[ix][iy]);
8159 LIN(met->
p[ip0], met->
h2o[ix][iy][ip0], met->
p[ip0 + 1],
8160 met->
h2o[ix][iy][ip0 + 1], met->
ps[ix][iy]);
8163 met->
z[ix][iy][ip0 + 1]
8165 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
8166 met->
t[ix][iy][ip0 + 1], met->
h2o[ix][iy][ip0 + 1]));
8167 for (
int ip = ip0 + 2; ip < met->
np; ip++)
8169 = (
float) (met->
z[ix][iy][ip - 1] +
8170 ZDIFF(logp[ip - 1], met->
t[ix][iy][ip - 1],
8171 met->
h2o[ix][iy][ip - 1], logp[ip],
8172 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
8177 ZDIFF(lnps, ts, h2os, logp[ip0],
8178 met->
t[ix][iy][ip0], met->
h2o[ix][iy][ip0]));
8179 for (
int ip = ip0 - 1; ip >= 0; ip--)
8181 = (
float) (met->
z[ix][iy][ip + 1] +
8182 ZDIFF(logp[ip + 1], met->
t[ix][iy][ip + 1],
8183 met->
h2o[ix][iy][ip + 1], logp[ip],
8184 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
8188 if (dx == 0 || dy == 0)
8192 if (dx < 0 || dy < 0) {
8193 if (fabs(met->
lon[1] - met->
lon[0]) < 0.5) {
8203 float ws[dx + 1][dy + 1];
8204#pragma omp parallel for default(shared) collapse(2)
8205 for (
int ix = 0; ix <= dx; ix++)
8206 for (
int iy = 0; iy < dy; iy++)
8207 ws[ix][iy] = (1.0f - (
float) ix / (float) dx)
8208 * (1.0f - (float) iy / (
float) dy);
8211#pragma omp parallel for default(shared) collapse(3)
8212 for (
int ix = 0; ix < met->
nx; ix++)
8213 for (
int iy = 0; iy < met->
ny; iy++)
8214 for (
int ip = 0; ip < met->
np; ip++)
8215 help[
ARRAY_3D(ip, ix, met->
nx, iy, met->
ny)] = met->
z[ix][iy][ip];
8218#pragma omp parallel for default(shared) collapse(3)
8219 for (
int ip = 0; ip < met->
np; ip++)
8220 for (
int ix = 0; ix < met->
nx; ix++)
8221 for (
int iy = 0; iy < met->
ny; iy++) {
8222 float res = 0, wsum = 0;
8223 int iy0 =
MAX(iy - dy + 1, 0);
8224 int iy1 =
MIN(iy + dy - 1, met->
ny - 1);
8225 for (
int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
8229 else if (ix3 >= met->
nx)
8231 for (
int iy2 = iy0; iy2 <= iy1; ++iy2)
8232 if (isfinite(help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)])) {
8233 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
8234 res += w * help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)];
8239 met->
z[ix][iy][ip] = res / wsum;
8241 met->
z[ix][iy][ip] = NAN;
8251 const char *filename,
8257 char levname[
LEN], tstr[10];
8259 double rtime = 0, r, r2;
8261 int varid, ndims, dimids[NC_MAX_DIMS], year2, mon2, day2, hour2, min2, sec2,
8262 year, mon, day, hour, min, sec;
8268 LOG(2,
"Read meteo grid information...");
8277 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
8278 if (nc_inq_varid(ncid,
"time", &varid) == NC_NOERR) {
8279 NC(nc_get_var_double(ncid, varid, &rtime));
8280 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
8281 WARN(
"Time information in meteo file does not match filename!");
8283 WARN(
"Time information in meteo file is missing!");
8294 sprintf(tstr,
"19%.2s", &filename[strlen(filename) - 11]);
8296 sprintf(tstr,
"20%.2s", &filename[strlen(filename) - 11]);
8298 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 9]);
8300 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 7]);
8302 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 5]);
8308 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
8309 || day < 1 || day > 31 || hour < 0 || hour > 23)
8310 ERRMSG(
"Cannot read time from filename!");
8311 jsec2time(met->
time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
8312 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
8313 met->
time, year2, mon2, day2, hour2, min2);
8316 if (nc_inq_varid(ncid,
"u", &varid) != NC_NOERR)
8317 if (nc_inq_varid(ncid,
"U", &varid) != NC_NOERR)
8319 (
"Variable 'u' or 'U' not found, cannot determine vertical dimension!");
8321 NC(nc_inq_varndims(ncid, varid, &ndims));
8322 NC(nc_inq_vardimid(ncid, varid, dimids));
8326 (ncid, dimids[ctl->
met_convention == 0 ? 1 : 3], levname, &dimlen));
8327 }
else if (ndims == 3) {
8329 (ncid, dimids[ctl->
met_convention == 0 ? 0 : 2], levname, &dimlen));
8331 ERRMSG(
"Cannot determine vertical dimension!")
8332 met->
np = (int) dimlen;
8334 LOG(2,
"Number of levels: %d", met->
np);
8335 if (met->
np < 2 || met->
np >
EP)
8336 ERRMSG(
"Number of levels out of range!");
8342 LOG(2,
"Number of longitudes: %d", met->
nx);
8345 LOG(2,
"Number of latitudes: %d", met->
ny);
8349 LOG(2,
"Longitudes: %g, %g ... %g deg",
8352 LOG(2,
"Latitudes: %g, %g ... %g deg",
8365 for (
int ip = 0; ip < met->
np; ip++)
8367 LOG(2,
"Altitude levels: %g, %g ... %g km",
8368 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
8369 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
8370 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
8374 if (strcasecmp(levname,
"hybrid") == 0)
8386 ERRMSG(
"You need to specify MET_NLEV, MET_LEV_HYAM, and MET_LEV_HYBM!");
8387 for (
int ip = 0; ip < ctl->
met_nlev; ip++) {
8395 met->
eta[k] = met->
hyam[k] / 100000.0 + met->
hybm[k];
8397 ERRMSG(
"Eta levels must be ascending!");
8401 for (
int ix = 2; ix < met->
nx; ix++)
8403 (fabs(met->
lon[ix] - met->
lon[ix - 1]) -
8404 fabs(met->
lon[1] - met->
lon[0])) > 0.001)
8405 ERRMSG(
"No regular grid spacing in longitudes!");
8406 for (
int iy = 2; iy < met->
ny; iy++)
8408 (fabs(met->
lat[iy] - met->
lat[iy - 1]) -
8409 fabs(met->
lat[1] - met->
lat[0])) > 0.001) {
8410 WARN(
"No regular grid spacing in latitudes!");
8425 LOG(2,
"Read surface data...");
8429 (ncid,
"lnsp",
"LNSP", NULL, NULL, NULL, NULL, ctl, met, dd, met->
ps,
8431 for (
int ix = 0; ix < met->
nx; ix++)
8432 for (
int iy = 0; iy < met->
ny; iy++)
8433 met->
ps[ix][iy] = (
float) (exp(met->
ps[ix][iy]) / 100.);
8436 (ncid,
"ps",
"PS",
"sp",
"SP", NULL, NULL, ctl, met, dd, met->
ps,
8438 WARN(
"Cannot not read surface pressure data (use lowest level)!");
8439 for (
int ix = 0; ix < met->
nx; ix++)
8440 for (
int iy = 0; iy < met->
ny; iy++)
8442 = (ctl->
met_np > 0 ? (
float) ctl->
met_p[0] : (
float) met->
p[0]);
8450 (ncid,
"z",
"Z", NULL, NULL, NULL, NULL, ctl, met, dd, met->
zs,
8451 (
float) (1. / (1000. *
G0)), 1))
8453 (ncid,
"zm",
"ZM", NULL, NULL, NULL, NULL, ctl, met, dd, met->
zs,
8454 (
float) (1. / 1000.), 1))
8455 WARN(
"Cannot read surface geopotential height!");
8466 memcpy(help, met->
pl,
sizeof(met->
pl));
8468 (ncid,
"gph",
"GPH", NULL, NULL, ctl, met, dd, met->
pl,
8469 (
float) (1e-3 /
G0)))
8470 ERRMSG(
"Cannot read geopotential height!");
8471 for (
int ix = 0; ix < met->
nx; ix++)
8472 for (
int iy = 0; iy < met->
ny; iy++)
8473 met->
zs[ix][iy] = met->
pl[ix][iy][0];
8474 memcpy(met->
pl, help,
sizeof(met->
pl));
8480 (ncid,
"t2m",
"T2M",
"2t",
"2T",
"t2",
"T2", ctl, met, dd, met->
ts, 1.0,
8482 WARN(
"Cannot read surface temperature!");
8486 (ncid,
"u10m",
"U10M",
"10u",
"10U",
"u10",
"U10", ctl, met, dd,
8488 WARN(
"Cannot read surface zonal wind!");
8492 (ncid,
"v10m",
"V10M",
"10v",
"10V",
"v10",
"V10", ctl, met, dd,
8494 WARN(
"Cannot read surface meridional wind!");
8498 (ncid,
"iews",
"IEWS", NULL, NULL, NULL, NULL, ctl, met, dd, met->
ess,
8500 WARN(
"Cannot read eastward turbulent surface stress!");
8504 (ncid,
"inss",
"INSS", NULL, NULL, NULL, NULL, ctl, met, dd, met->
nss,
8506 WARN(
"Cannot read nothward turbulent surface stress!");
8510 (ncid,
"ishf",
"ISHF", NULL, NULL, NULL, NULL, ctl, met, dd, met->
shf,
8512 WARN(
"Cannot read surface sensible heat flux!");
8516 (ncid,
"lsm",
"LSM", NULL, NULL, NULL, NULL, ctl, met, dd, met->
lsm,
8518 WARN(
"Cannot read land-sea mask!");
8522 (ncid,
"sstk",
"SSTK",
"sst",
"SST", NULL, NULL, ctl, met, dd, met->
sst,
8524 WARN(
"Cannot read sea surface temperature!");
8529 (ncid,
"blp",
"BLP", NULL, NULL, NULL, NULL, ctl, met, dd, met->
pbl,
8531 WARN(
"Cannot read planetary boundary layer pressure!");
8534 (ncid,
"blh",
"BLH", NULL, NULL, NULL, NULL, ctl, met, dd, met->
pbl,
8536 WARN(
"Cannot read planetary boundary layer height!");
8541 (ncid,
"cape",
"CAPE", NULL, NULL, NULL, NULL, ctl, met, dd,
8543 WARN(
"Cannot read CAPE!");
8548 (ncid,
"cin",
"CIN", NULL, NULL, NULL, NULL, ctl, met, dd, met->
cin,
8550 WARN(
"Cannot read convective inhibition!");
8562 SELECT_TIMER(
"READ_MET_NC_LEVELS",
"INPUT", NVTX_READ);
8563 LOG(2,
"Read level data...");
8567 (ncid,
"t",
"T",
"temp",
"TEMP", ctl, met, dd, met->
t, 1.0))
8568 ERRMSG(
"Cannot read temperature!");
8571 if (!
read_met_nc_3d(ncid,
"u",
"U", NULL, NULL, ctl, met, dd, met->
u, 1.0))
8572 ERRMSG(
"Cannot read zonal wind!");
8573 if (!
read_met_nc_3d(ncid,
"v",
"V", NULL, NULL, ctl, met, dd, met->
v, 1.0))
8574 ERRMSG(
"Cannot read meridional wind!");
8576 (ncid,
"w",
"W",
"omega",
"OMEGA", ctl, met, dd, met->
w, 0.01f))
8577 WARN(
"Cannot read vertical velocity!");
8582 (ncid,
"q",
"Q",
"sh",
"SH", ctl, met, dd, met->
h2o,
8584 WARN(
"Cannot read specific humidity!");
8587 (ncid,
"rh",
"RH", NULL, NULL, ctl, met, dd, met->
h2o, 0.01f))
8588 WARN(
"Cannot read relative humidity!");
8589#pragma omp parallel for default(shared) collapse(2)
8590 for (
int ix = 0; ix < met->
nx; ix++)
8591 for (
int iy = 0; iy < met->
ny; iy++)
8592 for (
int ip = 0; ip < met->
np; ip++) {
8593 double pw = met->
h2o[ix][iy][ip] *
PSAT(met->
t[ix][iy][ip]);
8594 met->
h2o[ix][iy][ip] =
8595 (float) (pw / (met->
p[ip] - (1.0 -
EPS) * pw));
8601 (ncid,
"o3",
"O3", NULL, NULL, ctl, met, dd, met->
o3,
8602 (
float) (
MA /
MO3)))
8603 WARN(
"Cannot read ozone data!");
8607 (ncid,
"clwc",
"CLWC", NULL, NULL, ctl, met, dd, met->
lwc, 1.0))
8608 WARN(
"Cannot read cloud liquid water content!");
8610 (ncid,
"crwc",
"CRWC", NULL, NULL, ctl, met, dd, met->
rwc, 1.0))
8611 WARN(
"Cannot read cloud rain water content!");
8613 (ncid,
"ciwc",
"CIWC", NULL, NULL, ctl, met, dd, met->
iwc, 1.0))
8614 WARN(
"Cannot read cloud ice water content!");
8616 (ncid,
"cswc",
"CSWC", NULL, NULL, ctl, met, dd, met->
swc, 1.0))
8617 WARN(
"Cannot read cloud snow water content!");
8619 (ncid,
"cc",
"CC", NULL, NULL, ctl, met, dd, met->
cc, 1.0))
8620 WARN(
"Cannot read cloud cover!");
8625 (ncid,
"ZETA",
"zeta", NULL, NULL, ctl, met, dd, met->
zetal, 1.0))
8626 WARN(
"Cannot read ZETA!");
8628 (ncid,
"ZETA_DOT_TOT",
"ZETA_DOT_clr",
"zeta_dot_clr",
8629 NULL, ctl, met, dd, met->
zeta_dotl, 0.00001157407f))
8630 WARN(
"Cannot read ZETA_DOT!");
8635#pragma omp parallel for default(shared)
8636 for (
int ix = 0; ix < met->
nx; ix++)
8637 for (
int iy = 0; iy < met->
ny; iy++)
8638 for (
int ip = 0; ip < met->
np; ip++)
8639 met->
zetal[ix][iy][ip] =
8640 (
float) (met->
hyam[ip] / 100000.0 + met->
hybm[ip]);
8642 (ncid,
"etadot",
"ETADOT", NULL, NULL, ctl, met, dd, met->
zeta_dotl,
8644 WARN(
"Cannot read eta vertical velocity!");
8649#pragma omp parallel for default(shared)
8650 for (
int ix = 0; ix < met->
nx; ix++)
8651 for (
int iy = 0; iy < met->
ny; iy++)
8652 for (
int ip = 0; ip < met->
np; ip++) {
8653 met->
ul[ix][iy][ip] = met->
u[ix][iy][ip];
8654 met->
vl[ix][iy][ip] = met->
v[ix][iy][ip];
8655 met->
wl[ix][iy][ip] = met->
w[ix][iy][ip];
8668 (ncid,
"pl",
"PL",
"pressure",
"PRESSURE", ctl, met, dd, met->
pl,
8671 (ncid,
"press",
"PRESS", NULL, NULL, ctl, met, dd, met->
pl, 1.0))
8672 ERRMSG(
"Cannot read pressure on model levels!");
8680 ERRMSG(
"Mismatch in number of model levels!");
8683 for (
int ix = 0; ix < met->
nx; ix++)
8684 for (
int iy = 0; iy < met->
ny; iy++)
8685 for (
int ip = 0; ip < met->
np; ip++)
8686 met->
pl[ix][iy][ip] =
8687 (
float) (met->
hyam[ip] / 100. +
8688 met->
hybm[ip] * met->
ps[ix][iy]);
8696 ERRMSG(
"Mismatch in number of model levels!");
8699#pragma omp parallel for default(shared) collapse(2)
8700 for (
int ix = 0; ix < met->
nx; ix++)
8701 for (
int iy = 0; iy < met->
ny; iy++)
8702 for (
int ip = 0; ip < met->
np; ip++) {
8704 met->
hyam[ip] / 100. + met->
hybm[ip] * met->
ps[ix][iy];
8706 met->
hyam[ip + 1] / 100. + met->
hybm[ip + 1] * met->
ps[ix][iy];
8707 met->
pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
8712 for (
int ix = 0; ix < met->
nx; ix++)
8713 for (
int iy = 0; iy < met->
ny; iy++)
8714 for (
int ip = 1; ip < met->
np; ip++)
8715 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
8716 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
8717 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
8718 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip]))
8719 ERRMSG(
"Pressure profiles are not monotonic!");
8740 for (
int ip = 0; ip < met->
np; ip++)
8741 met->
p[ip] = ctl->
met_p[ip];
8745 for (
int ip = 1; ip < met->
np; ip++)
8746 if (met->
p[ip - 1] < met->
p[ip])
8747 ERRMSG(
"Pressure levels must be descending!");
8754 const char *varname,
8755 const char *varname2,
8756 const char *varname3,
8757 const char *varname4,
8758 const char *varname5,
8759 const char *varname6,
8769 float offset, scalfac;
8774 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
8775 sprintf(varsel,
"%s", varname);
8776 else if (varname2 != NULL
8777 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
8778 sprintf(varsel,
"%s", varname2);
8779 else if (varname3 != NULL
8780 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
8781 sprintf(varsel,
"%s", varname3);
8782 else if (varname4 != NULL
8783 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
8784 sprintf(varsel,
"%s", varname4);
8785 else if (varname5 != NULL
8786 && nc_inq_varid(ncid, varname5, &varid) == NC_NOERR)
8787 sprintf(varsel,
"%s", varname5);
8788 else if (varname6 != NULL
8789 && nc_inq_varid(ncid, varname6, &varid) == NC_NOERR)
8790 sprintf(varsel,
"%s", varname6);
8796 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
8797 && nc_get_att_float(ncid, varid,
"scale_factor",
8798 &scalfac) == NC_NOERR) {
8806 short fillval, missval;
8807 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8809 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8813 LOG(2,
"Read 2-D variable: %s"
8814 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
8815 varsel, fillval, missval, scalfac, offset);
8818 NC(nc_get_var_short(ncid, varid, help));
8822 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
8826#pragma omp parallel for default(shared)
8827 for (
int ix = 0; ix < met->
nx; ix++)
8828 for (
int iy = 0; iy < met->
ny; iy++) {
8831 const short aux = help[
ARRAY_2D(iy, ix, met->
nx)];
8832 if ((fillval == 0 || aux != fillval)
8833 && (missval == 0 || aux != missval)
8834 && fabsf(aux * scalfac + offset) < 1e14f)
8835 dest[ix][iy] += scl * (aux * scalfac + offset);
8846 else if (!ctl->
dd) {
8854 float fillval, missval;
8855 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8857 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8861 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
8862 varsel, fillval, missval);
8865 NC(nc_get_var_float(ncid, varid, help));
8872#pragma omp parallel for default(shared)
8873 for (
int ix = 0; ix < met->
nx; ix++)
8874 for (
int iy = 0; iy < met->
ny; iy++) {
8877 const float aux = help[
ARRAY_2D(iy, ix, met->
nx)];
8878 if ((fillval == 0 || aux != fillval)
8879 && (missval == 0 || aux != missval)
8880 && fabsf(aux) < 1e14f)
8881 dest[ix][iy] += scl * aux;
8891#pragma omp parallel for default(shared)
8892 for (
int iy = 0; iy < met->
ny; iy++)
8893 for (
int ix = 0; ix < met->
nx; ix++) {
8896 const float aux = help[
ARRAY_2D(ix, iy, met->
ny)];
8897 if ((fillval == 0 || aux != fillval)
8898 && (missval == 0 || aux != missval)
8899 && fabsf(aux) < 1e14f)
8900 dest[ix][iy] += scl * aux;
8915 float fillval, missval;
8916 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8918 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8922 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
8923 varsel, fillval, missval);
8927 size_t help_subdomain_start[3];
8928 size_t help_subdomain_count[3];
8930 help_subdomain_start[0] = 0;
8934 help_subdomain_count[0] = 1;
8943 NC(nc_get_vara_float
8944 (ncid, varid, help_subdomain_start, help_subdomain_count, help));
8947 size_t help_halo_bnd_start[3];
8948 size_t help_halo_bnd_count[3];
8950 help_halo_bnd_start[0] = 0;
8954 help_halo_bnd_count[0] = 1;
8959 ALLOC(help_halo,
float,
8960 help_halo_bnd_count[1] * help_halo_bnd_count[2]);
8961 NC(nc_get_vara_float
8962 (ncid, varid, help_halo_bnd_start, help_halo_bnd_count, help_halo));
8967#pragma omp parallel for default(shared) num_threads(12)
8968 for (
int ix = 0; ix < (int) help_subdomain_count[2]; ix++)
8969 for (
int iy = 0; iy < (int) help_subdomain_count[1]; iy++) {
8973 help[
ARRAY_2D(iy, ix, (
int) help_subdomain_count[2])];
8974 if ((fillval == 0 || aux != fillval)
8975 && (missval == 0 || aux != missval)
8976 && fabsf(aux) < 1e14f) {
8983#pragma omp parallel for default(shared) num_threads(12)
8984 for (
int ix = 0; ix < (int) help_halo_bnd_count[2]; ix++)
8985 for (
int iy = 0; iy < (int) help_halo_bnd_count[1]; iy++) {
8989 help_halo[
ARRAY_2D(iy, ix, (
int) help_halo_bnd_count[2])];
8990 if ((fillval == 0 || aux != fillval)
8991 && (missval == 0 || aux != missval)
8992 && fabsf(aux) < 1e14f)
9000 ERRMSG(
"Domain decomposition with data convection incompatible!");
9016 const char *varname,
9017 const char *varname2,
9018 const char *varname3,
9019 const char *varname4,
9030 float offset, scalfac;
9035 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
9036 sprintf(varsel,
"%s", varname);
9037 else if (varname2 != NULL
9038 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
9039 sprintf(varsel,
"%s", varname2);
9040 else if (varname3 != NULL
9041 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
9042 sprintf(varsel,
"%s", varname3);
9043 else if (varname4 != NULL
9044 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
9045 sprintf(varsel,
"%s", varname4);
9050 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
9051 && nc_get_att_float(ncid, varid,
"scale_factor",
9052 &scalfac) == NC_NOERR) {
9060 short fillval, missval;
9061 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9063 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9067 LOG(2,
"Read 3-D variable: %s "
9068 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
9069 varsel, fillval, missval, scalfac, offset);
9072 NC(nc_get_var_short(ncid, varid, help));
9076 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
9080#pragma omp parallel for default(shared)
9081 for (
int ix = 0; ix < met->
nx; ix++)
9082 for (
int iy = 0; iy < met->
ny; iy++)
9083 for (
int ip = 0; ip < met->
np; ip++) {
9084 const short aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
9085 if ((fillval == 0 || aux != fillval)
9086 && (missval == 0 || aux != missval)
9087 && fabsf(aux * scalfac + offset) < 1e14f)
9088 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
9090 dest[ix][iy][ip] = NAN;
9099 else if (!ctl->
dd) {
9107 float fillval, missval;
9108 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9110 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9114 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
9115 varsel, fillval, missval);
9118 NC(nc_get_var_float(ncid, varid, help));
9125#pragma omp parallel for default(shared)
9126 for (
int ix = 0; ix < met->
nx; ix++)
9127 for (
int iy = 0; iy < met->
ny; iy++)
9128 for (
int ip = 0; ip < met->
np; ip++) {
9129 const float aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
9130 if ((fillval == 0 || aux != fillval)
9131 && (missval == 0 || aux != missval)
9132 && fabsf(aux) < 1e14f)
9133 dest[ix][iy][ip] = scl * aux;
9135 dest[ix][iy][ip] = NAN;
9143#pragma omp parallel for default(shared)
9144 for (
int ip = 0; ip < met->
np; ip++)
9145 for (
int iy = 0; iy < met->
ny; iy++)
9146 for (
int ix = 0; ix < met->
nx; ix++) {
9147 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9148 if ((fillval == 0 || aux != fillval)
9149 && (missval == 0 || aux != missval)
9150 && fabsf(aux) < 1e14f)
9151 dest[ix][iy][ip] = scl * aux;
9153 dest[ix][iy][ip] = NAN;
9166 float fillval, missval;
9167 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9169 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9173 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
9174 varsel, fillval, missval);
9176 SELECT_TIMER(
"read_met_nc_3d_CP1",
"INPUT", NVTX_READ);
9186 SELECT_TIMER(
"read_met_nc_3d_CP2",
"INPUT", NVTX_READ);
9189 NC(nc_get_vara_float
9194 ALLOC(help_halo,
float,
9198 SELECT_TIMER(
"read_met_nc_3d_CP3",
"INPUT", NVTX_READ);
9201 NC(nc_get_vara_float(ncid,
9205 SELECT_TIMER(
"read_met_nc_3d_CP4",
"INPUT", NVTX_READ);
9210#pragma omp parallel for default(shared) num_threads(12)
9213 for (
int ip = 0; ip < met->
np; ip++) {
9217 if ((fillval == 0 || aux != fillval)
9218 && (missval == 0 || aux != missval)
9219 && fabsf(aux) < 1e14f)
9225#pragma omp parallel for default(shared) num_threads(12)
9228 for (
int ip = 0; ip < met->
np; ip++) {
9232 if ((fillval == 0 || aux != fillval)
9233 && (missval == 0 || aux != missval)
9234 && fabsf(aux) < 1e14f)
9243#pragma omp parallel for default(shared) num_threads(12)
9244 for (
int ip = 0; ip < met->
np; ip++)
9247 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9248 if ((fillval == 0 || aux != fillval)
9249 && (missval == 0 || aux != missval)
9250 && fabsf(aux) < 1e14f)
9256#pragma omp parallel for default(shared) num_threads(12)
9257 for (
int ip = 0; ip < met->
np; ip++)
9260 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9261 if ((fillval == 0 || aux != fillval)
9262 && (missval == 0 || aux != missval)
9263 && fabsf(aux) < 1e14f)
9283 const char *filename,
9288 size_t filename_len = strlen(filename) + 1;
9289 char sf_filename[filename_len];
9290 char ml_filename[filename_len];
9291 strcpy(sf_filename, filename);
9292 strcpy(ml_filename, filename);
9297 FILE *ml_file = fopen(ml_filename,
"rb");
9298 FILE *sf_file = fopen(sf_filename,
"rb");
9299 if (ml_file == NULL || sf_file == NULL) {
9300 if (ml_file != NULL) {
9302 WARN(
"Cannot open file: %s", sf_filename);
9304 if (sf_file != NULL) {
9306 WARN(
"Cannot open file: %s", ml_filename);
9312 int ml_num_messages = 0, err = 0;
9313 ECC(codes_count_in_file(0, ml_file, &ml_num_messages));
9316 (size_t) ml_num_messages);
9317 for (
int i = 0; i < ml_num_messages; i++) {
9319 if ((h = codes_grib_handle_new_from_file(0, ml_file, &err)) != NULL)
9324 int sf_num_messages = 0;
9325 ECC(codes_count_in_file(0, sf_file, &sf_num_messages));
9328 (size_t) sf_num_messages);
9329 for (
int i = 0; i < sf_num_messages; i++) {
9331 if ((h = codes_grib_handle_new_from_file(0, sf_file, &err)) != NULL)
9344 for (
int i = 0; i < sf_num_messages; i++)
9345 codes_handle_delete(sf_handles[i]);
9349 size_t value_count = 0;
9350 ECC(codes_get_size(ml_handles[0],
"pv", &value_count));
9351 if (value_count % 2 != 0)
9352 ERRMSG(
"Unexpected pv array length!");
9353 size_t nlevels = value_count / 2 - 1;
9355 ALLOC(values,
double,
9357 ECC(codes_get_double_array(ml_handles[0],
"pv", values, &value_count));
9358 double *a_vals = values;
9359 double *b_vals = values + nlevels;
9360 if (met->
npl > (
int) nlevels)
9361 ERRMSG(
"met->npl exceeds number of pressure levels in GRIB!");
9362 for (
int nx = 0; nx < met->
nx; nx++)
9363 for (
int ny = 0; ny < met->
ny; ny++)
9364 for (
int level = 0; level <= met->
npl; level++) {
9365 const float p1 = (float) (a_vals[level] * 0.01f +
9366 met->
ps[nx][ny] * b_vals[level]);
9367 const float p2 = (float) (a_vals[level + 1] * 0.01f +
9368 met->
ps[nx][ny] * b_vals[level + 1]);
9369 met->
pl[nx][ny][level] = 0.5f * (p1 + p2);
9375 for (
int i = 0; i < ml_num_messages; i++)
9376 codes_handle_delete(ml_handles[i]);
9393 SELECT_TIMER(
"READ_MET_GRIB_GRID",
"INPUT", NVTX_READ);
9394 LOG(2,
"Read meteo grid information...");
9397 char datestr[
LEN], timestr[
LEN];
9398 size_t s_date =
sizeof(datestr);
9399 ECC(codes_get_string(handles[0],
"dataDate", datestr, &s_date));
9400 size_t s_time =
sizeof(timestr);
9401 ECC(codes_get_string(handles[0],
"dataTime", timestr, &s_time));
9402 int year, month, day, hour;
9403 if (sscanf(datestr,
"%4d%2d%2d", &year, &month, &day) != 3)
9404 ERRMSG(
"Failed to parse dataDate: %s", datestr);
9405 if (sscanf(timestr,
"%2d", &hour) != 1)
9406 ERRMSG(
"Failed to parse dataTime: %s", timestr);
9408 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)", met->
time, year, month,
9412 long count_lat = 0, count_lon = 0;
9413 ECC(codes_get_long(handles[0],
"Nj", &count_lat));
9414 ECC(codes_get_long(handles[0],
"Ni", &count_lon));
9415 met->
ny = (int) count_lat;
9416 met->
nx = (int) count_lon;
9419 LOG(2,
"Number of longitudes: %d", met->
nx);
9420 if (met->
nx < 2 || met->
nx >
EX)
9421 ERRMSG(
"Number of longitudes out of range!");
9422 LOG(2,
"Number of latitudes: %d", met->
ny);
9423 if (met->
ny < 2 || met->
ny >
EY)
9424 ERRMSG(
"Number of latitudes out of range!");
9426 double first_lon, last_lon, first_lat, last_lat, inc_lon, inc_lat;
9427 ECC(codes_get_double
9428 (handles[0],
"longitudeOfFirstGridPointInDegrees", &first_lon));
9429 ECC(codes_get_double
9430 (handles[0],
"latitudeOfFirstGridPointInDegrees", &first_lat));
9431 ECC(codes_get_double
9432 (handles[0],
"longitudeOfLastGridPointInDegrees", &last_lon));
9433 ECC(codes_get_double
9434 (handles[0],
"latitudeOfLastGridPointInDegrees", &last_lat));
9435 ECC(codes_get_double(handles[0],
"iDirectionIncrementInDegrees", &inc_lon));
9436 ECC(codes_get_double(handles[0],
"jDirectionIncrementInDegrees", &inc_lat));
9438 long jscanpos, iscanneg;
9439 ECC(codes_get_long(handles[0],
"iScansNegatively", &iscanneg));
9440 ECC(codes_get_long(handles[0],
"jScansPositively", &jscanpos));
9445 for (
double i = first_lon; i <= last_lon + 1e-6; i += inc_lon) {
9446 met->
lon[counter] = i;
9449 for (
double i = first_lon; i > last_lon - 1e-6; i -= inc_lon) {
9450 met->
lon[counter] = i;
9456 for (
double i = first_lat; i > last_lat - 1e-6; i -= inc_lat) {
9457 met->
lat[counter] = i;
9460 for (
double i = first_lat; i <= last_lat + 1e-6; i += inc_lat) {
9461 met->
lat[counter] = i;
9466 LOG(2,
"Longitudes: %g, %g ... %g deg",
9468 LOG(2,
"Latitudes: %g, %g ... %g deg",
9473 for (
int i = 0; i < count_handles; i++) {
9475 ECC(codes_get_long(handles[i],
"level", &level));
9476 if (level > max_level)
9477 max_level = (int) level;
9479 met->
npl = max_level;
9482 LOG(2,
"Number of levels: %d", met->
npl);
9484 ERRMSG(
"Number of levels out of range!");
9493 const int num_messages,
9498 SELECT_TIMER(
"READ_MET_GRIB_LEVELS",
"INPUT", NVTX_READ);
9499 LOG(2,
"Read level data...");
9502 int t_flag = 0, u_flag = 0, v_flag = 0, w_flag = 0, o3_flag = 0, h2o_flag =
9503 0, lwc_flag = 0, rwc_flag = 0, iwc_flag = 0, swc_flag = 0, cc_flag = 0;
9506 for (
int i = 0; i < num_messages; i++) {
9508 size_t max_size =
LEN;
9509 char short_name[max_size];
9515 ECC(codes_get_long(handles[i],
"level", ¤t_level));
9519 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
9520 ECC(codes_get_size(handles[i],
"values", &value_count));
9521 ALLOC(values,
double,
9523 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
9531 ECC_READ_3D(
"w", current_level, met->
w, 0.01f, w_flag);
9549 if (t_flag != met->
npl)
9550 ERRMSG(
"Cannot read temperature!");
9551 if (u_flag != met->
npl)
9552 ERRMSG(
"Cannot read zonal wind!");
9553 if (v_flag != met->
npl)
9554 ERRMSG(
"Cannot read meridional wind!");
9555 if (w_flag != met->
npl)
9556 WARN(
"Cannot read vertical velocity!");
9557 if (h2o_flag != met->
npl)
9558 WARN(
"Cannot read specific humidity!");
9559 if (o3_flag != met->
npl)
9560 WARN(
"Cannot read ozone data!");
9561 if (lwc_flag != met->
npl)
9562 WARN(
"Cannot read cloud liquid water content!");
9563 if (rwc_flag != met->
npl)
9564 WARN(
"Cannot read cloud rain water content!");
9565 if (iwc_flag != met->
npl)
9566 WARN(
"Cannot read cloud ice water content!");
9567 if (swc_flag != met->
npl)
9568 WARN(
"Cannot read cloud snow water content!");
9569 if (cc_flag != met->
npl)
9570 WARN(
"Cannot read cloud cover!");
9573 for (
int ix = 0; ix < met->
nx; ix++)
9574 for (
int iy = 0; iy < met->
ny; iy++)
9575 for (
int ip = 1; ip < met->
np; ip++)
9576 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
9577 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
9578 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
9579 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip])) {
9580 LOG(1,
"%f %f %f %f", met->
pl[ix][iy][0], met->
pl[ix][iy][1],
9581 met->
pl[ix][iy][ip - 1], met->
pl[ix][iy][ip]);
9582 ERRMSG(
"Pressure profiles are not monotonic!");
9603 for (
int ip = 0; ip < met->
np; ip++)
9604 met->
p[ip] = ctl->
met_p[ip];
9608 for (
int ip = 1; ip < met->
np; ip++)
9609 if (met->
p[ip - 1] < met->
p[ip])
9610 ERRMSG(
"Pressure levels must be descending!");
9619 const int num_messages,
9624 SELECT_TIMER(
"READ_MET_GRIB_SURFACE",
"INPUT", NVTX_READ);
9625 LOG(2,
"Read surface data...");
9628 int sp_flag = 0, z_flag = 0, t_flag = 0, u_flag = 0, v_flag = 0, lsm_flag =
9629 0, sst_flag = 0, cape_flag = 0, cin_flag = 0, pbl_flag = 0;
9632 for (
int i = 0; i < num_messages; i++) {
9634 size_t max_size =
LEN, value_count;
9636 char short_name[max_size];
9639 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
9640 ECC(codes_get_size(handles[i],
"values", &value_count));
9641 double *values = (
double *) malloc(value_count *
sizeof(
double));
9642 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
9680 WARN(
"Cannot read surface pressure data!");
9682 WARN(
"Cannot read surface geopotential height!");
9684 WARN(
"Cannot read surface temperature!");
9686 WARN(
"Cannot read surface zonal wind!");
9688 WARN(
"Cannot read surface meridional wind!");
9690 WARN(
"Cannot read land-sea mask!");
9692 WARN(
"Cannot read sea surface temperature!");
9695 WARN(
"Cannot read CAPE!");
9697 WARN(
"Cannot read convective inhibition!");
9699 if (ctl->
met_pbl == 0 && pbl_flag == 0)
9700 WARN(
"Cannot read planetary boundary layer!");
9710 const char *varname) {
9712 double aux[
EP], p[
EP];
9716 LOG(2,
"Interpolate meteo data to pressure levels: %s", varname);
9719#pragma omp parallel for default(shared) private(aux,p) collapse(2)
9720 for (
int ix = 0; ix < met->
nx; ix++)
9721 for (
int iy = 0; iy < met->
ny; iy++) {
9724 for (
int ip = 0; ip < met->
np; ip++)
9725 p[ip] = met->
pl[ix][iy][ip];
9728 for (
int ip = 0; ip < ctl->
met_np; ip++) {
9729 double pt = ctl->
met_p[ip];
9730 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
9732 else if ((pt > p[met->
np - 1] && p[1] > p[0])
9733 || (pt < p[met->
np - 1] && p[1] < p[0]))
9734 pt = p[met->
np - 1];
9736 aux[ip] =
LIN(p[ip2], var[ix][iy][ip2],
9737 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
9741 for (
int ip = 0; ip < ctl->
met_np; ip++)
9742 var[ix][iy][ip] = (
float) aux[ip];
9757 SELECT_TIMER(
"READ_MET_MONOTONIZE",
"METPROC", NVTX_READ);
9758 LOG(2,
"Make zeta profiles monotone...");
9761#pragma omp parallel for default(shared) collapse(2)
9762 for (
int i = 0; i < met->
nx; i++)
9763 for (
int j = 0; j < met->
ny; j++) {
9766 while (k < met->npl) {
9767 if ((met->
zetal[i][j][k - 1] >= met->
zetal[i][j][k])) {
9773 while ((met->
zetal[i][j][k - 1] >=
9774 met->
zetal[i][j][k + l]) & (k + l < met->npl));
9779 (float) (met->
zetal[i][j][k + l] - met->
zetal[i][j][k - 1])
9782 for (
int m = k; m < k + l; m++) {
9783 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
9784 met->
zetal[i][j][m] = s * d + met->
zetal[i][j][k - 1];
9796#pragma omp parallel for default(shared) collapse(2)
9797 for (
int i = 0; i < met->
nx; i++)
9798 for (
int j = 0; j < met->
ny; j++) {
9801 while (k < met->npl) {
9802 if ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k])) {
9809 while ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k + l]) & (k + l <
9814 float s = (float) (met->
pl[i][j][k + l] - met->
pl[i][j][k - 1])
9817 for (
int m = k; m < k + l; m++) {
9818 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
9819 met->
pl[i][j][m] = s * d + met->
pl[i][j][k - 1];
9834 const char *filename,
9845 (filename, NC_NOWRITE | NC_SHARE, MPI_COMM_WORLD, MPI_INFO_NULL,
9849 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
9850 WARN(
"Cannot open file!");
9883 MPI_Comm_rank(MPI_COMM_WORLD, &dd->
rank);
9884 MPI_Comm_size(MPI_COMM_WORLD, &dd->
size);
9892 LOG(2,
"Number of longitudes: %d", help_nx_glob);
9896 LOG(2,
"Number of latitudes: %d", help_ny_glob);
9899 double *help_lon_glob;
9900 double *help_lat_glob;
9901 ALLOC(help_lon_glob,
double,
9903 ALLOC(help_lat_glob,
double,
9908 LOG(2,
"Longitudes: %g, %g ... %g deg",
9909 help_lon_glob[0], help_lon_glob[1], help_lon_glob[help_nx_glob - 1]);
9911 LOG(2,
"Latitudes: %g, %g ... %g deg",
9912 help_lat_glob[0], help_lat_glob[1], help_lat_glob[help_ny_glob - 1]);
9936 met->
nx = met->
nx + gap;
9937 WARN(
"Extended subdomains at the right to fit to full domain.");
9943 met->
ny = met->
ny + gap;
9944 WARN(
"Extended subdomains at the bottom to fit to full domain.");
9955 if (!left && !right) {
9972 if (!top && !bottom) {
9990 double lon_shift = 0;
9991 if (left || right) {
10009 lon_shift = (left ? -360 : 360);
10026 double lon_range = 360;
10037 double lat_range = help_lat_glob[help_ny_glob - 1] - help_lat_glob[0];
10064 if (lat_range < 0) {
10071 (
"lat_range > 0, but is expected to be negative, i.e. latitudes should range from 90 to -90")
10078 LOG(2,
"Total longitude range: %g deg", lon_range);
10079 LOG(2,
"Total latitude range: %g deg", lat_range);
10081 LOG(2,
"Define subdomain properties.");
10082 LOG(2,
"MPI information: Rank %d, Size %d", dd->
rank, dd->
size);
10083 LOG(2,
"Edge position: l=%d,r=%d,t=%d, b=%d", (
int) left, (
int) right,
10084 (
int) top, (
int) bottom);
10085 LOG(2,
"Sizes for limits: EX %d EY %d EP %d",
EX,
EY,
EP);
10086 LOG(2,
"Total size for subdomain meteo data: nx %d ny %d np %d", met->
nx,
10088 LOG(2,
"Hyperslab sizes for boundary halos: nx %d ny %d np %d",
10091 LOG(2,
"Hyperslab sizes for subdomain and inner halos: nx %d ny %d np %d",
10100 LOG(2,
" %d Subdomain longitudes: %g, %g ... %g deg (edges: %g to %g)",
10103 LOG(2,
" %d Subdomain latitudes: %g, %g ... %g deg (edges: %g to %g)",
10107 free(help_lon_glob);
10108 free(help_lat_glob);
10119 LOG(2,
"Calculate planetary boundary layer...");
10125#pragma omp parallel for default(shared) collapse(2)
10126 for (
int ix = 0; ix < met->
nx; ix++)
10127 for (
int iy = 0; iy < met->
ny; iy++) {
10130 const float z = met->
zs[ix][iy] + met->
pbl[ix][iy];
10133 (float) (
LIN(met->
z[ix][iy][ip], met->
p[ip],
10134 met->
z[ix][iy][ip + 1], met->
p[ip + 1], z));
10139 else if (ctl->
met_pbl == 2) {
10143 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
10146#pragma omp parallel for default(shared) collapse(2)
10147 for (
int ix = 0; ix < met->
nx; ix++)
10148 for (
int iy = 0; iy < met->
ny; iy++) {
10151 const double pbl_bot = met->
ps[ix][iy] * exp(-dz /
H0);
10155 for (ip = 1; ip < met->
np; ip++)
10156 if (met->
p[ip] < pbl_bot)
10160 const double h2os =
LIN(met->
p[ip - 1], met->
h2o[ix][iy][ip - 1],
10161 met->
p[ip], met->
h2o[ix][iy][ip], pbl_bot);
10162 const double tvs =
THETAVIRT(pbl_bot, met->
ts[ix][iy], h2os);
10165 double rib_old = 0;
10168 for (; ip < met->
np; ip++) {
10171 double vh2 =
SQR(met->
u[ix][iy][ip] - met->
us[ix][iy])
10172 +
SQR(met->
v[ix][iy][ip] - met->
vs[ix][iy]);
10173 vh2 =
MAX(vh2,
SQR(umin));
10177 G0 * 1e3 * (met->
z[ix][iy][ip] - met->
zs[ix][iy]) / tvs
10179 met->
h2o[ix][iy][ip]) - tvs) / vh2;
10182 if (rib >= rib_crit) {
10183 met->
pbl[ix][iy] = (float) (
LIN(rib_old, met->
p[ip - 1],
10184 rib, met->
p[ip], rib_crit));
10185 if (met->
pbl[ix][iy] > pbl_bot)
10186 met->
pbl[ix][iy] = (float) pbl_bot;
10201 const double dtheta = 2.0, zmin = 0.1;
10204#pragma omp parallel for default(shared) collapse(2)
10205 for (
int ix = 0; ix < met->
nx; ix++)
10206 for (
int iy = 0; iy < met->
ny; iy++) {
10209 const double theta0 =
THETA(met->
ps[ix][iy], met->
ts[ix][iy]);
10213 for (ip = met->
np - 2; ip > 0; ip--)
10214 if (met->
p[ip] >= 300.)
10215 if (met->
p[ip] > met->
ps[ix][iy]
10216 ||
THETA(met->
p[ip], met->
t[ix][iy][ip]) <= theta0 + dtheta)
10221 = (float) (
LIN(
THETA(met->
p[ip + 1], met->
t[ix][iy][ip + 1]),
10223 THETA(met->
p[ip], met->
t[ix][iy][ip]),
10224 met->
p[ip], theta0 + dtheta));
10227 double pbl_min = met->
ps[ix][iy] * exp(-zmin /
H0);
10228 if (met->
pbl[ix][iy] > pbl_min || met->
p[ip] > met->
ps[ix][iy])
10229 met->
pbl[ix][iy] = (float) pbl_min;
10234#pragma omp parallel for default(shared) collapse(2)
10235 for (
int ix = 0; ix < met->
nx; ix++)
10236 for (
int iy = 0; iy < met->
ny; iy++) {
10240 met->
pbl[ix][iy] =
MIN(met->
pbl[ix][iy], (
float) pbl_min);
10244 met->
pbl[ix][iy] =
MAX(met->
pbl[ix][iy], (
float) pbl_max);
10254 SELECT_TIMER(
"READ_MET_PERIODIC",
"METPROC", NVTX_READ);
10255 LOG(2,
"Apply periodic boundary conditions...");
10258 if (!(fabs(met->
lon[met->
nx - 1] - met->
lon[0]
10259 + met->
lon[1] - met->
lon[0] - 360) < 0.01))
10263 if ((++met->
nx) >=
EX)
10264 ERRMSG(
"Cannot create periodic boundary conditions!");
10267 met->
lon[met->
nx - 1] = met->
lon[met->
nx - 2] + met->
lon[1] - met->
lon[0];
10270#pragma omp parallel for default(shared)
10271 for (
int iy = 0; iy < met->
ny; iy++) {
10272 met->
ps[met->
nx - 1][iy] = met->
ps[0][iy];
10273 met->
zs[met->
nx - 1][iy] = met->
zs[0][iy];
10274 met->
ts[met->
nx - 1][iy] = met->
ts[0][iy];
10275 met->
us[met->
nx - 1][iy] = met->
us[0][iy];
10276 met->
vs[met->
nx - 1][iy] = met->
vs[0][iy];
10277 met->
ess[met->
nx - 1][iy] = met->
ess[0][iy];
10278 met->
nss[met->
nx - 1][iy] = met->
nss[0][iy];
10279 met->
shf[met->
nx - 1][iy] = met->
shf[0][iy];
10280 met->
lsm[met->
nx - 1][iy] = met->
lsm[0][iy];
10281 met->
sst[met->
nx - 1][iy] = met->
sst[0][iy];
10282 met->
pbl[met->
nx - 1][iy] = met->
pbl[0][iy];
10283 met->
cape[met->
nx - 1][iy] = met->
cape[0][iy];
10284 met->
cin[met->
nx - 1][iy] = met->
cin[0][iy];
10285 for (
int ip = 0; ip < met->
np; ip++) {
10286 met->
t[met->
nx - 1][iy][ip] = met->
t[0][iy][ip];
10287 met->
u[met->
nx - 1][iy][ip] = met->
u[0][iy][ip];
10288 met->
v[met->
nx - 1][iy][ip] = met->
v[0][iy][ip];
10289 met->
w[met->
nx - 1][iy][ip] = met->
w[0][iy][ip];
10290 met->
h2o[met->
nx - 1][iy][ip] = met->
h2o[0][iy][ip];
10291 met->
o3[met->
nx - 1][iy][ip] = met->
o3[0][iy][ip];
10292 met->
lwc[met->
nx - 1][iy][ip] = met->
lwc[0][iy][ip];
10293 met->
rwc[met->
nx - 1][iy][ip] = met->
rwc[0][iy][ip];
10294 met->
iwc[met->
nx - 1][iy][ip] = met->
iwc[0][iy][ip];
10295 met->
swc[met->
nx - 1][iy][ip] = met->
swc[0][iy][ip];
10296 met->
cc[met->
nx - 1][iy][ip] = met->
cc[0][iy][ip];
10298 for (
int ip = 0; ip < met->
npl; ip++) {
10299 met->
ul[met->
nx - 1][iy][ip] = met->
ul[0][iy][ip];
10300 met->
vl[met->
nx - 1][iy][ip] = met->
vl[0][iy][ip];
10301 met->
wl[met->
nx - 1][iy][ip] = met->
wl[0][iy][ip];
10302 met->
pl[met->
nx - 1][iy][ip] = met->
pl[0][iy][ip];
10303 met->
zetal[met->
nx - 1][iy][ip] = met->
zetal[0][iy][ip];
10315 SELECT_TIMER(
"READ_MET_POLAR_WINDS",
"METPROC", NVTX_READ);
10316 LOG(2,
"Apply fix for polar winds...");
10319 if (fabs(met->
lat[0]) < 89.999 || fabs(met->
lat[met->
ny - 1]) < 89.999)
10323 for (
int ihem = 0; ihem < 2; ihem++) {
10326 int i89 = 1, i90 = 0, sign = 1;
10331 if (met->
lat[i90] < 0)
10335 double clon[
EX], slon[
EX];
10336#pragma omp parallel for default(shared)
10337 for (
int ix = 0; ix < met->
nx; ix++) {
10338 clon[ix] = cos(sign *
DEG2RAD(met->
lon[ix]));
10339 slon[ix] = sin(sign *
DEG2RAD(met->
lon[ix]));
10343#pragma omp parallel for default(shared)
10344 for (
int ip = 0; ip < met->
np; ip++) {
10347 double vel89x = 0, vel89y = 0;
10348 for (
int ix = 0; ix < met->
nx; ix++) {
10350 (met->
u[ix][i89][ip] * clon[ix] -
10351 met->
v[ix][i89][ip] * slon[ix]) / met->
nx;
10353 (met->
u[ix][i89][ip] * slon[ix] +
10354 met->
v[ix][i89][ip] * clon[ix]) / met->
nx;
10358 for (
int ix = 0; ix < met->
nx; ix++) {
10359 met->
u[ix][i90][ip]
10360 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
10361 met->
v[ix][i90][ip]
10362 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
10377 LOG(2,
"Calculate potential vorticity...");
10380#pragma omp parallel for default(shared)
10381 for (
int ip = 0; ip < met->
np; ip++)
10382 pows[ip] = pow(1000. / met->
p[ip], 0.286);
10385#pragma omp parallel for default(shared)
10386 for (
int ix = 0; ix < met->
nx; ix++) {
10389 const int ix0 =
MAX(ix - 1, 0);
10390 const int ix1 =
MIN(ix + 1, met->
nx - 1);
10393 for (
int iy = 0; iy < met->
ny; iy++) {
10396 const int iy0 =
MAX(iy - 1, 0);
10397 const int iy1 =
MIN(iy + 1, met->
ny - 1);
10400 const double latr = 0.5 * (met->
lat[iy1] + met->
lat[iy0]);
10401 const double dx = 1000. *
DEG2DX(met->
lon[ix1] - met->
lon[ix0], latr);
10402 const double dy = 1000. *
DEG2DY(met->
lat[iy1] - met->
lat[iy0]);
10403 const double c0 = cos(
DEG2RAD(met->
lat[iy0]));
10404 const double c1 = cos(
DEG2RAD(met->
lat[iy1]));
10405 const double cr = cos(
DEG2RAD(latr));
10406 const double vort = 2 * 7.2921e-5 * sin(
DEG2RAD(latr));
10409 for (
int ip = 0; ip < met->
np; ip++) {
10413 = (met->
t[ix1][iy][ip] - met->
t[ix0][iy][ip]) * pows[ip] / dx;
10414 const double dvdx = (met->
v[ix1][iy][ip] - met->
v[ix0][iy][ip]) / dx;
10418 = (met->
t[ix][iy1][ip] - met->
t[ix][iy0][ip]) * pows[ip] / dy;
10420 = (met->
u[ix][iy1][ip] * c1 - met->
u[ix][iy0][ip] * c0) / dy;
10423 const int ip0 =
MAX(ip - 1, 0);
10424 const int ip1 =
MIN(ip + 1, met->
np - 1);
10427 double dtdp, dudp, dvdp;
10428 const double dp0 = 100. * (met->
p[ip] - met->
p[ip0]);
10429 const double dp1 = 100. * (met->
p[ip1] - met->
p[ip]);
10430 if (ip != ip0 && ip != ip1) {
10431 double denom = dp0 * dp1 * (dp0 + dp1);
10432 dtdp = (dp0 * dp0 * met->
t[ix][iy][ip1] * pows[ip1]
10433 - dp1 * dp1 * met->
t[ix][iy][ip0] * pows[ip0]
10434 + (dp1 * dp1 - dp0 * dp0) * met->
t[ix][iy][ip] * pows[ip])
10436 dudp = (dp0 * dp0 * met->
u[ix][iy][ip1]
10437 - dp1 * dp1 * met->
u[ix][iy][ip0]
10438 + (dp1 * dp1 - dp0 * dp0) * met->
u[ix][iy][ip])
10440 dvdp = (dp0 * dp0 * met->
v[ix][iy][ip1]
10441 - dp1 * dp1 * met->
v[ix][iy][ip0]
10442 + (dp1 * dp1 - dp0 * dp0) * met->
v[ix][iy][ip])
10445 const double denom = dp0 + dp1;
10447 (met->
t[ix][iy][ip1] * pows[ip1] -
10448 met->
t[ix][iy][ip0] * pows[ip0]) / denom;
10449 dudp = (met->
u[ix][iy][ip1] - met->
u[ix][iy][ip0]) / denom;
10450 dvdp = (met->
v[ix][iy][ip1] - met->
v[ix][iy][ip0]) / denom;
10454 met->
pv[ix][iy][ip] = (float)
10456 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
10462#pragma omp parallel for default(shared)
10463 for (
int ix = 0; ix < met->
nx; ix++)
10464 for (
int ip = 0; ip < met->
np; ip++) {
10466 = met->
pv[ix][1][ip]
10467 = met->
pv[ix][2][ip];
10468 met->
pv[ix][met->
ny - 1][ip]
10469 = met->
pv[ix][met->
ny - 2][ip]
10470 = met->
pv[ix][met->
ny - 3][ip];
10481 LOG(2,
"Calculate total column ozone...");
10484#pragma omp parallel for default(shared) collapse(2)
10485 for (
int ix = 0; ix < met->
nx; ix++)
10486 for (
int iy = 0; iy < met->
ny; iy++) {
10490 for (
int ip = 1; ip < met->
np; ip++)
10491 if (met->
p[ip - 1] <= met->
ps[ix][iy]) {
10493 0.5 * (met->
o3[ix][iy][ip - 1] + met->
o3[ix][iy][ip]);
10494 const double dp = met->
p[ip - 1] - met->
p[ip];
10495 cd += vmr *
MO3 /
MA * dp * 1e2 /
G0;
10499 met->
o3c[ix][iy] = (float) (cd / 2.1415e-5);
10517 SELECT_TIMER(
"READ_MET_SAMPLE",
"METPROC", NVTX_READ);
10518 LOG(2,
"Downsampling of meteo data...");
10524 help->
nx = met->
nx;
10525 help->
ny = met->
ny;
10526 help->
np = met->
np;
10527 memcpy(help->
lon, met->
lon,
sizeof(met->
lon));
10528 memcpy(help->
lat, met->
lat,
sizeof(met->
lat));
10529 memcpy(help->
p, met->
p,
sizeof(met->
p));
10532 for (
int ix = 0; ix < met->
nx; ix += ctl->
met_dx) {
10533 for (
int iy = 0; iy < met->
ny; iy += ctl->
met_dy) {
10534 for (
int ip = 0; ip < met->
np; ip += ctl->
met_dp) {
10535 help->
ps[ix][iy] = 0;
10536 help->
zs[ix][iy] = 0;
10537 help->
ts[ix][iy] = 0;
10538 help->
us[ix][iy] = 0;
10539 help->
vs[ix][iy] = 0;
10540 help->
ess[ix][iy] = 0;
10541 help->
nss[ix][iy] = 0;
10542 help->
shf[ix][iy] = 0;
10543 help->
lsm[ix][iy] = 0;
10544 help->
sst[ix][iy] = 0;
10545 help->
pbl[ix][iy] = 0;
10546 help->
cape[ix][iy] = 0;
10547 help->
cin[ix][iy] = 0;
10548 help->
t[ix][iy][ip] = 0;
10549 help->
u[ix][iy][ip] = 0;
10550 help->
v[ix][iy][ip] = 0;
10551 help->
w[ix][iy][ip] = 0;
10552 help->
h2o[ix][iy][ip] = 0;
10553 help->
o3[ix][iy][ip] = 0;
10554 help->
lwc[ix][iy][ip] = 0;
10555 help->
rwc[ix][iy][ip] = 0;
10556 help->
iwc[ix][iy][ip] = 0;
10557 help->
swc[ix][iy][ip] = 0;
10558 help->
cc[ix][iy][ip] = 0;
10560 for (
int ix2 = ix - ctl->
met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
10565 else if (ix3 >= met->
nx)
10568 for (
int iy2 =
MAX(iy - ctl->
met_sy + 1, 0);
10569 iy2 <=
MIN(iy + ctl->
met_sy - 1, met->
ny - 1); iy2++)
10570 for (
int ip2 =
MAX(ip - ctl->
met_sp + 1, 0);
10571 ip2 <=
MIN(ip + ctl->
met_sp - 1, met->
np - 1); ip2++) {
10573 (1.0f - (float) abs(ix - ix2) / (float) ctl->
met_sx)
10574 * (1.0f - (float) abs(iy - iy2) / (float) ctl->
met_sy)
10575 * (1.0f - (float) abs(ip - ip2) / (float) ctl->
met_sp);
10576 help->
ps[ix][iy] += w * met->
ps[ix3][iy2];
10577 help->
zs[ix][iy] += w * met->
zs[ix3][iy2];
10578 help->
ts[ix][iy] += w * met->
ts[ix3][iy2];
10579 help->
us[ix][iy] += w * met->
us[ix3][iy2];
10580 help->
vs[ix][iy] += w * met->
vs[ix3][iy2];
10581 help->
ess[ix][iy] += w * met->
ess[ix3][iy2];
10582 help->
nss[ix][iy] += w * met->
nss[ix3][iy2];
10583 help->
shf[ix][iy] += w * met->
shf[ix3][iy2];
10584 help->
lsm[ix][iy] += w * met->
lsm[ix3][iy2];
10585 help->
sst[ix][iy] += w * met->
sst[ix3][iy2];
10586 help->
pbl[ix][iy] += w * met->
pbl[ix3][iy2];
10587 help->
cape[ix][iy] += w * met->
cape[ix3][iy2];
10588 help->
cin[ix][iy] += w * met->
cin[ix3][iy2];
10589 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip2];
10590 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip2];
10591 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip2];
10592 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip2];
10593 help->
h2o[ix][iy][ip] += w * met->
h2o[ix3][iy2][ip2];
10594 help->
o3[ix][iy][ip] += w * met->
o3[ix3][iy2][ip2];
10595 help->
lwc[ix][iy][ip] += w * met->
lwc[ix3][iy2][ip2];
10596 help->
rwc[ix][iy][ip] += w * met->
rwc[ix3][iy2][ip2];
10597 help->
iwc[ix][iy][ip] += w * met->
iwc[ix3][iy2][ip2];
10598 help->
swc[ix][iy][ip] += w * met->
swc[ix3][iy2][ip2];
10599 help->
cc[ix][iy][ip] += w * met->
cc[ix3][iy2][ip2];
10603 help->
ps[ix][iy] /= wsum;
10604 help->
zs[ix][iy] /= wsum;
10605 help->
ts[ix][iy] /= wsum;
10606 help->
us[ix][iy] /= wsum;
10607 help->
vs[ix][iy] /= wsum;
10608 help->
ess[ix][iy] /= wsum;
10609 help->
nss[ix][iy] /= wsum;
10610 help->
shf[ix][iy] /= wsum;
10611 help->
lsm[ix][iy] /= wsum;
10612 help->
sst[ix][iy] /= wsum;
10613 help->
pbl[ix][iy] /= wsum;
10614 help->
cape[ix][iy] /= wsum;
10615 help->
cin[ix][iy] /= wsum;
10616 help->
t[ix][iy][ip] /= wsum;
10617 help->
u[ix][iy][ip] /= wsum;
10618 help->
v[ix][iy][ip] /= wsum;
10619 help->
w[ix][iy][ip] /= wsum;
10620 help->
h2o[ix][iy][ip] /= wsum;
10621 help->
o3[ix][iy][ip] /= wsum;
10622 help->
lwc[ix][iy][ip] /= wsum;
10623 help->
rwc[ix][iy][ip] /= wsum;
10624 help->
iwc[ix][iy][ip] /= wsum;
10625 help->
swc[ix][iy][ip] /= wsum;
10626 help->
cc[ix][iy][ip] /= wsum;
10633 for (
int ix = 0; ix < help->
nx; ix += ctl->
met_dx) {
10634 met->
lon[met->
nx] = help->
lon[ix];
10636 for (
int iy = 0; iy < help->
ny; iy += ctl->
met_dy) {
10637 met->
lat[met->
ny] = help->
lat[iy];
10638 met->
ps[met->
nx][met->
ny] = help->
ps[ix][iy];
10639 met->
zs[met->
nx][met->
ny] = help->
zs[ix][iy];
10640 met->
ts[met->
nx][met->
ny] = help->
ts[ix][iy];
10641 met->
us[met->
nx][met->
ny] = help->
us[ix][iy];
10642 met->
vs[met->
nx][met->
ny] = help->
vs[ix][iy];
10643 met->
ess[met->
nx][met->
ny] = help->
ess[ix][iy];
10644 met->
nss[met->
nx][met->
ny] = help->
nss[ix][iy];
10645 met->
shf[met->
nx][met->
ny] = help->
shf[ix][iy];
10646 met->
lsm[met->
nx][met->
ny] = help->
lsm[ix][iy];
10647 met->
sst[met->
nx][met->
ny] = help->
sst[ix][iy];
10648 met->
pbl[met->
nx][met->
ny] = help->
pbl[ix][iy];
10650 met->
cin[met->
nx][met->
ny] = help->
cin[ix][iy];
10652 for (
int ip = 0; ip < help->
np; ip += ctl->
met_dp) {
10653 met->
p[met->
np] = help->
p[ip];
10654 met->
t[met->
nx][met->
ny][met->
np] = help->
t[ix][iy][ip];
10655 met->
u[met->
nx][met->
ny][met->
np] = help->
u[ix][iy][ip];
10656 met->
v[met->
nx][met->
ny][met->
np] = help->
v[ix][iy][ip];
10657 met->
w[met->
nx][met->
ny][met->
np] = help->
w[ix][iy][ip];
10658 met->
h2o[met->
nx][met->
ny][met->
np] = help->
h2o[ix][iy][ip];
10659 met->
o3[met->
nx][met->
ny][met->
np] = help->
o3[ix][iy][ip];
10660 met->
lwc[met->
nx][met->
ny][met->
np] = help->
lwc[ix][iy][ip];
10661 met->
rwc[met->
nx][met->
ny][met->
np] = help->
rwc[ix][iy][ip];
10662 met->
iwc[met->
nx][met->
ny][met->
np] = help->
iwc[ix][iy][ip];
10663 met->
swc[met->
nx][met->
ny][met->
np] = help->
swc[ix][iy][ip];
10664 met->
cc[met->
nx][met->
ny][met->
np] = help->
cc[ix][iy][ip];
10683 double p2[200], pv[
EP], pv2[200], t[
EP], t2[200], th[
EP],
10684 th2[200], z[
EP], z2[200];
10688 LOG(2,
"Calculate tropopause...");
10691#pragma omp parallel for default(shared)
10692 for (
int iz = 0; iz < met->
np; iz++)
10693 z[iz] =
Z(met->
p[iz]);
10694#pragma omp parallel for default(shared)
10695 for (
int iz = 0; iz <= 190; iz++) {
10696 z2[iz] = 4.5 + 0.1 * iz;
10697 p2[iz] =
P(z2[iz]);
10702#pragma omp parallel for default(shared) collapse(2)
10703 for (
int ix = 0; ix < met->
nx; ix++)
10704 for (
int iy = 0; iy < met->
ny; iy++)
10705 met->
pt[ix][iy] = NAN;
10709#pragma omp parallel for default(shared) collapse(2)
10710 for (
int ix = 0; ix < met->
nx; ix++)
10711 for (
int iy = 0; iy < met->
ny; iy++)
10719#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10720 for (
int ix = 0; ix < met->
nx; ix++)
10721 for (
int iy = 0; iy < met->
ny; iy++) {
10724 for (
int iz = 0; iz < met->
np; iz++)
10725 t[iz] = met->
t[ix][iy][iz];
10729 int iz = (int) gsl_stats_min_index(t2, 1, 171);
10730 if (iz > 0 && iz < 170)
10731 met->
pt[ix][iy] = (float) p2[iz];
10733 met->
pt[ix][iy] = NAN;
10741#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10742 for (
int ix = 0; ix < met->
nx; ix++)
10743 for (
int iy = 0; iy < met->
ny; iy++) {
10747 for (iz = 0; iz < met->
np; iz++)
10748 t[iz] = met->
t[ix][iy][iz];
10752 met->
pt[ix][iy] = NAN;
10753 for (iz = 0; iz <= 170; iz++) {
10755 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10756 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10761 if (iz > 0 && iz < 170)
10762 met->
pt[ix][iy] = (float) p2[iz];
10769 met->
pt[ix][iy] = NAN;
10770 for (; iz <= 170; iz++) {
10772 for (
int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
10773 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
10780 for (; iz <= 170; iz++) {
10782 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10783 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10788 if (iz > 0 && iz < 170)
10789 met->
pt[ix][iy] = (float) p2[iz];
10801#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
10802 for (
int ix = 0; ix < met->
nx; ix++)
10803 for (
int iy = 0; iy < met->
ny; iy++) {
10806 for (
int iz = 0; iz < met->
np; iz++)
10807 pv[iz] = met->
pv[ix][iy][iz];
10811 for (
int iz = 0; iz < met->
np; iz++)
10812 th[iz] =
THETA(met->
p[iz], met->
t[ix][iy][iz]);
10816 met->
pt[ix][iy] = NAN;
10817 for (
int iz = 0; iz <= 170; iz++)
10820 if (iz > 0 && iz < 170)
10821 met->
pt[ix][iy] = (float) p2[iz];
10828 ERRMSG(
"Cannot calculate tropopause!");
10831#pragma omp parallel for default(shared) collapse(2)
10832 for (
int ix = 0; ix < met->
nx; ix++)
10833 for (
int iy = 0; iy < met->
ny; iy++) {
10834 double h2ot, tt, zt;
10837 met->
lat[iy], &tt, ci, cw, 1);
10839 met->
lat[iy], &zt, ci, cw, 0);
10841 met->
lat[iy], &h2ot, ci, cw, 0);
10842 met->
tt[ix][iy] = (float) tt;
10843 met->
zt[ix][iy] = (float) zt;
10844 met->
h2ot[ix][iy] = (float) h2ot;
10851 const char *filename,
10861 LOG(1,
"Read observation data: %s", filename);
10865 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
10867 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
10869 ERRMSG(
"Set OBS_TYPE to 0 or 1!");
10872 for (
int i = 1; i < *nobs; i++)
10873 if (rt[i] < rt[i - 1])
10874 ERRMSG(
"Time must be ascending!");
10879 LOG(2,
"Number of observations: %d", *nobs);
10880 gsl_stats_minmax(&mini, &maxi, rt, 1, (
size_t) n);
10881 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
10882 gsl_stats_minmax(&mini, &maxi, rz, 1, (
size_t) n);
10883 LOG(2,
"Altitude range: %g ... %g km", mini, maxi);
10884 gsl_stats_minmax(&mini, &maxi, rlon, 1, (
size_t) n);
10885 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
10886 gsl_stats_minmax(&mini, &maxi, rlat, 1, (
size_t) n);
10887 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
10888 gsl_stats_minmax(&mini, &maxi, robs, 1, (
size_t) n);
10889 LOG(2,
"Observation range: %g ... %g", mini, maxi);
10895 const char *filename,
10905 if (!(in = fopen(filename,
"r")))
10906 ERRMSG(
"Cannot open file!");
10910 while (fgets(line,
LEN, in))
10911 if (sscanf(line,
"%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
10912 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
10913 if ((++(*nobs)) >=
NOBS)
10914 ERRMSG(
"Too many observations!");
10923 const char *filename,
10934 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
10935 ERRMSG(
"Cannot open file!");
10946 NC(nc_close(ncid));
10952 const char *filename,
10955 const char *varname,
10957 const char *defvalue,
10962 char fullname1[
LEN], fullname2[
LEN], rval[
LEN];
10964 int contain = 0, i;
10967 if (filename[strlen(filename) - 1] !=
'-')
10968 if (!(in = fopen(filename,
"r")))
10969 ERRMSG(
"Cannot open file!");
10973 sprintf(fullname1,
"%s[%d]", varname, arridx);
10974 sprintf(fullname2,
"%s[*]", varname);
10976 sprintf(fullname1,
"%s", varname);
10977 sprintf(fullname2,
"%s", varname);
10982 char dummy[
LEN], line[
LEN], rvarname[
LEN];
10983 while (fgets(line,
LEN, in)) {
10984 if (sscanf(line,
"%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
10985 if (strcasecmp(rvarname, fullname1) == 0 ||
10986 strcasecmp(rvarname, fullname2) == 0) {
10992 for (i = 1; i < argc - 1; i++)
10993 if (strcasecmp(argv[i], fullname1) == 0 ||
10994 strcasecmp(argv[i], fullname2) == 0) {
10995 sprintf(rval,
"%s", argv[i + 1]);
11006 if (strlen(defvalue) > 0)
11007 sprintf(rval,
"%s", defvalue);
11009 ERRMSG(
"Missing variable %s!\n", fullname1);
11013 LOG(1,
"%s = %s", fullname1, rval);
11017 sprintf(value,
"%s", rval);
11027 const double rhop) {
11030 const double rp_help = rp * 1e-6;
11033 const double rho =
RHO(p, T);
11036 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
11039 const double v = sqrt(8. *
KB * T / (M_PI * 4.8096e-26));
11042 const double lambda = 2. * eta / (rho * v);
11045 const double K = lambda / rp_help;
11048 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
11051 return 2. *
SQR(rp_help) * (rhop - rho) *
G0 / (9. * eta) * G;
11063 const int method) {
11069 gsl_interp_accel *acc = gsl_interp_accel_alloc();
11070 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (
size_t) n);
11073 gsl_spline_init(s, x, y, (
size_t) n);
11074 for (
int i = 0; i < n2; i++)
11077 else if (x2[i] >= x[n - 1])
11080 y2[i] = gsl_spline_eval(s, x2[i], acc);
11083 gsl_spline_free(s);
11084 gsl_interp_accel_free(acc);
11089 for (
int i = 0; i < n2; i++)
11092 else if (x2[i] >= x[n - 1])
11096 y2[i] =
LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
11110 float mean = 0, var = 0;
11112 for (
int i = 0; i < n; ++i) {
11114 var +=
SQR(data[i]);
11117 var = var / (float) n -
SQR(mean / (
float) n);
11119 return (var > 0 ? sqrtf(var) : 0);
11131 const double remain,
11143 t1.tm_year = year - 1900;
11144 t1.tm_mon = mon - 1;
11150 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
11158 const int output) {
11165 static int iname = -1, igroup = -1, nname, ngroup, ct_name[
NTIMER];
11168 t1 = omp_get_wtime();
11173 rt_name[iname] += dt;
11174 rt_min[iname] = (ct_name[iname] <= 0 ? dt :
MIN(rt_min[iname], dt));
11175 rt_max[iname] = (ct_name[iname] <= 0 ? dt :
MAX(rt_max[iname], dt));
11179 rt_group[igroup] += t1 - t0;
11183 for (
int i = 0; i < nname; i++)
11184 LOG(1,
"TIMER_%s = %.3f s (min= %g s, mean= %g s,"
11185 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
11186 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
11187 for (
int i = 0; i < ngroup; i++)
11188 LOG(1,
"TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
11189 double total = 0.0;
11190 for (
int i = 0; i < nname; i++)
11191 total += rt_name[i];
11192 LOG(1,
"TIMER_TOTAL = %.3f s", total);
11196 for (iname = 0; iname < nname; iname++)
11197 if (strcasecmp(name, names[iname]) == 0)
11199 for (igroup = 0; igroup < ngroup; igroup++)
11200 if (strcasecmp(group, groups[igroup]) == 0)
11204 if (iname >= nname) {
11205 sprintf(names[iname],
"%s", name);
11206 if ((++nname) >=
NTIMER)
11207 ERRMSG(
"Too many timers!");
11211 if (igroup >= ngroup) {
11212 sprintf(groups[igroup],
"%s", group);
11213 if ((++ngroup) >=
NTIMER)
11214 ERRMSG(
"Too many groups!");
11224 const char *filename,
11225 const int offset) {
11232 int len = (int) strlen(filename);
11233 sprintf(tstr,
"%.4s", &filename[len - offset]);
11234 int year = atoi(tstr);
11235 sprintf(tstr,
"%.2s", &filename[len - offset + 5]);
11236 int mon = atoi(tstr);
11237 sprintf(tstr,
"%.2s", &filename[len - offset + 8]);
11238 int day = atoi(tstr);
11239 sprintf(tstr,
"%.2s", &filename[len - offset + 11]);
11240 int hour = atoi(tstr);
11241 sprintf(tstr,
"%.2s", &filename[len - offset + 14]);
11242 int min = atoi(tstr);
11245 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
11246 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
11247 ERRMSG(
"Cannot read time from filename!");
11250 time2jsec(year, mon, day, hour, min, 0, 0.0, &t);
11267 const double p1 = pt * 0.866877899;
11268 const double p0 = pt / 0.866877899;
11271 if (atm->
p[ip] > p0)
11273 else if (atm->
p[ip] < p1)
11276 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
11282 const char *filename,
11290 const double t0 = t - 0.5 * ctl->
dt_mod;
11291 const double t1 = t + 0.5 * ctl->
dt_mod;
11297 if (!(out = popen(
"gnuplot",
"w")))
11298 ERRMSG(
"Cannot create pipe to gnuplot!");
11301 fprintf(out,
"set out \"%s.png\"\n", filename);
11305 int year, mon, day, hour, min, sec;
11306 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11307 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
11308 year, mon, day, hour, min);
11313 ERRMSG(
"Cannot open file!");
11315 while (fgets(line,
LEN, in))
11316 fprintf(out,
"%s", line);
11323 if (!(out = fopen(filename,
"w")))
11324 ERRMSG(
"Cannot create file!");
11329 "# $1 = time [s]\n"
11330 "# $2 = altitude [km]\n"
11331 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
11332 for (
int iq = 0; iq < ctl->
nq; iq++)
11333 fprintf(out,
"# $%i = %s [%s]\n", iq + 5, ctl->
qnt_name[iq],
11335 fprintf(out,
"\n");
11338 for (
int ip = 0; ip < atm->
np; ip += ctl->
atm_stride) {
11345 fprintf(out,
"%.2f %g %g %g", atm->
time[ip],
Z(atm->
p[ip]),
11346 atm->
lon[ip], atm->
lat[ip]);
11347 for (
int iq = 0; iq < ctl->
nq; iq++) {
11352 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
11354 fprintf(out,
"\n");
11364 const char *filename,
11366 const atm_t *atm) {
11371 if (!(out = fopen(filename,
"w")))
11372 ERRMSG(
"Cannot create file!");
11396 for (
int iq = 0; iq < ctl->
nq; iq++)
11414 const char *filename,
11416 const atm_t *atm) {
11418 int tid, pid, ncid, varid;
11419 size_t start[2], count[2];
11422 NC(nc_create(filename, NC_NETCDF4, &ncid));
11425 NC(nc_def_dim(ncid,
"time", 1, &tid));
11426 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11429 int dim_ids[2] = { tid, pid };
11430 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11431 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11432 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
11434 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
11436 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
11439 for (
int iq = 0; iq < ctl->
nq; iq++)
11449 NC(nc_enddef(ncid));
11457 for (
int iq = 0; iq < ctl->
nq; iq++)
11461 NC(nc_close(ncid));
11467 const char *dirname,
11473 static size_t out_cnt = 0;
11475 double r, r_start, r_stop;
11476 int year, mon, day, hour, min, sec;
11477 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
11478 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
11479 char filename_out[2 *
LEN] =
"traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
11481 int ncid, varid, tid, pid, cid;
11489 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11491 &min_start, &sec_start, &r_start);
11493 &min_stop, &sec_stop, &r_stop);
11495 sprintf(filename_out,
11496 "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc", dirname,
11497 year_start % 100, mon_start, day_start, hour_start,
11498 year_stop % 100, mon_stop, day_stop, hour_stop);
11499 LOG(1,
"Write traj file: %s", filename_out);
11502 start[0] = out_cnt;
11505 count[1] = (size_t) atm->
np;
11508 if (out_cnt == 0) {
11511 NC(nc_create(filename_out, NC_NETCDF4, &ncid));
11514 NC(nc_def_dim(ncid,
"time", NC_UNLIMITED, &tid));
11515 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11516 NC(nc_def_dim(ncid,
"TMDT", 7, &cid));
11521 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11522 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11523 NC_DEF_VAR(
"LAT", NC_DOUBLE, 2, dim_ids,
"Latitude",
"deg",
11525 NC_DEF_VAR(
"LON", NC_DOUBLE, 2, dim_ids,
"Longitude",
"deg",
11527 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 2, dim_ids,
"Pressure",
"hPa",
11529 NC_DEF_VAR(
"ZETA", NC_DOUBLE, 2, dim_ids,
"Zeta",
"K",
11531 for (
int iq = 0; iq < ctl->
nq; iq++)
11541 NC(nc_enddef(ncid));
11542 NC(nc_close(ncid));
11549 NC(nc_open(filename_out, NC_WRITE, &ncid));
11561 for (
int iq = 0; iq < ctl->
nq; iq++)
11565 NC(nc_close(ncid));
11568 if ((year == year_stop) && (mon == mon_stop)
11569 && (day == day_stop) && (hour == hour_stop)) {
11572 char filename_init[2 *
LEN] =
"./init_fix_YYYYMMDDHH.nc";
11573 sprintf(filename_init,
"%s/init_fix_%02d%02d%02d%02d.nc",
11574 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
11575 LOG(1,
"Write init file: %s", filename_init);
11578 NC(nc_create(filename_init, NC_NETCDF4, &ncid));
11581 NC(nc_def_dim(ncid,
"time", 1, &tid));
11582 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11587 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11588 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11589 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
11591 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
11593 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
11596 for (
int iq = 0; iq < ctl->
nq; iq++)
11606 NC(nc_enddef(ncid));
11614 for (
int iq = 0; iq < ctl->
nq; iq++)
11618 NC(nc_close(ncid));
11625 const char *filename,
11627 const atm_t *atm) {
11629 int ncid, obsid, varid;
11631 size_t start[2], count[2];
11634 NC(nc_create(filename, NC_NETCDF4, &ncid));
11637 NC(nc_def_dim(ncid,
"obs", (
size_t) atm->
np, &obsid));
11640 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &obsid,
"time",
11641 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11642 NC_DEF_VAR(
"press", NC_DOUBLE, 1, &obsid,
"pressure",
"hPa",
11644 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &obsid,
"longitude",
"degrees_east",
11646 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &obsid,
"latitude",
"degrees_north",
11648 for (
int iq = 0; iq < ctl->
nq; iq++)
11657 NC(nc_enddef(ncid));
11664 for (
int iq = 0; iq < ctl->
nq; iq++)
11668 NC(nc_close(ncid));
11674 const char *filename,
11681 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
11684 static int *obscount, nobs, nk;
11688 const int ensemble = (ctl->
nens > 0);
11694 if (ctl->
qnt_m < 0)
11695 ERRMSG(
"Need quantity mass!");
11698 ERRMSG(
"Missing ensemble IDs!");
11700 ERRMSG(
"Too many ensembles!");
11707 ALLOC(area,
double,
11713 ALLOC(rlon,
double,
11715 ALLOC(rlat,
double,
11717 ALLOC(robs,
double,
11728 LOG(1,
"Write CSI%s data: %s", ensemble ?
" ensemble" :
"", filename);
11729 if (!(out = fopen(filename,
"w")))
11730 ERRMSG(
"Cannot create file!");
11734 "# $1 = time [s]\n"
11735 "# $2 = ensemble ID\n"
11736 "# $3 = number of hits (cx)\n"
11737 "# $4 = number of misses (cy)\n"
11738 "# $5 = number of false alarms (cz)\n"
11739 "# $6 = number of observations (cx + cy)\n"
11740 "# $7 = number of forecasts (cx + cz)\n"
11741 "# $8 = bias (%%)\n"
11742 "# $9 = POD (%%)\n"
11743 "# $10 = FAR (%%)\n"
11744 "# $11 = CSI (%%)\n"
11745 "# $12 = hits by random chance\n"
11746 "# $13 = ETS (%%)\n"
11747 "# $14 = Pearson R\n"
11748 "# $15 = Spearman R\n"
11749 "# $16 = mean error [kg/m²]\n"
11750 "# $17 = RMSE [kg/m²]\n"
11751 "# $18 = MAE [kg/m²]\n"
11752 "# $19 = log-likelihood\n" "# $20 = number of points\n\n");
11760 for (
int iy = 0; iy < ctl->
csi_ny; iy++) {
11761 const double lat = ctl->
csi_lat0 + dlat * (iy + 0.5);
11762 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.0) * cos(
DEG2RAD(lat));
11767 const double t0 = t - 0.5 * ctl->
dt_mod;
11768 const double t1 = t + 0.5 * ctl->
dt_mod;
11772 ALLOC(modmean,
double,
11773 (ensemble ? ctl->
nens : 1) * grid_size);
11774 ALLOC(obsmean,
double,
11776 ALLOC(obscount,
int,
11778 ALLOC(obsstd,
double,
11782 for (
int i = 0; i < (ensemble ? ctl->
nens : 1); i++)
11783 ct[i] = cx[i] = cy[i] = cz[i] = n[i] = 0;
11786 for (
int i = 0; i < nobs; i++) {
11787 if (rt[i] < t0 || rt[i] >= t1 || !isfinite(robs[i]))
11791 const int ix = (int) ((rlon[i] - ctl->
csi_lon0) / dlon);
11792 const int iy = (int) ((rlat[i] - ctl->
csi_lat0) / dlat);
11793 const int iz = (int) ((rz[i] - ctl->
csi_z0) / dz);
11794 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
11800 obsmean[idx] += robs[i];
11801 obsstd[idx] +=
SQR(robs[i]);
11806 for (
int ip = 0; ip < atm->
np; ip++) {
11809 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11813 int ens_id = ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
11814 if (ens_id < 0 || ens_id >= (ensemble ? ctl->
nens : 1))
11815 ERRMSG(
"Ensemble ID out of range!");
11818 const int ix = (int) ((atm->
lon[ip] - ctl->
csi_lon0) / dlon);
11819 const int iy = (int) ((atm->
lat[ip] - ctl->
csi_lat0) / dlat);
11820 const int iz = (int) ((
Z(atm->
p[ip]) - ctl->
csi_z0) / dz);
11821 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
11831 for (
int e = 0; e < (ensemble ? ctl->
nens : 1); e++) {
11833 for (
int ix = 0; ix < ctl->
csi_nx; ix++)
11834 for (
int iy = 0; iy < ctl->
csi_ny; iy++)
11835 for (
int iz = 0; iz < ctl->
csi_nz; iz++) {
11840 if (obscount[idx]) {
11841 obsmean[idx] /= obscount[idx];
11843 sqrt(obsstd[idx] / obscount[idx] -
SQR(obsmean[idx]));
11847 const int midx = e * grid_size + idx;
11848 if (modmean[midx] > 0)
11849 modmean[midx] /= (1e6 * area[iy]);
11852 if (obscount[idx]) {
11867 x[n[e]] = modmean[midx];
11868 y[n[e]] = obsmean[idx];
11870 obsstdn[n[e]] = obsstd[idx];
11871 if ((++n[e]) >=
NCSI)
11872 ERRMSG(
"Too many points for statistics!");
11884 static double work[2 *
NCSI], work2[2 *
NCSI];
11885 const int n_obs = cx[e] + cy[e];
11886 const int n_for = cx[e] + cz[e];
11887 const double cx_rd = (ct[e] > 0) ? (1. * n_obs * n_for) / ct[e] : NAN;
11888 const double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
11889 const double pod = (n_obs > 0) ? 100. * cx[e] / n_obs : NAN;
11890 const double far = (n_for > 0) ? 100. * cz[e] / n_for : NAN;
11892 (cx[e] + cy[e] + cz[e] >
11893 0) ? 100. * cx[e] / (cx[e] + cy[e] + cz[e]) : NAN;
11895 (cx[e] + cy[e] + cz[e] - cx_rd >
11896 0) ? 100. * (cx[e] - cx_rd) / (cx[e] + cy[e] + cz[e] - cx_rd) : NAN;
11897 const double rho_p = gsl_stats_correlation(x, 1, y, 1, (
size_t) n[e]);
11898 const double rho_s =
11899 gsl_stats_spearman(x, 1, y, 1, (
size_t) n[e], work);
11900 for (
int i = 0; i < n[e]; i++) {
11901 work[i] = x[i] - y[i];
11902 work2[i] = (obsstdn[i] != 0) ? work[i] / obsstdn[i] : 0;
11904 const double mean = gsl_stats_mean(work, 1, (
size_t) n[e]);
11905 const double rmse =
11906 gsl_stats_sd_with_fixed_mean(work, 1, (
size_t) n[e], 0.0);
11907 const double absdev = gsl_stats_absdev_m(work, 1, (
size_t) n[e], 0.0);
11908 const double loglikelihood =
11909 gsl_stats_tss_m(work2, 1, (
size_t) n[e], 0.0) * -0.5;
11913 "%.2f %d %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n",
11914 t, ensemble ? e : -999, cx[e], cy[e], cz[e], n_obs, n_for, bias,
11915 pod, far, csi, cx_rd, ets, rho_p, rho_s, mean, rmse, absdev,
11916 loglikelihood, n[e]);
11919 for (
int i = 0; i < n[e]; i++)
11920 work[i] = work2[i] = x[i] = y[i] = obsstdn[i] = 0;
11921 ct[e] = cx[e] = cy[e] = cz[e] = n[e] = 0;
11949 const char *filename,
11959 static int n[
NENS];
11966 ERRMSG(
"Missing ensemble IDs!");
11969 const double t0 = t - 0.5 * ctl->
dt_mod;
11970 const double t1 = t + 0.5 * ctl->
dt_mod;
11973 for (
int i = 0; i <
NENS; i++) {
11974 for (
int iq = 0; iq < ctl->
nq; iq++)
11975 qm[iq][i] = qs[iq][i] = 0;
11976 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
11981 for (
int ip = 0; ip < atm->
np; ip++) {
11984 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11989 ERRMSG(
"Ensemble ID is out of range!");
11993 for (
int iq = 0; iq < ctl->
nq; iq++) {
11994 qm[iq][ctl->
qnt_ens] += atm->
q[iq][ip];
12005 LOG(1,
"Write ensemble data: %s", filename);
12006 if (!(out = fopen(filename,
"w")))
12007 ERRMSG(
"Cannot create file!");
12011 "# $1 = time [s]\n"
12012 "# $2 = altitude [km]\n"
12013 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
12014 for (
int iq = 0; iq < ctl->
nq; iq++)
12015 fprintf(out,
"# $%d = %s (mean) [%s]\n", 5 + iq,
12017 for (
int iq = 0; iq < ctl->
nq; iq++)
12018 fprintf(out,
"# $%d = %s (sigma) [%s]\n", 5 + ctl->
nq + iq,
12020 fprintf(out,
"# $%d = number of members\n\n", 5 + 2 * ctl->
nq);
12023 for (
int i = 0; i <
NENS; i++)
12025 cart2geo(xm[i], &dummy, &lon, &lat);
12026 fprintf(out,
"%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
12027 for (
int iq = 0; iq < ctl->
nq; iq++) {
12029 fprintf(out, ctl->
qnt_format[iq], qm[iq][i] / n[i]);
12031 for (
int iq = 0; iq < ctl->
nq; iq++) {
12033 double var = qs[iq][i] / n[i] -
SQR(qm[iq][i] / n[i]);
12034 fprintf(out, ctl->
qnt_format[iq], (var > 0 ? sqrt(var) : 0));
12036 fprintf(out,
" %d\n", n[i]);
12046 const char *filename,
12053 static double kz[
EP], kw[
EP];
12057 double *cd, *mean[
NQ], *sigma[
NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
12059 int *ixs, *iys, *izs, *np;
12065 LOG(1,
"Write grid data: %s", filename);
12078 for (
int iq = 0; iq < ctl->
nq; iq++) {
12079 ALLOC(mean[iq],
double,
12081 ALLOC(sigma[iq],
double,
12084 ALLOC(vmr_impl,
double,
12092 ALLOC(area,
double,
12094 ALLOC(press,
double,
12111#pragma omp parallel
for default(shared)
12112 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
12113 z[iz] = ctl->
grid_z0 + dz * (iz + 0.5);
12114 press[iz] =
P(z[iz]);
12118 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12119 lon[ix] = ctl->
grid_lon0 + dlon * (ix + 0.5);
12120#pragma omp parallel for default(shared)
12121 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
12122 lat[iy] = ctl->
grid_lat0 + dlat * (iy + 0.5);
12123 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
12127 const double t0 = t - 0.5 * ctl->
dt_mod;
12128 const double t1 = t + 0.5 * ctl->
dt_mod;
12131#pragma omp parallel for default(shared)
12132 for (
int ip = 0; ip < atm->
np; ip++) {
12133 ixs[ip] = (int) ((atm->
lon[ip] - ctl->
grid_lon0) / dlon);
12134 iys[ip] = (int) ((atm->
lat[ip] - ctl->
grid_lat0) / dlat);
12135 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
grid_z0) / dz);
12136 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
12137 || ixs[ip] < 0 || ixs[ip] >= ctl->
grid_nx
12138 || iys[ip] < 0 || iys[ip] >= ctl->
grid_ny
12139 || izs[ip] < 0 || izs[ip] >= ctl->
grid_nz)
12144 for (
int ip = 0; ip < atm->
np; ip++)
12145 if (izs[ip] >= 0) {
12150 for (
int iq = 0; iq < ctl->
nq; iq++) {
12151 mean[iq][idx] += kernel * atm->
q[iq][ip];
12152 sigma[iq][idx] +=
SQR(kernel * atm->
q[iq][ip]);
12157#pragma omp parallel for default(shared)
12158 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12159 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12160 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
12167 if (ctl->
qnt_m >= 0)
12168 cd[idx] = mean[ctl->
qnt_m][idx] / (1e6 * area[iy]);
12171 vmr_impl[idx] = NAN;
12172 if (ctl->
qnt_m >= 0 && ctl->
molmass > 0 && met0 != NULL
12175 if (mean[ctl->
qnt_m][idx] > 0) {
12181 lon[ix], lat[iy], &temp, ci, cw, 1);
12185 MA / ctl->
molmass * cd[idx] / (
RHO(press[iz], temp) * dz * 1e3);
12191 for (
int iq = 0; iq < ctl->
nq; iq++) {
12192 mean[iq][idx] /= np[idx];
12193 const double var = sigma[iq][idx] / np[idx] -
SQR(mean[iq][idx]);
12194 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
12196 for (
int iq = 0; iq < ctl->
nq; iq++) {
12197 mean[iq][idx] = NAN;
12198 sigma[iq][idx] = NAN;
12205 t, z, lon, lat, area, dz, np);
12210 t, z, lon, lat, area, dz, np);
12214 ERRMSG(
"Grid data format GRID_TYPE unknown!");
12218 for (
int iq = 0; iq < ctl->
nq; iq++) {
12237 const char *filename,
12242 const double *vmr_impl,
12247 const double *area,
12257 if (!(out = popen(
"gnuplot",
"w")))
12258 ERRMSG(
"Cannot create pipe to gnuplot!");
12261 fprintf(out,
"set out \"%s.png\"\n", filename);
12265 int year, mon, day, hour, min, sec;
12266 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
12267 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
12268 year, mon, day, hour, min);
12274 ERRMSG(
"Cannot open file!");
12275 while (fgets(line,
LEN, in))
12276 fprintf(out,
"%s", line);
12283 if (!(out = fopen(filename,
"w")))
12284 ERRMSG(
"Cannot create file!");
12289 "# $1 = time [s]\n"
12290 "# $2 = altitude [km]\n"
12291 "# $3 = longitude [deg]\n"
12292 "# $4 = latitude [deg]\n"
12293 "# $5 = surface area [km^2]\n"
12294 "# $6 = layer depth [km]\n"
12295 "# $7 = column density (implicit) [kg/m^2]\n"
12296 "# $8 = volume mixing ratio (implicit) [ppv]\n"
12297 "# $9 = number of particles [1]\n");
12298 for (
int iq = 0; iq < ctl->
nq; iq++)
12299 fprintf(out,
"# $%i = %s (mean) [%s]\n", 10 + iq, ctl->
qnt_name[iq],
12302 for (
int iq = 0; iq < ctl->
nq; iq++)
12303 fprintf(out,
"# $%i = %s (stddev) [%s]\n", 10 + ctl->
nq + iq,
12305 fprintf(out,
"\n");
12308 for (
int ix = 0; ix < ctl->
grid_nx; ix++) {
12310 fprintf(out,
"\n");
12311 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
12313 fprintf(out,
"\n");
12314 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
12317 fprintf(out,
"%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
12318 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
12319 for (
int iq = 0; iq < ctl->
nq; iq++) {
12321 fprintf(out, ctl->
qnt_format[iq], mean[iq][idx]);
12324 for (
int iq = 0; iq < ctl->
nq; iq++) {
12326 fprintf(out, ctl->
qnt_format[iq], sigma[iq][idx]);
12328 fprintf(out,
"\n");
12341 const char *filename,
12346 const double *vmr_impl,
12351 const double *area,
12355 char longname[2 *
LEN], varname[2 *
LEN];
12359 int *help2, ncid, dimid[10], varid;
12361 size_t start[2], count[2];
12364 ALLOC(help,
double,
12370 NC(nc_create(filename, NC_NETCDF4, &ncid));
12373 NC(nc_def_dim(ncid,
"time", 1, &dimid[0]));
12374 NC(nc_def_dim(ncid,
"z", (
size_t) ctl->
grid_nz, &dimid[1]));
12375 NC(nc_def_dim(ncid,
"lat", (
size_t) ctl->
grid_ny, &dimid[2]));
12376 NC(nc_def_dim(ncid,
"lon", (
size_t) ctl->
grid_nx, &dimid[3]));
12377 NC(nc_def_dim(ncid,
"dz", 1, &dimid[4]));
12380 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &dimid[0],
"time",
12381 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
12382 NC_DEF_VAR(
"z", NC_DOUBLE, 1, &dimid[1],
"altitude",
"km", 0, 0);
12383 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &dimid[2],
"latitude",
"degrees_north", 0,
12385 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &dimid[3],
"longitude",
"degrees_east", 0,
12387 NC_DEF_VAR(
"dz", NC_DOUBLE, 1, &dimid[1],
"layer depth",
"km", 0, 0);
12388 NC_DEF_VAR(
"area", NC_DOUBLE, 1, &dimid[2],
"surface area",
"km**2", 0, 0);
12390 NC_DEF_VAR(
"cd", NC_FLOAT, 4, dimid,
"column density",
"kg m**-2",
12393 "volume mixing ratio (implicit)",
"ppv", ctl->
grid_nc_level, 0);
12394 NC_DEF_VAR(
"np", NC_INT, 4, dimid,
"number of particles",
"1", 0, 0);
12395 for (
int iq = 0; iq < ctl->
nq; iq++) {
12396 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
12397 sprintf(longname,
"%s (mean)", ctl->
qnt_longname[iq]);
12401 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
12402 sprintf(longname,
"%s (stddev)", ctl->
qnt_longname[iq]);
12408 NC(nc_enddef(ncid));
12418 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12419 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12420 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12425 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12426 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12427 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12432 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12433 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12434 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12439 for (
int iq = 0; iq < ctl->
nq; iq++) {
12440 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
12441 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12442 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12443 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12450 for (
int iq = 0; iq < ctl->
nq; iq++) {
12451 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
12452 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12453 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12454 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12461 NC(nc_close(ncid));
12471 const char *filename,
12477 if (!(out = fopen(filename,
"w")))
12478 ERRMSG(
"Cannot create file!");
12568 ERRMSG(
"Number of meteo variables doesn't match!");
12586 const char *varname) {
12595 for (
int ix = 0; ix < met->
nx; ix++)
12596 for (
int iy = 0; iy < met->
ny; iy++)
12597 help[
ARRAY_2D(ix, iy, met->
ny)] = var[ix][iy];
12600 LOG(2,
"Write 2-D variable: %s (uncompressed)", varname);
12602 (
size_t) (met->
nx * met->
ny),
12616 const char *varname,
12617 const int precision,
12618 const double tolerance) {
12627#pragma omp parallel for default(shared) collapse(2)
12628 for (
int ix = 0; ix < met->
nx; ix++)
12629 for (
int iy = 0; iy < met->
ny; iy++)
12630 for (
int ip = 0; ip < met->
np; ip++)
12631 help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)] = var[ix][iy][ip];
12635 LOG(2,
"Write 3-D variable: %s (uncompressed)", varname);
12637 (
size_t) (met->
nx * met->
ny * met->
np),
12644 (
size_t) met->
np, 0, out);
12652 FWRITE(&tolerance,
double,
12656 tolerance, 0, out);
12671 (
size_t) met->
np, met->
p, 0, out);
12681 FWRITE(&tolerance,
double,
12685 tolerance, 0, out);
12691 ERRMSG(
"MET_TYPE not supported!");
12692 LOG(3,
"%d %g", precision, tolerance);
12702 const char *filename,
12708 size_t start[4], count[4];
12709 NC(nc_create(filename, NC_NETCDF4, &ncid));
12712 int tid, lonid, latid, levid;
12713 NC(nc_def_dim(ncid,
"time", 1, &tid));
12714 NC(nc_def_dim(ncid,
"lon", (
size_t) met->
nx, &lonid));
12715 NC(nc_def_dim(ncid,
"lat", (
size_t) met->
ny, &latid));
12716 NC(nc_def_dim(ncid,
"lev", (
size_t) met->
np, &levid));
12719 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"time",
12720 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
12721 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &lonid,
"longitude",
"degrees_east", 0, 0);
12722 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &latid,
"latitude",
"degrees_north", 0, 0);
12723 NC_DEF_VAR(
"lev", NC_DOUBLE, 1, &levid,
"pressure",
"Pa", 0, 0);
12726 int dimid2[2] = { latid, lonid };
12727 NC_DEF_VAR(
"sp", NC_FLOAT, 2, dimid2,
"Surface pressure",
"Pa",
12729 NC_DEF_VAR(
"z", NC_FLOAT, 2, dimid2,
"Geopotential",
"m**2 s**-2",
12731 NC_DEF_VAR(
"t2m", NC_FLOAT, 2, dimid2,
"2 metre temperature",
"K",
12733 NC_DEF_VAR(
"u10m", NC_FLOAT, 2, dimid2,
"10 metre U wind component",
12735 NC_DEF_VAR(
"v10m", NC_FLOAT, 2, dimid2,
"10 metre V wind component",
12738 "Instantaneous eastward turbulent surface stress",
"N m**-2",
12741 "Instantaneous northward turbulent surface stress",
"N m**-2",
12744 "Instantaneous surface sensible heat flux",
"W m**-1",
12746 NC_DEF_VAR(
"lsm", NC_FLOAT, 2, dimid2,
"Land/sea mask",
"-",
12748 NC_DEF_VAR(
"sstk", NC_FLOAT, 2, dimid2,
"Sea surface temperature",
"K",
12750 NC_DEF_VAR(
"blp", NC_FLOAT, 2, dimid2,
"Boundary layer pressure",
"Pa",
12752 NC_DEF_VAR(
"pt", NC_FLOAT, 2, dimid2,
"Tropopause pressure",
"Pa",
12754 NC_DEF_VAR(
"tt", NC_FLOAT, 2, dimid2,
"Tropopause temperature",
"K",
12756 NC_DEF_VAR(
"zt", NC_FLOAT, 2, dimid2,
"Tropopause height",
"m",
12758 NC_DEF_VAR(
"h2ot", NC_FLOAT, 2, dimid2,
"Tropopause water vapor",
"ppv",
12760 NC_DEF_VAR(
"pct", NC_FLOAT, 2, dimid2,
"Cloud top pressure",
"Pa",
12762 NC_DEF_VAR(
"pcb", NC_FLOAT, 2, dimid2,
"Cloud bottom pressure",
"Pa",
12764 NC_DEF_VAR(
"cl", NC_FLOAT, 2, dimid2,
"Total column cloud water",
12767 "Pressure at lifted condensation level (LCL)",
"Pa",
12770 "Pressure at level of free convection (LFC)",
"Pa",
12773 "Pressure at equilibrium level (EL)",
"Pa", ctl->
met_nc_level,
12776 "Convective available potential energy",
"J kg**-1",
12778 NC_DEF_VAR(
"cin", NC_FLOAT, 2, dimid2,
"Convective inhibition",
12780 NC_DEF_VAR(
"o3c", NC_FLOAT, 2, dimid2,
"Total column ozone",
"DU",
12784 int dimid3[3] = { levid, latid, lonid };
12785 NC_DEF_VAR(
"t", NC_FLOAT, 3, dimid3,
"Temperature",
"K",
12787 NC_DEF_VAR(
"u", NC_FLOAT, 3, dimid3,
"U velocity",
"m s**-1",
12789 NC_DEF_VAR(
"v", NC_FLOAT, 3, dimid3,
"V velocity",
"m s**-1",
12791 NC_DEF_VAR(
"w", NC_FLOAT, 3, dimid3,
"Vertical velocity",
"Pa s**-1",
12793 NC_DEF_VAR(
"q", NC_FLOAT, 3, dimid3,
"Specific humidity",
"kg kg**-1",
12795 NC_DEF_VAR(
"o3", NC_FLOAT, 3, dimid3,
"Ozone mass mixing ratio",
12797 NC_DEF_VAR(
"clwc", NC_FLOAT, 3, dimid3,
"Cloud liquid water content",
12799 NC_DEF_VAR(
"crwc", NC_FLOAT, 3, dimid3,
"Cloud rain water content",
12801 NC_DEF_VAR(
"ciwc", NC_FLOAT, 3, dimid3,
"Cloud ice water content",
12803 NC_DEF_VAR(
"cswc", NC_FLOAT, 3, dimid3,
"Cloud snow water content",
12805 NC_DEF_VAR(
"cc", NC_FLOAT, 3, dimid3,
"Cloud cover",
"-",
12809 NC(nc_enddef(ncid));
12816 for (
int ip = 0; ip < met->
np; ip++)
12817 phelp[ip] = 100. * met->
p[ip];
12860 NC(nc_close(ncid));
12867 const char *varname,
12873 size_t start[4], count[4];
12881 for (
int ix = 0; ix < met->
nx; ix++)
12882 for (
int iy = 0; iy < met->
ny; iy++)
12883 help[
ARRAY_2D(iy, ix, met->
nx)] = scl * var[ix][iy];
12896 const char *varname,
12902 size_t start[4], count[4];
12910 for (
int ix = 0; ix < met->
nx; ix++)
12911 for (
int iy = 0; iy < met->
ny; iy++)
12912 for (
int ip = 0; ip < met->
np; ip++)
12913 help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)] = scl * var[ix][iy][ip];
12925 const char *filename,
12934 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
12935 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
12937 static int nobs, *obscount, ip, okay;
12946 if (ctl->
qnt_m < 0)
12947 ERRMSG(
"Need quantity mass!");
12951 ERRMSG(
"Specify molar mass!");
12958 ALLOC(area,
double,
12962 ALLOC(press,
double,
12968 ALLOC(rlon,
double,
12970 ALLOC(rlat,
double,
12972 ALLOC(robs,
double,
12979 LOG(1,
"Write profile data: %s", filename);
12980 if (!(out = fopen(filename,
"w")))
12981 ERRMSG(
"Cannot create file!");
12985 "# $1 = time [s]\n"
12986 "# $2 = altitude [km]\n"
12987 "# $3 = longitude [deg]\n"
12988 "# $4 = latitude [deg]\n"
12989 "# $5 = pressure [hPa]\n"
12990 "# $6 = temperature [K]\n"
12991 "# $7 = volume mixing ratio [ppv]\n"
12992 "# $8 = H2O volume mixing ratio [ppv]\n"
12993 "# $9 = O3 volume mixing ratio [ppv]\n"
12994 "# $10 = observed BT index [K]\n"
12995 "# $11 = number of observations\n");
13003 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
13004 z[iz] = ctl->
prof_z0 + dz * (iz + 0.5);
13005 press[iz] =
P(z[iz]);
13009 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
13010 lon[ix] = ctl->
prof_lon0 + dlon * (ix + 0.5);
13011 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
13012 lat[iy] = ctl->
prof_lat0 + dlat * (iy + 0.5);
13013 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
13018 const double t0 = t - 0.5 * ctl->
dt_mod;
13019 const double t1 = t + 0.5 * ctl->
dt_mod;
13022 ALLOC(mass,
double,
13024 ALLOC(obsmean,
double,
13026 ALLOC(obscount,
int,
13030 for (
int i = 0; i < nobs; i++) {
13035 else if (rt[i] >= t1)
13039 if (!isfinite(robs[i]))
13043 const int ix = (int) ((rlon[i] - ctl->
prof_lon0) / dlon);
13044 const int iy = (int) ((rlat[i] - ctl->
prof_lat0) / dlat);
13047 if (ix < 0 || ix >= ctl->
prof_nx || iy < 0 || iy >= ctl->
prof_ny)
13052 obsmean[idx] += robs[i];
13057 for (ip = 0; ip < atm->
np; ip++) {
13060 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13064 const int ix = (int) ((atm->
lon[ip] - ctl->
prof_lon0) / dlon);
13065 const int iy = (int) ((atm->
lat[ip] - ctl->
prof_lat0) / dlat);
13066 const int iz = (int) ((
Z(atm->
p[ip]) - ctl->
prof_z0) / dz);
13069 if (ix < 0 || ix >= ctl->
prof_nx ||
13075 mass[idx] += atm->
q[ctl->
qnt_m][ip];
13079 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
13080 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
13082 if (obscount[idx2] > 0) {
13086 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
13088 if (mass[idx3] > 0) {
13097 fprintf(out,
"\n");
13100 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
13105 lon[ix], lat[iy], &temp, ci, cw, 1);
13107 lon[ix], lat[iy], &h2o, ci, cw, 0);
13109 lon[ix], lat[iy], &o3, ci, cw, 0);
13114 / (
RHO(press[iz], temp) * area[iy] * dz * 1e9);
13117 fprintf(out,
"%.2f %g %g %g %g %g %g %g %g %g %d\n",
13118 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
13119 obsmean[idx2] / obscount[idx2], obscount[idx2]);
13152 const char *filename,
13161 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[
EP],
13164 static int nobs, nk;
13177 ALLOC(rlon,
double,
13179 ALLOC(rlat,
double,
13181 ALLOC(robs,
double,
13192 LOG(1,
"Write sample data: %s", filename);
13193 if (!(out = fopen(filename,
"w")))
13194 ERRMSG(
"Cannot create file!");
13198 "# $1 = time [s]\n"
13199 "# $2 = altitude [km]\n"
13200 "# $3 = longitude [deg]\n"
13201 "# $4 = latitude [deg]\n"
13202 "# $5 = surface area [km^2]\n"
13203 "# $6 = layer depth [km]\n"
13204 "# $7 = number of particles [1]\n"
13205 "# $8 = column density [kg/m^2]\n"
13206 "# $9 = volume mixing ratio [ppv]\n"
13207 "# $10 = observed BT index [K]\n\n");
13212 area = M_PI * rmax2;
13216 const double t0 = t - 0.5 * ctl->
dt_mod;
13217 const double t1 = t + 0.5 * ctl->
dt_mod;
13220 for (
int i = 0; i < nobs; i++) {
13225 else if (rt[i] >= t1)
13230 geo2cart(0, rlon[i], rlat[i], x0);
13233 const double rp =
P(rz[i]);
13234 const double ptop =
P(rz[i] + ctl->
sample_dz);
13235 const double pbot =
P(rz[i] - ctl->
sample_dz);
13243 for (
int ip = 0; ip < atm->
np; ip++) {
13246 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13250 if (fabs(rlat[i] - atm->
lat[ip]) > dlat)
13256 if (
DIST2(x0, x1) > rmax2)
13261 if (atm->
p[ip] > pbot || atm->
p[ip] < ptop)
13265 if (ctl->
qnt_m >= 0)
13272 const double cd = mass / (1e6 * area);
13283 rlon[i], rlat[i], &temp, ci, cw, 1);
13292 fprintf(out,
"%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
13293 rlon[i], rlat[i], area, ctl->
sample_dz, np, cd, vmr, robs[i]);
13314 const char *filename,
13321 static double rmax2, x0[3], x1[3];
13330 LOG(1,
"Write station data: %s", filename);
13333 if (!(out = fopen(filename,
"w")))
13334 ERRMSG(
"Cannot create file!");
13338 "# $1 = time [s]\n"
13339 "# $2 = altitude [km]\n"
13340 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
13341 for (
int iq = 0; iq < ctl->
nq; iq++)
13342 fprintf(out,
"# $%i = %s [%s]\n", (iq + 5),
13344 fprintf(out,
"\n");
13352 const double t0 = t - 0.5 * ctl->
dt_mod;
13353 const double t1 = t + 0.5 * ctl->
dt_mod;
13356 for (
int ip = 0; ip < atm->
np; ip++) {
13359 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13375 if (
DIST2(x0, x1) > rmax2)
13383 fprintf(out,
"%.2f %g %g %g",
13384 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]);
13385 for (
int iq = 0; iq < ctl->
nq; iq++) {
13387 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
13389 fprintf(out,
"\n");
13400 const char *filename,
13411 LOG(1,
"Write VTK data: %s", filename);
13414 const double t0 = t - 0.5 * ctl->
dt_mod;
13415 const double t1 = t + 0.5 * ctl->
dt_mod;
13418 if (!(out = fopen(filename,
"w")))
13419 ERRMSG(
"Cannot create file!");
13423 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13424 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13431 "# vtk DataFile Version 3.0\n"
13432 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
13435 fprintf(out,
"POINTS %d float\n", np);
13437 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13438 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13442 const double coslat = cos(
DEG2RAD(atm->
lat[ip]));
13443 const double x = radius * coslat * cos(
DEG2RAD(atm->
lon[ip]));
13444 const double y = radius * coslat * sin(
DEG2RAD(atm->
lon[ip]));
13445 const double z = radius * sin(
DEG2RAD(atm->
lat[ip]));
13446 fprintf(out,
"%g %g %g\n", x, y, z);
13449 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13450 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13452 fprintf(out,
"%g %g %g\n", atm->
lon[ip], atm->
lat[ip],
13457 fprintf(out,
"POINT_DATA %d\n", np);
13458 for (
int iq = 0; iq < ctl->
nq; iq++) {
13459 fprintf(out,
"SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
13461 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13462 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13464 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).