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.), cos_sza_thresh = cos(sza_thresh);
101 const double oh =
clim_zm(&clim->
oh, t, lat, p);
108 const double sza =
sza_calc(t, lon, lat);
109 const double denom = (sza <= sza_thresh) ? cos(sza) : cos_sza_thresh;
120 const double sza_thresh =
DEG2RAD(85.), cos_sza_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) {
136 (sza <= sza_thresh) ? cos(sza) : cos_sza_thresh;
142 clim->
oh.
vmr[it][iz][iy] /= (sum / (double) n);
157 if (p < photo->p[photo->
np - 1])
158 p_help = photo->
p[photo->
np - 1];
159 else if (p > photo->
p[0])
160 p_help = photo->
p[0];
163 double sza_help = sza;
164 if (sza < photo->sza[0])
165 sza_help = photo->
sza[0];
166 else if (sza > photo->
sza[photo->
nsza - 1])
167 sza_help = photo->
sza[photo->
nsza - 1];
170 double o3c_help = o3c;
171 if (o3c < photo->o3c[0])
172 o3c_help = photo->
o3c[0];
173 else if (o3c > photo->
o3c[photo->
no3c - 1])
174 o3c_help = photo->
o3c[photo->
no3c - 1];
182 const double aux00 =
LIN(photo->
p[ip], rate[ip][isza][io3c],
183 photo->
p[ip + 1], rate[ip + 1][isza][io3c],
185 const double aux01 =
LIN(photo->
p[ip], rate[ip][isza][io3c + 1],
186 photo->
p[ip + 1], rate[ip + 1][isza][io3c + 1],
188 const double aux10 =
LIN(photo->
p[ip], rate[ip][isza + 1][io3c],
189 photo->
p[ip + 1], rate[ip + 1][isza + 1][io3c],
191 const double aux11 =
LIN(photo->
p[ip], rate[ip][isza + 1][io3c + 1],
192 photo->
p[ip + 1], rate[ip + 1][isza + 1][io3c + 1],
195 LIN(photo->
o3c[io3c], aux00, photo->
o3c[io3c + 1], aux01, o3c_help);
197 LIN(photo->
o3c[io3c], aux10, photo->
o3c[io3c + 1], aux11, o3c_help);
199 LIN(photo->
sza[isza], aux0, photo->
sza[isza + 1], aux1, sza_help);
200 return MAX(aux, 0.0);
211 double sec =
FMOD(t, 365.25 * 86400.);
213 sec += 365.25 * 86400.;
221 clim->
tropo[isec][ilat],
223 clim->
tropo[isec][ilat + 1], lat);
225 clim->
tropo[isec + 1][ilat],
227 clim->
tropo[isec + 1][ilat + 1], lat);
237 LOG(1,
"Initialize tropopause data...");
241 double tropo_time[12] = {
242 1209600.00, 3888000.00, 6393600.00,
243 9072000.00, 11664000.00, 14342400.00,
244 16934400.00, 19612800.00, 22291200.00,
245 24883200.00, 27561600.00, 30153600.00
251 const double tropo_lat[73] = {
252 -90, -87.5, -85, -82.5, -80, -77.5, -75, -72.5, -70, -67.5,
253 -65, -62.5, -60, -57.5, -55, -52.5, -50, -47.5, -45, -42.5,
254 -40, -37.5, -35, -32.5, -30, -27.5, -25, -22.5, -20, -17.5,
255 -15, -12.5, -10, -7.5, -5, -2.5, 0, 2.5, 5, 7.5, 10, 12.5,
256 15, 17.5, 20, 22.5, 25, 27.5, 30, 32.5, 35, 37.5, 40, 42.5,
257 45, 47.5, 50, 52.5, 55, 57.5, 60, 62.5, 65, 67.5, 70, 72.5,
258 75, 77.5, 80, 82.5, 85, 87.5, 90
263 const double tropo[12][73] = {
264 {324.1, 325.6, 325, 324.3, 322.5, 319.7, 314, 307.2, 301.8, 299.6,
265 297.1, 292.2, 285.6, 276.1, 264, 248.9, 231.9, 213.5, 194.4,
266 175.3, 157, 140.4, 126.7, 116.3, 109.5, 105.4, 103, 101.4, 100.4,
267 99.69, 99.19, 98.84, 98.56, 98.39, 98.39, 98.42, 98.44, 98.54,
268 98.68, 98.81, 98.89, 98.96, 99.12, 99.65, 101.4, 105.4, 113.5, 128,
269 152.1, 184.7, 214, 234.1, 247.3, 255.8, 262.6, 267.7, 271.7, 275,
270 277.2, 279, 280.1, 280.4, 280.6, 280.1, 279.3, 278.3, 276.8, 275.8,
271 275.3, 275.6, 275.4, 274.1, 273.5},
272 {337.3, 338.7, 337.8, 336.4, 333, 328.8, 321.1, 312.6, 306.6, 303.7,
273 300.2, 293.8, 285.4, 273.8, 259.6, 242.7, 224.4, 205.2, 186, 167.5,
274 150.3, 135, 122.8, 113.9, 108.2, 104.7, 102.5, 101.1, 100.2, 99.42,
275 98.88, 98.52, 98.25, 98.09, 98.07, 98.1, 98.12, 98.2, 98.25, 98.27,
276 98.26, 98.27, 98.36, 98.79, 100.2, 104.2, 113.7, 131.2, 159.5, 193,
277 220.4, 238.1, 250.2, 258.1, 264.7, 269.7, 273.7, 277.3, 280.2, 282.8,
278 284.9, 286.5, 288.1, 288.8, 289, 288.5, 287.2, 286.3, 286.1, 287.2,
279 287.5, 286.2, 285.8},
280 {335, 336, 335.7, 335.1, 332.3, 328.1, 320.6, 311.8, 305.1, 301.9,
281 297.6, 290, 280.4, 268.3, 254.6, 239.6, 223.9, 207.9, 192.2, 176.9,
282 161.7, 146.4, 132.2, 120.6, 112.3, 107.2, 104.3, 102.4, 101.3,
283 100.4, 99.86, 99.47, 99.16, 98.97, 98.94, 98.97, 99, 99.09, 99.2,
284 99.31, 99.35, 99.41, 99.51, 99.86, 101.1, 104.9, 114.3, 131, 156.8,
285 186.3, 209.3, 224.6, 236.8, 246.3, 254.9, 262.3, 268.8, 274.8,
286 279.9, 284.6, 288.6, 291.6, 294.9, 297.5, 299.8, 301.8, 303.1,
287 304.3, 304.9, 306, 306.6, 306.2, 306},
288 {306.2, 306.7, 305.7, 307.1, 307.3, 306.4, 301.8, 296.2, 292.4,
289 290.3, 287.1, 280.9, 273.4, 264.3, 254.1, 242.8, 231, 219, 207.2,
290 195.5, 183.3, 169.7, 154.7, 138.7, 124.1, 113.6, 107.8, 104.7,
291 102.8, 101.7, 100.9, 100.4, 100, 99.79, 99.7, 99.66, 99.68, 99.79,
292 99.94, 100.2, 100.5, 100.9, 101.4, 102.1, 103.4, 107, 115.2, 129.1,
293 148.7, 171, 190.8, 205.6, 218.4, 229.4, 239.6, 248.6, 256.5,
294 263.7, 270.3, 276.6, 282.6, 288.1, 294.5, 300.4, 306.3, 311.4,
295 315.1, 318.3, 320.3, 322.2, 322.8, 321.5, 321.1},
296 {266.5, 264.9, 260.8, 261, 262, 263, 261.3, 259.7, 259.2, 259.8,
297 260.1, 258.6, 256.7, 253.6, 249.5, 243.9, 237.4, 230, 222.1, 213.9,
298 205, 194.4, 180.4, 161.8, 140.7, 122.9, 112.1, 106.7, 104.1, 102.7,
299 101.8, 101.4, 101.1, 101, 101, 101, 101.1, 101.2, 101.5, 101.9,
300 102.4, 103, 103.8, 104.9, 106.8, 110.1, 115.6, 124, 135.2, 148.9,
301 165.2, 181.3, 198, 211.8, 223.5, 233.8, 242.9, 251.5, 259, 266.2,
302 273.1, 279.2, 286.2, 292.8, 299.6, 306, 311.1, 315.5, 318.8, 322.6,
303 325.3, 325.8, 325.8},
304 {220.1, 218.1, 210.8, 207.2, 207.6, 210.5, 211.4, 213.5, 217.3,
305 222.4, 227.9, 232.8, 237.4, 240.8, 242.8, 243, 241.5, 238.6, 234.2,
306 228.5, 221, 210.7, 195.1, 172.9, 147.8, 127.6, 115.6, 109.9, 107.1,
307 105.7, 105, 104.8, 104.8, 104.9, 105, 105.1, 105.3, 105.5, 105.8,
308 106.4, 107, 107.6, 108.1, 108.8, 110, 111.8, 114.2, 117.4, 121.6,
309 127.9, 137.3, 151.2, 169.5, 189, 205.8, 218.9, 229.1, 237.8, 245,
310 251.5, 257.1, 262.3, 268.2, 274, 280.4, 286.7, 292.4, 297.9, 302.9,
311 308.5, 312.2, 313.1, 313.3},
312 {187.4, 184.5, 173.3, 166.1, 165.4, 167.8, 169.6, 173.6, 179.6,
313 187.9, 198.9, 210, 220.5, 229.2, 235.7, 239.9, 241.8, 241.6, 239.6,
314 235.8, 229.4, 218.6, 200.9, 175.9, 149.4, 129.4, 118.3, 113.1,
315 110.8, 109.7, 109.3, 109.4, 109.7, 110, 110.2, 110.4, 110.5, 110.7,
316 111, 111.4, 111.8, 112.1, 112.3, 112.7, 113.2, 113.9, 115, 116.4,
317 117.9, 120.4, 124.1, 130.9, 142.2, 159.6, 179.6, 198.5, 212.9,
318 224.2, 232.7, 239.1, 243.8, 247.7, 252.4, 257.3, 263.2, 269.5,
319 275.4, 281.1, 286.3, 292, 296.3, 298.2, 298.8},
320 {166, 166.4, 155.7, 148.3, 147.1, 149, 152.1, 157, 163.6, 172.4,
321 185.3, 199.2, 212.6, 224, 233.2, 239.6, 243.3, 244.6, 243.6, 240.3,
322 233.9, 222.6, 203.7, 177, 149.5, 129.7, 119, 114, 111.7, 110.7,
323 110.3, 110.3, 110.6, 110.9, 111.1, 111.3, 111.5, 111.6, 111.9,
324 112.2, 112.5, 112.6, 112.8, 113, 113.4, 114, 115.1, 116.5, 118.3,
325 120.9, 124.4, 130.2, 139.4, 154.6, 173.8, 193.1, 208.1, 220.4,
326 230.1, 238.2, 244.7, 249.5, 254.5, 259.3, 264.5, 269.4, 273.7,
327 278.2, 282.6, 287.4, 290.9, 292.5, 293},
328 {171.9, 172.8, 166.2, 162.3, 161.4, 162.5, 165.2, 169.6, 175.3,
329 183.1, 193.8, 205.9, 218.3, 229.6, 238.5, 244.3, 246.9, 246.7,
330 243.8, 238.4, 230.2, 217.9, 199.6, 174.9, 148.9, 129.8, 119.5,
331 114.8, 112.3, 110.9, 110.3, 110.1, 110.2, 110.3, 110.4, 110.5,
332 110.6, 110.8, 111, 111.4, 111.8, 112, 112.2, 112.4, 112.9, 113.6,
333 114.7, 116.3, 118.4, 121.9, 127.1, 136.1, 149.8, 168.4, 186.9,
334 203.3, 217, 229.1, 238.7, 247, 254, 259.3, 264.3, 268.3, 272.5,
335 276.6, 280.4, 284.4, 288.4, 293.3, 297.2, 298.7, 299.1},
336 {191.6, 192.2, 189, 188.1, 190.2, 193.7, 197.8, 202.9, 208.5,
337 215.6, 224.2, 233.1, 241.2, 247.3, 250.8, 251.3, 248.9, 244.2,
338 237.3, 228.4, 217.2, 202.9, 184.5, 162.5, 140.7, 124.8, 116.2,
339 111.8, 109.4, 107.9, 107, 106.7, 106.6, 106.6, 106.7, 106.7,
340 106.8, 107, 107.4, 108, 108.7, 109.3, 109.8, 110.4, 111.2,
341 112.4, 114.2, 116.9, 121.1, 127.9, 139.3, 155.2, 173.6, 190.7,
342 206.1, 220.1, 232.3, 243, 251.8, 259.2, 265.7, 270.6, 275.3,
343 279.3, 283.3, 286.9, 289.7, 292.8, 296.1, 300.5, 303.9, 304.8,
345 {241.5, 239.6, 236.8, 237.4, 239.4, 242.3, 244.2, 246.4, 249.2,
346 253.6, 258.6, 262.7, 264.8, 264.2, 260.6, 254.1, 245.5, 235.3,
347 223.9, 211.7, 198.3, 183.1, 165.6, 147.1, 130.5, 118.7, 111.9,
348 108.1, 105.8, 104.3, 103.4, 102.8, 102.5, 102.4, 102.5, 102.5,
349 102.5, 102.7, 103.1, 103.8, 104.6, 105.4, 106.1, 107, 108.2,
350 109.9, 112.8, 117.5, 126, 140.4, 161, 181.9, 201.2, 216.8, 230.4,
351 241.8, 251.4, 259.9, 266.9, 272.8, 277.4, 280.4, 282.9, 284.6,
352 286.1, 287.4, 288.3, 289.5, 290.9, 294.2, 296.9, 297.5, 297.6},
353 {301.2, 300.3, 296.6, 295.4, 295, 294.3, 291.2, 287.4, 284.9, 284.7,
354 284.1, 281.5, 277.1, 270.4, 261.7, 250.6, 237.6, 223.1, 207.9, 192,
355 175.8, 158.8, 142.1, 127.6, 116.8, 109.9, 106, 103.6, 102.1, 101.1,
356 100.4, 99.96, 99.6, 99.37, 99.32, 99.32, 99.31, 99.46, 99.77, 100.2,
357 100.7, 101.3, 101.8, 102.7, 104.1, 106.8, 111.9, 121, 136.7, 160,
358 186.9, 209.9, 228.1, 241.2, 251.5, 259.5, 265.7, 270.9, 274.8, 278,
359 280.3, 281.8, 283, 283.3, 283.7, 283.8, 283, 282.2, 281.2, 281.4,
362 memcpy(clim->
tropo, tropo,
sizeof(clim->
tropo));
365 double tropomin = 1e99, tropomax = -1e99;
367 for (
int iy = 0; iy < clim->
tropo_nlat; iy++) {
368 tropomin =
MIN(tropomin, clim->
tropo[it][iy]);
369 tropomax =
MAX(tropomax, clim->
tropo[it][iy]);
374 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
378 LOG(2,
"Latitudes: %g, %g ... %g deg",
381 LOG(2,
"Tropopause altitude range: %g ... %g hPa",
Z(tropomax),
383 LOG(2,
"Tropopause pressure range: %g ... %g hPa", tropomin, tropomax);
393 if (t <= ts->time[0])
400 ts->
time[idx + 1], ts->
vmr[idx + 1], t);
413 double sec =
FMOD(t, 365.25 * 86400.);
415 sec += 365.25 * 86400.;
419 if (p < zm->p[zm->
np - 1])
420 p_help = zm->
p[zm->
np - 1];
421 else if (p > zm->
p[0])
425 double lat_help = lat;
426 if (lat < zm->lat[0])
427 lat_help = zm->
lat[0];
428 else if (lat > zm->
lat[zm->
nlat - 1])
429 lat_help = zm->
lat[zm->
nlat - 1];
437 const double aux00 =
LIN(zm->
p[ip], zm->
vmr[isec][ip][ilat],
438 zm->
p[ip + 1], zm->
vmr[isec][ip + 1][ilat],
440 const double aux01 =
LIN(zm->
p[ip], zm->
vmr[isec][ip][ilat + 1],
441 zm->
p[ip + 1], zm->
vmr[isec][ip + 1][ilat + 1],
443 const double aux10 =
LIN(zm->
p[ip], zm->
vmr[isec + 1][ip][ilat],
444 zm->
p[ip + 1], zm->
vmr[isec + 1][ip + 1][ilat],
446 const double aux11 =
LIN(zm->
p[ip], zm->
vmr[isec + 1][ip][ilat + 1],
447 zm->
p[ip + 1], zm->
vmr[isec + 1][ip + 1][ilat + 1],
450 LIN(zm->
lat[ilat], aux00, zm->
lat[ilat + 1], aux01, lat_help);
452 LIN(zm->
lat[ilat], aux10, zm->
lat[ilat + 1], aux11, lat_help);
453 const double aux =
LIN(zm->
time[isec], aux0, zm->
time[isec + 1], aux1, sec);
454 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]";
480 const int Nd0_x = 48;
481 const int Nd0_y = 24;
482 const int max_level_grid = 6;
483 cms_param_t *cms_param
484 = cms_set_parameters(nx, ny, max_level_grid, Nd0_x, Nd0_y, domain);
487 double cr = 0, t_coars = 0, t_eval = 0;
493 for (
size_t ip = 0; ip < np; ip++) {
496 cms_module_t *cms_ptr = cms_init(cms_param);
501 cms_sol = cms_read_zstd_sol(cms_ptr, inout);
503 cms_sol = cms_read_sol(cms_ptr, inout);
506#pragma omp parallel for collapse(2) default(shared)
507 for (
size_t ix = 0; ix < nx; ix++)
508 for (
size_t iy = 0; iy < ny; iy++) {
510 const double x[] = { lon[ix], lat[iy] };
511 cms_eval(cms_ptr, cms_sol, x, &val);
512 array[
ARRAY_3D(ix, iy, ny, ip, np)] = (float) val;
516 cr += cms_compression_rate(cms_ptr, cms_sol) / (double) np;
519 cms_delete_sol(cms_sol);
520 cms_delete_module(cms_ptr);
524 LOG(2,
"Read 3-D variable: %s (CMS, RATIO= %g)", varname, cr);
531 cms_module_t *cms_ptr[
EP];
532 cms_sol_t *cms_sol[
EP];
536 ? (size_t) omp_get_max_threads()
538 for (
size_t ip0 = 0; ip0 < np; ip0 += dip) {
541 double t0 = omp_get_wtime();
544#pragma omp parallel for default(shared)
545 for (
size_t ip = ip0; ip <
MIN(ip0 + dip, np); ip++) {
549 ALLOC(tmp_arr,
float,
553 for (
size_t ix = 0; ix < nx; ++ix)
554 for (
size_t iy = 0; iy < ny; ++iy)
556 array[
ARRAY_3D(ix, iy, ny, ip, np)];
559 double c_thresh_test;
560 if (strcasecmp(varname,
"Z") == 0)
562 else if (strcasecmp(varname,
"T") == 0)
564 else if (strcasecmp(varname,
"U") == 0)
566 else if (strcasecmp(varname,
"V") == 0)
568 else if (strcasecmp(varname,
"W") == 0)
570 else if (strcasecmp(varname,
"PV") == 0)
572 else if (strcasecmp(varname,
"H2O") == 0)
574 else if (strcasecmp(varname,
"O3") == 0)
576 else if (strcasecmp(varname,
"LWC") == 0)
578 else if (strcasecmp(varname,
"RWC") == 0)
580 else if (strcasecmp(varname,
"IWC") == 0)
582 else if (strcasecmp(varname,
"SWC") == 0)
584 else if (strcasecmp(varname,
"CC") == 0)
587 ERRMSG(
"Variable name unknown!");
590 cms_ptr[ip] = cms_init(cms_param);
594 cms_read_arr_new(cms_ptr[ip], tmp_arr, lon, lat,
595 nx, ny, c_thresh_test);
602 t_coars += (omp_get_wtime() - t0);
605 for (
size_t ip = ip0; ip <
MIN(ip0 + dip, np); ip++) {
608 double *tmp_cms, *tmp_org, *tmp_diff;
609 ALLOC(tmp_cms,
double,
611 ALLOC(tmp_org,
double,
613 ALLOC(tmp_diff,
double,
617 t0 = omp_get_wtime();
620#pragma omp parallel for collapse(2) default(shared)
621 for (
size_t ix = 0; ix < nx; ix++)
622 for (
size_t iy = 0; iy < ny; iy++) {
623 const size_t idx =
ARRAY_2D(ix, iy, ny);
624 const double x[] = { lon[ix], lat[iy] };
625 cms_eval(cms_ptr[ip], cms_sol[ip], x, &tmp_cms[idx]);
626 tmp_org[idx] = array[
ARRAY_3D(ix, iy, ny, ip, np)];
627 tmp_diff[idx] = tmp_cms[idx] - tmp_org[idx];
631 t_eval += (omp_get_wtime() - t0);
635 "cmultiscale: var= %s / lev= %lu / ratio= %g / rho= %g"
636 " / mean= %g / sd= %g / min= %g / max= %g", varname, ip,
637 cms_compression_rate(cms_ptr[ip], cms_sol[ip]),
638 gsl_stats_correlation(tmp_cms, 1, tmp_org, 1, nxy),
639 gsl_stats_mean(tmp_diff, 1, nxy), gsl_stats_sd(tmp_diff, 1, nxy),
640 gsl_stats_min(tmp_diff, 1, nxy), gsl_stats_max(tmp_diff, 1, nxy));
643 cr += cms_compression_rate(cms_ptr[ip], cms_sol[ip]) / (double) np;
647 cms_save_zstd_sol(cms_sol[ip], inout, 3);
649 cms_save_sol(cms_sol[ip], inout);
652 cms_delete_sol(cms_sol[ip]);
653 cms_delete_module(cms_ptr[ip]);
661 LOG(2,
"Write 3-D variable: %s"
662 " (CMS, RATIO= %g, T_COARS= %g s, T_EVAL= %g s)",
663 varname, cr, t_coars, t_eval);
667 cms_delete_param(cms_param);
678 const int decompress,
681 double min[
EP], max[
EP], off[
EP], scl[
EP];
683 unsigned short *sarray;
686 ALLOC(sarray,
unsigned short,
693 LOG(2,
"Read 3-D variable: %s (pck, RATIO= %g)",
694 varname, (
double)
sizeof(
float) / (
double)
sizeof(
unsigned short));
703 FREAD(sarray,
unsigned short,
708#pragma omp parallel for default(shared)
709 for (
size_t ixy = 0; ixy < nxy; ixy++)
710 for (
size_t iz = 0; iz < nz; iz++)
712 = (
float) (sarray[ixy * nz + iz] * scl[iz] + off[iz]);
719 LOG(2,
"Write 3-D variable: %s (pck, RATIO= %g)",
720 varname, (
double)
sizeof(
float) / (
double)
sizeof(
unsigned short));
723 for (
size_t iz = 0; iz < nz; iz++) {
727 for (
size_t ixy = 1; ixy < nxy; ixy++)
728 for (
size_t iz = 0; iz < nz; iz++) {
729 if (array[ixy * nz + iz] < min[iz])
730 min[iz] = array[ixy * nz + iz];
731 if (array[ixy * nz + iz] > max[iz])
732 max[iz] = array[ixy * nz + iz];
736 for (
size_t iz = 0; iz < nz; iz++) {
737 scl[iz] = (max[iz] - min[iz]) / 65533.;
742#pragma omp parallel for default(shared)
743 for (
size_t ixy = 0; ixy < nxy; ixy++)
744 for (
size_t iz = 0; iz < nz; iz++)
746 sarray[ixy * nz + iz] = (
unsigned short)
747 ((array[ixy * nz + iz] - off[iz]) / scl[iz] + .5);
749 sarray[ixy * nz + iz] = 0;
758 FWRITE(sarray,
unsigned short,
780 if ((precision > 0) == (tolerance > 0.0))
781 ERRMSG(
"Exactly one of precision or tolerance must be set for SZ3!");
783 size_t r1 = (size_t) nx, r2 = (
size_t) ny, r3 = (size_t) nz,
784 outSize = 0, total_elems = r1 * r2 * r3;
786 unsigned char *bytes = NULL;
792 FREAD(&sz3size,
size_t,
797 FREAD(bytes,
unsigned char,
801 void *outData = SZ_decompress(SZ_FLOAT, bytes, sz3size, 0, 0, r3, r2, r1);
803 ERRMSG(
"Decompression failed!");
805 memcpy(array, outData, total_elems *
sizeof(
float));
810 LOG(2,
"Read 3-D variable: %s (SZ3, PREC=%d, TOL=%g, RATIO=%g)",
811 varname, precision, tolerance,
812 (
double) (total_elems *
sizeof(
float)) / (
double) sz3size);
818 const int errBoundMode = (precision > 0) ? REL : ABS;
819 const double absBound = (errBoundMode == ABS) ? tolerance : 0.0;
820 const double relBound =
821 (errBoundMode == REL) ? pow(2.0, -(
double) precision) : 0.0;
823 bytes = SZ_compress_args(SZ_FLOAT, array, &outSize,
824 errBoundMode, absBound, relBound, 0.0,
826 if (!bytes || outSize == 0)
827 ERRMSG(
"Compression failed!");
832 FWRITE(bytes,
unsigned char,
838 LOG(2,
"Write 3-D variable: %s (SZ3, PREC=%d, TOL=%g, RATIO=%g)",
839 varname, precision, tolerance,
840 (
double) (total_elems *
sizeof(
float)) / (
double) outSize);
855 const double tolerance,
856 const int decompress,
860 const size_t snx = (size_t) nx;
861 const size_t sny = (size_t) ny;
862 const size_t snz = (size_t) nz;
863 const zfp_type type = zfp_type_float;
864 zfp_field *field = zfp_field_3d(array, type, snx, sny, snz);
867 zfp_stream *zfp = zfp_stream_open(NULL);
869 ERRMSG(
"Failed to allocate zfp structures!");
873 double actual_tol = 0;
874 if ((precision > 0 && tolerance > 0) || (precision <= 0 && tolerance <= 0)) {
875 ERRMSG(
"Exactly one of precision or tolerance must be set for zfp!");
876 }
else if (precision > 0)
878 (int) zfp_stream_set_precision(zfp, (
unsigned int) precision);
879 else if (tolerance > 0)
880 actual_tol = zfp_stream_set_accuracy(zfp, tolerance);
883 const size_t bufsize = zfp_stream_maximum_size(zfp, field);
889 bitstream *stream = stream_open(buffer, bufsize);
890 zfp_stream_set_bit_stream(zfp, stream);
891 zfp_stream_rewind(zfp);
896 FREAD(&zfpsize,
size_t,
899 if (zfpsize > bufsize)
900 ERRMSG(
"Compressed data size exceeds allocated buffer!");
901 FREAD(buffer,
unsigned char,
904 if (!zfp_decompress(zfp, field)) {
905 ERRMSG(
"Decompression failed!");
908 ((double) (snx * sny * snz *
sizeof(
float))) / (double) zfpsize;
909 const double bpv = (8.0 * (double) zfpsize) / (double) (snx * sny * snz);
911 "Read 3-D variable: %s (ZFP, PREC= %d, TOL= %g, RATIO= %g, BPV= %g)",
912 varname, actual_prec, actual_tol, cr, bpv);
917 zfpsize = zfp_compress(zfp, field);
919 ERRMSG(
"Compression failed!");
924 FWRITE(buffer,
unsigned char,
929 ((double) (snx * sny * snz *
sizeof(
float))) / (double) zfpsize;
930 const double bpv = (8.0 * (double) zfpsize) / (double) (snx * sny * snz);
932 "Write 3-D variable: %s (ZFP, PREC= %d, TOL= %g, RATIO= %g, BPV= %g)",
933 varname, actual_prec, actual_tol, cr, bpv);
937 zfp_field_free(field);
938 stream_close(stream);
939 zfp_stream_close(zfp);
951 const int decompress,
956 const size_t uncomprLen = n *
sizeof(float);
957 size_t compsize, comprLen = ZSTD_compressBound(uncomprLen);
960 char *compr = calloc(comprLen, 1);
962 ERRMSG(
"Memory allocation failed!");
963 char *uncompr = (
char *) array;
967 FREAD(&comprLen,
size_t,
970 FREAD(compr,
unsigned char,
973 compsize = ZSTD_decompress(uncompr, uncomprLen, compr, comprLen);
974 if (ZSTD_isError(compsize) || compsize != uncomprLen)
975 ERRMSG(
"Decompression failed or size mismatch!");
976 LOG(2,
"Read 3-D variable: %s (ZSTD, RATIO= %g)",
977 varname, ((
double) uncomprLen) / (
double) comprLen);
982 compsize = ZSTD_compress(compr, comprLen, uncompr, uncomprLen, level);
983 if (ZSTD_isError(compsize)) {
984 ERRMSG(
"Compression failed!");
989 FWRITE(compr,
unsigned char,
993 LOG(2,
"Write 3-D variable: %s (ZSTD, RATIO= %g)",
994 varname, ((
double) uncomprLen) / (
double) compsize);
1011 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
1012 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
1015 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
1016 *doy = d0l[mon - 1] + day - 1;
1018 *doy = d0[mon - 1] + day - 1;
1030 SELECT_TIMER(
"DD_ASSIGN_RECT_SUBDOMAINS",
"DD", NVTX_GPU);
1034#pragma acc enter data create(dd)
1035#pragma acc update device(dd->rank, dd->subdomain_lon_min, dd->subdomain_lon_max, dd->subdomain_lat_min, dd->subdomain_lat_max)
1036#pragma acc data present(atm, ctl, dd)
1037#pragma acc parallel loop independent gang vector
1039 for (
int ip = 0; ip < atm->
np; ip++) {
1041 double lont = atm->
lon[ip];
1053 (
"DD: Particle is outside the domain (lon: %f, lat: %f, subdomain: %d, subdomain bounds: [%f, %f], [%f, %f])",
1062#pragma acc exit data delete(dd)
1068#pragma acc enter data create(dd)
1069#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)
1070#pragma acc data present(atm, ctl, dd)
1071#pragma acc parallel loop independent gang vector
1073 for (
int ip = 0; ip < atm->
np; ip++) {
1079 double lont = atm->
lon[ip];
1080 double latt = atm->
lat[ip];
1095 bound = (lont - lon_max > 90) ? 1 : 0;
1097 bound = (lon_min - lont > 90) ? 1 : 0;
1100 if ((lont >= lon_max) && (latt >= lat_max)) {
1104 "DD: Particle crossing to upper right: from rank %d to rank %d (lon: %f, lat: %f)",
1106 }
else if ((lont >= lon_max) && (latt <= lat_min)) {
1110 "DD: Particle crossing to lower right: from rank %d to rank %d (lon: %f, lat: %f)",
1112 }
else if ((lont <= lon_min) && (latt >= lat_max)) {
1116 "DD: Particle crossing to upper left: from rank %d to rank %d (lon: %f, lat: %f)",
1118 }
else if ((lont <= lon_min) && (latt <= lat_min)) {
1122 "DD: Particle crossing to lower left: from rank %d to rank %d (lon: %f, lat: %f)",
1124 }
else if (lont >= lon_max) {
1128 "DD: Particle crossing to right: from rank %d to rank %d (lon: %f, lat: %f)",
1130 }
else if (lont <= lon_min) {
1134 "DD: Particle crossing to left: from rank %d to rank %d (lon: %f, lat: %f)",
1136 }
else if (latt <= lat_min) {
1140 "DD: Particle crossing downward: from rank %d to rank %d (lon: %f, lat: %f)",
1142 }
else if (latt >= lat_max) {
1146 "DD: Particle crossing upward: from rank %d to rank %d (lon: %f, lat: %f)",
1153 if ((lont >= lon_max) && (latt >= lat_max)) {
1157 "DD: Particle crossing to upper left (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1159 }
else if ((lont >= lon_max) && (latt <= lat_min)) {
1163 "DD: Particle crossing to lower left (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1165 }
else if ((lont <= lon_min) && (latt >= lat_max)) {
1169 "DD: Particle crossing to upper right (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1171 }
else if ((lont <= lon_min) && (latt <= lat_min)) {
1175 "DD: Particle crossing to lower right (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1177 }
else if (lont >= lon_max) {
1181 "DD: Particle crossing to left (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1183 }
else if (lont <= lon_min) {
1187 "DD: Particle crossing to right (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1189 }
else if (latt <= lat_min) {
1193 "DD: Particle crossing downward (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1195 }
else if (latt >= lat_max) {
1199 "DD: Particle crossing upward (bound case): from rank %d to rank %d (lon: %f, lat: %f)",
1228#pragma acc exit data delete(dd)
1249 int npart = *nparticles;
1250#pragma acc enter data create( nparticles, particles[:DD_NPART])
1251#pragma acc update device( nparticles)
1252#pragma acc parallel loop present( atm, ctl, particles, cache, nparticles)
1254 for (
int ip = atm->
np; ip < atm->np + *nparticles; ip++)
1259 particles[ip - atm->
np].
time = atm->
time[ip];
1260 particles[ip - atm->
np].
lon = atm->
lon[ip];
1261 particles[ip - atm->
np].
lat = atm->
lat[ip];
1262 particles[ip - atm->
np].
p = atm->
p[ip];
1264 for (
int iq = 0; iq < ctl->
nq; iq++)
1265 particles[ip - atm->
np].q[iq] = atm->
q[iq][ip];
1268 "DD: Particle being prepared for transfer: subdomain %d -> destination %d (lon: %f, lat: %f)",
1275#pragma acc update host( particles[:npart])
1276#pragma acc exit data delete( nparticles, particles)
1294 double wrapped_lon = lon;
1295 while (wrapped_lon < 0)
1297 while (wrapped_lon >= 360)
1301 double wrapped_lat = lat;
1304 wrapped_lat = 180 - lat;
1305 wrapped_lon = fmod(wrapped_lon + 180, 360);
1306 }
else if (lat < -90) {
1308 wrapped_lat = -180 - lat;
1309 wrapped_lon = fmod(wrapped_lon + 180, 360);
1314 double lon_range = 360.0;
1325 LOG(2,
"nx_glob: %d", nx_glob);
1327 double lat_range = met->
lat[ny_glob - 1] - met->
lat[0];
1328 double global_lon_min = met->
lon[0];
1329 double global_lat_min = met->
lat[0];
1333 (int) ((wrapped_lon -
1336 (int) ((wrapped_lat -
1341 (
"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",
1342 lon, lat, wrapped_lon, wrapped_lat, lon_range, lat_range, global_lon_min,
1343 global_lat_min, lon_idx, lat_idx);
1348 0) ? 0 : ((lon_idx >=
1353 0) ? 0 : ((lat_idx >=
1362 if (target_rank >= mpi_size)
1363 target_rank = mpi_size - 1;
1364 if (target_rank < 0)
1394 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
1397 MPI_Request *requests_snd_nbr =
1398 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1399 MPI_Request *requests_rcv_nbr =
1400 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1401 MPI_Request *requests_snd_part =
1402 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1403 MPI_Request *requests_rcv_part =
1404 (MPI_Request *) calloc((
size_t) nneighbours,
sizeof(MPI_Request));
1405 MPI_Status *states =
1406 (MPI_Status *) calloc((
size_t) nneighbours,
sizeof(MPI_Status));
1409 for (
int i = 0; i < nneighbours; i++) {
1410 requests_snd_nbr[i] = MPI_REQUEST_NULL;
1411 requests_rcv_nbr[i] = MPI_REQUEST_NULL;
1412 requests_snd_part[i] = MPI_REQUEST_NULL;
1413 requests_rcv_part[i] = MPI_REQUEST_NULL;
1417 for (
int idest = 0; idest < nneighbours; idest++) {
1420 if (neighbours[idest] < 0)
1426 for (
int ip = 0; ip < *nparticles; ip++)
1429 nbs[idest] = help_sum;
1432 LOG(3,
"DD: Rank %d sending %d particles to neighbour %d (rank %d)",
1433 rank, help_sum, idest, neighbours[idest]);
1438 MPI_Isend(&nbs[idest], 1, MPI_INT,
1439 neighbours[idest], 0, MPI_COMM_WORLD, &requests_snd_nbr[idest]);
1442 if (nbs[idest] == 0)
1451 for (
int ip = 0; ip < *nparticles; ip++) {
1452 if ((
int) particles[ip].q[ctl.
qnt_destination] == neighbours[idest]) {
1453 memcpy(&send_buffers[idest][ibs], &particles[ip],
sizeof(
particle_t));
1457 if (ibs == nbs[idest])
1464 MPI_Isend(send_buffers[idest], nbs[idest], MPI_Particle,
1465 neighbours[idest], 1, MPI_COMM_WORLD,
1466 &requests_snd_part[idest]);
1472 for (
int isourc = 0; isourc < nneighbours; isourc++) {
1475 if (neighbours[isourc] < 0) {
1476 requests_rcv_nbr[isourc] = MPI_REQUEST_NULL;
1481 MPI_Irecv(&nbr[isourc], 1, MPI_INT, neighbours[isourc], 0, MPI_COMM_WORLD,
1482 &requests_rcv_nbr[isourc]);
1486 MPI_Waitall(nneighbours, requests_rcv_nbr, states);
1489 for (
int isourc = 0; isourc < nneighbours; isourc++) {
1492 if ((neighbours[isourc] < 0) || (nbr[isourc] == 0)) {
1493 requests_rcv_part[isourc] = MPI_REQUEST_NULL;
1501 MPI_Irecv(recieve_buffers[isourc], nbr[isourc], MPI_Particle,
1502 neighbours[isourc], 1, MPI_COMM_WORLD,
1503 &requests_rcv_part[isourc]);
1507 MPI_Waitall(nneighbours, requests_rcv_part, states);
1515 for (
int isourc = 0; isourc < nneighbours; isourc++) {
1518 if (neighbours[isourc] < 0)
1521 if (nbr[isourc] > 0) {
1522 LOG(3,
"DD: Rank %d receiving %d particles from neighbour %d (rank %d)",
1523 rank, nbr[isourc], isourc, neighbours[isourc]);
1527 for (
int ip = 0; ip < nbr[isourc]; ip++) {
1528 memcpy(&particles[ip + api], &recieve_buffers[isourc][ip],
1542 MPI_Waitall(nneighbours, requests_snd_part, states);
1543 MPI_Waitall(nneighbours, requests_snd_nbr, states);
1546 for (
int i = 0; i < nneighbours; i++) {
1548 if ((send_buffers[i] != NULL) && (nbs[i] != 0)) {
1549 free(send_buffers[i]);
1550 send_buffers[i] = NULL;
1553 if ((recieve_buffers[i] != NULL) && (nbr[i] != 0)) {
1554 free(recieve_buffers[i]);
1555 recieve_buffers[i] = NULL;
1572 const int rank = dd->
rank;
1573 const int size = dd->
size;
1577 nb[0] = (size + rank - m) % size;
1578 nb[3] = (rank + m) % size;
1579 nb[1] = ((rank + 1) % m == 0) ?
DD_SPOLE : (size + rank - m + 1) % size;
1580 nb[2] = (rank % m == 0) ?
DD_NPOLE : (size + rank - m - 1) % size;
1581 nb[4] = ((rank + 1) % m == 0) ?
DD_SPOLE : (rank + m + 1) % size;
1582 nb[5] = (rank % m == 0) ?
DD_NPOLE : (rank + m - 1) % size;
1583 nb[6] = (rank % m == 0) ?
DD_NPOLE : rank - 1;
1584 nb[7] = ((rank + 1) % m == 0) ?
DD_SPOLE : rank + 1;
1600 double lon_spacing = met->
lon[1] - met->
lon[0];
1604 double total_range = met->
lon[nx_glob - 1] - met->
lon[0] + lon_spacing;
1607 return (fabs(total_range - 360.0) < 0.01);
1621 ERRMSG(
"The number of tasks and subdomains is not identical.");
1652 int npart = *nparticles;
1653#pragma acc enter data create(nparticles, particles[:DD_NPART])
1654#pragma acc update device(particles[:npart], nparticles)
1655#pragma acc data present(atm, ctl, cache, particles, nparticles)
1656#pragma acc parallel loop
1658 for (
int ip = atm->
np; ip < atm->np + *nparticles; ip++) {
1659 atm->
time[ip] = particles[ip - atm->
np].
time;
1660 atm->
lon[ip] = particles[ip - atm->
np].
lon;
1661 atm->
lat[ip] = particles[ip - atm->
np].
lat;
1662 atm->
p[ip] = particles[ip - atm->
np].
p;
1663 for (
int iq = 0; iq < ctl->
nq; iq++)
1664 atm->
q[iq][ip] = particles[ip - atm->
np].q[iq];
1668#pragma acc exit data delete(nparticles, particles)
1672 atm->
np += *nparticles;
1674#pragma acc update device(atm->np)
1677 ERRMSG(
"Number of particles to high. Increase NP!");
1686 MPI_Datatype types[5] = { MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE,
1687 MPI_DOUBLE, MPI_DOUBLE
1689 int blocklengths[5] = { 1, 1, 1, 1,
NQ };
1690 MPI_Aint displacements[5] = { offsetof(
particle_t, time),
1696 MPI_Type_create_struct(5, blocklengths, displacements, types, MPI_Particle);
1697 MPI_Type_commit(MPI_Particle);
1716 const int np = atm->
np;
1717 double amax = (met0->
nx * met0->
ny + met0->
ny) * met0->
np + met0->
np;
1719#pragma acc enter data create(amax, rank)
1720#pragma acc update device(rank, amax)
1721#pragma acc data present(ctl,met0,atm,dd,amax,rank)
1726#pragma acc parallel loop independent gang vector
1728#pragma omp parallel for default(shared)
1730 for (
int ip = 0; ip < np; ip++) {
1738 dd->a[ip] = amax + 1;
1740 dd->a[ip] = amax + 2;
1748#pragma acc host_data use_device(dd->a,dd->p)
1750 thrustSortWrapper(dd->a, np, dd->p);
1753 ERRMSG(
"GSL sort fallback not available on GPU, use THRUST!");
1755 gsl_sort_index((
size_t *) (dd->p), (dd->a), 1, (
size_t) np);
1763 for (
int iq = 0; iq < ctl->
nq; iq++)
1769#pragma acc parallel loop reduction(+:npt) present(atm, rank, ctl)
1771 for (
int ip = 0; ip < np; ip++)
1777 int nparticlest = 0;
1779#pragma acc parallel loop reduction(+:nparticlest) present(atm, rank, ctl)
1781 for (
int ip = npt; ip < np; ip++)
1787 *nparticles = nparticlest;
1791 for (
int ip = 0; ip < np; ip++)
1797 (
"DD: Rank %d: %d particles have subdomain index -1 and will be lost (kept: %d, to_send: %d, total_before: %d)",
1798 *rank, nlost, npt, nparticlest, np);
1803#pragma acc update device(atm->np)
1808 (
"Number of particles to send and recieve to small. Increase DD_NPART!");
1812#pragma acc exit data delete(amax, rank)
1827#pragma acc data present(dd,a)
1828#pragma acc parallel loop independent gang vector
1830#pragma omp parallel for default(shared)
1832 for (
int ip = 0; ip < np; ip++)
1833 dd->help[ip] = a[dd->p[ip]];
1835#pragma acc parallel loop independent gang vector
1837#pragma omp parallel
for default(shared)
1839 for (
int ip = 0; ip < np; ip++)
1840 a[ip] = dd->help[ip];
1853 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
1854 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
1859 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
1860 for (i = 11; i > 0; i--)
1864 *day = doy - d0l[i] + 1;
1866 for (i = 11; i > 0; i--)
1870 *day = doy - d0[i] + 1;
1881 double data[2 *
EX];
1885 ERRMSG(
"Too many data points!");
1888 gsl_fft_complex_wavetable *wavetable =
1889 gsl_fft_complex_wavetable_alloc((
size_t) n);
1890 gsl_fft_complex_workspace *workspace =
1891 gsl_fft_complex_workspace_alloc((
size_t) n);
1894 for (
int i = 0; i < n; i++) {
1895 data[2 * i] = fcReal[i];
1896 data[2 * i + 1] = fcImag[i];
1900 gsl_fft_complex_forward(data, 1, (
size_t) n, wavetable, workspace);
1903 for (
int i = 0; i < n; i++) {
1904 fcReal[i] = data[2 * i];
1905 fcImag[i] = data[2 * i + 1];
1909 gsl_fft_complex_wavetable_free(wavetable);
1910 gsl_fft_complex_workspace_free(workspace);
1921 const double radius = z +
RE;
1922 const double latrad =
DEG2RAD(lat);
1923 const double lonrad =
DEG2RAD(lon);
1924 const double coslat = cos(latrad);
1926 x[0] = radius * coslat * cos(lonrad);
1927 x[1] = radius * coslat * sin(lonrad);
1928 x[2] = radius * sin(latrad);
1937 const char *metbase,
1938 const double dt_met,
1945 int year, mon, day, hour, min, sec;
1949 t6 = floor(t / dt_met) * dt_met;
1951 t6 = ceil(t / dt_met) * dt_met;
1954 jsec2time(t6, &year, &mon, &day, &hour, &min, &sec, &r);
1959 sprintf(filename,
"%s_YYYY_MM_DD_HH.nc", metbase);
1961 sprintf(filename,
"%s_YYYY_MM_DD_HH.bin", metbase);
1963 sprintf(filename,
"%s_YYYY_MM_DD_HH.pck", metbase);
1965 sprintf(filename,
"%s_YYYY_MM_DD_HH.zfp", metbase);
1967 sprintf(filename,
"%s_YYYY_MM_DD_HH.zstd", metbase);
1969 sprintf(filename,
"%s_YYYY_MM_DD_HH.cms", metbase);
1971 sprintf(filename,
"%s_YYYY_MM_DD_HH.sz3", metbase);
1972 sprintf(repl,
"%d", year);
1974 sprintf(repl,
"%02d", mon);
1976 sprintf(repl,
"%02d", day);
1978 sprintf(repl,
"%02d", hour);
1984 sprintf(filename,
"%s_YYMMDDHH.nc", metbase);
1985 sprintf(repl,
"%d", year);
1987 sprintf(repl,
"%02d", year % 100);
1989 sprintf(repl,
"%02d", mon);
1991 sprintf(repl,
"%02d", day);
1993 sprintf(repl,
"%02d", hour);
2008 for (
int i = 0; i < 3; i++) {
2012 if (!(ch = strstr(orig, search)))
2014 strncpy(buffer, orig, (
size_t) (ch - orig));
2015 buffer[ch - orig] = 0;
2016 sprintf(buffer + (ch - orig),
"%s%s", repl, ch + strlen(search));
2018 strcpy(orig, buffer);
2025 const int met_tropo,
2045#pragma omp parallel for default(shared) private(ci,cw)
2046 for (
int ix = 0; ix < nx; ix++)
2047 for (
int iy = 0; iy < ny; iy++) {
2049 &pt[iy * nx + ix], ci, cw, 1);
2051 &ps[iy * nx + ix], ci, cw, 0);
2053 &zs[iy * nx + ix], ci, cw, 0);
2055 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
2057 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
2059 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
2061 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
2078 *lon2 =
FMOD(lon, 360.);
2079 if (*lon2 < lons[0])
2081 else if (*lon2 > lons[nlon - 1])
2086 if (lats[0] < lats[nlat - 1])
2087 *lat2 =
MIN(
MAX(*lat2, lats[0]), lats[nlat - 1]);
2089 *lat2 =
MIN(
MAX(*lat2, lats[nlat - 1]), lats[0]);
2096 float heights0[
EX][
EY][
EP],
2097 float array0[
EX][
EY][
EP],
2099 float heights1[
EX][
EY][
EP],
2100 float array1[
EX][
EY][
EP],
2102 const double height,
2128 int k_max = ind[0][0];
2129 for (
int i = 0; i < 2; i++)
2130 for (
int j = 0; j < 4; j++) {
2131 if (ci[2] > ind[i][j])
2133 if (k_max < ind[i][j])
2139 cw[0] = (lon2 - met0->
lon[ci[0]]) /
2140 (met0->
lon[ci[0] + 1] - met0->
lon[ci[0]]);
2141 cw[1] = (lat2 - met0->
lat[ci[1]]) /
2142 (met0->
lat[ci[1] + 1] - met0->
lat[ci[1]]);
2145 double height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2]]
2146 - heights0[ci[0]][ci[1]][ci[2]])
2147 + heights0[ci[0]][ci[1]][ci[2]];
2148 double height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2]]
2149 - heights0[ci[0]][ci[1] + 1][ci[2]])
2150 + heights0[ci[0]][ci[1] + 1][ci[2]];
2151 double height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2]]
2152 - heights0[ci[0] + 1][ci[1]][ci[2]])
2153 + heights0[ci[0] + 1][ci[1]][ci[2]];
2154 double height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2]]
2155 - heights0[ci[0] + 1][ci[1] + 1][ci[2]])
2156 + heights0[ci[0] + 1][ci[1] + 1][ci[2]];
2159 double height0 = cw[1] * (height01 - height00) + height00;
2160 double height1 = cw[1] * (height11 - height10) + height10;
2163 double height_bot = cw[0] * (height1 - height0) + height0;
2166 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
2167 - heights0[ci[0]][ci[1]][ci[2] + 1])
2168 + heights0[ci[0]][ci[1]][ci[2] + 1];
2169 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
2170 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
2171 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
2172 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
2173 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
2174 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
2175 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2176 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2177 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2180 height0 = cw[1] * (height01 - height00) + height00;
2181 height1 = cw[1] * (height11 - height10) + height10;
2184 double height_top = cw[0] * (height1 - height0) + height0;
2187 while (((heights0[0][0][0] > heights0[0][0][1]) &&
2188 ((height_bot <= height) || (height_top > height))
2189 && (height_bot >= height) && (ci[2] < k_max))
2191 ((heights0[0][0][0] < heights0[0][0][1]) &&
2192 ((height_bot >= height) || (height_top < height))
2193 && (height_bot <= height) && (ci[2] < k_max))
2197 height_bot = height_top;
2200 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
2201 - heights0[ci[0]][ci[1]][ci[2] + 1])
2202 + heights0[ci[0]][ci[1]][ci[2] + 1];
2203 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
2204 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
2205 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
2206 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
2207 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
2208 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
2209 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2210 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2211 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2214 height0 = cw[1] * (height01 - height00) + height00;
2215 height1 = cw[1] * (height11 - height10) + height10;
2218 height_top = cw[0] * (height1 - height0) + height0;
2222 cw[2] = (height - height_bot)
2223 / (height_top - height_bot);
2227 const double array000 = cw[3] * (array1[ci[0]][ci[1]][ci[2]]
2228 - array0[ci[0]][ci[1]][ci[2]])
2229 + array0[ci[0]][ci[1]][ci[2]];
2230 const double array100 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2]]
2231 - array0[ci[0] + 1][ci[1]][ci[2]])
2232 + array0[ci[0] + 1][ci[1]][ci[2]];
2233 const double array010 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2]]
2234 - array0[ci[0]][ci[1] + 1][ci[2]])
2235 + array0[ci[0]][ci[1] + 1][ci[2]];
2236 const double array110 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2]]
2237 - array0[ci[0] + 1][ci[1] + 1][ci[2]])
2238 + array0[ci[0] + 1][ci[1] + 1][ci[2]];
2239 const double array001 = cw[3] * (array1[ci[0]][ci[1]][ci[2] + 1]
2240 - array0[ci[0]][ci[1]][ci[2] + 1])
2241 + array0[ci[0]][ci[1]][ci[2] + 1];
2242 const double array101 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2] + 1]
2243 - array0[ci[0] + 1][ci[1]][ci[2] + 1])
2244 + array0[ci[0] + 1][ci[1]][ci[2] + 1];
2245 const double array011 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2] + 1]
2246 - array0[ci[0]][ci[1] + 1][ci[2] + 1])
2247 + array0[ci[0]][ci[1] + 1][ci[2] + 1];
2248 const double array111 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2249 - array0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2250 + array0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2252 const double array00 = cw[0] * (array100 - array000) + array000;
2253 const double array10 = cw[0] * (array110 - array010) + array010;
2254 const double array01 = cw[0] * (array101 - array001) + array001;
2255 const double array11 = cw[0] * (array111 - array011) + array011;
2257 const double aux0 = cw[1] * (array10 - array00) + array00;
2258 const double aux1 = cw[1] * (array11 - array01) + array01;
2261 *var = cw[2] * (aux1 - aux0) + aux0;
2291 cw[0] = (met->
p[ci[0] + 1] - p)
2292 / (met->
p[ci[0] + 1] - met->
p[ci[0]]);
2293 cw[1] = (met->
lon[ci[1] + 1] - lon2)
2294 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
2295 cw[2] = (met->
lat[ci[2] + 1] - lat2)
2296 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
2300 const double aux00 =
2301 cw[0] * (array[ci[1]][ci[2]][ci[0]] - array[ci[1]][ci[2]][ci[0] + 1])
2302 + array[ci[1]][ci[2]][ci[0] + 1];
2303 const double aux01 =
2304 cw[0] * (array[ci[1]][ci[2] + 1][ci[0]] -
2305 array[ci[1]][ci[2] + 1][ci[0] + 1])
2306 + array[ci[1]][ci[2] + 1][ci[0] + 1];
2307 const double aux10 =
2308 cw[0] * (array[ci[1] + 1][ci[2]][ci[0]] -
2309 array[ci[1] + 1][ci[2]][ci[0] + 1])
2310 + array[ci[1] + 1][ci[2]][ci[0] + 1];
2311 const double aux11 =
2312 cw[0] * (array[ci[1] + 1][ci[2] + 1][ci[0]] -
2313 array[ci[1] + 1][ci[2] + 1][ci[0] + 1])
2314 + array[ci[1] + 1][ci[2] + 1][ci[0] + 1];
2317 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
2318 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
2319 *var = cw[1] * (aux0 - aux1) + aux1;
2326 float array[
EX][
EY],
2347 cw[1] = (met->
lon[ci[1] + 1] - lon2)
2348 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
2349 cw[2] = (met->
lat[ci[2] + 1] - lat2)
2350 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
2354 const double aux00 = array[ci[1]][ci[2]];
2355 const double aux01 = array[ci[1]][ci[2] + 1];
2356 const double aux10 = array[ci[1] + 1][ci[2]];
2357 const double aux11 = array[ci[1] + 1][ci[2] + 1];
2360 if (isfinite(aux00) && isfinite(aux01)
2361 && isfinite(aux10) && isfinite(aux11)) {
2362 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
2363 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
2364 *var = cw[1] * (aux0 - aux1) + aux1;
2384 float array0[
EX][
EY][
EP],
2386 float array1[
EX][
EY][
EP],
2403 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
2406 *var = wt * (var0 - var1) + var1;
2413 float array0[
EX][
EY],
2415 float array1[
EX][
EY],
2431 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
2434 if (isfinite(var0) && isfinite(var1))
2435 *var = wt * (var0 - var1) + var1;
2446 float array0[
EX][
EY],
2448 float array1[
EX][
EY],
2449 const double lons[
EX],
2450 const double lats[
EY],
2469 const int ix =
locate_reg(lons, (
int) nlon, lon2);
2470 const int iy =
locate_irr(lats, (
int) nlat, lat2);
2474 for (
int dx = 0; dx < 2; dx++)
2475 for (
int dy = 0; dy < 2; dy++) {
2476 if (isfinite(array0[ix + dx][iy + dy])) {
2477 mean += array0[ix + dx][iy + dy];
2478 *sigma +=
SQR(array0[ix + dx][iy + dy]);
2481 if (isfinite(array1[ix + dx][iy + dy])) {
2482 mean += array1[ix + dx][iy + dy];
2483 *sigma +=
SQR(array1[ix + dx][iy + dy]);
2488 *sigma = sqrt(
MAX(*sigma / n -
SQR(mean / n), 0.0));
2491 if (method == 1 && isfinite(array0[ix][iy])
2492 && isfinite(array0[ix][iy + 1])
2493 && isfinite(array0[ix + 1][iy])
2494 && isfinite(array0[ix + 1][iy + 1])
2495 && isfinite(array1[ix][iy])
2496 && isfinite(array1[ix][iy + 1])
2497 && isfinite(array1[ix + 1][iy])
2498 && isfinite(array1[ix + 1][iy + 1])) {
2500 const double aux00 =
LIN(lons[ix], array0[ix][iy],
2501 lons[ix + 1], array0[ix + 1][iy], lon2);
2502 const double aux01 =
LIN(lons[ix], array0[ix][iy + 1],
2503 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
2504 const double aux0 =
LIN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
2506 const double aux10 =
LIN(lons[ix], array1[ix][iy],
2507 lons[ix + 1], array1[ix + 1][iy], lon2);
2508 const double aux11 =
LIN(lons[ix], array1[ix][iy + 1],
2509 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
2510 const double aux1 =
LIN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
2512 *var =
LIN(time0, aux0, time1, aux1, time);
2517 const double aux00 =
NN(lons[ix], array0[ix][iy],
2518 lons[ix + 1], array0[ix + 1][iy], lon2);
2519 const double aux01 =
NN(lons[ix], array0[ix][iy + 1],
2520 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
2521 const double aux0 =
NN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
2523 const double aux10 =
NN(lons[ix], array1[ix][iy],
2524 lons[ix + 1], array1[ix + 1][iy], lon2);
2525 const double aux11 =
NN(lons[ix], array1[ix][iy + 1],
2526 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
2527 const double aux1 =
NN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
2529 *var =
NN(time0, aux0, time1, aux1, time);
2554 const time_t jsec0 = (time_t) jsec + timegm(&t0);
2555 t1 = gmtime(&jsec0);
2557 *year = t1->tm_year + 1900;
2558 *mon = t1->tm_mon + 1;
2560 *hour = t1->tm_hour;
2563 *remain = jsec - floor(jsec);
2569 const double kz[
EP],
2570 const double kw[
EP],
2579 const double z =
Z(p);
2584 else if (z > kz[nk - 1])
2588 return LIN(kz[idx], kw[idx], kz[idx + 1], kw[idx + 1], z);
2605 const double a =
RA *
SQR(t), r =
SH(h2o) / (1. -
SH(h2o));
2619 const double press[138] = {
2620 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
2621 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
2622 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
2623 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
2624 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2625 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
2626 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
2627 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
2628 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
2629 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
2630 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
2631 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
2632 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
2633 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
2634 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
2635 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
2636 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
2637 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
2638 1010.8487, 1013.2500, 1044.45
2641 for (
int ip = 0; ip < ctl->
met_np; ip++)
2648 const double press[92] = {
2649 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
2650 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
2651 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
2652 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
2653 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
2655 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
2656 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
2657 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
2658 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
2659 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
2660 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
2661 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
2662 1007.4431, 1010.8487, 1013.2500, 1044.45
2665 for (
int ip = 0; ip < ctl->
met_np; ip++)
2672 const double press[60] = {
2673 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
2674 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
2675 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
2676 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
2677 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
2678 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
2679 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
2680 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1044.45
2683 for (
int ip = 0; ip < ctl->
met_np; ip++)
2690 const double press[147] = {
2691 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
2692 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
2693 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
2694 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
2695 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2696 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
2697 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
2698 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
2699 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
2700 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
2701 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
2702 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
2703 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
2704 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
2705 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
2706 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
2707 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
2708 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
2709 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73, 1028.85,
2711 1035.09, 1038.21, 1041.33, 1044.45
2714 for (
int ip = 0; ip < ctl->
met_np; ip++)
2721 const double press[101] = {
2722 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
2723 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
2724 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
2725 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
2726 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
2728 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
2729 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
2730 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
2731 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
2732 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
2733 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
2734 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
2735 1007.4431, 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73,
2737 1035.09, 1038.21, 1041.33, 1044.45
2740 for (
int ip = 0; ip < ctl->
met_np; ip++)
2747 const double press[62] = {
2748 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
2749 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
2750 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
2751 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
2752 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
2753 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
2754 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
2755 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1034.86, 1039.65,
2759 for (
int ip = 0; ip < ctl->
met_np; ip++)
2766 const double press[137] = {
2767 0.01, 0.02, 0.031, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861,
2768 0.2499, 0.3299, 0.4288, 0.5496, 0.6952, 0.869, 1.0742,
2769 1.3143, 1.5928, 1.9134, 2.2797, 2.6954, 3.1642, 3.6898,
2770 4.2759, 4.9262, 5.6441, 6.4334, 7.2974, 8.2397, 9.2634,
2771 10.372, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945, 18.9752,
2772 20.761, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2773 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.199, 54.5299,
2774 57.9834, 61.5607, 65.2695, 69.1187, 73.1187, 77.281, 81.6182,
2775 86.145, 90.8774, 95.828, 101.005, 106.415, 112.068, 117.971,
2776 124.134, 130.564, 137.27, 144.262, 151.549, 159.14, 167.045,
2777 175.273, 183.834, 192.739, 201.997, 211.619, 221.615, 231.995,
2778 242.772, 253.955, 265.556, 277.585, 290.055, 302.976, 316.361,
2779 330.22, 344.566, 359.411, 374.767, 390.645, 407.058, 424.019,
2780 441.539, 459.632, 478.31, 497.584, 517.42, 537.72, 558.343,
2781 579.193, 600.167, 621.162, 642.076, 662.808, 683.262, 703.347,
2782 722.979, 742.086, 760.6, 778.466, 795.64, 812.085, 827.776,
2783 842.696, 856.838, 870.2, 882.791, 894.622, 905.712, 916.081,
2784 925.757, 934.767, 943.14, 950.908, 958.104, 965.299, 972.495,
2785 979.69, 986.886, 994.081, 1001.28, 1008.47, 1015.67, 1022.86,
2786 1030.06, 1037.25, 1044.45
2789 for (
int ip = 0; ip < ctl->
met_np; ip++)
2796 const double press[59] = {
2797 0.1, 0.2, 0.3843, 0.6365, 0.9564, 1.3448, 1.8058, 2.3478,
2798 2.985, 3.7397, 4.6462, 5.7565, 7.1322, 8.8366, 10.9483,
2799 13.5647, 16.8064, 20.8227, 25.7989, 31.9642, 39.6029, 49.0671,
2800 60.1802, 73.0663, 87.7274, 104.229, 122.614, 142.902, 165.089,
2801 189.147, 215.025, 242.652, 272.059, 303.217, 336.044, 370.407,
2802 406.133, 443.009, 480.791, 519.209, 557.973, 596.777, 635.306,
2803 673.24, 710.263, 746.063, 780.346, 812.83, 843.263, 871.42,
2804 897.112, 920.189, 940.551, 958.148, 975.744, 993.341, 1010.94,
2808 for (
int ip = 0; ip < ctl->
met_np; ip++)
2812 ERRMSG(
"Use 0 for l137, 1 for l91, 2 for l60 or values between 3 and 7.");
2816 ERRMSG(
"Recompile with larger EP to use this pressure level definition.");
2829 int i = (ihi + ilo) >> 1;
2831 if (xx[i] < xx[i + 1])
2832 while (ihi > ilo + 1) {
2833 i = (ihi + ilo) >> 1;
2839 while (ihi > ilo + 1) {
2840 i = (ihi + ilo) >> 1;
2860 int i = (ihi + ilo) >> 1;
2862 if ((xx[ig] <= x && x < xx[ig + 1]) || (xx[ig] >= x && x > xx[ig + 1]))
2865 if (xx[i] < xx[i + 1])
2866 while (ihi > ilo + 1) {
2867 i = (ihi + ilo) >> 1;
2873 while (ihi > ilo + 1) {
2874 i = (ihi + ilo) >> 1;
2892 const int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
2906 float profiles[
EX][
EY][
EP],
2908 const int lon_ap_ind,
2909 const int lat_ap_ind,
2910 const double height_ap,
2916 np, height_ap, ind[0]);
2918 np, height_ap, ind[1]);
2920 np, height_ap, ind[2]);
2939 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2943 double dts, u[4], um = 0, v[4], vm = 0, w[4], wm = 0,
2947 for (
int i = 0; i < ctl->
advect; i++) {
2952 x[0] = atm->
lon[ip];
2953 x[1] = atm->
lat[ip];
2956 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
2957 x[0] = atm->
lon[ip] +
DX2DEG(dts * u[i - 1] / 1000., atm->
lat[ip]);
2958 x[1] = atm->
lat[ip] +
DY2DEG(dts * v[i - 1] / 1000.);
2959 x[2] = atm->
p[ip] + dts * w[i - 1];
2961 const double tm = atm->
time[ip] + dts;
2966 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2968 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2970 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
2976 met1, met1->
pl, met1->
ul,
2977 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2979 met1, met1->
pl, met1->
vl,
2980 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2982 met1, met1->
pl, met1->
wl,
2983 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
2989 k = (i == 0 ? 0.0 : 1.0);
2990 else if (ctl->
advect == 4)
2991 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2998 atm->
time[ip] += cache->
dt[ip];
2999 atm->
lon[ip] +=
DX2DEG(cache->
dt[ip] * um / 1000.,
3000 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
3001 atm->
lat[ip] +=
DY2DEG(cache->
dt[ip] * vm / 1000.);
3002 atm->
p[ip] += cache->
dt[ip] * wm;
3014 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3020 atm->
time[ip], atm->
p[ip],
3021 atm->
lon[ip], atm->
lat[ip],
3022 &atm->
q[qnt][ip], ci, cw, 1);
3025 double dts, u[4], um = 0, v[4], vm = 0, wdot[4],
3026 wdotm = 0, x[3] = { 0, 0, 0 };
3029 for (
int i = 0; i < ctl->
advect; i++) {
3034 x[0] = atm->
lon[ip];
3035 x[1] = atm->
lat[ip];
3036 x[2] = atm->
q[qnt][ip];
3038 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
3039 x[0] = atm->
lon[ip] +
DX2DEG(dts * u[i - 1] / 1000., atm->
lat[ip]);
3040 x[1] = atm->
lat[ip] +
DY2DEG(dts * v[i - 1] / 1000.);
3041 x[2] = atm->
q[qnt][ip] + dts * wdot[i - 1];
3044 const double tm = atm->
time[ip] + dts;
3049 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
3052 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
3055 tm, x[2], x[0], x[1], &wdot[i], ci, cw, 0);
3060 k = (i == 0 ? 0.0 : 1.0);
3061 else if (ctl->
advect == 4)
3062 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
3066 wdotm += k * wdot[i];
3070 atm->
time[ip] += cache->
dt[ip];
3071 atm->
lon[ip] +=
DX2DEG(cache->
dt[ip] * um / 1000.,
3072 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
3073 atm->
lat[ip] +=
DY2DEG(cache->
dt[ip] * vm / 1000.);
3074 atm->
q[qnt][ip] += cache->
dt[ip] * wdotm;
3080 atm->
q[qnt][ip], atm->
lon[ip], atm->
lat[ip],
3081 &atm->
p[ip], ci, cw, 1);
3100 SELECT_TIMER(
"MODULE_ADVECT_INIT",
"PHYSICS", NVTX_GPU);
3109 atm->
lon[ip], atm->
lat[ip], &atm->
p[ip], ci, cw, 1);
3124 SELECT_TIMER(
"MODULE_BOUND_COND",
"PHYSICS", NVTX_GPU);
3134 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3170 if (atm->
p[ip] < pbl)
3222 ERRMSG(
"Molar mass is not defined!");
3228 const int ensemble_mode = (ctl->
nens > 0);
3229 const int np = atm->
np;
3233 const int ngrid = nx * ny * nz;
3234 const int nens = ensemble_mode ? ctl->
nens : 1;
3236 double *restrict
const z = (
double *) malloc((
size_t) nz *
sizeof(double));
3237 double *restrict
const press =
3238 (
double *) malloc((
size_t) nz *
sizeof(double));
3239 double *restrict
const mass =
3240 (
double *) calloc((
size_t) ngrid * (size_t) nens,
sizeof(
double));
3241 double *restrict
const area =
3242 (
double *) malloc((
size_t) ny *
sizeof(double));
3243 double *restrict
const lon =
3244 (
double *) malloc((
size_t) nx *
sizeof(double));
3245 double *restrict
const lat =
3246 (
double *) malloc((
size_t) ny *
sizeof(double));
3248 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
3249 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
3250 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
3259#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])
3260#pragma acc data present(ctl,met0,met1,atm,ixs,iys,izs,z,press,mass,area,lon,lat)
3261#pragma acc parallel loop independent gang vector
3263#pragma omp parallel for default(shared)
3265 for (
int iz = 0; iz < nz; iz++) {
3267 press[iz] =
P(z[iz]);
3271 const double t0 = tt - 0.5 * ctl->
dt_mod;
3272 const double t1 = tt + 0.5 * ctl->
dt_mod;
3276#pragma acc parallel loop independent gang vector
3278#pragma omp parallel for default(shared)
3280 for (
int ip = 0; ip < np; ip++) {
3284 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
3285 || ixs[ip] < 0 || ixs[ip] >= nx
3286 || iys[ip] < 0 || iys[ip] >= ny || izs[ip] < 0 || izs[ip] >= nz)
3292#pragma acc parallel loop independent gang vector
3294#pragma omp parallel for default(shared)
3296 for (
int ix = 0; ix < nx; ix++)
3300#pragma acc parallel loop independent gang vector
3302#pragma omp parallel for default(shared)
3304 for (
int iy = 0; iy < ny; iy++) {
3306 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
3311#pragma acc parallel loop independent gang vector
3313 for (
int ip = 0; ip < np; ip++) {
3315 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
3316 if (ensemble_mode) {
3317 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
3318 mass_idx += ens * ngrid;
3321#pragma acc atomic update
3323 mass[mass_idx] += atm->
q[ctl->
qnt_m][ip];
3329#pragma acc parallel loop independent gang vector
3331#pragma omp parallel for default(shared)
3333 for (
int ip = 0; ip < np; ip++)
3341 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
3344 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
3345 if (ensemble_mode) {
3346 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
3347 mass_idx += ens * ngrid;
3351 const double m = mass[mass_idx];
3353 / (
RHO(press[izs[ip]], temp) * area[iys[ip]] * dz * 1e9);
3358#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
3386 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3403 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
3405 atm->
lat[ip], atm->
p[ip]));
3407 atm->
lat[ip], atm->
p[ip]));
3409 atm->
lat[ip], atm->
p[ip]));
3423 SELECT_TIMER(
"MODULE_CONVECTION",
"PHYSICS", NVTX_GPU);
3429 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3437 double pbot = ps, ptop = ps;
3454 double cape, cin, pel;
3460 if (isfinite(cape) && cape >= ctl->
conv_cape
3462 ptop = GSL_MIN(ptop, pel);
3466 if (ptop != pbot && atm->
p[ip] >= ptop) {
3471 pbot, atm->
lon[ip], atm->
lat[ip], &tbot, ci, cw, 1);
3473 atm->
lon[ip], atm->
lat[ip], &ttop, ci, cw, 1);
3474 const double rhobot = pbot / tbot;
3475 const double rhotop = ptop / ttop;
3478 const double rho = rhobot + (rhotop - rhobot) * cache->
rs[ip];
3481 atm->
p[ip] =
LIN(rhobot, pbot, rhotop, ptop, rho);
3505 dd_sort(ctl, *met, atm, dd, &nparticles, &dd->
rank);
3539 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3542 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,clim,atm)") {
3551 const double aux = exp(-cache->
dt[ip] / tdec);
3552 if (ctl->
qnt_m >= 0) {
3555 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
3556 atm->
q[ctl->
qnt_m][ip] *= aux;
3581 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3589 float umean = 0, usig = 0, vmean = 0, vsig = 0, wmean = 0, wsig = 0;
3590 for (
int i = 0; i < 2; i++)
3591 for (
int j = 0; j < 2; j++)
3592 for (
int k = 0; k < 2; k++) {
3593 umean += met0->
u[ix + i][iy + j][iz + k];
3594 usig +=
SQR(met0->
u[ix + i][iy + j][iz + k]);
3595 vmean += met0->
v[ix + i][iy + j][iz + k];
3596 vsig +=
SQR(met0->
v[ix + i][iy + j][iz + k]);
3597 wmean += met0->
w[ix + i][iy + j][iz + k];
3598 wsig +=
SQR(met0->
w[ix + i][iy + j][iz + k]);
3600 umean += met1->
u[ix + i][iy + j][iz + k];
3601 usig +=
SQR(met1->
u[ix + i][iy + j][iz + k]);
3602 vmean += met1->
v[ix + i][iy + j][iz + k];
3603 vsig +=
SQR(met1->
v[ix + i][iy + j][iz + k]);
3604 wmean += met1->
w[ix + i][iy + j][iz + k];
3605 wsig +=
SQR(met1->
w[ix + i][iy + j][iz + k]);
3607 usig = usig / 16.f -
SQR(umean / 16.f);
3608 usig = (usig > 0 ? sqrtf(usig) : 0);
3609 vsig = vsig / 16.f -
SQR(vmean / 16.f);
3610 vsig = (vsig > 0 ? sqrtf(vsig) : 0);
3611 wsig = wsig / 16.f -
SQR(wmean / 16.f);
3612 wsig = (wsig > 0 ? sqrtf(wsig) : 0);
3615 const double r = 1 - 2 * fabs(cache->
dt[ip]) / ctl->
dt_met;
3616 const double r2 = sqrt(1 - r * r);
3620 cache->
uvwp[ip][0] =
3621 (float) (r * cache->
uvwp[ip][0] +
3626 cache->
uvwp[ip][1] =
3627 (float) (r * cache->
uvwp[ip][1] +
3634 cache->
uvwp[ip][2] =
3635 (float) (r * cache->
uvwp[ip][2] +
3637 atm->
p[ip] += cache->
uvwp[ip][2] * cache->
dt[ip];
3658 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3660 double dsigw_dz = 0.0, sig_u = 0.25, sig_w = 0.1,
3661 tau_u = 300., tau_w = 100.;
3670 if (atm->
p[ip] >= pbl) {
3673 const double p =
MIN(atm->
p[ip], ps);
3674 const double zs =
Z(ps);
3675 const double z = 1e3 * (
Z(p) - zs);
3676 const double zi = 1e3 * (
Z(pbl) - zs);
3677 const double zratio = z / zi;
3680 double ess, nss, h2o, t;
3685 const double rho =
RHO(p,
TVIRT(t, h2o));
3686 const double tau = sqrt(
SQR(ess) +
SQR(nss));
3687 const double ustar = sqrt(tau / rho);
3697 sig_u = 1e-2 + 2.0 * ustar * (1.0 - zratio);
3698 sig_w = 1e-2 + 1.3 * ustar * (1.0 - zratio);
3701 dsigw_dz = -1.3 * ustar / zi;
3704 tau_u = 0.07 * zi / sig_u * sqrt(zratio);
3705 tau_w = 0.1 * zi / sig_w * pow(zratio, 0.8);
3712 const double wstar =
3713 pow(
G0 /
THETAVIRT(p, t, h2o) * shf / (rho *
CPD) * zi, 1. / 3.);
3717 + sqrt(0.4 *
SQR(wstar) + (5.0 - 4.0 * zratio) *
SQR(ustar));
3718 sig_w = 1e-2 + sqrt(1.2 *
SQR(wstar) * (1.0 - 0.9 * zratio)
3719 * pow(zratio, 2.0 / 3.0)
3720 + (1.8 - 1.4 * zratio) *
SQR(ustar));
3723 dsigw_dz = 0.5 / sig_w / zi * (-1.4 *
SQR(ustar) +
SQR(wstar)
3725 pow(
MAX(zratio, 1e-3), -1.0 / 3.0)
3726 - 1.8 * pow(zratio, 2.0 / 3.0)));
3729 const double C0 = 3.0;
3731 (1.5 - 1.2 * pow(zratio, 1.0 / 3.0)) *
SQR(wstar) * wstar / zi
3732 +
SQR(ustar) * ustar * (1.0 - 0.8 * zratio) / (
KARMAN * z);
3733 tau_u = 2 *
SQR(sig_u) / (C0 * eps);
3734 tau_w = 2 *
SQR(sig_w) / (C0 * eps);
3739 sig_u =
MAX(sig_u, 0.25);
3740 sig_w =
MAX(sig_w, 0.1);
3741 tau_u =
MAX(tau_u, 300.);
3742 tau_w =
MAX(tau_w, 100.);
3745 const double ru = exp(-fabs(cache->
dt[ip]) / tau_u);
3746 const double ru2 = sqrt(1.0 -
SQR(ru));
3748 = (float) (cache->
uvwp[ip][0] * ru + ru2 * cache->
rs[3 * ip]);
3750 = (float) (cache->
uvwp[ip][1] * ru + ru2 * cache->
rs[3 * ip + 1]);
3752 const double rw = exp(-fabs(cache->
dt[ip]) / tau_w);
3753 const double rw2 = sqrt(1.0 -
SQR(rw));
3755 = (float) (cache->
uvwp[ip][2] * rw + rw2 * cache->
rs[3 * ip + 2]
3756 + sig_w * dsigw_dz * cache->
dt[ip]);
3763 DZ2DP(cache->
uvwp[ip][2] * cache->
dt[ip] / 1000., atm->
p[ip]);
3785 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3794 const double wpbl =
pbl_weight(ctl, atm, ip, pbl, ps);
3795 const double wtrop =
tropo_weight(clim, atm, ip) * (1.0 - wpbl);
3796 const double wstrat = 1.0 - wpbl - wtrop;
3806 const double sigma = sqrt(2.0 * dx * fabs(cache->
dt[ip])) / 1000.;
3808 atm->
lat[ip] +=
DY2DEG(cache->
rs[3 * ip + 1] * sigma);
3813 const double sigma = sqrt(2.0 * dz * fabs(cache->
dt[ip])) / 1000.;
3814 atm->
p[ip] +=
DZ2DP(cache->
rs[3 * ip + 2] * sigma, atm->
p[ip]);
3833 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3836 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3848 const double dz = 1000. * (
Z(ps - ctl->
dry_depo_dp) -
Z(ps));
3868 const double aux = exp(-cache->
dt[ip] * v_dep / dz);
3869 if (ctl->
qnt_m >= 0) {
3872 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
3873 atm->
q[ctl->
qnt_m][ip] *= aux;
3897 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3900 const double a = 3.12541941e-06;
3901 const double b = -5.72532259e-01;
3902 const double low = pow(1. / a, 1. / b);
3905 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3912 if (!(lwc > 0 || rwc > 0))
3923 const double k = 9.1e7 * exp(-29700. /
RI * (1. / t - 1. / 298.15));
3926 const double H_SO2 =
3927 1.3e-2 * exp(2900. * (1. / t - 1. / 298.15)) *
RI * t;
3928 const double K_1S = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
3931 const double H_h2o2 =
3932 8.3e2 * exp(7600. * (1. / t - 1. / 298.15)) *
RI * t;
3938 cor = atm->
q[ctl->
qnt_Cx][ip] >
3939 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
3941 const double h2o2 = H_h2o2
3943 * M * cor * 1000. /
AVO;
3946 const double rho_air = atm->
p[ip] / (
RI * t) *
MA / 10.;
3947 const double CWC = (lwc + rwc) * rho_air / 1e3;
3950 const double rate_coef = k * K_1S * h2o2 * H_SO2 * CWC;
3951 const double aux = exp(-cache->
dt[ip] * rate_coef);
3952 if (ctl->
qnt_m >= 0) {
3955 atm->
q[ctl->
qnt_m][ip] *= aux;
3976 SELECT_TIMER(
"MODULE_ISOSURF_INIT",
"PHYSICS", NVTX_GPU);
3987 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
3990 cache->
iso_var[ip] = atm->
p[ip] / t;
3996 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
4007 LOG(1,
"Read balloon pressure data: %s", ctl->
balloon);
4011 if (!(in = fopen(ctl->
balloon,
"r")))
4012 ERRMSG(
"Cannot open file!");
4016 while (fgets(line,
LEN, in))
4017 if (sscanf(line,
"%lg %lg", &(cache->
iso_ts[cache->
iso_n]),
4020 ERRMSG(
"Too many data points!");
4023 if (cache->
iso_n < 1)
4024 ERRMSG(
"Could not read any data!");
4047 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,met1,atm)") {
4060 atm->
p[ip] = cache->
iso_var[ip] * t;
4066 atm->
p[ip] = 1000. * pow(cache->
iso_var[ip] / t, -1. / 0.286);
4072 atm->
p[ip] = cache->
iso_ps[0];
4100 const int nvar = NVAR, nfix = NFIX, nreact = NREACT;
4101 double rtol[1] = { 1.0e-3 };
4102 double atol[1] = { 1.0 };
4106#pragma acc data copy(rtol,atol,nvar,nfix,nreact)
4109 "acc data present(ctl,cache,clim,met0,met1,atm) ") {
4112 double var[nvar], fix[nfix], rconst[nreact];
4113 for (
int i = 0; i < nvar; i++)
4115 for (
int i = 0; i < nfix; i++)
4117 for (
int i = 0; i < nreact; i++)
4119 kpp_chem_initialize(ctl, clim, met0, met1, atm, var, fix, rconst, ip);
4124 for (
int i = 0; i < 20; i++) {
4131 Rosenbrock(var, fix, rconst, 0, ctl->
dt_kpp,
4132 atol, rtol, &FunTemplate, &JacTemplate, rpar, ipar);
4135 kpp_chem_output2atm(atm, ctl, met0, met1, var, ip);
4156 ERRMSG(
"Need T_ice and T_NAT to calculate T_STS!");
4160 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4162 double ps, ts, zs, us, vs, ess, nss, shf, lsm, sst, pbl, pt, pct, pcb,
4163 cl, plcl, plfc, pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot,
4164 o3, lwc, rwc, iwc, swc, cc, z, zt;
4212 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
4214 atm->
lat[ip], atm->
p[ip]));
4216 atm->
lat[ip], atm->
p[ip]));
4218 atm->
lat[ip], atm->
p[ip]));
4219 SET_ATM(qnt_vh, sqrt(u * u + v * v));
4241 atm->
lat[ip], atm->
p[ip])));
4259 const int np = atm->
np;
4260 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
4261 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
4262 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
4270 const double t0 = t - 0.5 * ctl->
dt_mod;
4271 const double t1 = t + 0.5 * ctl->
dt_mod;
4275#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
4276#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
4277#pragma acc parallel loop independent gang vector
4279#pragma omp parallel for default(shared)
4281 for (
int ip = 0; ip < np; ip++) {
4284 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
mixing_z0) / dz);
4285 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
4286 || ixs[ip] < 0 || ixs[ip] >= ctl->
mixing_nx
4287 || iys[ip] < 0 || iys[ip] >= ctl->
mixing_ny
4288 || izs[ip] < 0 || izs[ip] >= ctl->
mixing_nz)
4293 const int use_ensemble = (ctl->
nens > 0);
4295 const int quantities[] = {
4302 const int n_qnt =
sizeof(quantities) /
sizeof(quantities[0]);
4304 for (
int i = 0; i < n_qnt; i++)
4305 if (quantities[i] >= 0)
4311#pragma acc exit data delete(ixs,iys,izs)
4328 const int use_ensemble) {
4330 const int np = atm->
np;
4332 const int nens = use_ensemble ? ctl->
nens : 1;
4333 const int total_grid = ngrid * nens;
4335 double *restrict
const cmean =
4336 (
double *) malloc((
size_t) total_grid *
sizeof(double));
4337 int *restrict
const count =
4338 (
int *) malloc((
size_t) total_grid *
sizeof(int));
4342#pragma acc enter data create(cmean[0:total_grid],count[0:total_grid])
4343#pragma acc data present(ctl,clim,atm,ixs,iys,izs,cmean,count)
4344#pragma acc parallel loop independent gang vector
4349#pragma omp parallel for
4351 for (
int i = 0; i < total_grid; i++) {
4358#pragma acc parallel loop independent gang vector
4360 for (
int ip = 0; ip < np; ip++)
4362 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
4367#pragma acc atomic update
4369 cmean[idx] += atm->
q[qnt_idx][ip];
4371#pragma acc atomic update
4378#pragma acc parallel loop independent gang vector
4383#pragma omp parallel for
4385 for (
int i = 0; i < total_grid; i++)
4387 cmean[i] /= count[i];
4391#pragma acc parallel loop independent gang vector
4393#pragma omp parallel for
4395 for (
int ip = 0; ip < np; ip++) {
4397 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
4399 double mixparam = 1.0;
4408 atm->
q[qnt_idx][ip] += (cmean[idx] - atm->
q[qnt_idx][ip]) * mixparam;
4414#pragma acc exit data delete(cmean,count)
4435 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4438 const double a = 4.71572206e-08;
4439 const double b = -8.28782867e-01;
4440 const double low = pow(1. / a, 1. / b);
4444 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4470 0 ? pow(298. / t, ctl->
oh_chem[1]) : 1.);
4473 0 ? pow(298. / t, ctl->
oh_chem[3]) : 1.);
4474 const double c = log10(k0 * M / ki);
4475 k = k0 * M / (1. + k0 * M / ki) * pow(0.6, 1. / (1. + c * c));
4484 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
4487 const double rate_coef =
4489 atm->
lat[ip], atm->
p[ip]) * M * cor;
4490 const double aux = exp(-cache->
dt[ip] * rate_coef);
4491 if (ctl->
qnt_m >= 0) {
4494 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
4495 atm->
q[ctl->
qnt_m][ip] *= aux;
4516 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(cache,met0,met1,atm)") {
4527 while (atm->
lat[ip] < -90 || atm->
lat[ip] > 90) {
4528 if (atm->
lat[ip] > 90) {
4529 atm->
lat[ip] = 180 - atm->
lat[ip];
4530 atm->
lon[ip] += 180;
4532 if (atm->
lat[ip] < -90) {
4533 atm->
lat[ip] = -180 - atm->
lat[ip];
4534 atm->
lon[ip] += 180;
4539 while (atm->
lon[ip] < -180)
4540 atm->
lon[ip] += 360;
4541 while (atm->
lon[ip] >= 180)
4542 atm->
lon[ip] -= 360;
4545 if (atm->
p[ip] < met0->
p[met0->
np - 1]) {
4546 atm->
p[ip] = met0->
p[met0->
np - 1];
4547 }
else if (atm->
p[ip] > 300.) {
4549 if (atm->
p[ip] > ps)
4561 gsl_rng_env_setup();
4562 if (omp_get_max_threads() >
NTHREADS)
4563 ERRMSG(
"Too many threads!");
4564 for (
int i = 0; i <
NTHREADS; i++) {
4565 rng[i] = gsl_rng_alloc(gsl_rng_default);
4566 gsl_rng_set(rng[i], gsl_rng_default_seed
4567 + (
long unsigned) (ntask *
NTHREADS + i));
4572 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
4573 CURAND_STATUS_SUCCESS)
4574 ERRMSG(
"Cannot create random number generator!");
4575 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
4576 CURAND_STATUS_SUCCESS)
4577 ERRMSG(
"Cannot set seed for random number generator!");
4580 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
4581 CURAND_STATUS_SUCCESS)
4582 ERRMSG(
"Cannot set stream for random number generator!");
4599#pragma omp parallel for default(shared)
4600 for (
size_t i = 0; i < n; ++i)
4601 rs[i] = gsl_rng_uniform(rng[omp_get_thread_num()]);
4605 else if (method == 1) {
4606#pragma omp parallel for default(shared)
4607 for (
size_t i = 0; i < n; ++i)
4608 rs[i] = gsl_ran_gaussian_ziggurat(rng[omp_get_thread_num()], 1.0);
4614#pragma acc update device(rs[:n])
4622 const uint64_t key = 0xc8e4fd154ce32f6d;
4626#pragma acc data present(rs)
4627#pragma acc parallel loop independent gang vector
4629#pragma omp parallel for default(shared)
4631 for (
size_t i = 0; i < n + 1; ++i) {
4632 uint64_t r, t, x, y, z;
4633 y = x = (rng_ctr + i) * key;
4636 x = (x >> 32) | (x << 32);
4638 x = (x >> 32) | (x << 32);
4640 x = (x >> 32) | (x << 32);
4642 x = (x >> 32) | (x << 32);
4643 r = t ^ ((x * x + y) >> 32);
4644 rs[i] = (double) r / (
double) UINT64_MAX;
4651#pragma acc parallel loop independent gang vector
4653#pragma omp parallel for default(shared)
4655 for (
size_t i = 0; i < n; i += 2) {
4656 const double r = sqrt(-2.0 * log(rs[i]));
4657 const double phi = 2.0 * M_PI * rs[i + 1];
4658 rs[i] = r * cosf((
float) phi);
4659 rs[i + 1] = r * sinf((
float) phi);
4667#pragma acc host_data use_device(rs)
4672 if (curandGenerateUniformDouble(rng_curand, rs, (n < 4 ? 4 : n)) !=
4673 CURAND_STATUS_SUCCESS)
4674 ERRMSG(
"Cannot create random numbers!");
4678 else if (method == 1) {
4679 if (curandGenerateNormalDouble
4680 (rng_curand, rs, (n < 4 ? 4 : n), 0.0,
4681 1.0) != CURAND_STATUS_SUCCESS)
4682 ERRMSG(
"Cannot create random numbers!");
4686 ERRMSG(
"MPTRAC was compiled without cuRAND!");
4704 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4712 const double v_s =
sedi(atm->
p[ip], t, atm->
q[ctl->
qnt_rp][ip],
4716 atm->
p[ip] +=
DZ2DP(v_s * cache->
dt[ip] / 1000., atm->
p[ip]);
4731 const int np = atm->
np;
4732 double *restrict
const a = (
double *) malloc((
size_t) np *
sizeof(double));
4733 int *restrict
const p = (
int *) malloc((
size_t) np *
sizeof(int));
4734 if (a == NULL || p == NULL)
4735 ERRMSG(
"Out of memory!");
4738#pragma acc enter data create(a[0:np],p[0:np])
4739#pragma acc data present(ctl,met0,atm,a,p)
4744#pragma acc parallel loop independent gang vector
4746#pragma omp parallel for default(shared)
4748 for (
int ip = 0; ip < np; ip++) {
4759#pragma acc host_data use_device(a,p)
4761 thrustSortWrapper(a, np, p);
4764 ERRMSG(
"GSL sort fallback not available on GPU, use THRUST!");
4766 gsl_sort_index((
size_t *) p, a, 1, (
size_t) np);
4774 for (
int iq = 0; iq < ctl->
nq; iq++)
4779#pragma acc exit data delete(a,p)
4793 double *restrict
const help =
4794 (
double *) malloc((
size_t) np *
sizeof(double));
4796 ERRMSG(
"Out of memory!");
4800#pragma acc enter data create(help[0:np])
4801#pragma acc data present(a,p,help)
4802#pragma acc parallel loop independent gang vector
4804#pragma omp parallel for default(shared)
4806 for (
int ip = 0; ip < np; ip++)
4807 help[ip] = a[p[ip]];
4809#pragma acc parallel loop independent gang vector
4811#pragma omp parallel for default(shared)
4813 for (
int ip = 0; ip < np; ip++)
4818#pragma acc exit data delete(help)
4835 const double latmin = gsl_stats_min(met0->
lat, 1, (
size_t) met0->
ny),
4836 latmax = gsl_stats_max(met0->
lat, 1, (
size_t) met0->
ny);
4839 (fabs(met0->
lon[met0->
nx - 1] - met0->
lon[0] - 360.0) >= 0.01);
4842 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,atm)") {
4848 cache->
dt[ip] = t - atm->
time[ip];
4850 cache->
dt[ip] = 0.0;
4859 if (local && (atm->
lon[ip] <= met0->
lon[0]
4860 || atm->
lon[ip] >= met0->
lon[met0->
nx - 1]
4861 || atm->
lat[ip] <= latmin || atm->
lat[ip] >= latmax))
4862 cache->
dt[ip] = 0.0;
4877 SELECT_TIMER(
"MODULE_TIMESTEPS_INIT",
"PHYSICS", NVTX_GPU);
4881 ctl->
t_start = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
4883 ctl->
t_stop = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
4885 ctl->
t_start = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
4887 ctl->
t_stop = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
4892 ERRMSG(
"Nothing to do! Check T_STOP and DIRECTION!");
4912 SELECT_TIMER(
"MODULE_TRACER_CHEM",
"PHYSICS", NVTX_GPU);
4916 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4939 const double K_o1d =
ARRHENIUS(3.30e-10, 0, t) * o1d * M;
4941 atm->
p[ip], sza, o3c);
4942 atm->
q[ctl->
qnt_Cccl4][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4947 const double K_o1d =
ARRHENIUS(2.30e-10, 0, t) * o1d * M;
4949 atm->
p[ip], sza, o3c);
4950 atm->
q[ctl->
qnt_Cccl3f][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4955 const double K_o1d =
ARRHENIUS(1.40e-10, -25, t) * o1d * M;
4957 atm->
p[ip], sza, o3c);
4958 atm->
q[ctl->
qnt_Cccl2f2][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4963 const double K_o1d =
ARRHENIUS(1.19e-10, -20, t) * o1d * M;
4965 atm->
p[ip], sza, o3c);
4966 atm->
q[ctl->
qnt_Cn2o][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4985 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4988 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4994 if (!isfinite(pct) || atm->
p[ip] <= pct)
5010 double lwc, rwc, iwc, swc;
5015 const int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
5029 else if (t <= 238.15)
5049 const double K_1 = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
5050 const double K_2 = 6e-8 * exp(1.12e3 * (1. / t - 1. / 298.15));
5051 h *= (1. + K_1 / H_ion + K_1 * K_2 /
SQR(H_ion));
5055 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
5058 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
5084 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
5087 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
5092 const double aux = exp(-cache->
dt[ip] * lambda);
5093 if (ctl->
qnt_m >= 0) {
5096 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
5097 atm->
q[ctl->
qnt_m][ip] *= aux;
5122 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
5124 if (acc_get_num_devices(acc_device_nvidia) <= 0)
5125 ERRMSG(
"Not running on a GPU device!");
5126 acc_set_device_num(rank % acc_get_num_devices(acc_device_nvidia),
5128 acc_device_t device_type = acc_get_device_type();
5129 acc_init(device_type);
5144 SELECT_TIMER(
"CREATE_DATA_REGION",
"MEMORY", NVTX_GPU);
5145 ctl_t *ctlup = *ctl;
5148 met_t *met0up = *met0;
5149 met_t *met1up = *met1;
5150 atm_t *atmup = *atm;
5151#pragma acc enter data create(ctlup[:1],cacheup[:1],climup[:1],met0up[:1],met1up[:1],atmup[:1])
5154#pragma acc enter data create(ddup[:1])
5172 SELECT_TIMER(
"DELETE_DATA_REGION",
"MEMORY", NVTX_GPU);
5173#pragma acc exit data delete (ctl,cache,clim,met0,met1,atm)
5187 MPI_Type_free(&dd->MPI_Particle);
5206 char cachefile[
LEN], cmd[2 *
LEN], filename[
LEN];
5212 if (t == ctl->
t_start || !init) {
5219 ERRMSG(
"Cannot open file!");
5224 ERRMSG(
"Cannot open file!");
5234 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5235 LOG(1,
"Caching: %s", cachefile);
5236 if (system(cmd) != 0)
5237 WARN(
"Caching command failed!");
5242 if (t > (*met1)->time) {
5252 ERRMSG(
"Cannot open file!");
5262 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5263 LOG(1,
"Caching: %s", cachefile);
5264 if (system(cmd) != 0)
5265 WARN(
"Caching command failed!");
5270 if (t < (*met0)->time) {
5280 ERRMSG(
"Cannot open file!");
5290 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5291 LOG(1,
"Caching: %s", cachefile);
5292 if (system(cmd) != 0)
5293 WARN(
"Caching command failed!");
5298 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
5299 if ((*met0)->nx != (*met1)->nx
5300 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
5301 ERRMSG(
"Meteo grid dimensions do not match!");
5302 for (
int ix = 0; ix < (*met0)->nx; ix++)
5303 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
5304 ERRMSG(
"Meteo grid longitudes do not match!");
5305 for (
int iy = 0; iy < (*met0)->ny; iy++)
5306 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
5307 ERRMSG(
"Meteo grid latitudes do not match!");
5308 for (
int ip = 0; ip < (*met0)->np; ip++)
5309 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
5310 ERRMSG(
"Meteo grid pressure levels do not match!");
5336 const char *filename,
5349 LOG(1,
"Read atmospheric data: %s", filename);
5369 ERRMSG(
"Atmospheric data type not supported!");
5377 ERRMSG(
"Can not read any data!");
5381 LOG(2,
"Number of particles: %d", atm->
np);
5382 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
5383 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
5384 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
5385 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
5386 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
5387 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
5388 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
5389 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
5390 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
5391 for (
int iq = 0; iq < ctl->
nq; iq++) {
5393 sprintf(msg,
"Quantity %s range: %s ... %s %s",
5396 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
5397 LOG(2, msg, mini, maxi);
5467 const char *filename,
5476 LOG(1,
"\nMassive-Parallel Trajectory Calculations (MPTRAC)\n"
5477 "(executable: %s | version: %s | compiled: %s, %s)\n",
5478 argv[0], VERSION, __DATE__, __TIME__);
5582 ctl->
nq = (int)
scan_ctl(filename, argc, argv,
"NQ", -1,
"0", NULL);
5584 ERRMSG(
"Too many quantities!");
5585 for (
int iq = 0; iq < ctl->
nq; iq++) {
5591 scan_ctl(filename, argc, argv,
"QNT_FORMAT", iq,
"%g",
5593 if (strcasecmp(ctl->
qnt_name[iq],
"aoa") == 0)
5597 SET_QNT(qnt_idx,
"idx",
"particle index",
"-")
5598 SET_QNT(qnt_ens,
"ens",
"ensemble index",
"-")
5599 SET_QNT(qnt_stat,
"stat",
"station flag",
"-")
5600 SET_QNT(qnt_m,
"m",
"mass",
"kg")
5601 SET_QNT(qnt_vmr,
"vmr",
"volume mixing ratio",
"ppv")
5602 SET_QNT(qnt_rp,
"rp",
"particle radius",
"microns")
5603 SET_QNT(qnt_rhop,
"rhop",
"particle density",
"kg/m^3")
5604 SET_QNT(qnt_ps,
"ps",
"surface pressure",
"hPa")
5605 SET_QNT(qnt_ts,
"ts",
"surface temperature",
"K")
5606 SET_QNT(qnt_zs,
"zs",
"surface height",
"km")
5607 SET_QNT(qnt_us,
"us",
"surface zonal wind",
"m/s")
5608 SET_QNT(qnt_vs,
"vs",
"surface meridional wind",
"m/s")
5609 SET_QNT(qnt_ess,
"ess",
"eastward turbulent surface stress",
"N/m^2")
5610 SET_QNT(qnt_nss,
"nss",
"northward turbulent surface stress",
"N/m^2")
5611 SET_QNT(qnt_shf,
"shf",
"surface sensible heat flux",
"W/m^2")
5612 SET_QNT(qnt_lsm,
"lsm",
"land-sea mask",
"1")
5613 SET_QNT(qnt_sst,
"sst",
"sea surface temperature",
"K")
5614 SET_QNT(qnt_pbl,
"pbl",
"planetary boundary layer",
"hPa")
5615 SET_QNT(qnt_pt,
"pt",
"tropopause pressure",
"hPa")
5616 SET_QNT(qnt_tt,
"tt",
"tropopause temperature",
"K")
5617 SET_QNT(qnt_zt,
"zt",
"tropopause geopotential height",
"km")
5618 SET_QNT(qnt_h2ot,
"h2ot",
"tropopause water vapor",
"ppv")
5619 SET_QNT(qnt_zg,
"zg",
"geopotential height",
"km")
5620 SET_QNT(qnt_p,
"p",
"pressure",
"hPa")
5621 SET_QNT(qnt_t,
"t",
"temperature",
"K")
5622 SET_QNT(qnt_rho,
"rho",
"air density",
"kg/m^3")
5623 SET_QNT(qnt_u,
"u",
"zonal wind",
"m/s")
5624 SET_QNT(qnt_v,
"v",
"meridional wind",
"m/s")
5625 SET_QNT(qnt_w,
"w",
"vertical velocity",
"hPa/s")
5626 SET_QNT(qnt_h2o,
"h2o",
"water vapor",
"ppv")
5627 SET_QNT(qnt_o3,
"o3",
"ozone",
"ppv")
5628 SET_QNT(qnt_lwc,
"lwc",
"cloud liquid water content",
"kg/kg")
5629 SET_QNT(qnt_rwc,
"rwc",
"cloud rain water content",
"kg/kg")
5630 SET_QNT(qnt_iwc,
"iwc",
"cloud ice water content",
"kg/kg")
5631 SET_QNT(qnt_swc,
"swc",
"cloud snow water content",
"kg/kg")
5632 SET_QNT(qnt_cc,
"cc",
"cloud cover",
"1")
5633 SET_QNT(qnt_pct,
"pct",
"cloud top pressure",
"hPa")
5634 SET_QNT(qnt_pcb,
"pcb",
"cloud bottom pressure",
"hPa")
5635 SET_QNT(qnt_cl,
"cl",
"total column cloud water",
"kg/m^2")
5636 SET_QNT(qnt_plcl,
"plcl",
"lifted condensation level",
"hPa")
5637 SET_QNT(qnt_plfc,
"plfc",
"level of free convection",
"hPa")
5638 SET_QNT(qnt_pel,
"pel",
"equilibrium level",
"hPa")
5639 SET_QNT(qnt_cape,
"cape",
"convective available potential energy",
5641 SET_QNT(qnt_cin,
"cin",
"convective inhibition",
"J/kg")
5642 SET_QNT(qnt_o3c,
"o3c",
"total column ozone",
"DU")
5643 SET_QNT(qnt_hno3,
"hno3",
"nitric acid",
"ppv")
5644 SET_QNT(qnt_oh,
"oh",
"hydroxyl radical",
"ppv")
5645 SET_QNT(qnt_h2o2,
"h2o2",
"hydrogen peroxide",
"ppv")
5646 SET_QNT(qnt_ho2,
"ho2",
"hydroperoxyl radical",
"ppv")
5647 SET_QNT(qnt_o1d,
"o1d",
"atomic oxygen",
"ppv")
5648 SET_QNT(qnt_mloss_oh,
"mloss_oh",
"mass loss due to OH chemistry",
"kg")
5649 SET_QNT(qnt_mloss_h2o2,
"mloss_h2o2",
5650 "mass loss due to H2O2 chemistry",
"kg")
5651 SET_QNT(qnt_mloss_kpp,
"mloss_kpp",
"mass loss due to kpp chemistry",
5653 SET_QNT(qnt_mloss_wet,
"mloss_wet",
"mass loss due to wet deposition",
5655 SET_QNT(qnt_mloss_dry,
"mloss_dry",
"mass loss due to dry deposition",
5657 SET_QNT(qnt_mloss_decay,
"mloss_decay",
5658 "mass loss due to exponential decay",
"kg")
5659 SET_QNT(qnt_loss_rate,
"loss_rate",
"total loss rate",
"s^-1")
5660 SET_QNT(qnt_psat,
"psat",
"saturation pressure over water",
"hPa")
5661 SET_QNT(qnt_psice,
"psice",
"saturation pressure over ice",
"hPa")
5662 SET_QNT(qnt_pw,
"pw",
"partial water vapor pressure",
"hPa")
5663 SET_QNT(qnt_sh,
"sh",
"specific humidity",
"kg/kg")
5664 SET_QNT(qnt_rh,
"rh",
"relative humidity",
"%%")
5665 SET_QNT(qnt_rhice,
"rhice",
"relative humidity over ice",
"%%")
5666 SET_QNT(qnt_theta,
"theta",
"potential temperature",
"K")
5667 SET_QNT(qnt_zeta,
"zeta",
"zeta coordinate",
"K")
5668 SET_QNT(qnt_zeta_d,
"zeta_d",
"diagnosed zeta coordinate",
"K")
5669 SET_QNT(qnt_zeta_dot,
"zeta_dot",
"velocity of zeta coordinate",
5671 SET_QNT(qnt_eta,
"eta",
"eta coordinate",
"1")
5672 SET_QNT(qnt_eta_dot,
"eta_dot",
"velocity of eta coordinate",
"1/s")
5673 SET_QNT(qnt_tvirt,
"tvirt",
"virtual temperature",
"K")
5674 SET_QNT(qnt_lapse,
"lapse",
"temperature lapse rate",
"K/km")
5675 SET_QNT(qnt_vh,
"vh",
"horizontal velocity",
"m/s")
5676 SET_QNT(qnt_vz,
"vz",
"vertical velocity",
"m/s")
5677 SET_QNT(qnt_pv,
"pv",
"potential vorticity",
"PVU")
5678 SET_QNT(qnt_tdew,
"tdew",
"dew point temperature",
"K")
5679 SET_QNT(qnt_tice,
"tice",
"frost point temperature",
"K")
5680 SET_QNT(qnt_tsts,
"tsts",
"STS existence temperature",
"K")
5681 SET_QNT(qnt_tnat,
"tnat",
"NAT existence temperature",
"K")
5682 SET_QNT(qnt_Cx,
"Cx",
"Trace species x volume mixing ratio",
"ppv")
5683 SET_QNT(qnt_Ch2o,
"Ch2o",
"H2O volume mixing ratio",
"ppv")
5684 SET_QNT(qnt_Co3,
"Co3",
"O3 volume mixing ratio",
"ppv")
5685 SET_QNT(qnt_Cco,
"Cco",
"CO volume mixing ratio",
"ppv")
5686 SET_QNT(qnt_Coh,
"Coh",
"HO volume mixing ratio",
"ppv")
5687 SET_QNT(qnt_Ch,
"Ch",
"H radical volume mixing ratio",
"ppv")
5688 SET_QNT(qnt_Cho2,
"Cho2",
"HO2 volume mixing ratio",
"ppv")
5689 SET_QNT(qnt_Ch2o2,
"Ch2o2",
"H2O2 volume mixing ratio",
"ppv")
5690 SET_QNT(qnt_Co1d,
"Co1d",
"O(1D) volume mixing ratio",
"ppv")
5691 SET_QNT(qnt_Co3p,
"Co3p",
"O(3P) radical volume mixing ratio",
"ppv")
5692 SET_QNT(qnt_Cccl4,
"Cccl4",
"CCl4 (CFC-10) volume mixing ratio",
"ppv")
5693 SET_QNT(qnt_Cccl3f,
"Cccl3f",
"CCl3F (CFC-11) volume mixing ratio",
5695 SET_QNT(qnt_Cccl2f2,
"Cccl2f2",
"CCl2F2 (CFC-12) volume mixing ratio",
5697 SET_QNT(qnt_Cn2o,
"Cn2o",
"N2O volume mixing ratio",
"ppv")
5698 SET_QNT(qnt_Csf6,
"Csf6",
"SF6 volume mixing ratio",
"ppv")
5699 SET_QNT(qnt_aoa,
"aoa",
"age of air",
"s")
5701 SET_QNT(qnt_destination,
"destination",
5702 "subdomain index of destination",
"-")
5703 SET_QNT(qnt_subdomain,
"subdomain",
"current subdomain index",
"-")
5710 (int)
scan_ctl(filename, argc, argv,
"ADVECT_VERT_COORD", -1,
"0", NULL);
5712 ERRMSG(
"ADVECT_VERT_COORD must be 0, 1, 2, or 3!");
5715 ERRMSG(
"Add quantity zeta for diabatic advection!");
5717 ERRMSG(
"Add quantity eta for etadot avection!");
5720 (int)
scan_ctl(filename, argc, argv,
"MET_VERT_COORD", -1,
"0", NULL);
5722 ERRMSG(
"MET_VERT_COORD must be 0, 1, 2, 3, or 4!");
5726 (
"Using ADVECT_VERT_COORD = 2 requires meteo data on model levels!");
5729 (
"Using ADVECT_VERT_COORD = 3 requires A and B model level coefficients!");
5733 (int)
scan_ctl(filename, argc, argv,
"DIRECTION", -1,
"1", NULL);
5735 ERRMSG(
"Set DIRECTION to -1 or 1!");
5736 ctl->
t_stop =
scan_ctl(filename, argc, argv,
"T_STOP", -1,
"1e100", NULL);
5737 ctl->
dt_mod =
scan_ctl(filename, argc, argv,
"DT_MOD", -1,
"180", NULL);
5741 ctl->
dt_met =
scan_ctl(filename, argc, argv,
"DT_MET", -1,
"3600", NULL);
5743 (int)
scan_ctl(filename, argc, argv,
"MET_CONVENTION", -1,
"0", NULL);
5745 (int)
scan_ctl(filename, argc, argv,
"MET_TYPE", -1,
"0", NULL);
5748 (
"Please use meteo files in netcdf format for diabatic calculations.");
5751 (
"Please use meteo files in netcdf format for etadot calculations.");
5753 (int)
scan_ctl(filename, argc, argv,
"MET_CLAMS", -1,
"0", NULL);
5755 (int)
scan_ctl(filename, argc, argv,
"MET_NC_SCALE", -1,
"1", NULL);
5757 (int)
scan_ctl(filename, argc, argv,
"MET_NC_LEVEL", -1,
"0", NULL);
5759 (int)
scan_ctl(filename, argc, argv,
"MET_NC_QUANT", -1,
"0", NULL);
5761 (int)
scan_ctl(filename, argc, argv,
"MET_ZSTD_LEVEL", -1,
"0", NULL);
5762 for (
int i = 0; i <
METVAR; i++) {
5763 char defprec[
LEN] =
"0", deftol[
LEN] =
"0.0";
5765 sprintf(deftol,
"0.5");
5767 sprintf(deftol,
"5.0");
5769 sprintf(defprec,
"8");
5771 (int)
scan_ctl(filename, argc, argv,
"MET_COMP_PREC", i, defprec, NULL);
5773 scan_ctl(filename, argc, argv,
"MET_COMP_TOL", i, deftol, NULL);
5776 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_BATCH", -1,
"-1", NULL);
5778 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ZSTD", -1,
"1", NULL);
5780 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_HEUR", -1,
"1", NULL);
5782 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_Z", -1,
"1.0", NULL);
5784 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_T", -1,
"0.05", NULL);
5786 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_U", -1,
"0.05", NULL);
5788 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_V", -1,
"0.05", NULL);
5790 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_W", -1,
"1.0", NULL);
5792 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_PV", -1,
"1.0", NULL);
5794 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_H2O", -1,
"1.0", NULL);
5796 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_O3", -1,
"1.0", NULL);
5798 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_LWC", -1,
"1.0", NULL);
5800 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_RWC", -1,
"1.0", NULL);
5802 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_IWC", -1,
"1.0", NULL);
5804 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_SWC", -1,
"1.0", NULL);
5806 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_CC", -1,
"1.0", NULL);
5807 ctl->
met_dx = (int)
scan_ctl(filename, argc, argv,
"MET_DX", -1,
"1", NULL);
5808 ctl->
met_dy = (int)
scan_ctl(filename, argc, argv,
"MET_DY", -1,
"1", NULL);
5809 ctl->
met_dp = (int)
scan_ctl(filename, argc, argv,
"MET_DP", -1,
"1", NULL);
5811 ERRMSG(
"MET_DX, MET_DY, and MET_DP need to be greater than zero!");
5812 ctl->
met_sx = (int)
scan_ctl(filename, argc, argv,
"MET_SX", -1,
"1", NULL);
5813 ctl->
met_sy = (int)
scan_ctl(filename, argc, argv,
"MET_SY", -1,
"1", NULL);
5814 ctl->
met_sp = (int)
scan_ctl(filename, argc, argv,
"MET_SP", -1,
"1", NULL);
5816 ERRMSG(
"MET_SX, MET_SY, and MET_SP need to be greater than zero!");
5818 scan_ctl(filename, argc, argv,
"MET_DETREND", -1,
"-999", NULL);
5819 ctl->
met_np = (int)
scan_ctl(filename, argc, argv,
"MET_NP", -1,
"0", NULL);
5821 ERRMSG(
"Too many pressure levels!");
5823 (int)
scan_ctl(filename, argc, argv,
"MET_PRESS_LEVEL_DEF", -1,
"-1",
5829 for (
int ip = 0; ip < ctl->
met_np; ip++)
5831 scan_ctl(filename, argc, argv,
"MET_P", ip,
"", NULL);
5835 (int)
scan_ctl(filename, argc, argv,
"MET_NLEV", -1,
"0", NULL);
5837 ERRMSG(
"Too many model levels!");
5838 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
5840 scan_ctl(filename, argc, argv,
"MET_LEV_HYAM", ip,
"", NULL);
5841 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
5843 scan_ctl(filename, argc, argv,
"MET_LEV_HYBM", ip,
"", NULL);
5845 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SX", -1,
"-1", NULL);
5847 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SY", -1,
"-1", NULL);
5849 (int)
scan_ctl(filename, argc, argv,
"MET_RELHUM", -1,
"0", NULL);
5851 (int)
scan_ctl(filename, argc, argv,
"MET_CAPE", -1,
"1", NULL);
5853 ERRMSG(
"Set MET_CAPE to 0 or 1!");
5855 (int)
scan_ctl(filename, argc, argv,
"MET_PBL", -1,
"3", NULL);
5857 ERRMSG(
"Set MET_PBL to 0 ... 3!");
5859 scan_ctl(filename, argc, argv,
"MET_PBL_MIN", -1,
"0.1", NULL);
5861 scan_ctl(filename, argc, argv,
"MET_PBL_MAX", -1,
"5.0", NULL);
5863 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO", -1,
"3", NULL);
5865 ERRMSG(
"Set MET_TROPO to 0 ... 5!");
5867 scan_ctl(filename, argc, argv,
"MET_TROPO_PV", -1,
"3.5", NULL);
5869 scan_ctl(filename, argc, argv,
"MET_TROPO_THETA", -1,
"380", NULL);
5871 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO_SPLINE", -1,
"1", NULL);
5873 scan_ctl(filename, argc, argv,
"MET_DT_OUT", -1,
"0.1", NULL);
5875 (int)
scan_ctl(filename, argc, argv,
"MET_CACHE", -1,
"0", NULL);
5877 (int)
scan_ctl(filename, argc, argv,
"MET_MPI_SHARE", -1,
"0", NULL);
5880 ctl->
sort_dt =
scan_ctl(filename, argc, argv,
"SORT_DT", -1,
"-999", NULL);
5884 (int)
scan_ctl(filename, argc, argv,
"ISOSURF", -1,
"0", NULL);
5889 (int)
scan_ctl(filename, argc, argv,
"RNG_TYPE", -1,
"1", NULL);
5891 ERRMSG(
"Set RNG_TYPE to 0, 1, or 2!");
5894 ctl->
advect = (int)
scan_ctl(filename, argc, argv,
"ADVECT", -1,
"2", NULL);
5898 ERRMSG(
"Set ADVECT to 0, 1, 2, or 4!");
5902 = (int)
scan_ctl(filename, argc, argv,
"DIFFUSION", -1,
"0", NULL);
5904 ERRMSG(
"Set DIFFUSION to 0, 1 or 2!");
5906 scan_ctl(filename, argc, argv,
"TURB_DX_PBL", -1,
"50", NULL);
5908 scan_ctl(filename, argc, argv,
"TURB_DX_TROP", -1,
"50", NULL);
5910 scan_ctl(filename, argc, argv,
"TURB_DX_STRAT", -1,
"0", NULL);
5912 scan_ctl(filename, argc, argv,
"TURB_DZ_PBL", -1,
"0", NULL);
5914 scan_ctl(filename, argc, argv,
"TURB_DZ_TROP", -1,
"0", NULL);
5916 scan_ctl(filename, argc, argv,
"TURB_DZ_STRAT", -1,
"0.1", NULL);
5918 scan_ctl(filename, argc, argv,
"TURB_MESOX", -1,
"0.16", NULL);
5920 scan_ctl(filename, argc, argv,
"TURB_MESOZ", -1,
"0.16", NULL);
5924 = (int)
scan_ctl(filename, argc, argv,
"CONV_MIX_PBL", -1,
"0", NULL);
5926 =
scan_ctl(filename, argc, argv,
"CONV_PBL_TRANS", -1,
"0", NULL);
5928 =
scan_ctl(filename, argc, argv,
"CONV_CAPE", -1,
"-999", NULL);
5930 =
scan_ctl(filename, argc, argv,
"CONV_CIN", -1,
"-999", NULL);
5931 ctl->
conv_dt =
scan_ctl(filename, argc, argv,
"CONV_DT", -1,
"-999", NULL);
5935 scan_ctl(filename, argc, argv,
"BOUND_MASS", -1,
"-999", NULL);
5937 scan_ctl(filename, argc, argv,
"BOUND_MASS_TREND", -1,
"0", NULL);
5939 scan_ctl(filename, argc, argv,
"BOUND_VMR", -1,
"-999", NULL);
5941 scan_ctl(filename, argc, argv,
"BOUND_VMR_TREND", -1,
"0", NULL);
5943 scan_ctl(filename, argc, argv,
"BOUND_LAT0", -1,
"-999", NULL);
5945 scan_ctl(filename, argc, argv,
"BOUND_LAT1", -1,
"-999", NULL);
5947 scan_ctl(filename, argc, argv,
"BOUND_P0", -1,
"-999", NULL);
5949 scan_ctl(filename, argc, argv,
"BOUND_P1", -1,
"-999", NULL);
5951 scan_ctl(filename, argc, argv,
"BOUND_DPS", -1,
"-999", NULL);
5953 scan_ctl(filename, argc, argv,
"BOUND_DZS", -1,
"-999", NULL);
5955 scan_ctl(filename, argc, argv,
"BOUND_ZETAS", -1,
"-999", NULL);
5957 (int)
scan_ctl(filename, argc, argv,
"BOUND_PBL", -1,
"0", NULL);
5961 if (strcasecmp(ctl->
species,
"CF2Cl2") == 0) {
5965 }
else if (strcasecmp(ctl->
species,
"CFCl3") == 0) {
5969 }
else if (strcasecmp(ctl->
species,
"CH4") == 0) {
5976 }
else if (strcasecmp(ctl->
species,
"CO") == 0) {
5985 }
else if (strcasecmp(ctl->
species,
"CO2") == 0) {
5989 }
else if (strcasecmp(ctl->
species,
"H2O") == 0) {
5991 }
else if (strcasecmp(ctl->
species,
"N2O") == 0) {
5995 }
else if (strcasecmp(ctl->
species,
"NH3") == 0) {
6002 }
else if (strcasecmp(ctl->
species,
"HNO3") == 0) {
6006 }
else if (strcasecmp(ctl->
species,
"NO") == 0) {
6015 }
else if (strcasecmp(ctl->
species,
"NO2") == 0) {
6024 }
else if (strcasecmp(ctl->
species,
"O3") == 0) {
6031 }
else if (strcasecmp(ctl->
species,
"SF6") == 0) {
6035 }
else if (strcasecmp(ctl->
species,
"SO2") == 0) {
6048 sprintf(defstr,
"%g", ctl->
molmass);
6049 ctl->
molmass =
scan_ctl(filename, argc, argv,
"MOLMASS", -1, defstr, NULL);
6054 (int)
scan_ctl(filename, argc, argv,
"OH_CHEM_REACTION", -1, defstr,
6056 for (
int ip = 0; ip < 4; ip++) {
6057 sprintf(defstr,
"%g", ctl->
oh_chem[ip]);
6059 scan_ctl(filename, argc, argv,
"OH_CHEM", ip, defstr, NULL);
6062 scan_ctl(filename, argc, argv,
"OH_CHEM_BETA", -1,
"0", NULL);
6066 (int)
scan_ctl(filename, argc, argv,
"H2O2_CHEM_REACTION", -1,
"0", NULL);
6070 (int)
scan_ctl(filename, argc, argv,
"KPP_CHEM", -1,
"0", NULL);
6071 ctl->
dt_kpp =
scan_ctl(filename, argc, argv,
"DT_KPP", -1,
"1800", NULL);
6075 (int)
scan_ctl(filename, argc, argv,
"TRACER_CHEM", -1,
"0", NULL);
6078 for (
int ip = 0; ip < 2; ip++) {
6081 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_H", ip, defstr, NULL);
6083 for (
int ip = 0; ip < 1; ip++) {
6086 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_H", ip, defstr, NULL);
6089 scan_ctl(filename, argc, argv,
"WET_DEPO_SO2_PH", -1,
"0", NULL);
6091 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_A", -1,
"0", NULL);
6093 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_B", -1,
"0", NULL);
6095 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_A", -1,
"0", NULL);
6097 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_B", -1,
"0", NULL);
6099 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 0,
"0.5", NULL);
6101 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 1,
"0.36", NULL);
6103 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_RET_RATIO", -1,
"1", NULL);
6105 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_RET_RATIO", -1,
"1", NULL);
6109 scan_ctl(filename, argc, argv,
"DRY_DEPO_VDEP", -1,
"0", NULL);
6111 scan_ctl(filename, argc, argv,
"DRY_DEPO_DP", -1,
"30", NULL);
6114 scan_ctl(filename, argc, argv,
"CLIM_PHOTO", -1,
6115 "../../data/clams_photolysis_rates.nc", ctl->
clim_photo);
6116 scan_ctl(filename, argc, argv,
"CLIM_HNO3_FILENAME", -1,
6118 scan_ctl(filename, argc, argv,
"CLIM_OH_FILENAME", -1,
6120 scan_ctl(filename, argc, argv,
"CLIM_H2O2_FILENAME", -1,
6122 scan_ctl(filename, argc, argv,
"CLIM_HO2_FILENAME", -1,
6124 scan_ctl(filename, argc, argv,
"CLIM_O1D_FILENAME", -1,
6126 scan_ctl(filename, argc, argv,
"CLIM_CCL4_TIMESERIES", -1,
6128 scan_ctl(filename, argc, argv,
"CLIM_CCL3F_TIMESERIES", -1,
6130 scan_ctl(filename, argc, argv,
"CLIM_CCL2F2_TIMESERIES", -1,
6132 scan_ctl(filename, argc, argv,
"CLIM_N2O_TIMESERIES", -1,
6134 scan_ctl(filename, argc, argv,
"CLIM_SF6_TIMESERIES", -1,
6139 scan_ctl(filename, argc, argv,
"MIXING_DT", -1,
"3600.", NULL);
6141 scan_ctl(filename, argc, argv,
"MIXING_TROP", -1,
"-999", NULL);
6143 scan_ctl(filename, argc, argv,
"MIXING_STRAT", -1,
"-999", NULL);
6145 scan_ctl(filename, argc, argv,
"MIXING_Z0", -1,
"-5", NULL);
6147 scan_ctl(filename, argc, argv,
"MIXING_Z1", -1,
"85", NULL);
6149 (int)
scan_ctl(filename, argc, argv,
"MIXING_NZ", -1,
"90", NULL);
6151 scan_ctl(filename, argc, argv,
"MIXING_LON0", -1,
"-180", NULL);
6153 scan_ctl(filename, argc, argv,
"MIXING_LON1", -1,
"180", NULL);
6155 (int)
scan_ctl(filename, argc, argv,
"MIXING_NX", -1,
"360", NULL);
6157 scan_ctl(filename, argc, argv,
"MIXING_LAT0", -1,
"-90", NULL);
6159 scan_ctl(filename, argc, argv,
"MIXING_LAT1", -1,
"90", NULL);
6161 (int)
scan_ctl(filename, argc, argv,
"MIXING_NY", -1,
"180", NULL);
6165 scan_ctl(filename, argc, argv,
"CHEMGRID_Z0", -1,
"-5", NULL);
6167 scan_ctl(filename, argc, argv,
"CHEMGRID_Z1", -1,
"85", NULL);
6169 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NZ", -1,
"90", NULL);
6171 scan_ctl(filename, argc, argv,
"CHEMGRID_LON0", -1,
"-180", NULL);
6173 scan_ctl(filename, argc, argv,
"CHEMGRID_LON1", -1,
"180", NULL);
6175 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NX", -1,
"360", NULL);
6177 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT0", -1,
"-90", NULL);
6179 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT1", -1,
"90", NULL);
6181 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NY", -1,
"180", NULL);
6186 scan_ctl(filename, argc, argv,
"TDEC_STRAT", -1,
"0", NULL);
6189 ctl->
psc_h2o =
scan_ctl(filename, argc, argv,
"PSC_H2O", -1,
"4e-6", NULL);
6191 scan_ctl(filename, argc, argv,
"PSC_HNO3", -1,
"9e-9", NULL);
6197 scan_ctl(filename, argc, argv,
"ATM_DT_OUT", -1,
"86400", NULL);
6199 (int)
scan_ctl(filename, argc, argv,
"ATM_FILTER", -1,
"0", NULL);
6201 (int)
scan_ctl(filename, argc, argv,
"ATM_STRIDE", -1,
"1", NULL);
6203 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE", -1,
"0", NULL);
6205 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE_OUT", -1,
"-1", NULL);
6209 (int)
scan_ctl(filename, argc, argv,
"ATM_NC_LEVEL", -1,
"0", NULL);
6210 for (
int iq = 0; iq < ctl->
nq; iq++)
6212 (
int)
scan_ctl(filename, argc, argv,
"ATM_NC_QUANT", iq,
"0", NULL);
6214 (int)
scan_ctl(filename, argc, argv,
"OBS_TYPE", -1,
"0", NULL);
6220 scan_ctl(filename, argc, argv,
"CSI_DT_OUT", -1,
"86400", NULL);
6223 scan_ctl(filename, argc, argv,
"CSI_OBSMIN", -1,
"0", NULL);
6225 scan_ctl(filename, argc, argv,
"CSI_MODMIN", -1,
"0", NULL);
6226 ctl->
csi_z0 =
scan_ctl(filename, argc, argv,
"CSI_Z0", -1,
"-5", NULL);
6227 ctl->
csi_z1 =
scan_ctl(filename, argc, argv,
"CSI_Z1", -1,
"85", NULL);
6228 ctl->
csi_nz = (int)
scan_ctl(filename, argc, argv,
"CSI_NZ", -1,
"1", NULL);
6230 scan_ctl(filename, argc, argv,
"CSI_LON0", -1,
"-180", NULL);
6231 ctl->
csi_lon1 =
scan_ctl(filename, argc, argv,
"CSI_LON1", -1,
"180", NULL);
6233 (int)
scan_ctl(filename, argc, argv,
"CSI_NX", -1,
"360", NULL);
6234 ctl->
csi_lat0 =
scan_ctl(filename, argc, argv,
"CSI_LAT0", -1,
"-90", NULL);
6235 ctl->
csi_lat1 =
scan_ctl(filename, argc, argv,
"CSI_LAT1", -1,
"90", NULL);
6237 (int)
scan_ctl(filename, argc, argv,
"CSI_NY", -1,
"180", NULL);
6240 ctl->
nens = (int)
scan_ctl(filename, argc, argv,
"NENS", -1,
"0", NULL);
6243 scan_ctl(filename, argc, argv,
"ENS_DT_OUT", -1,
"86400", NULL);
6246 scan_ctl(filename, argc, argv,
"GRID_BASENAME", -1,
"-",
6251 scan_ctl(filename, argc, argv,
"GRID_DT_OUT", -1,
"86400", NULL);
6253 (int)
scan_ctl(filename, argc, argv,
"GRID_SPARSE", -1,
"0", NULL);
6255 (int)
scan_ctl(filename, argc, argv,
"GRID_NC_LEVEL", -1,
"0", NULL);
6256 for (
int iq = 0; iq < ctl->
nq; iq++)
6258 (
int)
scan_ctl(filename, argc, argv,
"GRID_NC_QUANT", iq,
"0", NULL);
6260 (int)
scan_ctl(filename, argc, argv,
"GRID_STDDEV", -1,
"0", NULL);
6261 ctl->
grid_z0 =
scan_ctl(filename, argc, argv,
"GRID_Z0", -1,
"-5", NULL);
6262 ctl->
grid_z1 =
scan_ctl(filename, argc, argv,
"GRID_Z1", -1,
"85", NULL);
6264 (int)
scan_ctl(filename, argc, argv,
"GRID_NZ", -1,
"1", NULL);
6266 scan_ctl(filename, argc, argv,
"GRID_LON0", -1,
"-180", NULL);
6268 scan_ctl(filename, argc, argv,
"GRID_LON1", -1,
"180", NULL);
6270 (int)
scan_ctl(filename, argc, argv,
"GRID_NX", -1,
"360", NULL);
6272 scan_ctl(filename, argc, argv,
"GRID_LAT0", -1,
"-90", NULL);
6274 scan_ctl(filename, argc, argv,
"GRID_LAT1", -1,
"90", NULL);
6276 (int)
scan_ctl(filename, argc, argv,
"GRID_NY", -1,
"180", NULL);
6278 (int)
scan_ctl(filename, argc, argv,
"GRID_TYPE", -1,
"0", NULL);
6281 scan_ctl(filename, argc, argv,
"PROF_BASENAME", -1,
"-",
6284 ctl->
prof_z0 =
scan_ctl(filename, argc, argv,
"PROF_Z0", -1,
"0", NULL);
6285 ctl->
prof_z1 =
scan_ctl(filename, argc, argv,
"PROF_Z1", -1,
"60", NULL);
6287 (int)
scan_ctl(filename, argc, argv,
"PROF_NZ", -1,
"60", NULL);
6289 scan_ctl(filename, argc, argv,
"PROF_LON0", -1,
"-180", NULL);
6291 scan_ctl(filename, argc, argv,
"PROF_LON1", -1,
"180", NULL);
6293 (int)
scan_ctl(filename, argc, argv,
"PROF_NX", -1,
"360", NULL);
6295 scan_ctl(filename, argc, argv,
"PROF_LAT0", -1,
"-90", NULL);
6297 scan_ctl(filename, argc, argv,
"PROF_LAT1", -1,
"90", NULL);
6299 (int)
scan_ctl(filename, argc, argv,
"PROF_NY", -1,
"180", NULL);
6302 scan_ctl(filename, argc, argv,
"SAMPLE_BASENAME", -1,
"-",
6304 scan_ctl(filename, argc, argv,
"SAMPLE_KERNEL", -1,
"-",
6306 scan_ctl(filename, argc, argv,
"SAMPLE_OBSFILE", -1,
"-",
6309 scan_ctl(filename, argc, argv,
"SAMPLE_DX", -1,
"50", NULL);
6311 scan_ctl(filename, argc, argv,
"SAMPLE_DZ", -1,
"-999", NULL);
6314 scan_ctl(filename, argc, argv,
"STAT_BASENAME", -1,
"-",
6318 ctl->
stat_r =
scan_ctl(filename, argc, argv,
"STAT_R", -1,
"50", NULL);
6320 scan_ctl(filename, argc, argv,
"STAT_T0", -1,
"-1e100", NULL);
6321 ctl->
stat_t1 =
scan_ctl(filename, argc, argv,
"STAT_T1", -1,
"1e100", NULL);
6326 scan_ctl(filename, argc, argv,
"VTK_DT_OUT", -1,
"86400", NULL);
6328 (int)
scan_ctl(filename, argc, argv,
"VTK_STRIDE", -1,
"1", NULL);
6330 scan_ctl(filename, argc, argv,
"VTK_SCALE", -1,
"1.0", NULL);
6332 scan_ctl(filename, argc, argv,
"VTK_OFFSET", -1,
"0.0", NULL);
6334 (int)
scan_ctl(filename, argc, argv,
"VTK_SPHERE", -1,
"0", NULL);
6337 ctl->
dd = (int)
scan_ctl(filename, argc, argv,
"DD", -1,
"0", NULL);
6339 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_MERIDIONAL", -1,
6340 (ctl->
dd == 1) ?
"2" :
"1", NULL);
6342 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_ZONAL", -1,
6343 (ctl->
dd == 1) ?
"2" :
"1", NULL);
6346 else if (ctl->
dd == 1)
6347 ERRMSG(
"Please provide zonal and meridional subdomain numbers!")
6349 (int)
scan_ctl(filename, argc, argv,
"DD_NBR_NEIGHBOURS", -1,
"8",
6352 (int)
scan_ctl(filename, argc, argv,
"DD_HALOS_SIZE", -1,
"1", NULL);
6358 const char *filename,
6365 LOG(1,
"Read meteo data: %s", filename);
6371 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
6399 ERRMSG(
"MET_TYPE not implemented!");
6453 LOG(2,
"Broadcast data on rank %d...", rank);
6584 ERRMSG(
"DD initialized, but model is compiled without DD.")
6593 ERRMSG(
"Code was compiled without KPP!");
6626#pragma acc update device(ctl[:1])
6630 if (cache != NULL) {
6633#pragma acc update device(cache[:1])
6640#pragma acc update device(clim[:1])
6647 met_t *met0up = *met0;
6648#pragma acc update device(met0up[:1])
6655 met_t *met1up = *met1;
6656#pragma acc update device(met1up[:1])
6663#pragma acc update device(atm[:1])
6682#pragma acc update host(ctl[:1])
6686 if (cache != NULL) {
6689#pragma acc update host(cache[:1])
6696#pragma acc update host(clim[:1])
6703 met_t *met0up = *met0;
6704#pragma acc update host(met0up[:1])
6711 met_t *met1up = *met1;
6712#pragma acc update host(met1up[:1])
6719#pragma acc update host(atm[:1])
6727 const char *filename,
6736 LOG(1,
"Write atmospheric data: %s", filename);
6760 ERRMSG(
"Atmospheric data type not supported!");
6764 LOG(2,
"Number of particles: %d", atm->
np);
6765 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
6766 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
6767 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
6768 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
6769 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
6770 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
6771 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
6772 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
6773 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
6774 for (
int iq = 0; iq < ctl->
nq; iq++) {
6776 sprintf(msg,
"Quantity %s range: %s ... %s %s",
6779 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
6780 LOG(2, msg, mini, maxi);
6787 const char *filename,
6795 LOG(1,
"Write meteo data: %s", filename);
6800 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
6804 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
6808 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
6812 ERRMSG(
"MPTRAC was compiled without SZ3 compression!");
6825 ERRMSG(
"MET_TYPE not implemented!");
6831 const char *dirname,
6838 char ext[10], filename[2 *
LEN];
6842 int year, mon, day, hour, min, sec;
6845 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
6860 sprintf(ext,
"tab");
6862 sprintf(ext,
"bin");
6865 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6866 dirname, ctl->
atm_basename, year, mon, day, hour, min, ext);
6872 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6875 write_grid(filename, ctl, met0, met1, atm, t);
6880 sprintf(filename,
"%s/%s.tab", dirname, ctl->
csi_basename);
6886 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.tab",
6887 dirname, ctl->
ens_basename, year, mon, day, hour, min);
6893 sprintf(filename,
"%s/%s.tab", dirname, ctl->
prof_basename);
6894 write_prof(filename, ctl, met0, met1, atm, t);
6905 sprintf(filename,
"%s/%s.tab", dirname, ctl->
stat_basename);
6914 sprintf(filename,
"%s/%s_%05d.vtk", dirname, ctl->
vtk_basename, ++nvtk);
6924 const double hno3) {
6927 const double h2o_help =
MAX(h2o, 0.1e-6);
6930 const double p_hno3 = hno3 * p / 1.333224;
6931 const double p_h2o = h2o_help * p / 1.333224;
6932 const double a = 0.009179 - 0.00088 * log10(p_h2o);
6933 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
6934 const double c = -11397.0 / a;
6935 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
6936 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
6954 const double p0 = pbl;
6957 if (atm->
p[ip] > p0)
6959 else if (atm->
p[ip] < p1)
6962 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
6968 const char *filename,
6974 if (!(in = fopen(filename,
"r"))) {
6975 WARN(
"Cannot open file!");
6981 while (fgets(line,
LEN, in)) {
6985 TOK(line, tok,
"%lg", atm->
time[atm->
np]);
6986 TOK(NULL, tok,
"%lg", atm->
p[atm->
np]);
6987 TOK(NULL, tok,
"%lg", atm->
lon[atm->
np]);
6988 TOK(NULL, tok,
"%lg", atm->
lat[atm->
np]);
6989 for (
int iq = 0; iq < ctl->
nq; iq++)
6990 TOK(NULL, tok,
"%lg", atm->
q[iq][atm->
np]);
6993 atm->
p[atm->
np] =
P(atm->
p[atm->
np]);
6996 if ((++atm->
np) >
NP)
6997 ERRMSG(
"Too many data points!");
7010 const char *filename,
7016 if (!(in = fopen(filename,
"r")))
7021 FREAD(&version,
int,
7025 ERRMSG(
"Wrong version of binary data!");
7043 for (
int iq = 0; iq < ctl->
nq; iq++)
7044 FREAD(atm->
q[iq],
double,
7054 ERRMSG(
"Error while reading binary data!");
7066 const char *filename,
7073 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
7080 if (nc_inq_varid(ncid,
"TIME_INIT", &varid) == NC_NOERR) {
7081 NC(nc_get_var_double(ncid, varid, atm->
time));
7083 WARN(
"TIME_INIT not found use time instead!");
7086 for (
int ip = 0; ip < atm->
np; ip++) {
7087 atm->
time[ip] = time_init;
7099 if (nc_inq_varid(ncid,
"PRESS_INIT", &varid) == NC_NOERR) {
7100 NC(nc_get_var_double(ncid, varid, atm->
p));
7102 WARN(
"PRESS_INIT not found use PRESS instead!");
7103 nc_inq_varid(ncid,
"PRESS", &varid);
7104 NC(nc_get_var_double(ncid, varid, atm->
p));
7109 for (
int iq = 0; iq < ctl->
nq; iq++)
7126 const char *filename,
7133 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
7146 for (
int iq = 0; iq < ctl->
nq; iq++)
7159 const char *filename,
7165 LOG(1,
"Read photolysis rates: %s", filename);
7168 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
7169 WARN(
"Photolysis rate data are missing!");
7176 if (photo->
p[0] < photo->
p[1])
7177 ERRMSG(
"Pressure data are not descending!");
7182 if (photo->
o3c[0] > photo->
o3c[1])
7183 ERRMSG(
"Total column ozone data are not ascending!");
7188 if (photo->
sza[0] > photo->
sza[1])
7189 ERRMSG(
"Solar zenith angle data are not ascending!");
7206 LOG(2,
"Number of pressure levels: %d", photo->
np);
7207 LOG(2,
"Altitude levels: %g, %g ... %g km",
7208 Z(photo->
p[0]),
Z(photo->
p[1]),
Z(photo->
p[photo->
np - 1]));
7209 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
7210 photo->
p[0], photo->
p[1], photo->
p[photo->
np - 1]);
7211 LOG(2,
"Number of solar zenith angles: %d", photo->
nsza);
7212 LOG(2,
"Solar zenith angles: %g, %g ... %g deg",
7215 LOG(2,
"Number of total column ozone values: %d", photo->
no3c);
7216 LOG(2,
"Total column ozone: %g, %g ... %g DU",
7218 LOG(2,
"N2O photolysis rate: %g, %g ... %g s**-1",
7219 photo->
n2o[0][0][0], photo->
n2o[1][0][0],
7220 photo->
n2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7221 LOG(2,
"CCl4 photolysis rate: %g, %g ... %g s**-1",
7222 photo->
ccl4[0][0][0], photo->
ccl4[1][0][0],
7224 LOG(2,
"CFC-11 photolysis rate: %g, %g ... %g s**-1",
7225 photo->
ccl3f[0][0][0], photo->
ccl3f[1][0][0],
7227 LOG(2,
"CFC-12 photolysis rate: %g, %g ... %g s**-1",
7230 LOG(2,
"O2 photolysis rate: %g, %g ... %g s**-1",
7231 photo->
o2[0][0][0], photo->
o2[1][0][0],
7232 photo->
o2[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7233 LOG(2,
"O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
7234 photo->
o3_1[0][0][0], photo->
o3_1[1][0][0],
7236 LOG(2,
"O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
7237 photo->
o3_2[0][0][0], photo->
o3_2[1][0][0],
7239 LOG(2,
"H2O2 photolysis rate: %g, %g ... %g s**-1",
7240 photo->
h2o2[0][0][0], photo->
h2o2[1][0][0],
7242 LOG(2,
"H2O photolysis rate: %g, %g ... %g s**-1",
7243 photo->
h2o[0][0][0], photo->
h2o[1][0][0],
7244 photo->
h2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7251 const char *varname,
7265 for (
int ip = 0; ip < photo->
np; ip++)
7266 for (
int is = 0; is < photo->
nsza; is++)
7267 for (
int io = 0; io < photo->
no3c; io++)
7278 const char *filename,
7282 LOG(1,
"Read climatological time series: %s", filename);
7286 if (!(in = fopen(filename,
"r"))) {
7287 WARN(
"Cannot open file!");
7294 while (fgets(line,
LEN, in))
7295 if (sscanf(line,
"%lg %lg", &ts->
time[nh], &ts->
vmr[nh]) == 2) {
7298 ts->
time[nh] = (ts->
time[nh] - 2000.0) * 365.25 * 86400.;
7301 if (nh > 0 && ts->
time[nh] <= ts->
time[nh - 1])
7302 ERRMSG(
"Time series must be ascending!");
7306 ERRMSG(
"Too many data points!");
7315 ERRMSG(
"Not enough data points!");
7318 LOG(2,
"Number of time steps: %d", ts->
ntime);
7319 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s", ts->
time[0], ts->
time[1],
7321 LOG(2,
"Volume mixing ratio range: %g ... %g ppv",
7322 gsl_stats_min(ts->
vmr, 1, (
size_t) nh), gsl_stats_max(ts->
vmr, 1,
7332 const char *filename,
7333 const char *varname,
7336 int ncid, varid, it, iy, iz, iz2, nt;
7338 double *help, varmin = 1e99, varmax = -1e99;
7341 LOG(1,
"Read %s data: %s", varname, filename);
7344 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
7345 WARN(
"%s climatology data are missing!", varname);
7352 if (zm->
p[0] < zm->
p[1])
7353 ERRMSG(
"Pressure data are not descending!");
7358 if (zm->
lat[0] > zm->
lat[1])
7359 ERRMSG(
"Latitude data are not ascending!");
7363 zm->
time[0] = 1209600.00;
7364 zm->
time[1] = 3888000.00;
7365 zm->
time[2] = 6393600.00;
7366 zm->
time[3] = 9072000.00;
7367 zm->
time[4] = 11664000.00;
7368 zm->
time[5] = 14342400.00;
7369 zm->
time[6] = 16934400.00;
7370 zm->
time[7] = 19612800.00;
7371 zm->
time[8] = 22291200.00;
7372 zm->
time[9] = 24883200.00;
7373 zm->
time[10] = 27561600.00;
7374 zm->
time[11] = 30153600.00;
7383 for (it = 0; it < zm->
ntime; it++)
7384 for (iz = 0; iz < zm->
np; iz++)
7385 for (iy = 0; iy < zm->
nlat; iy++)
7390 for (it = 0; it < zm->
ntime; it++)
7391 for (iy = 0; iy < zm->
nlat; iy++)
7392 for (iz = 0; iz < zm->
np; iz++) {
7393 if (zm->
vmr[it][iz][iy] < 0) {
7394 for (iz2 = 0; iz2 < zm->
np; iz2++)
7395 if (zm->
vmr[it][iz2][iy] >= 0) {
7396 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
7399 for (iz2 = zm->
np - 1; iz2 >= 0; iz2--)
7400 if (zm->
vmr[it][iz2][iy] >= 0) {
7401 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
7405 varmin =
MIN(varmin, zm->
vmr[it][iz][iy]);
7406 varmax =
MAX(varmax, zm->
vmr[it][iz][iy]);
7413 LOG(2,
"Number of time steps: %d", zm->
ntime);
7414 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
7416 LOG(2,
"Number of pressure levels: %d", zm->
np);
7417 LOG(2,
"Altitude levels: %g, %g ... %g km",
7418 Z(zm->
p[0]),
Z(zm->
p[1]),
Z(zm->
p[zm->
np - 1]));
7419 LOG(2,
"Pressure levels: %g, %g ... %g hPa", zm->
p[0],
7420 zm->
p[1], zm->
p[zm->
np - 1]);
7421 LOG(2,
"Number of latitudes: %d", zm->
nlat);
7422 LOG(2,
"Latitudes: %g, %g ... %g deg",
7424 LOG(2,
"%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
7431 const char *filename,
7437 LOG(1,
"Read kernel function: %s", filename);
7441 if (!(in = fopen(filename,
"r")))
7442 ERRMSG(
"Cannot open file!");
7447 while (fgets(line,
LEN, in))
7448 if (sscanf(line,
"%lg %lg", &kz[n], &kw[n]) == 2) {
7449 if (n > 0 && kz[n] < kz[n - 1])
7450 ERRMSG(
"Height levels must be ascending!");
7452 ERRMSG(
"Too many height levels!");
7461 ERRMSG(
"Not enough height levels!");
7464 const double kmax = gsl_stats_max(kw, 1, (
size_t) n);
7465 for (
int iz = 0; iz < n; iz++)
7472 const char *filename,
7480 int year, mon, day, hour, min, sec;
7486 if (!(in = fopen(filename,
"r"))) {
7487 WARN(
"Cannot open file!");
7493 FREAD(&met_type,
int,
7497 ERRMSG(
"Wrong MET_TYPE of binary data!");
7501 FREAD(&version,
int,
7505 ERRMSG(
"Wrong version of binary data!");
7511 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
7512 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
7513 met->
time, year, mon, day, hour, min);
7514 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
7515 || day < 1 || day > 31 || hour < 0 || hour > 23)
7516 ERRMSG(
"Error while reading time!");
7522 LOG(2,
"Number of longitudes: %d", met->
nx);
7523 if (met->
nx < 2 || met->
nx >
EX)
7524 ERRMSG(
"Number of longitudes out of range!");
7529 LOG(2,
"Number of latitudes: %d", met->
ny);
7530 if (met->
ny < 2 || met->
ny >
EY)
7531 ERRMSG(
"Number of latitudes out of range!");
7536 LOG(2,
"Number of levels: %d", met->
np);
7537 if (met->
np < 2 || met->
np >
EP)
7538 ERRMSG(
"Number of levels out of range!");
7544 LOG(2,
"Longitudes: %g, %g ... %g deg",
7550 LOG(2,
"Latitudes: %g, %g ... %g deg",
7556 LOG(2,
"Altitude levels: %g, %g ... %g km",
7557 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
7558 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
7559 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
7608 ERRMSG(
"Error while reading binary data!");
7623 const char *varname) {
7632 LOG(2,
"Read 2-D variable: %s (uncompressed)", varname);
7634 (
size_t) (met->
nx * met->
ny),
7638 for (
int ix = 0; ix < met->
nx; ix++)
7639 for (
int iy = 0; iy < met->
ny; iy++)
7640 var[ix][iy] = help[
ARRAY_2D(ix, iy, met->
ny)];
7653 const char *varname,
7654 const float bound_min,
7655 const float bound_max) {
7665 LOG(2,
"Read 3-D variable: %s (uncompressed)", varname);
7667 (
size_t) (met->
nx * met->
ny * met->
np),
7674 (
size_t) met->
np, 1, in);
7680 FREAD(&precision,
int,
7685 FREAD(&tolerance,
double,
7692 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
7702 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
7710 (
size_t) met->
np, 1, in);
7712 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
7720 FREAD(&precision,
int,
7725 FREAD(&tolerance,
double,
7732 ERRMSG(
"MPTRAC was compiled without sz3 compression!");
7737#pragma omp parallel for default(shared) collapse(2)
7738 for (
int ix = 0; ix < met->
nx; ix++)
7739 for (
int iy = 0; iy < met->
ny; iy++)
7740 for (
int ip = 0; ip < met->
np; ip++) {
7741 var[ix][iy][ip] = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
7742 if (var[ix][iy][ip] < bound_min)
7743 var[ix][iy][ip] = bound_min;
7744 else if (var[ix][iy][ip] > bound_max)
7745 var[ix][iy][ip] = bound_max;
7765 LOG(2,
"Calculate CAPE...");
7768 const double pfac = 1.01439, dz0 =
RI /
MA /
G0 * log(pfac);
7771#pragma omp parallel for default(shared) collapse(2)
7772 for (
int ix = 0; ix < met->
nx; ix++)
7773 for (
int iy = 0; iy < met->
ny; iy++) {
7777 double h2o = 0, t, theta = 0;
7778 double pbot =
MIN(met->
ps[ix][iy], met->
p[0]);
7779 double ptop = pbot - 50.;
7780 for (
int ip = 0; ip < met->
np; ip++) {
7781 if (met->
p[ip] <= pbot) {
7782 theta +=
THETA(met->
p[ip], met->
t[ix][iy][ip]);
7783 h2o += met->
h2o[ix][iy][ip];
7786 if (met->
p[ip] < ptop && n > 0)
7793 met->
plcl[ix][iy] = NAN;
7794 met->
plfc[ix][iy] = NAN;
7795 met->
pel[ix][iy] = NAN;
7796 met->
cape[ix][iy] = NAN;
7797 met->
cin[ix][iy] = NAN;
7803 pbot = met->
ps[ix][iy];
7805 met->
plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
7806 t = theta / pow(1000. / met->
plcl[ix][iy], 0.286);
7807 if (
RH(met->
plcl[ix][iy], t, h2o) > 100.)
7808 ptop = met->
plcl[ix][iy];
7810 pbot = met->
plcl[ix][iy];
7811 }
while (pbot - ptop > 0.1);
7815 double dcape, dz, h2o_env, t_env;
7816 double p = met->
ps[ix][iy];
7817 met->
cape[ix][iy] = met->
cin[ix][iy] = 0;
7819 dz = dz0 *
TVIRT(t, h2o);
7821 t = theta / pow(1000. / p, 0.286);
7825 &h2o_env, ci, cw, 0);
7826 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
7827 TVIRT(t_env, h2o_env) * dz;
7829 met->
cin[ix][iy] += fabsf((
float) dcape);
7830 }
while (p > met->
plcl[ix][iy]);
7835 p = met->
plcl[ix][iy];
7836 t = theta / pow(1000. / p, 0.286);
7839 dz = dz0 *
TVIRT(t, h2o);
7842 double psat =
PSAT(t);
7843 h2o = psat / (p - (1. -
EPS) * psat);
7847 &h2o_env, ci, cw, 0);
7848 double dcape_old = dcape;
7849 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
7850 TVIRT(t_env, h2o_env) * dz;
7852 met->
cape[ix][iy] += (float) dcape;
7853 if (!isfinite(met->
plfc[ix][iy]))
7854 met->
plfc[ix][iy] = (
float) p;
7855 }
else if (dcape_old > 0)
7856 met->
pel[ix][iy] = (float) p;
7857 if (dcape < 0 && !isfinite(met->
plfc[ix][iy]))
7858 met->
cin[ix][iy] += fabsf((
float) dcape);
7862 if (!isfinite(met->
plfc[ix][iy]))
7863 met->
cin[ix][iy] = NAN;
7874 LOG(2,
"Calculate cloud data...");
7877 const double ccmin = 0.01, cwmin = 1e-6;
7880#pragma omp parallel for default(shared) collapse(2)
7881 for (
int ix = 0; ix < met->
nx; ix++)
7882 for (
int iy = 0; iy < met->
ny; iy++) {
7885 met->
pct[ix][iy] = NAN;
7886 met->
pcb[ix][iy] = NAN;
7887 met->
cl[ix][iy] = 0;
7890 for (
int ip = 0; ip < met->
np - 1; ip++) {
7893 if (met->
p[ip] > met->
ps[ix][iy] || met->
p[ip] <
P(20.))
7897 if (met->
cc[ix][iy][ip] > ccmin
7898 && (met->
lwc[ix][iy][ip] > cwmin
7899 || met->
rwc[ix][iy][ip] > cwmin
7900 || met->
iwc[ix][iy][ip] > cwmin
7901 || met->
swc[ix][iy][ip] > cwmin)) {
7905 = (float) (0.5 * (met->
p[ip] + (
float) met->
p[ip + 1]));
7908 if (!isfinite(met->
pcb[ix][iy]))
7910 = (
float) (0.5 * (met->
p[ip] + met->
p[
MAX(ip - 1, 0)]));
7914 met->
cl[ix][iy] += (float)
7915 (0.5 * (met->
lwc[ix][iy][ip] + met->
lwc[ix][iy][ip + 1]
7916 + met->
rwc[ix][iy][ip] + met->
rwc[ix][iy][ip + 1]
7917 + met->
iwc[ix][iy][ip] + met->
iwc[ix][iy][ip + 1]
7918 + met->
swc[ix][iy][ip] + met->
swc[ix][iy][ip + 1])
7919 * 100. * (met->
p[ip] - met->
p[ip + 1]) /
G0);
7937 SELECT_TIMER(
"READ_MET_DETREND",
"METPROC", NVTX_READ);
7938 LOG(2,
"Detrend meteo data...");
7945 const double tssq = 2. *
SQR(sigma);
7948 int sy = (int) (3. *
DY2DEG(sigma) / fabs(met->
lat[1] - met->
lat[0]));
7952#pragma omp parallel for default(shared) collapse(2)
7953 for (
int ix = 0; ix < met->
nx; ix++) {
7954 for (
int iy = 0; iy < met->
ny; iy++) {
7962 (int) (3. *
DX2DEG(sigma, met->
lat[iy]) /
7963 fabs(met->
lon[1] - met->
lon[0]));
7968 for (
int ip = 0; ip < met->
np; ip++) {
7969 help->
t[ix][iy][ip] = 0;
7970 help->
u[ix][iy][ip] = 0;
7971 help->
v[ix][iy][ip] = 0;
7972 help->
w[ix][iy][ip] = 0;
7976 for (
int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
7980 else if (ix3 >= met->
nx)
7982 for (
int iy2 =
MAX(iy - sy, 0);
7983 iy2 <=
MIN(iy + sy, met->
ny - 1); iy2++) {
7990 const float w = (float) exp(-
DIST2(x0, x1) / tssq);
7994 for (
int ip = 0; ip < met->
np; ip++) {
7995 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip];
7996 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip];
7997 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip];
7998 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip];
8004 for (
int ip = 0; ip < met->
np; ip++) {
8005 help->
t[ix][iy][ip] /= wsum;
8006 help->
u[ix][iy][ip] /= wsum;
8007 help->
v[ix][iy][ip] /= wsum;
8008 help->
w[ix][iy][ip] /= wsum;
8014#pragma omp parallel for default(shared) collapse(3)
8015 for (
int ix = 0; ix < met->
nx; ix++)
8016 for (
int iy = 0; iy < met->
ny; iy++)
8017 for (
int ip = 0; ip < met->
np; ip++) {
8018 met->
t[ix][iy][ip] -= help->
t[ix][iy][ip];
8019 met->
u[ix][iy][ip] -= help->
u[ix][iy][ip];
8020 met->
v[ix][iy][ip] -= help->
v[ix][iy][ip];
8021 met->
w[ix][iy][ip] -= help->
w[ix][iy][ip];
8034 SELECT_TIMER(
"READ_MET_EXTRAPOLATE",
"METPROC", NVTX_READ);
8035 LOG(2,
"Extrapolate meteo data...");
8038#pragma omp parallel for default(shared) collapse(2)
8039 for (
int ix = 0; ix < met->
nx; ix++)
8040 for (
int iy = 0; iy < met->
ny; iy++) {
8044 for (ip0 = met->
np - 1; ip0 >= 0; ip0--)
8045 if (!isfinite(met->
t[ix][iy][ip0])
8046 || !isfinite(met->
u[ix][iy][ip0])
8047 || !isfinite(met->
v[ix][iy][ip0])
8048 || !isfinite(met->
w[ix][iy][ip0]))
8052 for (
int ip = ip0; ip >= 0; ip--) {
8053 met->
t[ix][iy][ip] = met->
t[ix][iy][ip + 1];
8054 met->
u[ix][iy][ip] = met->
u[ix][iy][ip + 1];
8055 met->
v[ix][iy][ip] = met->
v[ix][iy][ip + 1];
8056 met->
w[ix][iy][ip] = met->
w[ix][iy][ip + 1];
8057 met->
h2o[ix][iy][ip] = met->
h2o[ix][iy][ip + 1];
8058 met->
o3[ix][iy][ip] = met->
o3[ix][iy][ip + 1];
8059 met->
lwc[ix][iy][ip] = met->
lwc[ix][iy][ip + 1];
8060 met->
rwc[ix][iy][ip] = met->
rwc[ix][iy][ip + 1];
8061 met->
iwc[ix][iy][ip] = met->
iwc[ix][iy][ip + 1];
8062 met->
swc[ix][iy][ip] = met->
swc[ix][iy][ip + 1];
8063 met->
cc[ix][iy][ip] = met->
cc[ix][iy][ip + 1];
8082 LOG(2,
"Calculate geopotential heights...");
8089#pragma omp parallel for default(shared)
8090 for (
int ip = 0; ip < met->
np; ip++)
8091 logp[ip] = log(met->
p[ip]);
8094#pragma omp parallel for default(shared) collapse(2)
8095 for (
int ix = 0; ix < met->
nx; ix++)
8096 for (
int iy = 0; iy < met->
ny; iy++) {
8099 const double zs = met->
zs[ix][iy];
8100 const double lnps = log(met->
ps[ix][iy]);
8104 const double ts =
LIN(met->
p[ip0], met->
t[ix][iy][ip0], met->
p[ip0 + 1],
8105 met->
t[ix][iy][ip0 + 1], met->
ps[ix][iy]);
8107 LIN(met->
p[ip0], met->
h2o[ix][iy][ip0], met->
p[ip0 + 1],
8108 met->
h2o[ix][iy][ip0 + 1], met->
ps[ix][iy]);
8111 met->
z[ix][iy][ip0 + 1]
8113 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
8114 met->
t[ix][iy][ip0 + 1], met->
h2o[ix][iy][ip0 + 1]));
8115 for (
int ip = ip0 + 2; ip < met->
np; ip++)
8117 = (
float) (met->
z[ix][iy][ip - 1] +
8118 ZDIFF(logp[ip - 1], met->
t[ix][iy][ip - 1],
8119 met->
h2o[ix][iy][ip - 1], logp[ip],
8120 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
8125 ZDIFF(lnps, ts, h2os, logp[ip0],
8126 met->
t[ix][iy][ip0], met->
h2o[ix][iy][ip0]));
8127 for (
int ip = ip0 - 1; ip >= 0; ip--)
8129 = (
float) (met->
z[ix][iy][ip + 1] +
8130 ZDIFF(logp[ip + 1], met->
t[ix][iy][ip + 1],
8131 met->
h2o[ix][iy][ip + 1], logp[ip],
8132 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
8136 if (dx == 0 || dy == 0)
8140 if (dx < 0 || dy < 0) {
8141 if (fabs(met->
lon[1] - met->
lon[0]) < 0.5) {
8151 float ws[dx + 1][dy + 1];
8152#pragma omp parallel for default(shared) collapse(2)
8153 for (
int ix = 0; ix <= dx; ix++)
8154 for (
int iy = 0; iy < dy; iy++)
8155 ws[ix][iy] = (1.0f - (
float) ix / (float) dx)
8156 * (1.0f - (float) iy / (
float) dy);
8159#pragma omp parallel for default(shared) collapse(3)
8160 for (
int ix = 0; ix < met->
nx; ix++)
8161 for (
int iy = 0; iy < met->
ny; iy++)
8162 for (
int ip = 0; ip < met->
np; ip++)
8163 help[
ARRAY_3D(ip, ix, met->
nx, iy, met->
ny)] = met->
z[ix][iy][ip];
8166#pragma omp parallel for default(shared) collapse(3)
8167 for (
int ip = 0; ip < met->
np; ip++)
8168 for (
int ix = 0; ix < met->
nx; ix++)
8169 for (
int iy = 0; iy < met->
ny; iy++) {
8170 float res = 0, wsum = 0;
8171 int iy0 =
MAX(iy - dy + 1, 0);
8172 int iy1 =
MIN(iy + dy - 1, met->
ny - 1);
8173 for (
int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
8177 else if (ix3 >= met->
nx)
8179 for (
int iy2 = iy0; iy2 <= iy1; ++iy2)
8180 if (isfinite(help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)])) {
8181 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
8182 res += w * help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)];
8187 met->
z[ix][iy][ip] = res / wsum;
8189 met->
z[ix][iy][ip] = NAN;
8199 const char *filename,
8205 char levname[
LEN], tstr[10];
8207 double rtime = 0, r, r2;
8209 int varid, ndims, dimids[NC_MAX_DIMS], year2, mon2, day2, hour2, min2, sec2,
8210 year, mon, day, hour, min, sec;
8216 LOG(2,
"Read meteo grid information...");
8225 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
8226 if (nc_inq_varid(ncid,
"time", &varid) == NC_NOERR) {
8227 NC(nc_get_var_double(ncid, varid, &rtime));
8228 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
8229 WARN(
"Time information in meteo file does not match filename!");
8231 WARN(
"Time information in meteo file is missing!");
8242 sprintf(tstr,
"19%.2s", &filename[strlen(filename) - 11]);
8244 sprintf(tstr,
"20%.2s", &filename[strlen(filename) - 11]);
8246 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 9]);
8248 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 7]);
8250 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 5]);
8256 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
8257 || day < 1 || day > 31 || hour < 0 || hour > 23)
8258 ERRMSG(
"Cannot read time from filename!");
8259 jsec2time(met->
time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
8260 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
8261 met->
time, year2, mon2, day2, hour2, min2);
8264 if (nc_inq_varid(ncid,
"u", &varid) != NC_NOERR)
8265 if (nc_inq_varid(ncid,
"U", &varid) != NC_NOERR)
8267 (
"Variable 'u' or 'U' not found, cannot determine vertical dimension!");
8269 NC(nc_inq_varndims(ncid, varid, &ndims));
8270 NC(nc_inq_vardimid(ncid, varid, dimids));
8274 (ncid, dimids[ctl->
met_convention == 0 ? 1 : 3], levname, &dimlen));
8275 }
else if (ndims == 3) {
8277 (ncid, dimids[ctl->
met_convention == 0 ? 0 : 2], levname, &dimlen));
8279 ERRMSG(
"Cannot determine vertical dimension!")
8280 met->
np = (int) dimlen;
8282 LOG(2,
"Number of levels: %d", met->
np);
8283 if (met->
np < 2 || met->
np >
EP)
8284 ERRMSG(
"Number of levels out of range!");
8290 LOG(2,
"Number of longitudes: %d", met->
nx);
8293 LOG(2,
"Number of latitudes: %d", met->
ny);
8297 LOG(2,
"Longitudes: %g, %g ... %g deg",
8300 LOG(2,
"Latitudes: %g, %g ... %g deg",
8313 for (
int ip = 0; ip < met->
np; ip++)
8315 LOG(2,
"Altitude levels: %g, %g ... %g km",
8316 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
8317 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
8318 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
8322 if (strcasecmp(levname,
"hybrid") == 0)
8334 ERRMSG(
"You need to specify MET_NLEV, MET_LEV_HYAM, and MET_LEV_HYBM!");
8335 for (
int ip = 0; ip < ctl->
met_nlev; ip++) {
8343 met->
eta[k] = met->
hyam[k] / 100000.0 + met->
hybm[k];
8345 ERRMSG(
"Eta levels must be ascending!");
8349 for (
int ix = 2; ix < met->
nx; ix++)
8351 (fabs(met->
lon[ix] - met->
lon[ix - 1]) -
8352 fabs(met->
lon[1] - met->
lon[0])) > 0.001)
8353 ERRMSG(
"No regular grid spacing in longitudes!");
8354 for (
int iy = 2; iy < met->
ny; iy++)
8356 (fabs(met->
lat[iy] - met->
lat[iy - 1]) -
8357 fabs(met->
lat[1] - met->
lat[0])) > 0.001) {
8358 WARN(
"No regular grid spacing in latitudes!");
8373 LOG(2,
"Read surface data...");
8377 (ncid,
"lnsp",
"LNSP", NULL, NULL, NULL, NULL, ctl, met, dd, met->
ps,
8379 for (
int ix = 0; ix < met->
nx; ix++)
8380 for (
int iy = 0; iy < met->
ny; iy++)
8381 met->
ps[ix][iy] = (
float) (exp(met->
ps[ix][iy]) / 100.);
8384 (ncid,
"ps",
"PS",
"sp",
"SP", NULL, NULL, ctl, met, dd, met->
ps,
8386 WARN(
"Cannot not read surface pressure data (use lowest level)!");
8387 for (
int ix = 0; ix < met->
nx; ix++)
8388 for (
int iy = 0; iy < met->
ny; iy++)
8390 = (ctl->
met_np > 0 ? (
float) ctl->
met_p[0] : (
float) met->
p[0]);
8398 (ncid,
"z",
"Z", NULL, NULL, NULL, NULL, ctl, met, dd, met->
zs,
8399 (
float) (1. / (1000. *
G0)), 1))
8401 (ncid,
"zm",
"ZM", NULL, NULL, NULL, NULL, ctl, met, dd, met->
zs,
8402 (
float) (1. / 1000.), 1))
8403 WARN(
"Cannot read surface geopotential height!");
8414 memcpy(help, met->
pl,
sizeof(met->
pl));
8416 (ncid,
"gph",
"GPH", NULL, NULL, ctl, met, dd, met->
pl,
8417 (
float) (1e-3 /
G0)))
8418 ERRMSG(
"Cannot read geopotential height!");
8419 for (
int ix = 0; ix < met->
nx; ix++)
8420 for (
int iy = 0; iy < met->
ny; iy++)
8421 met->
zs[ix][iy] = met->
pl[ix][iy][0];
8422 memcpy(met->
pl, help,
sizeof(met->
pl));
8428 (ncid,
"t2m",
"T2M",
"2t",
"2T",
"t2",
"T2", ctl, met, dd, met->
ts, 1.0,
8430 WARN(
"Cannot read surface temperature!");
8434 (ncid,
"u10m",
"U10M",
"10u",
"10U",
"u10",
"U10", ctl, met, dd,
8436 WARN(
"Cannot read surface zonal wind!");
8440 (ncid,
"v10m",
"V10M",
"10v",
"10V",
"v10",
"V10", ctl, met, dd,
8442 WARN(
"Cannot read surface meridional wind!");
8446 (ncid,
"iews",
"IEWS", NULL, NULL, NULL, NULL, ctl, met, dd, met->
ess,
8448 WARN(
"Cannot read eastward turbulent surface stress!");
8452 (ncid,
"inss",
"INSS", NULL, NULL, NULL, NULL, ctl, met, dd, met->
nss,
8454 WARN(
"Cannot read nothward turbulent surface stress!");
8458 (ncid,
"ishf",
"ISHF", NULL, NULL, NULL, NULL, ctl, met, dd, met->
shf,
8460 WARN(
"Cannot read surface sensible heat flux!");
8464 (ncid,
"lsm",
"LSM", NULL, NULL, NULL, NULL, ctl, met, dd, met->
lsm,
8466 WARN(
"Cannot read land-sea mask!");
8470 (ncid,
"sstk",
"SSTK",
"sst",
"SST", NULL, NULL, ctl, met, dd, met->
sst,
8472 WARN(
"Cannot read sea surface temperature!");
8477 (ncid,
"blp",
"BLP", NULL, NULL, NULL, NULL, ctl, met, dd, met->
pbl,
8479 WARN(
"Cannot read planetary boundary layer pressure!");
8482 (ncid,
"blh",
"BLH", NULL, NULL, NULL, NULL, ctl, met, dd, met->
pbl,
8484 WARN(
"Cannot read planetary boundary layer height!");
8489 (ncid,
"cape",
"CAPE", NULL, NULL, NULL, NULL, ctl, met, dd,
8491 WARN(
"Cannot read CAPE!");
8496 (ncid,
"cin",
"CIN", NULL, NULL, NULL, NULL, ctl, met, dd, met->
cin,
8498 WARN(
"Cannot read convective inhibition!");
8510 SELECT_TIMER(
"READ_MET_NC_LEVELS",
"INPUT", NVTX_READ);
8511 LOG(2,
"Read level data...");
8515 (ncid,
"t",
"T",
"temp",
"TEMP", ctl, met, dd, met->
t, 1.0))
8516 ERRMSG(
"Cannot read temperature!");
8519 if (!
read_met_nc_3d(ncid,
"u",
"U", NULL, NULL, ctl, met, dd, met->
u, 1.0))
8520 ERRMSG(
"Cannot read zonal wind!");
8521 if (!
read_met_nc_3d(ncid,
"v",
"V", NULL, NULL, ctl, met, dd, met->
v, 1.0))
8522 ERRMSG(
"Cannot read meridional wind!");
8524 (ncid,
"w",
"W",
"omega",
"OMEGA", ctl, met, dd, met->
w, 0.01f))
8525 WARN(
"Cannot read vertical velocity!");
8530 (ncid,
"q",
"Q",
"sh",
"SH", ctl, met, dd, met->
h2o,
8532 WARN(
"Cannot read specific humidity!");
8535 (ncid,
"rh",
"RH", NULL, NULL, ctl, met, dd, met->
h2o, 0.01f))
8536 WARN(
"Cannot read relative humidity!");
8537#pragma omp parallel for default(shared) collapse(2)
8538 for (
int ix = 0; ix < met->
nx; ix++)
8539 for (
int iy = 0; iy < met->
ny; iy++)
8540 for (
int ip = 0; ip < met->
np; ip++) {
8541 double pw = met->
h2o[ix][iy][ip] *
PSAT(met->
t[ix][iy][ip]);
8542 met->
h2o[ix][iy][ip] =
8543 (float) (pw / (met->
p[ip] - (1.0 -
EPS) * pw));
8549 (ncid,
"o3",
"O3", NULL, NULL, ctl, met, dd, met->
o3,
8550 (
float) (
MA /
MO3)))
8551 WARN(
"Cannot read ozone data!");
8555 (ncid,
"clwc",
"CLWC", NULL, NULL, ctl, met, dd, met->
lwc, 1.0))
8556 WARN(
"Cannot read cloud liquid water content!");
8558 (ncid,
"crwc",
"CRWC", NULL, NULL, ctl, met, dd, met->
rwc, 1.0))
8559 WARN(
"Cannot read cloud rain water content!");
8561 (ncid,
"ciwc",
"CIWC", NULL, NULL, ctl, met, dd, met->
iwc, 1.0))
8562 WARN(
"Cannot read cloud ice water content!");
8564 (ncid,
"cswc",
"CSWC", NULL, NULL, ctl, met, dd, met->
swc, 1.0))
8565 WARN(
"Cannot read cloud snow water content!");
8567 (ncid,
"cc",
"CC", NULL, NULL, ctl, met, dd, met->
cc, 1.0))
8568 WARN(
"Cannot read cloud cover!");
8573 (ncid,
"ZETA",
"zeta", NULL, NULL, ctl, met, dd, met->
zetal, 1.0))
8574 WARN(
"Cannot read ZETA!");
8576 (ncid,
"ZETA_DOT_TOT",
"ZETA_DOT_clr",
"zeta_dot_clr",
8577 NULL, ctl, met, dd, met->
zeta_dotl, 0.00001157407f))
8578 WARN(
"Cannot read ZETA_DOT!");
8583#pragma omp parallel for default(shared)
8584 for (
int ix = 0; ix < met->
nx; ix++)
8585 for (
int iy = 0; iy < met->
ny; iy++)
8586 for (
int ip = 0; ip < met->
np; ip++)
8587 met->
zetal[ix][iy][ip] =
8588 (
float) (met->
hyam[ip] / 100000.0 + met->
hybm[ip]);
8590 (ncid,
"etadot",
"ETADOT", NULL, NULL, ctl, met, dd, met->
zeta_dotl,
8592 WARN(
"Cannot read eta vertical velocity!");
8597#pragma omp parallel for default(shared)
8598 for (
int ix = 0; ix < met->
nx; ix++)
8599 for (
int iy = 0; iy < met->
ny; iy++)
8600 for (
int ip = 0; ip < met->
np; ip++) {
8601 met->
ul[ix][iy][ip] = met->
u[ix][iy][ip];
8602 met->
vl[ix][iy][ip] = met->
v[ix][iy][ip];
8603 met->
wl[ix][iy][ip] = met->
w[ix][iy][ip];
8616 (ncid,
"pl",
"PL",
"pressure",
"PRESSURE", ctl, met, dd, met->
pl,
8619 (ncid,
"press",
"PRESS", NULL, NULL, ctl, met, dd, met->
pl, 1.0))
8620 ERRMSG(
"Cannot read pressure on model levels!");
8628 ERRMSG(
"Mismatch in number of model levels!");
8631 for (
int ix = 0; ix < met->
nx; ix++)
8632 for (
int iy = 0; iy < met->
ny; iy++)
8633 for (
int ip = 0; ip < met->
np; ip++)
8634 met->
pl[ix][iy][ip] =
8635 (
float) (met->
hyam[ip] / 100. +
8636 met->
hybm[ip] * met->
ps[ix][iy]);
8644 ERRMSG(
"Mismatch in number of model levels!");
8647#pragma omp parallel for default(shared) collapse(2)
8648 for (
int ix = 0; ix < met->
nx; ix++)
8649 for (
int iy = 0; iy < met->
ny; iy++)
8650 for (
int ip = 0; ip < met->
np; ip++) {
8652 met->
hyam[ip] / 100. + met->
hybm[ip] * met->
ps[ix][iy];
8654 met->
hyam[ip + 1] / 100. + met->
hybm[ip + 1] * met->
ps[ix][iy];
8655 met->
pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
8660 for (
int ix = 0; ix < met->
nx; ix++)
8661 for (
int iy = 0; iy < met->
ny; iy++)
8662 for (
int ip = 1; ip < met->
np; ip++)
8663 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
8664 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
8665 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
8666 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip]))
8667 ERRMSG(
"Pressure profiles are not monotonic!");
8688 for (
int ip = 0; ip < met->
np; ip++)
8689 met->
p[ip] = ctl->
met_p[ip];
8693 for (
int ip = 1; ip < met->
np; ip++)
8694 if (met->
p[ip - 1] < met->
p[ip])
8695 ERRMSG(
"Pressure levels must be descending!");
8702 const char *varname,
8703 const char *varname2,
8704 const char *varname3,
8705 const char *varname4,
8706 const char *varname5,
8707 const char *varname6,
8717 float offset, scalfac;
8722 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
8723 sprintf(varsel,
"%s", varname);
8724 else if (varname2 != NULL
8725 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
8726 sprintf(varsel,
"%s", varname2);
8727 else if (varname3 != NULL
8728 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
8729 sprintf(varsel,
"%s", varname3);
8730 else if (varname4 != NULL
8731 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
8732 sprintf(varsel,
"%s", varname4);
8733 else if (varname5 != NULL
8734 && nc_inq_varid(ncid, varname5, &varid) == NC_NOERR)
8735 sprintf(varsel,
"%s", varname5);
8736 else if (varname6 != NULL
8737 && nc_inq_varid(ncid, varname6, &varid) == NC_NOERR)
8738 sprintf(varsel,
"%s", varname6);
8744 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
8745 && nc_get_att_float(ncid, varid,
"scale_factor",
8746 &scalfac) == NC_NOERR) {
8754 short fillval, missval;
8755 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8757 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8761 LOG(2,
"Read 2-D variable: %s"
8762 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
8763 varsel, fillval, missval, scalfac, offset);
8766 NC(nc_get_var_short(ncid, varid, help));
8770 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
8774#pragma omp parallel for default(shared)
8775 for (
int ix = 0; ix < met->
nx; ix++)
8776 for (
int iy = 0; iy < met->
ny; iy++) {
8779 const short aux = help[
ARRAY_2D(iy, ix, met->
nx)];
8780 if ((fillval == 0 || aux != fillval)
8781 && (missval == 0 || aux != missval)
8782 && fabsf(aux * scalfac + offset) < 1e14f)
8783 dest[ix][iy] += scl * (aux * scalfac + offset);
8794 else if (!ctl->
dd) {
8802 float fillval, missval;
8803 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8805 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8809 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
8810 varsel, fillval, missval);
8813 NC(nc_get_var_float(ncid, varid, help));
8820#pragma omp parallel for default(shared)
8821 for (
int ix = 0; ix < met->
nx; ix++)
8822 for (
int iy = 0; iy < met->
ny; iy++) {
8825 const float aux = help[
ARRAY_2D(iy, ix, met->
nx)];
8826 if ((fillval == 0 || aux != fillval)
8827 && (missval == 0 || aux != missval)
8828 && fabsf(aux) < 1e14f)
8829 dest[ix][iy] += scl * aux;
8839#pragma omp parallel for default(shared)
8840 for (
int iy = 0; iy < met->
ny; iy++)
8841 for (
int ix = 0; ix < met->
nx; ix++) {
8844 const float aux = help[
ARRAY_2D(ix, iy, met->
ny)];
8845 if ((fillval == 0 || aux != fillval)
8846 && (missval == 0 || aux != missval)
8847 && fabsf(aux) < 1e14f)
8848 dest[ix][iy] += scl * aux;
8863 float fillval, missval;
8864 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8866 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8870 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
8871 varsel, fillval, missval);
8875 size_t help_subdomain_start[3];
8876 size_t help_subdomain_count[3];
8878 help_subdomain_start[0] = 0;
8882 help_subdomain_count[0] = 1;
8891 NC(nc_get_vara_float
8892 (ncid, varid, help_subdomain_start, help_subdomain_count, help));
8895 size_t help_halo_bnd_start[3];
8896 size_t help_halo_bnd_count[3];
8898 help_halo_bnd_start[0] = 0;
8902 help_halo_bnd_count[0] = 1;
8907 ALLOC(help_halo,
float,
8908 help_halo_bnd_count[1] * help_halo_bnd_count[2]);
8909 NC(nc_get_vara_float
8910 (ncid, varid, help_halo_bnd_start, help_halo_bnd_count, help_halo));
8915#pragma omp parallel for default(shared) num_threads(12)
8916 for (
int ix = 0; ix < (int) help_subdomain_count[2]; ix++)
8917 for (
int iy = 0; iy < (int) help_subdomain_count[1]; iy++) {
8921 help[
ARRAY_2D(iy, ix, (
int) help_subdomain_count[2])];
8922 if ((fillval == 0 || aux != fillval)
8923 && (missval == 0 || aux != missval)
8924 && fabsf(aux) < 1e14f) {
8931#pragma omp parallel for default(shared) num_threads(12)
8932 for (
int ix = 0; ix < (int) help_halo_bnd_count[2]; ix++)
8933 for (
int iy = 0; iy < (int) help_halo_bnd_count[1]; iy++) {
8937 help_halo[
ARRAY_2D(iy, ix, (
int) help_halo_bnd_count[2])];
8938 if ((fillval == 0 || aux != fillval)
8939 && (missval == 0 || aux != missval)
8940 && fabsf(aux) < 1e14f)
8948 ERRMSG(
"Domain decomposition with data convection incompatible!");
8964 const char *varname,
8965 const char *varname2,
8966 const char *varname3,
8967 const char *varname4,
8978 float offset, scalfac;
8983 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
8984 sprintf(varsel,
"%s", varname);
8985 else if (varname2 != NULL
8986 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
8987 sprintf(varsel,
"%s", varname2);
8988 else if (varname3 != NULL
8989 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
8990 sprintf(varsel,
"%s", varname3);
8991 else if (varname4 != NULL
8992 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
8993 sprintf(varsel,
"%s", varname4);
8998 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
8999 && nc_get_att_float(ncid, varid,
"scale_factor",
9000 &scalfac) == NC_NOERR) {
9008 short fillval, missval;
9009 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9011 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9015 LOG(2,
"Read 3-D variable: %s "
9016 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
9017 varsel, fillval, missval, scalfac, offset);
9020 NC(nc_get_var_short(ncid, varid, help));
9024 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
9028#pragma omp parallel for default(shared)
9029 for (
int ix = 0; ix < met->
nx; ix++)
9030 for (
int iy = 0; iy < met->
ny; iy++)
9031 for (
int ip = 0; ip < met->
np; ip++) {
9032 const short aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
9033 if ((fillval == 0 || aux != fillval)
9034 && (missval == 0 || aux != missval)
9035 && fabsf(aux * scalfac + offset) < 1e14f)
9036 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
9038 dest[ix][iy][ip] = NAN;
9047 else if (!ctl->
dd) {
9055 float fillval, missval;
9056 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9058 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9062 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
9063 varsel, fillval, missval);
9066 NC(nc_get_var_float(ncid, varid, help));
9073#pragma omp parallel for default(shared)
9074 for (
int ix = 0; ix < met->
nx; ix++)
9075 for (
int iy = 0; iy < met->
ny; iy++)
9076 for (
int ip = 0; ip < met->
np; ip++) {
9077 const float aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
9078 if ((fillval == 0 || aux != fillval)
9079 && (missval == 0 || aux != missval)
9080 && fabsf(aux) < 1e14f)
9081 dest[ix][iy][ip] = scl * aux;
9083 dest[ix][iy][ip] = NAN;
9091#pragma omp parallel for default(shared)
9092 for (
int ip = 0; ip < met->
np; ip++)
9093 for (
int iy = 0; iy < met->
ny; iy++)
9094 for (
int ix = 0; ix < met->
nx; ix++) {
9095 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9096 if ((fillval == 0 || aux != fillval)
9097 && (missval == 0 || aux != missval)
9098 && fabsf(aux) < 1e14f)
9099 dest[ix][iy][ip] = scl * aux;
9101 dest[ix][iy][ip] = NAN;
9114 float fillval, missval;
9115 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9117 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9121 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
9122 varsel, fillval, missval);
9124 SELECT_TIMER(
"read_met_nc_3d_CP1",
"INPUT", NVTX_READ);
9134 SELECT_TIMER(
"read_met_nc_3d_CP2",
"INPUT", NVTX_READ);
9137 NC(nc_get_vara_float
9142 ALLOC(help_halo,
float,
9146 SELECT_TIMER(
"read_met_nc_3d_CP3",
"INPUT", NVTX_READ);
9149 NC(nc_get_vara_float(ncid,
9153 SELECT_TIMER(
"read_met_nc_3d_CP4",
"INPUT", NVTX_READ);
9158#pragma omp parallel for default(shared) num_threads(12)
9161 for (
int ip = 0; ip < met->
np; ip++) {
9165 if ((fillval == 0 || aux != fillval)
9166 && (missval == 0 || aux != missval)
9167 && fabsf(aux) < 1e14f)
9173#pragma omp parallel for default(shared) num_threads(12)
9176 for (
int ip = 0; ip < met->
np; ip++) {
9180 if ((fillval == 0 || aux != fillval)
9181 && (missval == 0 || aux != missval)
9182 && fabsf(aux) < 1e14f)
9191#pragma omp parallel for default(shared) num_threads(12)
9192 for (
int ip = 0; ip < met->
np; ip++)
9195 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9196 if ((fillval == 0 || aux != fillval)
9197 && (missval == 0 || aux != missval)
9198 && fabsf(aux) < 1e14f)
9204#pragma omp parallel for default(shared) num_threads(12)
9205 for (
int ip = 0; ip < met->
np; ip++)
9208 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9209 if ((fillval == 0 || aux != fillval)
9210 && (missval == 0 || aux != missval)
9211 && fabsf(aux) < 1e14f)
9231 const char *filename,
9236 size_t filename_len = strlen(filename) + 1;
9237 char sf_filename[filename_len];
9238 char ml_filename[filename_len];
9239 strcpy(sf_filename, filename);
9240 strcpy(ml_filename, filename);
9245 FILE *ml_file = fopen(ml_filename,
"rb");
9246 FILE *sf_file = fopen(sf_filename,
"rb");
9247 if (ml_file == NULL || sf_file == NULL) {
9248 if (ml_file != NULL) {
9250 WARN(
"Cannot open file: %s", sf_filename);
9252 if (sf_file != NULL) {
9254 WARN(
"Cannot open file: %s", ml_filename);
9260 int ml_num_messages = 0, err = 0;
9261 ECC(codes_count_in_file(0, ml_file, &ml_num_messages));
9264 (size_t) ml_num_messages);
9265 for (
int i = 0; i < ml_num_messages; i++) {
9267 if ((h = codes_grib_handle_new_from_file(0, ml_file, &err)) != NULL)
9272 int sf_num_messages = 0;
9273 ECC(codes_count_in_file(0, sf_file, &sf_num_messages));
9276 (size_t) sf_num_messages);
9277 for (
int i = 0; i < sf_num_messages; i++) {
9279 if ((h = codes_grib_handle_new_from_file(0, sf_file, &err)) != NULL)
9292 for (
int i = 0; i < sf_num_messages; i++)
9293 codes_handle_delete(sf_handles[i]);
9297 size_t value_count = 0;
9298 ECC(codes_get_size(ml_handles[0],
"pv", &value_count));
9299 if (value_count % 2 != 0)
9300 ERRMSG(
"Unexpected pv array length!");
9301 size_t nlevels = value_count / 2 - 1;
9303 ALLOC(values,
double,
9305 ECC(codes_get_double_array(ml_handles[0],
"pv", values, &value_count));
9306 double *a_vals = values;
9307 double *b_vals = values + nlevels;
9308 if (met->
npl > (
int) nlevels)
9309 ERRMSG(
"met->npl exceeds number of pressure levels in GRIB!");
9310 for (
int nx = 0; nx < met->
nx; nx++)
9311 for (
int ny = 0; ny < met->
ny; ny++)
9312 for (
int level = 0; level <= met->
npl; level++) {
9313 const float p1 = (float) (a_vals[level] * 0.01f +
9314 met->
ps[nx][ny] * b_vals[level]);
9315 const float p2 = (float) (a_vals[level + 1] * 0.01f +
9316 met->
ps[nx][ny] * b_vals[level + 1]);
9317 met->
pl[nx][ny][level] = 0.5f * (p1 + p2);
9323 for (
int i = 0; i < ml_num_messages; i++)
9324 codes_handle_delete(ml_handles[i]);
9341 SELECT_TIMER(
"READ_MET_GRIB_GRID",
"INPUT", NVTX_READ);
9342 LOG(2,
"Read meteo grid information...");
9345 char datestr[
LEN], timestr[
LEN];
9346 size_t s_date =
sizeof(datestr);
9347 ECC(codes_get_string(handles[0],
"dataDate", datestr, &s_date));
9348 size_t s_time =
sizeof(timestr);
9349 ECC(codes_get_string(handles[0],
"dataTime", timestr, &s_time));
9350 int year, month, day, hour;
9351 if (sscanf(datestr,
"%4d%2d%2d", &year, &month, &day) != 3)
9352 ERRMSG(
"Failed to parse dataDate: %s", datestr);
9353 if (sscanf(timestr,
"%2d", &hour) != 1)
9354 ERRMSG(
"Failed to parse dataTime: %s", timestr);
9356 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)", met->
time, year, month,
9360 long count_lat = 0, count_lon = 0;
9361 ECC(codes_get_long(handles[0],
"Nj", &count_lat));
9362 ECC(codes_get_long(handles[0],
"Ni", &count_lon));
9363 met->
ny = (int) count_lat;
9364 met->
nx = (int) count_lon;
9367 LOG(2,
"Number of longitudes: %d", met->
nx);
9368 if (met->
nx < 2 || met->
nx >
EX)
9369 ERRMSG(
"Number of longitudes out of range!");
9370 LOG(2,
"Number of latitudes: %d", met->
ny);
9371 if (met->
ny < 2 || met->
ny >
EY)
9372 ERRMSG(
"Number of latitudes out of range!");
9374 double first_lon, last_lon, first_lat, last_lat, inc_lon, inc_lat;
9375 ECC(codes_get_double
9376 (handles[0],
"longitudeOfFirstGridPointInDegrees", &first_lon));
9377 ECC(codes_get_double
9378 (handles[0],
"latitudeOfFirstGridPointInDegrees", &first_lat));
9379 ECC(codes_get_double
9380 (handles[0],
"longitudeOfLastGridPointInDegrees", &last_lon));
9381 ECC(codes_get_double
9382 (handles[0],
"latitudeOfLastGridPointInDegrees", &last_lat));
9383 ECC(codes_get_double(handles[0],
"iDirectionIncrementInDegrees", &inc_lon));
9384 ECC(codes_get_double(handles[0],
"jDirectionIncrementInDegrees", &inc_lat));
9386 long jscanpos, iscanneg;
9387 ECC(codes_get_long(handles[0],
"iScansNegatively", &iscanneg));
9388 ECC(codes_get_long(handles[0],
"jScansPositively", &jscanpos));
9393 for (
double i = first_lon; i <= last_lon + 1e-6; i += inc_lon) {
9394 met->
lon[counter] = i;
9397 for (
double i = first_lon; i > last_lon - 1e-6; i -= inc_lon) {
9398 met->
lon[counter] = i;
9404 for (
double i = first_lat; i > last_lat - 1e-6; i -= inc_lat) {
9405 met->
lat[counter] = i;
9408 for (
double i = first_lat; i <= last_lat + 1e-6; i += inc_lat) {
9409 met->
lat[counter] = i;
9414 LOG(2,
"Longitudes: %g, %g ... %g deg",
9416 LOG(2,
"Latitudes: %g, %g ... %g deg",
9421 for (
int i = 0; i < count_handles; i++) {
9423 ECC(codes_get_long(handles[i],
"level", &level));
9424 if (level > max_level)
9425 max_level = (int) level;
9427 met->
npl = max_level;
9430 LOG(2,
"Number of levels: %d", met->
npl);
9432 ERRMSG(
"Number of levels out of range!");
9441 const int num_messages,
9446 SELECT_TIMER(
"READ_MET_GRIB_LEVELS",
"INPUT", NVTX_READ);
9447 LOG(2,
"Read level data...");
9450 int t_flag = 0, u_flag = 0, v_flag = 0, w_flag = 0, o3_flag = 0, h2o_flag =
9451 0, lwc_flag = 0, rwc_flag = 0, iwc_flag = 0, swc_flag = 0, cc_flag = 0;
9454 for (
int i = 0; i < num_messages; i++) {
9456 size_t max_size =
LEN;
9457 char short_name[max_size];
9463 ECC(codes_get_long(handles[i],
"level", ¤t_level));
9467 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
9468 ECC(codes_get_size(handles[i],
"values", &value_count));
9469 ALLOC(values,
double,
9471 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
9479 ECC_READ_3D(
"w", current_level, met->
w, 0.01f, w_flag);
9497 if (t_flag != met->
npl)
9498 ERRMSG(
"Cannot read temperature!");
9499 if (u_flag != met->
npl)
9500 ERRMSG(
"Cannot read zonal wind!");
9501 if (v_flag != met->
npl)
9502 ERRMSG(
"Cannot read meridional wind!");
9503 if (w_flag != met->
npl)
9504 WARN(
"Cannot read vertical velocity!");
9505 if (h2o_flag != met->
npl)
9506 WARN(
"Cannot read specific humidity!");
9507 if (o3_flag != met->
npl)
9508 WARN(
"Cannot read ozone data!");
9509 if (lwc_flag != met->
npl)
9510 WARN(
"Cannot read cloud liquid water content!");
9511 if (rwc_flag != met->
npl)
9512 WARN(
"Cannot read cloud rain water content!");
9513 if (iwc_flag != met->
npl)
9514 WARN(
"Cannot read cloud ice water content!");
9515 if (swc_flag != met->
npl)
9516 WARN(
"Cannot read cloud snow water content!");
9517 if (cc_flag != met->
npl)
9518 WARN(
"Cannot read cloud cover!");
9521 for (
int ix = 0; ix < met->
nx; ix++)
9522 for (
int iy = 0; iy < met->
ny; iy++)
9523 for (
int ip = 1; ip < met->
np; ip++)
9524 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
9525 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
9526 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
9527 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip])) {
9528 LOG(1,
"%f %f %f %f", met->
pl[ix][iy][0], met->
pl[ix][iy][1],
9529 met->
pl[ix][iy][ip - 1], met->
pl[ix][iy][ip]);
9530 ERRMSG(
"Pressure profiles are not monotonic!");
9551 for (
int ip = 0; ip < met->
np; ip++)
9552 met->
p[ip] = ctl->
met_p[ip];
9556 for (
int ip = 1; ip < met->
np; ip++)
9557 if (met->
p[ip - 1] < met->
p[ip])
9558 ERRMSG(
"Pressure levels must be descending!");
9567 const int num_messages,
9572 SELECT_TIMER(
"READ_MET_GRIB_SURFACE",
"INPUT", NVTX_READ);
9573 LOG(2,
"Read surface data...");
9576 int sp_flag = 0, z_flag = 0, t_flag = 0, u_flag = 0, v_flag = 0, lsm_flag =
9577 0, sst_flag = 0, cape_flag = 0, cin_flag = 0, pbl_flag = 0;
9580 for (
int i = 0; i < num_messages; i++) {
9582 size_t max_size =
LEN, value_count;
9584 char short_name[max_size];
9587 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
9588 ECC(codes_get_size(handles[i],
"values", &value_count));
9589 double *values = (
double *) malloc(value_count *
sizeof(
double));
9590 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
9628 WARN(
"Cannot read surface pressure data!");
9630 WARN(
"Cannot read surface geopotential height!");
9632 WARN(
"Cannot read surface temperature!");
9634 WARN(
"Cannot read surface zonal wind!");
9636 WARN(
"Cannot read surface meridional wind!");
9638 WARN(
"Cannot read land-sea mask!");
9640 WARN(
"Cannot read sea surface temperature!");
9643 WARN(
"Cannot read CAPE!");
9645 WARN(
"Cannot read convective inhibition!");
9647 if (ctl->
met_pbl == 0 && pbl_flag == 0)
9648 WARN(
"Cannot read planetary boundary layer!");
9658 const char *varname) {
9660 double aux[
EP], p[
EP];
9664 LOG(2,
"Interpolate meteo data to pressure levels: %s", varname);
9667#pragma omp parallel for default(shared) private(aux,p) collapse(2)
9668 for (
int ix = 0; ix < met->
nx; ix++)
9669 for (
int iy = 0; iy < met->
ny; iy++) {
9672 for (
int ip = 0; ip < met->
np; ip++)
9673 p[ip] = met->
pl[ix][iy][ip];
9676 for (
int ip = 0; ip < ctl->
met_np; ip++) {
9677 double pt = ctl->
met_p[ip];
9678 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
9680 else if ((pt > p[met->
np - 1] && p[1] > p[0])
9681 || (pt < p[met->
np - 1] && p[1] < p[0]))
9682 pt = p[met->
np - 1];
9684 aux[ip] =
LIN(p[ip2], var[ix][iy][ip2],
9685 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
9689 for (
int ip = 0; ip < ctl->
met_np; ip++)
9690 var[ix][iy][ip] = (
float) aux[ip];
9705 SELECT_TIMER(
"READ_MET_MONOTONIZE",
"METPROC", NVTX_READ);
9706 LOG(2,
"Make zeta profiles monotone...");
9709#pragma omp parallel for default(shared) collapse(2)
9710 for (
int i = 0; i < met->
nx; i++)
9711 for (
int j = 0; j < met->
ny; j++) {
9714 while (k < met->npl) {
9715 if ((met->
zetal[i][j][k - 1] >= met->
zetal[i][j][k])) {
9721 while ((met->
zetal[i][j][k - 1] >=
9722 met->
zetal[i][j][k + l]) & (k + l < met->npl));
9727 (float) (met->
zetal[i][j][k + l] - met->
zetal[i][j][k - 1])
9730 for (
int m = k; m < k + l; m++) {
9731 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
9732 met->
zetal[i][j][m] = s * d + met->
zetal[i][j][k - 1];
9744#pragma omp parallel for default(shared) collapse(2)
9745 for (
int i = 0; i < met->
nx; i++)
9746 for (
int j = 0; j < met->
ny; j++) {
9749 while (k < met->npl) {
9750 if ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k])) {
9757 while ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k + l]) & (k + l <
9762 float s = (float) (met->
pl[i][j][k + l] - met->
pl[i][j][k - 1])
9765 for (
int m = k; m < k + l; m++) {
9766 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
9767 met->
pl[i][j][m] = s * d + met->
pl[i][j][k - 1];
9782 const char *filename,
9793 (filename, NC_NOWRITE | NC_SHARE, MPI_COMM_WORLD, MPI_INFO_NULL,
9797 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
9798 WARN(
"Cannot open file!");
9831 MPI_Comm_rank(MPI_COMM_WORLD, &dd->
rank);
9832 MPI_Comm_size(MPI_COMM_WORLD, &dd->
size);
9840 LOG(2,
"Number of longitudes: %d", help_nx_glob);
9844 LOG(2,
"Number of latitudes: %d", help_ny_glob);
9847 double *help_lon_glob;
9848 double *help_lat_glob;
9849 ALLOC(help_lon_glob,
double,
9851 ALLOC(help_lat_glob,
double,
9856 LOG(2,
"Longitudes: %g, %g ... %g deg",
9857 help_lon_glob[0], help_lon_glob[1], help_lon_glob[help_nx_glob - 1]);
9859 LOG(2,
"Latitudes: %g, %g ... %g deg",
9860 help_lat_glob[0], help_lat_glob[1], help_lat_glob[help_ny_glob - 1]);
9884 met->
nx = met->
nx + gap;
9885 WARN(
"Extended subdomains at the right to fit to full domain.");
9891 met->
ny = met->
ny + gap;
9892 WARN(
"Extended subdomains at the bottom to fit to full domain.");
9903 if (!left && !right) {
9920 if (!top && !bottom) {
9938 double lon_shift = 0;
9939 if (left || right) {
9957 lon_shift = (left ? -360 : 360);
9974 double lon_range = 360;
9985 double lat_range = help_lat_glob[help_ny_glob - 1] - help_lat_glob[0];
10012 if (lat_range < 0) {
10019 (
"lat_range > 0, but is expected to be negative, i.e. latitudes should range from 90 to -90")
10026 LOG(2,
"Total longitude range: %g deg", lon_range);
10027 LOG(2,
"Total latitude range: %g deg", lat_range);
10029 LOG(2,
"Define subdomain properties.");
10030 LOG(2,
"MPI information: Rank %d, Size %d", dd->
rank, dd->
size);
10031 LOG(2,
"Edge position: l=%d,r=%d,t=%d, b=%d", (
int) left, (
int) right,
10032 (
int) top, (
int) bottom);
10033 LOG(2,
"Sizes for limits: EX %d EY %d EP %d",
EX,
EY,
EP);
10034 LOG(2,
"Total size for subdomain meteo data: nx %d ny %d np %d", met->
nx,
10036 LOG(2,
"Hyperslab sizes for boundary halos: nx %d ny %d np %d",
10039 LOG(2,
"Hyperslab sizes for subdomain and inner halos: nx %d ny %d np %d",
10048 LOG(2,
" %d Subdomain longitudes: %g, %g ... %g deg (edges: %g to %g)",
10051 LOG(2,
" %d Subdomain latitudes: %g, %g ... %g deg (edges: %g to %g)",
10055 free(help_lon_glob);
10056 free(help_lat_glob);
10067 LOG(2,
"Calculate planetary boundary layer...");
10073#pragma omp parallel for default(shared) collapse(2)
10074 for (
int ix = 0; ix < met->
nx; ix++)
10075 for (
int iy = 0; iy < met->
ny; iy++) {
10078 const float z = met->
zs[ix][iy] + met->
pbl[ix][iy];
10081 (float) (
LIN(met->
z[ix][iy][ip], met->
p[ip],
10082 met->
z[ix][iy][ip + 1], met->
p[ip + 1], z));
10087 else if (ctl->
met_pbl == 2) {
10091 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
10094#pragma omp parallel for default(shared) collapse(2)
10095 for (
int ix = 0; ix < met->
nx; ix++)
10096 for (
int iy = 0; iy < met->
ny; iy++) {
10099 const double pbl_bot = met->
ps[ix][iy] * exp(-dz /
H0);
10103 for (ip = 1; ip < met->
np; ip++)
10104 if (met->
p[ip] < pbl_bot)
10108 const double h2os =
LIN(met->
p[ip - 1], met->
h2o[ix][iy][ip - 1],
10109 met->
p[ip], met->
h2o[ix][iy][ip], pbl_bot);
10110 const double tvs =
THETAVIRT(pbl_bot, met->
ts[ix][iy], h2os);
10113 double rib_old = 0;
10116 for (; ip < met->
np; ip++) {
10119 double vh2 =
SQR(met->
u[ix][iy][ip] - met->
us[ix][iy])
10120 +
SQR(met->
v[ix][iy][ip] - met->
vs[ix][iy]);
10121 vh2 =
MAX(vh2,
SQR(umin));
10125 G0 * 1e3 * (met->
z[ix][iy][ip] - met->
zs[ix][iy]) / tvs
10127 met->
h2o[ix][iy][ip]) - tvs) / vh2;
10130 if (rib >= rib_crit) {
10131 met->
pbl[ix][iy] = (float) (
LIN(rib_old, met->
p[ip - 1],
10132 rib, met->
p[ip], rib_crit));
10133 if (met->
pbl[ix][iy] > pbl_bot)
10134 met->
pbl[ix][iy] = (float) pbl_bot;
10149 const double dtheta = 2.0, zmin = 0.1;
10152#pragma omp parallel for default(shared) collapse(2)
10153 for (
int ix = 0; ix < met->
nx; ix++)
10154 for (
int iy = 0; iy < met->
ny; iy++) {
10157 const double theta0 =
THETA(met->
ps[ix][iy], met->
ts[ix][iy]);
10161 for (ip = met->
np - 2; ip > 0; ip--)
10162 if (met->
p[ip] >= 300.)
10163 if (met->
p[ip] > met->
ps[ix][iy]
10164 ||
THETA(met->
p[ip], met->
t[ix][iy][ip]) <= theta0 + dtheta)
10169 = (float) (
LIN(
THETA(met->
p[ip + 1], met->
t[ix][iy][ip + 1]),
10171 THETA(met->
p[ip], met->
t[ix][iy][ip]),
10172 met->
p[ip], theta0 + dtheta));
10175 double pbl_min = met->
ps[ix][iy] * exp(-zmin /
H0);
10176 if (met->
pbl[ix][iy] > pbl_min || met->
p[ip] > met->
ps[ix][iy])
10177 met->
pbl[ix][iy] = (float) pbl_min;
10182#pragma omp parallel for default(shared) collapse(2)
10183 for (
int ix = 0; ix < met->
nx; ix++)
10184 for (
int iy = 0; iy < met->
ny; iy++) {
10188 met->
pbl[ix][iy] =
MIN(met->
pbl[ix][iy], (
float) pbl_min);
10192 met->
pbl[ix][iy] =
MAX(met->
pbl[ix][iy], (
float) pbl_max);
10202 SELECT_TIMER(
"READ_MET_PERIODIC",
"METPROC", NVTX_READ);
10203 LOG(2,
"Apply periodic boundary conditions...");
10206 if (!(fabs(met->
lon[met->
nx - 1] - met->
lon[0]
10207 + met->
lon[1] - met->
lon[0] - 360) < 0.01))
10211 if ((++met->
nx) >=
EX)
10212 ERRMSG(
"Cannot create periodic boundary conditions!");
10215 met->
lon[met->
nx - 1] = met->
lon[met->
nx - 2] + met->
lon[1] - met->
lon[0];
10218#pragma omp parallel for default(shared)
10219 for (
int iy = 0; iy < met->
ny; iy++) {
10220 met->
ps[met->
nx - 1][iy] = met->
ps[0][iy];
10221 met->
zs[met->
nx - 1][iy] = met->
zs[0][iy];
10222 met->
ts[met->
nx - 1][iy] = met->
ts[0][iy];
10223 met->
us[met->
nx - 1][iy] = met->
us[0][iy];
10224 met->
vs[met->
nx - 1][iy] = met->
vs[0][iy];
10225 met->
ess[met->
nx - 1][iy] = met->
ess[0][iy];
10226 met->
nss[met->
nx - 1][iy] = met->
nss[0][iy];
10227 met->
shf[met->
nx - 1][iy] = met->
shf[0][iy];
10228 met->
lsm[met->
nx - 1][iy] = met->
lsm[0][iy];
10229 met->
sst[met->
nx - 1][iy] = met->
sst[0][iy];
10230 met->
pbl[met->
nx - 1][iy] = met->
pbl[0][iy];
10231 met->
cape[met->
nx - 1][iy] = met->
cape[0][iy];
10232 met->
cin[met->
nx - 1][iy] = met->
cin[0][iy];
10233 for (
int ip = 0; ip < met->
np; ip++) {
10234 met->
t[met->
nx - 1][iy][ip] = met->
t[0][iy][ip];
10235 met->
u[met->
nx - 1][iy][ip] = met->
u[0][iy][ip];
10236 met->
v[met->
nx - 1][iy][ip] = met->
v[0][iy][ip];
10237 met->
w[met->
nx - 1][iy][ip] = met->
w[0][iy][ip];
10238 met->
h2o[met->
nx - 1][iy][ip] = met->
h2o[0][iy][ip];
10239 met->
o3[met->
nx - 1][iy][ip] = met->
o3[0][iy][ip];
10240 met->
lwc[met->
nx - 1][iy][ip] = met->
lwc[0][iy][ip];
10241 met->
rwc[met->
nx - 1][iy][ip] = met->
rwc[0][iy][ip];
10242 met->
iwc[met->
nx - 1][iy][ip] = met->
iwc[0][iy][ip];
10243 met->
swc[met->
nx - 1][iy][ip] = met->
swc[0][iy][ip];
10244 met->
cc[met->
nx - 1][iy][ip] = met->
cc[0][iy][ip];
10246 for (
int ip = 0; ip < met->
npl; ip++) {
10247 met->
ul[met->
nx - 1][iy][ip] = met->
ul[0][iy][ip];
10248 met->
vl[met->
nx - 1][iy][ip] = met->
vl[0][iy][ip];
10249 met->
wl[met->
nx - 1][iy][ip] = met->
wl[0][iy][ip];
10250 met->
pl[met->
nx - 1][iy][ip] = met->
pl[0][iy][ip];
10251 met->
zetal[met->
nx - 1][iy][ip] = met->
zetal[0][iy][ip];
10263 SELECT_TIMER(
"READ_MET_POLAR_WINDS",
"METPROC", NVTX_READ);
10264 LOG(2,
"Apply fix for polar winds...");
10267 if (fabs(met->
lat[0]) < 89.999 || fabs(met->
lat[met->
ny - 1]) < 89.999)
10271 for (
int ihem = 0; ihem < 2; ihem++) {
10274 int i89 = 1, i90 = 0, sign = 1;
10279 if (met->
lat[i90] < 0)
10283 double clon[
EX], slon[
EX];
10284#pragma omp parallel for default(shared)
10285 for (
int ix = 0; ix < met->
nx; ix++) {
10286 clon[ix] = cos(sign *
DEG2RAD(met->
lon[ix]));
10287 slon[ix] = sin(sign *
DEG2RAD(met->
lon[ix]));
10291#pragma omp parallel for default(shared)
10292 for (
int ip = 0; ip < met->
np; ip++) {
10295 double vel89x = 0, vel89y = 0;
10296 for (
int ix = 0; ix < met->
nx; ix++) {
10298 (met->
u[ix][i89][ip] * clon[ix] -
10299 met->
v[ix][i89][ip] * slon[ix]) / met->
nx;
10301 (met->
u[ix][i89][ip] * slon[ix] +
10302 met->
v[ix][i89][ip] * clon[ix]) / met->
nx;
10306 for (
int ix = 0; ix < met->
nx; ix++) {
10307 met->
u[ix][i90][ip]
10308 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
10309 met->
v[ix][i90][ip]
10310 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
10325 LOG(2,
"Calculate potential vorticity...");
10328#pragma omp parallel for default(shared)
10329 for (
int ip = 0; ip < met->
np; ip++)
10330 pows[ip] = pow(1000. / met->
p[ip], 0.286);
10333#pragma omp parallel for default(shared)
10334 for (
int ix = 0; ix < met->
nx; ix++) {
10337 const int ix0 =
MAX(ix - 1, 0);
10338 const int ix1 =
MIN(ix + 1, met->
nx - 1);
10341 for (
int iy = 0; iy < met->
ny; iy++) {
10344 const int iy0 =
MAX(iy - 1, 0);
10345 const int iy1 =
MIN(iy + 1, met->
ny - 1);
10348 const double latr = 0.5 * (met->
lat[iy1] + met->
lat[iy0]);
10349 const double dx = 1000. *
DEG2DX(met->
lon[ix1] - met->
lon[ix0], latr);
10350 const double dy = 1000. *
DEG2DY(met->
lat[iy1] - met->
lat[iy0]);
10351 const double c0 = cos(
DEG2RAD(met->
lat[iy0]));
10352 const double c1 = cos(
DEG2RAD(met->
lat[iy1]));
10353 const double cr = cos(
DEG2RAD(latr));
10354 const double vort = 2 * 7.2921e-5 * sin(
DEG2RAD(latr));
10357 for (
int ip = 0; ip < met->
np; ip++) {
10361 = (met->
t[ix1][iy][ip] - met->
t[ix0][iy][ip]) * pows[ip] / dx;
10362 const double dvdx = (met->
v[ix1][iy][ip] - met->
v[ix0][iy][ip]) / dx;
10366 = (met->
t[ix][iy1][ip] - met->
t[ix][iy0][ip]) * pows[ip] / dy;
10368 = (met->
u[ix][iy1][ip] * c1 - met->
u[ix][iy0][ip] * c0) / dy;
10371 const int ip0 =
MAX(ip - 1, 0);
10372 const int ip1 =
MIN(ip + 1, met->
np - 1);
10375 double dtdp, dudp, dvdp;
10376 const double dp0 = 100. * (met->
p[ip] - met->
p[ip0]);
10377 const double dp1 = 100. * (met->
p[ip1] - met->
p[ip]);
10378 if (ip != ip0 && ip != ip1) {
10379 double denom = dp0 * dp1 * (dp0 + dp1);
10380 dtdp = (dp0 * dp0 * met->
t[ix][iy][ip1] * pows[ip1]
10381 - dp1 * dp1 * met->
t[ix][iy][ip0] * pows[ip0]
10382 + (dp1 * dp1 - dp0 * dp0) * met->
t[ix][iy][ip] * pows[ip])
10384 dudp = (dp0 * dp0 * met->
u[ix][iy][ip1]
10385 - dp1 * dp1 * met->
u[ix][iy][ip0]
10386 + (dp1 * dp1 - dp0 * dp0) * met->
u[ix][iy][ip])
10388 dvdp = (dp0 * dp0 * met->
v[ix][iy][ip1]
10389 - dp1 * dp1 * met->
v[ix][iy][ip0]
10390 + (dp1 * dp1 - dp0 * dp0) * met->
v[ix][iy][ip])
10393 const double denom = dp0 + dp1;
10395 (met->
t[ix][iy][ip1] * pows[ip1] -
10396 met->
t[ix][iy][ip0] * pows[ip0]) / denom;
10397 dudp = (met->
u[ix][iy][ip1] - met->
u[ix][iy][ip0]) / denom;
10398 dvdp = (met->
v[ix][iy][ip1] - met->
v[ix][iy][ip0]) / denom;
10402 met->
pv[ix][iy][ip] = (float)
10404 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
10410#pragma omp parallel for default(shared)
10411 for (
int ix = 0; ix < met->
nx; ix++)
10412 for (
int ip = 0; ip < met->
np; ip++) {
10414 = met->
pv[ix][1][ip]
10415 = met->
pv[ix][2][ip];
10416 met->
pv[ix][met->
ny - 1][ip]
10417 = met->
pv[ix][met->
ny - 2][ip]
10418 = met->
pv[ix][met->
ny - 3][ip];
10429 LOG(2,
"Calculate total column ozone...");
10432#pragma omp parallel for default(shared) collapse(2)
10433 for (
int ix = 0; ix < met->
nx; ix++)
10434 for (
int iy = 0; iy < met->
ny; iy++) {
10438 for (
int ip = 1; ip < met->
np; ip++)
10439 if (met->
p[ip - 1] <= met->
ps[ix][iy]) {
10441 0.5 * (met->
o3[ix][iy][ip - 1] + met->
o3[ix][iy][ip]);
10442 const double dp = met->
p[ip - 1] - met->
p[ip];
10443 cd += vmr *
MO3 /
MA * dp * 1e2 /
G0;
10447 met->
o3c[ix][iy] = (float) (cd / 2.1415e-5);
10465 SELECT_TIMER(
"READ_MET_SAMPLE",
"METPROC", NVTX_READ);
10466 LOG(2,
"Downsampling of meteo data...");
10472 help->
nx = met->
nx;
10473 help->
ny = met->
ny;
10474 help->
np = met->
np;
10475 memcpy(help->
lon, met->
lon,
sizeof(met->
lon));
10476 memcpy(help->
lat, met->
lat,
sizeof(met->
lat));
10477 memcpy(help->
p, met->
p,
sizeof(met->
p));
10480 for (
int ix = 0; ix < met->
nx; ix += ctl->
met_dx) {
10481 for (
int iy = 0; iy < met->
ny; iy += ctl->
met_dy) {
10482 for (
int ip = 0; ip < met->
np; ip += ctl->
met_dp) {
10483 help->
ps[ix][iy] = 0;
10484 help->
zs[ix][iy] = 0;
10485 help->
ts[ix][iy] = 0;
10486 help->
us[ix][iy] = 0;
10487 help->
vs[ix][iy] = 0;
10488 help->
ess[ix][iy] = 0;
10489 help->
nss[ix][iy] = 0;
10490 help->
shf[ix][iy] = 0;
10491 help->
lsm[ix][iy] = 0;
10492 help->
sst[ix][iy] = 0;
10493 help->
pbl[ix][iy] = 0;
10494 help->
cape[ix][iy] = 0;
10495 help->
cin[ix][iy] = 0;
10496 help->
t[ix][iy][ip] = 0;
10497 help->
u[ix][iy][ip] = 0;
10498 help->
v[ix][iy][ip] = 0;
10499 help->
w[ix][iy][ip] = 0;
10500 help->
h2o[ix][iy][ip] = 0;
10501 help->
o3[ix][iy][ip] = 0;
10502 help->
lwc[ix][iy][ip] = 0;
10503 help->
rwc[ix][iy][ip] = 0;
10504 help->
iwc[ix][iy][ip] = 0;
10505 help->
swc[ix][iy][ip] = 0;
10506 help->
cc[ix][iy][ip] = 0;
10508 for (
int ix2 = ix - ctl->
met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
10513 else if (ix3 >= met->
nx)
10516 for (
int iy2 =
MAX(iy - ctl->
met_sy + 1, 0);
10517 iy2 <=
MIN(iy + ctl->
met_sy - 1, met->
ny - 1); iy2++)
10518 for (
int ip2 =
MAX(ip - ctl->
met_sp + 1, 0);
10519 ip2 <=
MIN(ip + ctl->
met_sp - 1, met->
np - 1); ip2++) {
10521 (1.0f - (float) abs(ix - ix2) / (float) ctl->
met_sx)
10522 * (1.0f - (float) abs(iy - iy2) / (float) ctl->
met_sy)
10523 * (1.0f - (float) abs(ip - ip2) / (float) ctl->
met_sp);
10524 help->
ps[ix][iy] += w * met->
ps[ix3][iy2];
10525 help->
zs[ix][iy] += w * met->
zs[ix3][iy2];
10526 help->
ts[ix][iy] += w * met->
ts[ix3][iy2];
10527 help->
us[ix][iy] += w * met->
us[ix3][iy2];
10528 help->
vs[ix][iy] += w * met->
vs[ix3][iy2];
10529 help->
ess[ix][iy] += w * met->
ess[ix3][iy2];
10530 help->
nss[ix][iy] += w * met->
nss[ix3][iy2];
10531 help->
shf[ix][iy] += w * met->
shf[ix3][iy2];
10532 help->
lsm[ix][iy] += w * met->
lsm[ix3][iy2];
10533 help->
sst[ix][iy] += w * met->
sst[ix3][iy2];
10534 help->
pbl[ix][iy] += w * met->
pbl[ix3][iy2];
10535 help->
cape[ix][iy] += w * met->
cape[ix3][iy2];
10536 help->
cin[ix][iy] += w * met->
cin[ix3][iy2];
10537 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip2];
10538 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip2];
10539 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip2];
10540 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip2];
10541 help->
h2o[ix][iy][ip] += w * met->
h2o[ix3][iy2][ip2];
10542 help->
o3[ix][iy][ip] += w * met->
o3[ix3][iy2][ip2];
10543 help->
lwc[ix][iy][ip] += w * met->
lwc[ix3][iy2][ip2];
10544 help->
rwc[ix][iy][ip] += w * met->
rwc[ix3][iy2][ip2];
10545 help->
iwc[ix][iy][ip] += w * met->
iwc[ix3][iy2][ip2];
10546 help->
swc[ix][iy][ip] += w * met->
swc[ix3][iy2][ip2];
10547 help->
cc[ix][iy][ip] += w * met->
cc[ix3][iy2][ip2];
10551 help->
ps[ix][iy] /= wsum;
10552 help->
zs[ix][iy] /= wsum;
10553 help->
ts[ix][iy] /= wsum;
10554 help->
us[ix][iy] /= wsum;
10555 help->
vs[ix][iy] /= wsum;
10556 help->
ess[ix][iy] /= wsum;
10557 help->
nss[ix][iy] /= wsum;
10558 help->
shf[ix][iy] /= wsum;
10559 help->
lsm[ix][iy] /= wsum;
10560 help->
sst[ix][iy] /= wsum;
10561 help->
pbl[ix][iy] /= wsum;
10562 help->
cape[ix][iy] /= wsum;
10563 help->
cin[ix][iy] /= wsum;
10564 help->
t[ix][iy][ip] /= wsum;
10565 help->
u[ix][iy][ip] /= wsum;
10566 help->
v[ix][iy][ip] /= wsum;
10567 help->
w[ix][iy][ip] /= wsum;
10568 help->
h2o[ix][iy][ip] /= wsum;
10569 help->
o3[ix][iy][ip] /= wsum;
10570 help->
lwc[ix][iy][ip] /= wsum;
10571 help->
rwc[ix][iy][ip] /= wsum;
10572 help->
iwc[ix][iy][ip] /= wsum;
10573 help->
swc[ix][iy][ip] /= wsum;
10574 help->
cc[ix][iy][ip] /= wsum;
10581 for (
int ix = 0; ix < help->
nx; ix += ctl->
met_dx) {
10582 met->
lon[met->
nx] = help->
lon[ix];
10584 for (
int iy = 0; iy < help->
ny; iy += ctl->
met_dy) {
10585 met->
lat[met->
ny] = help->
lat[iy];
10586 met->
ps[met->
nx][met->
ny] = help->
ps[ix][iy];
10587 met->
zs[met->
nx][met->
ny] = help->
zs[ix][iy];
10588 met->
ts[met->
nx][met->
ny] = help->
ts[ix][iy];
10589 met->
us[met->
nx][met->
ny] = help->
us[ix][iy];
10590 met->
vs[met->
nx][met->
ny] = help->
vs[ix][iy];
10591 met->
ess[met->
nx][met->
ny] = help->
ess[ix][iy];
10592 met->
nss[met->
nx][met->
ny] = help->
nss[ix][iy];
10593 met->
shf[met->
nx][met->
ny] = help->
shf[ix][iy];
10594 met->
lsm[met->
nx][met->
ny] = help->
lsm[ix][iy];
10595 met->
sst[met->
nx][met->
ny] = help->
sst[ix][iy];
10596 met->
pbl[met->
nx][met->
ny] = help->
pbl[ix][iy];
10598 met->
cin[met->
nx][met->
ny] = help->
cin[ix][iy];
10600 for (
int ip = 0; ip < help->
np; ip += ctl->
met_dp) {
10601 met->
p[met->
np] = help->
p[ip];
10602 met->
t[met->
nx][met->
ny][met->
np] = help->
t[ix][iy][ip];
10603 met->
u[met->
nx][met->
ny][met->
np] = help->
u[ix][iy][ip];
10604 met->
v[met->
nx][met->
ny][met->
np] = help->
v[ix][iy][ip];
10605 met->
w[met->
nx][met->
ny][met->
np] = help->
w[ix][iy][ip];
10606 met->
h2o[met->
nx][met->
ny][met->
np] = help->
h2o[ix][iy][ip];
10607 met->
o3[met->
nx][met->
ny][met->
np] = help->
o3[ix][iy][ip];
10608 met->
lwc[met->
nx][met->
ny][met->
np] = help->
lwc[ix][iy][ip];
10609 met->
rwc[met->
nx][met->
ny][met->
np] = help->
rwc[ix][iy][ip];
10610 met->
iwc[met->
nx][met->
ny][met->
np] = help->
iwc[ix][iy][ip];
10611 met->
swc[met->
nx][met->
ny][met->
np] = help->
swc[ix][iy][ip];
10612 met->
cc[met->
nx][met->
ny][met->
np] = help->
cc[ix][iy][ip];
10631 double p2[200], pv[
EP], pv2[200], t[
EP], t2[200], th[
EP],
10632 th2[200], z[
EP], z2[200];
10636 LOG(2,
"Calculate tropopause...");
10639#pragma omp parallel for default(shared)
10640 for (
int iz = 0; iz < met->
np; iz++)
10641 z[iz] =
Z(met->
p[iz]);
10642#pragma omp parallel for default(shared)
10643 for (
int iz = 0; iz <= 190; iz++) {
10644 z2[iz] = 4.5 + 0.1 * iz;
10645 p2[iz] =
P(z2[iz]);
10650#pragma omp parallel for default(shared) collapse(2)
10651 for (
int ix = 0; ix < met->
nx; ix++)
10652 for (
int iy = 0; iy < met->
ny; iy++)
10653 met->
pt[ix][iy] = NAN;
10657#pragma omp parallel for default(shared) collapse(2)
10658 for (
int ix = 0; ix < met->
nx; ix++)
10659 for (
int iy = 0; iy < met->
ny; iy++)
10667#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10668 for (
int ix = 0; ix < met->
nx; ix++)
10669 for (
int iy = 0; iy < met->
ny; iy++) {
10672 for (
int iz = 0; iz < met->
np; iz++)
10673 t[iz] = met->
t[ix][iy][iz];
10677 int iz = (int) gsl_stats_min_index(t2, 1, 171);
10678 if (iz > 0 && iz < 170)
10679 met->
pt[ix][iy] = (float) p2[iz];
10681 met->
pt[ix][iy] = NAN;
10689#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10690 for (
int ix = 0; ix < met->
nx; ix++)
10691 for (
int iy = 0; iy < met->
ny; iy++) {
10695 for (iz = 0; iz < met->
np; iz++)
10696 t[iz] = met->
t[ix][iy][iz];
10700 met->
pt[ix][iy] = NAN;
10701 for (iz = 0; iz <= 170; iz++) {
10703 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10704 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10709 if (iz > 0 && iz < 170)
10710 met->
pt[ix][iy] = (float) p2[iz];
10717 met->
pt[ix][iy] = NAN;
10718 for (; iz <= 170; iz++) {
10720 for (
int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
10721 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
10728 for (; iz <= 170; iz++) {
10730 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10731 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10736 if (iz > 0 && iz < 170)
10737 met->
pt[ix][iy] = (float) p2[iz];
10749#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
10750 for (
int ix = 0; ix < met->
nx; ix++)
10751 for (
int iy = 0; iy < met->
ny; iy++) {
10754 for (
int iz = 0; iz < met->
np; iz++)
10755 pv[iz] = met->
pv[ix][iy][iz];
10759 for (
int iz = 0; iz < met->
np; iz++)
10760 th[iz] =
THETA(met->
p[iz], met->
t[ix][iy][iz]);
10764 met->
pt[ix][iy] = NAN;
10765 for (
int iz = 0; iz <= 170; iz++)
10768 if (iz > 0 && iz < 170)
10769 met->
pt[ix][iy] = (float) p2[iz];
10776 ERRMSG(
"Cannot calculate tropopause!");
10779#pragma omp parallel for default(shared) collapse(2)
10780 for (
int ix = 0; ix < met->
nx; ix++)
10781 for (
int iy = 0; iy < met->
ny; iy++) {
10782 double h2ot, tt, zt;
10785 met->
lat[iy], &tt, ci, cw, 1);
10787 met->
lat[iy], &zt, ci, cw, 0);
10789 met->
lat[iy], &h2ot, ci, cw, 0);
10790 met->
tt[ix][iy] = (float) tt;
10791 met->
zt[ix][iy] = (float) zt;
10792 met->
h2ot[ix][iy] = (float) h2ot;
10799 const char *filename,
10809 LOG(1,
"Read observation data: %s", filename);
10813 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
10815 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
10817 ERRMSG(
"Set OBS_TYPE to 0 or 1!");
10820 for (
int i = 1; i < *nobs; i++)
10821 if (rt[i] < rt[i - 1])
10822 ERRMSG(
"Time must be ascending!");
10827 LOG(2,
"Number of observations: %d", *nobs);
10828 gsl_stats_minmax(&mini, &maxi, rt, 1, (
size_t) n);
10829 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
10830 gsl_stats_minmax(&mini, &maxi, rz, 1, (
size_t) n);
10831 LOG(2,
"Altitude range: %g ... %g km", mini, maxi);
10832 gsl_stats_minmax(&mini, &maxi, rlon, 1, (
size_t) n);
10833 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
10834 gsl_stats_minmax(&mini, &maxi, rlat, 1, (
size_t) n);
10835 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
10836 gsl_stats_minmax(&mini, &maxi, robs, 1, (
size_t) n);
10837 LOG(2,
"Observation range: %g ... %g", mini, maxi);
10843 const char *filename,
10853 if (!(in = fopen(filename,
"r")))
10854 ERRMSG(
"Cannot open file!");
10858 while (fgets(line,
LEN, in))
10859 if (sscanf(line,
"%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
10860 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
10861 if ((++(*nobs)) >=
NOBS)
10862 ERRMSG(
"Too many observations!");
10871 const char *filename,
10882 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
10883 ERRMSG(
"Cannot open file!");
10894 NC(nc_close(ncid));
10900 const char *filename,
10903 const char *varname,
10905 const char *defvalue,
10910 char fullname1[
LEN], fullname2[
LEN], rval[
LEN];
10912 int contain = 0, i;
10915 if (filename[strlen(filename) - 1] !=
'-')
10916 if (!(in = fopen(filename,
"r")))
10917 ERRMSG(
"Cannot open file!");
10921 sprintf(fullname1,
"%s[%d]", varname, arridx);
10922 sprintf(fullname2,
"%s[*]", varname);
10924 sprintf(fullname1,
"%s", varname);
10925 sprintf(fullname2,
"%s", varname);
10930 char dummy[
LEN], line[
LEN], rvarname[
LEN];
10931 while (fgets(line,
LEN, in)) {
10932 if (sscanf(line,
"%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
10933 if (strcasecmp(rvarname, fullname1) == 0 ||
10934 strcasecmp(rvarname, fullname2) == 0) {
10940 for (i = 1; i < argc - 1; i++)
10941 if (strcasecmp(argv[i], fullname1) == 0 ||
10942 strcasecmp(argv[i], fullname2) == 0) {
10943 sprintf(rval,
"%s", argv[i + 1]);
10954 if (strlen(defvalue) > 0)
10955 sprintf(rval,
"%s", defvalue);
10957 ERRMSG(
"Missing variable %s!\n", fullname1);
10961 LOG(1,
"%s = %s", fullname1, rval);
10965 sprintf(value,
"%s", rval);
10975 const double rhop) {
10978 const double rp_help = rp * 1e-6;
10981 const double rho =
RHO(p, T);
10984 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
10987 const double v = sqrt(8. *
KB * T / (M_PI * 4.8096e-26));
10990 const double lambda = 2. * eta / (rho * v);
10993 const double K = lambda / rp_help;
10996 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
10999 return 2. *
SQR(rp_help) * (rhop - rho) *
G0 / (9. * eta) * G;
11011 const int method) {
11017 gsl_interp_accel *acc = gsl_interp_accel_alloc();
11018 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (
size_t) n);
11021 gsl_spline_init(s, x, y, (
size_t) n);
11022 for (
int i = 0; i < n2; i++)
11025 else if (x2[i] >= x[n - 1])
11028 y2[i] = gsl_spline_eval(s, x2[i], acc);
11031 gsl_spline_free(s);
11032 gsl_interp_accel_free(acc);
11037 for (
int i = 0; i < n2; i++)
11040 else if (x2[i] >= x[n - 1])
11044 y2[i] =
LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
11058 float mean = 0, var = 0;
11060 for (
int i = 0; i < n; ++i) {
11062 var +=
SQR(data[i]);
11065 var = var / (float) n -
SQR(mean / (
float) n);
11067 return (var > 0 ? sqrtf(var) : 0);
11075 const double lat) {
11078 const double D = sec / 86400 - 0.5;
11081 const double g =
DEG2RAD(357.529 + 0.98560028 * D);
11082 const double q = 280.459 + 0.98564736 * D;
11083 const double L =
DEG2RAD(q + 1.915 * sin(g) + 0.020 * sin(2 * g));
11086 const double e =
DEG2RAD(23.439 - 0.00000036 * D);
11089 const double sindec = sin(e) * sin(L);
11092 const double ra = atan2(cos(e) * sin(L), cos(L));
11095 const double GMST = 18.697374558 + 24.06570982441908 * D;
11098 const double LST = GMST + lon / 15;
11101 const double h = LST / 12 * M_PI - ra;
11104 const double lat_help =
DEG2RAD(lat);
11107 return acos(sin(lat_help) * sindec +
11108 cos(lat_help) * sqrt(1 -
SQR(sindec)) * cos(h));
11120 const double remain,
11132 t1.tm_year = year - 1900;
11133 t1.tm_mon = mon - 1;
11139 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
11147 const int output) {
11154 static int iname = -1, igroup = -1, nname, ngroup, ct_name[
NTIMER];
11157 t1 = omp_get_wtime();
11162 rt_name[iname] += dt;
11163 rt_min[iname] = (ct_name[iname] <= 0 ? dt :
MIN(rt_min[iname], dt));
11164 rt_max[iname] = (ct_name[iname] <= 0 ? dt :
MAX(rt_max[iname], dt));
11168 rt_group[igroup] += t1 - t0;
11172 for (
int i = 0; i < nname; i++)
11173 LOG(1,
"TIMER_%s = %.3f s (min= %g s, mean= %g s,"
11174 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
11175 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
11176 for (
int i = 0; i < ngroup; i++)
11177 LOG(1,
"TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
11178 double total = 0.0;
11179 for (
int i = 0; i < nname; i++)
11180 total += rt_name[i];
11181 LOG(1,
"TIMER_TOTAL = %.3f s", total);
11185 for (iname = 0; iname < nname; iname++)
11186 if (strcasecmp(name, names[iname]) == 0)
11188 for (igroup = 0; igroup < ngroup; igroup++)
11189 if (strcasecmp(group, groups[igroup]) == 0)
11193 if (iname >= nname) {
11194 sprintf(names[iname],
"%s", name);
11195 if ((++nname) >=
NTIMER)
11196 ERRMSG(
"Too many timers!");
11200 if (igroup >= ngroup) {
11201 sprintf(groups[igroup],
"%s", group);
11202 if ((++ngroup) >=
NTIMER)
11203 ERRMSG(
"Too many groups!");
11213 const char *filename,
11214 const int offset) {
11221 int len = (int) strlen(filename);
11222 sprintf(tstr,
"%.4s", &filename[len - offset]);
11223 int year = atoi(tstr);
11224 sprintf(tstr,
"%.2s", &filename[len - offset + 5]);
11225 int mon = atoi(tstr);
11226 sprintf(tstr,
"%.2s", &filename[len - offset + 8]);
11227 int day = atoi(tstr);
11228 sprintf(tstr,
"%.2s", &filename[len - offset + 11]);
11229 int hour = atoi(tstr);
11230 sprintf(tstr,
"%.2s", &filename[len - offset + 14]);
11231 int min = atoi(tstr);
11234 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
11235 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
11236 ERRMSG(
"Cannot read time from filename!");
11239 time2jsec(year, mon, day, hour, min, 0, 0.0, &t);
11256 const double p1 = pt * 0.866877899;
11257 const double p0 = pt / 0.866877899;
11260 if (atm->
p[ip] > p0)
11262 else if (atm->
p[ip] < p1)
11265 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
11271 const char *filename,
11279 const double t0 = t - 0.5 * ctl->
dt_mod;
11280 const double t1 = t + 0.5 * ctl->
dt_mod;
11286 if (!(out = popen(
"gnuplot",
"w")))
11287 ERRMSG(
"Cannot create pipe to gnuplot!");
11290 fprintf(out,
"set out \"%s.png\"\n", filename);
11294 int year, mon, day, hour, min, sec;
11295 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11296 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
11297 year, mon, day, hour, min);
11302 ERRMSG(
"Cannot open file!");
11304 while (fgets(line,
LEN, in))
11305 fprintf(out,
"%s", line);
11312 if (!(out = fopen(filename,
"w")))
11313 ERRMSG(
"Cannot create file!");
11318 "# $1 = time [s]\n"
11319 "# $2 = altitude [km]\n"
11320 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
11321 for (
int iq = 0; iq < ctl->
nq; iq++)
11322 fprintf(out,
"# $%i = %s [%s]\n", iq + 5, ctl->
qnt_name[iq],
11324 fprintf(out,
"\n");
11327 for (
int ip = 0; ip < atm->
np; ip += ctl->
atm_stride) {
11334 fprintf(out,
"%.2f %g %g %g", atm->
time[ip],
Z(atm->
p[ip]),
11335 atm->
lon[ip], atm->
lat[ip]);
11336 for (
int iq = 0; iq < ctl->
nq; iq++) {
11341 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
11343 fprintf(out,
"\n");
11353 const char *filename,
11355 const atm_t *atm) {
11360 if (!(out = fopen(filename,
"w")))
11361 ERRMSG(
"Cannot create file!");
11385 for (
int iq = 0; iq < ctl->
nq; iq++)
11403 const char *filename,
11405 const atm_t *atm) {
11407 int tid, pid, ncid, varid;
11408 size_t start[2], count[2];
11411 nc_create(filename, NC_NETCDF4, &ncid);
11414 NC(nc_def_dim(ncid,
"time", 1, &tid));
11415 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11418 int dim_ids[2] = { tid, pid };
11419 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11420 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11421 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
11423 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
11425 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
11428 for (
int iq = 0; iq < ctl->
nq; iq++)
11438 NC(nc_enddef(ncid));
11446 for (
int iq = 0; iq < ctl->
nq; iq++)
11450 NC(nc_close(ncid));
11456 const char *dirname,
11462 static size_t out_cnt = 0;
11464 double r, r_start, r_stop;
11465 int year, mon, day, hour, min, sec;
11466 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
11467 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
11468 char filename_out[2 *
LEN] =
"traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
11470 int ncid, varid, tid, pid, cid;
11478 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11480 &min_start, &sec_start, &r_start);
11482 &min_stop, &sec_stop, &r_stop);
11484 sprintf(filename_out,
11485 "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc", dirname,
11486 year_start % 100, mon_start, day_start, hour_start,
11487 year_stop % 100, mon_stop, day_stop, hour_stop);
11488 LOG(1,
"Write traj file: %s", filename_out);
11491 start[0] = out_cnt;
11494 count[1] = (size_t) atm->
np;
11497 if (out_cnt == 0) {
11500 NC(nc_create(filename_out, NC_NETCDF4, &ncid));
11503 NC(nc_def_dim(ncid,
"time", NC_UNLIMITED, &tid));
11504 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11505 NC(nc_def_dim(ncid,
"TMDT", 7, &cid));
11510 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11511 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11512 NC_DEF_VAR(
"LAT", NC_DOUBLE, 2, dim_ids,
"Latitude",
"deg",
11514 NC_DEF_VAR(
"LON", NC_DOUBLE, 2, dim_ids,
"Longitude",
"deg",
11516 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 2, dim_ids,
"Pressure",
"hPa",
11518 NC_DEF_VAR(
"ZETA", NC_DOUBLE, 2, dim_ids,
"Zeta",
"K",
11520 for (
int iq = 0; iq < ctl->
nq; iq++)
11530 NC(nc_enddef(ncid));
11531 NC(nc_close(ncid));
11538 NC(nc_open(filename_out, NC_WRITE, &ncid));
11550 for (
int iq = 0; iq < ctl->
nq; iq++)
11554 NC(nc_close(ncid));
11557 if ((year == year_stop) && (mon == mon_stop)
11558 && (day == day_stop) && (hour == hour_stop)) {
11561 char filename_init[2 *
LEN] =
"./init_fix_YYYYMMDDHH.nc";
11562 sprintf(filename_init,
"%s/init_fix_%02d%02d%02d%02d.nc",
11563 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
11564 LOG(1,
"Write init file: %s", filename_init);
11567 nc_create(filename_init, NC_NETCDF4, &ncid);
11570 NC(nc_def_dim(ncid,
"time", 1, &tid));
11571 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11576 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11577 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11578 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
11580 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
11582 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
11585 for (
int iq = 0; iq < ctl->
nq; iq++)
11595 NC(nc_enddef(ncid));
11603 for (
int iq = 0; iq < ctl->
nq; iq++)
11607 NC(nc_close(ncid));
11614 const char *filename,
11616 const atm_t *atm) {
11618 int ncid, obsid, varid;
11620 size_t start[2], count[2];
11623 NC(nc_create(filename, NC_NETCDF4, &ncid));
11626 NC(nc_def_dim(ncid,
"obs", (
size_t) atm->
np, &obsid));
11629 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &obsid,
"time",
11630 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11631 NC_DEF_VAR(
"press", NC_DOUBLE, 1, &obsid,
"pressure",
"hPa",
11633 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &obsid,
"longitude",
"degrees_east",
11635 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &obsid,
"latitude",
"degrees_north",
11637 for (
int iq = 0; iq < ctl->
nq; iq++)
11646 NC(nc_enddef(ncid));
11653 for (
int iq = 0; iq < ctl->
nq; iq++)
11657 NC(nc_close(ncid));
11663 const char *filename,
11670 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
11673 static int *obscount, nobs, nk;
11677 const int ensemble = (ctl->
nens > 0);
11683 if (ctl->
qnt_m < 0)
11684 ERRMSG(
"Need quantity mass!");
11687 ERRMSG(
"Missing ensemble IDs!");
11689 ERRMSG(
"Too many ensembles!");
11696 ALLOC(area,
double,
11702 ALLOC(rlon,
double,
11704 ALLOC(rlat,
double,
11706 ALLOC(robs,
double,
11717 LOG(1,
"Write CSI%s data: %s", ensemble ?
" ensemble" :
"", filename);
11718 if (!(out = fopen(filename,
"w")))
11719 ERRMSG(
"Cannot create file!");
11723 "# $1 = time [s]\n"
11724 "# $2 = ensemble ID\n"
11725 "# $3 = number of hits (cx)\n"
11726 "# $4 = number of misses (cy)\n"
11727 "# $5 = number of false alarms (cz)\n"
11728 "# $6 = number of observations (cx + cy)\n"
11729 "# $7 = number of forecasts (cx + cz)\n"
11730 "# $8 = bias (%%)\n"
11731 "# $9 = POD (%%)\n"
11732 "# $10 = FAR (%%)\n"
11733 "# $11 = CSI (%%)\n"
11734 "# $12 = hits by random chance\n"
11735 "# $13 = ETS (%%)\n"
11736 "# $14 = Pearson R\n"
11737 "# $15 = Spearman R\n"
11738 "# $16 = mean error [kg/m²]\n"
11739 "# $17 = RMSE [kg/m²]\n"
11740 "# $18 = MAE [kg/m²]\n"
11741 "# $19 = log-likelihood\n" "# $20 = number of points\n\n");
11749 for (
int iy = 0; iy < ctl->
csi_ny; iy++) {
11750 const double lat = ctl->
csi_lat0 + dlat * (iy + 0.5);
11751 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.0) * cos(
DEG2RAD(lat));
11756 const double t0 = t - 0.5 * ctl->
dt_mod;
11757 const double t1 = t + 0.5 * ctl->
dt_mod;
11761 ALLOC(modmean,
double,
11762 (ensemble ? ctl->
nens : 1) * grid_size);
11763 ALLOC(obsmean,
double,
11765 ALLOC(obscount,
int,
11767 ALLOC(obsstd,
double,
11771 for (
int i = 0; i < (ensemble ? ctl->
nens : 1); i++)
11772 ct[i] = cx[i] = cy[i] = cz[i] = n[i] = 0;
11775 for (
int i = 0; i < nobs; i++) {
11776 if (rt[i] < t0 || rt[i] >= t1 || !isfinite(robs[i]))
11780 const int ix = (int) ((rlon[i] - ctl->
csi_lon0) / dlon);
11781 const int iy = (int) ((rlat[i] - ctl->
csi_lat0) / dlat);
11782 const int iz = (int) ((rz[i] - ctl->
csi_z0) / dz);
11783 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
11789 obsmean[idx] += robs[i];
11790 obsstd[idx] +=
SQR(robs[i]);
11795 for (
int ip = 0; ip < atm->
np; ip++) {
11798 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11802 int ens_id = ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
11803 if (ens_id < 0 || ens_id >= (ensemble ? ctl->
nens : 1))
11804 ERRMSG(
"Ensemble ID out of range!");
11807 const int ix = (int) ((atm->
lon[ip] - ctl->
csi_lon0) / dlon);
11808 const int iy = (int) ((atm->
lat[ip] - ctl->
csi_lat0) / dlat);
11809 const int iz = (int) ((
Z(atm->
p[ip]) - ctl->
csi_z0) / dz);
11810 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
11820 for (
int e = 0; e < (ensemble ? ctl->
nens : 1); e++) {
11822 for (
int ix = 0; ix < ctl->
csi_nx; ix++)
11823 for (
int iy = 0; iy < ctl->
csi_ny; iy++)
11824 for (
int iz = 0; iz < ctl->
csi_nz; iz++) {
11829 if (obscount[idx]) {
11830 obsmean[idx] /= obscount[idx];
11832 sqrt(obsstd[idx] / obscount[idx] -
SQR(obsmean[idx]));
11836 const int midx = e * grid_size + idx;
11837 if (modmean[midx] > 0)
11838 modmean[midx] /= (1e6 * area[iy]);
11841 if (obscount[idx]) {
11856 x[n[e]] = modmean[midx];
11857 y[n[e]] = obsmean[idx];
11859 obsstdn[n[e]] = obsstd[idx];
11860 if ((++n[e]) >=
NCSI)
11861 ERRMSG(
"Too many points for statistics!");
11873 static double work[2 *
NCSI], work2[2 *
NCSI];
11874 const int n_obs = cx[e] + cy[e];
11875 const int n_for = cx[e] + cz[e];
11876 const double cx_rd = (ct[e] > 0) ? (1. * n_obs * n_for) / ct[e] : NAN;
11877 const double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
11878 const double pod = (n_obs > 0) ? 100. * cx[e] / n_obs : NAN;
11879 const double far = (n_for > 0) ? 100. * cz[e] / n_for : NAN;
11881 (cx[e] + cy[e] + cz[e] >
11882 0) ? 100. * cx[e] / (cx[e] + cy[e] + cz[e]) : NAN;
11884 (cx[e] + cy[e] + cz[e] - cx_rd >
11885 0) ? 100. * (cx[e] - cx_rd) / (cx[e] + cy[e] + cz[e] - cx_rd) : NAN;
11886 const double rho_p = gsl_stats_correlation(x, 1, y, 1, (
size_t) n[e]);
11887 const double rho_s =
11888 gsl_stats_spearman(x, 1, y, 1, (
size_t) n[e], work);
11889 for (
int i = 0; i < n[e]; i++) {
11890 work[i] = x[i] - y[i];
11891 work2[i] = (obsstdn[i] != 0) ? work[i] / obsstdn[i] : 0;
11893 const double mean = gsl_stats_mean(work, 1, (
size_t) n[e]);
11894 const double rmse =
11895 gsl_stats_sd_with_fixed_mean(work, 1, (
size_t) n[e], 0.0);
11896 const double absdev = gsl_stats_absdev_m(work, 1, (
size_t) n[e], 0.0);
11897 const double loglikelihood =
11898 gsl_stats_tss_m(work2, 1, (
size_t) n[e], 0.0) * -0.5;
11902 "%.2f %d %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n",
11903 t, ensemble ? e : -999, cx[e], cy[e], cz[e], n_obs, n_for, bias,
11904 pod, far, csi, cx_rd, ets, rho_p, rho_s, mean, rmse, absdev,
11905 loglikelihood, n[e]);
11908 for (
int i = 0; i < n[e]; i++)
11909 work[i] = work2[i] = x[i] = y[i] = obsstdn[i] = 0;
11910 ct[e] = cx[e] = cy[e] = cz[e] = n[e] = 0;
11938 const char *filename,
11948 static int n[
NENS];
11955 ERRMSG(
"Missing ensemble IDs!");
11958 const double t0 = t - 0.5 * ctl->
dt_mod;
11959 const double t1 = t + 0.5 * ctl->
dt_mod;
11962 for (
int i = 0; i <
NENS; i++) {
11963 for (
int iq = 0; iq < ctl->
nq; iq++)
11964 qm[iq][i] = qs[iq][i] = 0;
11965 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
11970 for (
int ip = 0; ip < atm->
np; ip++) {
11973 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11978 ERRMSG(
"Ensemble ID is out of range!");
11982 for (
int iq = 0; iq < ctl->
nq; iq++) {
11983 qm[iq][ctl->
qnt_ens] += atm->
q[iq][ip];
11994 LOG(1,
"Write ensemble data: %s", filename);
11995 if (!(out = fopen(filename,
"w")))
11996 ERRMSG(
"Cannot create file!");
12000 "# $1 = time [s]\n"
12001 "# $2 = altitude [km]\n"
12002 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
12003 for (
int iq = 0; iq < ctl->
nq; iq++)
12004 fprintf(out,
"# $%d = %s (mean) [%s]\n", 5 + iq,
12006 for (
int iq = 0; iq < ctl->
nq; iq++)
12007 fprintf(out,
"# $%d = %s (sigma) [%s]\n", 5 + ctl->
nq + iq,
12009 fprintf(out,
"# $%d = number of members\n\n", 5 + 2 * ctl->
nq);
12012 for (
int i = 0; i <
NENS; i++)
12014 cart2geo(xm[i], &dummy, &lon, &lat);
12015 fprintf(out,
"%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
12016 for (
int iq = 0; iq < ctl->
nq; iq++) {
12018 fprintf(out, ctl->
qnt_format[iq], qm[iq][i] / n[i]);
12020 for (
int iq = 0; iq < ctl->
nq; iq++) {
12022 double var = qs[iq][i] / n[i] -
SQR(qm[iq][i] / n[i]);
12023 fprintf(out, ctl->
qnt_format[iq], (var > 0 ? sqrt(var) : 0));
12025 fprintf(out,
" %d\n", n[i]);
12035 const char *filename,
12042 static double kz[
EP], kw[
EP];
12046 double *cd, *mean[
NQ], *sigma[
NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
12048 int *ixs, *iys, *izs, *np;
12054 LOG(1,
"Write grid data: %s", filename);
12067 for (
int iq = 0; iq < ctl->
nq; iq++) {
12068 ALLOC(mean[iq],
double,
12070 ALLOC(sigma[iq],
double,
12073 ALLOC(vmr_impl,
double,
12081 ALLOC(area,
double,
12083 ALLOC(press,
double,
12100#pragma omp parallel
for default(shared)
12101 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
12102 z[iz] = ctl->
grid_z0 + dz * (iz + 0.5);
12103 press[iz] =
P(z[iz]);
12107 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12108 lon[ix] = ctl->
grid_lon0 + dlon * (ix + 0.5);
12109#pragma omp parallel for default(shared)
12110 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
12111 lat[iy] = ctl->
grid_lat0 + dlat * (iy + 0.5);
12112 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
12116 const double t0 = t - 0.5 * ctl->
dt_mod;
12117 const double t1 = t + 0.5 * ctl->
dt_mod;
12120#pragma omp parallel for default(shared)
12121 for (
int ip = 0; ip < atm->
np; ip++) {
12122 ixs[ip] = (int) ((atm->
lon[ip] - ctl->
grid_lon0) / dlon);
12123 iys[ip] = (int) ((atm->
lat[ip] - ctl->
grid_lat0) / dlat);
12124 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
grid_z0) / dz);
12125 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
12126 || ixs[ip] < 0 || ixs[ip] >= ctl->
grid_nx
12127 || iys[ip] < 0 || iys[ip] >= ctl->
grid_ny
12128 || izs[ip] < 0 || izs[ip] >= ctl->
grid_nz)
12133 for (
int ip = 0; ip < atm->
np; ip++)
12134 if (izs[ip] >= 0) {
12139 for (
int iq = 0; iq < ctl->
nq; iq++) {
12140 mean[iq][idx] += kernel * atm->
q[iq][ip];
12141 sigma[iq][idx] +=
SQR(kernel * atm->
q[iq][ip]);
12146#pragma omp parallel for default(shared)
12147 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12148 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12149 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
12156 if (ctl->
qnt_m >= 0)
12157 cd[idx] = mean[ctl->
qnt_m][idx] / (1e6 * area[iy]);
12160 vmr_impl[idx] = NAN;
12161 if (ctl->
qnt_m >= 0 && ctl->
molmass > 0 && met0 != NULL
12164 if (mean[ctl->
qnt_m][idx] > 0) {
12170 lon[ix], lat[iy], &temp, ci, cw, 1);
12174 MA / ctl->
molmass * cd[idx] / (
RHO(press[iz], temp) * dz * 1e3);
12180 for (
int iq = 0; iq < ctl->
nq; iq++) {
12181 mean[iq][idx] /= np[idx];
12182 const double var = sigma[iq][idx] / np[idx] -
SQR(mean[iq][idx]);
12183 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
12185 for (
int iq = 0; iq < ctl->
nq; iq++) {
12186 mean[iq][idx] = NAN;
12187 sigma[iq][idx] = NAN;
12194 t, z, lon, lat, area, dz, np);
12199 t, z, lon, lat, area, dz, np);
12203 ERRMSG(
"Grid data format GRID_TYPE unknown!");
12207 for (
int iq = 0; iq < ctl->
nq; iq++) {
12226 const char *filename,
12231 const double *vmr_impl,
12236 const double *area,
12246 if (!(out = popen(
"gnuplot",
"w")))
12247 ERRMSG(
"Cannot create pipe to gnuplot!");
12250 fprintf(out,
"set out \"%s.png\"\n", filename);
12254 int year, mon, day, hour, min, sec;
12255 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
12256 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
12257 year, mon, day, hour, min);
12263 ERRMSG(
"Cannot open file!");
12264 while (fgets(line,
LEN, in))
12265 fprintf(out,
"%s", line);
12272 if (!(out = fopen(filename,
"w")))
12273 ERRMSG(
"Cannot create file!");
12278 "# $1 = time [s]\n"
12279 "# $2 = altitude [km]\n"
12280 "# $3 = longitude [deg]\n"
12281 "# $4 = latitude [deg]\n"
12282 "# $5 = surface area [km^2]\n"
12283 "# $6 = layer depth [km]\n"
12284 "# $7 = column density (implicit) [kg/m^2]\n"
12285 "# $8 = volume mixing ratio (implicit) [ppv]\n"
12286 "# $9 = number of particles [1]\n");
12287 for (
int iq = 0; iq < ctl->
nq; iq++)
12288 fprintf(out,
"# $%i = %s (mean) [%s]\n", 10 + iq, ctl->
qnt_name[iq],
12291 for (
int iq = 0; iq < ctl->
nq; iq++)
12292 fprintf(out,
"# $%i = %s (stddev) [%s]\n", 10 + ctl->
nq + iq,
12294 fprintf(out,
"\n");
12297 for (
int ix = 0; ix < ctl->
grid_nx; ix++) {
12299 fprintf(out,
"\n");
12300 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
12302 fprintf(out,
"\n");
12303 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
12306 fprintf(out,
"%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
12307 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
12308 for (
int iq = 0; iq < ctl->
nq; iq++) {
12310 fprintf(out, ctl->
qnt_format[iq], mean[iq][idx]);
12313 for (
int iq = 0; iq < ctl->
nq; iq++) {
12315 fprintf(out, ctl->
qnt_format[iq], sigma[iq][idx]);
12317 fprintf(out,
"\n");
12330 const char *filename,
12335 const double *vmr_impl,
12340 const double *area,
12344 char longname[2 *
LEN], varname[2 *
LEN];
12348 int *help2, ncid, dimid[10], varid;
12350 size_t start[2], count[2];
12353 ALLOC(help,
double,
12359 NC(nc_create(filename, NC_NETCDF4, &ncid));
12362 NC(nc_def_dim(ncid,
"time", 1, &dimid[0]));
12363 NC(nc_def_dim(ncid,
"z", (
size_t) ctl->
grid_nz, &dimid[1]));
12364 NC(nc_def_dim(ncid,
"lat", (
size_t) ctl->
grid_ny, &dimid[2]));
12365 NC(nc_def_dim(ncid,
"lon", (
size_t) ctl->
grid_nx, &dimid[3]));
12366 NC(nc_def_dim(ncid,
"dz", 1, &dimid[4]));
12369 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &dimid[0],
"time",
12370 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
12371 NC_DEF_VAR(
"z", NC_DOUBLE, 1, &dimid[1],
"altitude",
"km", 0, 0);
12372 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &dimid[2],
"latitude",
"degrees_north", 0,
12374 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &dimid[3],
"longitude",
"degrees_east", 0,
12376 NC_DEF_VAR(
"dz", NC_DOUBLE, 1, &dimid[1],
"layer depth",
"km", 0, 0);
12377 NC_DEF_VAR(
"area", NC_DOUBLE, 1, &dimid[2],
"surface area",
"km**2", 0, 0);
12379 NC_DEF_VAR(
"cd", NC_FLOAT, 4, dimid,
"column density",
"kg m**-2",
12382 "volume mixing ratio (implicit)",
"ppv", ctl->
grid_nc_level, 0);
12383 NC_DEF_VAR(
"np", NC_INT, 4, dimid,
"number of particles",
"1", 0, 0);
12384 for (
int iq = 0; iq < ctl->
nq; iq++) {
12385 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
12386 sprintf(longname,
"%s (mean)", ctl->
qnt_longname[iq]);
12390 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
12391 sprintf(longname,
"%s (stddev)", ctl->
qnt_longname[iq]);
12397 NC(nc_enddef(ncid));
12407 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12408 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12409 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12414 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12415 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12416 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12421 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12422 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12423 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12428 for (
int iq = 0; iq < ctl->
nq; iq++) {
12429 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
12430 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12431 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12432 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12439 for (
int iq = 0; iq < ctl->
nq; iq++) {
12440 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
12441 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12442 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12443 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12450 NC(nc_close(ncid));
12460 const char *filename,
12466 if (!(out = fopen(filename,
"w")))
12467 ERRMSG(
"Cannot create file!");
12557 ERRMSG(
"Number of meteo variables doesn't match!");
12575 const char *varname) {
12584 for (
int ix = 0; ix < met->
nx; ix++)
12585 for (
int iy = 0; iy < met->
ny; iy++)
12586 help[
ARRAY_2D(ix, iy, met->
ny)] = var[ix][iy];
12589 LOG(2,
"Write 2-D variable: %s (uncompressed)", varname);
12591 (
size_t) (met->
nx * met->
ny),
12605 const char *varname,
12606 const int precision,
12607 const double tolerance) {
12616#pragma omp parallel for default(shared) collapse(2)
12617 for (
int ix = 0; ix < met->
nx; ix++)
12618 for (
int iy = 0; iy < met->
ny; iy++)
12619 for (
int ip = 0; ip < met->
np; ip++)
12620 help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)] = var[ix][iy][ip];
12624 LOG(2,
"Write 3-D variable: %s (uncompressed)", varname);
12626 (
size_t) (met->
nx * met->
ny * met->
np),
12633 (
size_t) met->
np, 0, out);
12641 FWRITE(&tolerance,
double,
12645 tolerance, 0, out);
12660 (
size_t) met->
np, 0, out);
12670 FWRITE(&tolerance,
double,
12674 tolerance, 0, out);
12680 ERRMSG(
"MET_TYPE not supported!");
12681 LOG(3,
"%d %g", precision, tolerance);
12691 const char *filename,
12697 size_t start[4], count[4];
12698 nc_create(filename, NC_NETCDF4, &ncid);
12701 int tid, lonid, latid, levid;
12702 NC(nc_def_dim(ncid,
"time", 1, &tid));
12703 NC(nc_def_dim(ncid,
"lon", (
size_t) met->
nx, &lonid));
12704 NC(nc_def_dim(ncid,
"lat", (
size_t) met->
ny, &latid));
12705 NC(nc_def_dim(ncid,
"lev", (
size_t) met->
np, &levid));
12708 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"time",
12709 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
12710 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &lonid,
"longitude",
"degrees_east", 0, 0);
12711 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &latid,
"latitude",
"degrees_north", 0, 0);
12712 NC_DEF_VAR(
"lev", NC_DOUBLE, 1, &levid,
"pressure",
"Pa", 0, 0);
12715 int dimid2[2] = { latid, lonid };
12716 NC_DEF_VAR(
"sp", NC_FLOAT, 2, dimid2,
"Surface pressure",
"Pa",
12718 NC_DEF_VAR(
"z", NC_FLOAT, 2, dimid2,
"Geopotential",
"m**2 s**-2",
12720 NC_DEF_VAR(
"t2m", NC_FLOAT, 2, dimid2,
"2 metre temperature",
"K",
12722 NC_DEF_VAR(
"u10m", NC_FLOAT, 2, dimid2,
"10 metre U wind component",
12724 NC_DEF_VAR(
"v10m", NC_FLOAT, 2, dimid2,
"10 metre V wind component",
12727 "Instantaneous eastward turbulent surface stress",
"N m**-2",
12730 "Instantaneous northward turbulent surface stress",
"N m**-2",
12733 "Instantaneous surface sensible heat flux",
"W m**-1",
12735 NC_DEF_VAR(
"lsm", NC_FLOAT, 2, dimid2,
"Land/sea mask",
"-",
12737 NC_DEF_VAR(
"sstk", NC_FLOAT, 2, dimid2,
"Sea surface temperature",
"K",
12739 NC_DEF_VAR(
"blp", NC_FLOAT, 2, dimid2,
"Boundary layer pressure",
"Pa",
12741 NC_DEF_VAR(
"pt", NC_FLOAT, 2, dimid2,
"Tropopause pressure",
"Pa",
12743 NC_DEF_VAR(
"tt", NC_FLOAT, 2, dimid2,
"Tropopause temperature",
"K",
12745 NC_DEF_VAR(
"zt", NC_FLOAT, 2, dimid2,
"Tropopause height",
"m",
12747 NC_DEF_VAR(
"h2ot", NC_FLOAT, 2, dimid2,
"Tropopause water vapor",
"ppv",
12749 NC_DEF_VAR(
"pct", NC_FLOAT, 2, dimid2,
"Cloud top pressure",
"Pa",
12751 NC_DEF_VAR(
"pcb", NC_FLOAT, 2, dimid2,
"Cloud bottom pressure",
"Pa",
12753 NC_DEF_VAR(
"cl", NC_FLOAT, 2, dimid2,
"Total column cloud water",
12756 "Pressure at lifted condensation level (LCL)",
"Pa",
12759 "Pressure at level of free convection (LFC)",
"Pa",
12762 "Pressure at equilibrium level (EL)",
"Pa", ctl->
met_nc_level,
12765 "Convective available potential energy",
"J kg**-1",
12767 NC_DEF_VAR(
"cin", NC_FLOAT, 2, dimid2,
"Convective inhibition",
12769 NC_DEF_VAR(
"o3c", NC_FLOAT, 2, dimid2,
"Total column ozone",
"DU",
12773 int dimid3[3] = { levid, latid, lonid };
12774 NC_DEF_VAR(
"t", NC_FLOAT, 3, dimid3,
"Temperature",
"K",
12776 NC_DEF_VAR(
"u", NC_FLOAT, 3, dimid3,
"U velocity",
"m s**-1",
12778 NC_DEF_VAR(
"v", NC_FLOAT, 3, dimid3,
"V velocity",
"m s**-1",
12780 NC_DEF_VAR(
"w", NC_FLOAT, 3, dimid3,
"Vertical velocity",
"Pa s**-1",
12782 NC_DEF_VAR(
"q", NC_FLOAT, 3, dimid3,
"Specific humidity",
"kg kg**-1",
12784 NC_DEF_VAR(
"o3", NC_FLOAT, 3, dimid3,
"Ozone mass mixing ratio",
12786 NC_DEF_VAR(
"clwc", NC_FLOAT, 3, dimid3,
"Cloud liquid water content",
12788 NC_DEF_VAR(
"crwc", NC_FLOAT, 3, dimid3,
"Cloud rain water content",
12790 NC_DEF_VAR(
"ciwc", NC_FLOAT, 3, dimid3,
"Cloud ice water content",
12792 NC_DEF_VAR(
"cswc", NC_FLOAT, 3, dimid3,
"Cloud snow water content",
12794 NC_DEF_VAR(
"cc", NC_FLOAT, 3, dimid3,
"Cloud cover",
"-",
12798 NC(nc_enddef(ncid));
12805 for (
int ip = 0; ip < met->
np; ip++)
12806 phelp[ip] = 100. * met->
p[ip];
12849 NC(nc_close(ncid));
12856 const char *varname,
12862 size_t start[4], count[4];
12870 for (
int ix = 0; ix < met->
nx; ix++)
12871 for (
int iy = 0; iy < met->
ny; iy++)
12872 help[
ARRAY_2D(iy, ix, met->
nx)] = scl * var[ix][iy];
12885 const char *varname,
12891 size_t start[4], count[4];
12899 for (
int ix = 0; ix < met->
nx; ix++)
12900 for (
int iy = 0; iy < met->
ny; iy++)
12901 for (
int ip = 0; ip < met->
np; ip++)
12902 help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)] = scl * var[ix][iy][ip];
12914 const char *filename,
12923 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
12924 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
12926 static int nobs, *obscount, ip, okay;
12935 if (ctl->
qnt_m < 0)
12936 ERRMSG(
"Need quantity mass!");
12940 ERRMSG(
"Specify molar mass!");
12947 ALLOC(area,
double,
12951 ALLOC(press,
double,
12957 ALLOC(rlon,
double,
12959 ALLOC(rlat,
double,
12961 ALLOC(robs,
double,
12968 LOG(1,
"Write profile data: %s", filename);
12969 if (!(out = fopen(filename,
"w")))
12970 ERRMSG(
"Cannot create file!");
12974 "# $1 = time [s]\n"
12975 "# $2 = altitude [km]\n"
12976 "# $3 = longitude [deg]\n"
12977 "# $4 = latitude [deg]\n"
12978 "# $5 = pressure [hPa]\n"
12979 "# $6 = temperature [K]\n"
12980 "# $7 = volume mixing ratio [ppv]\n"
12981 "# $8 = H2O volume mixing ratio [ppv]\n"
12982 "# $9 = O3 volume mixing ratio [ppv]\n"
12983 "# $10 = observed BT index [K]\n"
12984 "# $11 = number of observations\n");
12992 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
12993 z[iz] = ctl->
prof_z0 + dz * (iz + 0.5);
12994 press[iz] =
P(z[iz]);
12998 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
12999 lon[ix] = ctl->
prof_lon0 + dlon * (ix + 0.5);
13000 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
13001 lat[iy] = ctl->
prof_lat0 + dlat * (iy + 0.5);
13002 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
13007 const double t0 = t - 0.5 * ctl->
dt_mod;
13008 const double t1 = t + 0.5 * ctl->
dt_mod;
13011 ALLOC(mass,
double,
13013 ALLOC(obsmean,
double,
13015 ALLOC(obscount,
int,
13019 for (
int i = 0; i < nobs; i++) {
13024 else if (rt[i] >= t1)
13028 if (!isfinite(robs[i]))
13032 const int ix = (int) ((rlon[i] - ctl->
prof_lon0) / dlon);
13033 const int iy = (int) ((rlat[i] - ctl->
prof_lat0) / dlat);
13036 if (ix < 0 || ix >= ctl->
prof_nx || iy < 0 || iy >= ctl->
prof_ny)
13041 obsmean[idx] += robs[i];
13046 for (ip = 0; ip < atm->
np; ip++) {
13049 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13053 const int ix = (int) ((atm->
lon[ip] - ctl->
prof_lon0) / dlon);
13054 const int iy = (int) ((atm->
lat[ip] - ctl->
prof_lat0) / dlat);
13055 const int iz = (int) ((
Z(atm->
p[ip]) - ctl->
prof_z0) / dz);
13058 if (ix < 0 || ix >= ctl->
prof_nx ||
13064 mass[idx] += atm->
q[ctl->
qnt_m][ip];
13068 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
13069 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
13071 if (obscount[idx2] > 0) {
13075 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
13077 if (mass[idx3] > 0) {
13086 fprintf(out,
"\n");
13089 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
13094 lon[ix], lat[iy], &temp, ci, cw, 1);
13096 lon[ix], lat[iy], &h2o, ci, cw, 0);
13098 lon[ix], lat[iy], &o3, ci, cw, 0);
13103 / (
RHO(press[iz], temp) * area[iy] * dz * 1e9);
13106 fprintf(out,
"%.2f %g %g %g %g %g %g %g %g %g %d\n",
13107 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
13108 obsmean[idx2] / obscount[idx2], obscount[idx2]);
13141 const char *filename,
13150 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[
EP],
13153 static int nobs, nk;
13166 ALLOC(rlon,
double,
13168 ALLOC(rlat,
double,
13170 ALLOC(robs,
double,
13181 LOG(1,
"Write sample data: %s", filename);
13182 if (!(out = fopen(filename,
"w")))
13183 ERRMSG(
"Cannot create file!");
13187 "# $1 = time [s]\n"
13188 "# $2 = altitude [km]\n"
13189 "# $3 = longitude [deg]\n"
13190 "# $4 = latitude [deg]\n"
13191 "# $5 = surface area [km^2]\n"
13192 "# $6 = layer depth [km]\n"
13193 "# $7 = number of particles [1]\n"
13194 "# $8 = column density [kg/m^2]\n"
13195 "# $9 = volume mixing ratio [ppv]\n"
13196 "# $10 = observed BT index [K]\n\n");
13201 area = M_PI * rmax2;
13205 const double t0 = t - 0.5 * ctl->
dt_mod;
13206 const double t1 = t + 0.5 * ctl->
dt_mod;
13209 for (
int i = 0; i < nobs; i++) {
13214 else if (rt[i] >= t1)
13219 geo2cart(0, rlon[i], rlat[i], x0);
13222 const double rp =
P(rz[i]);
13223 const double ptop =
P(rz[i] + ctl->
sample_dz);
13224 const double pbot =
P(rz[i] - ctl->
sample_dz);
13232 for (
int ip = 0; ip < atm->
np; ip++) {
13235 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13239 if (fabs(rlat[i] - atm->
lat[ip]) > dlat)
13245 if (
DIST2(x0, x1) > rmax2)
13250 if (atm->
p[ip] > pbot || atm->
p[ip] < ptop)
13254 if (ctl->
qnt_m >= 0)
13261 const double cd = mass / (1e6 * area);
13272 rlon[i], rlat[i], &temp, ci, cw, 1);
13281 fprintf(out,
"%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
13282 rlon[i], rlat[i], area, ctl->
sample_dz, np, cd, vmr, robs[i]);
13303 const char *filename,
13310 static double rmax2, x0[3], x1[3];
13319 LOG(1,
"Write station data: %s", filename);
13322 if (!(out = fopen(filename,
"w")))
13323 ERRMSG(
"Cannot create file!");
13327 "# $1 = time [s]\n"
13328 "# $2 = altitude [km]\n"
13329 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
13330 for (
int iq = 0; iq < ctl->
nq; iq++)
13331 fprintf(out,
"# $%i = %s [%s]\n", (iq + 5),
13333 fprintf(out,
"\n");
13341 const double t0 = t - 0.5 * ctl->
dt_mod;
13342 const double t1 = t + 0.5 * ctl->
dt_mod;
13345 for (
int ip = 0; ip < atm->
np; ip++) {
13348 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13364 if (
DIST2(x0, x1) > rmax2)
13372 fprintf(out,
"%.2f %g %g %g",
13373 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]);
13374 for (
int iq = 0; iq < ctl->
nq; iq++) {
13376 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
13378 fprintf(out,
"\n");
13389 const char *filename,
13400 LOG(1,
"Write VTK data: %s", filename);
13403 const double t0 = t - 0.5 * ctl->
dt_mod;
13404 const double t1 = t + 0.5 * ctl->
dt_mod;
13407 if (!(out = fopen(filename,
"w")))
13408 ERRMSG(
"Cannot create file!");
13412 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13413 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13420 "# vtk DataFile Version 3.0\n"
13421 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
13424 fprintf(out,
"POINTS %d float\n", np);
13426 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13427 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13431 const double coslat = cos(
DEG2RAD(atm->
lat[ip]));
13432 const double x = radius * coslat * cos(
DEG2RAD(atm->
lon[ip]));
13433 const double y = radius * coslat * sin(
DEG2RAD(atm->
lon[ip]));
13434 const double z = radius * sin(
DEG2RAD(atm->
lat[ip]));
13435 fprintf(out,
"%g %g %g\n", x, y, z);
13438 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13439 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13441 fprintf(out,
"%g %g %g\n", atm->
lon[ip], atm->
lat[ip],
13446 fprintf(out,
"POINT_DATA %d\n", np);
13447 for (
int iq = 0; iq < ctl->
nq; iq++) {
13448 fprintf(out,
"SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
13450 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13451 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13453 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.
void intpol_met_space_2d(const met_t *met, float array[EX][EY], const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables in 2D space.
int read_met_nc_3d(const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const ctl_t *ctl, const met_t *met, dd_t *dd, float dest[EX][EY][EP], const float scl)
Reads a 3-dimensional meteorological variable from a NetCDF file.
int read_atm_nc(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a generic netCDF file and populates the given atmospheric structure.
void read_met_pbl(const ctl_t *ctl, met_t *met)
Computes the planetary boundary layer (PBL) pressure based on meteorological data.
void read_met_detrend(const ctl_t *ctl, met_t *met)
Detrends meteorological data.
void read_met_tropo(const ctl_t *ctl, const clim_t *clim, met_t *met)
Calculates the tropopause and related meteorological variables based on various methods and stores th...
void read_obs_asc(const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from an ASCII file.
void module_chem_init(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Initializes the chemistry modules by setting atmospheric composition.
int locate_reg(const double *xx, const int n, const double x)
Locate the index of the interval containing a given value in a regular grid.
void get_tropo(const int met_tropo, ctl_t *ctl, clim_t *clim, met_t *met, const double *lons, const int nx, const double *lats, const int ny, double *pt, double *zt, double *tt, double *qt, double *o3t, double *ps, double *zs)
Calculate tropopause data.
void read_met_nc_levels(const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads and processes meteorological level data from NetCDF files with domain decomposition.
void read_met_monotonize(const ctl_t *ctl, met_t *met)
Makes zeta and pressure profiles monotone.
int read_clim_ts(const char *filename, clim_ts_t *ts)
Reads a climatological time series from a file and populates the given time series structure.
void read_met_periodic(met_t *met)
Applies periodic boundary conditions to meteorological data along longitudinal axis.
void mptrac_run_timestep(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t **met0, met_t **met1, atm_t *atm, double t, dd_t *dd)
Executes a single timestep of the MPTRAC model simulation.
void module_timesteps_init(ctl_t *ctl, const atm_t *atm)
Initialize start time and time interval for time-stepping.
void write_ens(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes ensemble data to a file.
void module_mixing(const ctl_t *ctl, const clim_t *clim, atm_t *atm, const double t)
Update atmospheric properties through interparcel mixing.
double clim_zm(const clim_zm_t *zm, const double t, const double lat, const double p)
Interpolates monthly mean zonal mean climatological variables.
void module_mixing_help(const ctl_t *ctl, const clim_t *clim, atm_t *atm, const int *ixs, const int *iys, const int *izs, const int qnt_idx, const int use_ensemble)
Perform subgrid-scale interparcel mixing of a given quantity.
void read_clim_photo_help(const int ncid, const char *varname, const clim_photo_t *photo, double var[CP][CSZA][CO3])
Reads a 3D climatological photochemistry variable from a NetCDF file.
void read_met_ml2pl(const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname)
Interpolates meteorological data to specified pressure levels.
double clim_tropo(const clim_t *clim, const double t, const double lat)
Calculates the tropopause pressure based on climatological data.
void read_obs_nc(const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from a NetCDF file.
void read_met_bin_2d(FILE *in, const met_t *met, float var[EX][EY], const char *varname)
Reads a 2-dimensional meteorological variable from a binary file and stores it in the provided array.
int locate_irr(const double *xx, const int n, const double x)
Locate the index of the interval containing a given value in a sorted array.
void module_isosurf_init(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Initialize the isosurface module based on atmospheric data.
void level_definitions(ctl_t *ctl)
Defines pressure levels for meteorological data.
void write_grid_asc(const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
Writes grid data to an ASCII file.
void mptrac_update_device(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
Updates device memory for specified data structures.
void time2jsec(const int year, const int mon, const int day, const int hour, const int min, const int sec, const double remain, double *jsec)
Converts time components to seconds since January 1, 2000, 12:00:00 UTC.
void mptrac_init(ctl_t *ctl, cache_t *cache, clim_t *clim, atm_t *atm, const int ntask)
Initializes the MPTRAC model and its associated components.
void intpol_met_time_3d(const met_t *met0, float array0[EX][EY][EP], const met_t *met1, float array1[EX][EY][EP], const double ts, const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological data in 3D space and time.
void fft_help(double *fcReal, double *fcImag, const int n)
Computes the Fast Fourier Transform (FFT) of a complex sequence.
void module_wet_depo(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Perform wet deposition calculations for air parcels.
void compress_pck(const char *varname, float *array, const size_t nxy, const size_t nz, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats.
double nat_temperature(const double p, const double h2o, const double hno3)
Calculates the nitric acid trihydrate (NAT) temperature.
void spline(const double *x, const double *y, const int n, const double *x2, double *y2, const int n2, const int method)
Performs spline interpolation or linear interpolation.
void module_chem_grid(const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double tt)
Computes gridded chemical tracer concentrations (volume mixing ratio) from individual air parcel mass...
double clim_photo(const double rate[CP][CSZA][CO3], const clim_photo_t *photo, const double p, const double sza, const double o3c)
Calculates the photolysis rate for a given set of atmospheric conditions.
void read_clim_zm(const char *filename, const char *varname, clim_zm_t *zm)
Reads zonally averaged climatological data from a netCDF file and populates the given structure.
void read_met_nc_grid_dd_naive(dd_t *dd, const ctl_t *ctl, met_t *met, const int ncid)
Read meteorological grid data from a NetCDF file and set up subdomain decomposition with halos.
void module_sedi(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate sedimentation of particles in the atmosphere.
int read_met_nc(const char *filename, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads meteorological data from a NetCDF file and processes it.
void timer(const char *name, const char *group, const int output)
Measures and reports elapsed time for named and grouped timers.
void write_atm_asc(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes air parcel data to an ASCII file or gnuplot.
void intpol_met_space_3d(const met_t *met, float array[EX][EY][EP], const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables in 3D space.
void module_convection(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Performs convective mixing of atmospheric particles.
void read_kernel(const char *filename, double kz[EP], double kw[EP], int *nk)
Reads kernel function data from a file and populates the provided arrays.
void module_bound_cond(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Apply boundary conditions to particles based on meteorological and climatological data.
double scan_ctl(const char *filename, int argc, char *argv[], const char *varname, const int arridx, const char *defvalue, char *value)
Scans a control file or command-line arguments for a specified variable.
void module_advect_init(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Initializes the advection module by setting up pressure fields.
void mptrac_get_met(ctl_t *ctl, clim_t *clim, const double t, met_t **met0, met_t **met1, dd_t *dd)
Retrieves meteorological data for the specified time.
void module_sort_help(double *a, const int *p, const int np)
Reorder an array based on a given permutation.
float stddev(const float *data, const int n)
Calculates the standard deviation of a set of data.
void intpol_tropo_3d(const double time0, float array0[EX][EY], const double time1, float array1[EX][EY], const double lons[EX], const double lats[EY], const int nlon, const int nlat, const double time, const double lon, const double lat, const int method, double *var, double *sigma)
Interpolates tropopause data in 3D (latitude, longitude, and time).
void read_met_bin_3d(FILE *in, const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname, const float bound_min, const float bound_max)
Reads 3D meteorological data from a binary file, potentially using different compression methods.
int locate_irr_float(const float *xx, const int n, const double x, const int ig)
Locate the index of the interval containing a given value in an irregularly spaced array.
double time_from_filename(const char *filename, const int offset)
Extracts and converts a timestamp from a filename to Julian seconds.
void write_prof(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes profile data to a specified file.
void mptrac_read_clim(const ctl_t *ctl, clim_t *clim)
Reads various climatological data and populates the given climatology structure.
double tropo_weight(const clim_t *clim, const atm_t *atm, const int ip)
Computes a weighting factor based on tropopause pressure.
void write_met_nc(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a NetCDF file.
void module_rng_init(const int ntask)
Initialize random number generators for parallel tasks.
int mptrac_read_atm(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a specified file into the given atmospheric structure.
void mptrac_update_host(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
Updates host memory for specified data structures.
void mptrac_write_output(const char *dirname, const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double t)
Writes various types of output data to files in a specified directory.
double clim_oh(const ctl_t *ctl, const clim_t *clim, const double t, const double lon, const double lat, const double p)
Calculates the hydroxyl radical (OH) concentration from climatology data, with an optional diurnal co...
void read_met_ozone(met_t *met)
Calculates the total column ozone from meteorological ozone data.
void read_met_nc_surface(const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads and processes surface meteorological data from NetCDF files with domain decomposition.
void clim_tropo_init(clim_t *clim)
Initializes the tropopause data in the climatology structure.
void module_rng(const ctl_t *ctl, double *rs, const size_t n, const int method)
Generate random numbers using various methods and distributions.
void get_met_help(const ctl_t *ctl, const double t, const int direct, const char *metbase, const double dt_met, char *filename)
Generates a formatted filename for meteorological data files based on the input parameters.
void write_station(const char *filename, const ctl_t *ctl, atm_t *atm, const double t)
Writes station data to a specified file.
void cart2geo(const double *x, double *z, double *lon, double *lat)
State variables of cuRAND random number generator.
double sza_calc(const double sec, const double lon, const double lat)
Calculates the solar zenith angle.
void doy2day(const int year, const int doy, int *mon, int *day)
Converts a given day of the year (DOY) to a date (month and day).
void intpol_met_4d_zeta(const met_t *met0, float heights0[EX][EY][EP], float array0[EX][EY][EP], const met_t *met1, float heights1[EX][EY][EP], float array1[EX][EY][EP], const double ts, const double height, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables to a given position and time.
void intpol_met_time_2d(const met_t *met0, float array0[EX][EY], const met_t *met1, float array1[EX][EY], const double ts, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological data in 2D space and time.
void module_position(const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Update the positions and pressure levels of atmospheric particles.
void clim_oh_diurnal_correction(const ctl_t *ctl, clim_t *clim)
Applies a diurnal correction to the hydroxyl radical (OH) concentration in climatology data.
void locate_vert(float profiles[EX][EY][EP], const int np, const int lon_ap_ind, const int lat_ap_ind, const double height_ap, int *ind)
Locate the four vertical indizes of a box for a given height value.
void write_met_bin_2d(FILE *out, met_t *met, float var[EX][EY], const char *varname)
Writes a 2-dimensional meteorological variable to a binary file.
void read_met_pv(met_t *met)
Calculates potential vorticity (PV) from meteorological data.
int read_atm_bin(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a binary file and populates the given atmospheric structure.
void get_met_replace(char *orig, char *search, char *repl)
Replaces occurrences of a substring in a string with another substring.
void module_diff_meso(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate mesoscale diffusion for atmospheric particles.
void module_sort(const ctl_t *ctl, met_t *met0, atm_t *atm)
Sort particles according to box index.
double clim_ts(const clim_ts_t *ts, const double t)
Interpolates a time series of climatological variables.
void jsec2time(const double jsec, int *year, int *mon, int *day, int *hour, int *min, int *sec, double *remain)
Converts Julian seconds to calendar date and time components.
int read_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a binary file.
void write_atm_clams(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a NetCDF file in the CLaMS format.
void module_diff_turb(const ctl_t *ctl, cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Applies turbulent diffusion processes to atmospheric particles.
int read_atm_clams(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads atmospheric data from a CLAMS NetCDF file.
int mptrac_read_met(const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met, dd_t *dd)
Reads meteorological data from a file, supporting multiple formats and MPI broadcasting.
void write_vtk(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes VTK (Visualization Toolkit) data to a specified file.
void module_tracer_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Simulate chemical reactions involving long-lived atmospheric tracers.
void mptrac_read_ctl(const char *filename, int argc, char *argv[], ctl_t *ctl)
Reads control parameters from a configuration file and populates the given structure.
void mptrac_free(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm, dd_t *dd)
Frees memory resources allocated for MPTRAC.
void read_met_polar_winds(met_t *met)
Applies a fix for polar winds in meteorological data.
void module_h2o2_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Perform chemical reactions involving H2O2 within cloud particles.
void write_grid_nc(const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
Writes grid data to a NetCDF file.
double pbl_weight(const ctl_t *ctl, const atm_t *atm, const int ip, const double pbl, const double ps)
Computes a weighting factor based on planetary boundary layer pressure.
void module_diff_pbl(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Computes particle diffusion within the planetary boundary layer (PBL).
void write_met_nc_3d(const int ncid, const char *varname, met_t *met, float var[EX][EY][EP], const float scl)
Writes a 3D meteorological variable to a NetCDF file.
void module_isosurf(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Apply the isosurface module to adjust atmospheric properties.
void module_oh_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Perform hydroxyl chemistry calculations for atmospheric particles.
void geo2cart(const double z, const double lon, const double lat, double *x)
Converts geographic coordinates (longitude, latitude, altitude) to Cartesian coordinates.
void read_met_nc_grid(const char *filename, const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads meteorological grid data from NetCDF files with domain decomposition.
double kernel_weight(const double kz[EP], const double kw[EP], const int nk, const double p)
Calculates the kernel weight based on altitude and given kernel data.
int read_atm_asc(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from an ASCII file and populates the given atmospheric structure.
void intpol_check_lon_lat(const double *lons, const int nlon, const double *lats, const int nlat, const double lon, const double lat, double *lon2, double *lat2)
Adjusts longitude and latitude to ensure they fall within valid bounds.
void write_sample(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes sample data to a specified file.
void write_grid(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes grid data to a file in ASCII or netCDF format.
void module_dry_depo(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate dry deposition of atmospheric particles.
void write_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data in binary format to a specified file.
void write_atm_bin(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a binary file.
void read_met_cape(const ctl_t *ctl, const clim_t *clim, met_t *met)
Calculates Convective Available Potential Energy (CAPE) for each grid point.
void mptrac_write_met(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a file, supporting multiple formats and compression options.
double lapse_rate(const double t, const double h2o)
Calculates the moist adiabatic lapse rate in Kelvin per kilometer.
void write_csi(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes Critical Success Index (CSI) data to a file.
void write_atm_nc(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a NetCDF file.
MPTRAC library declarations.
#define NN(x0, y0, x1, y1, x)
Perform nearest-neighbor interpolation.
int dd_init(ctl_t *ctl, dd_t *dd, atm_t *atm)
Initializes domain decomposition for parallel processing.
void compress_zstd(const char *varname, float *array, const size_t n, const int decompress, const int level, FILE *inout)
Compresses or decompresses a float array using Zstandard (ZSTD).
#define LEN
Maximum length of ASCII data lines.
#define RE
Mean radius of Earth [km].
#define TVIRT(t, h2o)
Compute virtual temperature.
#define DD_NPOLE
Constant indicating the North pole [-].
void read_met_grib_surface(codes_handle **handles, const int num_messages, const ctl_t *ctl, met_t *met)
Reads surface meteorological data from a grib file and stores it in the meteorological data structure...
#define ARRAY_3D(ix, iy, ny, iz, nz)
Compute the linear index of a 3D array element.
#define PARTICLE_LOOP(ip0, ip1, check_dt,...)
Loop over particle indices with OpenACC acceleration.
#define MA
Molar mass of dry air [g/mol].
#define AVO
Avogadro constant [1/mol].
#define KB
Boltzmann constant [kg m^2/(K s^2)].
#define MH2O
Molar mass of water vapor [g/mol].
#define METVAR
Number of 3-D meteorological variables.
#define NENS
Maximum number of data points for ensemble analysis.
#define FWRITE(ptr, type, size, out)
Write data from memory to a file stream.
#define PW(p, h2o)
Calculate partial water vapor pressure.
#define H0
Scale height [km].
#define NC_PUT_ATT_GLOBAL(attname, text)
Add a global text attribute to a NetCDF file.
#define MOLEC_DENS(p, t)
Calculate the density of a gas molecule.
void dd_sort(const ctl_t *ctl, met_t *met0, atm_t *atm, dd_t *dd, int *nparticles, int *rank)
Sort particles according to box index and target rank for neighbours.
#define DD_SPOLE
Constant indicating the South pole [-].
#define LAPSE(p1, t1, p2, t2)
Calculate lapse rate.
#define NC(cmd)
Execute a NetCDF command and check for errors.
#define ECC_READ_3D(variable, level, target, scaling_factor, found_flag)
Writes 3D data from a grib message into the meteo struct.
#define DOTP(a, b)
Calculate the dot product of two vectors.
#define RA
Specific gas constant of dry air [J/(kg K)].
#define KARMAN
Karman's constant.
#define INTPOL_INIT
Initialize arrays for interpolation.
#define MIN(a, b)
Macro to determine the minimum of two values.
#define ERRMSG(...)
Print an error message with contextual information and terminate the program.
#define NC_PUT_INT(varname, ptr, hyperslab)
Write integer data to a NetCDF variable.
void compress_cms(const ctl_t *ctl, const char *varname, float *array, const size_t nx, const size_t ny, const size_t np, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using a custom multiscale compression algorithm.
void compress_zfp(const char *varname, float *array, const int nx, const int ny, const int nz, const int precision, const double tolerance, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using the ZFP library.
#define EY
Maximum number of latitudes for meteo data.
void dd_particles2atm(atm_t *atm, particle_t *particles, ctl_t *ctl, int *nparticles, cache_t *cache)
Converts particle data to atmospheric data.
#define SH(h2o)
Compute specific humidity from water vapor volume mixing ratio.
#define INTPOL_3D(var, init)
Perform 3D interpolation for a meteorological variable.
#define NOBS
Maximum number of observation data points.
#define NTHREADS
Maximum number of OpenMP threads.
#define ARRAY_2D(ix, iy, ny)
Macro for computing the linear index of a 2D array element.
#define Z(p)
Convert pressure to altitude.
#define codes_handle
Placeholder when ECCODES is not available.
#define P(z)
Compute pressure at given altitude.
#define LV
Latent heat of vaporization of water [J/kg].
#define G0
Standard gravity [m/s^2].
#define CP
Maximum number of pressure levels for climatological data.
#define NQ
Maximum number of quantities per data point.
#define FREAD(ptr, type, size, in)
Read data from a file stream and store it in memory.
#define DX2DEG(dx, lat)
Convert a distance in kilometers to degrees longitude at a given latitude.
#define DEG2DY(dlat)
Convert a latitude difference to a distance in the y-direction (north-south).
#define EX
Maximum number of longitudes for meteo data.
#define EPS
Ratio of the specific gas constant of dry air and water vapor [1].
#define PSICE(t)
Compute saturation pressure over ice (WMO, 2018).
#define THETA(p, t)
Compute potential temperature.
#define RI
Ideal gas constant [J/(mol K)].
int dd_is_periodic_longitude(met_t *met, int nx_glob)
Check whether the longitude grid is periodic (global coverage).
int read_met_grib(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a grib file and processes it.
#define SET_QNT(qnt, name, longname, unit)
Set atmospheric quantity index.
#define TICE(p, h2o)
Calculate frost point temperature (WMO, 2018).
#define TOK(line, tok, format, var)
Get string tokens.
void dd_get_rect_neighbour(const ctl_t ctl, dd_t *dd)
Determines rectangular neighbouring ranks for MPI processes.
#define ZDIFF(lnp0, t0, h2o0, lnp1, t1, h2o1)
Calculate geopotential height difference.
#define THETAVIRT(p, t, h2o)
Compute virtual potential temperature.
#define DZ2DP(dz, p)
Convert a change in altitude to a change in pressure.
void dd_atm2particles(atm_t *atm, particle_t *particles, ctl_t *ctl, int *nparticles, cache_t *cache, int rank)
Converts atmospheric data to particle data.
#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)
Assigns rectangular subdomains to atmospheric data particles.
#define DEG2RAD(deg)
Converts degrees to radians.
void broadcast_large_data(void *data, size_t N)
Broadcasts large data across all processes in an MPI communicator.
#define MO3
Molar mass of ozone [g/mol].
#define SQR(x)
Compute the square of a value.
#define RAD2DEG(rad)
Converts radians to degrees.
#define NP
Maximum number of atmospheric data points.
#define NTIMER
Maximum number of timers.
#define SELECT_TIMER(id, group, color)
Select and start a timer with specific attributes.
#define INTPOL_2D(var, init)
Perform 2D interpolation for a meteorological variable.
void dd_communicate_particles(particle_t *particles, int *nparticles, MPI_Datatype MPI_Particle, int *neighbours, int nneighbours, ctl_t ctl)
Communicates particles between MPI processes.
#define RH(p, t, h2o)
Compute relative humidity over water.
#define NC_PUT_FLOAT(varname, ptr, hyperslab)
Write a float array to a NetCDF file.
#define CY
Maximum number of latitudes for climatological data.
void module_dd(ctl_t *ctl, atm_t *atm, cache_t *cache, dd_t *dd, met_t **met)
Manages domain decomposition and particle communication in parallel processing.
void dd_sort_help(double *a, dd_t *dd, const int np)
Reorder an array according to a permutation vector.
#define LOG(level,...)
Print a log message with a specified logging level.
#define NC_DEF_VAR(varname, type, ndims, dims, long_name, units, level, quant)
Define a NetCDF variable with attributes.
#define TDEW(p, h2o)
Calculate dew point temperature.
#define ARRHENIUS(a, b, t)
Calculate the Arrhenius rate constant.
void dd_assign_rect_subdomains_atm(atm_t *atm, ctl_t *ctl, dd_t *dd, int init)
Assign atmospheric particles to rectangular subdomains.
#define NCSI
Maximum number of data points for CSI calculation.
#define NC_GET_DOUBLE(varname, ptr, force)
Retrieve a double-precision variable from a NetCDF file.
#define MPI_Datatype
Placeholder when MPI is not available.
#define EP
Maximum number of pressure levels for meteo data.
#define PSAT(t)
Compute saturation pressure over water.
#define DD_NPART
Maximum number of particles to send and recieve in domain decomposition.
#define RHO(p, t)
Compute density of air.
void module_kpp_chem(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
KPP chemistry module.
#define CO3
Maximum number of total column ozone data for climatological data.
void read_met_grib_grid(codes_handle **handles, int count_handles, met_t *met)
Reads global meteorological information from a grib file.
void compress_sz3(const char *varname, float *array, const int nx, const int ny, const int nz, const int precision, const double tolerance, const int decompress, FILE *inout)
Compresses or decompresses a 3-D float array using the SZ3 library.
void dd_register_MPI_type_particle(MPI_Datatype *MPI_Particle)
Registers a custom MPI datatype for particle structures.
#define NC_PUT_DOUBLE(varname, ptr, hyperslab)
Write double precision data to a NetCDF variable.
#define ECC(cmd)
Execute an ECCODES command and check for errors.
#define LIN(x0, y0, x1, y1, x)
Linear interpolation.
#define DIST2(a, b)
Calculate the squared Euclidean distance between two points in Cartesian coordinates.
#define NC_INQ_DIM(dimname, ptr, min, max, check)
Inquire the length of a dimension in a NetCDF file.
#define DEG2DX(dlon, lat)
Convert a longitude difference to a distance in the x-direction (east-west) at a specific latitude.
#define CPD
Specific heat of dry air at constant pressure [J/(kg K)].
#define CSZA
Maximum number of solar zenith angles for climatological data.
#define DY2DEG(dy)
Convert a distance in kilometers to degrees latitude.
#define MAX(a, b)
Macro to determine the maximum of two values.
#define DD_NNMAX
Maximum number of neighbours to communicate with in domain decomposition.
#define FMOD(x, y)
Calculate the floating-point remainder of dividing x by y.
double lat[NP]
Latitude [deg].
double lon[NP]
Longitude [deg].
int np
Number of air parcels.
double q[NQ][NP]
Quantity data (for various, user-defined attributes).
double p[NP]
Pressure [hPa].
double dt[NP]
Timesteps [s].
double iso_ts[NP]
Isosurface balloon time [s].
int iso_n
Isosurface balloon number of data points.
double iso_ps[NP]
Isosurface balloon pressure [hPa].
double rs[3 *NP+1]
Random numbers.
float uvwp[NP][3]
Wind perturbations [m/s].
double iso_var[NP]
Isosurface variables.
Climatological data in the form of photolysis rates.
int nsza
Number of solar zenith angles.
double sza[CSZA]
Solar zenith angle [rad].
double o3_1[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O1d + O2) [1/s].
double p[CP]
Pressure [hPa].
double ccl2f2[CP][CSZA][CO3]
CCl2F2 photolysis rate [1/s].
double o2[CP][CSZA][CO3]
O2 photolysis rate [1/s].
double ccl3f[CP][CSZA][CO3]
CCl3F photolysis rate [1/s].
double n2o[CP][CSZA][CO3]
N2O photolysis rate [1/s].
double h2o2[CP][CSZA][CO3]
H2O2 photolysis rate [1/s].
double h2o[CP][CSZA][CO3]
H2O photolysis rate [1/s].
double ccl4[CP][CSZA][CO3]
CCl4 photolysis rate [1/s].
double o3_2[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O3p + O2) [1/s].
double o3c[CO3]
Total column ozone [DU].
int np
Number of pressure levels.
int no3c
Number of total ozone columns.
clim_ts_t ccl2f2
CFC-12 time series.
clim_photo_t photo
Photolysis rates.
clim_zm_t ho2
HO2 zonal means.
clim_zm_t hno3
HNO3 zonal means.
int tropo_ntime
Number of tropopause timesteps.
clim_ts_t sf6
SF6 time series.
clim_ts_t ccl4
CFC-10 time series.
clim_ts_t ccl3f
CFC-11 time series.
clim_zm_t o1d
O(1D) zonal means.
double tropo_lat[73]
Tropopause latitudes [deg].
clim_zm_t h2o2
H2O2 zonal means.
int tropo_nlat
Number of tropopause latitudes.
clim_zm_t oh
OH zonal means.
double tropo[12][73]
Tropopause pressure values [hPa].
double tropo_time[12]
Tropopause time steps [s].
clim_ts_t n2o
N2O time series.
Climatological data in the form of time series.
double vmr[CTS]
Volume mixing ratio [ppv].
double time[CTS]
Time [s].
int ntime
Number of timesteps.
Climatological data in the form of zonal means.
int np
Number of pressure levels.
double p[CP]
Pressure [hPa].
double vmr[CT][CP][CY]
Volume mixing ratio [ppv].
int ntime
Number of timesteps.
int nlat
Number of latitudes.
double lat[CY]
Latitude [deg].
double grid_z0
Lower altitude of gridded data [km].
int qnt_o3
Quantity array index for ozone volume mixing ratio.
double csi_lat1
Upper latitude of gridded CSI data [deg].
char csi_obsfile[LEN]
Observation data file for CSI analysis.
int qnt_Coh
Quantity array index for OH volume mixing ratio (chemistry code).
double wet_depo_ic_a
Coefficient A for wet deposition in cloud (exponential form).
int met_nc_scale
Check netCDF scaling factors (0=no, 1=yes).
int qnt_pel
Quantity array index for pressure at equilibrium level (EL).
int csi_nz
Number of altitudes of gridded CSI data.
double molmass
Molar mass [g/mol].
int qnt_p
Quantity array index for pressure.
int qnt_Cccl2f2
Quantity array index for CFC-12 volume mixing ratio (chemistry code).
int dd_halos_size
Domain decomposition size of halos given in grid-points.
char atm_gpfile[LEN]
Gnuplot file for atmospheric data.
int mixing_nx
Number of longitudes of mixing grid.
double chemgrid_z1
Upper altitude of chemistry grid [km].
char qnt_format[NQ][LEN]
Quantity output format.
int qnt_m
Quantity array index for mass.
int qnt_aoa
Quantity array index for age of air.
int qnt_rhop
Quantity array index for particle density.
int qnt_swc
Quantity array index for cloud snow water content.
double csi_obsmin
Minimum observation index to trigger detection.
int qnt_pcb
Quantity array index for cloud bottom pressure.
char clim_n2o_timeseries[LEN]
Filename of N2O time series.
double bound_dzs
Boundary conditions surface layer depth [km].
double csi_lon1
Upper longitude of gridded CSI data [deg].
int qnt_u
Quantity array index for zonal wind.
double stat_lon
Longitude of station [deg].
double mixing_trop
Interparcel exchange parameter for mixing in the troposphere.
double sort_dt
Time step for sorting of particle data [s].
double mixing_z1
Upper altitude of mixing grid [km].
double stat_r
Search radius around station [km].
double wet_depo_bc_a
Coefficient A for wet deposition below cloud (exponential form).
int met_zstd_level
ZSTD compression level (from -5 to 22).
int csi_ny
Number of latitudes of gridded CSI data.
int vtk_sphere
Spherical projection for VTK data (0=no, 1=yes).
double chemgrid_z0
Lower altitude of chemistry grid [km].
double met_pbl_min
Minimum depth of planetary boundary layer [km].
int qnt_iwc
Quantity array index for cloud ice water content.
double chemgrid_lat0
Lower latitude of chemistry grid [deg].
double conv_cape
CAPE threshold for convection module [J/kg].
int qnt_Co1d
Quantity array index for O(1D) volume mixing ratio (chemistry code).
double met_cms_eps_pv
cmultiscale compression epsilon for potential vorticity.
int qnt_pw
Quantity array index for partial water vapor pressure.
char prof_basename[LEN]
Basename for profile output file.
double grid_z1
Upper altitude of gridded data [km].
int direction
Direction flag (1=forward calculation, -1=backward calculation).
char balloon[LEN]
Balloon position filename.
int qnt_Cccl4
Quantity array index for CFC-10 volume mixing ratio (chemistry code).
int met_dp
Stride for pressure levels.
double met_dt_out
Time step for sampling of meteo data along trajectories [s].
int qnt_h2o2
Quantity array index for H2O2 volume mixing ratio (climatology).
int qnt_vh
Quantity array index for horizontal wind.
char species[LEN]
Species.
int csi_nx
Number of longitudes of gridded CSI data.
double csi_lat0
Lower latitude of gridded CSI data [deg].
double turb_dz_trop
Vertical turbulent diffusion coefficient (troposphere) [m^2/s].
int met_pbl
Planetary boundary layer data (0=file, 1=z2p, 2=Richardson, 3=theta).
double met_comp_tol[METVAR]
Compression tolerance for SZ3 or ZFP.
int qnt_lwc
Quantity array index for cloud liquid water content.
double turb_mesoz
Vertical scaling factor for mesoscale wind fluctuations.
int grid_nc_level
zlib compression level of netCDF grid data files (0=off).
int grid_nx
Number of longitudes of gridded data.
int atm_type
Type of atmospheric data files (0=ASCII, 1=binary, 2=netCDF, 3=CLaMS_traj, 4=CLaMS_pos).
double bound_mass
Boundary conditions mass per particle [kg].
double grid_lat0
Lower latitude of gridded data [deg].
int qnt_ts
Quantity array index for surface temperature.
int qnt_loss_rate
Quantity array index for total loss rate.
double met_cms_eps_h2o
cmultiscale compression epsilon for water vapor.
int qnt_plfc
Quantity array index for pressure at level of free convection (LCF).
double grid_lon0
Lower longitude of gridded data [deg].
int qnt_o1d
Quantity array index for O(1D) volume mixing ratio (climatology).
int met_tropo_spline
Tropopause interpolation method (0=linear, 1=spline).
char sample_kernel[LEN]
Kernel data file for sample output.
int qnt_tvirt
Quantity array index for virtual temperature.
double dt_met
Time step of meteo data [s].
char clim_ho2_filename[LEN]
Filename of HO2 climatology.
double chemgrid_lat1
Upper latitude of chemistry grid [deg].
int met_geopot_sy
Latitudinal smoothing of geopotential heights.
char grid_gpfile[LEN]
Gnuplot file for gridded data.
double met_cms_eps_u
cmultiscale compression epsilon for zonal wind.
double turb_dx_strat
Horizontal turbulent diffusion coefficient (stratosphere) [m^2/s].
int qnt_vmr
Quantity array index for volume mixing ratio.
int qnt_lsm
Quantity array index for land-sea mask.
int qnt_theta
Quantity array index for potential temperature.
double bound_lat1
Boundary conditions maximum longitude [deg].
double stat_t1
Stop time for station output [s].
char csi_kernel[LEN]
Kernel data file for CSI output.
double turb_dx_trop
Horizontal turbulent diffusion coefficient (troposphere) [m^2/s].
int grid_type
Type of grid data files (0=ASCII, 1=netCDF).
double csi_lon0
Lower longitude of gridded CSI data [deg].
int qnt_pbl
Quantity array index for boundary layer pressure.
double oh_chem[4]
Coefficients for OH reaction rate (A, E/R or k0, n, kinf, m).
int grid_stddev
Include standard deviations in grid output (0=no, 1=yes).
int qnt_psice
Quantity array index for saturation pressure over ice.
double chemgrid_lon0
Lower longitude of chemistry grid [deg].
int bound_pbl
Boundary conditions planetary boundary layer (0=no, 1=yes).
int qnt_mloss_wet
Quantity array index for total mass loss due to wet deposition.
int met_geopot_sx
Longitudinal smoothing of geopotential heights.
int met_sy
Smoothing for latitudes.
int qnt_ps
Quantity array index for surface pressure.
int rng_type
Random number generator (0=GSL, 1=Squares, 2=cuRAND).
char prof_obsfile[LEN]
Observation data file for profile output.
int isosurf
Isosurface parameter (0=none, 1=pressure, 2=density, 3=theta, 4=balloon).
double bound_p1
Boundary conditions top pressure [hPa].
int qnt_zs
Quantity array index for surface geopotential height.
int prof_nz
Number of altitudes of gridded profile data.
double csi_dt_out
Time step for CSI output [s].
int met_cape
Convective available potential energy data (0=file, 1=calculate).
double csi_modmin
Minimum column density to trigger detection [kg/m^2].
int met_sx
Smoothing for longitudes.
double chemgrid_lon1
Upper longitude of chemistry grid [deg].
double turb_mesox
Horizontal scaling factor for mesoscale wind fluctuations.
double met_cms_eps_iwc
cmultiscale compression epsilon for cloud ice water content.
double met_cms_eps_swc
cmultiscale compression epsilon for cloud snow water content.
char grid_kernel[LEN]
Kernel data file for grid output.
double met_cms_eps_v
cmultiscale compression epsilon for meridional wind.
double prof_z0
Lower altitude of gridded profile data [km].
int qnt_w
Quantity array index for vertical velocity.
double bound_vmr
Boundary conditions volume mixing ratio [ppv].
double met_tropo_pv
Dynamical tropopause potential vorticity threshold [PVU].
int prof_nx
Number of longitudes of gridded profile data.
int qnt_stat
Quantity array index for station flag.
int met_tropo
Tropopause definition (0=none, 1=clim, 2=cold point, 3=WMO_1st, 4=WMO_2nd, 5=dynamical).
int qnt_rp
Quantity array index for particle radius.
int met_mpi_share
Use MPI to share meteo (0=no, 1=yes).
double mixing_strat
Interparcel exchange parameter for mixing in the stratosphere.
int qnt_vz
Quantity array index for vertical velocity.
int qnt_ho2
Quantity array index for HO2 volume mixing ratio (climatology).
double csi_z1
Upper altitude of gridded CSI data [km].
double stat_t0
Start time for station output [s].
double oh_chem_beta
Beta parameter for diurnal variablity of OH.
int dd
Domain decomposition (0=no, 1=yes, with 2x2 if not specified).
char clim_o1d_filename[LEN]
Filename of O(1D) climatology.
int qnt_eta
Quantity array index for eta vertical coordinate.
char clim_photo[LEN]
Filename of photolysis rates climatology.
double wet_depo_so2_ph
pH value used to calculate effective Henry constant of SO2.
double mixing_z0
Lower altitude of mixing grid [km].
int qnt_mloss_decay
Quantity array index for total mass loss due to exponential decay.
int atm_type_out
Type of atmospheric data files for output (-1=same as ATM_TYPE, 0=ASCII, 1=binary,...
int met_nlev
Number of meteo data model levels.
double dt_kpp
Time step for KPP chemistry [s].
char csi_basename[LEN]
Basename of CSI data files.
double dry_depo_dp
Dry deposition surface layer [hPa].
int qnt_shf
Quantity array index for surface sensible heat flux.
int qnt_vs
Quantity array index for surface meridional wind.
int qnt_Cco
Quantity array index for CO volume mixing ratio (chemistry code).
double vtk_dt_out
Time step for VTK data output [s].
double t_stop
Stop time of simulation [s].
double conv_dt
Time interval for convection module [s].
char sample_obsfile[LEN]
Observation data file for sample output.
int qnt_hno3
Quantity array index for HNO3 volume mixing ratio (climatology).
char grid_basename[LEN]
Basename of grid data files.
int met_clams
Read MPTRAC or CLaMS meteo data (0=MPTRAC, 1=CLaMS).
int met_comp_prec[METVAR]
Compression precision for SZ3 or ZFP.
int qnt_h2ot
Quantity array index for tropopause water vapor volume mixing ratio.
int qnt_rh
Quantity array index for relative humidity over water.
double met_cms_eps_cc
cmultiscale compression epsilon for cloud cover.
double bound_lat0
Boundary conditions minimum longitude [deg].
double met_pbl_max
Maximum depth of planetary boundary layer [km].
int met_dx
Stride for longitudes.
int qnt_destination
Quantity array index for destination subdomain in domain decomposition.
int mixing_ny
Number of latitudes of mixing grid.
int met_convention
Meteo data layout (0=[lev, lat, lon], 1=[lon, lat, lev]).
int qnt_zeta_d
Quantity array index for diagnosed zeta vertical coordinate.
char clim_h2o2_filename[LEN]
Filename of H2O2 climatology.
int tracer_chem
Switch for first order tracer chemistry module (0=off, 1=on).
double dt_mod
Time step of simulation [s].
int diffusion
Diffusion scheme (0=off, 1=fixed-K, 2=PBL).
int qnt_tnat
Quantity array index for T_NAT.
int qnt_eta_dot
Quantity array index for velocity of eta vertical coordinate.
int qnt_tice
Quantity array index for T_ice.
int qnt_zg
Quantity array index for geopotential height.
double vtk_offset
Vertical offset for VTK data [km].
int qnt_v
Quantity array index for meridional wind.
int qnt_mloss_dry
Quantity array index for total mass loss due to dry deposition.
double bound_vmr_trend
Boundary conditions volume mixing ratio trend [ppv/s].
int met_cache
Preload meteo data into disk cache (0=no, 1=yes).
int qnt_oh
Quantity array index for OH volume mixing ratio (climatology).
char qnt_unit[NQ][LEN]
Quantity units.
int qnt_Ch
Quantity array index for H volume mixing ratio (chemistry code).
int met_press_level_def
Use predefined pressure levels or not.
int oh_chem_reaction
Reaction type for OH chemistry (0=none, 2=bimolecular, 3=termolecular).
int qnt_h2o
Quantity array index for water vapor volume mixing ratio.
int prof_ny
Number of latitudes of gridded profile data.
int qnt_rhice
Quantity array index for relative humidity over ice.
int qnt_rho
Quantity array index for density of air.
double sample_dz
Layer depth for sample output [km].
double tdec_strat
Life time of particles in the stratosphere [s].
int obs_type
Type of observation data files (0=ASCII, 1=netCDF).
int grid_nc_quant[NQ]
Number of digits for quantization of netCDF grid data files (0=off).
double met_cms_eps_lwc
cmultiscale compression epsilon for cloud liquid water content.
int qnt_us
Quantity array index for surface zonal wind.
double met_cms_eps_z
cmultiscale compression epsilon for geopotential height.
double grid_lon1
Upper longitude of gridded data [deg].
int qnt_Cn2o
Quantity array index for N2O volume mixing ratio (chemistry code).
int qnt_Cccl3f
Quantity array index for CFC-11 volume mixing ratio (chemistry code).
char qnt_name[NQ][LEN]
Quantity names.
char atm_basename[LEN]
Basename of atmospheric data files.
double mixing_lat0
Lower latitude of mixing grid [deg].
int nens
Number of ensembles.
int qnt_pt
Quantity array index for tropopause pressure.
int qnt_cl
Quantity array index for total column cloud water.
int advect
Advection scheme (0=off, 1=Euler, 2=midpoint, 4=Runge-Kutta).
double prof_z1
Upper altitude of gridded profile data [km].
double met_lev_hyam[EP]
Meteo data model level a coefficients.
int qnt_t
Quantity array index for temperature.
int atm_filter
Time filter for atmospheric data output (0=none, 1=missval, 2=remove).
int kpp_chem
Switch for KPP chemistry module (0=off, 1=on).
int qnt_zeta
Quantity array index for zeta vertical coordinate.
double conv_pbl_trans
Depth of PBL transition layer (fraction of PBL depth).
char ens_basename[LEN]
Basename of ensemble data file.
double wet_depo_pre[2]
Coefficients for precipitation calculation.
int met_vert_coord
Vertical coordinate of input meteo data (0=plev, 1=mlev_p_file, 2=mlev_ab_file, 3=mlev_ab_full,...
double csi_z0
Lower altitude of gridded CSI data [km].
int qnt_lapse
Quantity array index for lapse rate.
double stat_lat
Latitude of station [deg].
int qnt_Cho2
Quantity array index for HO2 volume mixing ratio (chemistry code).
double wet_depo_bc_h[2]
Coefficients for wet deposition below cloud (Henry's law: Hb, Cb).
int grid_ny
Number of latitudes of gridded data.
int qnt_Csf6
Quantity array index for SF6 volume mixing ratio (chemistry code).
int qnt_Ch2o
Quantity array index for H2O volume mixing ratio (chemistry code).
double met_detrend
FWHM of horizontal Gaussian used for detrending [km].
int conv_mix_pbl
Vertical mixing in the PBL (0=off, 1=on).
char metbase[LEN]
Basename for meteo data.
double bound_dps
Boundary conditions surface layer depth [hPa].
int dd_nbr_neighbours
Domain decomposition number of neighbours to communicate with.
double met_cms_eps_t
cmultiscale compression epsilon for temperature.
int chemgrid_nz
Number of altitudes of chemistry grid.
int qnt_cape
Quantity array index for convective available potential energy (CAPE).
int qnt_zeta_dot
Quantity array index for velocity of zeta vertical coordinate.
double bound_mass_trend
Boundary conditions mass per particle trend [kg/s].
int mixing_nz
Number of altitudes of mixing grid.
int qnt_o3c
Quantity array index for total column ozone.
double bound_p0
Boundary conditions bottom pressure [hPa].
double mixing_lon0
Lower longitude of mixing grid [deg].
char clim_ccl4_timeseries[LEN]
Filename of CFC-10 time series.
int qnt_Co3
Quantity array index for O3 volume mixing ratio (chemistry code).
int qnt_tsts
Quantity array index for T_STS.
int grid_nz
Number of altitudes of gridded data.
char clim_oh_filename[LEN]
Filename of OH climatology.
int qnt_nss
Quantity array index for northward turbulent surface stress.
double ens_dt_out
Time step for ensemble output [s].
char sample_basename[LEN]
Basename of sample data file.
int atm_stride
Particle index stride for atmospheric data files.
int met_relhum
Try to read relative humidity (0=no, 1=yes).
double mixing_lat1
Upper latitude of mixing grid [deg].
double atm_dt_out
Time step for atmospheric data output [s].
char clim_sf6_timeseries[LEN]
Filename of SF6 time series.
double prof_lat1
Upper latitude of gridded profile data [deg].
int met_cms_batch
cmultiscale batch size.
double psc_h2o
H2O volume mixing ratio for PSC analysis.
int met_sp
Smoothing for pressure levels.
double prof_lon0
Lower longitude of gridded profile data [deg].
int chemgrid_nx
Number of longitudes of chemistry grid.
int qnt_pct
Quantity array index for cloud top pressure.
int qnt_mloss_kpp
Quantity array index for total mass loss due to KPP chemistry.
int qnt_psat
Quantity array index for saturation pressure over water.
int qnt_subdomain
Quantity array index for current subdomain in domain decomposition.
double met_lev_hybm[EP]
Meteo data model level b coefficients.
double prof_lat0
Lower latitude of gridded profile data [deg].
int qnt_cin
Quantity array index for convective inhibition (CIN).
double psc_hno3
HNO3 volume mixing ratio for PSC analysis.
double prof_lon1
Upper longitude of gridded profile data [deg].
double met_cms_eps_rwc
cmultiscale compression epsilon for cloud rain water content.
int met_nc_quant
Number of digits for quantization of netCDF meteo files (0=off).
int h2o2_chem_reaction
Reaction type for H2O2 chemistry (0=none, 1=SO2).
int qnt_Co3p
Quantity array index for O(3P) volume mixing ratio (chemistry code).
int atm_nc_quant[NQ]
Number of digits for quantization of netCDF atmospheric data files (0=off).
double wet_depo_bc_ret_ratio
Coefficients for wet deposition below cloud: retention ratio.
int chemgrid_ny
Number of latitudes of chemistry grid.
char clim_ccl3f_timeseries[LEN]
Filename of CFC-11 time series.
double met_cms_eps_o3
cmultiscale compression epsilon for ozone.
int met_cms_zstd
cmultiscale ZSTD compression (0=off, 1=on).
int grid_sparse
Sparse output in grid data files (0=no, 1=yes).
char vtk_basename[LEN]
Basename of VTK data files.
double dry_depo_vdep
Dry deposition velocity [m/s].
int qnt_tt
Quantity array index for tropopause temperature.
int met_np
Number of target pressure levels.
int qnt_ens
Quantity array index for ensemble IDs.
int met_nc_level
zlib compression level of netCDF meteo files (0=off).
double mixing_dt
Time interval for mixing [s].
int qnt_mloss_h2o2
Quantity array index for total mass loss due to H2O2 chemistry.
double vtk_scale
Vertical scaling factor for VTK data.
char clim_ccl2f2_timeseries[LEN]
Filename of CFC-12 time series.
double met_cms_eps_w
cmultiscale compression epsilon for vertical velocity.
double wet_depo_ic_h[2]
Coefficients for wet deposition in cloud (Henry's law: Hb, Cb).
double turb_dx_pbl
Horizontal turbulent diffusion coefficient (PBL) [m^2/s].
double conv_cin
CIN threshold for convection module [J/kg].
int qnt_pv
Quantity array index for potential vorticity.
int advect_vert_coord
Vertical velocity of air parcels (0=omega_on_plev, 1=zetadot_on_mlev, 2=omega_on_mlev,...
int qnt_mloss_oh
Quantity array index for total mass loss due to OH chemistry.
int qnt_Ch2o2
Quantity array index for H2O2 volume mixing ratio (chemistry code).
int qnt_sst
Quantity array index for sea surface temperature.
double mixing_lon1
Upper longitude of mixing grid [deg].
int atm_nc_level
zlib compression level of netCDF atmospheric data files (0=off).
char clim_hno3_filename[LEN]
Filename of HNO3 climatology.
int met_cms_heur
cmultiscale coarsening heuristics (0=default, 1=mean diff, 2=median diff, 3=max diff).
double wet_depo_ic_ret_ratio
Coefficients for wet deposition in cloud: retention ratio.
int qnt_sh
Quantity array index for specific humidity.
int qnt_ess
Quantity array index for eastward turbulent surface stress.
double wet_depo_ic_b
Coefficient B for wet deposition in cloud (exponential form).
double wet_depo_bc_b
Coefficient B for wet deposition below cloud (exponential form).
int met_dy
Stride for latitudes.
int qnt_Cx
Quantity array index for trace species x volume mixing ratio (chemistry code).
double turb_dz_strat
Vertical turbulent diffusion coefficient (stratosphere) [m^2/s].
double bound_zetas
Boundary conditions surface layer zeta [K].
int dd_subdomains_zonal
Domain decomposition zonal subdomain number.
int qnt_idx
Quantity array index for air parcel IDs.
double met_tropo_theta
Dynamical tropopause potential temperature threshold [K].
int qnt_rwc
Quantity array index for cloud rain water content.
double t_start
Start time of simulation [s].
char qnt_longname[NQ][LEN]
Quantity long names.
double met_p[EP]
Target pressure levels [hPa].
int nq
Number of quantities.
double tdec_trop
Life time of particles in the troposphere [s].
double sample_dx
Horizontal radius for sample output [km].
int vtk_stride
Particle index stride for VTK data.
char stat_basename[LEN]
Basename of station data file.
double turb_dz_pbl
Vertical turbulent diffusion coefficient (PBL) [m^2/s].
double grid_lat1
Upper latitude of gridded data [deg].
int dd_subdomains_meridional
Domain decomposition meridional subdomain number.
int qnt_zt
Quantity array index for tropopause geopotential height.
int met_type
Type of meteo data files (0=netCDF, 1=binary, 2=pck, 3=ZFP, 4=ZSTD, 5=cms, 6=grib,...
int qnt_cc
Quantity array index for cloud cover.
int qnt_plcl
Quantity array index for pressure at lifted condensation level (LCL).
double grid_dt_out
Time step for gridded data output [s].
int qnt_tdew
Quantity array index for dew point temperature.
Domain decomposition data structure.
size_t halo_bnd_count[4]
Hyperslab of boundary halos count.
int halo_offset_end
Hyperslab of boundary halos count.
int neighbours[DD_NNMAX]
Rank of neighbouring nodes.
double subdomain_lon_min
Rectangular grid limit of subdomain.
size_t halo_bnd_start[4]
Hyperslab of boundary halos start.
double subdomain_lat_max
Rectangular grid limit of subdomain.
int init
Shows if domain decomposition was initialized.
double subdomain_lon_max
Rectangular grid limit of subdomain.
int halo_offset_start
Hyperslab of boundary halos count.
size_t subdomain_count[4]
Hyperslab start and count for subdomain.
size_t subdomain_start[4]
Hyperslab start and count for subdomain.
double subdomain_lat_min
Rectangular grid limit of subdomain.
float zt[EX][EY]
Tropopause geopotential height [km].
float sst[EX][EY]
Sea surface temperature [K].
float rwc[EX][EY][EP]
Cloud rain water content [kg/kg].
float o3c[EX][EY]
Total column ozone [DU].
float zeta_dotl[EX][EY][EP]
Vertical velocity on model levels [K/s].
float h2o[EX][EY][EP]
Water vapor volume mixing ratio [1].
float cape[EX][EY]
Convective available potential energy [J/kg].
float w[EX][EY][EP]
Vertical velocity [hPa/s].
float pct[EX][EY]
Cloud top pressure [hPa].
double hybrid[EP]
Model hybrid levels.
int nx
Number of longitudes.
int ny
Number of latitudes.
float shf[EX][EY]
Surface sensible heat flux [W/m^2].
float ps[EX][EY]
Surface pressure [hPa].
float lwc[EX][EY][EP]
Cloud liquid water content [kg/kg].
float us[EX][EY]
Surface zonal wind [m/s].
float wl[EX][EY][EP]
Vertical velocity on model levels [hPa/s].
float vl[EX][EY][EP]
Meridional wind on model levels [m/s].
float zs[EX][EY]
Surface geopotential height [km].
float o3[EX][EY][EP]
Ozone volume mixing ratio [1].
float cc[EX][EY][EP]
Cloud cover [1].
int np
Number of pressure levels.
float t[EX][EY][EP]
Temperature [K].
float ts[EX][EY]
Surface temperature [K].
float u[EX][EY][EP]
Zonal wind [m/s].
float ess[EX][EY]
Eastward turbulent surface stress [N/m^2].
float ul[EX][EY][EP]
Zonal wind on model levels [m/s].
float pcb[EX][EY]
Cloud bottom pressure [hPa].
float pel[EX][EY]
Pressure at equilibrium level (EL) [hPa].
float cin[EX][EY]
Convective inhibition [J/kg].
float plcl[EX][EY]
Pressure at lifted condensation level (LCL) [hPa].
double lon[EX]
Longitudes [deg].
float pt[EX][EY]
Tropopause pressure [hPa].
float tt[EX][EY]
Tropopause temperature [K].
float pbl[EX][EY]
Boundary layer pressure [hPa].
float vs[EX][EY]
Surface meridional wind [m/s].
float z[EX][EY][EP]
Geopotential height [km].
float v[EX][EY][EP]
Meridional wind [m/s].
int npl
Number of model levels.
float lsm[EX][EY]
Land-sea mask [1].
float iwc[EX][EY][EP]
Cloud ice water content [kg/kg].
float h2ot[EX][EY]
Tropopause water vapor volume mixing ratio [ppv].
float pv[EX][EY][EP]
Potential vorticity [PVU].
double eta[EP]
Model level eta values.
float cl[EX][EY]
Total column cloud water [kg/m^2].
float nss[EX][EY]
Northward turbulent surface stress [N/m^2].
float pl[EX][EY][EP]
Pressure on model levels [hPa].
float plfc[EX][EY]
Pressure at level of free convection (LFC) [hPa].
double hyam[EP]
Model level a coefficients [Pa].
double lat[EY]
Latitudes [deg].
float swc[EX][EY][EP]
Cloud snow water content [kg/kg].
double hybm[EP]
Model level b coefficients.
float zetal[EX][EY][EP]
Zeta on model levels [K].
double p[EP]
Pressure levels [hPa].
double lat
Latitude [deg].
double lon
Longitude [deg].
double q[NQ]
Quantity data (for various, user-defined attributes).