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;
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];
1100 (
"DD: Particle is outside the domain (lon: %f, lat: %f, subdomain: %d, subdomain bounds: [%f, %f], [%f, %f])",
1109#pragma acc exit data delete(dd)
1115#pragma acc enter data create(dd)
1116#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)
1117#pragma acc data present(atm, ctl, dd)
1118#pragma acc parallel loop independent gang vector
1120 for (
int ip = 0; ip < atm->
np; ip++) {
1126 double lont = atm->
lon[ip];
1127 double latt = atm->
lat[ip];
1142 bound = (lont - lon_max > 90) ? 1 : 0;
1144 bound = (lon_min - lont > 90) ? 1 : 0;
1147 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)) {
1159 "DD: Particle crossing to lower right: from rank %d to rank %d (lon: %f, lat: %f)",
1161 }
else if ((lont <= lon_min) && (latt >= lat_max)) {
1166 "DD: Particle crossing to upper left: from rank %d to rank %d (lon: %f, lat: %f)",
1168 }
else if ((lont <= lon_min) && (latt <= lat_min)) {
1173 "DD: Particle crossing to lower left: from rank %d to rank %d (lon: %f, lat: %f)",
1175 }
else if (lont >= lon_max) {
1180 "DD: Particle crossing to right: from rank %d to rank %d (lon: %f, lat: %f)",
1182 }
else if (lont <= lon_min) {
1187 "DD: Particle crossing to left: from rank %d to rank %d (lon: %f, lat: %f)",
1189 }
else if (latt <= lat_min) {
1194 "DD: Particle crossing downward: from rank %d to rank %d (lon: %f, lat: %f)",
1196 }
else if (latt >= lat_max) {
1201 "DD: Particle crossing upward: from rank %d to rank %d (lon: %f, lat: %f)",
1209 if ((lont >= lon_max) && (latt >= lat_max)) {
1214 "DD: Particle crossing to upper left (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1216 }
else if ((lont >= lon_max) && (latt <= lat_min)) {
1221 "DD: Particle crossing to lower left (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1223 }
else if ((lont <= lon_min) && (latt >= lat_max)) {
1228 "DD: Particle crossing to upper right (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1230 }
else if ((lont <= lon_min) && (latt <= lat_min)) {
1235 "DD: Particle crossing to lower right (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1237 }
else if (lont >= lon_max) {
1242 "DD: Particle crossing to left (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1244 }
else if (lont <= lon_min) {
1249 "DD: Particle crossing to right (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1251 }
else if (latt <= lat_min) {
1256 "DD: Particle crossing downward (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1258 }
else if (latt >= lat_max) {
1263 "DD: Particle crossing upward (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1273#pragma acc exit data delete(dd)
1294 int npart = *nparticles;
1295#pragma acc enter data create( nparticles, particles[:DD_NPART])
1296#pragma acc update device( nparticles)
1297#pragma acc parallel loop present( atm, ctl, particles, cache, nparticles)
1299 for (
int ip = atm->
np; ip < atm->np + *nparticles; ip++)
1304 particles[ip - atm->
np].
time = atm->
time[ip];
1305 particles[ip - atm->
np].
lon = atm->
lon[ip];
1306 particles[ip - atm->
np].
lat = atm->
lat[ip];
1307 particles[ip - atm->
np].
p = atm->
p[ip];
1308 for (
int iq = 0; iq < ctl->
nq; iq++)
1309 particles[ip - atm->
np].q[iq] = atm->
q[iq][ip];
1312 "DD: Particle being prepared for transfer: subdomain %d -> destination %d (lon: %f, lat: %f)",
1319#pragma acc update host( particles[:npart])
1320#pragma acc exit data delete( nparticles, particles)
1338 double wrapped_lon = lon;
1339 while (wrapped_lon < 0)
1341 while (wrapped_lon >= 360)
1345 double wrapped_lat = lat;
1349 wrapped_lat = 180 - lat;
1350 wrapped_lon = fmod(wrapped_lon + 180, 360);
1351 }
else if (lat < -90) {
1354 wrapped_lat = -180 - lat;
1355 wrapped_lon = fmod(wrapped_lon + 180, 360);
1359 double lon_range = 360.0;
1360 LOG(2,
"nx_glob: %d", nx_glob);
1361 double lat_range = met->
lat[ny_glob - 1] - met->
lat[0];
1362 double global_lon_min = met->
lon[0];
1363 double global_lat_min = met->
lat[0];
1367 (int) ((wrapped_lon -
1370 (int) ((wrapped_lat -
1375 (
"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",
1376 lon, lat, wrapped_lon, wrapped_lat, lon_range, lat_range, global_lon_min,
1377 global_lat_min, lon_idx, lat_idx);
1382 0) ? 0 : ((lon_idx >=
1387 0) ? 0 : ((lat_idx >=
1389 dd_subdomains_meridional - 1 : lat_idx);
1395 if (target_rank >= mpi_size)
1396 target_rank = mpi_size - 1;
1397 if (target_rank < 0)
1427 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
1430 MPI_Request *requests_snd_nbr =
1431 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1432 MPI_Request *requests_rcv_nbr =
1433 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1434 MPI_Request *requests_snd_part =
1435 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1436 MPI_Request *requests_rcv_part =
1437 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1438 MPI_Status *states =
1439 (MPI_Status *) calloc((
size_t) nneighbours,
sizeof(MPI_Status));
1442 for (
int i = 0; i < nneighbours; i++) {
1443 requests_snd_nbr[i] = MPI_REQUEST_NULL;
1444 requests_rcv_nbr[i] = MPI_REQUEST_NULL;
1445 requests_snd_part[i] = MPI_REQUEST_NULL;
1446 requests_rcv_part[i] = MPI_REQUEST_NULL;
1450 for (
int idest = 0; idest < nneighbours; idest++) {
1453 if (neighbours[idest] < 0)
1459 for (
int ip = 0; ip < *nparticles; ip++)
1462 nbs[idest] = help_sum;
1465 LOG(3,
"DD: Rank %d sending %d particles to neighbour %d (rank %d)",
1466 rank, help_sum, idest, neighbours[idest]);
1471 MPI_Isend(&nbs[idest], 1, MPI_INT,
1472 neighbours[idest], 0, MPI_COMM_WORLD, &requests_snd_nbr[idest]);
1475 if (nbs[idest] == 0)
1484 for (
int ip = 0; ip < *nparticles; ip++) {
1485 if ((
int) particles[ip].q[ctl.
qnt_destination] == neighbours[idest]) {
1486 memcpy(&send_buffers[idest][ibs], &particles[ip],
sizeof(
particle_t));
1490 if (ibs == nbs[idest])
1497 MPI_Isend(send_buffers[idest], nbs[idest], MPI_Particle,
1498 neighbours[idest], 1, MPI_COMM_WORLD,
1499 &requests_snd_part[idest]);
1505 for (
int isourc = 0; isourc < nneighbours; isourc++) {
1508 if (neighbours[isourc] < 0) {
1509 requests_rcv_nbr[isourc] = MPI_REQUEST_NULL;
1514 MPI_Irecv(&nbr[isourc], 1, MPI_INT, neighbours[isourc], 0, MPI_COMM_WORLD,
1515 &requests_rcv_nbr[isourc]);
1519 MPI_Waitall(nneighbours, requests_rcv_nbr, states);
1522 for (
int isourc = 0; isourc < nneighbours; isourc++) {
1525 if ((neighbours[isourc] < 0) || (nbr[isourc] == 0)) {
1526 requests_rcv_part[isourc] = MPI_REQUEST_NULL;
1534 MPI_Irecv(recieve_buffers[isourc], nbr[isourc], MPI_Particle,
1535 neighbours[isourc], 1, MPI_COMM_WORLD,
1536 &requests_rcv_part[isourc]);
1540 MPI_Waitall(nneighbours, requests_rcv_part, states);
1548 for (
int isourc = 0; isourc < nneighbours; isourc++) {
1551 if (neighbours[isourc] < 0)
1554 if (nbr[isourc] > 0) {
1555 LOG(3,
"DD: Rank %d receiving %d particles from neighbour %d (rank %d)",
1556 rank, nbr[isourc], isourc, neighbours[isourc]);
1560 for (
int ip = 0; ip < nbr[isourc]; ip++) {
1561 memcpy(&particles[ip + api], &recieve_buffers[isourc][ip],
1575 MPI_Waitall(nneighbours, requests_snd_part, states);
1576 MPI_Waitall(nneighbours, requests_snd_nbr, states);
1579 for (
int i = 0; i < nneighbours; i++) {
1581 if ((send_buffers[i] != NULL) && (nbs[i] != 0)) {
1582 free(send_buffers[i]);
1583 send_buffers[i] = NULL;
1586 if ((recieve_buffers[i] != NULL) && (nbr[i] != 0)) {
1587 free(recieve_buffers[i]);
1588 recieve_buffers[i] = NULL;
1605 const int rank = dd->
rank;
1606 const int size = dd->
size;
1610 nb[0] = (size + rank - m) % size;
1611 nb[3] = (rank + m) % size;
1612 nb[1] = ((rank + 1) % m == 0) ?
DD_SPOLE : (size + rank - m + 1) % size;
1613 nb[2] = (rank % m == 0) ?
DD_NPOLE : (size + rank - m - 1) % size;
1614 nb[4] = ((rank + 1) % m == 0) ?
DD_SPOLE : (rank + m + 1) % size;
1615 nb[5] = (rank % m == 0) ?
DD_NPOLE : (rank + m - 1) % size;
1616 nb[6] = (rank % m == 0) ?
DD_NPOLE : rank - 1;
1617 nb[7] = ((rank + 1) % m == 0) ?
DD_SPOLE : rank + 1;
1633 double lon_spacing = met->
lon[1] - met->
lon[0];
1637 double total_range = met->
lon[nx_glob - 1] - met->
lon[0] + lon_spacing;
1640 return (fabs(total_range - 360.0) < 0.01);
1654 ERRMSG(
"The number of tasks and subdomains is not identical.");
1683 int npart = *nparticles;
1684#pragma acc enter data create(nparticles, particles[:DD_NPART])
1685#pragma acc update device(particles[:npart], nparticles)
1686#pragma acc data present(atm, ctl, cache, particles, nparticles)
1687#pragma acc parallel loop
1689 for (
int ip = atm->
np; ip < atm->np + *nparticles; ip++) {
1690 atm->
time[ip] = particles[ip - atm->
np].
time;
1691 atm->
lon[ip] = particles[ip - atm->
np].
lon;
1692 atm->
lat[ip] = particles[ip - atm->
np].
lat;
1693 atm->
p[ip] = particles[ip - atm->
np].
p;
1694 for (
int iq = 0; iq < ctl->
nq; iq++)
1695 atm->
q[iq][ip] = particles[ip - atm->
np].q[iq];
1699#pragma acc exit data delete(nparticles, particles)
1703 atm->
np += *nparticles;
1705#pragma acc update device(atm->np)
1708 ERRMSG(
"Number of particles to high. Increase NP!");
1718 MPI_Datatype types[5] = { MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE,
1719 MPI_DOUBLE, MPI_DOUBLE
1722 int blocklengths[5] = { 1, 1, 1, 1,
NQ };
1724 MPI_Aint displacements[5] = { offsetof(
particle_t, time),
1731 MPI_Type_create_struct(5, blocklengths, displacements, types, MPI_Particle);
1732 MPI_Type_commit(MPI_Particle);
1751 const int np = atm->
np;
1752 double amax = (met0->
nx * met0->
ny + met0->
ny) * met0->
np + met0->
np;
1754#pragma acc enter data create(amax, rank)
1755#pragma acc update device(rank, amax)
1756#pragma acc data present(ctl,met0,atm,dd,amax,rank)
1761#pragma acc parallel loop independent gang vector
1763#pragma omp parallel for default(shared)
1765 for (
int ip = 0; ip < np; ip++) {
1773 dd->a[ip] = amax + 1;
1775 dd->a[ip] = amax + 2;
1783#pragma acc host_data use_device(dd->a,dd->p)
1785 thrustSortWrapper(dd->a, np, dd->p);
1788 ERRMSG(
"GSL sort fallback not available on GPU, use THRUST!");
1790 gsl_sort_index((
size_t *) (dd->p), (dd->a), 1, (
size_t) np);
1798 for (
int iq = 0; iq < ctl->
nq; iq++)
1804#pragma acc parallel loop reduction(+:npt) present(atm, rank, ctl)
1806 for (
int ip = 0; ip < np; ip++)
1812 int nparticlest = 0;
1814#pragma acc parallel loop reduction(+:nparticlest) present(atm, rank, ctl)
1816 for (
int ip = npt; ip < np; ip++)
1822 *nparticles = nparticlest;
1826 for (
int ip = 0; ip < np; ip++)
1832 (
"DD: Rank %d: %d particles have subdomain index -1 and will be lost (kept: %d, to_send: %d, total_before: %d)",
1833 *rank, nlost, npt, nparticlest, np);
1838#pragma acc update device(atm->np)
1843 (
"Number of particles to send and recieve to small. Increase DD_NPART!");
1847#pragma acc exit data delete(amax, rank)
1862#pragma acc data present(dd,a)
1863#pragma acc parallel loop independent gang vector
1865#pragma omp parallel for default(shared)
1867 for (
int ip = 0; ip < np; ip++)
1868 dd->help[ip] = a[dd->p[ip]];
1870#pragma acc parallel loop independent gang vector
1872#pragma omp parallel
for default(shared)
1874 for (
int ip = 0; ip < np; ip++)
1875 a[ip] = dd->help[ip];
1888 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
1889 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
1894 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
1895 for (i = 11; i > 0; i--)
1899 *day = doy - d0l[i] + 1;
1901 for (i = 11; i > 0; i--)
1905 *day = doy - d0[i] + 1;
1916 double data[2 *
EX];
1920 ERRMSG(
"Too many data points!");
1923 gsl_fft_complex_wavetable *wavetable =
1924 gsl_fft_complex_wavetable_alloc((
size_t) n);
1925 gsl_fft_complex_workspace *workspace =
1926 gsl_fft_complex_workspace_alloc((
size_t) n);
1929 for (
int i = 0; i < n; i++) {
1930 data[2 * i] = fcReal[i];
1931 data[2 * i + 1] = fcImag[i];
1935 gsl_fft_complex_forward(data, 1, (
size_t) n, wavetable, workspace);
1938 for (
int i = 0; i < n; i++) {
1939 fcReal[i] = data[2 * i];
1940 fcImag[i] = data[2 * i + 1];
1944 gsl_fft_complex_wavetable_free(wavetable);
1945 gsl_fft_complex_workspace_free(workspace);
1956 const double radius = z +
RE;
1957 const double latrad =
DEG2RAD(lat);
1958 const double lonrad =
DEG2RAD(lon);
1959 const double coslat = cos(latrad);
1961 x[0] = radius * coslat * cos(lonrad);
1962 x[1] = radius * coslat * sin(lonrad);
1963 x[2] = radius * sin(latrad);
1972 const char *metbase,
1973 const double dt_met,
1980 int year, mon, day, hour, min, sec;
1984 t6 = floor(t / dt_met) * dt_met;
1986 t6 = ceil(t / dt_met) * dt_met;
1989 jsec2time(t6, &year, &mon, &day, &hour, &min, &sec, &r);
1994 sprintf(filename,
"%s_YYYY_MM_DD_HH.nc", metbase);
1996 sprintf(filename,
"%s_YYYY_MM_DD_HH.bin", metbase);
1998 sprintf(filename,
"%s_YYYY_MM_DD_HH.pck", metbase);
2000 sprintf(filename,
"%s_YYYY_MM_DD_HH.zfp", metbase);
2002 sprintf(filename,
"%s_YYYY_MM_DD_HH.zstd", metbase);
2004 sprintf(filename,
"%s_YYYY_MM_DD_HH.cms", metbase);
2006 sprintf(filename,
"%s_YYYY_MM_DD_HH.sz3", metbase);
2007 sprintf(repl,
"%d", year);
2009 sprintf(repl,
"%02d", mon);
2011 sprintf(repl,
"%02d", day);
2013 sprintf(repl,
"%02d", hour);
2019 sprintf(filename,
"%s_YYMMDDHH.nc", metbase);
2020 sprintf(repl,
"%d", year);
2022 sprintf(repl,
"%02d", year % 100);
2024 sprintf(repl,
"%02d", mon);
2026 sprintf(repl,
"%02d", day);
2028 sprintf(repl,
"%02d", hour);
2043 for (
int i = 0; i < 3; i++) {
2047 if (!(ch = strstr(orig, search)))
2049 strncpy(buffer, orig, (
size_t) (ch - orig));
2050 buffer[ch - orig] = 0;
2051 sprintf(buffer + (ch - orig),
"%s%s", repl, ch + strlen(search));
2053 strcpy(orig, buffer);
2060 const int met_tropo,
2080#pragma omp parallel for default(shared) private(ci,cw)
2081 for (
int ix = 0; ix < nx; ix++)
2082 for (
int iy = 0; iy < ny; iy++) {
2084 &pt[iy * nx + ix], ci, cw, 1);
2086 &ps[iy * nx + ix], ci, cw, 0);
2088 &zs[iy * nx + ix], ci, cw, 0);
2090 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
2092 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
2094 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
2096 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
2113 *lon2 =
FMOD(lon, 360.);
2114 if (*lon2 < lons[0])
2116 else if (*lon2 > lons[nlon - 1])
2121 if (lats[0] < lats[nlat - 1])
2122 *lat2 =
MIN(
MAX(*lat2, lats[0]), lats[nlat - 1]);
2124 *lat2 =
MIN(
MAX(*lat2, lats[nlat - 1]), lats[0]);
2131 float heights0[
EX][
EY][
EP],
2132 float array0[
EX][
EY][
EP],
2134 float heights1[
EX][
EY][
EP],
2135 float array1[
EX][
EY][
EP],
2137 const double height,
2163 int k_max = ind[0][0];
2164 for (
int i = 0; i < 2; i++)
2165 for (
int j = 0; j < 4; j++) {
2166 if (ci[2] > ind[i][j])
2168 if (k_max < ind[i][j])
2174 cw[0] = (lon2 - met0->
lon[ci[0]]) /
2175 (met0->
lon[ci[0] + 1] - met0->
lon[ci[0]]);
2176 cw[1] = (lat2 - met0->
lat[ci[1]]) /
2177 (met0->
lat[ci[1] + 1] - met0->
lat[ci[1]]);
2180 double height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2]]
2181 - heights0[ci[0]][ci[1]][ci[2]])
2182 + heights0[ci[0]][ci[1]][ci[2]];
2183 double height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2]]
2184 - heights0[ci[0]][ci[1] + 1][ci[2]])
2185 + heights0[ci[0]][ci[1] + 1][ci[2]];
2186 double height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2]]
2187 - heights0[ci[0] + 1][ci[1]][ci[2]])
2188 + heights0[ci[0] + 1][ci[1]][ci[2]];
2189 double height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2]]
2190 - heights0[ci[0] + 1][ci[1] + 1][ci[2]])
2191 + heights0[ci[0] + 1][ci[1] + 1][ci[2]];
2194 double height0 = cw[1] * (height01 - height00) + height00;
2195 double height1 = cw[1] * (height11 - height10) + height10;
2198 double height_bot = cw[0] * (height1 - height0) + height0;
2201 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
2202 - heights0[ci[0]][ci[1]][ci[2] + 1])
2203 + heights0[ci[0]][ci[1]][ci[2] + 1];
2204 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
2205 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
2206 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
2207 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
2208 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
2209 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
2210 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2211 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2212 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2215 height0 = cw[1] * (height01 - height00) + height00;
2216 height1 = cw[1] * (height11 - height10) + height10;
2219 double height_top = cw[0] * (height1 - height0) + height0;
2222 while (((heights0[0][0][0] > heights0[0][0][1]) &&
2223 ((height_bot <= height) || (height_top > height))
2224 && (height_bot >= height) && (ci[2] < k_max))
2226 ((heights0[0][0][0] < heights0[0][0][1]) &&
2227 ((height_bot >= height) || (height_top < height))
2228 && (height_bot <= height) && (ci[2] < k_max))
2232 height_bot = height_top;
2235 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
2236 - heights0[ci[0]][ci[1]][ci[2] + 1])
2237 + heights0[ci[0]][ci[1]][ci[2] + 1];
2238 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
2239 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
2240 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
2241 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
2242 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
2243 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
2244 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2245 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2246 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2249 height0 = cw[1] * (height01 - height00) + height00;
2250 height1 = cw[1] * (height11 - height10) + height10;
2253 height_top = cw[0] * (height1 - height0) + height0;
2257 cw[2] = (height - height_bot)
2258 / (height_top - height_bot);
2262 const double array000 = cw[3] * (array1[ci[0]][ci[1]][ci[2]]
2263 - array0[ci[0]][ci[1]][ci[2]])
2264 + array0[ci[0]][ci[1]][ci[2]];
2265 const double array100 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2]]
2266 - array0[ci[0] + 1][ci[1]][ci[2]])
2267 + array0[ci[0] + 1][ci[1]][ci[2]];
2268 const double array010 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2]]
2269 - array0[ci[0]][ci[1] + 1][ci[2]])
2270 + array0[ci[0]][ci[1] + 1][ci[2]];
2271 const double array110 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2]]
2272 - array0[ci[0] + 1][ci[1] + 1][ci[2]])
2273 + array0[ci[0] + 1][ci[1] + 1][ci[2]];
2274 const double array001 = cw[3] * (array1[ci[0]][ci[1]][ci[2] + 1]
2275 - array0[ci[0]][ci[1]][ci[2] + 1])
2276 + array0[ci[0]][ci[1]][ci[2] + 1];
2277 const double array101 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2] + 1]
2278 - array0[ci[0] + 1][ci[1]][ci[2] + 1])
2279 + array0[ci[0] + 1][ci[1]][ci[2] + 1];
2280 const double array011 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2] + 1]
2281 - array0[ci[0]][ci[1] + 1][ci[2] + 1])
2282 + array0[ci[0]][ci[1] + 1][ci[2] + 1];
2283 const double array111 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2284 - array0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2285 + array0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2287 const double array00 = cw[0] * (array100 - array000) + array000;
2288 const double array10 = cw[0] * (array110 - array010) + array010;
2289 const double array01 = cw[0] * (array101 - array001) + array001;
2290 const double array11 = cw[0] * (array111 - array011) + array011;
2292 const double aux0 = cw[1] * (array10 - array00) + array00;
2293 const double aux1 = cw[1] * (array11 - array01) + array01;
2296 *var = cw[2] * (aux1 - aux0) + aux0;
2326 cw[0] = (met->
p[ci[0] + 1] - p)
2327 / (met->
p[ci[0] + 1] - met->
p[ci[0]]);
2328 cw[1] = (met->
lon[ci[1] + 1] - lon2)
2329 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
2330 cw[2] = (met->
lat[ci[2] + 1] - lat2)
2331 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
2335 const double aux00 =
2336 cw[0] * (array[ci[1]][ci[2]][ci[0]] - array[ci[1]][ci[2]][ci[0] + 1])
2337 + array[ci[1]][ci[2]][ci[0] + 1];
2338 const double aux01 =
2339 cw[0] * (array[ci[1]][ci[2] + 1][ci[0]] -
2340 array[ci[1]][ci[2] + 1][ci[0] + 1])
2341 + array[ci[1]][ci[2] + 1][ci[0] + 1];
2342 const double aux10 =
2343 cw[0] * (array[ci[1] + 1][ci[2]][ci[0]] -
2344 array[ci[1] + 1][ci[2]][ci[0] + 1])
2345 + array[ci[1] + 1][ci[2]][ci[0] + 1];
2346 const double aux11 =
2347 cw[0] * (array[ci[1] + 1][ci[2] + 1][ci[0]] -
2348 array[ci[1] + 1][ci[2] + 1][ci[0] + 1])
2349 + array[ci[1] + 1][ci[2] + 1][ci[0] + 1];
2352 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
2353 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
2354 *var = cw[1] * (aux0 - aux1) + aux1;
2361 float array[
EX][
EY],
2382 cw[1] = (met->
lon[ci[1] + 1] - lon2)
2383 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
2384 cw[2] = (met->
lat[ci[2] + 1] - lat2)
2385 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
2389 const double aux00 = array[ci[1]][ci[2]];
2390 const double aux01 = array[ci[1]][ci[2] + 1];
2391 const double aux10 = array[ci[1] + 1][ci[2]];
2392 const double aux11 = array[ci[1] + 1][ci[2] + 1];
2395 if (isfinite(aux00) && isfinite(aux01)
2396 && isfinite(aux10) && isfinite(aux11)) {
2397 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
2398 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
2399 *var = cw[1] * (aux0 - aux1) + aux1;
2419 float array0[
EX][
EY][
EP],
2421 float array1[
EX][
EY][
EP],
2438 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
2441 *var = wt * (var0 - var1) + var1;
2448 float array0[
EX][
EY],
2450 float array1[
EX][
EY],
2466 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
2469 if (isfinite(var0) && isfinite(var1))
2470 *var = wt * (var0 - var1) + var1;
2481 float array0[
EX][
EY],
2483 float array1[
EX][
EY],
2484 const double lons[
EX],
2485 const double lats[
EY],
2504 const int ix =
locate_reg(lons, (
int) nlon, lon2);
2505 const int iy =
locate_irr(lats, (
int) nlat, lat2);
2509 for (
int dx = 0; dx < 2; dx++)
2510 for (
int dy = 0; dy < 2; dy++) {
2511 if (isfinite(array0[ix + dx][iy + dy])) {
2512 mean += array0[ix + dx][iy + dy];
2513 *sigma +=
SQR(array0[ix + dx][iy + dy]);
2516 if (isfinite(array1[ix + dx][iy + dy])) {
2517 mean += array1[ix + dx][iy + dy];
2518 *sigma +=
SQR(array1[ix + dx][iy + dy]);
2523 *sigma = sqrt(
MAX(*sigma / n -
SQR(mean / n), 0.0));
2526 if (method == 1 && isfinite(array0[ix][iy])
2527 && isfinite(array0[ix][iy + 1])
2528 && isfinite(array0[ix + 1][iy])
2529 && isfinite(array0[ix + 1][iy + 1])
2530 && isfinite(array1[ix][iy])
2531 && isfinite(array1[ix][iy + 1])
2532 && isfinite(array1[ix + 1][iy])
2533 && isfinite(array1[ix + 1][iy + 1])) {
2535 const double aux00 =
LIN(lons[ix], array0[ix][iy],
2536 lons[ix + 1], array0[ix + 1][iy], lon2);
2537 const double aux01 =
LIN(lons[ix], array0[ix][iy + 1],
2538 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
2539 const double aux0 =
LIN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
2541 const double aux10 =
LIN(lons[ix], array1[ix][iy],
2542 lons[ix + 1], array1[ix + 1][iy], lon2);
2543 const double aux11 =
LIN(lons[ix], array1[ix][iy + 1],
2544 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
2545 const double aux1 =
LIN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
2547 *var =
LIN(time0, aux0, time1, aux1, time);
2552 const double aux00 =
NN(lons[ix], array0[ix][iy],
2553 lons[ix + 1], array0[ix + 1][iy], lon2);
2554 const double aux01 =
NN(lons[ix], array0[ix][iy + 1],
2555 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
2556 const double aux0 =
NN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
2558 const double aux10 =
NN(lons[ix], array1[ix][iy],
2559 lons[ix + 1], array1[ix + 1][iy], lon2);
2560 const double aux11 =
NN(lons[ix], array1[ix][iy + 1],
2561 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
2562 const double aux1 =
NN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
2564 *var =
NN(time0, aux0, time1, aux1, time);
2589 const time_t jsec0 = (time_t) jsec + timegm(&t0);
2590 t1 = gmtime(&jsec0);
2592 *year = t1->tm_year + 1900;
2593 *mon = t1->tm_mon + 1;
2595 *hour = t1->tm_hour;
2598 *remain = jsec - floor(jsec);
2604 const double kz[
EP],
2605 const double kw[
EP],
2614 const double z =
Z(p);
2619 else if (z > kz[nk - 1])
2623 return LIN(kz[idx], kw[idx], kz[idx + 1], kw[idx + 1], z);
2640 const double a =
RA *
SQR(t), r =
SH(h2o) / (1. -
SH(h2o));
2654 const double press[138] = {
2655 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
2656 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
2657 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
2658 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
2659 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2660 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
2661 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
2662 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
2663 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
2664 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
2665 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
2666 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
2667 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
2668 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
2669 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
2670 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
2671 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
2672 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
2673 1010.8487, 1013.2500, 1044.45
2676 for (
int ip = 0; ip < ctl->
met_np; ip++)
2683 const double press[92] = {
2684 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
2685 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
2686 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
2687 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
2688 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
2690 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
2691 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
2692 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
2693 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
2694 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
2695 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
2696 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
2697 1007.4431, 1010.8487, 1013.2500, 1044.45
2700 for (
int ip = 0; ip < ctl->
met_np; ip++)
2707 const double press[60] = {
2708 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
2709 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
2710 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
2711 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
2712 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
2713 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
2714 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
2715 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1044.45
2718 for (
int ip = 0; ip < ctl->
met_np; ip++)
2725 const double press[147] = {
2726 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
2727 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
2728 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
2729 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
2730 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2731 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
2732 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
2733 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
2734 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
2735 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
2736 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
2737 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
2738 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
2739 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
2740 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
2741 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
2742 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
2743 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
2744 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73, 1028.85,
2746 1035.09, 1038.21, 1041.33, 1044.45
2749 for (
int ip = 0; ip < ctl->
met_np; ip++)
2756 const double press[101] = {
2757 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
2758 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
2759 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
2760 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
2761 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
2763 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
2764 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
2765 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
2766 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
2767 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
2768 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
2769 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
2770 1007.4431, 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73,
2772 1035.09, 1038.21, 1041.33, 1044.45
2775 for (
int ip = 0; ip < ctl->
met_np; ip++)
2782 const double press[62] = {
2783 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
2784 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
2785 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
2786 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
2787 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
2788 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
2789 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
2790 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1034.86, 1039.65,
2794 for (
int ip = 0; ip < ctl->
met_np; ip++)
2801 const double press[137] = {
2802 0.01, 0.02, 0.031, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861,
2803 0.2499, 0.3299, 0.4288, 0.5496, 0.6952, 0.869, 1.0742,
2804 1.3143, 1.5928, 1.9134, 2.2797, 2.6954, 3.1642, 3.6898,
2805 4.2759, 4.9262, 5.6441, 6.4334, 7.2974, 8.2397, 9.2634,
2806 10.372, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945, 18.9752,
2807 20.761, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2808 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.199, 54.5299,
2809 57.9834, 61.5607, 65.2695, 69.1187, 73.1187, 77.281, 81.6182,
2810 86.145, 90.8774, 95.828, 101.005, 106.415, 112.068, 117.971,
2811 124.134, 130.564, 137.27, 144.262, 151.549, 159.14, 167.045,
2812 175.273, 183.834, 192.739, 201.997, 211.619, 221.615, 231.995,
2813 242.772, 253.955, 265.556, 277.585, 290.055, 302.976, 316.361,
2814 330.22, 344.566, 359.411, 374.767, 390.645, 407.058, 424.019,
2815 441.539, 459.632, 478.31, 497.584, 517.42, 537.72, 558.343,
2816 579.193, 600.167, 621.162, 642.076, 662.808, 683.262, 703.347,
2817 722.979, 742.086, 760.6, 778.466, 795.64, 812.085, 827.776,
2818 842.696, 856.838, 870.2, 882.791, 894.622, 905.712, 916.081,
2819 925.757, 934.767, 943.14, 950.908, 958.104, 965.299, 972.495,
2820 979.69, 986.886, 994.081, 1001.28, 1008.47, 1015.67, 1022.86,
2821 1030.06, 1037.25, 1044.45
2824 for (
int ip = 0; ip < ctl->
met_np; ip++)
2831 const double press[59] = {
2832 0.1, 0.2, 0.3843, 0.6365, 0.9564, 1.3448, 1.8058, 2.3478,
2833 2.985, 3.7397, 4.6462, 5.7565, 7.1322, 8.8366, 10.9483,
2834 13.5647, 16.8064, 20.8227, 25.7989, 31.9642, 39.6029, 49.0671,
2835 60.1802, 73.0663, 87.7274, 104.229, 122.614, 142.902, 165.089,
2836 189.147, 215.025, 242.652, 272.059, 303.217, 336.044, 370.407,
2837 406.133, 443.009, 480.791, 519.209, 557.973, 596.777, 635.306,
2838 673.24, 710.263, 746.063, 780.346, 812.83, 843.263, 871.42,
2839 897.112, 920.189, 940.551, 958.148, 975.744, 993.341, 1010.94,
2843 for (
int ip = 0; ip < ctl->
met_np; ip++)
2847 ERRMSG(
"Use 0 for l137, 1 for l91, 2 for l60 or values between 3 and 7.");
2851 ERRMSG(
"Recompile with larger EP to use this pressure level definition.");
2864 int i = (ihi + ilo) >> 1;
2866 if (xx[i] < xx[i + 1])
2867 while (ihi > ilo + 1) {
2868 i = (ihi + ilo) >> 1;
2874 while (ihi > ilo + 1) {
2875 i = (ihi + ilo) >> 1;
2895 int i = (ihi + ilo) >> 1;
2897 if ((xx[ig] <= x && x < xx[ig + 1]) || (xx[ig] >= x && x > xx[ig + 1]))
2900 if (xx[i] < xx[i + 1])
2901 while (ihi > ilo + 1) {
2902 i = (ihi + ilo) >> 1;
2908 while (ihi > ilo + 1) {
2909 i = (ihi + ilo) >> 1;
2927 const int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
2941 float profiles[
EX][
EY][
EP],
2943 const int lon_ap_ind,
2944 const int lat_ap_ind,
2945 const double height_ap,
2951 np, height_ap, ind[0]);
2953 np, height_ap, ind[1]);
2955 np, height_ap, ind[2]);
2974 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2978 double dts, u[4], um = 0, v[4], vm = 0, w[4], wm = 0,
2982 for (
int i = 0; i < ctl->
advect; i++) {
2987 x[0] = atm->
lon[ip];
2988 x[1] = atm->
lat[ip];
2991 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
2992 x[0] = atm->
lon[ip] +
DX2DEG(dts * u[i - 1] / 1000., atm->
lat[ip]);
2993 x[1] = atm->
lat[ip] +
DY2DEG(dts * v[i - 1] / 1000.);
2994 x[2] = atm->
p[ip] + dts * w[i - 1];
2996 const double tm = atm->
time[ip] + dts;
3001 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3003 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3005 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
3011 met1, met1->
pl, met1->
ul,
3012 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3014 met1, met1->
pl, met1->
vl,
3015 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3017 met1, met1->
pl, met1->
wl,
3018 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
3024 k = (i == 0 ? 0.0 : 1.0);
3025 else if (ctl->
advect == 4)
3026 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
3033 atm->
time[ip] += cache->
dt[ip];
3034 atm->
lon[ip] +=
DX2DEG(cache->
dt[ip] * um / 1000.,
3035 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
3036 atm->
lat[ip] +=
DY2DEG(cache->
dt[ip] * vm / 1000.);
3037 atm->
p[ip] += cache->
dt[ip] * wm;
3049 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3055 atm->
time[ip], atm->
p[ip],
3056 atm->
lon[ip], atm->
lat[ip],
3057 &atm->
q[qnt][ip], ci, cw, 1);
3060 double dts, u[4], um = 0, v[4], vm = 0, wdot[4],
3061 wdotm = 0, x[3] = { 0, 0, 0 };
3064 for (
int i = 0; i < ctl->
advect; i++) {
3069 x[0] = atm->
lon[ip];
3070 x[1] = atm->
lat[ip];
3071 x[2] = atm->
q[qnt][ip];
3073 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
3074 x[0] = atm->
lon[ip] +
DX2DEG(dts * u[i - 1] / 1000., atm->
lat[ip]);
3075 x[1] = atm->
lat[ip] +
DY2DEG(dts * v[i - 1] / 1000.);
3076 x[2] = atm->
q[qnt][ip] + dts * wdot[i - 1];
3079 const double tm = atm->
time[ip] + dts;
3084 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3087 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3090 tm, x[2], x[0], x[1], &wdot[i], ci, cw, 0);
3095 k = (i == 0 ? 0.0 : 1.0);
3096 else if (ctl->
advect == 4)
3097 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
3101 wdotm += k * wdot[i];
3105 atm->
time[ip] += cache->
dt[ip];
3106 atm->
lon[ip] +=
DX2DEG(cache->
dt[ip] * um / 1000.,
3107 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
3108 atm->
lat[ip] +=
DY2DEG(cache->
dt[ip] * vm / 1000.);
3109 atm->
q[qnt][ip] += cache->
dt[ip] * wdotm;
3115 atm->
q[qnt][ip], atm->
lon[ip], atm->
lat[ip],
3116 &atm->
p[ip], ci, cw, 1);
3144 atm->
lon[ip], atm->
lat[ip], &atm->
p[ip], ci, cw, 1);
3169 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3205 if (atm->
p[ip] < pbl)
3257 ERRMSG(
"Molar mass is not defined!");
3263 const int ensemble_mode = (ctl->
nens > 0);
3264 const int np = atm->
np;
3268 const int ngrid = nx * ny * nz;
3269 const int nens = ensemble_mode ? ctl->
nens : 1;
3271 double *restrict
const z = (
double *) malloc((
size_t) nz *
sizeof(double));
3272 double *restrict
const press =
3273 (
double *) malloc((
size_t) nz *
sizeof(double));
3274 double *restrict
const mass =
3275 (
double *) calloc((
size_t) ngrid * (size_t) nens,
sizeof(
double));
3276 double *restrict
const area =
3277 (
double *) malloc((
size_t) ny *
sizeof(double));
3278 double *restrict
const lon =
3279 (
double *) malloc((
size_t) nx *
sizeof(double));
3280 double *restrict
const lat =
3281 (
double *) malloc((
size_t) ny *
sizeof(double));
3283 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
3284 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
3285 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
3294#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])
3295#pragma acc data present(ctl,met0,met1,atm,ixs,iys,izs,z,press,mass,area,lon,lat)
3296#pragma acc parallel loop independent gang vector
3298#pragma omp parallel for default(shared)
3300 for (
int iz = 0; iz < nz; iz++) {
3302 press[iz] =
P(z[iz]);
3306 const double t0 = tt - 0.5 * ctl->
dt_mod;
3307 const double t1 = tt + 0.5 * ctl->
dt_mod;
3311#pragma acc parallel loop independent gang vector
3313#pragma omp parallel for default(shared)
3315 for (
int ip = 0; ip < np; ip++) {
3319 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
3320 || ixs[ip] < 0 || ixs[ip] >= nx
3321 || iys[ip] < 0 || iys[ip] >= ny || izs[ip] < 0 || izs[ip] >= nz)
3327#pragma acc parallel loop independent gang vector
3329#pragma omp parallel for default(shared)
3331 for (
int ix = 0; ix < nx; ix++)
3335#pragma acc parallel loop independent gang vector
3337#pragma omp parallel for default(shared)
3339 for (
int iy = 0; iy < ny; iy++) {
3341 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
3346#pragma acc parallel loop independent gang vector
3348 for (
int ip = 0; ip < np; ip++) {
3350 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
3351 if (ensemble_mode) {
3352 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
3353 mass_idx += ens * ngrid;
3356#pragma acc atomic update
3358 mass[mass_idx] += atm->
q[ctl->
qnt_m][ip];
3364#pragma acc parallel loop independent gang vector
3366#pragma omp parallel for default(shared)
3368 for (
int ip = 0; ip < np; ip++)
3376 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
3379 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
3380 if (ensemble_mode) {
3381 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
3382 mass_idx += ens * ngrid;
3386 const double m = mass[mass_idx];
3388 / (
RHO(press[izs[ip]], temp) * area[iys[ip]] * dz * 1e9);
3393#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
3421 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3438 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
3440 atm->
lat[ip], atm->
p[ip]));
3442 atm->
lat[ip], atm->
p[ip]));
3444 atm->
lat[ip], atm->
p[ip]));
3464 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3472 double pbot = ps, ptop = ps;
3489 double cape, cin, pel;
3495 if (isfinite(cape) && cape >= ctl->
conv_cape
3497 ptop = GSL_MIN(ptop, pel);
3501 if (ptop != pbot && atm->
p[ip] >= ptop) {
3506 pbot, atm->
lon[ip], atm->
lat[ip], &tbot, ci, cw, 1);
3508 atm->
lon[ip], atm->
lat[ip], &ttop, ci, cw, 1);
3509 const double rhobot = pbot / tbot;
3510 const double rhotop = ptop / ttop;
3513 const double rho = rhobot + (rhotop - rhobot) * cache->
rs[ip];
3516 atm->
p[ip] =
LIN(rhobot, pbot, rhotop, ptop, rho);
3540 dd_sort(ctl, *met, atm, dd, &nparticles, &dd->
rank);
3574 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3577 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,clim,atm)") {
3586 const double aux = exp(-cache->
dt[ip] / tdec);
3587 if (ctl->
qnt_m >= 0) {
3590 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
3591 atm->
q[ctl->
qnt_m][ip] *= aux;
3616 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3624 float umean = 0, usig = 0, vmean = 0, vsig = 0, wmean = 0, wsig = 0;
3625 for (
int i = 0; i < 2; i++)
3626 for (
int j = 0; j < 2; j++)
3627 for (
int k = 0; k < 2; k++) {
3628 umean += met0->
u[ix + i][iy + j][iz + k];
3629 usig +=
SQR(met0->
u[ix + i][iy + j][iz + k]);
3630 vmean += met0->
v[ix + i][iy + j][iz + k];
3631 vsig +=
SQR(met0->
v[ix + i][iy + j][iz + k]);
3632 wmean += met0->
w[ix + i][iy + j][iz + k];
3633 wsig +=
SQR(met0->
w[ix + i][iy + j][iz + k]);
3635 umean += met1->
u[ix + i][iy + j][iz + k];
3636 usig +=
SQR(met1->
u[ix + i][iy + j][iz + k]);
3637 vmean += met1->
v[ix + i][iy + j][iz + k];
3638 vsig +=
SQR(met1->
v[ix + i][iy + j][iz + k]);
3639 wmean += met1->
w[ix + i][iy + j][iz + k];
3640 wsig +=
SQR(met1->
w[ix + i][iy + j][iz + k]);
3642 usig = usig / 16.f -
SQR(umean / 16.f);
3643 usig = (usig > 0 ? sqrtf(usig) : 0);
3644 vsig = vsig / 16.f -
SQR(vmean / 16.f);
3645 vsig = (vsig > 0 ? sqrtf(vsig) : 0);
3646 wsig = wsig / 16.f -
SQR(wmean / 16.f);
3647 wsig = (wsig > 0 ? sqrtf(wsig) : 0);
3650 const double r = 1 - 2 * fabs(cache->
dt[ip]) / ctl->
dt_met;
3651 const double r2 = sqrt(1 - r * r);
3655 cache->
uvwp[ip][0] =
3656 (float) (r * cache->
uvwp[ip][0] +
3661 cache->
uvwp[ip][1] =
3662 (float) (r * cache->
uvwp[ip][1] +
3669 cache->
uvwp[ip][2] =
3670 (float) (r * cache->
uvwp[ip][2] +
3672 atm->
p[ip] += cache->
uvwp[ip][2] * cache->
dt[ip];
3693 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3695 double dsigw_dz = 0.0, sig_u = 0.25, sig_w = 0.1,
3696 tau_u = 300., tau_w = 100.;
3705 if (atm->
p[ip] >= pbl) {
3708 const double p =
MIN(atm->
p[ip], ps);
3709 const double zs =
Z(ps);
3710 const double z = 1e3 * (
Z(p) - zs);
3711 const double zi = 1e3 * (
Z(pbl) - zs);
3712 const double zratio = z / zi;
3715 double ess, nss, h2o, t;
3720 const double rho =
RHO(p,
TVIRT(t, h2o));
3721 const double tau = sqrt(
SQR(ess) +
SQR(nss));
3722 const double ustar = sqrt(tau / rho);
3732 sig_u = 1e-2 + 2.0 * ustar * (1.0 - zratio);
3733 sig_w = 1e-2 + 1.3 * ustar * (1.0 - zratio);
3736 dsigw_dz = -1.3 * ustar / zi;
3739 tau_u = 0.07 * zi / sig_u * sqrt(zratio);
3740 tau_w = 0.1 * zi / sig_w * pow(zratio, 0.8);
3747 const double wstar =
3748 pow(
G0 /
THETAVIRT(p, t, h2o) * shf / (rho *
CPD) * zi, 1. / 3.);
3752 + sqrt(0.4 *
SQR(wstar) + (5.0 - 4.0 * zratio) *
SQR(ustar));
3753 sig_w = 1e-2 + sqrt(1.2 *
SQR(wstar) * (1.0 - 0.9 * zratio)
3754 * pow(zratio, 2.0 / 3.0)
3755 + (1.8 - 1.4 * zratio) *
SQR(ustar));
3758 dsigw_dz = 0.5 / sig_w / zi * (-1.4 *
SQR(ustar) +
SQR(wstar)
3760 pow(
MAX(zratio, 1e-3), -1.0 / 3.0)
3761 - 1.8 * pow(zratio, 2.0 / 3.0)));
3764 const double C0 = 3.0;
3766 (1.5 - 1.2 * pow(zratio, 1.0 / 3.0)) *
SQR(wstar) * wstar / zi
3767 +
SQR(ustar) * ustar * (1.0 - 0.8 * zratio) / (
KARMAN * z);
3768 tau_u = 2 *
SQR(sig_u) / (C0 * eps);
3769 tau_w = 2 *
SQR(sig_w) / (C0 * eps);
3774 sig_u =
MAX(sig_u, 0.25);
3775 sig_w =
MAX(sig_w, 0.1);
3776 tau_u =
MAX(tau_u, 300.);
3777 tau_w =
MAX(tau_w, 100.);
3780 const double ru = exp(-fabs(cache->
dt[ip]) / tau_u);
3781 const double ru2 = sqrt(1.0 -
SQR(ru));
3783 = (float) (cache->
uvwp[ip][0] * ru + ru2 * cache->
rs[3 * ip]);
3785 = (float) (cache->
uvwp[ip][1] * ru + ru2 * cache->
rs[3 * ip + 1]);
3787 const double rw = exp(-fabs(cache->
dt[ip]) / tau_w);
3788 const double rw2 = sqrt(1.0 -
SQR(rw));
3790 = (float) (cache->
uvwp[ip][2] * rw + rw2 * cache->
rs[3 * ip + 2]
3791 + sig_w * dsigw_dz * cache->
dt[ip]);
3798 DZ2DP(cache->
uvwp[ip][2] * cache->
dt[ip] / 1000., atm->
p[ip]);
3820 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3829 const double wpbl =
pbl_weight(ctl, atm, ip, pbl, ps);
3830 const double wtrop =
tropo_weight(clim, atm, ip) * (1.0 - wpbl);
3831 const double wstrat = 1.0 - wpbl - wtrop;
3841 const double sigma = sqrt(2.0 * dx * fabs(cache->
dt[ip])) / 1000.;
3843 atm->
lat[ip] +=
DY2DEG(cache->
rs[3 * ip + 1] * sigma);
3848 const double sigma = sqrt(2.0 * dz * fabs(cache->
dt[ip])) / 1000.;
3849 atm->
p[ip] +=
DZ2DP(cache->
rs[3 * ip + 2] * sigma, atm->
p[ip]);
3868 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3871 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3883 const double dz = 1000. * (
Z(ps - ctl->
dry_depo_dp) -
Z(ps));
3903 const double aux = exp(-cache->
dt[ip] * v_dep / dz);
3904 if (ctl->
qnt_m >= 0) {
3907 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
3908 atm->
q[ctl->
qnt_m][ip] *= aux;
3932 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3935 const double a = 3.12541941e-06;
3936 const double b = -5.72532259e-01;
3937 const double low = pow(1. / a, 1. / b);
3940 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3947 if (!(lwc > 0 || rwc > 0))
3958 const double k = 9.1e7 * exp(-29700. /
RI * (1. / t - 1. / 298.15));
3961 const double H_SO2 =
3962 1.3e-2 * exp(2900. * (1. / t - 1. / 298.15)) *
RI * t;
3963 const double K_1S = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
3966 const double H_h2o2 =
3967 8.3e2 * exp(7600. * (1. / t - 1. / 298.15)) *
RI * t;
3973 cor = atm->
q[ctl->
qnt_Cx][ip] >
3974 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
3976 const double h2o2 = H_h2o2
3978 * M * cor * 1000. /
AVO;
3981 const double rho_air = atm->
p[ip] / (
RI * t) *
MA / 10.;
3982 const double CWC = (lwc + rwc) * rho_air / 1e3;
3985 const double rate_coef = k * K_1S * h2o2 * H_SO2 * CWC;
3986 const double aux = exp(-cache->
dt[ip] * rate_coef);
3987 if (ctl->
qnt_m >= 0) {
3990 atm->
q[ctl->
qnt_m][ip] *= aux;
4022 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
4025 cache->
iso_var[ip] = atm->
p[ip] / t;
4031 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
4042 LOG(1,
"Read balloon pressure data: %s", ctl->
balloon);
4046 if (!(in = fopen(ctl->
balloon,
"r")))
4047 ERRMSG(
"Cannot open file!");
4051 while (fgets(line,
LEN, in))
4052 if (sscanf(line,
"%lg %lg", &(cache->
iso_ts[cache->
iso_n]),
4055 ERRMSG(
"Too many data points!");
4058 if (cache->
iso_n < 1)
4059 ERRMSG(
"Could not read any data!");
4082 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,met1,atm)") {
4095 atm->
p[ip] = cache->
iso_var[ip] * t;
4101 atm->
p[ip] = 1000. * pow(cache->
iso_var[ip] / t, -1. / 0.286);
4107 atm->
p[ip] = cache->
iso_ps[0];
4135 const int nvar = NVAR, nfix = NFIX, nreact = NREACT;
4136 double rtol[1] = { 1.0e-3 };
4137 double atol[1] = { 1.0 };
4141#pragma acc data copy(rtol,atol,nvar,nfix,nreact)
4144 "acc data present(ctl,cache,clim,met0,met1,atm) ") {
4147 double var[nvar], fix[nfix], rconst[nreact];
4148 for (
int i = 0; i < nvar; i++)
4150 for (
int i = 0; i < nfix; i++)
4152 for (
int i = 0; i < nreact; i++)
4154 kpp_chem_initialize(ctl, clim, met0, met1, atm, var, fix, rconst, ip);
4159 for (
int i = 0; i < 20; i++) {
4166 Rosenbrock(var, fix, rconst, 0, ctl->
dt_kpp,
4167 atol, rtol, &FunTemplate, &JacTemplate, rpar, ipar);
4170 kpp_chem_output2atm(atm, ctl, met0, met1, var, ip);
4191 ERRMSG(
"Need T_ice and T_NAT to calculate T_STS!");
4195 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4197 double ps, ts, zs, us, vs, ess, nss, shf, lsm, sst, pbl, pt, pct, pcb,
4198 cl, plcl, plfc, pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot,
4199 o3, lwc, rwc, iwc, swc, cc, z, zt;
4247 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
4249 atm->
lat[ip], atm->
p[ip]));
4251 atm->
lat[ip], atm->
p[ip]));
4253 atm->
lat[ip], atm->
p[ip]));
4254 SET_ATM(qnt_vh, sqrt(u * u + v * v));
4276 atm->
lat[ip], atm->
p[ip])));
4294 const int np = atm->
np;
4295 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
4296 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
4297 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
4305 const double t0 = t - 0.5 * ctl->
dt_mod;
4306 const double t1 = t + 0.5 * ctl->
dt_mod;
4310#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
4311#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
4312#pragma acc parallel loop independent gang vector
4314#pragma omp parallel for default(shared)
4316 for (
int ip = 0; ip < np; ip++) {
4319 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
mixing_z0) / dz);
4320 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
4321 || ixs[ip] < 0 || ixs[ip] >= ctl->
mixing_nx
4322 || iys[ip] < 0 || iys[ip] >= ctl->
mixing_ny
4323 || izs[ip] < 0 || izs[ip] >= ctl->
mixing_nz)
4328 const int use_ensemble = (ctl->
nens > 0);
4330 const int quantities[] = {
4338 const int n_qnt =
sizeof(quantities) /
sizeof(quantities[0]);
4340 for (
int i = 0; i < n_qnt; i++)
4341 if (quantities[i] >= 0)
4347#pragma acc exit data delete(ixs,iys,izs)
4364 const int use_ensemble) {
4366 const int np = atm->
np;
4368 const int nens = use_ensemble ? ctl->
nens : 1;
4369 const int total_grid = ngrid * nens;
4371 double *restrict
const cmean =
4372 (
double *) malloc((
size_t) total_grid *
sizeof(double));
4373 int *restrict
const count =
4374 (
int *) malloc((
size_t) total_grid *
sizeof(int));
4378#pragma acc enter data create(cmean[0:total_grid],count[0:total_grid])
4379#pragma acc data present(ctl,clim,atm,ixs,iys,izs,cmean,count)
4380#pragma acc parallel loop independent gang vector
4385#pragma omp parallel for
4387 for (
int i = 0; i < total_grid; i++) {
4394#pragma acc parallel loop independent gang vector
4396 for (
int ip = 0; ip < np; ip++)
4398 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
4403#pragma acc atomic update
4405 cmean[idx] += atm->
q[qnt_idx][ip];
4407#pragma acc atomic update
4414#pragma acc parallel loop independent gang vector
4419#pragma omp parallel for
4421 for (
int i = 0; i < total_grid; i++)
4423 cmean[i] /= count[i];
4427#pragma acc parallel loop independent gang vector
4429#pragma omp parallel for
4431 for (
int ip = 0; ip < np; ip++) {
4433 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
4435 double mixparam = 1.0;
4444 atm->
q[qnt_idx][ip] += (cmean[idx] - atm->
q[qnt_idx][ip]) * mixparam;
4450#pragma acc exit data delete(cmean,count)
4471 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4474 const double a = 4.71572206e-08;
4475 const double b = -8.28782867e-01;
4476 const double low = pow(1. / a, 1. / b);
4480 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4506 0 ? pow(298. / t, ctl->
oh_chem[1]) : 1.);
4509 0 ? pow(298. / t, ctl->
oh_chem[3]) : 1.);
4510 const double c = log10(k0 * M / ki);
4511 k = k0 * M / (1. + k0 * M / ki) * pow(0.6, 1. / (1. + c * c));
4520 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
4523 const double rate_coef =
4525 atm->
lat[ip], atm->
p[ip]) * M * cor;
4526 const double aux = exp(-cache->
dt[ip] * rate_coef);
4527 if (ctl->
qnt_m >= 0) {
4530 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
4531 atm->
q[ctl->
qnt_m][ip] *= aux;
4552 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(cache,met0,met1,atm)") {
4563 while (atm->
lat[ip] < -90 || atm->
lat[ip] > 90) {
4564 if (atm->
lat[ip] > 90) {
4565 atm->
lat[ip] = 180 - atm->
lat[ip];
4566 atm->
lon[ip] += 180;
4568 if (atm->
lat[ip] < -90) {
4569 atm->
lat[ip] = -180 - atm->
lat[ip];
4570 atm->
lon[ip] += 180;
4575 while (atm->
lon[ip] < -180)
4576 atm->
lon[ip] += 360;
4577 while (atm->
lon[ip] >= 180)
4578 atm->
lon[ip] -= 360;
4581 if (atm->
p[ip] < met0->
p[met0->
np - 1]) {
4582 atm->
p[ip] = met0->
p[met0->
np - 1];
4583 }
else if (atm->
p[ip] > 300.) {
4585 if (atm->
p[ip] > ps)
4602 const double lambda_rn222 = log(2.0) / (3.8235 * 86400.0);
4603 const double lambda_pb210 = log(2.0) / (22.3 * 365.25 * 86400.0);
4604 const double lambda_be7 = log(2.0) / (53.22 * 86400.0);
4605 const double lambda_cs137 = log(2.0) / (30.05 * 365.25 * 86400.0);
4606 const double lambda_i131 = log(2.0) / (8.02 * 86400.0);
4607 const double lambda_xe133 = log(2.0) / (5.2474 * 86400.0);
4613 const double dt = cache->
dt[ip];
4617 atm->
q[ctl->
qnt_Apb210][ip] *= exp(-dt * lambda_pb210);
4622 const double aux = exp(-dt * lambda_rn222);
4623 const double lost = old * (1.0 - aux);
4628 atm->
q[ctl->
qnt_Apb210][ip] += lost * lambda_pb210 / lambda_rn222;
4633 atm->
q[ctl->
qnt_Abe7][ip] *= exp(-dt * lambda_be7);
4637 atm->
q[ctl->
qnt_Acs137][ip] *= exp(-dt * lambda_cs137);
4641 atm->
q[ctl->
qnt_Ai131][ip] *= exp(-dt * lambda_i131);
4645 atm->
q[ctl->
qnt_Axe133][ip] *= exp(-dt * lambda_xe133);
4655 gsl_rng_env_setup();
4656 if (omp_get_max_threads() >
NTHREADS)
4657 ERRMSG(
"Too many threads!");
4658 for (
int i = 0; i <
NTHREADS; i++) {
4659 rng[i] = gsl_rng_alloc(gsl_rng_default);
4660 gsl_rng_set(rng[i], gsl_rng_default_seed
4661 + (
long unsigned) (ntask *
NTHREADS + i));
4666 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
4667 CURAND_STATUS_SUCCESS)
4668 ERRMSG(
"Cannot create random number generator!");
4669 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
4670 CURAND_STATUS_SUCCESS)
4671 ERRMSG(
"Cannot set seed for random number generator!");
4674 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
4675 CURAND_STATUS_SUCCESS)
4676 ERRMSG(
"Cannot set stream for random number generator!");
4693#pragma omp parallel for default(shared)
4694 for (
size_t i = 0; i < n; ++i)
4695 rs[i] = gsl_rng_uniform(rng[omp_get_thread_num()]);
4699 else if (method == 1) {
4700#pragma omp parallel for default(shared)
4701 for (
size_t i = 0; i < n; ++i)
4702 rs[i] = gsl_ran_gaussian_ziggurat(rng[omp_get_thread_num()], 1.0);
4708#pragma acc update device(rs[:n])
4716 const uint64_t key = 0xc8e4fd154ce32f6d;
4720#pragma acc data present(rs)
4721#pragma acc parallel loop independent gang vector
4723#pragma omp parallel for default(shared)
4725 for (
size_t i = 0; i < n + 1; ++i) {
4726 uint64_t r, t, x, y, z;
4727 y = x = (rng_ctr + i) * key;
4730 x = (x >> 32) | (x << 32);
4732 x = (x >> 32) | (x << 32);
4734 x = (x >> 32) | (x << 32);
4736 x = (x >> 32) | (x << 32);
4737 r = t ^ ((x * x + y) >> 32);
4738 rs[i] = (double) r / (
double) UINT64_MAX;
4745#pragma acc parallel loop independent gang vector
4747#pragma omp parallel for default(shared)
4749 for (
size_t i = 0; i < n; i += 2) {
4750 const double r = sqrt(-2.0 * log(rs[i]));
4751 const double phi = 2.0 * M_PI * rs[i + 1];
4752 rs[i] = r * cosf((
float) phi);
4753 rs[i + 1] = r * sinf((
float) phi);
4761#pragma acc host_data use_device(rs)
4766 if (curandGenerateUniformDouble(rng_curand, rs, (n < 4 ? 4 : n)) !=
4767 CURAND_STATUS_SUCCESS)
4768 ERRMSG(
"Cannot create random numbers!");
4772 else if (method == 1) {
4773 if (curandGenerateNormalDouble
4774 (rng_curand, rs, (n < 4 ? 4 : n), 0.0,
4775 1.0) != CURAND_STATUS_SUCCESS)
4776 ERRMSG(
"Cannot create random numbers!");
4780 ERRMSG(
"MPTRAC was compiled without cuRAND!");
4798 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4806 const double v_s =
sedi(atm->
p[ip], t, atm->
q[ctl->
qnt_rp][ip],
4810 atm->
p[ip] +=
DZ2DP(v_s * cache->
dt[ip] / 1000., atm->
p[ip]);
4825 const int np = atm->
np;
4826 double *restrict
const a = (
double *) malloc((
size_t) np *
sizeof(double));
4827 int *restrict
const p = (
int *) malloc((
size_t) np *
sizeof(int));
4828 if (a == NULL || p == NULL)
4829 ERRMSG(
"Out of memory!");
4832#pragma acc enter data create(a[0:np],p[0:np])
4833#pragma acc data present(ctl,met0,atm,a,p)
4838#pragma acc parallel loop independent gang vector
4840#pragma omp parallel for default(shared)
4842 for (
int ip = 0; ip < np; ip++) {
4853#pragma acc host_data use_device(a,p)
4855 thrustSortWrapper(a, np, p);
4858 ERRMSG(
"GSL sort fallback not available on GPU, use THRUST!");
4860 gsl_sort_index((
size_t *) p, a, 1, (
size_t) np);
4868 for (
int iq = 0; iq < ctl->
nq; iq++)
4873#pragma acc exit data delete(a,p)
4887 double *restrict
const help =
4888 (
double *) malloc((
size_t) np *
sizeof(double));
4890 ERRMSG(
"Out of memory!");
4894#pragma acc enter data create(help[0:np])
4895#pragma acc data present(a,p,help)
4896#pragma acc parallel loop independent gang vector
4898#pragma omp parallel for default(shared)
4900 for (
int ip = 0; ip < np; ip++)
4901 help[ip] = a[p[ip]];
4903#pragma acc parallel loop independent gang vector
4905#pragma omp parallel for default(shared)
4907 for (
int ip = 0; ip < np; ip++)
4912#pragma acc exit data delete(help)
4929 const double latmin = gsl_stats_min(met0->
lat, 1, (
size_t) met0->
ny),
4930 latmax = gsl_stats_max(met0->
lat, 1, (
size_t) met0->
ny);
4933 (fabs(met0->
lon[met0->
nx - 1] - met0->
lon[0] - 360.0) >= 0.01);
4936 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,atm)") {
4942 cache->
dt[ip] = t - atm->
time[ip];
4944 cache->
dt[ip] = 0.0;
4953 if (local && (atm->
lon[ip] <= met0->
lon[0]
4954 || atm->
lon[ip] >= met0->
lon[met0->
nx - 1]
4955 || atm->
lat[ip] <= latmin || atm->
lat[ip] >= latmax))
4956 cache->
dt[ip] = 0.0;
4975 ctl->
t_start = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
4977 ctl->
t_stop = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
4979 ctl->
t_start = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
4981 ctl->
t_stop = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
4986 ERRMSG(
"Nothing to do! Check T_STOP and DIRECTION!");
5010 "acc data present(ctl,cache,clim,met0,met1,atm)") {
5034 const double K_o1d =
ARRHENIUS(3.30e-10, 0, t) * o1d * M;
5036 atm->
p[ip], sza, o3c);
5037 atm->
q[ctl->
qnt_Cccl4][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5042 const double K_o1d =
ARRHENIUS(2.30e-10, 0, t) * o1d * M;
5044 atm->
p[ip], sza, o3c);
5045 atm->
q[ctl->
qnt_Cccl3f][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5050 const double K_o1d =
ARRHENIUS(1.40e-10, -25, t) * o1d * M;
5052 atm->
p[ip], sza, o3c);
5053 atm->
q[ctl->
qnt_Cccl2f2][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5058 const double K_o1d =
ARRHENIUS(1.19e-10, -20, t) * o1d * M;
5060 atm->
p[ip], sza, o3c);
5061 atm->
q[ctl->
qnt_Cn2o][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
5080 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
5083 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
5089 if (!isfinite(pct) || atm->
p[ip] <= pct)
5105 double lwc, rwc, iwc, swc;
5110 const int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
5124 else if (t <= 238.15)
5144 const double K_1 = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
5145 const double K_2 = 6e-8 * exp(1.12e3 * (1. / t - 1. / 298.15));
5146 h *= (1. + K_1 / H_ion + K_1 * K_2 /
SQR(H_ion));
5150 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
5153 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
5179 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
5182 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
5187 const double aux = exp(-cache->
dt[ip] * lambda);
5188 if (ctl->
qnt_m >= 0) {
5191 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
5192 atm->
q[ctl->
qnt_m][ip] *= aux;
5217 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
5219 if (acc_get_num_devices(acc_device_nvidia) <= 0)
5220 ERRMSG(
"Not running on a GPU device!");
5221 acc_set_device_num(rank % acc_get_num_devices(acc_device_nvidia),
5223 acc_device_t device_type = acc_get_device_type();
5224 acc_init(device_type);
5240 ctl_t *ctlup = *ctl;
5243 met_t *met0up = *met0;
5244 met_t *met1up = *met1;
5245 atm_t *atmup = *atm;
5246#pragma acc enter data create(ctlup[:1],cacheup[:1],climup[:1],met0up[:1],met1up[:1],atmup[:1])
5249#pragma acc enter data create(ddup[:1])
5268#pragma acc exit data delete (ctl,cache,clim,met0,met1,atm)
5282 MPI_Type_free(&dd->MPI_Particle);
5301 char cachefile[
LEN], cmd[2 *
LEN], filename[
LEN];
5307 if (t == ctl->
t_start || !init) {
5314 ERRMSG(
"Cannot open file!");
5319 ERRMSG(
"Cannot open file!");
5329 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5330 LOG(1,
"Caching: %s", cachefile);
5331 if (system(cmd) != 0)
5332 WARN(
"Caching command failed!");
5337 if (t > (*met1)->time) {
5347 ERRMSG(
"Cannot open file!");
5357 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5358 LOG(1,
"Caching: %s", cachefile);
5359 if (system(cmd) != 0)
5360 WARN(
"Caching command failed!");
5365 if (t < (*met0)->time) {
5375 ERRMSG(
"Cannot open file!");
5385 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5386 LOG(1,
"Caching: %s", cachefile);
5387 if (system(cmd) != 0)
5388 WARN(
"Caching command failed!");
5393 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
5394 if ((*met0)->nx != (*met1)->nx
5395 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
5396 ERRMSG(
"Meteo grid dimensions do not match!");
5397 for (
int ix = 0; ix < (*met0)->nx; ix++)
5398 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
5399 ERRMSG(
"Meteo grid longitudes do not match!");
5400 for (
int iy = 0; iy < (*met0)->ny; iy++)
5401 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
5402 ERRMSG(
"Meteo grid latitudes do not match!");
5403 for (
int ip = 0; ip < (*met0)->np; ip++)
5404 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
5405 ERRMSG(
"Meteo grid pressure levels do not match!");
5431 const char *filename,
5444 LOG(1,
"Read atmospheric data: %s", filename);
5464 ERRMSG(
"Atmospheric data type not supported!");
5472 ERRMSG(
"Can not read any data!");
5476 LOG(2,
"Number of particles: %d", atm->
np);
5477 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
5478 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
5479 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
5480 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
5481 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
5482 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
5483 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
5484 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
5485 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
5486 for (
int iq = 0; iq < ctl->
nq; iq++) {
5488 sprintf(msg,
"Quantity %s range: %s ... %s %s",
5491 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
5492 LOG(2, msg, mini, maxi);
5562 const char *filename,
5571 LOG(1,
"\nMassive-Parallel Trajectory Calculations (MPTRAC)\n"
5572 "(executable: %s | version: %s | compiled: %s, %s)\n",
5573 argv[0], VERSION, __DATE__, __TIME__);
5680 ctl->
nq = (int)
scan_ctl(filename, argc, argv,
"NQ", -1,
"0", NULL);
5682 ERRMSG(
"Too many quantities!");
5683 for (
int iq = 0; iq < ctl->
nq; iq++) {
5689 scan_ctl(filename, argc, argv,
"QNT_FORMAT", iq,
"%g",
5691 if (strcasecmp(ctl->
qnt_name[iq],
"aoa") == 0)
5695 SET_QNT(qnt_idx,
"idx",
"particle index",
"-")
5696 SET_QNT(qnt_ens,
"ens",
"ensemble index",
"-")
5697 SET_QNT(qnt_stat,
"stat",
"station flag",
"-")
5698 SET_QNT(qnt_m,
"m",
"mass",
"kg")
5699 SET_QNT(qnt_vmr,
"vmr",
"volume mixing ratio",
"ppv")
5700 SET_QNT(qnt_rp,
"rp",
"particle radius",
"microns")
5701 SET_QNT(qnt_rhop,
"rhop",
"particle density",
"kg/m^3")
5702 SET_QNT(qnt_ps,
"ps",
"surface pressure",
"hPa")
5703 SET_QNT(qnt_ts,
"ts",
"surface temperature",
"K")
5704 SET_QNT(qnt_zs,
"zs",
"surface height",
"km")
5705 SET_QNT(qnt_us,
"us",
"surface zonal wind",
"m/s")
5706 SET_QNT(qnt_vs,
"vs",
"surface meridional wind",
"m/s")
5707 SET_QNT(qnt_ess,
"ess",
"eastward turbulent surface stress",
"N/m^2")
5708 SET_QNT(qnt_nss,
"nss",
"northward turbulent surface stress",
"N/m^2")
5709 SET_QNT(qnt_shf,
"shf",
"surface sensible heat flux",
"W/m^2")
5710 SET_QNT(qnt_lsm,
"lsm",
"land-sea mask",
"1")
5711 SET_QNT(qnt_sst,
"sst",
"sea surface temperature",
"K")
5712 SET_QNT(qnt_pbl,
"pbl",
"planetary boundary layer",
"hPa")
5713 SET_QNT(qnt_pt,
"pt",
"tropopause pressure",
"hPa")
5714 SET_QNT(qnt_tt,
"tt",
"tropopause temperature",
"K")
5715 SET_QNT(qnt_zt,
"zt",
"tropopause geopotential height",
"km")
5716 SET_QNT(qnt_h2ot,
"h2ot",
"tropopause water vapor",
"ppv")
5717 SET_QNT(qnt_zg,
"zg",
"geopotential height",
"km")
5718 SET_QNT(qnt_p,
"p",
"pressure",
"hPa")
5719 SET_QNT(qnt_t,
"t",
"temperature",
"K")
5720 SET_QNT(qnt_rho,
"rho",
"air density",
"kg/m^3")
5721 SET_QNT(qnt_u,
"u",
"zonal wind",
"m/s")
5722 SET_QNT(qnt_v,
"v",
"meridional wind",
"m/s")
5723 SET_QNT(qnt_w,
"w",
"vertical velocity",
"hPa/s")
5724 SET_QNT(qnt_h2o,
"h2o",
"water vapor",
"ppv")
5725 SET_QNT(qnt_o3,
"o3",
"ozone",
"ppv")
5726 SET_QNT(qnt_lwc,
"lwc",
"cloud liquid water content",
"kg/kg")
5727 SET_QNT(qnt_rwc,
"rwc",
"cloud rain water content",
"kg/kg")
5728 SET_QNT(qnt_iwc,
"iwc",
"cloud ice water content",
"kg/kg")
5729 SET_QNT(qnt_swc,
"swc",
"cloud snow water content",
"kg/kg")
5730 SET_QNT(qnt_cc,
"cc",
"cloud cover",
"1")
5731 SET_QNT(qnt_pct,
"pct",
"cloud top pressure",
"hPa")
5732 SET_QNT(qnt_pcb,
"pcb",
"cloud bottom pressure",
"hPa")
5733 SET_QNT(qnt_cl,
"cl",
"total column cloud water",
"kg/m^2")
5734 SET_QNT(qnt_plcl,
"plcl",
"lifted condensation level",
"hPa")
5735 SET_QNT(qnt_plfc,
"plfc",
"level of free convection",
"hPa")
5736 SET_QNT(qnt_pel,
"pel",
"equilibrium level",
"hPa")
5737 SET_QNT(qnt_cape,
"cape",
"convective available potential energy",
5739 SET_QNT(qnt_cin,
"cin",
"convective inhibition",
"J/kg")
5740 SET_QNT(qnt_o3c,
"o3c",
"total column ozone",
"DU")
5741 SET_QNT(qnt_hno3,
"hno3",
"nitric acid",
"ppv")
5742 SET_QNT(qnt_oh,
"oh",
"hydroxyl radical",
"ppv")
5743 SET_QNT(qnt_h2o2,
"h2o2",
"hydrogen peroxide",
"ppv")
5744 SET_QNT(qnt_ho2,
"ho2",
"hydroperoxyl radical",
"ppv")
5745 SET_QNT(qnt_o1d,
"o1d",
"atomic oxygen",
"ppv")
5746 SET_QNT(qnt_mloss_oh,
"mloss_oh",
"mass loss due to OH chemistry",
"kg")
5747 SET_QNT(qnt_mloss_h2o2,
"mloss_h2o2",
5748 "mass loss due to H2O2 chemistry",
"kg")
5749 SET_QNT(qnt_mloss_kpp,
"mloss_kpp",
"mass loss due to kpp chemistry",
5751 SET_QNT(qnt_mloss_wet,
"mloss_wet",
"mass loss due to wet deposition",
5753 SET_QNT(qnt_mloss_dry,
"mloss_dry",
"mass loss due to dry deposition",
5755 SET_QNT(qnt_mloss_decay,
"mloss_decay",
5756 "mass loss due to exponential decay",
"kg")
5757 SET_QNT(qnt_loss_rate,
"loss_rate",
"total loss rate",
"s^-1")
5758 SET_QNT(qnt_psat,
"psat",
"saturation pressure over water",
"hPa")
5759 SET_QNT(qnt_psice,
"psice",
"saturation pressure over ice",
"hPa")
5760 SET_QNT(qnt_pw,
"pw",
"partial water vapor pressure",
"hPa")
5761 SET_QNT(qnt_sh,
"sh",
"specific humidity",
"kg/kg")
5762 SET_QNT(qnt_rh,
"rh",
"relative humidity",
"%%")
5763 SET_QNT(qnt_rhice,
"rhice",
"relative humidity over ice",
"%%")
5764 SET_QNT(qnt_theta,
"theta",
"potential temperature",
"K")
5765 SET_QNT(qnt_zeta,
"zeta",
"zeta coordinate",
"K")
5766 SET_QNT(qnt_zeta_d,
"zeta_d",
"diagnosed zeta coordinate",
"K")
5767 SET_QNT(qnt_zeta_dot,
"zeta_dot",
"velocity of zeta coordinate",
5769 SET_QNT(qnt_eta,
"eta",
"eta coordinate",
"1")
5770 SET_QNT(qnt_eta_dot,
"eta_dot",
"velocity of eta coordinate",
"1/s")
5771 SET_QNT(qnt_tvirt,
"tvirt",
"virtual temperature",
"K")
5772 SET_QNT(qnt_lapse,
"lapse",
"temperature lapse rate",
"K/km")
5773 SET_QNT(qnt_vh,
"vh",
"horizontal velocity",
"m/s")
5774 SET_QNT(qnt_vz,
"vz",
"vertical velocity",
"m/s")
5775 SET_QNT(qnt_pv,
"pv",
"potential vorticity",
"PVU")
5776 SET_QNT(qnt_tdew,
"tdew",
"dew point temperature",
"K")
5777 SET_QNT(qnt_tice,
"tice",
"frost point temperature",
"K")
5778 SET_QNT(qnt_tsts,
"tsts",
"STS existence temperature",
"K")
5779 SET_QNT(qnt_tnat,
"tnat",
"NAT existence temperature",
"K")
5780 SET_QNT(qnt_Cx,
"Cx",
"Trace species x volume mixing ratio",
"ppv")
5781 SET_QNT(qnt_Ch2o,
"Ch2o",
"H2O volume mixing ratio",
"ppv")
5782 SET_QNT(qnt_Co3,
"Co3",
"O3 volume mixing ratio",
"ppv")
5783 SET_QNT(qnt_Cco,
"Cco",
"CO volume mixing ratio",
"ppv")
5784 SET_QNT(qnt_Coh,
"Coh",
"HO volume mixing ratio",
"ppv")
5785 SET_QNT(qnt_Ch,
"Ch",
"H radical volume mixing ratio",
"ppv")
5786 SET_QNT(qnt_Cho2,
"Cho2",
"HO2 volume mixing ratio",
"ppv")
5787 SET_QNT(qnt_Ch2o2,
"Ch2o2",
"H2O2 volume mixing ratio",
"ppv")
5788 SET_QNT(qnt_Co1d,
"Co1d",
"O(1D) volume mixing ratio",
"ppv")
5789 SET_QNT(qnt_Co3p,
"Co3p",
"O(3P) radical volume mixing ratio",
"ppv")
5790 SET_QNT(qnt_Cccl4,
"Cccl4",
"CCl4 (CFC-10) volume mixing ratio",
"ppv")
5791 SET_QNT(qnt_Cccl3f,
"Cccl3f",
"CCl3F (CFC-11) volume mixing ratio",
5793 SET_QNT(qnt_Cccl2f2,
"Cccl2f2",
"CCl2F2 (CFC-12) volume mixing ratio",
5795 SET_QNT(qnt_Cn2o,
"Cn2o",
"N2O volume mixing ratio",
"ppv")
5796 SET_QNT(qnt_Csf6,
"Csf6",
"SF6 volume mixing ratio",
"ppv")
5797 SET_QNT(qnt_aoa,
"aoa",
"age of air",
"s")
5798 SET_QNT(qnt_Arn222,
"Arn222",
"Rn-222 activity",
"Bq")
5799 SET_QNT(qnt_Apb210,
"Apb210",
"Pb-210 activity",
"Bq")
5800 SET_QNT(qnt_Abe7,
"Abe7",
"Be-7 activity",
"Bq")
5801 SET_QNT(qnt_Acs137,
"Acs137",
"Cs-137 activity",
"Bq")
5802 SET_QNT(qnt_Ai131,
"Ai131",
"I-131 activity",
"Bq")
5803 SET_QNT(qnt_Axe133,
"Axe133",
"Xe-133 activity",
"Bq")
5804 SET_QNT(qnt_subdomain,
"subdomain",
"current subdomain index",
"-")
5805 SET_QNT(qnt_destination,
"destination",
5806 "subdomain index of destination",
"-")
5812 (int)
scan_ctl(filename, argc, argv,
"ADVECT_VERT_COORD", -1,
"0", NULL);
5814 ERRMSG(
"ADVECT_VERT_COORD must be 0, 1, 2, or 3!");
5817 ERRMSG(
"Add quantity zeta for diabatic advection!");
5819 ERRMSG(
"Add quantity eta for etadot avection!");
5822 (int)
scan_ctl(filename, argc, argv,
"MET_VERT_COORD", -1,
"0", NULL);
5824 ERRMSG(
"MET_VERT_COORD must be 0, 1, 2, 3, or 4!");
5828 (
"Using ADVECT_VERT_COORD = 2 requires meteo data on model levels!");
5831 (
"Using ADVECT_VERT_COORD = 3 requires A and B model level coefficients!");
5835 (int)
scan_ctl(filename, argc, argv,
"DIRECTION", -1,
"1", NULL);
5837 ERRMSG(
"Set DIRECTION to -1 or 1!");
5838 ctl->
t_stop =
scan_ctl(filename, argc, argv,
"T_STOP", -1,
"1e100", NULL);
5839 ctl->
dt_mod =
scan_ctl(filename, argc, argv,
"DT_MOD", -1,
"180", NULL);
5843 ctl->
dt_met =
scan_ctl(filename, argc, argv,
"DT_MET", -1,
"3600", NULL);
5845 (int)
scan_ctl(filename, argc, argv,
"MET_CONVENTION", -1,
"0", NULL);
5847 (int)
scan_ctl(filename, argc, argv,
"MET_TYPE", -1,
"0", NULL);
5850 (
"Please use meteo files in netcdf format for diabatic calculations.");
5853 (
"Please use meteo files in netcdf format for etadot calculations.");
5855 (int)
scan_ctl(filename, argc, argv,
"MET_CLAMS", -1,
"0", NULL);
5857 (int)
scan_ctl(filename, argc, argv,
"MET_NC_SCALE", -1,
"1", NULL);
5859 (int)
scan_ctl(filename, argc, argv,
"MET_NC_LEVEL", -1,
"0", NULL);
5861 (int)
scan_ctl(filename, argc, argv,
"MET_NC_QUANT", -1,
"0", NULL);
5863 (int)
scan_ctl(filename, argc, argv,
"MET_ZSTD_LEVEL", -1,
"0", NULL);
5864 for (
int i = 0; i <
METVAR; i++) {
5865 char defprec[
LEN] =
"0", deftol[
LEN] =
"0.0";
5867 sprintf(deftol,
"0.5");
5869 sprintf(deftol,
"5.0");
5871 sprintf(defprec,
"8");
5873 (int)
scan_ctl(filename, argc, argv,
"MET_COMP_PREC", i, defprec, NULL);
5875 scan_ctl(filename, argc, argv,
"MET_COMP_TOL", i, deftol, NULL);
5878 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_BATCH", -1,
"-1", NULL);
5880 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ZSTD", -1,
"1", NULL);
5882 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ND0X", -1,
"48", NULL);
5884 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ND0Y", -1,
"24", NULL);
5886 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_MAXLEV", -1,
"6", NULL);
5888 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_Z", -1,
"1.0", NULL);
5890 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_T", -1,
"0.05", NULL);
5892 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_U", -1,
"0.05", NULL);
5894 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_V", -1,
"0.05", NULL);
5896 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_W", -1,
"1.0", NULL);
5898 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_PV", -1,
"1.0", NULL);
5900 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_H2O", -1,
"1.0", NULL);
5902 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_O3", -1,
"1.0", NULL);
5904 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_LWC", -1,
"1.0", NULL);
5906 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_RWC", -1,
"1.0", NULL);
5908 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_IWC", -1,
"1.0", NULL);
5910 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_SWC", -1,
"1.0", NULL);
5912 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_CC", -1,
"1.0", NULL);
5913 ctl->
met_dx = (int)
scan_ctl(filename, argc, argv,
"MET_DX", -1,
"1", NULL);
5914 ctl->
met_dy = (int)
scan_ctl(filename, argc, argv,
"MET_DY", -1,
"1", NULL);
5915 ctl->
met_dp = (int)
scan_ctl(filename, argc, argv,
"MET_DP", -1,
"1", NULL);
5917 ERRMSG(
"MET_DX, MET_DY, and MET_DP need to be greater than zero!");
5918 ctl->
met_sx = (int)
scan_ctl(filename, argc, argv,
"MET_SX", -1,
"1", NULL);
5919 ctl->
met_sy = (int)
scan_ctl(filename, argc, argv,
"MET_SY", -1,
"1", NULL);
5920 ctl->
met_sp = (int)
scan_ctl(filename, argc, argv,
"MET_SP", -1,
"1", NULL);
5922 ERRMSG(
"MET_SX, MET_SY, and MET_SP need to be greater than zero!");
5924 scan_ctl(filename, argc, argv,
"MET_DETREND", -1,
"-999", NULL);
5925 ctl->
met_np = (int)
scan_ctl(filename, argc, argv,
"MET_NP", -1,
"0", NULL);
5927 ERRMSG(
"Too many pressure levels!");
5929 (int)
scan_ctl(filename, argc, argv,
"MET_PRESS_LEVEL_DEF", -1,
"-1",
5935 for (
int ip = 0; ip < ctl->
met_np; ip++)
5937 scan_ctl(filename, argc, argv,
"MET_P", ip,
"", NULL);
5941 (int)
scan_ctl(filename, argc, argv,
"MET_NLEV", -1,
"0", NULL);
5943 ERRMSG(
"Too many model levels!");
5944 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
5946 scan_ctl(filename, argc, argv,
"MET_LEV_HYAM", ip,
"", NULL);
5947 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
5949 scan_ctl(filename, argc, argv,
"MET_LEV_HYBM", ip,
"", NULL);
5951 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SX", -1,
"-1", NULL);
5953 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SY", -1,
"-1", NULL);
5955 (int)
scan_ctl(filename, argc, argv,
"MET_RELHUM", -1,
"0", NULL);
5957 (int)
scan_ctl(filename, argc, argv,
"MET_CAPE", -1,
"1", NULL);
5959 ERRMSG(
"Set MET_CAPE to 0 or 1!");
5961 (int)
scan_ctl(filename, argc, argv,
"MET_PBL", -1,
"3", NULL);
5963 ERRMSG(
"Set MET_PBL to 0 ... 3!");
5965 scan_ctl(filename, argc, argv,
"MET_PBL_MIN", -1,
"0.1", NULL);
5967 scan_ctl(filename, argc, argv,
"MET_PBL_MAX", -1,
"5.0", NULL);
5969 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO", -1,
"3", NULL);
5971 ERRMSG(
"Set MET_TROPO to 0 ... 5!");
5973 scan_ctl(filename, argc, argv,
"MET_TROPO_PV", -1,
"3.5", NULL);
5975 scan_ctl(filename, argc, argv,
"MET_TROPO_THETA", -1,
"380", NULL);
5977 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO_SPLINE", -1,
"1", NULL);
5979 scan_ctl(filename, argc, argv,
"MET_DT_OUT", -1,
"0.1", NULL);
5981 (int)
scan_ctl(filename, argc, argv,
"MET_CACHE", -1,
"0", NULL);
5983 (int)
scan_ctl(filename, argc, argv,
"MET_MPI_SHARE", -1,
"0", NULL);
5986 ctl->
sort_dt =
scan_ctl(filename, argc, argv,
"SORT_DT", -1,
"-999", NULL);
5990 (int)
scan_ctl(filename, argc, argv,
"ISOSURF", -1,
"0", NULL);
5995 (int)
scan_ctl(filename, argc, argv,
"RNG_TYPE", -1,
"1", NULL);
5997 ERRMSG(
"Set RNG_TYPE to 0, 1, or 2!");
6000 ctl->
advect = (int)
scan_ctl(filename, argc, argv,
"ADVECT", -1,
"2", NULL);
6004 ERRMSG(
"Set ADVECT to 0, 1, 2, or 4!");
6008 = (int)
scan_ctl(filename, argc, argv,
"DIFFUSION", -1,
"0", NULL);
6010 ERRMSG(
"Set DIFFUSION to 0, 1 or 2!");
6012 scan_ctl(filename, argc, argv,
"TURB_DX_PBL", -1,
"50", NULL);
6014 scan_ctl(filename, argc, argv,
"TURB_DX_TROP", -1,
"50", NULL);
6016 scan_ctl(filename, argc, argv,
"TURB_DX_STRAT", -1,
"0", NULL);
6018 scan_ctl(filename, argc, argv,
"TURB_DZ_PBL", -1,
"0", NULL);
6020 scan_ctl(filename, argc, argv,
"TURB_DZ_TROP", -1,
"0", NULL);
6022 scan_ctl(filename, argc, argv,
"TURB_DZ_STRAT", -1,
"0.1", NULL);
6024 scan_ctl(filename, argc, argv,
"TURB_MESOX", -1,
"0.16", NULL);
6026 scan_ctl(filename, argc, argv,
"TURB_MESOZ", -1,
"0.16", NULL);
6030 = (int)
scan_ctl(filename, argc, argv,
"CONV_MIX_PBL", -1,
"0", NULL);
6032 =
scan_ctl(filename, argc, argv,
"CONV_PBL_TRANS", -1,
"0", NULL);
6034 =
scan_ctl(filename, argc, argv,
"CONV_CAPE", -1,
"-999", NULL);
6036 =
scan_ctl(filename, argc, argv,
"CONV_CIN", -1,
"-999", NULL);
6037 ctl->
conv_dt =
scan_ctl(filename, argc, argv,
"CONV_DT", -1,
"-999", NULL);
6041 scan_ctl(filename, argc, argv,
"BOUND_MASS", -1,
"-999", NULL);
6043 scan_ctl(filename, argc, argv,
"BOUND_MASS_TREND", -1,
"0", NULL);
6045 scan_ctl(filename, argc, argv,
"BOUND_VMR", -1,
"-999", NULL);
6047 scan_ctl(filename, argc, argv,
"BOUND_VMR_TREND", -1,
"0", NULL);
6049 scan_ctl(filename, argc, argv,
"BOUND_LAT0", -1,
"-999", NULL);
6051 scan_ctl(filename, argc, argv,
"BOUND_LAT1", -1,
"-999", NULL);
6053 scan_ctl(filename, argc, argv,
"BOUND_P0", -1,
"-999", NULL);
6055 scan_ctl(filename, argc, argv,
"BOUND_P1", -1,
"-999", NULL);
6057 scan_ctl(filename, argc, argv,
"BOUND_DPS", -1,
"-999", NULL);
6059 scan_ctl(filename, argc, argv,
"BOUND_DZS", -1,
"-999", NULL);
6061 scan_ctl(filename, argc, argv,
"BOUND_ZETAS", -1,
"-999", NULL);
6063 (int)
scan_ctl(filename, argc, argv,
"BOUND_PBL", -1,
"0", NULL);
6067 if (strcasecmp(ctl->
species,
"CF2Cl2") == 0) {
6071 }
else if (strcasecmp(ctl->
species,
"CFCl3") == 0) {
6075 }
else if (strcasecmp(ctl->
species,
"CH4") == 0) {
6082 }
else if (strcasecmp(ctl->
species,
"CO") == 0) {
6091 }
else if (strcasecmp(ctl->
species,
"CO2") == 0) {
6095 }
else if (strcasecmp(ctl->
species,
"H2O") == 0) {
6097 }
else if (strcasecmp(ctl->
species,
"N2O") == 0) {
6101 }
else if (strcasecmp(ctl->
species,
"NH3") == 0) {
6108 }
else if (strcasecmp(ctl->
species,
"HNO3") == 0) {
6112 }
else if (strcasecmp(ctl->
species,
"NO") == 0) {
6121 }
else if (strcasecmp(ctl->
species,
"NO2") == 0) {
6130 }
else if (strcasecmp(ctl->
species,
"O3") == 0) {
6137 }
else if (strcasecmp(ctl->
species,
"SF6") == 0) {
6141 }
else if (strcasecmp(ctl->
species,
"SO2") == 0) {
6154 sprintf(defstr,
"%g", ctl->
molmass);
6155 ctl->
molmass =
scan_ctl(filename, argc, argv,
"MOLMASS", -1, defstr, NULL);
6160 (int)
scan_ctl(filename, argc, argv,
"OH_CHEM_REACTION", -1, defstr,
6162 for (
int ip = 0; ip < 4; ip++) {
6163 sprintf(defstr,
"%g", ctl->
oh_chem[ip]);
6165 scan_ctl(filename, argc, argv,
"OH_CHEM", ip, defstr, NULL);
6168 scan_ctl(filename, argc, argv,
"OH_CHEM_BETA", -1,
"0", NULL);
6172 (int)
scan_ctl(filename, argc, argv,
"H2O2_CHEM_REACTION", -1,
"0", NULL);
6176 (int)
scan_ctl(filename, argc, argv,
"KPP_CHEM", -1,
"0", NULL);
6177 ctl->
dt_kpp =
scan_ctl(filename, argc, argv,
"DT_KPP", -1,
"1800", NULL);
6181 (int)
scan_ctl(filename, argc, argv,
"TRACER_CHEM", -1,
"0", NULL);
6185 (int)
scan_ctl(filename, argc, argv,
"RADIO_DECAY", -1,
"0", NULL);
6188 for (
int ip = 0; ip < 2; ip++) {
6191 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_H", ip, defstr, NULL);
6193 for (
int ip = 0; ip < 1; ip++) {
6196 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_H", ip, defstr, NULL);
6199 scan_ctl(filename, argc, argv,
"WET_DEPO_SO2_PH", -1,
"0", NULL);
6201 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_A", -1,
"0", NULL);
6203 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_B", -1,
"0", NULL);
6205 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_A", -1,
"0", NULL);
6207 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_B", -1,
"0", NULL);
6209 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 0,
"0.5", NULL);
6211 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 1,
"0.36", NULL);
6213 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_RET_RATIO", -1,
"1", NULL);
6215 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_RET_RATIO", -1,
"1", NULL);
6219 scan_ctl(filename, argc, argv,
"DRY_DEPO_VDEP", -1,
"0", NULL);
6221 scan_ctl(filename, argc, argv,
"DRY_DEPO_DP", -1,
"30", NULL);
6224 scan_ctl(filename, argc, argv,
"CLIM_PHOTO", -1,
6225 "../../data/clams_photolysis_rates.nc", ctl->
clim_photo);
6226 scan_ctl(filename, argc, argv,
"CLIM_HNO3_FILENAME", -1,
6228 scan_ctl(filename, argc, argv,
"CLIM_OH_FILENAME", -1,
6230 scan_ctl(filename, argc, argv,
"CLIM_H2O2_FILENAME", -1,
6232 scan_ctl(filename, argc, argv,
"CLIM_HO2_FILENAME", -1,
6234 scan_ctl(filename, argc, argv,
"CLIM_O1D_FILENAME", -1,
6236 scan_ctl(filename, argc, argv,
"CLIM_CCL4_TIMESERIES", -1,
6238 scan_ctl(filename, argc, argv,
"CLIM_CCL3F_TIMESERIES", -1,
6240 scan_ctl(filename, argc, argv,
"CLIM_CCL2F2_TIMESERIES", -1,
6242 scan_ctl(filename, argc, argv,
"CLIM_N2O_TIMESERIES", -1,
6244 scan_ctl(filename, argc, argv,
"CLIM_SF6_TIMESERIES", -1,
6249 scan_ctl(filename, argc, argv,
"MIXING_DT", -1,
"3600.", NULL);
6251 scan_ctl(filename, argc, argv,
"MIXING_TROP", -1,
"-999", NULL);
6253 scan_ctl(filename, argc, argv,
"MIXING_STRAT", -1,
"-999", NULL);
6255 scan_ctl(filename, argc, argv,
"MIXING_Z0", -1,
"-5", NULL);
6257 scan_ctl(filename, argc, argv,
"MIXING_Z1", -1,
"85", NULL);
6259 (int)
scan_ctl(filename, argc, argv,
"MIXING_NZ", -1,
"90", NULL);
6261 scan_ctl(filename, argc, argv,
"MIXING_LON0", -1,
"-180", NULL);
6263 scan_ctl(filename, argc, argv,
"MIXING_LON1", -1,
"180", NULL);
6265 (int)
scan_ctl(filename, argc, argv,
"MIXING_NX", -1,
"360", NULL);
6267 scan_ctl(filename, argc, argv,
"MIXING_LAT0", -1,
"-90", NULL);
6269 scan_ctl(filename, argc, argv,
"MIXING_LAT1", -1,
"90", NULL);
6271 (int)
scan_ctl(filename, argc, argv,
"MIXING_NY", -1,
"180", NULL);
6275 scan_ctl(filename, argc, argv,
"CHEMGRID_Z0", -1,
"-5", NULL);
6277 scan_ctl(filename, argc, argv,
"CHEMGRID_Z1", -1,
"85", NULL);
6279 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NZ", -1,
"90", NULL);
6281 scan_ctl(filename, argc, argv,
"CHEMGRID_LON0", -1,
"-180", NULL);
6283 scan_ctl(filename, argc, argv,
"CHEMGRID_LON1", -1,
"180", NULL);
6285 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NX", -1,
"360", NULL);
6287 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT0", -1,
"-90", NULL);
6289 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT1", -1,
"90", NULL);
6291 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NY", -1,
"180", NULL);
6296 scan_ctl(filename, argc, argv,
"TDEC_STRAT", -1,
"0", NULL);
6299 ctl->
psc_h2o =
scan_ctl(filename, argc, argv,
"PSC_H2O", -1,
"4e-6", NULL);
6301 scan_ctl(filename, argc, argv,
"PSC_HNO3", -1,
"9e-9", NULL);
6307 scan_ctl(filename, argc, argv,
"ATM_DT_OUT", -1,
"86400", NULL);
6309 (int)
scan_ctl(filename, argc, argv,
"ATM_FILTER", -1,
"0", NULL);
6311 (int)
scan_ctl(filename, argc, argv,
"ATM_STRIDE", -1,
"1", NULL);
6313 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE", -1,
"0", NULL);
6315 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE_OUT", -1,
"-1", NULL);
6319 (int)
scan_ctl(filename, argc, argv,
"ATM_NC_LEVEL", -1,
"0", NULL);
6320 for (
int iq = 0; iq < ctl->
nq; iq++)
6322 (
int)
scan_ctl(filename, argc, argv,
"ATM_NC_QUANT", iq,
"0", NULL);
6324 (int)
scan_ctl(filename, argc, argv,
"OBS_TYPE", -1,
"0", NULL);
6330 scan_ctl(filename, argc, argv,
"CSI_DT_OUT", -1,
"86400", NULL);
6333 scan_ctl(filename, argc, argv,
"CSI_OBSMIN", -1,
"0", NULL);
6335 scan_ctl(filename, argc, argv,
"CSI_MODMIN", -1,
"0", NULL);
6336 ctl->
csi_z0 =
scan_ctl(filename, argc, argv,
"CSI_Z0", -1,
"-5", NULL);
6337 ctl->
csi_z1 =
scan_ctl(filename, argc, argv,
"CSI_Z1", -1,
"85", NULL);
6338 ctl->
csi_nz = (int)
scan_ctl(filename, argc, argv,
"CSI_NZ", -1,
"1", NULL);
6340 scan_ctl(filename, argc, argv,
"CSI_LON0", -1,
"-180", NULL);
6341 ctl->
csi_lon1 =
scan_ctl(filename, argc, argv,
"CSI_LON1", -1,
"180", NULL);
6343 (int)
scan_ctl(filename, argc, argv,
"CSI_NX", -1,
"360", NULL);
6344 ctl->
csi_lat0 =
scan_ctl(filename, argc, argv,
"CSI_LAT0", -1,
"-90", NULL);
6345 ctl->
csi_lat1 =
scan_ctl(filename, argc, argv,
"CSI_LAT1", -1,
"90", NULL);
6347 (int)
scan_ctl(filename, argc, argv,
"CSI_NY", -1,
"180", NULL);
6350 ctl->
nens = (int)
scan_ctl(filename, argc, argv,
"NENS", -1,
"0", NULL);
6353 scan_ctl(filename, argc, argv,
"ENS_DT_OUT", -1,
"86400", NULL);
6356 scan_ctl(filename, argc, argv,
"GRID_BASENAME", -1,
"-",
6361 scan_ctl(filename, argc, argv,
"GRID_DT_OUT", -1,
"86400", NULL);
6363 (int)
scan_ctl(filename, argc, argv,
"GRID_SPARSE", -1,
"0", NULL);
6365 (int)
scan_ctl(filename, argc, argv,
"GRID_NC_LEVEL", -1,
"0", NULL);
6366 for (
int iq = 0; iq < ctl->
nq; iq++)
6368 (
int)
scan_ctl(filename, argc, argv,
"GRID_NC_QUANT", iq,
"0", NULL);
6370 (int)
scan_ctl(filename, argc, argv,
"GRID_STDDEV", -1,
"0", NULL);
6371 ctl->
grid_z0 =
scan_ctl(filename, argc, argv,
"GRID_Z0", -1,
"-5", NULL);
6372 ctl->
grid_z1 =
scan_ctl(filename, argc, argv,
"GRID_Z1", -1,
"85", NULL);
6374 (int)
scan_ctl(filename, argc, argv,
"GRID_NZ", -1,
"1", NULL);
6376 scan_ctl(filename, argc, argv,
"GRID_LON0", -1,
"-180", NULL);
6378 scan_ctl(filename, argc, argv,
"GRID_LON1", -1,
"180", NULL);
6380 (int)
scan_ctl(filename, argc, argv,
"GRID_NX", -1,
"360", NULL);
6382 scan_ctl(filename, argc, argv,
"GRID_LAT0", -1,
"-90", NULL);
6384 scan_ctl(filename, argc, argv,
"GRID_LAT1", -1,
"90", NULL);
6386 (int)
scan_ctl(filename, argc, argv,
"GRID_NY", -1,
"180", NULL);
6388 (int)
scan_ctl(filename, argc, argv,
"GRID_TYPE", -1,
"0", NULL);
6391 scan_ctl(filename, argc, argv,
"PROF_BASENAME", -1,
"-",
6394 ctl->
prof_z0 =
scan_ctl(filename, argc, argv,
"PROF_Z0", -1,
"0", NULL);
6395 ctl->
prof_z1 =
scan_ctl(filename, argc, argv,
"PROF_Z1", -1,
"60", NULL);
6397 (int)
scan_ctl(filename, argc, argv,
"PROF_NZ", -1,
"60", NULL);
6399 scan_ctl(filename, argc, argv,
"PROF_LON0", -1,
"-180", NULL);
6401 scan_ctl(filename, argc, argv,
"PROF_LON1", -1,
"180", NULL);
6403 (int)
scan_ctl(filename, argc, argv,
"PROF_NX", -1,
"360", NULL);
6405 scan_ctl(filename, argc, argv,
"PROF_LAT0", -1,
"-90", NULL);
6407 scan_ctl(filename, argc, argv,
"PROF_LAT1", -1,
"90", NULL);
6409 (int)
scan_ctl(filename, argc, argv,
"PROF_NY", -1,
"180", NULL);
6412 scan_ctl(filename, argc, argv,
"SAMPLE_BASENAME", -1,
"-",
6414 scan_ctl(filename, argc, argv,
"SAMPLE_KERNEL", -1,
"-",
6416 scan_ctl(filename, argc, argv,
"SAMPLE_OBSFILE", -1,
"-",
6419 scan_ctl(filename, argc, argv,
"SAMPLE_DX", -1,
"50", NULL);
6421 scan_ctl(filename, argc, argv,
"SAMPLE_DZ", -1,
"-999", NULL);
6424 scan_ctl(filename, argc, argv,
"STAT_BASENAME", -1,
"-",
6428 ctl->
stat_r =
scan_ctl(filename, argc, argv,
"STAT_R", -1,
"50", NULL);
6430 scan_ctl(filename, argc, argv,
"STAT_T0", -1,
"-1e100", NULL);
6431 ctl->
stat_t1 =
scan_ctl(filename, argc, argv,
"STAT_T1", -1,
"1e100", NULL);
6436 scan_ctl(filename, argc, argv,
"VTK_DT_OUT", -1,
"86400", NULL);
6438 (int)
scan_ctl(filename, argc, argv,
"VTK_STRIDE", -1,
"1", NULL);
6440 scan_ctl(filename, argc, argv,
"VTK_SCALE", -1,
"1.0", NULL);
6442 scan_ctl(filename, argc, argv,
"VTK_OFFSET", -1,
"0.0", NULL);
6444 (int)
scan_ctl(filename, argc, argv,
"VTK_SPHERE", -1,
"0", NULL);
6447 ctl->
dd = (int)
scan_ctl(filename, argc, argv,
"DD", -1,
"0", NULL);
6449 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_MERIDIONAL", -1,
6450 (ctl->
dd == 1) ?
"2" :
"1", NULL);
6452 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_ZONAL", -1,
6453 (ctl->
dd == 1) ?
"2" :
"1", NULL);
6456 else if (ctl->
dd == 1)
6457 ERRMSG(
"Please provide zonal and meridional subdomain numbers!")
6459 (int)
scan_ctl(filename, argc, argv,
"DD_NBR_NEIGHBOURS", -1,
"8",
6462 (int)
scan_ctl(filename, argc, argv,
"DD_HALOS_SIZE", -1,
"1", NULL);
6468 const char *filename,
6475 LOG(1,
"Read meteo data: %s", filename);
6481 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
6509 ERRMSG(
"MET_TYPE not implemented!");
6563 LOG(2,
"Broadcast data on rank %d...", rank);
6698 ERRMSG(
"DD initialized, but model is compiled without DD.")
6707 ERRMSG(
"Code was compiled without KPP!");
6740#pragma acc update device(ctl[:1])
6744 if (cache != NULL) {
6747#pragma acc update device(cache[:1])
6754#pragma acc update device(clim[:1])
6761 met_t *met0up = *met0;
6762#pragma acc update device(met0up[:1])
6769 met_t *met1up = *met1;
6770#pragma acc update device(met1up[:1])
6777#pragma acc update device(atm[:1])
6796#pragma acc update host(ctl[:1])
6800 if (cache != NULL) {
6803#pragma acc update host(cache[:1])
6810#pragma acc update host(clim[:1])
6817 met_t *met0up = *met0;
6818#pragma acc update host(met0up[:1])
6825 met_t *met1up = *met1;
6826#pragma acc update host(met1up[:1])
6833#pragma acc update host(atm[:1])
6841 const char *filename,
6850 LOG(1,
"Write atmospheric data: %s", filename);
6874 ERRMSG(
"Atmospheric data type not supported!");
6878 LOG(2,
"Number of particles: %d", atm->
np);
6879 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
6880 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
6881 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
6882 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
6883 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
6884 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
6885 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
6886 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
6887 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
6888 for (
int iq = 0; iq < ctl->
nq; iq++) {
6890 sprintf(msg,
"Quantity %s range: %s ... %s %s",
6893 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
6894 LOG(2, msg, mini, maxi);
6901 const char *filename,
6909 LOG(1,
"Write meteo data: %s", filename);
6914 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
6918 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
6922 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
6926 ERRMSG(
"MPTRAC was compiled without SZ3 compression!");
6939 ERRMSG(
"MET_TYPE not implemented!");
6945 const char *dirname,
6952 char ext[10], filename[2 *
LEN];
6956 int year, mon, day, hour, min, sec;
6959 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
6974 sprintf(ext,
"tab");
6976 sprintf(ext,
"bin");
6979 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6980 dirname, ctl->
atm_basename, year, mon, day, hour, min, ext);
6986 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6989 write_grid(filename, ctl, met0, met1, atm, t);
6994 sprintf(filename,
"%s/%s.tab", dirname, ctl->
csi_basename);
7000 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.tab",
7001 dirname, ctl->
ens_basename, year, mon, day, hour, min);
7007 sprintf(filename,
"%s/%s.tab", dirname, ctl->
prof_basename);
7008 write_prof(filename, ctl, met0, met1, atm, t);
7019 sprintf(filename,
"%s/%s.tab", dirname, ctl->
stat_basename);
7028 sprintf(filename,
"%s/%s_%05d.vtk", dirname, ctl->
vtk_basename, ++nvtk);
7038 const double hno3) {
7041 const double h2o_help =
MAX(h2o, 0.1e-6);
7044 const double p_hno3 = hno3 * p / 1.333224;
7045 const double p_h2o = h2o_help * p / 1.333224;
7046 const double a = 0.009179 - 0.00088 * log10(p_h2o);
7047 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
7048 const double c = -11397.0 / a;
7049 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
7050 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
7068 const double p0 = pbl;
7071 if (atm->
p[ip] > p0)
7073 else if (atm->
p[ip] < p1)
7076 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
7082 const char *filename,
7088 if (!(in = fopen(filename,
"r"))) {
7089 WARN(
"Cannot open file!");
7095 while (fgets(line,
LEN, in)) {
7099 TOK(line, tok,
"%lg", atm->
time[atm->
np]);
7100 TOK(NULL, tok,
"%lg", atm->
p[atm->
np]);
7101 TOK(NULL, tok,
"%lg", atm->
lon[atm->
np]);
7102 TOK(NULL, tok,
"%lg", atm->
lat[atm->
np]);
7103 for (
int iq = 0; iq < ctl->
nq; iq++)
7104 TOK(NULL, tok,
"%lg", atm->
q[iq][atm->
np]);
7107 atm->
p[atm->
np] =
P(atm->
p[atm->
np]);
7110 if ((++atm->
np) >
NP)
7111 ERRMSG(
"Too many data points!");
7124 const char *filename,
7130 if (!(in = fopen(filename,
"r")))
7135 FREAD(&version,
int,
7139 ERRMSG(
"Wrong version of binary data!");
7157 for (
int iq = 0; iq < ctl->
nq; iq++)
7158 FREAD(atm->
q[iq],
double,
7168 ERRMSG(
"Error while reading binary data!");
7180 const char *filename,
7187 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
7194 if (nc_inq_varid(ncid,
"TIME_INIT", &varid) == NC_NOERR) {
7195 NC(nc_get_var_double(ncid, varid, atm->
time));
7197 WARN(
"TIME_INIT not found use time instead!");
7200 for (
int ip = 0; ip < atm->
np; ip++) {
7201 atm->
time[ip] = time_init;
7213 if (nc_inq_varid(ncid,
"PRESS_INIT", &varid) == NC_NOERR) {
7214 NC(nc_get_var_double(ncid, varid, atm->
p));
7216 WARN(
"PRESS_INIT not found use PRESS instead!");
7217 nc_inq_varid(ncid,
"PRESS", &varid);
7218 NC(nc_get_var_double(ncid, varid, atm->
p));
7223 for (
int iq = 0; iq < ctl->
nq; iq++)
7240 const char *filename,
7247 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
7260 for (
int iq = 0; iq < ctl->
nq; iq++)
7273 const char *filename,
7279 LOG(1,
"Read photolysis rates: %s", filename);
7282 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
7283 WARN(
"Photolysis rate data are missing!");
7290 if (photo->
p[0] < photo->
p[1])
7291 ERRMSG(
"Pressure data are not descending!");
7296 if (photo->
o3c[0] > photo->
o3c[1])
7297 ERRMSG(
"Total column ozone data are not ascending!");
7302 if (photo->
sza[0] > photo->
sza[1])
7303 ERRMSG(
"Solar zenith angle data are not ascending!");
7320 LOG(2,
"Number of pressure levels: %d", photo->
np);
7321 LOG(2,
"Altitude levels: %g, %g ... %g km",
7322 Z(photo->
p[0]),
Z(photo->
p[1]),
Z(photo->
p[photo->
np - 1]));
7323 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
7324 photo->
p[0], photo->
p[1], photo->
p[photo->
np - 1]);
7325 LOG(2,
"Number of solar zenith angles: %d", photo->
nsza);
7326 LOG(2,
"Solar zenith angles: %g, %g ... %g deg",
7329 LOG(2,
"Number of total column ozone values: %d", photo->
no3c);
7330 LOG(2,
"Total column ozone: %g, %g ... %g DU",
7332 LOG(2,
"N2O photolysis rate: %g, %g ... %g s**-1",
7333 photo->
n2o[0][0][0], photo->
n2o[1][0][0],
7334 photo->
n2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7335 LOG(2,
"CCl4 photolysis rate: %g, %g ... %g s**-1",
7336 photo->
ccl4[0][0][0], photo->
ccl4[1][0][0],
7338 LOG(2,
"CFC-11 photolysis rate: %g, %g ... %g s**-1",
7339 photo->
ccl3f[0][0][0], photo->
ccl3f[1][0][0],
7341 LOG(2,
"CFC-12 photolysis rate: %g, %g ... %g s**-1",
7344 LOG(2,
"O2 photolysis rate: %g, %g ... %g s**-1",
7345 photo->
o2[0][0][0], photo->
o2[1][0][0],
7346 photo->
o2[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7347 LOG(2,
"O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
7348 photo->
o3_1[0][0][0], photo->
o3_1[1][0][0],
7350 LOG(2,
"O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
7351 photo->
o3_2[0][0][0], photo->
o3_2[1][0][0],
7353 LOG(2,
"H2O2 photolysis rate: %g, %g ... %g s**-1",
7354 photo->
h2o2[0][0][0], photo->
h2o2[1][0][0],
7356 LOG(2,
"H2O photolysis rate: %g, %g ... %g s**-1",
7357 photo->
h2o[0][0][0], photo->
h2o[1][0][0],
7358 photo->
h2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7365 const char *varname,
7379 for (
int ip = 0; ip < photo->
np; ip++)
7380 for (
int is = 0; is < photo->
nsza; is++)
7381 for (
int io = 0; io < photo->
no3c; io++)
7392 const char *filename,
7396 LOG(1,
"Read climatological time series: %s", filename);
7400 if (!(in = fopen(filename,
"r"))) {
7401 WARN(
"Cannot open file!");
7408 while (fgets(line,
LEN, in))
7409 if (sscanf(line,
"%lg %lg", &ts->
time[nh], &ts->
vmr[nh]) == 2) {
7412 ts->
time[nh] = (ts->
time[nh] - 2000.0) * 365.25 * 86400.;
7415 if (nh > 0 && ts->
time[nh] <= ts->
time[nh - 1])
7416 ERRMSG(
"Time series must be ascending!");
7420 ERRMSG(
"Too many data points!");
7429 ERRMSG(
"Not enough data points!");
7432 LOG(2,
"Number of time steps: %d", ts->
ntime);
7433 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s", ts->
time[0], ts->
time[1],
7435 LOG(2,
"Volume mixing ratio range: %g ... %g ppv",
7436 gsl_stats_min(ts->
vmr, 1, (
size_t) nh), gsl_stats_max(ts->
vmr, 1,
7446 const char *filename,
7447 const char *varname,
7450 int ncid, varid, it, iy, iz, iz2, nt;
7452 double *help, varmin = 1e99, varmax = -1e99;
7455 LOG(1,
"Read %s data: %s", varname, filename);
7458 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
7459 WARN(
"%s climatology data are missing!", varname);
7466 if (zm->
p[0] < zm->
p[1])
7467 ERRMSG(
"Pressure data are not descending!");
7472 if (zm->
lat[0] > zm->
lat[1])
7473 ERRMSG(
"Latitude data are not ascending!");
7477 zm->
time[0] = 1209600.00;
7478 zm->
time[1] = 3888000.00;
7479 zm->
time[2] = 6393600.00;
7480 zm->
time[3] = 9072000.00;
7481 zm->
time[4] = 11664000.00;
7482 zm->
time[5] = 14342400.00;
7483 zm->
time[6] = 16934400.00;
7484 zm->
time[7] = 19612800.00;
7485 zm->
time[8] = 22291200.00;
7486 zm->
time[9] = 24883200.00;
7487 zm->
time[10] = 27561600.00;
7488 zm->
time[11] = 30153600.00;
7497 for (it = 0; it < zm->
ntime; it++)
7498 for (iz = 0; iz < zm->
np; iz++)
7499 for (iy = 0; iy < zm->
nlat; iy++)
7504 for (it = 0; it < zm->
ntime; it++)
7505 for (iy = 0; iy < zm->
nlat; iy++)
7506 for (iz = 0; iz < zm->
np; iz++) {
7507 if (zm->
vmr[it][iz][iy] < 0) {
7508 for (iz2 = 0; iz2 < zm->
np; iz2++)
7509 if (zm->
vmr[it][iz2][iy] >= 0) {
7510 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
7513 for (iz2 = zm->
np - 1; iz2 >= 0; iz2--)
7514 if (zm->
vmr[it][iz2][iy] >= 0) {
7515 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
7519 varmin =
MIN(varmin, zm->
vmr[it][iz][iy]);
7520 varmax =
MAX(varmax, zm->
vmr[it][iz][iy]);
7527 LOG(2,
"Number of time steps: %d", zm->
ntime);
7528 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
7530 LOG(2,
"Number of pressure levels: %d", zm->
np);
7531 LOG(2,
"Altitude levels: %g, %g ... %g km",
7532 Z(zm->
p[0]),
Z(zm->
p[1]),
Z(zm->
p[zm->
np - 1]));
7533 LOG(2,
"Pressure levels: %g, %g ... %g hPa", zm->
p[0],
7534 zm->
p[1], zm->
p[zm->
np - 1]);
7535 LOG(2,
"Number of latitudes: %d", zm->
nlat);
7536 LOG(2,
"Latitudes: %g, %g ... %g deg",
7538 LOG(2,
"%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
7545 const char *filename,
7551 LOG(1,
"Read kernel function: %s", filename);
7555 if (!(in = fopen(filename,
"r")))
7556 ERRMSG(
"Cannot open file!");
7561 while (fgets(line,
LEN, in))
7562 if (sscanf(line,
"%lg %lg", &kz[n], &kw[n]) == 2) {
7563 if (n > 0 && kz[n] < kz[n - 1])
7564 ERRMSG(
"Height levels must be ascending!");
7566 ERRMSG(
"Too many height levels!");
7575 ERRMSG(
"Not enough height levels!");
7578 const double kmax = gsl_stats_max(kw, 1, (
size_t) n);
7579 for (
int iz = 0; iz < n; iz++)
7586 const char *filename,
7594 int year, mon, day, hour, min, sec;
7600 if (!(in = fopen(filename,
"r"))) {
7601 WARN(
"Cannot open file!");
7607 FREAD(&met_type,
int,
7611 ERRMSG(
"Wrong MET_TYPE of binary data!");
7615 FREAD(&version,
int,
7619 ERRMSG(
"Wrong version of binary data!");
7625 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
7626 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
7627 met->
time, year, mon, day, hour, min);
7628 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
7629 || day < 1 || day > 31 || hour < 0 || hour > 23)
7630 ERRMSG(
"Error while reading time!");
7636 LOG(2,
"Number of longitudes: %d", met->
nx);
7637 if (met->
nx < 2 || met->
nx >
EX)
7638 ERRMSG(
"Number of longitudes out of range!");
7643 LOG(2,
"Number of latitudes: %d", met->
ny);
7644 if (met->
ny < 2 || met->
ny >
EY)
7645 ERRMSG(
"Number of latitudes out of range!");
7650 LOG(2,
"Number of levels: %d", met->
np);
7651 if (met->
np < 2 || met->
np >
EP)
7652 ERRMSG(
"Number of levels out of range!");
7658 LOG(2,
"Longitudes: %g, %g ... %g deg",
7664 LOG(2,
"Latitudes: %g, %g ... %g deg",
7670 LOG(2,
"Altitude levels: %g, %g ... %g km",
7671 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
7672 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
7673 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
7722 ERRMSG(
"Error while reading binary data!");
7737 const char *varname) {
7746 LOG(2,
"Read 2-D variable: %s (uncompressed)", varname);
7748 (
size_t) (met->
nx * met->
ny),
7752 for (
int ix = 0; ix < met->
nx; ix++)
7753 for (
int iy = 0; iy < met->
ny; iy++)
7754 var[ix][iy] = help[
ARRAY_2D(ix, iy, met->
ny)];
7767 const char *varname,
7768 const float bound_min,
7769 const float bound_max) {
7779 LOG(2,
"Read 3-D variable: %s (uncompressed)", varname);
7781 (
size_t) (met->
nx * met->
ny * met->
np),
7788 (
size_t) met->
np, 1, in);
7794 FREAD(&precision,
int,
7799 FREAD(&tolerance,
double,
7806 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
7816 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
7824 (
size_t) met->
np, met->
p, 1, in);
7826 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
7834 FREAD(&precision,
int,
7839 FREAD(&tolerance,
double,
7846 ERRMSG(
"MPTRAC was compiled without sz3 compression!");
7851#pragma omp parallel for default(shared) collapse(2)
7852 for (
int ix = 0; ix < met->
nx; ix++)
7853 for (
int iy = 0; iy < met->
ny; iy++)
7854 for (
int ip = 0; ip < met->
np; ip++) {
7855 var[ix][iy][ip] = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
7856 if (var[ix][iy][ip] < bound_min)
7857 var[ix][iy][ip] = bound_min;
7858 else if (var[ix][iy][ip] > bound_max)
7859 var[ix][iy][ip] = bound_max;
7879 LOG(2,
"Calculate CAPE...");
7882 const double pfac = 1.01439, dz0 =
RI /
MA /
G0 * log(pfac);
7885#pragma omp parallel for default(shared) collapse(2)
7886 for (
int ix = 0; ix < met->
nx; ix++)
7887 for (
int iy = 0; iy < met->
ny; iy++) {
7891 double h2o = 0, t, theta = 0;
7892 double pbot =
MIN(met->
ps[ix][iy], met->
p[0]);
7893 double ptop = pbot - 50.;
7894 for (
int ip = 0; ip < met->
np; ip++) {
7895 if (met->
p[ip] <= pbot) {
7896 theta +=
THETA(met->
p[ip], met->
t[ix][iy][ip]);
7897 h2o += met->
h2o[ix][iy][ip];
7900 if (met->
p[ip] < ptop && n > 0)
7907 met->
plcl[ix][iy] = NAN;
7908 met->
plfc[ix][iy] = NAN;
7909 met->
pel[ix][iy] = NAN;
7910 met->
cape[ix][iy] = NAN;
7911 met->
cin[ix][iy] = NAN;
7917 pbot = met->
ps[ix][iy];
7919 met->
plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
7920 t = theta / pow(1000. / met->
plcl[ix][iy], 0.286);
7921 if (
RH(met->
plcl[ix][iy], t, h2o) > 100.)
7922 ptop = met->
plcl[ix][iy];
7924 pbot = met->
plcl[ix][iy];
7925 }
while (pbot - ptop > 0.1);
7929 double dcape, dz, h2o_env, t_env;
7930 double p = met->
ps[ix][iy];
7931 met->
cape[ix][iy] = met->
cin[ix][iy] = 0;
7933 dz = dz0 *
TVIRT(t, h2o);
7935 t = theta / pow(1000. / p, 0.286);
7939 &h2o_env, ci, cw, 0);
7940 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
7941 TVIRT(t_env, h2o_env) * dz;
7943 met->
cin[ix][iy] += fabsf((
float) dcape);
7944 }
while (p > met->
plcl[ix][iy]);
7949 p = met->
plcl[ix][iy];
7950 t = theta / pow(1000. / p, 0.286);
7953 dz = dz0 *
TVIRT(t, h2o);
7956 double psat =
PSAT(t);
7957 h2o = psat / (p - (1. -
EPS) * psat);
7961 &h2o_env, ci, cw, 0);
7962 double dcape_old = dcape;
7963 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
7964 TVIRT(t_env, h2o_env) * dz;
7966 met->
cape[ix][iy] += (float) dcape;
7967 if (!isfinite(met->
plfc[ix][iy]))
7968 met->
plfc[ix][iy] = (
float) p;
7969 }
else if (dcape_old > 0)
7970 met->
pel[ix][iy] = (float) p;
7971 if (dcape < 0 && !isfinite(met->
plfc[ix][iy]))
7972 met->
cin[ix][iy] += fabsf((
float) dcape);
7976 if (!isfinite(met->
plfc[ix][iy]))
7977 met->
cin[ix][iy] = NAN;
7988 LOG(2,
"Calculate cloud data...");
7991 const double ccmin = 0.01, cwmin = 1e-6;
7994#pragma omp parallel for default(shared) collapse(2)
7995 for (
int ix = 0; ix < met->
nx; ix++)
7996 for (
int iy = 0; iy < met->
ny; iy++) {
7999 met->
pct[ix][iy] = NAN;
8000 met->
pcb[ix][iy] = NAN;
8001 met->
cl[ix][iy] = 0;
8004 for (
int ip = 0; ip < met->
np - 1; ip++) {
8007 if (met->
p[ip] > met->
ps[ix][iy] || met->
p[ip] <
P(20.))
8011 if (met->
cc[ix][iy][ip] > ccmin
8012 && (met->
lwc[ix][iy][ip] > cwmin
8013 || met->
rwc[ix][iy][ip] > cwmin
8014 || met->
iwc[ix][iy][ip] > cwmin
8015 || met->
swc[ix][iy][ip] > cwmin)) {
8019 = (float) (0.5 * (met->
p[ip] + (
float) met->
p[ip + 1]));
8022 if (!isfinite(met->
pcb[ix][iy]))
8024 = (
float) (0.5 * (met->
p[ip] + met->
p[
MAX(ip - 1, 0)]));
8028 met->
cl[ix][iy] += (float)
8029 (0.5 * (met->
lwc[ix][iy][ip] + met->
lwc[ix][iy][ip + 1]
8030 + met->
rwc[ix][iy][ip] + met->
rwc[ix][iy][ip + 1]
8031 + met->
iwc[ix][iy][ip] + met->
iwc[ix][iy][ip + 1]
8032 + met->
swc[ix][iy][ip] + met->
swc[ix][iy][ip + 1])
8033 * 100. * (met->
p[ip] - met->
p[ip + 1]) /
G0);
8052 LOG(2,
"Detrend meteo data...");
8059 const double tssq = 2. *
SQR(sigma);
8062 int sy = (int) (3. *
DY2DEG(sigma) / fabs(met->
lat[1] - met->
lat[0]));
8066#pragma omp parallel for default(shared) collapse(2)
8067 for (
int ix = 0; ix < met->
nx; ix++) {
8068 for (
int iy = 0; iy < met->
ny; iy++) {
8076 (int) (3. *
DX2DEG(sigma, met->
lat[iy]) /
8077 fabs(met->
lon[1] - met->
lon[0]));
8082 for (
int ip = 0; ip < met->
np; ip++) {
8083 help->
t[ix][iy][ip] = 0;
8084 help->
u[ix][iy][ip] = 0;
8085 help->
v[ix][iy][ip] = 0;
8086 help->
w[ix][iy][ip] = 0;
8090 for (
int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
8094 else if (ix3 >= met->
nx)
8096 for (
int iy2 =
MAX(iy - sy, 0);
8097 iy2 <=
MIN(iy + sy, met->
ny - 1); iy2++) {
8104 const float w = (float) exp(-
DIST2(x0, x1) / tssq);
8108 for (
int ip = 0; ip < met->
np; ip++) {
8109 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip];
8110 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip];
8111 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip];
8112 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip];
8118 for (
int ip = 0; ip < met->
np; ip++) {
8119 help->
t[ix][iy][ip] /= wsum;
8120 help->
u[ix][iy][ip] /= wsum;
8121 help->
v[ix][iy][ip] /= wsum;
8122 help->
w[ix][iy][ip] /= wsum;
8128#pragma omp parallel for default(shared) collapse(3)
8129 for (
int ix = 0; ix < met->
nx; ix++)
8130 for (
int iy = 0; iy < met->
ny; iy++)
8131 for (
int ip = 0; ip < met->
np; ip++) {
8132 met->
t[ix][iy][ip] -= help->
t[ix][iy][ip];
8133 met->
u[ix][iy][ip] -= help->
u[ix][iy][ip];
8134 met->
v[ix][iy][ip] -= help->
v[ix][iy][ip];
8135 met->
w[ix][iy][ip] -= help->
w[ix][iy][ip];
8149 LOG(2,
"Extrapolate meteo data...");
8152#pragma omp parallel for default(shared) collapse(2)
8153 for (
int ix = 0; ix < met->
nx; ix++)
8154 for (
int iy = 0; iy < met->
ny; iy++) {
8158 for (ip0 = met->
np - 1; ip0 >= 0; ip0--)
8159 if (!isfinite(met->
t[ix][iy][ip0])
8160 || !isfinite(met->
u[ix][iy][ip0])
8161 || !isfinite(met->
v[ix][iy][ip0])
8162 || !isfinite(met->
w[ix][iy][ip0]))
8166 for (
int ip = ip0; ip >= 0; ip--) {
8167 met->
t[ix][iy][ip] = met->
t[ix][iy][ip + 1];
8168 met->
u[ix][iy][ip] = met->
u[ix][iy][ip + 1];
8169 met->
v[ix][iy][ip] = met->
v[ix][iy][ip + 1];
8170 met->
w[ix][iy][ip] = met->
w[ix][iy][ip + 1];
8171 met->
h2o[ix][iy][ip] = met->
h2o[ix][iy][ip + 1];
8172 met->
o3[ix][iy][ip] = met->
o3[ix][iy][ip + 1];
8173 met->
lwc[ix][iy][ip] = met->
lwc[ix][iy][ip + 1];
8174 met->
rwc[ix][iy][ip] = met->
rwc[ix][iy][ip + 1];
8175 met->
iwc[ix][iy][ip] = met->
iwc[ix][iy][ip + 1];
8176 met->
swc[ix][iy][ip] = met->
swc[ix][iy][ip + 1];
8177 met->
cc[ix][iy][ip] = met->
cc[ix][iy][ip + 1];
8196 LOG(2,
"Calculate geopotential heights...");
8203#pragma omp parallel for default(shared)
8204 for (
int ip = 0; ip < met->
np; ip++)
8205 logp[ip] = log(met->
p[ip]);
8208#pragma omp parallel for default(shared) collapse(2)
8209 for (
int ix = 0; ix < met->
nx; ix++)
8210 for (
int iy = 0; iy < met->
ny; iy++) {
8213 const double zs = met->
zs[ix][iy];
8214 const double lnps = log(met->
ps[ix][iy]);
8218 const double ts =
LIN(met->
p[ip0], met->
t[ix][iy][ip0], met->
p[ip0 + 1],
8219 met->
t[ix][iy][ip0 + 1], met->
ps[ix][iy]);
8221 LIN(met->
p[ip0], met->
h2o[ix][iy][ip0], met->
p[ip0 + 1],
8222 met->
h2o[ix][iy][ip0 + 1], met->
ps[ix][iy]);
8225 met->
z[ix][iy][ip0 + 1]
8227 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
8228 met->
t[ix][iy][ip0 + 1], met->
h2o[ix][iy][ip0 + 1]));
8229 for (
int ip = ip0 + 2; ip < met->
np; ip++)
8231 = (
float) (met->
z[ix][iy][ip - 1] +
8232 ZDIFF(logp[ip - 1], met->
t[ix][iy][ip - 1],
8233 met->
h2o[ix][iy][ip - 1], logp[ip],
8234 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
8239 ZDIFF(lnps, ts, h2os, logp[ip0],
8240 met->
t[ix][iy][ip0], met->
h2o[ix][iy][ip0]));
8241 for (
int ip = ip0 - 1; ip >= 0; ip--)
8243 = (
float) (met->
z[ix][iy][ip + 1] +
8244 ZDIFF(logp[ip + 1], met->
t[ix][iy][ip + 1],
8245 met->
h2o[ix][iy][ip + 1], logp[ip],
8246 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
8250 if (dx == 0 || dy == 0)
8254 if (dx < 0 || dy < 0) {
8255 if (fabs(met->
lon[1] - met->
lon[0]) < 0.5) {
8265 float ws[dx + 1][dy + 1];
8266#pragma omp parallel for default(shared) collapse(2)
8267 for (
int ix = 0; ix <= dx; ix++)
8268 for (
int iy = 0; iy < dy; iy++)
8269 ws[ix][iy] = (1.0f - (
float) ix / (float) dx)
8270 * (1.0f - (float) iy / (
float) dy);
8273#pragma omp parallel for default(shared) collapse(3)
8274 for (
int ix = 0; ix < met->
nx; ix++)
8275 for (
int iy = 0; iy < met->
ny; iy++)
8276 for (
int ip = 0; ip < met->
np; ip++)
8277 help[
ARRAY_3D(ip, ix, met->
nx, iy, met->
ny)] = met->
z[ix][iy][ip];
8280#pragma omp parallel for default(shared) collapse(3)
8281 for (
int ip = 0; ip < met->
np; ip++)
8282 for (
int ix = 0; ix < met->
nx; ix++)
8283 for (
int iy = 0; iy < met->
ny; iy++) {
8284 float res = 0, wsum = 0;
8285 int iy0 =
MAX(iy - dy + 1, 0);
8286 int iy1 =
MIN(iy + dy - 1, met->
ny - 1);
8287 for (
int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
8291 else if (ix3 >= met->
nx)
8293 for (
int iy2 = iy0; iy2 <= iy1; ++iy2)
8294 if (isfinite(help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)])) {
8295 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
8296 res += w * help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)];
8301 met->
z[ix][iy][ip] = res / wsum;
8303 met->
z[ix][iy][ip] = NAN;
8313 const char *filename,
8319 char levname[
LEN], tstr[10];
8321 double rtime = 0, r, r2;
8323 int varid, ndims, dimids[NC_MAX_DIMS], year2, mon2, day2, hour2, min2, sec2,
8324 year, mon, day, hour, min, sec;
8330 LOG(2,
"Read meteo grid information...");
8339 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
8340 if (nc_inq_varid(ncid,
"time", &varid) == NC_NOERR) {
8341 NC(nc_get_var_double(ncid, varid, &rtime));
8342 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
8343 WARN(
"Time information in meteo file does not match filename!");
8345 WARN(
"Time information in meteo file is missing!");
8356 sprintf(tstr,
"19%.2s", &filename[strlen(filename) - 11]);
8358 sprintf(tstr,
"20%.2s", &filename[strlen(filename) - 11]);
8360 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 9]);
8362 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 7]);
8364 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 5]);
8370 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
8371 || day < 1 || day > 31 || hour < 0 || hour > 23)
8372 ERRMSG(
"Cannot read time from filename!");
8373 jsec2time(met->
time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
8374 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
8375 met->
time, year2, mon2, day2, hour2, min2);
8378 if (nc_inq_varid(ncid,
"u", &varid) != NC_NOERR)
8379 if (nc_inq_varid(ncid,
"U", &varid) != NC_NOERR)
8381 (
"Variable 'u' or 'U' not found, cannot determine vertical dimension!");
8383 NC(nc_inq_varndims(ncid, varid, &ndims));
8384 NC(nc_inq_vardimid(ncid, varid, dimids));
8388 (ncid, dimids[ctl->
met_convention == 0 ? 1 : 3], levname, &dimlen));
8389 }
else if (ndims == 3) {
8391 (ncid, dimids[ctl->
met_convention == 0 ? 0 : 2], levname, &dimlen));
8393 ERRMSG(
"Cannot determine vertical dimension!")
8394 met->
np = (int) dimlen;
8396 LOG(2,
"Number of levels: %d", met->
np);
8397 if (met->
np < 2 || met->
np >
EP)
8398 ERRMSG(
"Number of levels out of range!");
8404 LOG(2,
"Number of longitudes: %d", met->
nx);
8407 LOG(2,
"Number of latitudes: %d", met->
ny);
8411 LOG(2,
"Longitudes: %g, %g ... %g deg",
8414 LOG(2,
"Latitudes: %g, %g ... %g deg",
8427 for (
int ip = 0; ip < met->
np; ip++)
8429 LOG(2,
"Altitude levels: %g, %g ... %g km",
8430 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
8431 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
8432 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
8436 if (strcasecmp(levname,
"hybrid") == 0)
8448 ERRMSG(
"You need to specify MET_NLEV, MET_LEV_HYAM, and MET_LEV_HYBM!");
8449 for (
int ip = 0; ip < ctl->
met_nlev; ip++) {
8457 met->
eta[k] = met->
hyam[k] / 100000.0 + met->
hybm[k];
8459 ERRMSG(
"Eta levels must be ascending!");
8463 for (
int ix = 2; ix < met->
nx; ix++)
8465 (fabs(met->
lon[ix] - met->
lon[ix - 1]) -
8466 fabs(met->
lon[1] - met->
lon[0])) > 0.001)
8467 ERRMSG(
"No regular grid spacing in longitudes!");
8468 for (
int iy = 2; iy < met->
ny; iy++)
8470 (fabs(met->
lat[iy] - met->
lat[iy - 1]) -
8471 fabs(met->
lat[1] - met->
lat[0])) > 0.001) {
8472 WARN(
"No regular grid spacing in latitudes!");
8487 LOG(2,
"Read surface data...");
8491 (ncid,
"lnsp",
"LNSP", NULL, NULL, NULL, NULL, ctl, met, dd, met->
ps,
8493 for (
int ix = 0; ix < met->
nx; ix++)
8494 for (
int iy = 0; iy < met->
ny; iy++)
8495 met->
ps[ix][iy] = (
float) (exp(met->
ps[ix][iy]) / 100.);
8498 (ncid,
"ps",
"PS",
"sp",
"SP", NULL, NULL, ctl, met, dd, met->
ps,
8500 WARN(
"Cannot not read surface pressure data (use lowest level)!");
8501 for (
int ix = 0; ix < met->
nx; ix++)
8502 for (
int iy = 0; iy < met->
ny; iy++)
8504 = (ctl->
met_np > 0 ? (
float) ctl->
met_p[0] : (
float) met->
p[0]);
8512 (ncid,
"z",
"Z", NULL, NULL, NULL, NULL, ctl, met, dd, met->
zs,
8513 (
float) (1. / (1000. *
G0)), 1))
8515 (ncid,
"zm",
"ZM", NULL, NULL, NULL, NULL, ctl, met, dd, met->
zs,
8516 (
float) (1. / 1000.), 1))
8517 WARN(
"Cannot read surface geopotential height!");
8528 memcpy(help, met->
pl,
sizeof(met->
pl));
8530 (ncid,
"gph",
"GPH", NULL, NULL, ctl, met, dd, met->
pl,
8531 (
float) (1e-3 /
G0)))
8532 ERRMSG(
"Cannot read geopotential height!");
8533 for (
int ix = 0; ix < met->
nx; ix++)
8534 for (
int iy = 0; iy < met->
ny; iy++)
8535 met->
zs[ix][iy] = met->
pl[ix][iy][0];
8536 memcpy(met->
pl, help,
sizeof(met->
pl));
8542 (ncid,
"t2m",
"T2M",
"2t",
"2T",
"t2",
"T2", ctl, met, dd, met->
ts, 1.0,
8544 WARN(
"Cannot read surface temperature!");
8548 (ncid,
"u10m",
"U10M",
"10u",
"10U",
"u10",
"U10", ctl, met, dd,
8550 WARN(
"Cannot read surface zonal wind!");
8554 (ncid,
"v10m",
"V10M",
"10v",
"10V",
"v10",
"V10", ctl, met, dd,
8556 WARN(
"Cannot read surface meridional wind!");
8560 (ncid,
"iews",
"IEWS", NULL, NULL, NULL, NULL, ctl, met, dd, met->
ess,
8562 WARN(
"Cannot read eastward turbulent surface stress!");
8566 (ncid,
"inss",
"INSS", NULL, NULL, NULL, NULL, ctl, met, dd, met->
nss,
8568 WARN(
"Cannot read nothward turbulent surface stress!");
8572 (ncid,
"ishf",
"ISHF", NULL, NULL, NULL, NULL, ctl, met, dd, met->
shf,
8574 WARN(
"Cannot read surface sensible heat flux!");
8578 (ncid,
"lsm",
"LSM", NULL, NULL, NULL, NULL, ctl, met, dd, met->
lsm,
8580 WARN(
"Cannot read land-sea mask!");
8584 (ncid,
"sstk",
"SSTK",
"sst",
"SST", NULL, NULL, ctl, met, dd, met->
sst,
8586 WARN(
"Cannot read sea surface temperature!");
8591 (ncid,
"blp",
"BLP", NULL, NULL, NULL, NULL, ctl, met, dd, met->
pbl,
8593 WARN(
"Cannot read planetary boundary layer pressure!");
8596 (ncid,
"blh",
"BLH", NULL, NULL, NULL, NULL, ctl, met, dd, met->
pbl,
8598 WARN(
"Cannot read planetary boundary layer height!");
8603 (ncid,
"cape",
"CAPE", NULL, NULL, NULL, NULL, ctl, met, dd,
8605 WARN(
"Cannot read CAPE!");
8610 (ncid,
"cin",
"CIN", NULL, NULL, NULL, NULL, ctl, met, dd, met->
cin,
8612 WARN(
"Cannot read convective inhibition!");
8625 LOG(2,
"Read level data...");
8629 (ncid,
"t",
"T",
"temp",
"TEMP", ctl, met, dd, met->
t, 1.0))
8630 ERRMSG(
"Cannot read temperature!");
8633 if (!
read_met_nc_3d(ncid,
"u",
"U", NULL, NULL, ctl, met, dd, met->
u, 1.0))
8634 ERRMSG(
"Cannot read zonal wind!");
8635 if (!
read_met_nc_3d(ncid,
"v",
"V", NULL, NULL, ctl, met, dd, met->
v, 1.0))
8636 ERRMSG(
"Cannot read meridional wind!");
8638 (ncid,
"w",
"W",
"omega",
"OMEGA", ctl, met, dd, met->
w, 0.01f))
8639 WARN(
"Cannot read vertical velocity!");
8644 (ncid,
"q",
"Q",
"sh",
"SH", ctl, met, dd, met->
h2o,
8646 WARN(
"Cannot read specific humidity!");
8649 (ncid,
"rh",
"RH", NULL, NULL, ctl, met, dd, met->
h2o, 0.01f))
8650 WARN(
"Cannot read relative humidity!");
8651#pragma omp parallel for default(shared) collapse(2)
8652 for (
int ix = 0; ix < met->
nx; ix++)
8653 for (
int iy = 0; iy < met->
ny; iy++)
8654 for (
int ip = 0; ip < met->
np; ip++) {
8655 double pw = met->
h2o[ix][iy][ip] *
PSAT(met->
t[ix][iy][ip]);
8656 met->
h2o[ix][iy][ip] =
8657 (float) (pw / (met->
p[ip] - (1.0 -
EPS) * pw));
8663 (ncid,
"o3",
"O3", NULL, NULL, ctl, met, dd, met->
o3,
8664 (
float) (
MA /
MO3)))
8665 WARN(
"Cannot read ozone data!");
8669 (ncid,
"clwc",
"CLWC", NULL, NULL, ctl, met, dd, met->
lwc, 1.0))
8670 WARN(
"Cannot read cloud liquid water content!");
8672 (ncid,
"crwc",
"CRWC", NULL, NULL, ctl, met, dd, met->
rwc, 1.0))
8673 WARN(
"Cannot read cloud rain water content!");
8675 (ncid,
"ciwc",
"CIWC", NULL, NULL, ctl, met, dd, met->
iwc, 1.0))
8676 WARN(
"Cannot read cloud ice water content!");
8678 (ncid,
"cswc",
"CSWC", NULL, NULL, ctl, met, dd, met->
swc, 1.0))
8679 WARN(
"Cannot read cloud snow water content!");
8681 (ncid,
"cc",
"CC", NULL, NULL, ctl, met, dd, met->
cc, 1.0))
8682 WARN(
"Cannot read cloud cover!");
8687 (ncid,
"ZETA",
"zeta", NULL, NULL, ctl, met, dd, met->
zetal, 1.0))
8688 WARN(
"Cannot read ZETA!");
8690 (ncid,
"ZETA_DOT_TOT",
"ZETA_DOT_clr",
"zeta_dot_clr",
8691 NULL, ctl, met, dd, met->
zeta_dotl, 0.00001157407f))
8692 WARN(
"Cannot read ZETA_DOT!");
8697#pragma omp parallel for default(shared)
8698 for (
int ix = 0; ix < met->
nx; ix++)
8699 for (
int iy = 0; iy < met->
ny; iy++)
8700 for (
int ip = 0; ip < met->
np; ip++)
8701 met->
zetal[ix][iy][ip] =
8702 (
float) (met->
hyam[ip] / 100000.0 + met->
hybm[ip]);
8704 (ncid,
"etadot",
"ETADOT", NULL, NULL, ctl, met, dd, met->
zeta_dotl,
8706 WARN(
"Cannot read eta vertical velocity!");
8711#pragma omp parallel for default(shared)
8712 for (
int ix = 0; ix < met->
nx; ix++)
8713 for (
int iy = 0; iy < met->
ny; iy++)
8714 for (
int ip = 0; ip < met->
np; ip++) {
8715 met->
ul[ix][iy][ip] = met->
u[ix][iy][ip];
8716 met->
vl[ix][iy][ip] = met->
v[ix][iy][ip];
8717 met->
wl[ix][iy][ip] = met->
w[ix][iy][ip];
8730 (ncid,
"pl",
"PL",
"pressure",
"PRESSURE", ctl, met, dd, met->
pl,
8733 (ncid,
"press",
"PRESS", NULL, NULL, ctl, met, dd, met->
pl, 1.0))
8734 ERRMSG(
"Cannot read pressure on model levels!");
8742 ERRMSG(
"Mismatch in number of model levels!");
8745 for (
int ix = 0; ix < met->
nx; ix++)
8746 for (
int iy = 0; iy < met->
ny; iy++)
8747 for (
int ip = 0; ip < met->
np; ip++)
8748 met->
pl[ix][iy][ip] =
8749 (
float) (met->
hyam[ip] / 100. +
8750 met->
hybm[ip] * met->
ps[ix][iy]);
8758 ERRMSG(
"Mismatch in number of model levels!");
8761#pragma omp parallel for default(shared) collapse(2)
8762 for (
int ix = 0; ix < met->
nx; ix++)
8763 for (
int iy = 0; iy < met->
ny; iy++)
8764 for (
int ip = 0; ip < met->
np; ip++) {
8766 met->
hyam[ip] / 100. + met->
hybm[ip] * met->
ps[ix][iy];
8768 met->
hyam[ip + 1] / 100. + met->
hybm[ip + 1] * met->
ps[ix][iy];
8769 met->
pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
8774 for (
int ix = 0; ix < met->
nx; ix++)
8775 for (
int iy = 0; iy < met->
ny; iy++)
8776 for (
int ip = 1; ip < met->
np; ip++)
8777 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
8778 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
8779 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
8780 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip]))
8781 ERRMSG(
"Pressure profiles are not monotonic!");
8802 for (
int ip = 0; ip < met->
np; ip++)
8803 met->
p[ip] = ctl->
met_p[ip];
8807 for (
int ip = 1; ip < met->
np; ip++)
8808 if (met->
p[ip - 1] < met->
p[ip])
8809 ERRMSG(
"Pressure levels must be descending!");
8816 const char *varname,
8817 const char *varname2,
8818 const char *varname3,
8819 const char *varname4,
8820 const char *varname5,
8821 const char *varname6,
8831 float offset, scalfac;
8836 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
8837 sprintf(varsel,
"%s", varname);
8838 else if (varname2 != NULL
8839 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
8840 sprintf(varsel,
"%s", varname2);
8841 else if (varname3 != NULL
8842 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
8843 sprintf(varsel,
"%s", varname3);
8844 else if (varname4 != NULL
8845 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
8846 sprintf(varsel,
"%s", varname4);
8847 else if (varname5 != NULL
8848 && nc_inq_varid(ncid, varname5, &varid) == NC_NOERR)
8849 sprintf(varsel,
"%s", varname5);
8850 else if (varname6 != NULL
8851 && nc_inq_varid(ncid, varname6, &varid) == NC_NOERR)
8852 sprintf(varsel,
"%s", varname6);
8858 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
8859 && nc_get_att_float(ncid, varid,
"scale_factor",
8860 &scalfac) == NC_NOERR) {
8868 short fillval, missval;
8869 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8871 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8875 LOG(2,
"Read 2-D variable: %s"
8876 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
8877 varsel, fillval, missval, scalfac, offset);
8880 NC(nc_get_var_short(ncid, varid, help));
8884 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
8888#pragma omp parallel for default(shared)
8889 for (
int ix = 0; ix < met->
nx; ix++)
8890 for (
int iy = 0; iy < met->
ny; iy++) {
8893 const short aux = help[
ARRAY_2D(iy, ix, met->
nx)];
8894 if ((fillval == 0 || aux != fillval)
8895 && (missval == 0 || aux != missval)
8896 && fabsf(aux * scalfac + offset) < 1e14f)
8897 dest[ix][iy] += scl * (aux * scalfac + offset);
8908 else if (!ctl->
dd) {
8916 float fillval, missval;
8917 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8919 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8923 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
8924 varsel, fillval, missval);
8927 NC(nc_get_var_float(ncid, varid, help));
8934#pragma omp parallel for default(shared)
8935 for (
int ix = 0; ix < met->
nx; ix++)
8936 for (
int iy = 0; iy < met->
ny; iy++) {
8939 const float aux = help[
ARRAY_2D(iy, ix, met->
nx)];
8940 if ((fillval == 0 || aux != fillval)
8941 && (missval == 0 || aux != missval)
8942 && fabsf(aux) < 1e14f)
8943 dest[ix][iy] += scl * aux;
8953#pragma omp parallel for default(shared)
8954 for (
int iy = 0; iy < met->
ny; iy++)
8955 for (
int ix = 0; ix < met->
nx; ix++) {
8958 const float aux = help[
ARRAY_2D(ix, iy, met->
ny)];
8959 if ((fillval == 0 || aux != fillval)
8960 && (missval == 0 || aux != missval)
8961 && fabsf(aux) < 1e14f)
8962 dest[ix][iy] += scl * aux;
8977 float fillval, missval;
8978 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8980 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8984 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
8985 varsel, fillval, missval);
8989 size_t help_subdomain_start[3];
8990 size_t help_subdomain_count[3];
8992 help_subdomain_start[0] = 0;
8996 help_subdomain_count[0] = 1;
9005 NC(nc_get_vara_float
9006 (ncid, varid, help_subdomain_start, help_subdomain_count, help));
9009 size_t help_halo_bnd_start[3];
9010 size_t help_halo_bnd_count[3];
9012 help_halo_bnd_start[0] = 0;
9016 help_halo_bnd_count[0] = 1;
9021 ALLOC(help_halo,
float,
9022 help_halo_bnd_count[1] * help_halo_bnd_count[2]);
9023 NC(nc_get_vara_float
9024 (ncid, varid, help_halo_bnd_start, help_halo_bnd_count, help_halo));
9029#pragma omp parallel for default(shared) num_threads(12)
9030 for (
int ix = 0; ix < (int) help_subdomain_count[2]; ix++)
9031 for (
int iy = 0; iy < (int) help_subdomain_count[1]; iy++) {
9035 help[
ARRAY_2D(iy, ix, (
int) help_subdomain_count[2])];
9036 if ((fillval == 0 || aux != fillval)
9037 && (missval == 0 || aux != missval)
9038 && fabsf(aux) < 1e14f) {
9045#pragma omp parallel for default(shared) num_threads(12)
9046 for (
int ix = 0; ix < (int) help_halo_bnd_count[2]; ix++)
9047 for (
int iy = 0; iy < (int) help_halo_bnd_count[1]; iy++) {
9051 help_halo[
ARRAY_2D(iy, ix, (
int) help_halo_bnd_count[2])];
9052 if ((fillval == 0 || aux != fillval)
9053 && (missval == 0 || aux != missval)
9054 && fabsf(aux) < 1e14f)
9062 ERRMSG(
"Domain decomposition with data convection incompatible!");
9078 const char *varname,
9079 const char *varname2,
9080 const char *varname3,
9081 const char *varname4,
9092 float offset, scalfac;
9097 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
9098 sprintf(varsel,
"%s", varname);
9099 else if (varname2 != NULL
9100 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
9101 sprintf(varsel,
"%s", varname2);
9102 else if (varname3 != NULL
9103 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
9104 sprintf(varsel,
"%s", varname3);
9105 else if (varname4 != NULL
9106 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
9107 sprintf(varsel,
"%s", varname4);
9112 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
9113 && nc_get_att_float(ncid, varid,
"scale_factor",
9114 &scalfac) == NC_NOERR) {
9122 short fillval, missval;
9123 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9125 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9129 LOG(2,
"Read 3-D variable: %s "
9130 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
9131 varsel, fillval, missval, scalfac, offset);
9134 NC(nc_get_var_short(ncid, varid, help));
9138 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
9142#pragma omp parallel for default(shared)
9143 for (
int ix = 0; ix < met->
nx; ix++)
9144 for (
int iy = 0; iy < met->
ny; iy++)
9145 for (
int ip = 0; ip < met->
np; ip++) {
9146 const short aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
9147 if ((fillval == 0 || aux != fillval)
9148 && (missval == 0 || aux != missval)
9149 && fabsf(aux * scalfac + offset) < 1e14f)
9150 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
9152 dest[ix][iy][ip] = NAN;
9161 else if (!ctl->
dd) {
9169 float fillval, missval;
9170 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9172 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9176 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
9177 varsel, fillval, missval);
9180 NC(nc_get_var_float(ncid, varid, help));
9187#pragma omp parallel for default(shared)
9188 for (
int ix = 0; ix < met->
nx; ix++)
9189 for (
int iy = 0; iy < met->
ny; iy++)
9190 for (
int ip = 0; ip < met->
np; ip++) {
9191 const float aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
9192 if ((fillval == 0 || aux != fillval)
9193 && (missval == 0 || aux != missval)
9194 && fabsf(aux) < 1e14f)
9195 dest[ix][iy][ip] = scl * aux;
9197 dest[ix][iy][ip] = NAN;
9205#pragma omp parallel for default(shared)
9206 for (
int ip = 0; ip < met->
np; ip++)
9207 for (
int iy = 0; iy < met->
ny; iy++)
9208 for (
int ix = 0; ix < met->
nx; ix++) {
9209 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9210 if ((fillval == 0 || aux != fillval)
9211 && (missval == 0 || aux != missval)
9212 && fabsf(aux) < 1e14f)
9213 dest[ix][iy][ip] = scl * aux;
9215 dest[ix][iy][ip] = NAN;
9228 float fillval, missval;
9229 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9231 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9235 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
9236 varsel, fillval, missval);
9251 NC(nc_get_vara_float
9256 ALLOC(help_halo,
float,
9263 NC(nc_get_vara_float(ncid,
9272#pragma omp parallel for default(shared) num_threads(12)
9275 for (
int ip = 0; ip < met->
np; ip++) {
9279 if ((fillval == 0 || aux != fillval)
9280 && (missval == 0 || aux != missval)
9281 && fabsf(aux) < 1e14f)
9287#pragma omp parallel for default(shared) num_threads(12)
9290 for (
int ip = 0; ip < met->
np; ip++) {
9294 if ((fillval == 0 || aux != fillval)
9295 && (missval == 0 || aux != missval)
9296 && fabsf(aux) < 1e14f)
9305#pragma omp parallel for default(shared) num_threads(12)
9306 for (
int ip = 0; ip < met->
np; ip++)
9309 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9310 if ((fillval == 0 || aux != fillval)
9311 && (missval == 0 || aux != missval)
9312 && fabsf(aux) < 1e14f)
9318#pragma omp parallel for default(shared) num_threads(12)
9319 for (
int ip = 0; ip < met->
np; ip++)
9322 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9323 if ((fillval == 0 || aux != fillval)
9324 && (missval == 0 || aux != missval)
9325 && fabsf(aux) < 1e14f)
9345 const char *filename,
9350 size_t filename_len = strlen(filename) + 1;
9351 char sf_filename[filename_len];
9352 char ml_filename[filename_len];
9353 strcpy(sf_filename, filename);
9354 strcpy(ml_filename, filename);
9359 FILE *ml_file = fopen(ml_filename,
"rb");
9360 FILE *sf_file = fopen(sf_filename,
"rb");
9361 if (ml_file == NULL || sf_file == NULL) {
9362 if (ml_file != NULL) {
9364 WARN(
"Cannot open file: %s", sf_filename);
9366 if (sf_file != NULL) {
9368 WARN(
"Cannot open file: %s", ml_filename);
9374 int ml_num_messages = 0, err = 0;
9375 ECC(codes_count_in_file(0, ml_file, &ml_num_messages));
9378 (size_t) ml_num_messages);
9379 for (
int i = 0; i < ml_num_messages; i++) {
9381 if ((h = codes_grib_handle_new_from_file(0, ml_file, &err)) != NULL)
9386 int sf_num_messages = 0;
9387 ECC(codes_count_in_file(0, sf_file, &sf_num_messages));
9390 (size_t) sf_num_messages);
9391 for (
int i = 0; i < sf_num_messages; i++) {
9393 if ((h = codes_grib_handle_new_from_file(0, sf_file, &err)) != NULL)
9406 for (
int i = 0; i < sf_num_messages; i++)
9407 codes_handle_delete(sf_handles[i]);
9411 size_t value_count = 0;
9412 ECC(codes_get_size(ml_handles[0],
"pv", &value_count));
9413 if (value_count % 2 != 0)
9414 ERRMSG(
"Unexpected pv array length!");
9415 size_t nlevels = value_count / 2 - 1;
9417 ALLOC(values,
double,
9419 ECC(codes_get_double_array(ml_handles[0],
"pv", values, &value_count));
9420 double *a_vals = values;
9421 double *b_vals = values + nlevels;
9422 if (met->
npl > (
int) nlevels)
9423 ERRMSG(
"met->npl exceeds number of pressure levels in GRIB!");
9424 for (
int nx = 0; nx < met->
nx; nx++)
9425 for (
int ny = 0; ny < met->
ny; ny++)
9426 for (
int level = 0; level <= met->
npl; level++) {
9427 const float p1 = (float) (a_vals[level] * 0.01f +
9428 met->
ps[nx][ny] * b_vals[level]);
9429 const float p2 = (float) (a_vals[level + 1] * 0.01f +
9430 met->
ps[nx][ny] * b_vals[level + 1]);
9431 met->
pl[nx][ny][level] = 0.5f * (p1 + p2);
9437 for (
int i = 0; i < ml_num_messages; i++)
9438 codes_handle_delete(ml_handles[i]);
9456 LOG(2,
"Read meteo grid information...");
9459 char datestr[
LEN], timestr[
LEN];
9460 size_t s_date =
sizeof(datestr);
9461 ECC(codes_get_string(handles[0],
"dataDate", datestr, &s_date));
9462 size_t s_time =
sizeof(timestr);
9463 ECC(codes_get_string(handles[0],
"dataTime", timestr, &s_time));
9464 int year, month, day, hour;
9465 if (sscanf(datestr,
"%4d%2d%2d", &year, &month, &day) != 3)
9466 ERRMSG(
"Failed to parse dataDate: %s", datestr);
9467 if (sscanf(timestr,
"%2d", &hour) != 1)
9468 ERRMSG(
"Failed to parse dataTime: %s", timestr);
9470 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)", met->
time, year, month,
9474 long count_lat = 0, count_lon = 0;
9475 ECC(codes_get_long(handles[0],
"Nj", &count_lat));
9476 ECC(codes_get_long(handles[0],
"Ni", &count_lon));
9477 met->
ny = (int) count_lat;
9478 met->
nx = (int) count_lon;
9481 LOG(2,
"Number of longitudes: %d", met->
nx);
9482 if (met->
nx < 2 || met->
nx >
EX)
9483 ERRMSG(
"Number of longitudes out of range!");
9484 LOG(2,
"Number of latitudes: %d", met->
ny);
9485 if (met->
ny < 2 || met->
ny >
EY)
9486 ERRMSG(
"Number of latitudes out of range!");
9488 double first_lon, last_lon, first_lat, last_lat, inc_lon, inc_lat;
9489 ECC(codes_get_double
9490 (handles[0],
"longitudeOfFirstGridPointInDegrees", &first_lon));
9491 ECC(codes_get_double
9492 (handles[0],
"latitudeOfFirstGridPointInDegrees", &first_lat));
9493 ECC(codes_get_double
9494 (handles[0],
"longitudeOfLastGridPointInDegrees", &last_lon));
9495 ECC(codes_get_double
9496 (handles[0],
"latitudeOfLastGridPointInDegrees", &last_lat));
9497 ECC(codes_get_double(handles[0],
"iDirectionIncrementInDegrees", &inc_lon));
9498 ECC(codes_get_double(handles[0],
"jDirectionIncrementInDegrees", &inc_lat));
9500 long jscanpos, iscanneg;
9501 ECC(codes_get_long(handles[0],
"iScansNegatively", &iscanneg));
9502 ECC(codes_get_long(handles[0],
"jScansPositively", &jscanpos));
9507 for (
double i = first_lon; i <= last_lon + 1e-6; i += inc_lon) {
9508 met->
lon[counter] = i;
9511 for (
double i = first_lon; i > last_lon - 1e-6; i -= inc_lon) {
9512 met->
lon[counter] = i;
9518 for (
double i = first_lat; i > last_lat - 1e-6; i -= inc_lat) {
9519 met->
lat[counter] = i;
9522 for (
double i = first_lat; i <= last_lat + 1e-6; i += inc_lat) {
9523 met->
lat[counter] = i;
9528 LOG(2,
"Longitudes: %g, %g ... %g deg",
9530 LOG(2,
"Latitudes: %g, %g ... %g deg",
9535 for (
int i = 0; i < count_handles; i++) {
9537 ECC(codes_get_long(handles[i],
"level", &level));
9538 if (level > max_level)
9539 max_level = (int) level;
9541 met->
npl = max_level;
9544 LOG(2,
"Number of levels: %d", met->
npl);
9546 ERRMSG(
"Number of levels out of range!");
9555 const int num_messages,
9561 LOG(2,
"Read level data...");
9564 int t_flag = 0, u_flag = 0, v_flag = 0, w_flag = 0, o3_flag = 0, h2o_flag =
9565 0, lwc_flag = 0, rwc_flag = 0, iwc_flag = 0, swc_flag = 0, cc_flag = 0;
9568 for (
int i = 0; i < num_messages; i++) {
9570 size_t max_size =
LEN;
9571 char short_name[max_size];
9577 ECC(codes_get_long(handles[i],
"level", ¤t_level));
9581 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
9582 ECC(codes_get_size(handles[i],
"values", &value_count));
9583 ALLOC(values,
double,
9585 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
9593 ECC_READ_3D(
"w", current_level, met->
w, 0.01f, w_flag);
9611 if (t_flag != met->
npl)
9612 ERRMSG(
"Cannot read temperature!");
9613 if (u_flag != met->
npl)
9614 ERRMSG(
"Cannot read zonal wind!");
9615 if (v_flag != met->
npl)
9616 ERRMSG(
"Cannot read meridional wind!");
9617 if (w_flag != met->
npl)
9618 WARN(
"Cannot read vertical velocity!");
9619 if (h2o_flag != met->
npl)
9620 WARN(
"Cannot read specific humidity!");
9621 if (o3_flag != met->
npl)
9622 WARN(
"Cannot read ozone data!");
9623 if (lwc_flag != met->
npl)
9624 WARN(
"Cannot read cloud liquid water content!");
9625 if (rwc_flag != met->
npl)
9626 WARN(
"Cannot read cloud rain water content!");
9627 if (iwc_flag != met->
npl)
9628 WARN(
"Cannot read cloud ice water content!");
9629 if (swc_flag != met->
npl)
9630 WARN(
"Cannot read cloud snow water content!");
9631 if (cc_flag != met->
npl)
9632 WARN(
"Cannot read cloud cover!");
9635 for (
int ix = 0; ix < met->
nx; ix++)
9636 for (
int iy = 0; iy < met->
ny; iy++)
9637 for (
int ip = 1; ip < met->
np; ip++)
9638 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
9639 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
9640 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
9641 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip])) {
9642 LOG(1,
"%f %f %f %f", met->
pl[ix][iy][0], met->
pl[ix][iy][1],
9643 met->
pl[ix][iy][ip - 1], met->
pl[ix][iy][ip]);
9644 ERRMSG(
"Pressure profiles are not monotonic!");
9665 for (
int ip = 0; ip < met->
np; ip++)
9666 met->
p[ip] = ctl->
met_p[ip];
9670 for (
int ip = 1; ip < met->
np; ip++)
9671 if (met->
p[ip - 1] < met->
p[ip])
9672 ERRMSG(
"Pressure levels must be descending!");
9681 const int num_messages,
9687 LOG(2,
"Read surface data...");
9690 int sp_flag = 0, z_flag = 0, t_flag = 0, u_flag = 0, v_flag = 0, lsm_flag =
9691 0, sst_flag = 0, cape_flag = 0, cin_flag = 0, pbl_flag = 0;
9694 for (
int i = 0; i < num_messages; i++) {
9696 size_t max_size =
LEN, value_count;
9698 char short_name[max_size];
9701 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
9702 ECC(codes_get_size(handles[i],
"values", &value_count));
9703 double *values = (
double *) malloc(value_count *
sizeof(
double));
9704 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
9742 WARN(
"Cannot read surface pressure data!");
9744 WARN(
"Cannot read surface geopotential height!");
9746 WARN(
"Cannot read surface temperature!");
9748 WARN(
"Cannot read surface zonal wind!");
9750 WARN(
"Cannot read surface meridional wind!");
9752 WARN(
"Cannot read land-sea mask!");
9754 WARN(
"Cannot read sea surface temperature!");
9757 WARN(
"Cannot read CAPE!");
9759 WARN(
"Cannot read convective inhibition!");
9761 if (ctl->
met_pbl == 0 && pbl_flag == 0)
9762 WARN(
"Cannot read planetary boundary layer!");
9772 const char *varname) {
9774 double aux[
EP], p[
EP];
9778 LOG(2,
"Interpolate meteo data to pressure levels: %s", varname);
9781#pragma omp parallel for default(shared) private(aux,p) collapse(2)
9782 for (
int ix = 0; ix < met->
nx; ix++)
9783 for (
int iy = 0; iy < met->
ny; iy++) {
9786 for (
int ip = 0; ip < met->
np; ip++)
9787 p[ip] = met->
pl[ix][iy][ip];
9790 for (
int ip = 0; ip < ctl->
met_np; ip++) {
9791 double pt = ctl->
met_p[ip];
9792 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
9794 else if ((pt > p[met->
np - 1] && p[1] > p[0])
9795 || (pt < p[met->
np - 1] && p[1] < p[0]))
9796 pt = p[met->
np - 1];
9798 aux[ip] =
LIN(p[ip2], var[ix][iy][ip2],
9799 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
9803 for (
int ip = 0; ip < ctl->
met_np; ip++)
9804 var[ix][iy][ip] = (
float) aux[ip];
9820 LOG(2,
"Make zeta profiles monotone...");
9823#pragma omp parallel for default(shared) collapse(2)
9824 for (
int i = 0; i < met->
nx; i++)
9825 for (
int j = 0; j < met->
ny; j++) {
9828 while (k < met->npl) {
9829 if ((met->
zetal[i][j][k - 1] >= met->
zetal[i][j][k])) {
9835 while ((met->
zetal[i][j][k - 1] >=
9836 met->
zetal[i][j][k + l]) & (k + l < met->npl));
9841 (float) (met->
zetal[i][j][k + l] - met->
zetal[i][j][k - 1])
9844 for (
int m = k; m < k + l; m++) {
9845 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
9846 met->
zetal[i][j][m] = s * d + met->
zetal[i][j][k - 1];
9858#pragma omp parallel for default(shared) collapse(2)
9859 for (
int i = 0; i < met->
nx; i++)
9860 for (
int j = 0; j < met->
ny; j++) {
9863 while (k < met->npl) {
9864 if ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k])) {
9871 while ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k + l]) & (k + l <
9876 float s = (float) (met->
pl[i][j][k + l] - met->
pl[i][j][k - 1])
9879 for (
int m = k; m < k + l; m++) {
9880 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
9881 met->
pl[i][j][m] = s * d + met->
pl[i][j][k - 1];
9896 const char *filename,
9907 (filename, NC_NOWRITE | NC_SHARE, MPI_COMM_WORLD, MPI_INFO_NULL,
9911 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
9912 WARN(
"Cannot open file!");
9945 MPI_Comm_rank(MPI_COMM_WORLD, &dd->
rank);
9946 MPI_Comm_size(MPI_COMM_WORLD, &dd->
size);
9954 LOG(2,
"Number of longitudes: %d", help_nx_glob);
9958 LOG(2,
"Number of latitudes: %d", help_ny_glob);
9961 double *help_lon_glob;
9962 double *help_lat_glob;
9963 ALLOC(help_lon_glob,
double,
9965 ALLOC(help_lat_glob,
double,
9970 LOG(2,
"Longitudes: %g, %g ... %g deg",
9971 help_lon_glob[0], help_lon_glob[1], help_lon_glob[help_nx_glob - 1]);
9973 LOG(2,
"Latitudes: %g, %g ... %g deg",
9974 help_lat_glob[0], help_lat_glob[1], help_lat_glob[help_ny_glob - 1]);
9998 met->
nx = met->
nx + gap;
9999 WARN(
"Extended subdomains at the right to fit to full domain.");
10005 met->
ny = met->
ny + gap;
10006 WARN(
"Extended subdomains at the bottom to fit to full domain.");
10017 if (!left && !right) {
10034 if (!top && !bottom) {
10052 double lon_shift = 0;
10053 if (left || right) {
10071 lon_shift = (left ? -360 : 360);
10087 double lon_range = 360;
10088 double lat_range = help_lat_glob[help_ny_glob - 1] - help_lat_glob[0];
10115 if (lat_range < 0) {
10122 (
"lat_range > 0, but is expected to be negative, i.e. latitudes should range from 90 to -90")
10129 LOG(2,
"Total longitude range: %g deg", lon_range);
10130 LOG(2,
"Total latitude range: %g deg", lat_range);
10132 LOG(2,
"Define subdomain properties.");
10133 LOG(2,
"MPI information: Rank %d, Size %d", dd->
rank, dd->
size);
10134 LOG(2,
"Edge position: l=%d,r=%d,t=%d, b=%d", (
int) left, (
int) right,
10135 (
int) top, (
int) bottom);
10136 LOG(2,
"Sizes for limits: EX %d EY %d EP %d",
EX,
EY,
EP);
10137 LOG(2,
"Total size for subdomain meteo data: nx %d ny %d np %d", met->
nx,
10139 LOG(2,
"Hyperslab sizes for boundary halos: nx %d ny %d np %d",
10142 LOG(2,
"Hyperslab sizes for subdomain and inner halos: nx %d ny %d np %d",
10151 LOG(2,
" %d Subdomain longitudes: %g, %g ... %g deg (edges: %g to %g)",
10154 LOG(2,
" %d Subdomain latitudes: %g, %g ... %g deg (edges: %g to %g)",
10158 free(help_lon_glob);
10159 free(help_lat_glob);
10170 LOG(2,
"Calculate planetary boundary layer...");
10176#pragma omp parallel for default(shared) collapse(2)
10177 for (
int ix = 0; ix < met->
nx; ix++)
10178 for (
int iy = 0; iy < met->
ny; iy++) {
10181 const float z = met->
zs[ix][iy] + met->
pbl[ix][iy];
10184 (float) (
LIN(met->
z[ix][iy][ip], met->
p[ip],
10185 met->
z[ix][iy][ip + 1], met->
p[ip + 1], z));
10190 else if (ctl->
met_pbl == 2) {
10194 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
10197#pragma omp parallel for default(shared) collapse(2)
10198 for (
int ix = 0; ix < met->
nx; ix++)
10199 for (
int iy = 0; iy < met->
ny; iy++) {
10202 const double pbl_bot = met->
ps[ix][iy] * exp(-dz /
H0);
10206 for (ip = 1; ip < met->
np; ip++)
10207 if (met->
p[ip] < pbl_bot)
10211 const double h2os =
LIN(met->
p[ip - 1], met->
h2o[ix][iy][ip - 1],
10212 met->
p[ip], met->
h2o[ix][iy][ip], pbl_bot);
10213 const double tvs =
THETAVIRT(pbl_bot, met->
ts[ix][iy], h2os);
10216 double rib_old = 0;
10219 for (; ip < met->
np; ip++) {
10222 double vh2 =
SQR(met->
u[ix][iy][ip] - met->
us[ix][iy])
10223 +
SQR(met->
v[ix][iy][ip] - met->
vs[ix][iy]);
10224 vh2 =
MAX(vh2,
SQR(umin));
10228 G0 * 1e3 * (met->
z[ix][iy][ip] - met->
zs[ix][iy]) / tvs
10230 met->
h2o[ix][iy][ip]) - tvs) / vh2;
10233 if (rib >= rib_crit) {
10234 met->
pbl[ix][iy] = (float) (
LIN(rib_old, met->
p[ip - 1],
10235 rib, met->
p[ip], rib_crit));
10236 if (met->
pbl[ix][iy] > pbl_bot)
10237 met->
pbl[ix][iy] = (float) pbl_bot;
10252 const double dtheta = 2.0, zmin = 0.1;
10255#pragma omp parallel for default(shared) collapse(2)
10256 for (
int ix = 0; ix < met->
nx; ix++)
10257 for (
int iy = 0; iy < met->
ny; iy++) {
10260 const double theta0 =
THETA(met->
ps[ix][iy], met->
ts[ix][iy]);
10264 for (ip = met->
np - 2; ip > 0; ip--)
10265 if (met->
p[ip] >= 300.)
10266 if (met->
p[ip] > met->
ps[ix][iy]
10267 ||
THETA(met->
p[ip], met->
t[ix][iy][ip]) <= theta0 + dtheta)
10272 = (float) (
LIN(
THETA(met->
p[ip + 1], met->
t[ix][iy][ip + 1]),
10274 THETA(met->
p[ip], met->
t[ix][iy][ip]),
10275 met->
p[ip], theta0 + dtheta));
10278 double pbl_min = met->
ps[ix][iy] * exp(-zmin /
H0);
10279 if (met->
pbl[ix][iy] > pbl_min || met->
p[ip] > met->
ps[ix][iy])
10280 met->
pbl[ix][iy] = (float) pbl_min;
10285#pragma omp parallel for default(shared) collapse(2)
10286 for (
int ix = 0; ix < met->
nx; ix++)
10287 for (
int iy = 0; iy < met->
ny; iy++) {
10291 met->
pbl[ix][iy] =
MIN(met->
pbl[ix][iy], (
float) pbl_min);
10295 met->
pbl[ix][iy] =
MAX(met->
pbl[ix][iy], (
float) pbl_max);
10306 LOG(2,
"Apply periodic boundary conditions...");
10309 if (!(fabs(met->
lon[met->
nx - 1] - met->
lon[0]
10310 + met->
lon[1] - met->
lon[0] - 360) < 0.01))
10314 if ((++met->
nx) >=
EX)
10315 ERRMSG(
"Cannot create periodic boundary conditions!");
10318 met->
lon[met->
nx - 1] = met->
lon[met->
nx - 2] + met->
lon[1] - met->
lon[0];
10321#pragma omp parallel for default(shared)
10322 for (
int iy = 0; iy < met->
ny; iy++) {
10323 met->
ps[met->
nx - 1][iy] = met->
ps[0][iy];
10324 met->
zs[met->
nx - 1][iy] = met->
zs[0][iy];
10325 met->
ts[met->
nx - 1][iy] = met->
ts[0][iy];
10326 met->
us[met->
nx - 1][iy] = met->
us[0][iy];
10327 met->
vs[met->
nx - 1][iy] = met->
vs[0][iy];
10328 met->
ess[met->
nx - 1][iy] = met->
ess[0][iy];
10329 met->
nss[met->
nx - 1][iy] = met->
nss[0][iy];
10330 met->
shf[met->
nx - 1][iy] = met->
shf[0][iy];
10331 met->
lsm[met->
nx - 1][iy] = met->
lsm[0][iy];
10332 met->
sst[met->
nx - 1][iy] = met->
sst[0][iy];
10333 met->
pbl[met->
nx - 1][iy] = met->
pbl[0][iy];
10334 met->
cape[met->
nx - 1][iy] = met->
cape[0][iy];
10335 met->
cin[met->
nx - 1][iy] = met->
cin[0][iy];
10336 for (
int ip = 0; ip < met->
np; ip++) {
10337 met->
t[met->
nx - 1][iy][ip] = met->
t[0][iy][ip];
10338 met->
u[met->
nx - 1][iy][ip] = met->
u[0][iy][ip];
10339 met->
v[met->
nx - 1][iy][ip] = met->
v[0][iy][ip];
10340 met->
w[met->
nx - 1][iy][ip] = met->
w[0][iy][ip];
10341 met->
h2o[met->
nx - 1][iy][ip] = met->
h2o[0][iy][ip];
10342 met->
o3[met->
nx - 1][iy][ip] = met->
o3[0][iy][ip];
10343 met->
lwc[met->
nx - 1][iy][ip] = met->
lwc[0][iy][ip];
10344 met->
rwc[met->
nx - 1][iy][ip] = met->
rwc[0][iy][ip];
10345 met->
iwc[met->
nx - 1][iy][ip] = met->
iwc[0][iy][ip];
10346 met->
swc[met->
nx - 1][iy][ip] = met->
swc[0][iy][ip];
10347 met->
cc[met->
nx - 1][iy][ip] = met->
cc[0][iy][ip];
10349 for (
int ip = 0; ip < met->
npl; ip++) {
10350 met->
ul[met->
nx - 1][iy][ip] = met->
ul[0][iy][ip];
10351 met->
vl[met->
nx - 1][iy][ip] = met->
vl[0][iy][ip];
10352 met->
wl[met->
nx - 1][iy][ip] = met->
wl[0][iy][ip];
10353 met->
pl[met->
nx - 1][iy][ip] = met->
pl[0][iy][ip];
10354 met->
zetal[met->
nx - 1][iy][ip] = met->
zetal[0][iy][ip];
10367 LOG(2,
"Apply fix for polar winds...");
10370 if (fabs(met->
lat[0]) < 89.999 || fabs(met->
lat[met->
ny - 1]) < 89.999)
10374 for (
int ihem = 0; ihem < 2; ihem++) {
10377 int i89 = 1, i90 = 0, sign = 1;
10382 if (met->
lat[i90] < 0)
10386 double clon[
EX], slon[
EX];
10387#pragma omp parallel for default(shared)
10388 for (
int ix = 0; ix < met->
nx; ix++) {
10389 clon[ix] = cos(sign *
DEG2RAD(met->
lon[ix]));
10390 slon[ix] = sin(sign *
DEG2RAD(met->
lon[ix]));
10394#pragma omp parallel for default(shared)
10395 for (
int ip = 0; ip < met->
np; ip++) {
10398 double vel89x = 0, vel89y = 0;
10399 for (
int ix = 0; ix < met->
nx; ix++) {
10401 (met->
u[ix][i89][ip] * clon[ix] -
10402 met->
v[ix][i89][ip] * slon[ix]) / met->
nx;
10404 (met->
u[ix][i89][ip] * slon[ix] +
10405 met->
v[ix][i89][ip] * clon[ix]) / met->
nx;
10409 for (
int ix = 0; ix < met->
nx; ix++) {
10410 met->
u[ix][i90][ip]
10411 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
10412 met->
v[ix][i90][ip]
10413 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
10428 LOG(2,
"Calculate potential vorticity...");
10431#pragma omp parallel for default(shared)
10432 for (
int ip = 0; ip < met->
np; ip++)
10433 pows[ip] = pow(1000. / met->
p[ip], 0.286);
10436#pragma omp parallel for default(shared)
10437 for (
int ix = 0; ix < met->
nx; ix++) {
10440 const int ix0 =
MAX(ix - 1, 0);
10441 const int ix1 =
MIN(ix + 1, met->
nx - 1);
10444 for (
int iy = 0; iy < met->
ny; iy++) {
10447 const int iy0 =
MAX(iy - 1, 0);
10448 const int iy1 =
MIN(iy + 1, met->
ny - 1);
10451 const double latr = 0.5 * (met->
lat[iy1] + met->
lat[iy0]);
10452 const double dx = 1000. *
DEG2DX(met->
lon[ix1] - met->
lon[ix0], latr);
10453 const double dy = 1000. *
DEG2DY(met->
lat[iy1] - met->
lat[iy0]);
10454 const double c0 = cos(
DEG2RAD(met->
lat[iy0]));
10455 const double c1 = cos(
DEG2RAD(met->
lat[iy1]));
10456 const double cr = cos(
DEG2RAD(latr));
10457 const double vort = 2 * 7.2921e-5 * sin(
DEG2RAD(latr));
10460 for (
int ip = 0; ip < met->
np; ip++) {
10464 = (met->
t[ix1][iy][ip] - met->
t[ix0][iy][ip]) * pows[ip] / dx;
10465 const double dvdx = (met->
v[ix1][iy][ip] - met->
v[ix0][iy][ip]) / dx;
10469 = (met->
t[ix][iy1][ip] - met->
t[ix][iy0][ip]) * pows[ip] / dy;
10471 = (met->
u[ix][iy1][ip] * c1 - met->
u[ix][iy0][ip] * c0) / dy;
10474 const int ip0 =
MAX(ip - 1, 0);
10475 const int ip1 =
MIN(ip + 1, met->
np - 1);
10478 double dtdp, dudp, dvdp;
10479 const double dp0 = 100. * (met->
p[ip] - met->
p[ip0]);
10480 const double dp1 = 100. * (met->
p[ip1] - met->
p[ip]);
10481 if (ip != ip0 && ip != ip1) {
10482 double denom = dp0 * dp1 * (dp0 + dp1);
10483 dtdp = (dp0 * dp0 * met->
t[ix][iy][ip1] * pows[ip1]
10484 - dp1 * dp1 * met->
t[ix][iy][ip0] * pows[ip0]
10485 + (dp1 * dp1 - dp0 * dp0) * met->
t[ix][iy][ip] * pows[ip])
10487 dudp = (dp0 * dp0 * met->
u[ix][iy][ip1]
10488 - dp1 * dp1 * met->
u[ix][iy][ip0]
10489 + (dp1 * dp1 - dp0 * dp0) * met->
u[ix][iy][ip])
10491 dvdp = (dp0 * dp0 * met->
v[ix][iy][ip1]
10492 - dp1 * dp1 * met->
v[ix][iy][ip0]
10493 + (dp1 * dp1 - dp0 * dp0) * met->
v[ix][iy][ip])
10496 const double denom = dp0 + dp1;
10498 (met->
t[ix][iy][ip1] * pows[ip1] -
10499 met->
t[ix][iy][ip0] * pows[ip0]) / denom;
10500 dudp = (met->
u[ix][iy][ip1] - met->
u[ix][iy][ip0]) / denom;
10501 dvdp = (met->
v[ix][iy][ip1] - met->
v[ix][iy][ip0]) / denom;
10505 met->
pv[ix][iy][ip] = (float)
10507 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
10513#pragma omp parallel for default(shared)
10514 for (
int ix = 0; ix < met->
nx; ix++)
10515 for (
int ip = 0; ip < met->
np; ip++) {
10517 = met->
pv[ix][1][ip]
10518 = met->
pv[ix][2][ip];
10519 met->
pv[ix][met->
ny - 1][ip]
10520 = met->
pv[ix][met->
ny - 2][ip]
10521 = met->
pv[ix][met->
ny - 3][ip];
10532 LOG(2,
"Calculate total column ozone...");
10535#pragma omp parallel for default(shared) collapse(2)
10536 for (
int ix = 0; ix < met->
nx; ix++)
10537 for (
int iy = 0; iy < met->
ny; iy++) {
10541 for (
int ip = 1; ip < met->
np; ip++)
10542 if (met->
p[ip - 1] <= met->
ps[ix][iy]) {
10544 0.5 * (met->
o3[ix][iy][ip - 1] + met->
o3[ix][iy][ip]);
10545 const double dp = met->
p[ip - 1] - met->
p[ip];
10546 cd += vmr *
MO3 /
MA * dp * 1e2 /
G0;
10550 met->
o3c[ix][iy] = (float) (cd / 2.1415e-5);
10569 LOG(2,
"Downsampling of meteo data...");
10575 help->
nx = met->
nx;
10576 help->
ny = met->
ny;
10577 help->
np = met->
np;
10578 memcpy(help->
lon, met->
lon,
sizeof(met->
lon));
10579 memcpy(help->
lat, met->
lat,
sizeof(met->
lat));
10580 memcpy(help->
p, met->
p,
sizeof(met->
p));
10583 for (
int ix = 0; ix < met->
nx; ix += ctl->
met_dx) {
10584 for (
int iy = 0; iy < met->
ny; iy += ctl->
met_dy) {
10585 for (
int ip = 0; ip < met->
np; ip += ctl->
met_dp) {
10586 help->
ps[ix][iy] = 0;
10587 help->
zs[ix][iy] = 0;
10588 help->
ts[ix][iy] = 0;
10589 help->
us[ix][iy] = 0;
10590 help->
vs[ix][iy] = 0;
10591 help->
ess[ix][iy] = 0;
10592 help->
nss[ix][iy] = 0;
10593 help->
shf[ix][iy] = 0;
10594 help->
lsm[ix][iy] = 0;
10595 help->
sst[ix][iy] = 0;
10596 help->
pbl[ix][iy] = 0;
10597 help->
cape[ix][iy] = 0;
10598 help->
cin[ix][iy] = 0;
10599 help->
t[ix][iy][ip] = 0;
10600 help->
u[ix][iy][ip] = 0;
10601 help->
v[ix][iy][ip] = 0;
10602 help->
w[ix][iy][ip] = 0;
10603 help->
h2o[ix][iy][ip] = 0;
10604 help->
o3[ix][iy][ip] = 0;
10605 help->
lwc[ix][iy][ip] = 0;
10606 help->
rwc[ix][iy][ip] = 0;
10607 help->
iwc[ix][iy][ip] = 0;
10608 help->
swc[ix][iy][ip] = 0;
10609 help->
cc[ix][iy][ip] = 0;
10611 for (
int ix2 = ix - ctl->
met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
10616 else if (ix3 >= met->
nx)
10619 for (
int iy2 =
MAX(iy - ctl->
met_sy + 1, 0);
10620 iy2 <=
MIN(iy + ctl->
met_sy - 1, met->
ny - 1); iy2++)
10621 for (
int ip2 =
MAX(ip - ctl->
met_sp + 1, 0);
10622 ip2 <=
MIN(ip + ctl->
met_sp - 1, met->
np - 1); ip2++) {
10624 (1.0f - (float) abs(ix - ix2) / (float) ctl->
met_sx)
10625 * (1.0f - (float) abs(iy - iy2) / (float) ctl->
met_sy)
10626 * (1.0f - (float) abs(ip - ip2) / (float) ctl->
met_sp);
10627 help->
ps[ix][iy] += w * met->
ps[ix3][iy2];
10628 help->
zs[ix][iy] += w * met->
zs[ix3][iy2];
10629 help->
ts[ix][iy] += w * met->
ts[ix3][iy2];
10630 help->
us[ix][iy] += w * met->
us[ix3][iy2];
10631 help->
vs[ix][iy] += w * met->
vs[ix3][iy2];
10632 help->
ess[ix][iy] += w * met->
ess[ix3][iy2];
10633 help->
nss[ix][iy] += w * met->
nss[ix3][iy2];
10634 help->
shf[ix][iy] += w * met->
shf[ix3][iy2];
10635 help->
lsm[ix][iy] += w * met->
lsm[ix3][iy2];
10636 help->
sst[ix][iy] += w * met->
sst[ix3][iy2];
10637 help->
pbl[ix][iy] += w * met->
pbl[ix3][iy2];
10638 help->
cape[ix][iy] += w * met->
cape[ix3][iy2];
10639 help->
cin[ix][iy] += w * met->
cin[ix3][iy2];
10640 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip2];
10641 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip2];
10642 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip2];
10643 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip2];
10644 help->
h2o[ix][iy][ip] += w * met->
h2o[ix3][iy2][ip2];
10645 help->
o3[ix][iy][ip] += w * met->
o3[ix3][iy2][ip2];
10646 help->
lwc[ix][iy][ip] += w * met->
lwc[ix3][iy2][ip2];
10647 help->
rwc[ix][iy][ip] += w * met->
rwc[ix3][iy2][ip2];
10648 help->
iwc[ix][iy][ip] += w * met->
iwc[ix3][iy2][ip2];
10649 help->
swc[ix][iy][ip] += w * met->
swc[ix3][iy2][ip2];
10650 help->
cc[ix][iy][ip] += w * met->
cc[ix3][iy2][ip2];
10654 help->
ps[ix][iy] /= wsum;
10655 help->
zs[ix][iy] /= wsum;
10656 help->
ts[ix][iy] /= wsum;
10657 help->
us[ix][iy] /= wsum;
10658 help->
vs[ix][iy] /= wsum;
10659 help->
ess[ix][iy] /= wsum;
10660 help->
nss[ix][iy] /= wsum;
10661 help->
shf[ix][iy] /= wsum;
10662 help->
lsm[ix][iy] /= wsum;
10663 help->
sst[ix][iy] /= wsum;
10664 help->
pbl[ix][iy] /= wsum;
10665 help->
cape[ix][iy] /= wsum;
10666 help->
cin[ix][iy] /= wsum;
10667 help->
t[ix][iy][ip] /= wsum;
10668 help->
u[ix][iy][ip] /= wsum;
10669 help->
v[ix][iy][ip] /= wsum;
10670 help->
w[ix][iy][ip] /= wsum;
10671 help->
h2o[ix][iy][ip] /= wsum;
10672 help->
o3[ix][iy][ip] /= wsum;
10673 help->
lwc[ix][iy][ip] /= wsum;
10674 help->
rwc[ix][iy][ip] /= wsum;
10675 help->
iwc[ix][iy][ip] /= wsum;
10676 help->
swc[ix][iy][ip] /= wsum;
10677 help->
cc[ix][iy][ip] /= wsum;
10684 for (
int ix = 0; ix < help->
nx; ix += ctl->
met_dx) {
10685 met->
lon[met->
nx] = help->
lon[ix];
10687 for (
int iy = 0; iy < help->
ny; iy += ctl->
met_dy) {
10688 met->
lat[met->
ny] = help->
lat[iy];
10689 met->
ps[met->
nx][met->
ny] = help->
ps[ix][iy];
10690 met->
zs[met->
nx][met->
ny] = help->
zs[ix][iy];
10691 met->
ts[met->
nx][met->
ny] = help->
ts[ix][iy];
10692 met->
us[met->
nx][met->
ny] = help->
us[ix][iy];
10693 met->
vs[met->
nx][met->
ny] = help->
vs[ix][iy];
10694 met->
ess[met->
nx][met->
ny] = help->
ess[ix][iy];
10695 met->
nss[met->
nx][met->
ny] = help->
nss[ix][iy];
10696 met->
shf[met->
nx][met->
ny] = help->
shf[ix][iy];
10697 met->
lsm[met->
nx][met->
ny] = help->
lsm[ix][iy];
10698 met->
sst[met->
nx][met->
ny] = help->
sst[ix][iy];
10699 met->
pbl[met->
nx][met->
ny] = help->
pbl[ix][iy];
10701 met->
cin[met->
nx][met->
ny] = help->
cin[ix][iy];
10703 for (
int ip = 0; ip < help->
np; ip += ctl->
met_dp) {
10704 met->
p[met->
np] = help->
p[ip];
10705 met->
t[met->
nx][met->
ny][met->
np] = help->
t[ix][iy][ip];
10706 met->
u[met->
nx][met->
ny][met->
np] = help->
u[ix][iy][ip];
10707 met->
v[met->
nx][met->
ny][met->
np] = help->
v[ix][iy][ip];
10708 met->
w[met->
nx][met->
ny][met->
np] = help->
w[ix][iy][ip];
10709 met->
h2o[met->
nx][met->
ny][met->
np] = help->
h2o[ix][iy][ip];
10710 met->
o3[met->
nx][met->
ny][met->
np] = help->
o3[ix][iy][ip];
10711 met->
lwc[met->
nx][met->
ny][met->
np] = help->
lwc[ix][iy][ip];
10712 met->
rwc[met->
nx][met->
ny][met->
np] = help->
rwc[ix][iy][ip];
10713 met->
iwc[met->
nx][met->
ny][met->
np] = help->
iwc[ix][iy][ip];
10714 met->
swc[met->
nx][met->
ny][met->
np] = help->
swc[ix][iy][ip];
10715 met->
cc[met->
nx][met->
ny][met->
np] = help->
cc[ix][iy][ip];
10734 double p2[200], pv[
EP], pv2[200], t[
EP], t2[200], th[
EP],
10735 th2[200], z[
EP], z2[200];
10739 LOG(2,
"Calculate tropopause...");
10742#pragma omp parallel for default(shared)
10743 for (
int iz = 0; iz < met->
np; iz++)
10744 z[iz] =
Z(met->
p[iz]);
10745#pragma omp parallel for default(shared)
10746 for (
int iz = 0; iz <= 190; iz++) {
10747 z2[iz] = 4.5 + 0.1 * iz;
10748 p2[iz] =
P(z2[iz]);
10753#pragma omp parallel for default(shared) collapse(2)
10754 for (
int ix = 0; ix < met->
nx; ix++)
10755 for (
int iy = 0; iy < met->
ny; iy++)
10756 met->
pt[ix][iy] = NAN;
10760#pragma omp parallel for default(shared) collapse(2)
10761 for (
int ix = 0; ix < met->
nx; ix++)
10762 for (
int iy = 0; iy < met->
ny; iy++)
10770#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10771 for (
int ix = 0; ix < met->
nx; ix++)
10772 for (
int iy = 0; iy < met->
ny; iy++) {
10775 for (
int iz = 0; iz < met->
np; iz++)
10776 t[iz] = met->
t[ix][iy][iz];
10780 int iz = (int) gsl_stats_min_index(t2, 1, 171);
10781 if (iz > 0 && iz < 170)
10782 met->
pt[ix][iy] = (float) p2[iz];
10784 met->
pt[ix][iy] = NAN;
10792#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10793 for (
int ix = 0; ix < met->
nx; ix++)
10794 for (
int iy = 0; iy < met->
ny; iy++) {
10798 for (iz = 0; iz < met->
np; iz++)
10799 t[iz] = met->
t[ix][iy][iz];
10803 met->
pt[ix][iy] = NAN;
10804 for (iz = 0; iz <= 170; iz++) {
10806 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10807 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10812 if (iz > 0 && iz < 170)
10813 met->
pt[ix][iy] = (float) p2[iz];
10820 met->
pt[ix][iy] = NAN;
10821 for (; iz <= 170; iz++) {
10823 for (
int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
10824 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
10831 for (; iz <= 170; iz++) {
10833 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10834 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10839 if (iz > 0 && iz < 170)
10840 met->
pt[ix][iy] = (float) p2[iz];
10852#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
10853 for (
int ix = 0; ix < met->
nx; ix++)
10854 for (
int iy = 0; iy < met->
ny; iy++) {
10857 for (
int iz = 0; iz < met->
np; iz++)
10858 pv[iz] = met->
pv[ix][iy][iz];
10862 for (
int iz = 0; iz < met->
np; iz++)
10863 th[iz] =
THETA(met->
p[iz], met->
t[ix][iy][iz]);
10867 met->
pt[ix][iy] = NAN;
10868 for (
int iz = 0; iz <= 170; iz++)
10871 if (iz > 0 && iz < 170)
10872 met->
pt[ix][iy] = (float) p2[iz];
10879 ERRMSG(
"Cannot calculate tropopause!");
10882#pragma omp parallel for default(shared) collapse(2)
10883 for (
int ix = 0; ix < met->
nx; ix++)
10884 for (
int iy = 0; iy < met->
ny; iy++) {
10885 double h2ot, tt, zt;
10888 met->
lat[iy], &tt, ci, cw, 1);
10890 met->
lat[iy], &zt, ci, cw, 0);
10892 met->
lat[iy], &h2ot, ci, cw, 0);
10893 met->
tt[ix][iy] = (float) tt;
10894 met->
zt[ix][iy] = (float) zt;
10895 met->
h2ot[ix][iy] = (float) h2ot;
10902 const char *filename,
10912 LOG(1,
"Read observation data: %s", filename);
10916 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
10918 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
10920 ERRMSG(
"Set OBS_TYPE to 0 or 1!");
10923 for (
int i = 1; i < *nobs; i++)
10924 if (rt[i] < rt[i - 1])
10925 ERRMSG(
"Time must be ascending!");
10930 LOG(2,
"Number of observations: %d", *nobs);
10931 gsl_stats_minmax(&mini, &maxi, rt, 1, (
size_t) n);
10932 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
10933 gsl_stats_minmax(&mini, &maxi, rz, 1, (
size_t) n);
10934 LOG(2,
"Altitude range: %g ... %g km", mini, maxi);
10935 gsl_stats_minmax(&mini, &maxi, rlon, 1, (
size_t) n);
10936 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
10937 gsl_stats_minmax(&mini, &maxi, rlat, 1, (
size_t) n);
10938 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
10939 gsl_stats_minmax(&mini, &maxi, robs, 1, (
size_t) n);
10940 LOG(2,
"Observation range: %g ... %g", mini, maxi);
10946 const char *filename,
10956 if (!(in = fopen(filename,
"r")))
10957 ERRMSG(
"Cannot open file!");
10961 while (fgets(line,
LEN, in))
10962 if (sscanf(line,
"%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
10963 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
10964 if ((++(*nobs)) >=
NOBS)
10965 ERRMSG(
"Too many observations!");
10974 const char *filename,
10985 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
10986 ERRMSG(
"Cannot open file!");
10997 NC(nc_close(ncid));
11003 const char *filename,
11006 const char *varname,
11008 const char *defvalue,
11013 char fullname1[
LEN], fullname2[
LEN], rval[
LEN];
11015 int contain = 0, i;
11018 if (filename[strlen(filename) - 1] !=
'-')
11019 if (!(in = fopen(filename,
"r")))
11020 ERRMSG(
"Cannot open file!");
11024 sprintf(fullname1,
"%s[%d]", varname, arridx);
11025 sprintf(fullname2,
"%s[*]", varname);
11027 sprintf(fullname1,
"%s", varname);
11028 sprintf(fullname2,
"%s", varname);
11033 char dummy[
LEN], line[
LEN], rvarname[
LEN];
11034 while (fgets(line,
LEN, in)) {
11035 if (sscanf(line,
"%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
11036 if (strcasecmp(rvarname, fullname1) == 0 ||
11037 strcasecmp(rvarname, fullname2) == 0) {
11043 for (i = 1; i < argc - 1; i++)
11044 if (strcasecmp(argv[i], fullname1) == 0 ||
11045 strcasecmp(argv[i], fullname2) == 0) {
11046 sprintf(rval,
"%s", argv[i + 1]);
11057 if (strlen(defvalue) > 0)
11058 sprintf(rval,
"%s", defvalue);
11060 ERRMSG(
"Missing variable %s!\n", fullname1);
11064 LOG(1,
"%s = %s", fullname1, rval);
11068 sprintf(value,
"%s", rval);
11078 const double rhop) {
11081 const double rp_help = rp * 1e-6;
11084 const double rho =
RHO(p, T);
11087 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
11090 const double v = sqrt(8. *
KB * T / (M_PI * 4.8096e-26));
11093 const double lambda = 2. * eta / (rho * v);
11096 const double K = lambda / rp_help;
11099 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
11102 return 2. *
SQR(rp_help) * (rhop - rho) *
G0 / (9. * eta) * G;
11114 const int method) {
11120 gsl_interp_accel *acc = gsl_interp_accel_alloc();
11121 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (
size_t) n);
11124 gsl_spline_init(s, x, y, (
size_t) n);
11125 for (
int i = 0; i < n2; i++)
11128 else if (x2[i] >= x[n - 1])
11131 y2[i] = gsl_spline_eval(s, x2[i], acc);
11134 gsl_spline_free(s);
11135 gsl_interp_accel_free(acc);
11140 for (
int i = 0; i < n2; i++)
11143 else if (x2[i] >= x[n - 1])
11147 y2[i] =
LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
11161 float mean = 0, var = 0;
11163 for (
int i = 0; i < n; ++i) {
11165 var +=
SQR(data[i]);
11168 var = var / (float) n -
SQR(mean / (
float) n);
11170 return (var > 0 ? sqrtf(var) : 0);
11182 const double remain,
11194 t1.tm_year = year - 1900;
11195 t1.tm_mon = mon - 1;
11201 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
11209 const int output) {
11216 static int iname = -1, igroup = -1, nname, ngroup, ct_name[
NTIMER];
11219 t1 = omp_get_wtime();
11224 rt_name[iname] += dt;
11225 rt_min[iname] = (ct_name[iname] <= 0 ? dt :
MIN(rt_min[iname], dt));
11226 rt_max[iname] = (ct_name[iname] <= 0 ? dt :
MAX(rt_max[iname], dt));
11230 rt_group[igroup] += t1 - t0;
11234 for (
int i = 0; i < nname; i++)
11235 LOG(1,
"TIMER_%s = %.3f s (min= %g s, mean= %g s,"
11236 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
11237 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
11238 for (
int i = 0; i < ngroup; i++)
11239 LOG(1,
"TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
11240 double total = 0.0;
11241 for (
int i = 0; i < nname; i++)
11242 total += rt_name[i];
11243 LOG(1,
"TIMER_TOTAL = %.3f s", total);
11247 for (iname = 0; iname < nname; iname++)
11248 if (strcasecmp(name, names[iname]) == 0)
11250 for (igroup = 0; igroup < ngroup; igroup++)
11251 if (strcasecmp(group, groups[igroup]) == 0)
11255 if (iname >= nname) {
11256 sprintf(names[iname],
"%s", name);
11257 if ((++nname) >=
NTIMER)
11258 ERRMSG(
"Too many timers!");
11262 if (igroup >= ngroup) {
11263 sprintf(groups[igroup],
"%s", group);
11264 if ((++ngroup) >=
NTIMER)
11265 ERRMSG(
"Too many groups!");
11275 const char *filename,
11276 const int offset) {
11283 int len = (int) strlen(filename);
11284 sprintf(tstr,
"%.4s", &filename[len - offset]);
11285 int year = atoi(tstr);
11286 sprintf(tstr,
"%.2s", &filename[len - offset + 5]);
11287 int mon = atoi(tstr);
11288 sprintf(tstr,
"%.2s", &filename[len - offset + 8]);
11289 int day = atoi(tstr);
11290 sprintf(tstr,
"%.2s", &filename[len - offset + 11]);
11291 int hour = atoi(tstr);
11292 sprintf(tstr,
"%.2s", &filename[len - offset + 14]);
11293 int min = atoi(tstr);
11296 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
11297 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
11298 ERRMSG(
"Cannot read time from filename!");
11301 time2jsec(year, mon, day, hour, min, 0, 0.0, &t);
11318 const double p1 = pt * 0.866877899;
11319 const double p0 = pt / 0.866877899;
11322 if (atm->
p[ip] > p0)
11324 else if (atm->
p[ip] < p1)
11327 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
11333 const char *filename,
11341 const double t0 = t - 0.5 * ctl->
dt_mod;
11342 const double t1 = t + 0.5 * ctl->
dt_mod;
11348 if (!(out = popen(
"gnuplot",
"w")))
11349 ERRMSG(
"Cannot create pipe to gnuplot!");
11352 fprintf(out,
"set out \"%s.png\"\n", filename);
11356 int year, mon, day, hour, min, sec;
11357 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11358 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
11359 year, mon, day, hour, min);
11364 ERRMSG(
"Cannot open file!");
11366 while (fgets(line,
LEN, in))
11367 fprintf(out,
"%s", line);
11374 if (!(out = fopen(filename,
"w")))
11375 ERRMSG(
"Cannot create file!");
11380 "# $1 = time [s]\n"
11381 "# $2 = altitude [km]\n"
11382 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
11383 for (
int iq = 0; iq < ctl->
nq; iq++)
11384 fprintf(out,
"# $%i = %s [%s]\n", iq + 5, ctl->
qnt_name[iq],
11386 fprintf(out,
"\n");
11389 for (
int ip = 0; ip < atm->
np; ip += ctl->
atm_stride) {
11396 fprintf(out,
"%.2f %g %g %g", atm->
time[ip],
Z(atm->
p[ip]),
11397 atm->
lon[ip], atm->
lat[ip]);
11398 for (
int iq = 0; iq < ctl->
nq; iq++) {
11403 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
11405 fprintf(out,
"\n");
11415 const char *filename,
11417 const atm_t *atm) {
11422 if (!(out = fopen(filename,
"w")))
11423 ERRMSG(
"Cannot create file!");
11447 for (
int iq = 0; iq < ctl->
nq; iq++)
11465 const char *filename,
11467 const atm_t *atm) {
11469 int tid, pid, ncid, varid;
11470 size_t start[2], count[2];
11473 NC(nc_create(filename, NC_NETCDF4, &ncid));
11476 NC(nc_def_dim(ncid,
"time", 1, &tid));
11477 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11480 int dim_ids[2] = { tid, pid };
11481 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11482 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11483 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
11485 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
11487 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
11490 for (
int iq = 0; iq < ctl->
nq; iq++)
11500 NC(nc_enddef(ncid));
11508 for (
int iq = 0; iq < ctl->
nq; iq++)
11512 NC(nc_close(ncid));
11518 const char *dirname,
11524 static size_t out_cnt = 0;
11526 double r, r_start, r_stop;
11527 int year, mon, day, hour, min, sec;
11528 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
11529 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
11530 char filename_out[2 *
LEN] =
"traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
11532 int ncid, varid, tid, pid, cid;
11540 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11542 &min_start, &sec_start, &r_start);
11544 &min_stop, &sec_stop, &r_stop);
11546 sprintf(filename_out,
11547 "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc", dirname,
11548 year_start % 100, mon_start, day_start, hour_start,
11549 year_stop % 100, mon_stop, day_stop, hour_stop);
11550 LOG(1,
"Write traj file: %s", filename_out);
11553 start[0] = out_cnt;
11556 count[1] = (size_t) atm->
np;
11559 if (out_cnt == 0) {
11562 NC(nc_create(filename_out, NC_NETCDF4, &ncid));
11565 NC(nc_def_dim(ncid,
"time", NC_UNLIMITED, &tid));
11566 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11567 NC(nc_def_dim(ncid,
"TMDT", 7, &cid));
11572 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11573 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11574 NC_DEF_VAR(
"LAT", NC_DOUBLE, 2, dim_ids,
"Latitude",
"deg",
11576 NC_DEF_VAR(
"LON", NC_DOUBLE, 2, dim_ids,
"Longitude",
"deg",
11578 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 2, dim_ids,
"Pressure",
"hPa",
11580 NC_DEF_VAR(
"ZETA", NC_DOUBLE, 2, dim_ids,
"Zeta",
"K",
11582 for (
int iq = 0; iq < ctl->
nq; iq++)
11592 NC(nc_enddef(ncid));
11593 NC(nc_close(ncid));
11600 NC(nc_open(filename_out, NC_WRITE, &ncid));
11612 for (
int iq = 0; iq < ctl->
nq; iq++)
11616 NC(nc_close(ncid));
11619 if ((year == year_stop) && (mon == mon_stop)
11620 && (day == day_stop) && (hour == hour_stop)) {
11623 char filename_init[2 *
LEN] =
"./init_fix_YYYYMMDDHH.nc";
11624 sprintf(filename_init,
"%s/init_fix_%02d%02d%02d%02d.nc",
11625 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
11626 LOG(1,
"Write init file: %s", filename_init);
11629 NC(nc_create(filename_init, NC_NETCDF4, &ncid));
11632 NC(nc_def_dim(ncid,
"time", 1, &tid));
11633 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11638 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11639 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11640 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
11642 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
11644 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
11647 for (
int iq = 0; iq < ctl->
nq; iq++)
11657 NC(nc_enddef(ncid));
11665 for (
int iq = 0; iq < ctl->
nq; iq++)
11669 NC(nc_close(ncid));
11676 const char *filename,
11678 const atm_t *atm) {
11680 int ncid, obsid, varid;
11682 size_t start[2], count[2];
11685 NC(nc_create(filename, NC_NETCDF4, &ncid));
11688 NC(nc_def_dim(ncid,
"obs", (
size_t) atm->
np, &obsid));
11691 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &obsid,
"time",
11692 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11693 NC_DEF_VAR(
"press", NC_DOUBLE, 1, &obsid,
"pressure",
"hPa",
11695 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &obsid,
"longitude",
"degrees_east",
11697 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &obsid,
"latitude",
"degrees_north",
11699 for (
int iq = 0; iq < ctl->
nq; iq++)
11708 NC(nc_enddef(ncid));
11715 for (
int iq = 0; iq < ctl->
nq; iq++)
11719 NC(nc_close(ncid));
11725 const char *filename,
11732 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
11735 static int *obscount, nobs, nk;
11739 const int ensemble = (ctl->
nens > 0);
11745 if (ctl->
qnt_m < 0)
11746 ERRMSG(
"Need quantity mass!");
11749 ERRMSG(
"Missing ensemble IDs!");
11751 ERRMSG(
"Too many ensembles!");
11758 ALLOC(area,
double,
11764 ALLOC(rlon,
double,
11766 ALLOC(rlat,
double,
11768 ALLOC(robs,
double,
11779 LOG(1,
"Write CSI%s data: %s", ensemble ?
" ensemble" :
"", filename);
11780 if (!(out = fopen(filename,
"w")))
11781 ERRMSG(
"Cannot create file!");
11785 "# $1 = time [s]\n"
11786 "# $2 = ensemble ID\n"
11787 "# $3 = number of hits (cx)\n"
11788 "# $4 = number of misses (cy)\n"
11789 "# $5 = number of false alarms (cz)\n"
11790 "# $6 = number of observations (cx + cy)\n"
11791 "# $7 = number of forecasts (cx + cz)\n"
11792 "# $8 = bias (%%)\n"
11793 "# $9 = POD (%%)\n"
11794 "# $10 = FAR (%%)\n"
11795 "# $11 = CSI (%%)\n"
11796 "# $12 = hits by random chance\n"
11797 "# $13 = ETS (%%)\n"
11798 "# $14 = Pearson R\n"
11799 "# $15 = Spearman R\n"
11800 "# $16 = mean error [kg/m²]\n"
11801 "# $17 = RMSE [kg/m²]\n"
11802 "# $18 = MAE [kg/m²]\n"
11803 "# $19 = log-likelihood\n" "# $20 = number of points\n\n");
11811 for (
int iy = 0; iy < ctl->
csi_ny; iy++) {
11812 const double lat = ctl->
csi_lat0 + dlat * (iy + 0.5);
11813 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.0) * cos(
DEG2RAD(lat));
11818 const double t0 = t - 0.5 * ctl->
dt_mod;
11819 const double t1 = t + 0.5 * ctl->
dt_mod;
11823 ALLOC(modmean,
double,
11824 (ensemble ? ctl->
nens : 1) * grid_size);
11825 ALLOC(obsmean,
double,
11827 ALLOC(obscount,
int,
11829 ALLOC(obsstd,
double,
11833 for (
int i = 0; i < (ensemble ? ctl->
nens : 1); i++)
11834 ct[i] = cx[i] = cy[i] = cz[i] = n[i] = 0;
11837 for (
int i = 0; i < nobs; i++) {
11838 if (rt[i] < t0 || rt[i] >= t1 || !isfinite(robs[i]))
11842 const int ix = (int) ((rlon[i] - ctl->
csi_lon0) / dlon);
11843 const int iy = (int) ((rlat[i] - ctl->
csi_lat0) / dlat);
11844 const int iz = (int) ((rz[i] - ctl->
csi_z0) / dz);
11845 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
11851 obsmean[idx] += robs[i];
11852 obsstd[idx] +=
SQR(robs[i]);
11857 for (
int ip = 0; ip < atm->
np; ip++) {
11860 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11864 int ens_id = ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
11865 if (ens_id < 0 || ens_id >= (ensemble ? ctl->
nens : 1))
11866 ERRMSG(
"Ensemble ID out of range!");
11869 const int ix = (int) ((atm->
lon[ip] - ctl->
csi_lon0) / dlon);
11870 const int iy = (int) ((atm->
lat[ip] - ctl->
csi_lat0) / dlat);
11871 const int iz = (int) ((
Z(atm->
p[ip]) - ctl->
csi_z0) / dz);
11872 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
11882 for (
int e = 0; e < (ensemble ? ctl->
nens : 1); e++) {
11884 for (
int ix = 0; ix < ctl->
csi_nx; ix++)
11885 for (
int iy = 0; iy < ctl->
csi_ny; iy++)
11886 for (
int iz = 0; iz < ctl->
csi_nz; iz++) {
11891 if (obscount[idx]) {
11892 obsmean[idx] /= obscount[idx];
11894 sqrt(obsstd[idx] / obscount[idx] -
SQR(obsmean[idx]));
11898 const int midx = e * grid_size + idx;
11899 if (modmean[midx] > 0)
11900 modmean[midx] /= (1e6 * area[iy]);
11903 if (obscount[idx]) {
11918 x[n[e]] = modmean[midx];
11919 y[n[e]] = obsmean[idx];
11921 obsstdn[n[e]] = obsstd[idx];
11922 if ((++n[e]) >=
NCSI)
11923 ERRMSG(
"Too many points for statistics!");
11935 static double work[2 *
NCSI], work2[2 *
NCSI];
11936 const int n_obs = cx[e] + cy[e];
11937 const int n_for = cx[e] + cz[e];
11938 const double cx_rd = (ct[e] > 0) ? (1. * n_obs * n_for) / ct[e] : NAN;
11939 const double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
11940 const double pod = (n_obs > 0) ? 100. * cx[e] / n_obs : NAN;
11941 const double far = (n_for > 0) ? 100. * cz[e] / n_for : NAN;
11943 (cx[e] + cy[e] + cz[e] >
11944 0) ? 100. * cx[e] / (cx[e] + cy[e] + cz[e]) : NAN;
11946 (cx[e] + cy[e] + cz[e] - cx_rd >
11947 0) ? 100. * (cx[e] - cx_rd) / (cx[e] + cy[e] + cz[e] - cx_rd) : NAN;
11948 const double rho_p = gsl_stats_correlation(x, 1, y, 1, (
size_t) n[e]);
11949 const double rho_s =
11950 gsl_stats_spearman(x, 1, y, 1, (
size_t) n[e], work);
11951 for (
int i = 0; i < n[e]; i++) {
11952 work[i] = x[i] - y[i];
11953 work2[i] = (obsstdn[i] != 0) ? work[i] / obsstdn[i] : 0;
11955 const double mean = gsl_stats_mean(work, 1, (
size_t) n[e]);
11956 const double rmse =
11957 gsl_stats_sd_with_fixed_mean(work, 1, (
size_t) n[e], 0.0);
11958 const double absdev = gsl_stats_absdev_m(work, 1, (
size_t) n[e], 0.0);
11959 const double loglikelihood =
11960 gsl_stats_tss_m(work2, 1, (
size_t) n[e], 0.0) * -0.5;
11964 "%.2f %d %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n",
11965 t, ensemble ? e : -999, cx[e], cy[e], cz[e], n_obs, n_for, bias,
11966 pod, far, csi, cx_rd, ets, rho_p, rho_s, mean, rmse, absdev,
11967 loglikelihood, n[e]);
11970 for (
int i = 0; i < n[e]; i++)
11971 work[i] = work2[i] = x[i] = y[i] = obsstdn[i] = 0;
11972 ct[e] = cx[e] = cy[e] = cz[e] = n[e] = 0;
12000 const char *filename,
12010 static int n[
NENS];
12017 ERRMSG(
"Missing ensemble IDs!");
12020 const double t0 = t - 0.5 * ctl->
dt_mod;
12021 const double t1 = t + 0.5 * ctl->
dt_mod;
12024 for (
int i = 0; i <
NENS; i++) {
12025 for (
int iq = 0; iq < ctl->
nq; iq++)
12026 qm[iq][i] = qs[iq][i] = 0;
12027 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
12032 for (
int ip = 0; ip < atm->
np; ip++) {
12035 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
12040 ERRMSG(
"Ensemble ID is out of range!");
12044 for (
int iq = 0; iq < ctl->
nq; iq++) {
12045 qm[iq][ctl->
qnt_ens] += atm->
q[iq][ip];
12056 LOG(1,
"Write ensemble data: %s", filename);
12057 if (!(out = fopen(filename,
"w")))
12058 ERRMSG(
"Cannot create file!");
12062 "# $1 = time [s]\n"
12063 "# $2 = altitude [km]\n"
12064 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
12065 for (
int iq = 0; iq < ctl->
nq; iq++)
12066 fprintf(out,
"# $%d = %s (mean) [%s]\n", 5 + iq,
12068 for (
int iq = 0; iq < ctl->
nq; iq++)
12069 fprintf(out,
"# $%d = %s (sigma) [%s]\n", 5 + ctl->
nq + iq,
12071 fprintf(out,
"# $%d = number of members\n\n", 5 + 2 * ctl->
nq);
12074 for (
int i = 0; i <
NENS; i++)
12076 cart2geo(xm[i], &dummy, &lon, &lat);
12077 fprintf(out,
"%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
12078 for (
int iq = 0; iq < ctl->
nq; iq++) {
12080 fprintf(out, ctl->
qnt_format[iq], qm[iq][i] / n[i]);
12082 for (
int iq = 0; iq < ctl->
nq; iq++) {
12084 double var = qs[iq][i] / n[i] -
SQR(qm[iq][i] / n[i]);
12085 fprintf(out, ctl->
qnt_format[iq], (var > 0 ? sqrt(var) : 0));
12087 fprintf(out,
" %d\n", n[i]);
12097 const char *filename,
12104 static double kz[
EP], kw[
EP];
12108 double *cd, *mean[
NQ], *sigma[
NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
12110 int *ixs, *iys, *izs, *np;
12116 LOG(1,
"Write grid data: %s", filename);
12129 for (
int iq = 0; iq < ctl->
nq; iq++) {
12130 ALLOC(mean[iq],
double,
12132 ALLOC(sigma[iq],
double,
12135 ALLOC(vmr_impl,
double,
12143 ALLOC(area,
double,
12145 ALLOC(press,
double,
12162#pragma omp parallel
for default(shared)
12163 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
12164 z[iz] = ctl->
grid_z0 + dz * (iz + 0.5);
12165 press[iz] =
P(z[iz]);
12169 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12170 lon[ix] = ctl->
grid_lon0 + dlon * (ix + 0.5);
12171#pragma omp parallel for default(shared)
12172 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
12173 lat[iy] = ctl->
grid_lat0 + dlat * (iy + 0.5);
12174 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
12178 const double t0 = t - 0.5 * ctl->
dt_mod;
12179 const double t1 = t + 0.5 * ctl->
dt_mod;
12182#pragma omp parallel for default(shared)
12183 for (
int ip = 0; ip < atm->
np; ip++) {
12184 ixs[ip] = (int) ((atm->
lon[ip] - ctl->
grid_lon0) / dlon);
12185 iys[ip] = (int) ((atm->
lat[ip] - ctl->
grid_lat0) / dlat);
12186 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
grid_z0) / dz);
12187 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
12188 || ixs[ip] < 0 || ixs[ip] >= ctl->
grid_nx
12189 || iys[ip] < 0 || iys[ip] >= ctl->
grid_ny
12190 || izs[ip] < 0 || izs[ip] >= ctl->
grid_nz)
12195 for (
int ip = 0; ip < atm->
np; ip++)
12196 if (izs[ip] >= 0) {
12201 for (
int iq = 0; iq < ctl->
nq; iq++) {
12202 mean[iq][idx] += kernel * atm->
q[iq][ip];
12203 sigma[iq][idx] +=
SQR(kernel * atm->
q[iq][ip]);
12208#pragma omp parallel for default(shared)
12209 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12210 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12211 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
12218 if (ctl->
qnt_m >= 0)
12219 cd[idx] = mean[ctl->
qnt_m][idx] / (1e6 * area[iy]);
12222 vmr_impl[idx] = NAN;
12223 if (ctl->
qnt_m >= 0 && ctl->
molmass > 0 && met0 != NULL
12226 if (mean[ctl->
qnt_m][idx] > 0) {
12232 lon[ix], lat[iy], &temp, ci, cw, 1);
12236 MA / ctl->
molmass * cd[idx] / (
RHO(press[iz], temp) * dz * 1e3);
12242 for (
int iq = 0; iq < ctl->
nq; iq++) {
12243 mean[iq][idx] /= np[idx];
12244 const double var = sigma[iq][idx] / np[idx] -
SQR(mean[iq][idx]);
12245 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
12247 for (
int iq = 0; iq < ctl->
nq; iq++) {
12248 mean[iq][idx] = NAN;
12249 sigma[iq][idx] = NAN;
12256 t, z, lon, lat, area, dz, np);
12261 t, z, lon, lat, area, dz, np);
12265 ERRMSG(
"Grid data format GRID_TYPE unknown!");
12269 for (
int iq = 0; iq < ctl->
nq; iq++) {
12288 const char *filename,
12293 const double *vmr_impl,
12298 const double *area,
12308 if (!(out = popen(
"gnuplot",
"w")))
12309 ERRMSG(
"Cannot create pipe to gnuplot!");
12312 fprintf(out,
"set out \"%s.png\"\n", filename);
12316 int year, mon, day, hour, min, sec;
12317 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
12318 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
12319 year, mon, day, hour, min);
12325 ERRMSG(
"Cannot open file!");
12326 while (fgets(line,
LEN, in))
12327 fprintf(out,
"%s", line);
12334 if (!(out = fopen(filename,
"w")))
12335 ERRMSG(
"Cannot create file!");
12340 "# $1 = time [s]\n"
12341 "# $2 = altitude [km]\n"
12342 "# $3 = longitude [deg]\n"
12343 "# $4 = latitude [deg]\n"
12344 "# $5 = surface area [km^2]\n"
12345 "# $6 = layer depth [km]\n"
12346 "# $7 = column density (implicit) [kg/m^2]\n"
12347 "# $8 = volume mixing ratio (implicit) [ppv]\n"
12348 "# $9 = number of particles [1]\n");
12349 for (
int iq = 0; iq < ctl->
nq; iq++)
12350 fprintf(out,
"# $%i = %s (mean) [%s]\n", 10 + iq, ctl->
qnt_name[iq],
12353 for (
int iq = 0; iq < ctl->
nq; iq++)
12354 fprintf(out,
"# $%i = %s (stddev) [%s]\n", 10 + ctl->
nq + iq,
12356 fprintf(out,
"\n");
12359 for (
int ix = 0; ix < ctl->
grid_nx; ix++) {
12361 fprintf(out,
"\n");
12362 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
12364 fprintf(out,
"\n");
12365 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
12368 fprintf(out,
"%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
12369 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
12370 for (
int iq = 0; iq < ctl->
nq; iq++) {
12372 fprintf(out, ctl->
qnt_format[iq], mean[iq][idx]);
12375 for (
int iq = 0; iq < ctl->
nq; iq++) {
12377 fprintf(out, ctl->
qnt_format[iq], sigma[iq][idx]);
12379 fprintf(out,
"\n");
12392 const char *filename,
12397 const double *vmr_impl,
12402 const double *area,
12406 char longname[2 *
LEN], varname[2 *
LEN];
12410 int *help2, ncid, dimid[10], varid;
12412 size_t start[2], count[2];
12415 ALLOC(help,
double,
12421 NC(nc_create(filename, NC_NETCDF4, &ncid));
12424 NC(nc_def_dim(ncid,
"time", 1, &dimid[0]));
12425 NC(nc_def_dim(ncid,
"z", (
size_t) ctl->
grid_nz, &dimid[1]));
12426 NC(nc_def_dim(ncid,
"lat", (
size_t) ctl->
grid_ny, &dimid[2]));
12427 NC(nc_def_dim(ncid,
"lon", (
size_t) ctl->
grid_nx, &dimid[3]));
12428 NC(nc_def_dim(ncid,
"dz", 1, &dimid[4]));
12431 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &dimid[0],
"time",
12432 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
12433 NC_DEF_VAR(
"z", NC_DOUBLE, 1, &dimid[1],
"altitude",
"km", 0, 0);
12434 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &dimid[2],
"latitude",
"degrees_north", 0,
12436 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &dimid[3],
"longitude",
"degrees_east", 0,
12438 NC_DEF_VAR(
"dz", NC_DOUBLE, 1, &dimid[1],
"layer depth",
"km", 0, 0);
12439 NC_DEF_VAR(
"area", NC_DOUBLE, 1, &dimid[2],
"surface area",
"km**2", 0, 0);
12441 NC_DEF_VAR(
"cd", NC_FLOAT, 4, dimid,
"column density",
"kg m**-2",
12444 "volume mixing ratio (implicit)",
"ppv", ctl->
grid_nc_level, 0);
12445 NC_DEF_VAR(
"np", NC_INT, 4, dimid,
"number of particles",
"1", 0, 0);
12446 for (
int iq = 0; iq < ctl->
nq; iq++) {
12447 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
12448 sprintf(longname,
"%s (mean)", ctl->
qnt_longname[iq]);
12452 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
12453 sprintf(longname,
"%s (stddev)", ctl->
qnt_longname[iq]);
12459 NC(nc_enddef(ncid));
12469 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12470 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12471 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12476 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12477 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12478 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12483 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12484 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12485 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12490 for (
int iq = 0; iq < ctl->
nq; iq++) {
12491 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
12492 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12493 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12494 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12501 for (
int iq = 0; iq < ctl->
nq; iq++) {
12502 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
12503 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12504 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12505 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12512 NC(nc_close(ncid));
12522 const char *filename,
12528 if (!(out = fopen(filename,
"w")))
12529 ERRMSG(
"Cannot create file!");
12619 ERRMSG(
"Number of meteo variables doesn't match!");
12637 const char *varname) {
12646 for (
int ix = 0; ix < met->
nx; ix++)
12647 for (
int iy = 0; iy < met->
ny; iy++)
12648 help[
ARRAY_2D(ix, iy, met->
ny)] = var[ix][iy];
12651 LOG(2,
"Write 2-D variable: %s (uncompressed)", varname);
12653 (
size_t) (met->
nx * met->
ny),
12667 const char *varname,
12668 const int precision,
12669 const double tolerance) {
12678#pragma omp parallel for default(shared) collapse(2)
12679 for (
int ix = 0; ix < met->
nx; ix++)
12680 for (
int iy = 0; iy < met->
ny; iy++)
12681 for (
int ip = 0; ip < met->
np; ip++)
12682 help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)] = var[ix][iy][ip];
12686 LOG(2,
"Write 3-D variable: %s (uncompressed)", varname);
12688 (
size_t) (met->
nx * met->
ny * met->
np),
12695 (
size_t) met->
np, 0, out);
12703 FWRITE(&tolerance,
double,
12707 tolerance, 0, out);
12722 (
size_t) met->
np, met->
p, 0, out);
12732 FWRITE(&tolerance,
double,
12736 tolerance, 0, out);
12742 ERRMSG(
"MET_TYPE not supported!");
12743 LOG(3,
"%d %g", precision, tolerance);
12753 const char *filename,
12759 size_t start[4], count[4];
12760 NC(nc_create(filename, NC_NETCDF4, &ncid));
12763 int tid, lonid, latid, levid;
12764 NC(nc_def_dim(ncid,
"time", 1, &tid));
12765 NC(nc_def_dim(ncid,
"lon", (
size_t) met->
nx, &lonid));
12766 NC(nc_def_dim(ncid,
"lat", (
size_t) met->
ny, &latid));
12767 NC(nc_def_dim(ncid,
"lev", (
size_t) met->
np, &levid));
12770 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"time",
12771 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
12772 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &lonid,
"longitude",
"degrees_east", 0, 0);
12773 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &latid,
"latitude",
"degrees_north", 0, 0);
12774 NC_DEF_VAR(
"lev", NC_DOUBLE, 1, &levid,
"pressure",
"Pa", 0, 0);
12777 int dimid2[2] = { latid, lonid };
12778 NC_DEF_VAR(
"sp", NC_FLOAT, 2, dimid2,
"Surface pressure",
"Pa",
12780 NC_DEF_VAR(
"z", NC_FLOAT, 2, dimid2,
"Geopotential",
"m**2 s**-2",
12782 NC_DEF_VAR(
"t2m", NC_FLOAT, 2, dimid2,
"2 metre temperature",
"K",
12784 NC_DEF_VAR(
"u10m", NC_FLOAT, 2, dimid2,
"10 metre U wind component",
12786 NC_DEF_VAR(
"v10m", NC_FLOAT, 2, dimid2,
"10 metre V wind component",
12789 "Instantaneous eastward turbulent surface stress",
"N m**-2",
12792 "Instantaneous northward turbulent surface stress",
"N m**-2",
12795 "Instantaneous surface sensible heat flux",
"W m**-1",
12797 NC_DEF_VAR(
"lsm", NC_FLOAT, 2, dimid2,
"Land/sea mask",
"-",
12799 NC_DEF_VAR(
"sstk", NC_FLOAT, 2, dimid2,
"Sea surface temperature",
"K",
12801 NC_DEF_VAR(
"blp", NC_FLOAT, 2, dimid2,
"Boundary layer pressure",
"Pa",
12803 NC_DEF_VAR(
"pt", NC_FLOAT, 2, dimid2,
"Tropopause pressure",
"Pa",
12805 NC_DEF_VAR(
"tt", NC_FLOAT, 2, dimid2,
"Tropopause temperature",
"K",
12807 NC_DEF_VAR(
"zt", NC_FLOAT, 2, dimid2,
"Tropopause height",
"m",
12809 NC_DEF_VAR(
"h2ot", NC_FLOAT, 2, dimid2,
"Tropopause water vapor",
"ppv",
12811 NC_DEF_VAR(
"pct", NC_FLOAT, 2, dimid2,
"Cloud top pressure",
"Pa",
12813 NC_DEF_VAR(
"pcb", NC_FLOAT, 2, dimid2,
"Cloud bottom pressure",
"Pa",
12815 NC_DEF_VAR(
"cl", NC_FLOAT, 2, dimid2,
"Total column cloud water",
12818 "Pressure at lifted condensation level (LCL)",
"Pa",
12821 "Pressure at level of free convection (LFC)",
"Pa",
12824 "Pressure at equilibrium level (EL)",
"Pa", ctl->
met_nc_level,
12827 "Convective available potential energy",
"J kg**-1",
12829 NC_DEF_VAR(
"cin", NC_FLOAT, 2, dimid2,
"Convective inhibition",
12831 NC_DEF_VAR(
"o3c", NC_FLOAT, 2, dimid2,
"Total column ozone",
"DU",
12835 int dimid3[3] = { levid, latid, lonid };
12836 NC_DEF_VAR(
"t", NC_FLOAT, 3, dimid3,
"Temperature",
"K",
12838 NC_DEF_VAR(
"u", NC_FLOAT, 3, dimid3,
"U velocity",
"m s**-1",
12840 NC_DEF_VAR(
"v", NC_FLOAT, 3, dimid3,
"V velocity",
"m s**-1",
12842 NC_DEF_VAR(
"w", NC_FLOAT, 3, dimid3,
"Vertical velocity",
"Pa s**-1",
12844 NC_DEF_VAR(
"q", NC_FLOAT, 3, dimid3,
"Specific humidity",
"kg kg**-1",
12846 NC_DEF_VAR(
"o3", NC_FLOAT, 3, dimid3,
"Ozone mass mixing ratio",
12848 NC_DEF_VAR(
"clwc", NC_FLOAT, 3, dimid3,
"Cloud liquid water content",
12850 NC_DEF_VAR(
"crwc", NC_FLOAT, 3, dimid3,
"Cloud rain water content",
12852 NC_DEF_VAR(
"ciwc", NC_FLOAT, 3, dimid3,
"Cloud ice water content",
12854 NC_DEF_VAR(
"cswc", NC_FLOAT, 3, dimid3,
"Cloud snow water content",
12856 NC_DEF_VAR(
"cc", NC_FLOAT, 3, dimid3,
"Cloud cover",
"-",
12860 NC(nc_enddef(ncid));
12867 for (
int ip = 0; ip < met->
np; ip++)
12868 phelp[ip] = 100. * met->
p[ip];
12911 NC(nc_close(ncid));
12918 const char *varname,
12924 size_t start[4], count[4];
12932 for (
int ix = 0; ix < met->
nx; ix++)
12933 for (
int iy = 0; iy < met->
ny; iy++)
12934 help[
ARRAY_2D(iy, ix, met->
nx)] = scl * var[ix][iy];
12947 const char *varname,
12953 size_t start[4], count[4];
12961 for (
int ix = 0; ix < met->
nx; ix++)
12962 for (
int iy = 0; iy < met->
ny; iy++)
12963 for (
int ip = 0; ip < met->
np; ip++)
12964 help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)] = scl * var[ix][iy][ip];
12976 const char *filename,
12985 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
12986 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
12988 static int nobs, *obscount, ip, okay;
12997 if (ctl->
qnt_m < 0)
12998 ERRMSG(
"Need quantity mass!");
13002 ERRMSG(
"Specify molar mass!");
13009 ALLOC(area,
double,
13013 ALLOC(press,
double,
13019 ALLOC(rlon,
double,
13021 ALLOC(rlat,
double,
13023 ALLOC(robs,
double,
13030 LOG(1,
"Write profile data: %s", filename);
13031 if (!(out = fopen(filename,
"w")))
13032 ERRMSG(
"Cannot create file!");
13036 "# $1 = time [s]\n"
13037 "# $2 = altitude [km]\n"
13038 "# $3 = longitude [deg]\n"
13039 "# $4 = latitude [deg]\n"
13040 "# $5 = pressure [hPa]\n"
13041 "# $6 = temperature [K]\n"
13042 "# $7 = volume mixing ratio [ppv]\n"
13043 "# $8 = H2O volume mixing ratio [ppv]\n"
13044 "# $9 = O3 volume mixing ratio [ppv]\n"
13045 "# $10 = observed BT index [K]\n"
13046 "# $11 = number of observations\n");
13054 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
13055 z[iz] = ctl->
prof_z0 + dz * (iz + 0.5);
13056 press[iz] =
P(z[iz]);
13060 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
13061 lon[ix] = ctl->
prof_lon0 + dlon * (ix + 0.5);
13062 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
13063 lat[iy] = ctl->
prof_lat0 + dlat * (iy + 0.5);
13064 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
13069 const double t0 = t - 0.5 * ctl->
dt_mod;
13070 const double t1 = t + 0.5 * ctl->
dt_mod;
13073 ALLOC(mass,
double,
13075 ALLOC(obsmean,
double,
13077 ALLOC(obscount,
int,
13081 for (
int i = 0; i < nobs; i++) {
13086 else if (rt[i] >= t1)
13090 if (!isfinite(robs[i]))
13094 const int ix = (int) ((rlon[i] - ctl->
prof_lon0) / dlon);
13095 const int iy = (int) ((rlat[i] - ctl->
prof_lat0) / dlat);
13098 if (ix < 0 || ix >= ctl->
prof_nx || iy < 0 || iy >= ctl->
prof_ny)
13103 obsmean[idx] += robs[i];
13108 for (ip = 0; ip < atm->
np; ip++) {
13111 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13115 const int ix = (int) ((atm->
lon[ip] - ctl->
prof_lon0) / dlon);
13116 const int iy = (int) ((atm->
lat[ip] - ctl->
prof_lat0) / dlat);
13117 const int iz = (int) ((
Z(atm->
p[ip]) - ctl->
prof_z0) / dz);
13120 if (ix < 0 || ix >= ctl->
prof_nx ||
13126 mass[idx] += atm->
q[ctl->
qnt_m][ip];
13130 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
13131 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
13133 if (obscount[idx2] > 0) {
13137 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
13139 if (mass[idx3] > 0) {
13148 fprintf(out,
"\n");
13151 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
13156 lon[ix], lat[iy], &temp, ci, cw, 1);
13158 lon[ix], lat[iy], &h2o, ci, cw, 0);
13160 lon[ix], lat[iy], &o3, ci, cw, 0);
13165 / (
RHO(press[iz], temp) * area[iy] * dz * 1e9);
13168 fprintf(out,
"%.2f %g %g %g %g %g %g %g %g %g %d\n",
13169 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
13170 obsmean[idx2] / obscount[idx2], obscount[idx2]);
13203 const char *filename,
13212 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[
EP],
13215 static int nobs, nk;
13228 ALLOC(rlon,
double,
13230 ALLOC(rlat,
double,
13232 ALLOC(robs,
double,
13243 LOG(1,
"Write sample data: %s", filename);
13244 if (!(out = fopen(filename,
"w")))
13245 ERRMSG(
"Cannot create file!");
13249 "# $1 = time [s]\n"
13250 "# $2 = altitude [km]\n"
13251 "# $3 = longitude [deg]\n"
13252 "# $4 = latitude [deg]\n"
13253 "# $5 = surface area [km^2]\n"
13254 "# $6 = layer depth [km]\n"
13255 "# $7 = number of particles [1]\n"
13256 "# $8 = column density [kg/m^2]\n"
13257 "# $9 = volume mixing ratio [ppv]\n"
13258 "# $10 = observed BT index [K]\n\n");
13263 area = M_PI * rmax2;
13267 const double t0 = t - 0.5 * ctl->
dt_mod;
13268 const double t1 = t + 0.5 * ctl->
dt_mod;
13271 for (
int i = 0; i < nobs; i++) {
13276 else if (rt[i] >= t1)
13281 geo2cart(0, rlon[i], rlat[i], x0);
13284 const double rp =
P(rz[i]);
13285 const double ptop =
P(rz[i] + ctl->
sample_dz);
13286 const double pbot =
P(rz[i] - ctl->
sample_dz);
13294 for (
int ip = 0; ip < atm->
np; ip++) {
13297 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13301 if (fabs(rlat[i] - atm->
lat[ip]) > dlat)
13307 if (
DIST2(x0, x1) > rmax2)
13312 if (atm->
p[ip] > pbot || atm->
p[ip] < ptop)
13316 if (ctl->
qnt_m >= 0)
13323 const double cd = mass / (1e6 * area);
13334 rlon[i], rlat[i], &temp, ci, cw, 1);
13343 fprintf(out,
"%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
13344 rlon[i], rlat[i], area, ctl->
sample_dz, np, cd, vmr, robs[i]);
13365 const char *filename,
13372 static double rmax2, x0[3], x1[3];
13381 LOG(1,
"Write station data: %s", filename);
13384 if (!(out = fopen(filename,
"w")))
13385 ERRMSG(
"Cannot create file!");
13389 "# $1 = time [s]\n"
13390 "# $2 = altitude [km]\n"
13391 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
13392 for (
int iq = 0; iq < ctl->
nq; iq++)
13393 fprintf(out,
"# $%i = %s [%s]\n", (iq + 5),
13395 fprintf(out,
"\n");
13403 const double t0 = t - 0.5 * ctl->
dt_mod;
13404 const double t1 = t + 0.5 * ctl->
dt_mod;
13407 for (
int ip = 0; ip < atm->
np; ip++) {
13410 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13426 if (
DIST2(x0, x1) > rmax2)
13434 fprintf(out,
"%.2f %g %g %g",
13435 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]);
13436 for (
int iq = 0; iq < ctl->
nq; iq++) {
13438 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
13440 fprintf(out,
"\n");
13451 const char *filename,
13462 LOG(1,
"Write VTK data: %s", filename);
13465 const double t0 = t - 0.5 * ctl->
dt_mod;
13466 const double t1 = t + 0.5 * ctl->
dt_mod;
13469 if (!(out = fopen(filename,
"w")))
13470 ERRMSG(
"Cannot create file!");
13474 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13475 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13482 "# vtk DataFile Version 3.0\n"
13483 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
13486 fprintf(out,
"POINTS %d float\n", np);
13488 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13489 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13493 const double coslat = cos(
DEG2RAD(atm->
lat[ip]));
13494 const double x = radius * coslat * cos(
DEG2RAD(atm->
lon[ip]));
13495 const double y = radius * coslat * sin(
DEG2RAD(atm->
lon[ip]));
13496 const double z = radius * sin(
DEG2RAD(atm->
lat[ip]));
13497 fprintf(out,
"%g %g %g\n", x, y, z);
13500 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13501 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13503 fprintf(out,
"%g %g %g\n", atm->
lon[ip], atm->
lat[ip],
13508 fprintf(out,
"POINT_DATA %d\n", np);
13509 for (
int iq = 0; iq < ctl->
nq; iq++) {
13510 fprintf(out,
"SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
13512 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13513 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13515 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 module_radio_decay(const ctl_t *ctl, const cache_t *cache, atm_t *atm)
Apply radioactive decay to atmospheric tracer species.
void mptrac_get_met(ctl_t *ctl, clim_t *clim, const double t, met_t **met0, met_t **met1, dd_t *dd)
Retrieves meteorological data for the specified time.
void module_sort_help(double *a, const int *p, const int np)
Reorder an array based on a given permutation.
float stddev(const float *data, const int n)
Calculates the standard deviation of a set of data.
void intpol_tropo_3d(const double time0, float array0[EX][EY], const double time1, float array1[EX][EY], const double lons[EX], const double lats[EY], const int nlon, const int nlat, const double time, const double lon, const double lat, const int method, double *var, double *sigma)
Interpolates tropopause data in 3D (latitude, longitude, and time).
void read_met_bin_3d(FILE *in, const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname, const float bound_min, const float bound_max)
Reads 3D meteorological data from a binary file, potentially using different compression methods.
int locate_irr_float(const float *xx, const int n, const double x, const int ig)
Locate the index of the interval containing a given value in an irregularly spaced array.
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 SELECT_TIMER(id, group)
Select and start a timer with specific attributes.
#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 3-D meteorological field using cmultiscale.
#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 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).
int qnt_Acs137
Quantity array index for radioactive activity of Cs-137.
double grid_lon0
Lower longitude of gridded data [deg].
int qnt_o1d
Quantity array index for O(1D) volume mixing ratio (climatology).
int met_tropo_spline
Tropopause interpolation method (0=linear, 1=spline).
char sample_kernel[LEN]
Kernel data file for sample output.
int qnt_tvirt
Quantity array index for virtual temperature.
double dt_met
Time step of meteo data [s].
char clim_ho2_filename[LEN]
Filename of HO2 climatology.
double chemgrid_lat1
Upper latitude of chemistry grid [deg].
int met_geopot_sy
Latitudinal smoothing of geopotential heights.
char grid_gpfile[LEN]
Gnuplot file for gridded data.
double 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 radio_decay
Switch for radioactive decay module (0=off, 1=on).
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.
int qnt_Ai131
Quantity array index for radioactive activity of I-131.
double wet_depo_pre[2]
Coefficients for precipitation calculation.
int met_vert_coord
Vertical coordinate of input meteo data (0=plev, 1=mlev_p_file, 2=mlev_ab_file, 3=mlev_ab_full,...
double csi_z0
Lower altitude of gridded CSI data [km].
int qnt_lapse
Quantity array index for lapse rate.
int qnt_Apb210
Quantity array index for radioactive activity of Pb-210.
double stat_lat
Latitude of station [deg].
int qnt_Cho2
Quantity array index for HO2 volume mixing ratio (chemistry code).
double wet_depo_bc_h[2]
Coefficients for wet deposition below cloud (Henry's law: Hb, Cb).
int grid_ny
Number of latitudes of gridded data.
int qnt_Csf6
Quantity array index for SF6 volume mixing ratio (chemistry code).
int qnt_Ch2o
Quantity array index for H2O volume mixing ratio (chemistry code).
double met_detrend
FWHM of horizontal Gaussian used for detrending [km].
int conv_mix_pbl
Vertical mixing in the PBL (0=off, 1=on).
char metbase[LEN]
Basename for meteo data.
double bound_dps
Boundary conditions surface layer depth [hPa].
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 qnt_Axe133
Quantity array index for radioactive activity of Xe-133.
int chemgrid_nx
Number of longitudes of chemistry grid.
int qnt_pct
Quantity array index for cloud top pressure.
int qnt_mloss_kpp
Quantity array index for total mass loss due to KPP chemistry.
int qnt_psat
Quantity array index for saturation pressure over water.
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.
int qnt_Abe7
Quantity array index for radioactive activity of Be-7.
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_Arn222
Quantity array index for radioactive activity of Rn-222.
int qnt_mloss_h2o2
Quantity array index for total mass loss due to H2O2 chemistry.
double vtk_scale
Vertical scaling factor for VTK data.
char clim_ccl2f2_timeseries[LEN]
Filename of CFC-12 time series.
double 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).