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 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
1031 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
1036 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
1037 for (i = 11; i > 0; i--)
1041 *day = doy - d0l[i] + 1;
1043 for (i = 11; i > 0; i--)
1047 *day = doy - d0[i] + 1;
1058 double data[2 *
EX];
1062 ERRMSG(
"Too many data points!");
1065 gsl_fft_complex_wavetable *wavetable =
1066 gsl_fft_complex_wavetable_alloc((
size_t) n);
1067 gsl_fft_complex_workspace *workspace =
1068 gsl_fft_complex_workspace_alloc((
size_t) n);
1071 for (
int i = 0; i < n; i++) {
1072 data[2 * i] = fcReal[i];
1073 data[2 * i + 1] = fcImag[i];
1077 gsl_fft_complex_forward(data, 1, (
size_t) n, wavetable, workspace);
1080 for (
int i = 0; i < n; i++) {
1081 fcReal[i] = data[2 * i];
1082 fcImag[i] = data[2 * i + 1];
1086 gsl_fft_complex_wavetable_free(wavetable);
1087 gsl_fft_complex_workspace_free(workspace);
1098 const double radius = z +
RE;
1099 const double latrad =
DEG2RAD(lat);
1100 const double lonrad =
DEG2RAD(lon);
1101 const double coslat = cos(latrad);
1103 x[0] = radius * coslat * cos(lonrad);
1104 x[1] = radius * coslat * sin(lonrad);
1105 x[2] = radius * sin(latrad);
1114 const char *metbase,
1115 const double dt_met,
1122 int year, mon, day, hour, min, sec;
1126 t6 = floor(t / dt_met) * dt_met;
1128 t6 = ceil(t / dt_met) * dt_met;
1131 jsec2time(t6, &year, &mon, &day, &hour, &min, &sec, &r);
1136 sprintf(filename,
"%s_YYYY_MM_DD_HH.nc", metbase);
1138 sprintf(filename,
"%s_YYYY_MM_DD_HH.bin", metbase);
1140 sprintf(filename,
"%s_YYYY_MM_DD_HH.pck", metbase);
1142 sprintf(filename,
"%s_YYYY_MM_DD_HH.zfp", metbase);
1144 sprintf(filename,
"%s_YYYY_MM_DD_HH.zstd", metbase);
1146 sprintf(filename,
"%s_YYYY_MM_DD_HH.cms", metbase);
1148 sprintf(filename,
"%s_YYYY_MM_DD_HH.sz3", metbase);
1149 sprintf(repl,
"%d", year);
1151 sprintf(repl,
"%02d", mon);
1153 sprintf(repl,
"%02d", day);
1155 sprintf(repl,
"%02d", hour);
1161 sprintf(filename,
"%s_YYMMDDHH.nc", metbase);
1162 sprintf(repl,
"%d", year);
1164 sprintf(repl,
"%02d", year % 100);
1166 sprintf(repl,
"%02d", mon);
1168 sprintf(repl,
"%02d", day);
1170 sprintf(repl,
"%02d", hour);
1185 for (
int i = 0; i < 3; i++) {
1189 if (!(ch = strstr(orig, search)))
1191 strncpy(buffer, orig, (
size_t) (ch - orig));
1192 buffer[ch - orig] = 0;
1193 sprintf(buffer + (ch - orig),
"%s%s", repl, ch + strlen(search));
1195 strcpy(orig, buffer);
1202 const int met_tropo,
1222#pragma omp parallel for default(shared) private(ci,cw)
1223 for (
int ix = 0; ix < nx; ix++)
1224 for (
int iy = 0; iy < ny; iy++) {
1226 &pt[iy * nx + ix], ci, cw, 1);
1228 &ps[iy * nx + ix], ci, cw, 0);
1230 &zs[iy * nx + ix], ci, cw, 0);
1232 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
1234 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
1236 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
1238 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
1255 *lon2 =
FMOD(lon, 360.);
1256 if (*lon2 < lons[0])
1258 else if (*lon2 > lons[nlon - 1])
1263 if (lats[0] < lats[nlat - 1])
1264 *lat2 =
MIN(
MAX(*lat2, lats[0]), lats[nlat - 1]);
1266 *lat2 =
MIN(
MAX(*lat2, lats[nlat - 1]), lats[0]);
1273 float heights0[
EX][
EY][
EP],
1274 float array0[
EX][
EY][
EP],
1276 float heights1[
EX][
EY][
EP],
1277 float array1[
EX][
EY][
EP],
1279 const double height,
1305 int k_max = ind[0][0];
1306 for (
int i = 0; i < 2; i++)
1307 for (
int j = 0; j < 4; j++) {
1308 if (ci[2] > ind[i][j])
1310 if (k_max < ind[i][j])
1316 cw[0] = (lon2 - met0->
lon[ci[0]]) /
1317 (met0->
lon[ci[0] + 1] - met0->
lon[ci[0]]);
1318 cw[1] = (lat2 - met0->
lat[ci[1]]) /
1319 (met0->
lat[ci[1] + 1] - met0->
lat[ci[1]]);
1322 double height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2]]
1323 - heights0[ci[0]][ci[1]][ci[2]])
1324 + heights0[ci[0]][ci[1]][ci[2]];
1325 double height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2]]
1326 - heights0[ci[0]][ci[1] + 1][ci[2]])
1327 + heights0[ci[0]][ci[1] + 1][ci[2]];
1328 double height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2]]
1329 - heights0[ci[0] + 1][ci[1]][ci[2]])
1330 + heights0[ci[0] + 1][ci[1]][ci[2]];
1331 double height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2]]
1332 - heights0[ci[0] + 1][ci[1] + 1][ci[2]])
1333 + heights0[ci[0] + 1][ci[1] + 1][ci[2]];
1336 double height0 = cw[1] * (height01 - height00) + height00;
1337 double height1 = cw[1] * (height11 - height10) + height10;
1340 double height_bot = cw[0] * (height1 - height0) + height0;
1343 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
1344 - heights0[ci[0]][ci[1]][ci[2] + 1])
1345 + heights0[ci[0]][ci[1]][ci[2] + 1];
1346 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
1347 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
1348 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
1349 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
1350 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
1351 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
1352 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1353 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1354 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1357 height0 = cw[1] * (height01 - height00) + height00;
1358 height1 = cw[1] * (height11 - height10) + height10;
1361 double height_top = cw[0] * (height1 - height0) + height0;
1364 while (((heights0[0][0][0] > heights0[0][0][1]) &&
1365 ((height_bot <= height) || (height_top > height))
1366 && (height_bot >= height) && (ci[2] < k_max))
1368 ((heights0[0][0][0] < heights0[0][0][1]) &&
1369 ((height_bot >= height) || (height_top < height))
1370 && (height_bot <= height) && (ci[2] < k_max))
1374 height_bot = height_top;
1377 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
1378 - heights0[ci[0]][ci[1]][ci[2] + 1])
1379 + heights0[ci[0]][ci[1]][ci[2] + 1];
1380 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
1381 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
1382 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
1383 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
1384 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
1385 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
1386 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1387 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1388 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1391 height0 = cw[1] * (height01 - height00) + height00;
1392 height1 = cw[1] * (height11 - height10) + height10;
1395 height_top = cw[0] * (height1 - height0) + height0;
1399 cw[2] = (height - height_bot)
1400 / (height_top - height_bot);
1404 const double array000 = cw[3] * (array1[ci[0]][ci[1]][ci[2]]
1405 - array0[ci[0]][ci[1]][ci[2]])
1406 + array0[ci[0]][ci[1]][ci[2]];
1407 const double array100 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2]]
1408 - array0[ci[0] + 1][ci[1]][ci[2]])
1409 + array0[ci[0] + 1][ci[1]][ci[2]];
1410 const double array010 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2]]
1411 - array0[ci[0]][ci[1] + 1][ci[2]])
1412 + array0[ci[0]][ci[1] + 1][ci[2]];
1413 const double array110 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2]]
1414 - array0[ci[0] + 1][ci[1] + 1][ci[2]])
1415 + array0[ci[0] + 1][ci[1] + 1][ci[2]];
1416 const double array001 = cw[3] * (array1[ci[0]][ci[1]][ci[2] + 1]
1417 - array0[ci[0]][ci[1]][ci[2] + 1])
1418 + array0[ci[0]][ci[1]][ci[2] + 1];
1419 const double array101 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2] + 1]
1420 - array0[ci[0] + 1][ci[1]][ci[2] + 1])
1421 + array0[ci[0] + 1][ci[1]][ci[2] + 1];
1422 const double array011 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2] + 1]
1423 - array0[ci[0]][ci[1] + 1][ci[2] + 1])
1424 + array0[ci[0]][ci[1] + 1][ci[2] + 1];
1425 const double array111 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1426 - array0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1427 + array0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1429 const double array00 = cw[0] * (array100 - array000) + array000;
1430 const double array10 = cw[0] * (array110 - array010) + array010;
1431 const double array01 = cw[0] * (array101 - array001) + array001;
1432 const double array11 = cw[0] * (array111 - array011) + array011;
1434 const double aux0 = cw[1] * (array10 - array00) + array00;
1435 const double aux1 = cw[1] * (array11 - array01) + array01;
1438 *var = cw[2] * (aux1 - aux0) + aux0;
1468 cw[0] = (met->
p[ci[0] + 1] - p)
1469 / (met->
p[ci[0] + 1] - met->
p[ci[0]]);
1470 cw[1] = (met->
lon[ci[1] + 1] - lon2)
1471 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
1472 cw[2] = (met->
lat[ci[2] + 1] - lat2)
1473 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
1477 const double aux00 =
1478 cw[0] * (array[ci[1]][ci[2]][ci[0]] - array[ci[1]][ci[2]][ci[0] + 1])
1479 + array[ci[1]][ci[2]][ci[0] + 1];
1480 const double aux01 =
1481 cw[0] * (array[ci[1]][ci[2] + 1][ci[0]] -
1482 array[ci[1]][ci[2] + 1][ci[0] + 1])
1483 + array[ci[1]][ci[2] + 1][ci[0] + 1];
1484 const double aux10 =
1485 cw[0] * (array[ci[1] + 1][ci[2]][ci[0]] -
1486 array[ci[1] + 1][ci[2]][ci[0] + 1])
1487 + array[ci[1] + 1][ci[2]][ci[0] + 1];
1488 const double aux11 =
1489 cw[0] * (array[ci[1] + 1][ci[2] + 1][ci[0]] -
1490 array[ci[1] + 1][ci[2] + 1][ci[0] + 1])
1491 + array[ci[1] + 1][ci[2] + 1][ci[0] + 1];
1494 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
1495 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
1496 *var = cw[1] * (aux0 - aux1) + aux1;
1522 if (z >= zs[ix][iy][iz + 1])
1523 aux00 = array[ix][iy][iz + 1];
1524 else if (z <= zs[ix][iy][iz])
1525 aux00 = array[ix][iy][iz];
1527 aux00 =
LIN(zs[ix][iy][iz], array[ix][iy][iz],
1528 zs[ix][iy][iz + 1], array[ix][iy][iz + 1], z);
1532 if (z >= zs[ix][iy + 1][iz + 1])
1533 aux01 = array[ix][iy + 1][iz + 1];
1534 else if (z <= zs[ix][iy + 1][iz])
1535 aux01 = array[ix][iy + 1][iz];
1537 aux01 =
LIN(zs[ix][iy + 1][iz], array[ix][iy + 1][iz],
1538 zs[ix][iy + 1][iz + 1], array[ix][iy + 1][iz + 1], z);
1542 if (z >= zs[ix + 1][iy][iz + 1])
1543 aux10 = array[ix + 1][iy][iz + 1];
1544 else if (z <= zs[ix + 1][iy][iz])
1545 aux10 = array[ix + 1][iy][iz];
1547 aux10 =
LIN(zs[ix + 1][iy][iz], array[ix + 1][iy][iz],
1548 zs[ix + 1][iy][iz + 1], array[ix + 1][iy][iz + 1], z);
1552 if (z >= zs[ix + 1][iy + 1][iz + 1])
1553 aux11 = array[ix + 1][iy + 1][iz + 1];
1554 else if (z <= zs[ix + 1][iy + 1][iz])
1555 aux11 = array[ix + 1][iy + 1][iz];
1557 aux11 =
LIN(zs[ix + 1][iy + 1][iz], array[ix + 1][iy + 1][iz],
1558 zs[ix + 1][iy + 1][iz + 1], array[ix + 1][iy + 1][iz + 1], z);
1561 const double aux0 =
LIN(met->
lat[iy], aux00, met->
lat[iy + 1], aux01, lat2);
1562 const double aux1 =
LIN(met->
lat[iy], aux10, met->
lat[iy + 1], aux11, lat2);
1563 *var =
LIN(met->
lon[ix], aux0, met->
lon[ix + 1], aux1, lon2);
1570 float array[
EX][
EY],
1591 cw[1] = (met->
lon[ci[1] + 1] - lon2)
1592 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
1593 cw[2] = (met->
lat[ci[2] + 1] - lat2)
1594 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
1598 const double aux00 = array[ci[1]][ci[2]];
1599 const double aux01 = array[ci[1]][ci[2] + 1];
1600 const double aux10 = array[ci[1] + 1][ci[2]];
1601 const double aux11 = array[ci[1] + 1][ci[2] + 1];
1604 if (isfinite(aux00) && isfinite(aux01)
1605 && isfinite(aux10) && isfinite(aux11)) {
1606 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
1607 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
1608 *var = cw[1] * (aux0 - aux1) + aux1;
1628 float array0[
EX][
EY][
EP],
1630 float array1[
EX][
EY][
EP],
1647 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
1650 *var = wt * (var0 - var1) + var1;
1658 float array0[
EX][
EY][
EP],
1661 float array1[
EX][
EY][
EP],
1675 *var =
LIN(met0->
time, var0, met1->
time, var1, ts);
1682 float array0[
EX][
EY],
1684 float array1[
EX][
EY],
1700 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
1703 if (isfinite(var0) && isfinite(var1))
1704 *var = wt * (var0 - var1) + var1;
1715 float array0[
EX][
EY],
1717 float array1[
EX][
EY],
1718 const double lons[
EX],
1719 const double lats[
EY],
1738 const int ix =
locate_reg(lons, (
int) nlon, lon2);
1739 const int iy =
locate_irr(lats, (
int) nlat, lat2);
1743 for (
int dx = 0; dx < 2; dx++)
1744 for (
int dy = 0; dy < 2; dy++) {
1745 if (isfinite(array0[ix + dx][iy + dy])) {
1746 mean += array0[ix + dx][iy + dy];
1747 *sigma +=
SQR(array0[ix + dx][iy + dy]);
1750 if (isfinite(array1[ix + dx][iy + dy])) {
1751 mean += array1[ix + dx][iy + dy];
1752 *sigma +=
SQR(array1[ix + dx][iy + dy]);
1757 *sigma = sqrt(
MAX(*sigma / n -
SQR(mean / n), 0.0));
1760 if (method == 1 && isfinite(array0[ix][iy])
1761 && isfinite(array0[ix][iy + 1])
1762 && isfinite(array0[ix + 1][iy])
1763 && isfinite(array0[ix + 1][iy + 1])
1764 && isfinite(array1[ix][iy])
1765 && isfinite(array1[ix][iy + 1])
1766 && isfinite(array1[ix + 1][iy])
1767 && isfinite(array1[ix + 1][iy + 1])) {
1769 const double aux00 =
LIN(lons[ix], array0[ix][iy],
1770 lons[ix + 1], array0[ix + 1][iy], lon2);
1771 const double aux01 =
LIN(lons[ix], array0[ix][iy + 1],
1772 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
1773 const double aux0 =
LIN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
1775 const double aux10 =
LIN(lons[ix], array1[ix][iy],
1776 lons[ix + 1], array1[ix + 1][iy], lon2);
1777 const double aux11 =
LIN(lons[ix], array1[ix][iy + 1],
1778 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
1779 const double aux1 =
LIN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
1781 *var =
LIN(time0, aux0, time1, aux1, time);
1786 const double aux00 =
NN(lons[ix], array0[ix][iy],
1787 lons[ix + 1], array0[ix + 1][iy], lon2);
1788 const double aux01 =
NN(lons[ix], array0[ix][iy + 1],
1789 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
1790 const double aux0 =
NN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
1792 const double aux10 =
NN(lons[ix], array1[ix][iy],
1793 lons[ix + 1], array1[ix + 1][iy], lon2);
1794 const double aux11 =
NN(lons[ix], array1[ix][iy + 1],
1795 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
1796 const double aux1 =
NN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
1798 *var =
NN(time0, aux0, time1, aux1, time);
1823 const time_t jsec0 = (time_t) jsec + timegm(&t0);
1824 t1 = gmtime(&jsec0);
1826 *year = t1->tm_year + 1900;
1827 *mon = t1->tm_mon + 1;
1829 *hour = t1->tm_hour;
1832 *remain = jsec - floor(jsec);
1838 const double kz[
EP],
1839 const double kw[
EP],
1848 const double z =
Z(p);
1853 else if (z > kz[nk - 1])
1857 return LIN(kz[idx], kw[idx], kz[idx + 1], kw[idx + 1], z);
1874 const double a =
RA *
SQR(t), r =
SH(h2o) / (1. -
SH(h2o));
1888 const double press[138] = {
1889 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
1890 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
1891 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
1892 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
1893 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
1894 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
1895 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
1896 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
1897 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
1898 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
1899 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
1900 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
1901 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
1902 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
1903 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
1904 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
1905 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
1906 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
1907 1010.8487, 1013.2500, 1044.45
1910 for (
int ip = 0; ip < ctl->
met_np; ip++)
1917 const double press[92] = {
1918 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
1919 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
1920 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
1921 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
1922 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
1924 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
1925 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
1926 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
1927 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
1928 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
1929 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
1930 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
1931 1007.4431, 1010.8487, 1013.2500, 1044.45
1934 for (
int ip = 0; ip < ctl->
met_np; ip++)
1941 const double press[60] = {
1942 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
1943 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
1944 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
1945 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
1946 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
1947 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
1948 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
1949 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1044.45
1952 for (
int ip = 0; ip < ctl->
met_np; ip++)
1959 const double press[147] = {
1960 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
1961 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
1962 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
1963 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
1964 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
1965 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
1966 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
1967 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
1968 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
1969 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
1970 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
1971 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
1972 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
1973 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
1974 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
1975 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
1976 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
1977 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
1978 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73, 1028.85,
1980 1035.09, 1038.21, 1041.33, 1044.45
1983 for (
int ip = 0; ip < ctl->
met_np; ip++)
1990 const double press[101] = {
1991 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
1992 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
1993 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
1994 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
1995 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
1997 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
1998 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
1999 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
2000 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
2001 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
2002 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
2003 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
2004 1007.4431, 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73,
2006 1035.09, 1038.21, 1041.33, 1044.45
2009 for (
int ip = 0; ip < ctl->
met_np; ip++)
2016 const double press[62] = {
2017 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
2018 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
2019 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
2020 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
2021 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
2022 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
2023 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
2024 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1034.86, 1039.65,
2028 for (
int ip = 0; ip < ctl->
met_np; ip++)
2035 const double press[137] = {
2036 0.01, 0.02, 0.031, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861,
2037 0.2499, 0.3299, 0.4288, 0.5496, 0.6952, 0.869, 1.0742,
2038 1.3143, 1.5928, 1.9134, 2.2797, 2.6954, 3.1642, 3.6898,
2039 4.2759, 4.9262, 5.6441, 6.4334, 7.2974, 8.2397, 9.2634,
2040 10.372, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945, 18.9752,
2041 20.761, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2042 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.199, 54.5299,
2043 57.9834, 61.5607, 65.2695, 69.1187, 73.1187, 77.281, 81.6182,
2044 86.145, 90.8774, 95.828, 101.005, 106.415, 112.068, 117.971,
2045 124.134, 130.564, 137.27, 144.262, 151.549, 159.14, 167.045,
2046 175.273, 183.834, 192.739, 201.997, 211.619, 221.615, 231.995,
2047 242.772, 253.955, 265.556, 277.585, 290.055, 302.976, 316.361,
2048 330.22, 344.566, 359.411, 374.767, 390.645, 407.058, 424.019,
2049 441.539, 459.632, 478.31, 497.584, 517.42, 537.72, 558.343,
2050 579.193, 600.167, 621.162, 642.076, 662.808, 683.262, 703.347,
2051 722.979, 742.086, 760.6, 778.466, 795.64, 812.085, 827.776,
2052 842.696, 856.838, 870.2, 882.791, 894.622, 905.712, 916.081,
2053 925.757, 934.767, 943.14, 950.908, 958.104, 965.299, 972.495,
2054 979.69, 986.886, 994.081, 1001.28, 1008.47, 1015.67, 1022.86,
2055 1030.06, 1037.25, 1044.45
2058 for (
int ip = 0; ip < ctl->
met_np; ip++)
2065 const double press[59] = {
2066 0.1, 0.2, 0.3843, 0.6365, 0.9564, 1.3448, 1.8058, 2.3478,
2067 2.985, 3.7397, 4.6462, 5.7565, 7.1322, 8.8366, 10.9483,
2068 13.5647, 16.8064, 20.8227, 25.7989, 31.9642, 39.6029, 49.0671,
2069 60.1802, 73.0663, 87.7274, 104.229, 122.614, 142.902, 165.089,
2070 189.147, 215.025, 242.652, 272.059, 303.217, 336.044, 370.407,
2071 406.133, 443.009, 480.791, 519.209, 557.973, 596.777, 635.306,
2072 673.24, 710.263, 746.063, 780.346, 812.83, 843.263, 871.42,
2073 897.112, 920.189, 940.551, 958.148, 975.744, 993.341, 1010.94,
2077 for (
int ip = 0; ip < ctl->
met_np; ip++)
2081 ERRMSG(
"Use 0 for l137, 1 for l91, 2 for l60 or values between 3 and 7.");
2085 ERRMSG(
"Recompile with larger EP to use this pressure level definition.");
2098 int i = (ihi + ilo) >> 1;
2100 if (xx[i] < xx[i + 1])
2101 while (ihi > ilo + 1) {
2102 i = (ihi + ilo) >> 1;
2108 while (ihi > ilo + 1) {
2109 i = (ihi + ilo) >> 1;
2129 int i = (ihi + ilo) >> 1;
2131 if (x >= xx[ig] && x < xx[ig + 1])
2134 if (xx[i] < xx[i + 1])
2135 while (ihi > ilo + 1) {
2136 i = (ihi + ilo) >> 1;
2142 while (ihi > ilo + 1) {
2143 i = (ihi + ilo) >> 1;
2161 const int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
2175 float profiles[
EX][
EY][
EP],
2177 const int lon_ap_ind,
2178 const int lat_ap_ind,
2179 const double height_ap,
2185 np, height_ap, ind[0]);
2187 np, height_ap, ind[1]);
2189 np, height_ap, ind[2]);
2208 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2212 double dts, u[4], um = 0, v[4], vm = 0, w[4], wm = 0,
2216 for (
int i = 0; i < ctl->
advect; i++) {
2221 x[0] = atm->
lon[ip];
2222 x[1] = atm->
lat[ip];
2225 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
2226 x[0] = atm->
lon[ip] +
DX2DEG(dts * u[i - 1] / 1000., atm->
lat[ip]);
2227 x[1] = atm->
lat[ip] +
DY2DEG(dts * v[i - 1] / 1000.);
2228 x[2] = atm->
p[ip] + dts * w[i - 1];
2230 const double tm = atm->
time[ip] + dts;
2235 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2237 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2239 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
2245 met1, met1->
pl, met1->
ul,
2246 tm, x[2], x[0], x[1], &u[i]);
2248 met1, met1->
pl, met1->
vl,
2249 tm, x[2], x[0], x[1], &v[i]);
2251 met1, met1->
pl, met1->
wl,
2252 tm, x[2], x[0], x[1], &w[i]);
2258 k = (i == 0 ? 0.0 : 1.0);
2259 else if (ctl->
advect == 4)
2260 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2267 atm->
time[ip] += cache->
dt[ip];
2268 atm->
lon[ip] +=
DX2DEG(cache->
dt[ip] * um / 1000.,
2269 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
2270 atm->
lat[ip] +=
DY2DEG(cache->
dt[ip] * vm / 1000.);
2271 atm->
p[ip] += cache->
dt[ip] * wm;
2279 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2285 atm->
lon[ip], atm->
lat[ip],
2289 double dts, u[4], um = 0, v[4], vm = 0, zeta_dot[4],
2290 zeta_dotm = 0, x[3] = { 0, 0, 0 };
2293 for (
int i = 0; i < ctl->
advect; i++) {
2298 x[0] = atm->
lon[ip];
2299 x[1] = atm->
lat[ip];
2302 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
2303 x[0] = atm->
lon[ip] +
DX2DEG(dts * u[i - 1] / 1000., atm->
lat[ip]);
2304 x[1] = atm->
lat[ip] +
DY2DEG(dts * v[i - 1] / 1000.);
2305 x[2] = atm->
q[ctl->
qnt_zeta][ip] + dts * zeta_dot[i - 1];
2307 const double tm = atm->
time[ip] + dts;
2311 met1->
ul, tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2313 met1->
vl, tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2316 x[1], &zeta_dot[i], ci, cw, 0);
2321 k = (i == 0 ? 0.0 : 1.0);
2322 else if (ctl->
advect == 4)
2323 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2326 zeta_dotm += k * zeta_dot[i];
2330 atm->
time[ip] += cache->
dt[ip];
2331 atm->
lon[ip] +=
DX2DEG(cache->
dt[ip] * um / 1000.,
2332 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
2333 atm->
lat[ip] +=
DY2DEG(cache->
dt[ip] * vm / 1000.);
2334 atm->
q[ctl->
qnt_zeta][ip] += cache->
dt[ip] * zeta_dotm;
2340 atm->
lat[ip], &atm->
p[ip], ci, cw, 1);
2359 SELECT_TIMER(
"MODULE_ADVECT_INIT",
"PHYSICS", NVTX_GPU);
2368 atm->
lon[ip], atm->
lat[ip], &atm->
p[ip], ci, cw, 1);
2383 SELECT_TIMER(
"MODULE_BOUND_COND",
"PHYSICS", NVTX_GPU);
2393 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2429 if (atm->
p[ip] < pbl)
2481 ERRMSG(
"Molar mass is not defined!");
2487 const int ensemble_mode = (ctl->
nens > 0);
2488 const int np = atm->
np;
2492 const int ngrid = nx * ny * nz;
2493 const int nens = ensemble_mode ? ctl->
nens : 1;
2495 double *restrict
const z = (
double *) malloc((
size_t) nz *
sizeof(double));
2496 double *restrict
const press =
2497 (
double *) malloc((
size_t) nz *
sizeof(double));
2498 double *restrict
const mass =
2499 (
double *) calloc((
size_t) ngrid * (size_t) nens,
sizeof(
double));
2500 double *restrict
const area =
2501 (
double *) malloc((
size_t) ny *
sizeof(double));
2502 double *restrict
const lon =
2503 (
double *) malloc((
size_t) nx *
sizeof(double));
2504 double *restrict
const lat =
2505 (
double *) malloc((
size_t) ny *
sizeof(double));
2507 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
2508 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
2509 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
2518#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])
2519#pragma acc data present(ctl,met0,met1,atm,ixs,iys,izs,z,press,mass,area,lon,lat)
2520#pragma acc parallel loop independent gang vector
2522#pragma omp parallel for default(shared)
2524 for (
int iz = 0; iz < nz; iz++) {
2526 press[iz] =
P(z[iz]);
2530 const double t0 = tt - 0.5 * ctl->
dt_mod;
2531 const double t1 = tt + 0.5 * ctl->
dt_mod;
2535#pragma acc parallel loop independent gang vector
2537#pragma omp parallel for default(shared)
2539 for (
int ip = 0; ip < np; ip++) {
2543 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
2544 || ixs[ip] < 0 || ixs[ip] >= nx
2545 || iys[ip] < 0 || iys[ip] >= ny || izs[ip] < 0 || izs[ip] >= nz)
2551#pragma acc parallel loop independent gang vector
2553#pragma omp parallel for default(shared)
2555 for (
int ix = 0; ix < nx; ix++)
2559#pragma acc parallel loop independent gang vector
2561#pragma omp parallel for default(shared)
2563 for (
int iy = 0; iy < ny; iy++) {
2565 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
2570#pragma acc parallel loop independent gang vector
2572 for (
int ip = 0; ip < np; ip++) {
2574 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
2575 if (ensemble_mode) {
2576 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
2577 mass_idx += ens * ngrid;
2580#pragma acc atomic update
2582 mass[mass_idx] += atm->
q[ctl->
qnt_m][ip];
2588#pragma acc parallel loop independent gang vector
2590#pragma omp parallel for default(shared)
2592 for (
int ip = 0; ip < np; ip++)
2600 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
2603 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
2604 if (ensemble_mode) {
2605 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
2606 mass_idx += ens * ngrid;
2610 const double m = mass[mass_idx];
2612 / (
RHO(press[izs[ip]], temp) * area[iys[ip]] * dz * 1e9);
2617#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
2645 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2662 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
2664 atm->
lat[ip], atm->
p[ip]));
2666 atm->
lat[ip], atm->
p[ip]));
2668 atm->
lat[ip], atm->
p[ip]));
2682 SELECT_TIMER(
"MODULE_CONVECTION",
"PHYSICS", NVTX_GPU);
2688 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2696 double pbot = ps, ptop = ps;
2713 double cape, cin, pel;
2719 if (isfinite(cape) && cape >= ctl->
conv_cape
2721 ptop = GSL_MIN(ptop, pel);
2725 if (ptop != pbot && atm->
p[ip] >= ptop) {
2730 pbot, atm->
lon[ip], atm->
lat[ip], &tbot, ci, cw, 1);
2732 atm->
lon[ip], atm->
lat[ip], &ttop, ci, cw, 1);
2733 const double rhobot = pbot / tbot;
2734 const double rhotop = ptop / ttop;
2737 const double rho = rhobot + (rhotop - rhobot) * cache->
rs[ip];
2740 atm->
p[ip] =
LIN(rhobot, pbot, rhotop, ptop, rho);
2758 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
2761 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,clim,atm)") {
2770 const double aux = exp(-cache->
dt[ip] / tdec);
2771 if (ctl->
qnt_m >= 0) {
2774 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
2775 atm->
q[ctl->
qnt_m][ip] *= aux;
2800 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2808 float umean = 0, usig = 0, vmean = 0, vsig = 0, wmean = 0, wsig = 0;
2809 for (
int i = 0; i < 2; i++)
2810 for (
int j = 0; j < 2; j++)
2811 for (
int k = 0; k < 2; k++) {
2812 umean += met0->
u[ix + i][iy + j][iz + k];
2813 usig +=
SQR(met0->
u[ix + i][iy + j][iz + k]);
2814 vmean += met0->
v[ix + i][iy + j][iz + k];
2815 vsig +=
SQR(met0->
v[ix + i][iy + j][iz + k]);
2816 wmean += met0->
w[ix + i][iy + j][iz + k];
2817 wsig +=
SQR(met0->
w[ix + i][iy + j][iz + k]);
2819 umean += met1->
u[ix + i][iy + j][iz + k];
2820 usig +=
SQR(met1->
u[ix + i][iy + j][iz + k]);
2821 vmean += met1->
v[ix + i][iy + j][iz + k];
2822 vsig +=
SQR(met1->
v[ix + i][iy + j][iz + k]);
2823 wmean += met1->
w[ix + i][iy + j][iz + k];
2824 wsig +=
SQR(met1->
w[ix + i][iy + j][iz + k]);
2826 usig = usig / 16.f -
SQR(umean / 16.f);
2827 usig = (usig > 0 ? sqrtf(usig) : 0);
2828 vsig = vsig / 16.f -
SQR(vmean / 16.f);
2829 vsig = (vsig > 0 ? sqrtf(vsig) : 0);
2830 wsig = wsig / 16.f -
SQR(wmean / 16.f);
2831 wsig = (wsig > 0 ? sqrtf(wsig) : 0);
2834 const double r = 1 - 2 * fabs(cache->
dt[ip]) / ctl->
dt_met;
2835 const double r2 = sqrt(1 - r * r);
2839 cache->
uvwp[ip][0] =
2840 (float) (r * cache->
uvwp[ip][0] +
2845 cache->
uvwp[ip][1] =
2846 (float) (r * cache->
uvwp[ip][1] +
2853 cache->
uvwp[ip][2] =
2854 (float) (r * cache->
uvwp[ip][2] +
2856 atm->
p[ip] += cache->
uvwp[ip][2] * cache->
dt[ip];
2877 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2879 double dsigw_dz = 0.0, sig_u = 0.25, sig_w = 0.1,
2880 tau_u = 300., tau_w = 100.;
2889 if (atm->
p[ip] >= pbl) {
2892 const double p =
MIN(atm->
p[ip], ps);
2893 const double zs =
Z(ps);
2894 const double z = 1e3 * (
Z(p) - zs);
2895 const double zi = 1e3 * (
Z(pbl) - zs);
2896 const double zratio = z / zi;
2899 double ess, nss, h2o, t;
2904 const double rho =
RHO(p,
TVIRT(t, h2o));
2905 const double tau = sqrt(
SQR(ess) +
SQR(nss));
2906 const double ustar = sqrt(tau / rho);
2916 sig_u = 1e-2 + 2.0 * ustar * (1.0 - zratio);
2917 sig_w = 1e-2 + 1.3 * ustar * (1.0 - zratio);
2920 dsigw_dz = -1.3 * ustar / zi;
2923 tau_u = 0.07 * zi / sig_u * sqrt(zratio);
2924 tau_w = 0.1 * zi / sig_w * pow(zratio, 0.8);
2931 const double wstar =
2932 pow(
G0 /
THETAVIRT(p, t, h2o) * shf / (rho *
CPD) * zi, 1. / 3.);
2936 + sqrt(0.4 *
SQR(wstar) + (5.0 - 4.0 * zratio) *
SQR(ustar));
2937 sig_w = 1e-2 + sqrt(1.2 *
SQR(wstar) * (1.0 - 0.9 * zratio)
2938 * pow(zratio, 2.0 / 3.0)
2939 + (1.8 - 1.4 * zratio) *
SQR(ustar));
2942 dsigw_dz = 0.5 / sig_w / zi * (-1.4 *
SQR(ustar) +
SQR(wstar)
2944 pow(
MAX(zratio, 1e-3), -1.0 / 3.0)
2945 - 1.8 * pow(zratio, 2.0 / 3.0)));
2948 const double C0 = 3.0;
2950 (1.5 - 1.2 * pow(zratio, 1.0 / 3.0)) *
SQR(wstar) * wstar / zi
2951 +
SQR(ustar) * ustar * (1.0 - 0.8 * zratio) / (
KARMAN * z);
2952 tau_u = 2 *
SQR(sig_u) / (C0 * eps);
2953 tau_w = 2 *
SQR(sig_w) / (C0 * eps);
2958 sig_u =
MAX(sig_u, 0.25);
2959 sig_w =
MAX(sig_w, 0.1);
2960 tau_u =
MAX(tau_u, 300.);
2961 tau_w =
MAX(tau_w, 100.);
2964 const double ru = exp(-fabs(cache->
dt[ip]) / tau_u);
2965 const double ru2 = sqrt(1.0 -
SQR(ru));
2967 = (float) (cache->
uvwp[ip][0] * ru + ru2 * cache->
rs[3 * ip]);
2969 = (float) (cache->
uvwp[ip][1] * ru + ru2 * cache->
rs[3 * ip + 1]);
2971 const double rw = exp(-fabs(cache->
dt[ip]) / tau_w);
2972 const double rw2 = sqrt(1.0 -
SQR(rw));
2974 = (float) (cache->
uvwp[ip][2] * rw + rw2 * cache->
rs[3 * ip + 2]
2975 + sig_w * dsigw_dz * cache->
dt[ip]);
2982 DZ2DP(cache->
uvwp[ip][2] * cache->
dt[ip] / 1000., atm->
p[ip]);
3004 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3013 const double wpbl =
pbl_weight(ctl, atm, ip, pbl, ps);
3014 const double wtrop =
tropo_weight(clim, atm, ip) * (1.0 - wpbl);
3015 const double wstrat = 1.0 - wpbl - wtrop;
3025 const double sigma = sqrt(2.0 * dx * fabs(cache->
dt[ip])) / 1000.;
3027 atm->
lat[ip] +=
DY2DEG(cache->
rs[3 * ip + 1] * sigma);
3032 const double sigma = sqrt(2.0 * dz * fabs(cache->
dt[ip])) / 1000.;
3033 atm->
p[ip] +=
DZ2DP(cache->
rs[3 * ip + 2] * sigma, atm->
p[ip]);
3052 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3055 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3067 const double dz = 1000. * (
Z(ps - ctl->
dry_depo_dp) -
Z(ps));
3087 const double aux = exp(-cache->
dt[ip] * v_dep / dz);
3088 if (ctl->
qnt_m >= 0) {
3091 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
3092 atm->
q[ctl->
qnt_m][ip] *= aux;
3116 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3119 const double a = 3.12541941e-06;
3120 const double b = -5.72532259e-01;
3121 const double low = pow(1. / a, 1. / b);
3124 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3131 if (!(lwc > 0 || rwc > 0))
3142 const double k = 9.1e7 * exp(-29700. /
RI * (1. / t - 1. / 298.15));
3145 const double H_SO2 =
3146 1.3e-2 * exp(2900. * (1. / t - 1. / 298.15)) *
RI * t;
3147 const double K_1S = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
3150 const double H_h2o2 =
3151 8.3e2 * exp(7600. * (1. / t - 1. / 298.15)) *
RI * t;
3157 cor = atm->
q[ctl->
qnt_Cx][ip] >
3158 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
3160 const double h2o2 = H_h2o2
3162 * M * cor * 1000. /
AVO;
3165 const double rho_air = atm->
p[ip] / (
RI * t) *
MA / 10.;
3166 const double CWC = (lwc + rwc) * rho_air / 1e3;
3169 const double rate_coef = k * K_1S * h2o2 * H_SO2 * CWC;
3170 const double aux = exp(-cache->
dt[ip] * rate_coef);
3171 if (ctl->
qnt_m >= 0) {
3174 atm->
q[ctl->
qnt_m][ip] *= aux;
3195 SELECT_TIMER(
"MODULE_ISOSURF_INIT",
"PHYSICS", NVTX_GPU);
3206 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
3209 cache->
iso_var[ip] = atm->
p[ip] / t;
3215 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
3226 LOG(1,
"Read balloon pressure data: %s", ctl->
balloon);
3230 if (!(in = fopen(ctl->
balloon,
"r")))
3231 ERRMSG(
"Cannot open file!");
3235 while (fgets(line,
LEN, in))
3236 if (sscanf(line,
"%lg %lg", &(cache->
iso_ts[cache->
iso_n]),
3239 ERRMSG(
"Too many data points!");
3242 if (cache->
iso_n < 1)
3243 ERRMSG(
"Could not read any data!");
3266 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,met1,atm)") {
3279 atm->
p[ip] = cache->
iso_var[ip] * t;
3285 atm->
p[ip] = 1000. * pow(cache->
iso_var[ip] / t, -1. / 0.286);
3291 atm->
p[ip] = cache->
iso_ps[0];
3319 const int nvar = NVAR, nfix = NFIX, nreact = NREACT;
3320 double rtol[1] = { 1.0e-3 };
3321 double atol[1] = { 1.0 };
3325#pragma acc data copy(rtol,atol,nvar,nfix,nreact)
3328 "acc data present(ctl,cache,clim,met0,met1,atm) ") {
3331 double var[nvar], fix[nfix], rconst[nreact];
3332 for (
int i = 0; i < nvar; i++)
3334 for (
int i = 0; i < nfix; i++)
3336 for (
int i = 0; i < nreact; i++)
3338 kpp_chem_initialize(ctl, clim, met0, met1, atm, var, fix, rconst, ip);
3343 for (
int i = 0; i < 20; i++) {
3350 Rosenbrock(var, fix, rconst, 0, ctl->
dt_kpp,
3351 atol, rtol, &FunTemplate, &JacTemplate, rpar, ipar);
3354 kpp_chem_output2atm(atm, ctl, met0, met1, var, ip);
3375 ERRMSG(
"Need T_ice and T_NAT to calculate T_STS!");
3379 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3381 double ps, ts, zs, us, vs, ess, nss, shf, lsm, sst, pbl, pt, pct, pcb,
3382 cl, plcl, plfc, pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot,
3383 o3, lwc, rwc, iwc, swc, cc, z, zt;
3431 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
3433 atm->
lat[ip], atm->
p[ip]));
3435 atm->
lat[ip], atm->
p[ip]));
3437 atm->
lat[ip], atm->
p[ip]));
3438 SET_ATM(qnt_vh, sqrt(u * u + v * v));
3458 atm->
lat[ip], atm->
p[ip])));
3476 const int np = atm->
np;
3477 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
3478 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
3479 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
3487 const double t0 = t - 0.5 * ctl->
dt_mod;
3488 const double t1 = t + 0.5 * ctl->
dt_mod;
3492#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
3493#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
3494#pragma acc parallel loop independent gang vector
3496#pragma omp parallel for default(shared)
3498 for (
int ip = 0; ip < np; ip++) {
3501 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
mixing_z0) / dz);
3502 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
3503 || ixs[ip] < 0 || ixs[ip] >= ctl->
mixing_nx
3504 || iys[ip] < 0 || iys[ip] >= ctl->
mixing_ny
3505 || izs[ip] < 0 || izs[ip] >= ctl->
mixing_nz)
3510 const int use_ensemble = (ctl->
nens > 0);
3512 const int quantities[] = {
3519 const int n_qnt =
sizeof(quantities) /
sizeof(quantities[0]);
3521 for (
int i = 0; i < n_qnt; i++)
3522 if (quantities[i] >= 0)
3528#pragma acc exit data delete(ixs,iys,izs)
3545 const int use_ensemble) {
3547 const int np = atm->
np;
3549 const int nens = use_ensemble ? ctl->
nens : 1;
3550 const int total_grid = ngrid * nens;
3552 double *restrict
const cmean =
3553 (
double *) malloc((
size_t) total_grid *
sizeof(double));
3554 int *restrict
const count =
3555 (
int *) malloc((
size_t) total_grid *
sizeof(int));
3559#pragma acc enter data create(cmean[0:total_grid],count[0:total_grid])
3560#pragma acc data present(ctl,clim,atm,ixs,iys,izs,cmean,count)
3561#pragma acc parallel loop independent gang vector
3566#pragma omp parallel for
3568 for (
int i = 0; i < total_grid; i++) {
3575#pragma acc parallel loop independent gang vector
3577 for (
int ip = 0; ip < np; ip++)
3579 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
3584#pragma acc atomic update
3586 cmean[idx] += atm->
q[qnt_idx][ip];
3588#pragma acc atomic update
3595#pragma acc parallel loop independent gang vector
3600#pragma omp parallel for
3602 for (
int i = 0; i < total_grid; i++)
3604 cmean[i] /= count[i];
3608#pragma acc parallel loop independent gang vector
3610#pragma omp parallel for
3612 for (
int ip = 0; ip < np; ip++) {
3614 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
3616 double mixparam = 1.0;
3625 atm->
q[qnt_idx][ip] += (cmean[idx] - atm->
q[qnt_idx][ip]) * mixparam;
3631#pragma acc exit data delete(cmean,count)
3652 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3655 const double a = 4.71572206e-08;
3656 const double b = -8.28782867e-01;
3657 const double low = pow(1. / a, 1. / b);
3661 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3687 0 ? pow(298. / t, ctl->
oh_chem[1]) : 1.);
3690 0 ? pow(298. / t, ctl->
oh_chem[3]) : 1.);
3691 const double c = log10(k0 * M / ki);
3692 k = k0 * M / (1. + k0 * M / ki) * pow(0.6, 1. / (1. + c * c));
3701 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
3704 const double rate_coef =
3706 atm->
lat[ip], atm->
p[ip]) * M * cor;
3707 const double aux = exp(-cache->
dt[ip] * rate_coef);
3708 if (ctl->
qnt_m >= 0) {
3711 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
3712 atm->
q[ctl->
qnt_m][ip] *= aux;
3733 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(cache,met0,met1,atm)") {
3744 while (atm->
lat[ip] < -90 || atm->
lat[ip] > 90) {
3745 if (atm->
lat[ip] > 90) {
3746 atm->
lat[ip] = 180 - atm->
lat[ip];
3747 atm->
lon[ip] += 180;
3749 if (atm->
lat[ip] < -90) {
3750 atm->
lat[ip] = -180 - atm->
lat[ip];
3751 atm->
lon[ip] += 180;
3756 while (atm->
lon[ip] < -180)
3757 atm->
lon[ip] += 360;
3758 while (atm->
lon[ip] >= 180)
3759 atm->
lon[ip] -= 360;
3762 if (atm->
p[ip] < met0->
p[met0->
np - 1]) {
3763 atm->
p[ip] = met0->
p[met0->
np - 1];
3764 }
else if (atm->
p[ip] > 300.) {
3766 if (atm->
p[ip] > ps)
3778 gsl_rng_env_setup();
3779 if (omp_get_max_threads() >
NTHREADS)
3780 ERRMSG(
"Too many threads!");
3781 for (
int i = 0; i <
NTHREADS; i++) {
3782 rng[i] = gsl_rng_alloc(gsl_rng_default);
3783 gsl_rng_set(rng[i], gsl_rng_default_seed
3784 + (
long unsigned) (ntask *
NTHREADS + i));
3789 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
3790 CURAND_STATUS_SUCCESS)
3791 ERRMSG(
"Cannot create random number generator!");
3792 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
3793 CURAND_STATUS_SUCCESS)
3794 ERRMSG(
"Cannot set seed for random number generator!");
3797 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
3798 CURAND_STATUS_SUCCESS)
3799 ERRMSG(
"Cannot set stream for random number generator!");
3816#pragma omp parallel for default(shared)
3817 for (
size_t i = 0; i < n; ++i)
3818 rs[i] = gsl_rng_uniform(rng[omp_get_thread_num()]);
3822 else if (method == 1) {
3823#pragma omp parallel for default(shared)
3824 for (
size_t i = 0; i < n; ++i)
3825 rs[i] = gsl_ran_gaussian_ziggurat(rng[omp_get_thread_num()], 1.0);
3831#pragma acc update device(rs[:n])
3839 const uint64_t key = 0xc8e4fd154ce32f6d;
3843#pragma acc data present(rs)
3844#pragma acc parallel loop independent gang vector
3846#pragma omp parallel for default(shared)
3848 for (
size_t i = 0; i < n + 1; ++i) {
3849 uint64_t r, t, x, y, z;
3850 y = x = (rng_ctr + i) * key;
3853 x = (x >> 32) | (x << 32);
3855 x = (x >> 32) | (x << 32);
3857 x = (x >> 32) | (x << 32);
3859 x = (x >> 32) | (x << 32);
3860 r = t ^ ((x * x + y) >> 32);
3861 rs[i] = (double) r / (
double) UINT64_MAX;
3868#pragma acc parallel loop independent gang vector
3870#pragma omp parallel for default(shared)
3872 for (
size_t i = 0; i < n; i += 2) {
3873 const double r = sqrt(-2.0 * log(rs[i]));
3874 const double phi = 2.0 * M_PI * rs[i + 1];
3875 rs[i] = r * cosf((
float) phi);
3876 rs[i + 1] = r * sinf((
float) phi);
3884#pragma acc host_data use_device(rs)
3889 if (curandGenerateUniformDouble(rng_curand, rs, (n < 4 ? 4 : n)) !=
3890 CURAND_STATUS_SUCCESS)
3891 ERRMSG(
"Cannot create random numbers!");
3895 else if (method == 1) {
3896 if (curandGenerateNormalDouble
3897 (rng_curand, rs, (n < 4 ? 4 : n), 0.0,
3898 1.0) != CURAND_STATUS_SUCCESS)
3899 ERRMSG(
"Cannot create random numbers!");
3903 ERRMSG(
"MPTRAC was compiled without cuRAND!");
3921 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3929 const double v_s =
sedi(atm->
p[ip], t, atm->
q[ctl->
qnt_rp][ip],
3933 atm->
p[ip] +=
DZ2DP(v_s * cache->
dt[ip] / 1000., atm->
p[ip]);
3948 const int np = atm->
np;
3949 double *restrict
const a = (
double *) malloc((
size_t) np *
sizeof(double));
3950 int *restrict
const p = (
int *) malloc((
size_t) np *
sizeof(int));
3951 if (a == NULL || p == NULL)
3952 ERRMSG(
"Out of memory!");
3955#pragma acc enter data create(a[0:np],p[0:np])
3956#pragma acc data present(ctl,met0,atm,a,p)
3961#pragma acc parallel loop independent gang vector
3963#pragma omp parallel for default(shared)
3965 for (
int ip = 0; ip < np; ip++) {
3976#pragma acc host_data use_device(a,p)
3978 thrustSortWrapper(a, np, p);
3981 ERRMSG(
"GSL sort fallback not available on GPU, use THRUST!");
3983 gsl_sort_index((
size_t *) p, a, 1, (
size_t) np);
3991 for (
int iq = 0; iq < ctl->
nq; iq++)
3996#pragma acc exit data delete(a,p)
4010 double *restrict
const help =
4011 (
double *) malloc((
size_t) np *
sizeof(double));
4013 ERRMSG(
"Out of memory!");
4017#pragma acc enter data create(help[0:np])
4018#pragma acc data present(a,p,help)
4019#pragma acc parallel loop independent gang vector
4021#pragma omp parallel for default(shared)
4023 for (
int ip = 0; ip < np; ip++)
4024 help[ip] = a[p[ip]];
4026#pragma acc parallel loop independent gang vector
4028#pragma omp parallel for default(shared)
4030 for (
int ip = 0; ip < np; ip++)
4035#pragma acc exit data delete(help)
4052 const double latmin = gsl_stats_min(met0->
lat, 1, (
size_t) met0->
ny),
4053 latmax = gsl_stats_max(met0->
lat, 1, (
size_t) met0->
ny);
4056 (fabs(met0->
lon[met0->
nx - 1] - met0->
lon[0] - 360.0) >= 0.01);
4059 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,atm)") {
4065 cache->
dt[ip] = t - atm->
time[ip];
4067 cache->
dt[ip] = 0.0;
4076 if (local && (atm->
lon[ip] <= met0->
lon[0]
4077 || atm->
lon[ip] >= met0->
lon[met0->
nx - 1]
4078 || atm->
lat[ip] <= latmin || atm->
lat[ip] >= latmax))
4079 cache->
dt[ip] = 0.0;
4094 SELECT_TIMER(
"MODULE_TIMESTEPS_INIT",
"PHYSICS", NVTX_GPU);
4098 ctl->
t_start = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
4100 ctl->
t_stop = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
4102 ctl->
t_start = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
4104 ctl->
t_stop = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
4109 ERRMSG(
"Nothing to do! Check T_STOP and DIRECTION!");
4129 SELECT_TIMER(
"MODULE_TRACER_CHEM",
"PHYSICS", NVTX_GPU);
4133 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4156 const double K_o1d =
ARRHENIUS(3.30e-10, 0, t) * o1d * M;
4158 atm->
p[ip], sza, o3c);
4159 atm->
q[ctl->
qnt_Cccl4][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4164 const double K_o1d =
ARRHENIUS(2.30e-10, 0, t) * o1d * M;
4166 atm->
p[ip], sza, o3c);
4167 atm->
q[ctl->
qnt_Cccl3f][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4172 const double K_o1d =
ARRHENIUS(1.40e-10, -25, t) * o1d * M;
4174 atm->
p[ip], sza, o3c);
4175 atm->
q[ctl->
qnt_Cccl2f2][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4180 const double K_o1d =
ARRHENIUS(1.19e-10, -20, t) * o1d * M;
4182 atm->
p[ip], sza, o3c);
4183 atm->
q[ctl->
qnt_Cn2o][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4202 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4205 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4211 if (!isfinite(pct) || atm->
p[ip] <= pct)
4227 double lwc, rwc, iwc, swc;
4232 const int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
4246 else if (t <= 238.15)
4266 const double K_1 = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
4267 const double K_2 = 6e-8 * exp(1.12e3 * (1. / t - 1. / 298.15));
4268 h *= (1. + K_1 / H_ion + K_1 * K_2 /
SQR(H_ion));
4272 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
4275 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
4301 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
4304 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
4309 const double aux = exp(-cache->
dt[ip] * lambda);
4310 if (ctl->
qnt_m >= 0) {
4313 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
4314 atm->
q[ctl->
qnt_m][ip] *= aux;
4338 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
4340 if (acc_get_num_devices(acc_device_nvidia) <= 0)
4341 ERRMSG(
"Not running on a GPU device!");
4342 acc_set_device_num(rank % acc_get_num_devices(acc_device_nvidia),
4344 acc_device_t device_type = acc_get_device_type();
4345 acc_init(device_type);
4359 SELECT_TIMER(
"CREATE_DATA_REGION",
"MEMORY", NVTX_GPU);
4360 ctl_t *ctlup = *ctl;
4363 met_t *met0up = *met0;
4364 met_t *met1up = *met1;
4365 atm_t *atmup = *atm;
4366#pragma acc enter data create(ctlup[:1],cacheup[:1],climup[:1],met0up[:1],met1up[:1],atmup[:1])
4393 SELECT_TIMER(
"DELETE_DATA_REGION",
"MEMORY", NVTX_GPU);
4394#pragma acc exit data delete (ctl,cache,clim,met0,met1,atm)
4408 MPI_Type_free(&mpi_info->MPI_Particle);
4425 char cachefile[
LEN], cmd[2 *
LEN], filename[
LEN];
4431 if (t == ctl->
t_start || !init) {
4438 ERRMSG(
"Cannot open file!");
4443 ERRMSG(
"Cannot open file!");
4453 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
4454 LOG(1,
"Caching: %s", cachefile);
4455 if (system(cmd) != 0)
4456 WARN(
"Caching command failed!");
4461 if (t > (*met1)->time) {
4471 ERRMSG(
"Cannot open file!");
4481 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
4482 LOG(1,
"Caching: %s", cachefile);
4483 if (system(cmd) != 0)
4484 WARN(
"Caching command failed!");
4489 if (t < (*met0)->time) {
4499 ERRMSG(
"Cannot open file!");
4509 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
4510 LOG(1,
"Caching: %s", cachefile);
4511 if (system(cmd) != 0)
4512 WARN(
"Caching command failed!");
4517 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
4518 if ((*met0)->nx != (*met1)->nx
4519 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
4520 ERRMSG(
"Meteo grid dimensions do not match!");
4521 for (
int ix = 0; ix < (*met0)->nx; ix++)
4522 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
4523 ERRMSG(
"Meteo grid longitudes do not match!");
4524 for (
int iy = 0; iy < (*met0)->ny; iy++)
4525 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
4526 ERRMSG(
"Meteo grid latitudes do not match!");
4527 for (
int ip = 0; ip < (*met0)->np; ip++)
4528 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
4529 ERRMSG(
"Meteo grid pressure levels do not match!");
4555 const char *filename,
4568 LOG(1,
"Read atmospheric data: %s", filename);
4588 ERRMSG(
"Atmospheric data type not supported!");
4596 ERRMSG(
"Can not read any data!");
4600 LOG(2,
"Number of particles: %d", atm->
np);
4601 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
4602 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
4603 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
4604 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
4605 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
4606 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
4607 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
4608 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
4609 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
4610 for (
int iq = 0; iq < ctl->
nq; iq++) {
4612 sprintf(msg,
"Quantity %s range: %s ... %s %s",
4615 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
4616 LOG(2, msg, mini, maxi);
4686 const char *filename,
4695 LOG(1,
"\nMassive-Parallel Trajectory Calculations (MPTRAC)\n"
4696 "(executable: %s | version: %s | compiled: %s, %s)\n",
4697 argv[0], VERSION, __DATE__, __TIME__);
4799 ctl->
nq = (int)
scan_ctl(filename, argc, argv,
"NQ", -1,
"0", NULL);
4801 ERRMSG(
"Too many quantities!");
4802 for (
int iq = 0; iq < ctl->
nq; iq++) {
4808 scan_ctl(filename, argc, argv,
"QNT_FORMAT", iq,
"%g",
4810 if (strcasecmp(ctl->
qnt_name[iq],
"aoa") == 0)
4814 SET_QNT(qnt_idx,
"idx",
"particle index",
"-")
4815 SET_QNT(qnt_ens,
"ens",
"ensemble index",
"-")
4816 SET_QNT(qnt_stat,
"stat",
"station flag",
"-")
4817 SET_QNT(qnt_m,
"m",
"mass",
"kg")
4818 SET_QNT(qnt_vmr,
"vmr",
"volume mixing ratio",
"ppv")
4819 SET_QNT(qnt_rp,
"rp",
"particle radius",
"microns")
4820 SET_QNT(qnt_rhop,
"rhop",
"particle density",
"kg/m^3")
4821 SET_QNT(qnt_ps,
"ps",
"surface pressure",
"hPa")
4822 SET_QNT(qnt_ts,
"ts",
"surface temperature",
"K")
4823 SET_QNT(qnt_zs,
"zs",
"surface height",
"km")
4824 SET_QNT(qnt_us,
"us",
"surface zonal wind",
"m/s")
4825 SET_QNT(qnt_vs,
"vs",
"surface meridional wind",
"m/s")
4826 SET_QNT(qnt_ess,
"ess",
"eastward turbulent surface stress",
"N/m^2")
4827 SET_QNT(qnt_nss,
"nss",
"northward turbulent surface stress",
"N/m^2")
4828 SET_QNT(qnt_shf,
"shf",
"surface sensible heat flux",
"W/m^2")
4829 SET_QNT(qnt_lsm,
"lsm",
"land-sea mask",
"1")
4830 SET_QNT(qnt_sst,
"sst",
"sea surface temperature",
"K")
4831 SET_QNT(qnt_pbl,
"pbl",
"planetary boundary layer",
"hPa")
4832 SET_QNT(qnt_pt,
"pt",
"tropopause pressure",
"hPa")
4833 SET_QNT(qnt_tt,
"tt",
"tropopause temperature",
"K")
4834 SET_QNT(qnt_zt,
"zt",
"tropopause geopotential height",
"km")
4835 SET_QNT(qnt_h2ot,
"h2ot",
"tropopause water vapor",
"ppv")
4836 SET_QNT(qnt_zg,
"zg",
"geopotential height",
"km")
4837 SET_QNT(qnt_p,
"p",
"pressure",
"hPa")
4838 SET_QNT(qnt_t,
"t",
"temperature",
"K")
4839 SET_QNT(qnt_rho,
"rho",
"air density",
"kg/m^3")
4840 SET_QNT(qnt_u,
"u",
"zonal wind",
"m/s")
4841 SET_QNT(qnt_v,
"v",
"meridional wind",
"m/s")
4842 SET_QNT(qnt_w,
"w",
"vertical velocity",
"hPa/s")
4843 SET_QNT(qnt_h2o,
"h2o",
"water vapor",
"ppv")
4844 SET_QNT(qnt_o3,
"o3",
"ozone",
"ppv")
4845 SET_QNT(qnt_lwc,
"lwc",
"cloud liquid water content",
"kg/kg")
4846 SET_QNT(qnt_rwc,
"rwc",
"cloud rain water content",
"kg/kg")
4847 SET_QNT(qnt_iwc,
"iwc",
"cloud ice water content",
"kg/kg")
4848 SET_QNT(qnt_swc,
"swc",
"cloud snow water content",
"kg/kg")
4849 SET_QNT(qnt_cc,
"cc",
"cloud cover",
"1")
4850 SET_QNT(qnt_pct,
"pct",
"cloud top pressure",
"hPa")
4851 SET_QNT(qnt_pcb,
"pcb",
"cloud bottom pressure",
"hPa")
4852 SET_QNT(qnt_cl,
"cl",
"total column cloud water",
"kg/m^2")
4853 SET_QNT(qnt_plcl,
"plcl",
"lifted condensation level",
"hPa")
4854 SET_QNT(qnt_plfc,
"plfc",
"level of free convection",
"hPa")
4855 SET_QNT(qnt_pel,
"pel",
"equilibrium level",
"hPa")
4856 SET_QNT(qnt_cape,
"cape",
"convective available potential energy",
4858 SET_QNT(qnt_cin,
"cin",
"convective inhibition",
"J/kg")
4859 SET_QNT(qnt_o3c,
"o3c",
"total column ozone",
"DU")
4860 SET_QNT(qnt_hno3,
"hno3",
"nitric acid",
"ppv")
4861 SET_QNT(qnt_oh,
"oh",
"hydroxyl radical",
"ppv")
4862 SET_QNT(qnt_h2o2,
"h2o2",
"hydrogen peroxide",
"ppv")
4863 SET_QNT(qnt_ho2,
"ho2",
"hydroperoxyl radical",
"ppv")
4864 SET_QNT(qnt_o1d,
"o1d",
"atomic oxygen",
"ppv")
4865 SET_QNT(qnt_mloss_oh,
"mloss_oh",
"mass loss due to OH chemistry",
"kg")
4866 SET_QNT(qnt_mloss_h2o2,
"mloss_h2o2",
4867 "mass loss due to H2O2 chemistry",
"kg")
4868 SET_QNT(qnt_mloss_kpp,
"mloss_kpp",
"mass loss due to kpp chemistry",
4870 SET_QNT(qnt_mloss_wet,
"mloss_wet",
"mass loss due to wet deposition",
4872 SET_QNT(qnt_mloss_dry,
"mloss_dry",
"mass loss due to dry deposition",
4874 SET_QNT(qnt_mloss_decay,
"mloss_decay",
4875 "mass loss due to exponential decay",
"kg")
4876 SET_QNT(qnt_loss_rate,
"loss_rate",
"total loss rate",
"s^-1")
4877 SET_QNT(qnt_psat,
"psat",
"saturation pressure over water",
"hPa")
4878 SET_QNT(qnt_psice,
"psice",
"saturation pressure over ice",
"hPa")
4879 SET_QNT(qnt_pw,
"pw",
"partial water vapor pressure",
"hPa")
4880 SET_QNT(qnt_sh,
"sh",
"specific humidity",
"kg/kg")
4881 SET_QNT(qnt_rh,
"rh",
"relative humidity",
"%%")
4882 SET_QNT(qnt_rhice,
"rhice",
"relative humidity over ice",
"%%")
4883 SET_QNT(qnt_theta,
"theta",
"potential temperature",
"K")
4884 SET_QNT(qnt_zeta,
"zeta",
"zeta coordinate",
"K")
4885 SET_QNT(qnt_zeta_d,
"zeta_d",
"diagnosed zeta coordinate",
"K")
4886 SET_QNT(qnt_zeta_dot,
"zeta_dot",
"velocity of zeta coordinate",
4888 SET_QNT(qnt_tvirt,
"tvirt",
"virtual temperature",
"K")
4889 SET_QNT(qnt_lapse,
"lapse",
"temperature lapse rate",
"K/km")
4890 SET_QNT(qnt_vh,
"vh",
"horizontal velocity",
"m/s")
4891 SET_QNT(qnt_vz,
"vz",
"vertical velocity",
"m/s")
4892 SET_QNT(qnt_pv,
"pv",
"potential vorticity",
"PVU")
4893 SET_QNT(qnt_tdew,
"tdew",
"dew point temperature",
"K")
4894 SET_QNT(qnt_tice,
"tice",
"frost point temperature",
"K")
4895 SET_QNT(qnt_tsts,
"tsts",
"STS existence temperature",
"K")
4896 SET_QNT(qnt_tnat,
"tnat",
"NAT existence temperature",
"K")
4897 SET_QNT(qnt_Cx,
"Cx",
"Trace species x volume mixing ratio",
"ppv")
4898 SET_QNT(qnt_Ch2o,
"Ch2o",
"H2O volume mixing ratio",
"ppv")
4899 SET_QNT(qnt_Co3,
"Co3",
"O3 volume mixing ratio",
"ppv")
4900 SET_QNT(qnt_Cco,
"Cco",
"CO volume mixing ratio",
"ppv")
4901 SET_QNT(qnt_Coh,
"Coh",
"HO volume mixing ratio",
"ppv")
4902 SET_QNT(qnt_Ch,
"Ch",
"H radical volume mixing ratio",
"ppv")
4903 SET_QNT(qnt_Cho2,
"Cho2",
"HO2 volume mixing ratio",
"ppv")
4904 SET_QNT(qnt_Ch2o2,
"Ch2o2",
"H2O2 volume mixing ratio",
"ppv")
4905 SET_QNT(qnt_Co1d,
"Co1d",
"O(1D) volume mixing ratio",
"ppv")
4906 SET_QNT(qnt_Co3p,
"Co3p",
"O(3P) radical volume mixing ratio",
"ppv")
4907 SET_QNT(qnt_Cccl4,
"Cccl4",
"CCl4 (CFC-10) volume mixing ratio",
"ppv")
4908 SET_QNT(qnt_Cccl3f,
"Cccl3f",
"CCl3F (CFC-11) volume mixing ratio",
4910 SET_QNT(qnt_Cccl2f2,
"Cccl2f2",
"CCl2F2 (CFC-12) volume mixing ratio",
4912 SET_QNT(qnt_Cn2o,
"Cn2o",
"N2O volume mixing ratio",
"ppv")
4913 SET_QNT(qnt_Csf6,
"Csf6",
"SF6 volume mixing ratio",
"ppv")
4914 SET_QNT(qnt_aoa,
"aoa",
"age of air",
"s")
4916 SET_QNT(qnt_destination,
"destination",
4917 "subdomain index of destination",
"-")
4918 SET_QNT(qnt_subdomain,
"subdomain",
"current subdomain index",
"-")
4925 (int)
scan_ctl(filename, argc, argv,
"ADVECT_VERT_COORD", -1,
"0", NULL);
4927 ERRMSG(
"Set ADVECT_VERT_COORD to 0, 1, or 2!");
4929 (int)
scan_ctl(filename, argc, argv,
"MET_VERT_COORD", -1,
"0", NULL);
4931 ERRMSG(
"Set MET_VERT_COORD to 0, 1, 2, 3, or 4!");
4933 ERRMSG(
"Please add zeta to your quantities for diabatic calculations!");
4936 (
"Using ADVECT_VERT_COORD = 2 requires meteo data on model levels!");
4940 (int)
scan_ctl(filename, argc, argv,
"DIRECTION", -1,
"1", NULL);
4942 ERRMSG(
"Set DIRECTION to -1 or 1!");
4943 ctl->
t_stop =
scan_ctl(filename, argc, argv,
"T_STOP", -1,
"1e100", NULL);
4944 ctl->
dt_mod =
scan_ctl(filename, argc, argv,
"DT_MOD", -1,
"180", NULL);
4948 ctl->
dt_met =
scan_ctl(filename, argc, argv,
"DT_MET", -1,
"3600", NULL);
4950 (int)
scan_ctl(filename, argc, argv,
"MET_CONVENTION", -1,
"0", NULL);
4952 (int)
scan_ctl(filename, argc, argv,
"MET_TYPE", -1,
"0", NULL);
4955 (
"Please use meteo files in netcdf format for diabatic calculations.");
4957 (int)
scan_ctl(filename, argc, argv,
"MET_CLAMS", -1,
"0", NULL);
4959 (int)
scan_ctl(filename, argc, argv,
"MET_NC_SCALE", -1,
"1", NULL);
4961 (int)
scan_ctl(filename, argc, argv,
"MET_NC_LEVEL", -1,
"0", NULL);
4963 (int)
scan_ctl(filename, argc, argv,
"MET_NC_QUANT", -1,
"0", NULL);
4965 (int)
scan_ctl(filename, argc, argv,
"MET_ZSTD_LEVEL", -1,
"0", NULL);
4966 for (
int i = 0; i <
METVAR; i++) {
4967 char defprec[
LEN] =
"0", deftol[
LEN] =
"0.0";
4969 sprintf(deftol,
"0.5");
4971 sprintf(deftol,
"5.0");
4973 sprintf(defprec,
"8");
4975 (int)
scan_ctl(filename, argc, argv,
"MET_COMP_PREC", i, defprec, NULL);
4977 scan_ctl(filename, argc, argv,
"MET_COMP_TOL", i, deftol, NULL);
4980 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_BATCH", -1,
"-1", NULL);
4982 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ZSTD", -1,
"1", NULL);
4984 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_HEUR", -1,
"1", NULL);
4986 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_Z", -1,
"1.0", NULL);
4988 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_T", -1,
"0.05", NULL);
4990 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_U", -1,
"0.05", NULL);
4992 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_V", -1,
"0.05", NULL);
4994 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_W", -1,
"1.0", NULL);
4996 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_PV", -1,
"1.0", NULL);
4998 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_H2O", -1,
"1.0", NULL);
5000 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_O3", -1,
"1.0", NULL);
5002 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_LWC", -1,
"1.0", NULL);
5004 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_RWC", -1,
"1.0", NULL);
5006 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_IWC", -1,
"1.0", NULL);
5008 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_SWC", -1,
"1.0", NULL);
5010 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_CC", -1,
"1.0", NULL);
5011 ctl->
met_dx = (int)
scan_ctl(filename, argc, argv,
"MET_DX", -1,
"1", NULL);
5012 ctl->
met_dy = (int)
scan_ctl(filename, argc, argv,
"MET_DY", -1,
"1", NULL);
5013 ctl->
met_dp = (int)
scan_ctl(filename, argc, argv,
"MET_DP", -1,
"1", NULL);
5015 ERRMSG(
"MET_DX, MET_DY, and MET_DP need to be greater than zero!");
5016 ctl->
met_sx = (int)
scan_ctl(filename, argc, argv,
"MET_SX", -1,
"1", NULL);
5017 ctl->
met_sy = (int)
scan_ctl(filename, argc, argv,
"MET_SY", -1,
"1", NULL);
5018 ctl->
met_sp = (int)
scan_ctl(filename, argc, argv,
"MET_SP", -1,
"1", NULL);
5020 ERRMSG(
"MET_SX, MET_SY, and MET_SP need to be greater than zero!");
5022 scan_ctl(filename, argc, argv,
"MET_DETREND", -1,
"-999", NULL);
5023 ctl->
met_np = (int)
scan_ctl(filename, argc, argv,
"MET_NP", -1,
"0", NULL);
5025 ERRMSG(
"Too many pressure levels!");
5027 (int)
scan_ctl(filename, argc, argv,
"MET_PRESS_LEVEL_DEF", -1,
"-1",
5033 for (
int ip = 0; ip < ctl->
met_np; ip++)
5035 scan_ctl(filename, argc, argv,
"MET_P", ip,
"", NULL);
5039 (int)
scan_ctl(filename, argc, argv,
"MET_NLEV", -1,
"0", NULL);
5041 ERRMSG(
"Too many model levels!");
5042 for (
int ip = 0; ip < ctl->
met_nlev; ip++) {
5044 scan_ctl(filename, argc, argv,
"MET_LEV_HYAM", ip,
"", NULL);
5046 scan_ctl(filename, argc, argv,
"MET_LEV_HYBM", ip,
"", NULL);
5049 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SX", -1,
"-1", NULL);
5051 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SY", -1,
"-1", NULL);
5053 (int)
scan_ctl(filename, argc, argv,
"MET_RELHUM", -1,
"0", NULL);
5055 (int)
scan_ctl(filename, argc, argv,
"MET_CAPE", -1,
"1", NULL);
5057 ERRMSG(
"Set MET_CAPE to 0 or 1!");
5059 (int)
scan_ctl(filename, argc, argv,
"MET_PBL", -1,
"3", NULL);
5061 ERRMSG(
"Set MET_PBL to 0 ... 3!");
5063 scan_ctl(filename, argc, argv,
"MET_PBL_MIN", -1,
"0.1", NULL);
5065 scan_ctl(filename, argc, argv,
"MET_PBL_MAX", -1,
"5.0", NULL);
5067 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO", -1,
"3", NULL);
5069 ERRMSG(
"Set MET_TROPO to 0 ... 5!");
5071 scan_ctl(filename, argc, argv,
"MET_TROPO_PV", -1,
"3.5", NULL);
5073 scan_ctl(filename, argc, argv,
"MET_TROPO_THETA", -1,
"380", NULL);
5075 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO_SPLINE", -1,
"1", NULL);
5077 scan_ctl(filename, argc, argv,
"MET_DT_OUT", -1,
"0.1", NULL);
5079 (int)
scan_ctl(filename, argc, argv,
"MET_CACHE", -1,
"0", NULL);
5081 (int)
scan_ctl(filename, argc, argv,
"MET_MPI_SHARE", -1,
"0", NULL);
5084 ctl->
sort_dt =
scan_ctl(filename, argc, argv,
"SORT_DT", -1,
"-999", NULL);
5088 (int)
scan_ctl(filename, argc, argv,
"ISOSURF", -1,
"0", NULL);
5093 (int)
scan_ctl(filename, argc, argv,
"RNG_TYPE", -1,
"1", NULL);
5095 ERRMSG(
"Set RNG_TYPE to 0, 1, or 2!");
5098 ctl->
advect = (int)
scan_ctl(filename, argc, argv,
"ADVECT", -1,
"2", NULL);
5102 ERRMSG(
"Set ADVECT to 0, 1, 2, or 4!");
5106 = (int)
scan_ctl(filename, argc, argv,
"DIFFUSION", -1,
"0", NULL);
5108 ERRMSG(
"Set DIFFUSION to 0, 1 or 2!");
5110 scan_ctl(filename, argc, argv,
"TURB_DX_PBL", -1,
"50", NULL);
5112 scan_ctl(filename, argc, argv,
"TURB_DX_TROP", -1,
"50", NULL);
5114 scan_ctl(filename, argc, argv,
"TURB_DX_STRAT", -1,
"0", NULL);
5116 scan_ctl(filename, argc, argv,
"TURB_DZ_PBL", -1,
"0", NULL);
5118 scan_ctl(filename, argc, argv,
"TURB_DZ_TROP", -1,
"0", NULL);
5120 scan_ctl(filename, argc, argv,
"TURB_DZ_STRAT", -1,
"0.1", NULL);
5122 scan_ctl(filename, argc, argv,
"TURB_MESOX", -1,
"0.16", NULL);
5124 scan_ctl(filename, argc, argv,
"TURB_MESOZ", -1,
"0.16", NULL);
5128 = (int)
scan_ctl(filename, argc, argv,
"CONV_MIX_PBL", -1,
"0", NULL);
5130 =
scan_ctl(filename, argc, argv,
"CONV_PBL_TRANS", -1,
"0", NULL);
5132 =
scan_ctl(filename, argc, argv,
"CONV_CAPE", -1,
"-999", NULL);
5134 =
scan_ctl(filename, argc, argv,
"CONV_CIN", -1,
"-999", NULL);
5135 ctl->
conv_dt =
scan_ctl(filename, argc, argv,
"CONV_DT", -1,
"-999", NULL);
5139 scan_ctl(filename, argc, argv,
"BOUND_MASS", -1,
"-999", NULL);
5141 scan_ctl(filename, argc, argv,
"BOUND_MASS_TREND", -1,
"0", NULL);
5143 scan_ctl(filename, argc, argv,
"BOUND_VMR", -1,
"-999", NULL);
5145 scan_ctl(filename, argc, argv,
"BOUND_VMR_TREND", -1,
"0", NULL);
5147 scan_ctl(filename, argc, argv,
"BOUND_LAT0", -1,
"-999", NULL);
5149 scan_ctl(filename, argc, argv,
"BOUND_LAT1", -1,
"-999", NULL);
5151 scan_ctl(filename, argc, argv,
"BOUND_P0", -1,
"-999", NULL);
5153 scan_ctl(filename, argc, argv,
"BOUND_P1", -1,
"-999", NULL);
5155 scan_ctl(filename, argc, argv,
"BOUND_DPS", -1,
"-999", NULL);
5157 scan_ctl(filename, argc, argv,
"BOUND_DZS", -1,
"-999", NULL);
5159 scan_ctl(filename, argc, argv,
"BOUND_ZETAS", -1,
"-999", NULL);
5161 (int)
scan_ctl(filename, argc, argv,
"BOUND_PBL", -1,
"0", NULL);
5165 if (strcasecmp(ctl->
species,
"CF2Cl2") == 0) {
5169 }
else if (strcasecmp(ctl->
species,
"CFCl3") == 0) {
5173 }
else if (strcasecmp(ctl->
species,
"CH4") == 0) {
5180 }
else if (strcasecmp(ctl->
species,
"CO") == 0) {
5189 }
else if (strcasecmp(ctl->
species,
"CO2") == 0) {
5193 }
else if (strcasecmp(ctl->
species,
"H2O") == 0) {
5195 }
else if (strcasecmp(ctl->
species,
"N2O") == 0) {
5199 }
else if (strcasecmp(ctl->
species,
"NH3") == 0) {
5206 }
else if (strcasecmp(ctl->
species,
"HNO3") == 0) {
5210 }
else if (strcasecmp(ctl->
species,
"NO") == 0) {
5219 }
else if (strcasecmp(ctl->
species,
"NO2") == 0) {
5228 }
else if (strcasecmp(ctl->
species,
"O3") == 0) {
5235 }
else if (strcasecmp(ctl->
species,
"SF6") == 0) {
5239 }
else if (strcasecmp(ctl->
species,
"SO2") == 0) {
5252 sprintf(defstr,
"%g", ctl->
molmass);
5253 ctl->
molmass =
scan_ctl(filename, argc, argv,
"MOLMASS", -1, defstr, NULL);
5258 (int)
scan_ctl(filename, argc, argv,
"OH_CHEM_REACTION", -1, defstr,
5260 for (
int ip = 0; ip < 4; ip++) {
5261 sprintf(defstr,
"%g", ctl->
oh_chem[ip]);
5263 scan_ctl(filename, argc, argv,
"OH_CHEM", ip, defstr, NULL);
5266 scan_ctl(filename, argc, argv,
"OH_CHEM_BETA", -1,
"0", NULL);
5270 (int)
scan_ctl(filename, argc, argv,
"H2O2_CHEM_REACTION", -1,
"0", NULL);
5274 (int)
scan_ctl(filename, argc, argv,
"KPP_CHEM", -1,
"0", NULL);
5275 ctl->
dt_kpp =
scan_ctl(filename, argc, argv,
"DT_KPP", -1,
"1800", NULL);
5279 (int)
scan_ctl(filename, argc, argv,
"TRACER_CHEM", -1,
"0", NULL);
5282 for (
int ip = 0; ip < 2; ip++) {
5285 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_H", ip, defstr, NULL);
5287 for (
int ip = 0; ip < 1; ip++) {
5290 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_H", ip, defstr, NULL);
5293 scan_ctl(filename, argc, argv,
"WET_DEPO_SO2_PH", -1,
"0", NULL);
5295 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_A", -1,
"0", NULL);
5297 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_B", -1,
"0", NULL);
5299 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_A", -1,
"0", NULL);
5301 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_B", -1,
"0", NULL);
5303 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 0,
"0.5", NULL);
5305 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 1,
"0.36", NULL);
5307 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_RET_RATIO", -1,
"1", NULL);
5309 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_RET_RATIO", -1,
"1", NULL);
5313 scan_ctl(filename, argc, argv,
"DRY_DEPO_VDEP", -1,
"0", NULL);
5315 scan_ctl(filename, argc, argv,
"DRY_DEPO_DP", -1,
"30", NULL);
5318 scan_ctl(filename, argc, argv,
"CLIM_PHOTO", -1,
5319 "../../data/clams_photolysis_rates.nc", ctl->
clim_photo);
5320 scan_ctl(filename, argc, argv,
"CLIM_HNO3_FILENAME", -1,
5322 scan_ctl(filename, argc, argv,
"CLIM_OH_FILENAME", -1,
5324 scan_ctl(filename, argc, argv,
"CLIM_H2O2_FILENAME", -1,
5326 scan_ctl(filename, argc, argv,
"CLIM_HO2_FILENAME", -1,
5328 scan_ctl(filename, argc, argv,
"CLIM_O1D_FILENAME", -1,
5330 scan_ctl(filename, argc, argv,
"CLIM_CCL4_TIMESERIES", -1,
5332 scan_ctl(filename, argc, argv,
"CLIM_CCL3F_TIMESERIES", -1,
5334 scan_ctl(filename, argc, argv,
"CLIM_CCL2F2_TIMESERIES", -1,
5336 scan_ctl(filename, argc, argv,
"CLIM_N2O_TIMESERIES", -1,
5338 scan_ctl(filename, argc, argv,
"CLIM_SF6_TIMESERIES", -1,
5343 scan_ctl(filename, argc, argv,
"MIXING_DT", -1,
"3600.", NULL);
5345 scan_ctl(filename, argc, argv,
"MIXING_TROP", -1,
"-999", NULL);
5347 scan_ctl(filename, argc, argv,
"MIXING_STRAT", -1,
"-999", NULL);
5349 scan_ctl(filename, argc, argv,
"MIXING_Z0", -1,
"-5", NULL);
5351 scan_ctl(filename, argc, argv,
"MIXING_Z1", -1,
"85", NULL);
5353 (int)
scan_ctl(filename, argc, argv,
"MIXING_NZ", -1,
"90", NULL);
5355 scan_ctl(filename, argc, argv,
"MIXING_LON0", -1,
"-180", NULL);
5357 scan_ctl(filename, argc, argv,
"MIXING_LON1", -1,
"180", NULL);
5359 (int)
scan_ctl(filename, argc, argv,
"MIXING_NX", -1,
"360", NULL);
5361 scan_ctl(filename, argc, argv,
"MIXING_LAT0", -1,
"-90", NULL);
5363 scan_ctl(filename, argc, argv,
"MIXING_LAT1", -1,
"90", NULL);
5365 (int)
scan_ctl(filename, argc, argv,
"MIXING_NY", -1,
"180", NULL);
5369 scan_ctl(filename, argc, argv,
"CHEMGRID_Z0", -1,
"-5", NULL);
5371 scan_ctl(filename, argc, argv,
"CHEMGRID_Z1", -1,
"85", NULL);
5373 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NZ", -1,
"90", NULL);
5375 scan_ctl(filename, argc, argv,
"CHEMGRID_LON0", -1,
"-180", NULL);
5377 scan_ctl(filename, argc, argv,
"CHEMGRID_LON1", -1,
"180", NULL);
5379 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NX", -1,
"360", NULL);
5381 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT0", -1,
"-90", NULL);
5383 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT1", -1,
"90", NULL);
5385 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NY", -1,
"180", NULL);
5390 scan_ctl(filename, argc, argv,
"TDEC_STRAT", -1,
"0", NULL);
5393 ctl->
psc_h2o =
scan_ctl(filename, argc, argv,
"PSC_H2O", -1,
"4e-6", NULL);
5395 scan_ctl(filename, argc, argv,
"PSC_HNO3", -1,
"9e-9", NULL);
5401 scan_ctl(filename, argc, argv,
"ATM_DT_OUT", -1,
"86400", NULL);
5403 (int)
scan_ctl(filename, argc, argv,
"ATM_FILTER", -1,
"0", NULL);
5405 (int)
scan_ctl(filename, argc, argv,
"ATM_STRIDE", -1,
"1", NULL);
5407 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE", -1,
"0", NULL);
5409 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE_OUT", -1,
"-1", NULL);
5413 (int)
scan_ctl(filename, argc, argv,
"ATM_NC_LEVEL", -1,
"0", NULL);
5414 for (
int iq = 0; iq < ctl->
nq; iq++)
5416 (
int)
scan_ctl(filename, argc, argv,
"ATM_NC_QUANT", iq,
"0", NULL);
5418 (int)
scan_ctl(filename, argc, argv,
"OBS_TYPE", -1,
"0", NULL);
5424 scan_ctl(filename, argc, argv,
"CSI_DT_OUT", -1,
"86400", NULL);
5427 scan_ctl(filename, argc, argv,
"CSI_OBSMIN", -1,
"0", NULL);
5429 scan_ctl(filename, argc, argv,
"CSI_MODMIN", -1,
"0", NULL);
5430 ctl->
csi_z0 =
scan_ctl(filename, argc, argv,
"CSI_Z0", -1,
"-5", NULL);
5431 ctl->
csi_z1 =
scan_ctl(filename, argc, argv,
"CSI_Z1", -1,
"85", NULL);
5432 ctl->
csi_nz = (int)
scan_ctl(filename, argc, argv,
"CSI_NZ", -1,
"1", NULL);
5434 scan_ctl(filename, argc, argv,
"CSI_LON0", -1,
"-180", NULL);
5435 ctl->
csi_lon1 =
scan_ctl(filename, argc, argv,
"CSI_LON1", -1,
"180", NULL);
5437 (int)
scan_ctl(filename, argc, argv,
"CSI_NX", -1,
"360", NULL);
5438 ctl->
csi_lat0 =
scan_ctl(filename, argc, argv,
"CSI_LAT0", -1,
"-90", NULL);
5439 ctl->
csi_lat1 =
scan_ctl(filename, argc, argv,
"CSI_LAT1", -1,
"90", NULL);
5441 (int)
scan_ctl(filename, argc, argv,
"CSI_NY", -1,
"180", NULL);
5444 ctl->
nens = (int)
scan_ctl(filename, argc, argv,
"NENS", -1,
"0", NULL);
5447 scan_ctl(filename, argc, argv,
"ENS_DT_OUT", -1,
"86400", NULL);
5450 scan_ctl(filename, argc, argv,
"GRID_BASENAME", -1,
"-",
5455 scan_ctl(filename, argc, argv,
"GRID_DT_OUT", -1,
"86400", NULL);
5457 (int)
scan_ctl(filename, argc, argv,
"GRID_SPARSE", -1,
"0", NULL);
5459 (int)
scan_ctl(filename, argc, argv,
"GRID_NC_LEVEL", -1,
"0", NULL);
5460 for (
int iq = 0; iq < ctl->
nq; iq++)
5462 (
int)
scan_ctl(filename, argc, argv,
"GRID_NC_QUANT", iq,
"0", NULL);
5464 (int)
scan_ctl(filename, argc, argv,
"GRID_STDDEV", -1,
"0", NULL);
5465 ctl->
grid_z0 =
scan_ctl(filename, argc, argv,
"GRID_Z0", -1,
"-5", NULL);
5466 ctl->
grid_z1 =
scan_ctl(filename, argc, argv,
"GRID_Z1", -1,
"85", NULL);
5468 (int)
scan_ctl(filename, argc, argv,
"GRID_NZ", -1,
"1", NULL);
5470 scan_ctl(filename, argc, argv,
"GRID_LON0", -1,
"-180", NULL);
5472 scan_ctl(filename, argc, argv,
"GRID_LON1", -1,
"180", NULL);
5474 (int)
scan_ctl(filename, argc, argv,
"GRID_NX", -1,
"360", NULL);
5476 scan_ctl(filename, argc, argv,
"GRID_LAT0", -1,
"-90", NULL);
5478 scan_ctl(filename, argc, argv,
"GRID_LAT1", -1,
"90", NULL);
5480 (int)
scan_ctl(filename, argc, argv,
"GRID_NY", -1,
"180", NULL);
5482 (int)
scan_ctl(filename, argc, argv,
"GRID_TYPE", -1,
"0", NULL);
5485 scan_ctl(filename, argc, argv,
"PROF_BASENAME", -1,
"-",
5488 ctl->
prof_z0 =
scan_ctl(filename, argc, argv,
"PROF_Z0", -1,
"0", NULL);
5489 ctl->
prof_z1 =
scan_ctl(filename, argc, argv,
"PROF_Z1", -1,
"60", NULL);
5491 (int)
scan_ctl(filename, argc, argv,
"PROF_NZ", -1,
"60", NULL);
5493 scan_ctl(filename, argc, argv,
"PROF_LON0", -1,
"-180", NULL);
5495 scan_ctl(filename, argc, argv,
"PROF_LON1", -1,
"180", NULL);
5497 (int)
scan_ctl(filename, argc, argv,
"PROF_NX", -1,
"360", NULL);
5499 scan_ctl(filename, argc, argv,
"PROF_LAT0", -1,
"-90", NULL);
5501 scan_ctl(filename, argc, argv,
"PROF_LAT1", -1,
"90", NULL);
5503 (int)
scan_ctl(filename, argc, argv,
"PROF_NY", -1,
"180", NULL);
5506 scan_ctl(filename, argc, argv,
"SAMPLE_BASENAME", -1,
"-",
5508 scan_ctl(filename, argc, argv,
"SAMPLE_KERNEL", -1,
"-",
5510 scan_ctl(filename, argc, argv,
"SAMPLE_OBSFILE", -1,
"-",
5513 scan_ctl(filename, argc, argv,
"SAMPLE_DX", -1,
"50", NULL);
5515 scan_ctl(filename, argc, argv,
"SAMPLE_DZ", -1,
"-999", NULL);
5518 scan_ctl(filename, argc, argv,
"STAT_BASENAME", -1,
"-",
5522 ctl->
stat_r =
scan_ctl(filename, argc, argv,
"STAT_R", -1,
"50", NULL);
5524 scan_ctl(filename, argc, argv,
"STAT_T0", -1,
"-1e100", NULL);
5525 ctl->
stat_t1 =
scan_ctl(filename, argc, argv,
"STAT_T1", -1,
"1e100", NULL);
5530 scan_ctl(filename, argc, argv,
"VTK_DT_OUT", -1,
"86400", NULL);
5532 (int)
scan_ctl(filename, argc, argv,
"VTK_STRIDE", -1,
"1", NULL);
5534 scan_ctl(filename, argc, argv,
"VTK_SCALE", -1,
"1.0", NULL);
5536 scan_ctl(filename, argc, argv,
"VTK_OFFSET", -1,
"0.0", NULL);
5538 (int)
scan_ctl(filename, argc, argv,
"VTK_SPHERE", -1,
"0", NULL);
5543 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_MERIDIONAL", -1,
"1",
5546 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_ZONAL", -1,
"1",
5549 (int)
scan_ctl(filename, argc, argv,
"DD_NBR_NEIGHBOURS", -1,
"8", NULL);
5551 (int)
scan_ctl(filename, argc, argv,
"DD_HALOS_SIZE", -1,
"1", NULL);
5559 const char *filename,
5565 LOG(1,
"Read meteo data: %s", filename);
5571 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
5604 ERRMSG(
"MET_TYPE not implemented!");
5658 LOG(2,
"Broadcast data on rank %d...", rank);
5798 module_dd(ctl, atm, cache, mpi_info, met0);
5806 ERRMSG(
"Code was compiled without KPP!");
5839#pragma acc update device(ctl[:1])
5843 if (cache != NULL) {
5846#pragma acc update device(cache[:1])
5853#pragma acc update device(clim[:1])
5860 met_t *met0up = *met0;
5861#pragma acc update device(met0up[:1])
5868 met_t *met1up = *met1;
5869#pragma acc update device(met1up[:1])
5876#pragma acc update device(atm[:1])
5895#pragma acc update host(ctl[:1])
5899 if (cache != NULL) {
5902#pragma acc update host(cache[:1])
5909#pragma acc update host(clim[:1])
5916 met_t *met0up = *met0;
5917#pragma acc update host(met0up[:1])
5924 met_t *met1up = *met1;
5925#pragma acc update host(met1up[:1])
5932#pragma acc update host(atm[:1])
5940 const char *filename,
5949 LOG(1,
"Write atmospheric data: %s", filename);
5973 ERRMSG(
"Atmospheric data type not supported!");
5977 LOG(2,
"Number of particles: %d", atm->
np);
5978 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
5979 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
5980 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
5981 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
5982 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
5983 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
5984 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
5985 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
5986 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
5987 for (
int iq = 0; iq < ctl->
nq; iq++) {
5989 sprintf(msg,
"Quantity %s range: %s ... %s %s",
5992 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
5993 LOG(2, msg, mini, maxi);
6000 const char *filename,
6008 LOG(1,
"Write meteo data: %s", filename);
6013 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
6017 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
6021 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
6025 ERRMSG(
"MPTRAC was compiled without SZ3 compression!");
6038 ERRMSG(
"MET_TYPE not implemented!");
6044 const char *dirname,
6051 char ext[10], filename[2 *
LEN];
6055 int year, mon, day, hour, min, sec;
6058 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
6073 sprintf(ext,
"tab");
6075 sprintf(ext,
"bin");
6078 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6079 dirname, ctl->
atm_basename, year, mon, day, hour, min, ext);
6085 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6088 write_grid(filename, ctl, met0, met1, atm, t);
6093 sprintf(filename,
"%s/%s.tab", dirname, ctl->
csi_basename);
6099 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.tab",
6100 dirname, ctl->
ens_basename, year, mon, day, hour, min);
6106 sprintf(filename,
"%s/%s.tab", dirname, ctl->
prof_basename);
6107 write_prof(filename, ctl, met0, met1, atm, t);
6118 sprintf(filename,
"%s/%s.tab", dirname, ctl->
stat_basename);
6127 sprintf(filename,
"%s/%s_%05d.vtk", dirname, ctl->
vtk_basename, ++nvtk);
6137 const double hno3) {
6140 const double h2o_help =
MAX(h2o, 0.1e-6);
6143 const double p_hno3 = hno3 * p / 1.333224;
6144 const double p_h2o = h2o_help * p / 1.333224;
6145 const double a = 0.009179 - 0.00088 * log10(p_h2o);
6146 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
6147 const double c = -11397.0 / a;
6148 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
6149 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
6167 const double p0 = pbl;
6170 if (atm->
p[ip] > p0)
6172 else if (atm->
p[ip] < p1)
6175 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
6181 const char *filename,
6187 if (!(in = fopen(filename,
"r"))) {
6188 WARN(
"Cannot open file!");
6194 while (fgets(line,
LEN, in)) {
6198 TOK(line, tok,
"%lg", atm->
time[atm->
np]);
6199 TOK(NULL, tok,
"%lg", atm->
p[atm->
np]);
6200 TOK(NULL, tok,
"%lg", atm->
lon[atm->
np]);
6201 TOK(NULL, tok,
"%lg", atm->
lat[atm->
np]);
6202 for (
int iq = 0; iq < ctl->
nq; iq++)
6203 TOK(NULL, tok,
"%lg", atm->
q[iq][atm->
np]);
6206 atm->
p[atm->
np] =
P(atm->
p[atm->
np]);
6209 if ((++atm->
np) >
NP)
6210 ERRMSG(
"Too many data points!");
6223 const char *filename,
6229 if (!(in = fopen(filename,
"r")))
6234 FREAD(&version,
int,
6238 ERRMSG(
"Wrong version of binary data!");
6256 for (
int iq = 0; iq < ctl->
nq; iq++)
6257 FREAD(atm->
q[iq],
double,
6267 ERRMSG(
"Error while reading binary data!");
6279 const char *filename,
6286 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
6293 if (nc_inq_varid(ncid,
"TIME_INIT", &varid) == NC_NOERR) {
6294 NC(nc_get_var_double(ncid, varid, atm->
time));
6296 WARN(
"TIME_INIT not found use time instead!");
6299 for (
int ip = 0; ip < atm->
np; ip++) {
6300 atm->
time[ip] = time_init;
6312 if (nc_inq_varid(ncid,
"PRESS_INIT", &varid) == NC_NOERR) {
6313 NC(nc_get_var_double(ncid, varid, atm->
p));
6315 WARN(
"PRESS_INIT not found use PRESS instead!");
6316 nc_inq_varid(ncid,
"PRESS", &varid);
6317 NC(nc_get_var_double(ncid, varid, atm->
p));
6322 for (
int iq = 0; iq < ctl->
nq; iq++)
6339 const char *filename,
6346 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
6359 for (
int iq = 0; iq < ctl->
nq; iq++)
6372 const char *filename,
6378 LOG(1,
"Read photolysis rates: %s", filename);
6381 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
6382 WARN(
"Photolysis rate data are missing!");
6389 if (photo->
p[0] < photo->
p[1])
6390 ERRMSG(
"Pressure data are not descending!");
6395 if (photo->
o3c[0] > photo->
o3c[1])
6396 ERRMSG(
"Total column ozone data are not ascending!");
6401 if (photo->
sza[0] > photo->
sza[1])
6402 ERRMSG(
"Solar zenith angle data are not ascending!");
6419 LOG(2,
"Number of pressure levels: %d", photo->
np);
6420 LOG(2,
"Altitude levels: %g, %g ... %g km",
6421 Z(photo->
p[0]),
Z(photo->
p[1]),
Z(photo->
p[photo->
np - 1]));
6422 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
6423 photo->
p[0], photo->
p[1], photo->
p[photo->
np - 1]);
6424 LOG(2,
"Number of solar zenith angles: %d", photo->
nsza);
6425 LOG(2,
"Solar zenith angles: %g, %g ... %g deg",
6428 LOG(2,
"Number of total column ozone values: %d", photo->
no3c);
6429 LOG(2,
"Total column ozone: %g, %g ... %g DU",
6431 LOG(2,
"N2O photolysis rate: %g, %g ... %g s**-1",
6432 photo->
n2o[0][0][0], photo->
n2o[1][0][0],
6433 photo->
n2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
6434 LOG(2,
"CCl4 photolysis rate: %g, %g ... %g s**-1",
6435 photo->
ccl4[0][0][0], photo->
ccl4[1][0][0],
6437 LOG(2,
"CFC-11 photolysis rate: %g, %g ... %g s**-1",
6438 photo->
ccl3f[0][0][0], photo->
ccl3f[1][0][0],
6440 LOG(2,
"CFC-12 photolysis rate: %g, %g ... %g s**-1",
6443 LOG(2,
"O2 photolysis rate: %g, %g ... %g s**-1",
6444 photo->
o2[0][0][0], photo->
o2[1][0][0],
6445 photo->
o2[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
6446 LOG(2,
"O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
6447 photo->
o3_1[0][0][0], photo->
o3_1[1][0][0],
6449 LOG(2,
"O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
6450 photo->
o3_2[0][0][0], photo->
o3_2[1][0][0],
6452 LOG(2,
"H2O2 photolysis rate: %g, %g ... %g s**-1",
6453 photo->
h2o2[0][0][0], photo->
h2o2[1][0][0],
6455 LOG(2,
"H2O photolysis rate: %g, %g ... %g s**-1",
6456 photo->
h2o[0][0][0], photo->
h2o[1][0][0],
6457 photo->
h2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
6464 const char *varname,
6478 for (
int ip = 0; ip < photo->
np; ip++)
6479 for (
int is = 0; is < photo->
nsza; is++)
6480 for (
int io = 0; io < photo->
no3c; io++)
6491 const char *filename,
6495 LOG(1,
"Read climatological time series: %s", filename);
6499 if (!(in = fopen(filename,
"r"))) {
6500 WARN(
"Cannot open file!");
6507 while (fgets(line,
LEN, in))
6508 if (sscanf(line,
"%lg %lg", &ts->
time[nh], &ts->
vmr[nh]) == 2) {
6511 ts->
time[nh] = (ts->
time[nh] - 2000.0) * 365.25 * 86400.;
6514 if (nh > 0 && ts->
time[nh] <= ts->
time[nh - 1])
6515 ERRMSG(
"Time series must be ascending!");
6519 ERRMSG(
"Too many data points!");
6528 ERRMSG(
"Not enough data points!");
6531 LOG(2,
"Number of time steps: %d", ts->
ntime);
6532 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s", ts->
time[0], ts->
time[1],
6534 LOG(2,
"Volume mixing ratio range: %g ... %g ppv",
6535 gsl_stats_min(ts->
vmr, 1, (
size_t) nh), gsl_stats_max(ts->
vmr, 1,
6545 const char *filename,
6546 const char *varname,
6549 int ncid, varid, it, iy, iz, iz2, nt;
6551 double *help, varmin = 1e99, varmax = -1e99;
6554 LOG(1,
"Read %s data: %s", varname, filename);
6557 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
6558 WARN(
"%s climatology data are missing!", varname);
6565 if (zm->
p[0] < zm->
p[1])
6566 ERRMSG(
"Pressure data are not descending!");
6571 if (zm->
lat[0] > zm->
lat[1])
6572 ERRMSG(
"Latitude data are not ascending!");
6576 zm->
time[0] = 1209600.00;
6577 zm->
time[1] = 3888000.00;
6578 zm->
time[2] = 6393600.00;
6579 zm->
time[3] = 9072000.00;
6580 zm->
time[4] = 11664000.00;
6581 zm->
time[5] = 14342400.00;
6582 zm->
time[6] = 16934400.00;
6583 zm->
time[7] = 19612800.00;
6584 zm->
time[8] = 22291200.00;
6585 zm->
time[9] = 24883200.00;
6586 zm->
time[10] = 27561600.00;
6587 zm->
time[11] = 30153600.00;
6596 for (it = 0; it < zm->
ntime; it++)
6597 for (iz = 0; iz < zm->
np; iz++)
6598 for (iy = 0; iy < zm->
nlat; iy++)
6603 for (it = 0; it < zm->
ntime; it++)
6604 for (iy = 0; iy < zm->
nlat; iy++)
6605 for (iz = 0; iz < zm->
np; iz++) {
6606 if (zm->
vmr[it][iz][iy] < 0) {
6607 for (iz2 = 0; iz2 < zm->
np; iz2++)
6608 if (zm->
vmr[it][iz2][iy] >= 0) {
6609 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
6612 for (iz2 = zm->
np - 1; iz2 >= 0; iz2--)
6613 if (zm->
vmr[it][iz2][iy] >= 0) {
6614 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
6618 varmin =
MIN(varmin, zm->
vmr[it][iz][iy]);
6619 varmax =
MAX(varmax, zm->
vmr[it][iz][iy]);
6626 LOG(2,
"Number of time steps: %d", zm->
ntime);
6627 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
6629 LOG(2,
"Number of pressure levels: %d", zm->
np);
6630 LOG(2,
"Altitude levels: %g, %g ... %g km",
6631 Z(zm->
p[0]),
Z(zm->
p[1]),
Z(zm->
p[zm->
np - 1]));
6632 LOG(2,
"Pressure levels: %g, %g ... %g hPa", zm->
p[0],
6633 zm->
p[1], zm->
p[zm->
np - 1]);
6634 LOG(2,
"Number of latitudes: %d", zm->
nlat);
6635 LOG(2,
"Latitudes: %g, %g ... %g deg",
6637 LOG(2,
"%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
6644 const char *filename,
6650 LOG(1,
"Read kernel function: %s", filename);
6654 if (!(in = fopen(filename,
"r")))
6655 ERRMSG(
"Cannot open file!");
6660 while (fgets(line,
LEN, in))
6661 if (sscanf(line,
"%lg %lg", &kz[n], &kw[n]) == 2) {
6662 if (n > 0 && kz[n] < kz[n - 1])
6663 ERRMSG(
"Height levels must be ascending!");
6665 ERRMSG(
"Too many height levels!");
6674 ERRMSG(
"Not enough height levels!");
6677 const double kmax = gsl_stats_max(kw, 1, (
size_t) n);
6678 for (
int iz = 0; iz < n; iz++)
6685 const char *filename,
6693 int year, mon, day, hour, min, sec;
6699 if (!(in = fopen(filename,
"r"))) {
6700 WARN(
"Cannot open file!");
6706 FREAD(&met_type,
int,
6710 ERRMSG(
"Wrong MET_TYPE of binary data!");
6714 FREAD(&version,
int,
6718 ERRMSG(
"Wrong version of binary data!");
6724 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
6725 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
6726 met->
time, year, mon, day, hour, min);
6727 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
6728 || day < 1 || day > 31 || hour < 0 || hour > 23)
6729 ERRMSG(
"Error while reading time!");
6735 LOG(2,
"Number of longitudes: %d", met->
nx);
6736 if (met->
nx < 2 || met->
nx >
EX)
6737 ERRMSG(
"Number of longitudes out of range!");
6742 LOG(2,
"Number of latitudes: %d", met->
ny);
6743 if (met->
ny < 2 || met->
ny >
EY)
6744 ERRMSG(
"Number of latitudes out of range!");
6749 LOG(2,
"Number of levels: %d", met->
np);
6750 if (met->
np < 2 || met->
np >
EP)
6751 ERRMSG(
"Number of levels out of range!");
6757 LOG(2,
"Longitudes: %g, %g ... %g deg",
6763 LOG(2,
"Latitudes: %g, %g ... %g deg",
6769 LOG(2,
"Altitude levels: %g, %g ... %g km",
6770 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
6771 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
6772 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
6821 ERRMSG(
"Error while reading binary data!");
6836 const char *varname) {
6845 LOG(2,
"Read 2-D variable: %s (uncompressed)", varname);
6847 (
size_t) (met->
nx * met->
ny),
6851 for (
int ix = 0; ix < met->
nx; ix++)
6852 for (
int iy = 0; iy < met->
ny; iy++)
6853 var[ix][iy] = help[
ARRAY_2D(ix, iy, met->
ny)];
6866 const char *varname,
6867 const float bound_min,
6868 const float bound_max) {
6878 LOG(2,
"Read 3-D variable: %s (uncompressed)", varname);
6880 (
size_t) (met->
nx * met->
ny * met->
np),
6887 (
size_t) met->
np, 1, in);
6893 FREAD(&precision,
int,
6898 FREAD(&tolerance,
double,
6905 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
6915 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
6923 (
size_t) met->
np, 1, in);
6925 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
6933 FREAD(&precision,
int,
6938 FREAD(&tolerance,
double,
6945 ERRMSG(
"MPTRAC was compiled without sz3 compression!");
6950#pragma omp parallel for default(shared) collapse(2)
6951 for (
int ix = 0; ix < met->
nx; ix++)
6952 for (
int iy = 0; iy < met->
ny; iy++)
6953 for (
int ip = 0; ip < met->
np; ip++) {
6954 var[ix][iy][ip] = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
6955 if (var[ix][iy][ip] < bound_min)
6956 var[ix][iy][ip] = bound_min;
6957 else if (var[ix][iy][ip] > bound_max)
6958 var[ix][iy][ip] = bound_max;
6978 LOG(2,
"Calculate CAPE...");
6981 const double pfac = 1.01439, dz0 =
RI /
MA /
G0 * log(pfac);
6984#pragma omp parallel for default(shared) collapse(2)
6985 for (
int ix = 0; ix < met->
nx; ix++)
6986 for (
int iy = 0; iy < met->
ny; iy++) {
6990 double h2o = 0, t, theta = 0;
6991 double pbot =
MIN(met->
ps[ix][iy], met->
p[0]);
6992 double ptop = pbot - 50.;
6993 for (
int ip = 0; ip < met->
np; ip++) {
6994 if (met->
p[ip] <= pbot) {
6995 theta +=
THETA(met->
p[ip], met->
t[ix][iy][ip]);
6996 h2o += met->
h2o[ix][iy][ip];
6999 if (met->
p[ip] < ptop && n > 0)
7006 met->
plcl[ix][iy] = NAN;
7007 met->
plfc[ix][iy] = NAN;
7008 met->
pel[ix][iy] = NAN;
7009 met->
cape[ix][iy] = NAN;
7010 met->
cin[ix][iy] = NAN;
7016 pbot = met->
ps[ix][iy];
7018 met->
plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
7019 t = theta / pow(1000. / met->
plcl[ix][iy], 0.286);
7020 if (
RH(met->
plcl[ix][iy], t, h2o) > 100.)
7021 ptop = met->
plcl[ix][iy];
7023 pbot = met->
plcl[ix][iy];
7024 }
while (pbot - ptop > 0.1);
7028 double dcape, dz, h2o_env, t_env;
7029 double p = met->
ps[ix][iy];
7030 met->
cape[ix][iy] = met->
cin[ix][iy] = 0;
7032 dz = dz0 *
TVIRT(t, h2o);
7034 t = theta / pow(1000. / p, 0.286);
7038 &h2o_env, ci, cw, 0);
7039 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
7040 TVIRT(t_env, h2o_env) * dz;
7042 met->
cin[ix][iy] += fabsf((
float) dcape);
7043 }
while (p > met->
plcl[ix][iy]);
7048 p = met->
plcl[ix][iy];
7049 t = theta / pow(1000. / p, 0.286);
7052 dz = dz0 *
TVIRT(t, h2o);
7055 double psat =
PSAT(t);
7056 h2o = psat / (p - (1. -
EPS) * psat);
7060 &h2o_env, ci, cw, 0);
7061 double dcape_old = dcape;
7062 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
7063 TVIRT(t_env, h2o_env) * dz;
7065 met->
cape[ix][iy] += (float) dcape;
7066 if (!isfinite(met->
plfc[ix][iy]))
7067 met->
plfc[ix][iy] = (
float) p;
7068 }
else if (dcape_old > 0)
7069 met->
pel[ix][iy] = (float) p;
7070 if (dcape < 0 && !isfinite(met->
plfc[ix][iy]))
7071 met->
cin[ix][iy] += fabsf((
float) dcape);
7075 if (!isfinite(met->
plfc[ix][iy]))
7076 met->
cin[ix][iy] = NAN;
7087 LOG(2,
"Calculate cloud data...");
7090 const double ccmin = 0.01, cwmin = 1e-6;
7093#pragma omp parallel for default(shared) collapse(2)
7094 for (
int ix = 0; ix < met->
nx; ix++)
7095 for (
int iy = 0; iy < met->
ny; iy++) {
7098 met->
pct[ix][iy] = NAN;
7099 met->
pcb[ix][iy] = NAN;
7100 met->
cl[ix][iy] = 0;
7103 for (
int ip = 0; ip < met->
np - 1; ip++) {
7106 if (met->
p[ip] > met->
ps[ix][iy] || met->
p[ip] <
P(20.))
7110 if (met->
cc[ix][iy][ip] > ccmin
7111 && (met->
lwc[ix][iy][ip] > cwmin
7112 || met->
rwc[ix][iy][ip] > cwmin
7113 || met->
iwc[ix][iy][ip] > cwmin
7114 || met->
swc[ix][iy][ip] > cwmin)) {
7118 = (float) (0.5 * (met->
p[ip] + (
float) met->
p[ip + 1]));
7121 if (!isfinite(met->
pcb[ix][iy]))
7123 = (
float) (0.5 * (met->
p[ip] + met->
p[
MAX(ip - 1, 0)]));
7127 met->
cl[ix][iy] += (float)
7128 (0.5 * (met->
lwc[ix][iy][ip] + met->
lwc[ix][iy][ip + 1]
7129 + met->
rwc[ix][iy][ip] + met->
rwc[ix][iy][ip + 1]
7130 + met->
iwc[ix][iy][ip] + met->
iwc[ix][iy][ip + 1]
7131 + met->
swc[ix][iy][ip] + met->
swc[ix][iy][ip + 1])
7132 * 100. * (met->
p[ip] - met->
p[ip + 1]) /
G0);
7150 SELECT_TIMER(
"READ_MET_DETREND",
"METPROC", NVTX_READ);
7151 LOG(2,
"Detrend meteo data...");
7158 const double tssq = 2. *
SQR(sigma);
7161 int sy = (int) (3. *
DY2DEG(sigma) / fabs(met->
lat[1] - met->
lat[0]));
7165#pragma omp parallel for default(shared) collapse(2)
7166 for (
int ix = 0; ix < met->
nx; ix++) {
7167 for (
int iy = 0; iy < met->
ny; iy++) {
7175 (int) (3. *
DX2DEG(sigma, met->
lat[iy]) /
7176 fabs(met->
lon[1] - met->
lon[0]));
7181 for (
int ip = 0; ip < met->
np; ip++) {
7182 help->
t[ix][iy][ip] = 0;
7183 help->
u[ix][iy][ip] = 0;
7184 help->
v[ix][iy][ip] = 0;
7185 help->
w[ix][iy][ip] = 0;
7189 for (
int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
7193 else if (ix3 >= met->
nx)
7195 for (
int iy2 =
MAX(iy - sy, 0);
7196 iy2 <=
MIN(iy + sy, met->
ny - 1); iy2++) {
7203 const float w = (float) exp(-
DIST2(x0, x1) / tssq);
7207 for (
int ip = 0; ip < met->
np; ip++) {
7208 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip];
7209 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip];
7210 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip];
7211 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip];
7217 for (
int ip = 0; ip < met->
np; ip++) {
7218 help->
t[ix][iy][ip] /= wsum;
7219 help->
u[ix][iy][ip] /= wsum;
7220 help->
v[ix][iy][ip] /= wsum;
7221 help->
w[ix][iy][ip] /= wsum;
7227#pragma omp parallel for default(shared) collapse(3)
7228 for (
int ix = 0; ix < met->
nx; ix++)
7229 for (
int iy = 0; iy < met->
ny; iy++)
7230 for (
int ip = 0; ip < met->
np; ip++) {
7231 met->
t[ix][iy][ip] -= help->
t[ix][iy][ip];
7232 met->
u[ix][iy][ip] -= help->
u[ix][iy][ip];
7233 met->
v[ix][iy][ip] -= help->
v[ix][iy][ip];
7234 met->
w[ix][iy][ip] -= help->
w[ix][iy][ip];
7247 SELECT_TIMER(
"READ_MET_EXTRAPOLATE",
"METPROC", NVTX_READ);
7248 LOG(2,
"Extrapolate meteo data...");
7251#pragma omp parallel for default(shared) collapse(2)
7252 for (
int ix = 0; ix < met->
nx; ix++)
7253 for (
int iy = 0; iy < met->
ny; iy++) {
7257 for (ip0 = met->
np - 1; ip0 >= 0; ip0--)
7258 if (!isfinite(met->
t[ix][iy][ip0])
7259 || !isfinite(met->
u[ix][iy][ip0])
7260 || !isfinite(met->
v[ix][iy][ip0])
7261 || !isfinite(met->
w[ix][iy][ip0]))
7265 for (
int ip = ip0; ip >= 0; ip--) {
7266 met->
t[ix][iy][ip] = met->
t[ix][iy][ip + 1];
7267 met->
u[ix][iy][ip] = met->
u[ix][iy][ip + 1];
7268 met->
v[ix][iy][ip] = met->
v[ix][iy][ip + 1];
7269 met->
w[ix][iy][ip] = met->
w[ix][iy][ip + 1];
7270 met->
h2o[ix][iy][ip] = met->
h2o[ix][iy][ip + 1];
7271 met->
o3[ix][iy][ip] = met->
o3[ix][iy][ip + 1];
7272 met->
lwc[ix][iy][ip] = met->
lwc[ix][iy][ip + 1];
7273 met->
rwc[ix][iy][ip] = met->
rwc[ix][iy][ip + 1];
7274 met->
iwc[ix][iy][ip] = met->
iwc[ix][iy][ip + 1];
7275 met->
swc[ix][iy][ip] = met->
swc[ix][iy][ip + 1];
7276 met->
cc[ix][iy][ip] = met->
cc[ix][iy][ip + 1];
7295 LOG(2,
"Calculate geopotential heights...");
7302#pragma omp parallel for default(shared)
7303 for (
int ip = 0; ip < met->
np; ip++)
7304 logp[ip] = log(met->
p[ip]);
7307#pragma omp parallel for default(shared) collapse(2)
7308 for (
int ix = 0; ix < met->
nx; ix++)
7309 for (
int iy = 0; iy < met->
ny; iy++) {
7312 const double zs = met->
zs[ix][iy];
7313 const double lnps = log(met->
ps[ix][iy]);
7317 const double ts =
LIN(met->
p[ip0], met->
t[ix][iy][ip0], met->
p[ip0 + 1],
7318 met->
t[ix][iy][ip0 + 1], met->
ps[ix][iy]);
7320 LIN(met->
p[ip0], met->
h2o[ix][iy][ip0], met->
p[ip0 + 1],
7321 met->
h2o[ix][iy][ip0 + 1], met->
ps[ix][iy]);
7324 met->
z[ix][iy][ip0 + 1]
7326 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
7327 met->
t[ix][iy][ip0 + 1], met->
h2o[ix][iy][ip0 + 1]));
7328 for (
int ip = ip0 + 2; ip < met->
np; ip++)
7330 = (
float) (met->
z[ix][iy][ip - 1] +
7331 ZDIFF(logp[ip - 1], met->
t[ix][iy][ip - 1],
7332 met->
h2o[ix][iy][ip - 1], logp[ip],
7333 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
7338 ZDIFF(lnps, ts, h2os, logp[ip0],
7339 met->
t[ix][iy][ip0], met->
h2o[ix][iy][ip0]));
7340 for (
int ip = ip0 - 1; ip >= 0; ip--)
7342 = (
float) (met->
z[ix][iy][ip + 1] +
7343 ZDIFF(logp[ip + 1], met->
t[ix][iy][ip + 1],
7344 met->
h2o[ix][iy][ip + 1], logp[ip],
7345 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
7349 if (dx == 0 || dy == 0)
7353 if (dx < 0 || dy < 0) {
7354 if (fabs(met->
lon[1] - met->
lon[0]) < 0.5) {
7364 float ws[dx + 1][dy + 1];
7365#pragma omp parallel for default(shared) collapse(2)
7366 for (
int ix = 0; ix <= dx; ix++)
7367 for (
int iy = 0; iy < dy; iy++)
7368 ws[ix][iy] = (1.0f - (
float) ix / (float) dx)
7369 * (1.0f - (float) iy / (
float) dy);
7372#pragma omp parallel for default(shared) collapse(3)
7373 for (
int ix = 0; ix < met->
nx; ix++)
7374 for (
int iy = 0; iy < met->
ny; iy++)
7375 for (
int ip = 0; ip < met->
np; ip++)
7376 help[
ARRAY_3D(ip, ix, met->
nx, iy, met->
ny)] = met->
z[ix][iy][ip];
7379#pragma omp parallel for default(shared) collapse(3)
7380 for (
int ip = 0; ip < met->
np; ip++)
7381 for (
int ix = 0; ix < met->
nx; ix++)
7382 for (
int iy = 0; iy < met->
ny; iy++) {
7383 float res = 0, wsum = 0;
7384 int iy0 =
MAX(iy - dy + 1, 0);
7385 int iy1 =
MIN(iy + dy - 1, met->
ny - 1);
7386 for (
int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
7390 else if (ix3 >= met->
nx)
7392 for (
int iy2 = iy0; iy2 <= iy1; ++iy2)
7393 if (isfinite(help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)])) {
7394 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
7395 res += w * help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)];
7400 met->
z[ix][iy][ip] = res / wsum;
7402 met->
z[ix][iy][ip] = NAN;
7412 const char *filename,
7417 char levname[
LEN], tstr[10];
7419 double rtime = 0, r, r2;
7421 int varid, year2, mon2, day2, hour2, min2, sec2,
7422 year, mon, day, hour, min, sec;
7427 SELECT_TIMER(
"READ_MET_NC_GRID_DD",
"INPUT", NVTX_READ);
7428 LOG(2,
"Read meteo grid information...");
7437 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
7438 if (nc_inq_varid(ncid,
"time", &varid) == NC_NOERR) {
7439 NC(nc_get_var_double(ncid, varid, &rtime));
7440 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
7441 WARN(
"Time information in meteo file does not match filename!");
7443 WARN(
"Time information in meteo file is missing!");
7454 sprintf(tstr,
"19%.2s", &filename[strlen(filename) - 11]);
7456 sprintf(tstr,
"20%.2s", &filename[strlen(filename) - 11]);
7458 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 9]);
7460 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 7]);
7462 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 5]);
7468 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
7469 || day < 1 || day > 31 || hour < 0 || hour > 23)
7470 ERRMSG(
"Cannot read time from filename!");
7471 jsec2time(met->
time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
7472 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
7473 met->
time, year2, mon2, day2, hour2, min2);
7477 LOG(2,
"Number of longitudes: %d", met->
nx_glob);
7481 LOG(2,
"Number of latitudes: %d", met->
ny_glob);
7486 sprintf(levname,
"lev");
7487 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR)
7488 sprintf(levname,
"plev");
7489 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR)
7490 sprintf(levname,
"hybrid");
7494 sprintf(levname,
"lev_2");
7495 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR) {
7496 sprintf(levname,
"plev");
7497 NC(nc_inq_dimid(ncid, levname, &dimid2));
7499 NC(nc_inq_dimlen(ncid, dimid2, &np));
7504 LOG(2,
"Number of levels: %d", met->
np);
7506 ERRMSG(
"Number of levels out of range!");
7510 LOG(2,
"Longitudes: %g, %g ... %g deg",
7513 LOG(2,
"Latitudes: %g, %g ... %g deg",
7517 for (
int ix = 2; ix < met->
nx; ix++)
7519 (fabs(met->
lon[ix] - met->
lon[ix - 1]) -
7520 fabs(met->
lon[1] - met->
lon[0])) > 0.001)
7521 ERRMSG(
"No regular grid spacing in longitudes!");
7522 for (
int iy = 2; iy < met->
ny; iy++)
7524 (fabs(met->
lat[iy] - met->
lat[iy - 1]) -
7525 fabs(met->
lat[1] - met->
lat[0])) > 0.001) {
7526 WARN(
"No regular grid spacing in latitudes!");
7532 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
7533 MPI_Comm_size(MPI_COMM_WORLD, &size);
7555 met->
nx = met->
nx + gap;
7556 WARN(
"Extended subdomains at the right to fit to full domain.");
7562 met->
ny = met->
ny + gap;
7563 WARN(
"Extended subdomains at the bottom to fit to full domain.");
7574 if (!left && !right) {
7591 if (!top && !bottom) {
7609 double lon_shift = 0;
7610 if (left || right) {
7628 lon_shift = (left ? -360 : 360);
7633 double lon_range = met->
lon[met->
nx_glob - 1] - met->
lon[0];
7634 double lat_range = met->
lat[met->
ny_glob - 1] - met->
lat[0];
7639 met->
lat[iy] = met->
lat[iy_];
7643 double help_lon[
EX];
7658 for (
int ix = 0; ix < (int) met->
nx; ix++)
7659 met->
lon[ix] = help_lon[ix];
7671 LOG(2,
" %d Subdomain longitudes: %g, %g ... %g deg", rank,
7673 LOG(2,
" %d Subdomain latitudes: %g, %g ... %g deg", rank,
7676 LOG(2,
"Define subdomain properties.");
7677 LOG(2,
"MPI information: Rank %d, Size %d", rank, size);
7678 LOG(2,
"Edge position: l=%d,r=%d,t=%d, b=%d", (
int) left, (
int) right,
7679 (
int) top, (
int) bottom);
7680 LOG(2,
"Sizes for limits: EX %d EY %d EP %d",
EX,
EY,
EP);
7681 LOG(2,
"Total size for subdomain meteo data: nx %d ny %d np %d", met->
nx,
7683 LOG(2,
"Hyperslab sizes for boundary halos: nx %d ny %d np %d",
7686 LOG(2,
"Hyperslab sizes for subdomain and inner halos: nx %d ny %d np %d",
7699 for (
int ip = 0; ip < met->
np; ip++)
7701 LOG(2,
"Altitude levels: %g, %g ... %g km",
7702 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
7703 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
7704 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
7708 if (strcasecmp(levname,
"hybrid") == 0)
7722 LOG(2,
"Read surface data...");
7726 (ncid,
"lnsp",
"LNSP", NULL, NULL, NULL, NULL, ctl, met, met->
ps, 1.0f,
7728 for (
int ix = 0; ix < met->
nx; ix++)
7729 for (
int iy = 0; iy < met->
ny; iy++)
7730 met->
ps[ix][iy] = (
float) (exp(met->
ps[ix][iy]) / 100.);
7733 (ncid,
"ps",
"PS",
"sp",
"SP", NULL, NULL, ctl, met, met->
ps, 0.01f,
7735 WARN(
"Cannot not read surface pressure data (use lowest level)!");
7736 for (
int ix = 0; ix < met->
nx; ix++)
7737 for (
int iy = 0; iy < met->
ny; iy++)
7739 = (ctl->
met_np > 0 ? (
float) ctl->
met_p[0] : (
float) met->
p[0]);
7747 (ncid,
"z",
"Z", NULL, NULL, NULL, NULL, ctl, met, met->
zs,
7748 (
float) (1. / (1000. *
G0)), 1))
7750 (ncid,
"zm",
"ZM", NULL, NULL, NULL, NULL, ctl, met, met->
zs,
7751 (
float) (1. / 1000.), 1))
7752 WARN(
"Cannot read surface geopotential height!");
7763 memcpy(help, met->
pl,
sizeof(met->
pl));
7765 (ncid,
"gph",
"GPH", NULL, NULL, ctl, met, met->
pl,
7766 (
float) (1e-3 /
G0)))
7767 ERRMSG(
"Cannot read geopotential height!");
7768 for (
int ix = 0; ix < met->
nx; ix++)
7769 for (
int iy = 0; iy < met->
ny; iy++)
7770 met->
zs[ix][iy] = met->
pl[ix][iy][0];
7771 memcpy(met->
pl, help,
sizeof(met->
pl));
7777 (ncid,
"t2m",
"T2M",
"2t",
"2T",
"t2",
"T2", ctl, met, met->
ts, 1.0, 1))
7778 WARN(
"Cannot read surface temperature!");
7782 (ncid,
"u10m",
"U10M",
"10u",
"10U",
"u10",
"U10", ctl, met, met->
us,
7784 WARN(
"Cannot read surface zonal wind!");
7788 (ncid,
"v10m",
"V10M",
"10v",
"10V",
"v10",
"V10", ctl, met, met->
vs,
7790 WARN(
"Cannot read surface meridional wind!");
7794 (ncid,
"iews",
"IEWS", NULL, NULL, NULL, NULL, ctl, met, met->
ess, 1.0,
7796 WARN(
"Cannot read eastward turbulent surface stress!");
7800 (ncid,
"inss",
"INSS", NULL, NULL, NULL, NULL, ctl, met, met->
nss, 1.0,
7802 WARN(
"Cannot read nothward turbulent surface stress!");
7806 (ncid,
"ishf",
"ISHF", NULL, NULL, NULL, NULL, ctl, met, met->
shf, 1.0,
7808 WARN(
"Cannot read surface sensible heat flux!");
7812 (ncid,
"lsm",
"LSM", NULL, NULL, NULL, NULL, ctl, met, met->
lsm, 1.0,
7814 WARN(
"Cannot read land-sea mask!");
7818 (ncid,
"sstk",
"SSTK",
"sst",
"SST", NULL, NULL, ctl, met, met->
sst,
7820 WARN(
"Cannot read sea surface temperature!");
7825 (ncid,
"blp",
"BLP", NULL, NULL, NULL, NULL, ctl, met, met->
pbl,
7827 WARN(
"Cannot read planetary boundary layer pressure!");
7830 (ncid,
"blh",
"BLH", NULL, NULL, NULL, NULL, ctl, met, met->
pbl,
7832 WARN(
"Cannot read planetary boundary layer height!");
7837 (ncid,
"cape",
"CAPE", NULL, NULL, NULL, NULL, ctl, met, met->
cape,
7839 WARN(
"Cannot read CAPE!");
7844 (ncid,
"cin",
"CIN", NULL, NULL, NULL, NULL, ctl, met, met->
cin,
7846 WARN(
"Cannot read convective inhibition!");
7859 SELECT_TIMER(
"READ_MET_NC_LEVELS_DD",
"INPUT", NVTX_READ);
7860 LOG(2,
"Read level data...");
7864 (ncid,
"t",
"T",
"temp",
"TEMP", ctl, met, met->
t, 1.0))
7865 ERRMSG(
"Cannot read temperature!");
7869 ERRMSG(
"Cannot read zonal wind!");
7871 ERRMSG(
"Cannot read meridional wind!");
7873 (ncid,
"w",
"W",
"omega",
"OMEGA", ctl, met, met->
w, 0.01f))
7874 WARN(
"Cannot read vertical velocity!");
7879 (ncid,
"q",
"Q",
"sh",
"SH", ctl, met, met->
h2o, (
float) (
MA /
MH2O)))
7880 WARN(
"Cannot read specific humidity!");
7883 (ncid,
"rh",
"RH", NULL, NULL, ctl, met, met->
h2o, 0.01f))
7884 WARN(
"Cannot read relative humidity!");
7885#pragma omp parallel for default(shared) collapse(2)
7886 for (
int ix = 0; ix < met->
nx; ix++)
7887 for (
int iy = 0; iy < met->
ny; iy++)
7888 for (
int ip = 0; ip < met->
np; ip++) {
7889 double pw = met->
h2o[ix][iy][ip] *
PSAT(met->
t[ix][iy][ip]);
7890 met->
h2o[ix][iy][ip] =
7891 (float) (pw / (met->
p[ip] - (1.0 -
EPS) * pw));
7897 (ncid,
"o3",
"O3", NULL, NULL, ctl, met, met->
o3, (
float) (
MA /
MO3)))
7898 WARN(
"Cannot read ozone data!");
7902 (ncid,
"clwc",
"CLWC", NULL, NULL, ctl, met, met->
lwc, 1.0))
7903 WARN(
"Cannot read cloud liquid water content!");
7905 (ncid,
"crwc",
"CRWC", NULL, NULL, ctl, met, met->
rwc, 1.0))
7906 WARN(
"Cannot read cloud rain water content!");
7908 (ncid,
"ciwc",
"CIWC", NULL, NULL, ctl, met, met->
iwc, 1.0))
7909 WARN(
"Cannot read cloud ice water content!");
7911 (ncid,
"cswc",
"CSWC", NULL, NULL, ctl, met, met->
swc, 1.0))
7912 WARN(
"Cannot read cloud snow water content!");
7914 (ncid,
"cc",
"CC", NULL, NULL, ctl, met, met->
cc, 1.0))
7915 WARN(
"Cannot read cloud cover!");
7919 (ncid,
"ZETA",
"zeta", NULL, NULL, ctl, met, met->
zetal, 1.0))
7920 WARN(
"Cannot read ZETA!");
7922 (ncid,
"ZETA_DOT_TOT",
"ZETA_DOT_clr",
"zeta_dot_clr",
7923 NULL, ctl, met, met->
zeta_dotl, 0.00001157407f))
7924 WARN(
"Cannot read ZETA_DOT!");
7928#pragma omp parallel for default(shared)
7929 for (
int ix = 0; ix < met->
nx; ix++)
7930 for (
int iy = 0; iy < met->
ny; iy++)
7931 for (
int ip = 0; ip < met->
np; ip++) {
7932 met->
ul[ix][iy][ip] = met->
u[ix][iy][ip];
7933 met->
vl[ix][iy][ip] = met->
v[ix][iy][ip];
7934 met->
wl[ix][iy][ip] = met->
w[ix][iy][ip];
7947 (ncid,
"pl",
"PL",
"pressure",
"PRESSURE", ctl, met, met->
pl,
7950 (ncid,
"press",
"PRESS", NULL, NULL, ctl, met, met->
pl, 1.0))
7951 ERRMSG(
"Cannot read pressure on model levels!");
7959 double hyam[
EP], hybm[
EP];
7973 ERRMSG(
"Mismatch in number of model levels!");
7976 for (
int ip = 0; ip < met->
np; ip++) {
7983 for (
int ix = 0; ix < met->
nx; ix++)
7984 for (
int iy = 0; iy < met->
ny; iy++)
7985 for (
int ip = 0; ip < met->
np; ip++)
7986 met->
pl[ix][iy][ip] =
7987 (
float) (hyam[ip] / 100. + hybm[ip] * met->
ps[ix][iy]);
7995 double hyam[
EP], hybm[
EP];
7998 for (
int ip = 0; ip < met->
np + 1; ip++) {
8005 ERRMSG(
"Mismatch in number of model levels!");
8008#pragma omp parallel for default(shared) collapse(2)
8009 for (
int ix = 0; ix < met->
nx; ix++)
8010 for (
int iy = 0; iy < met->
ny; iy++)
8011 for (
int ip = 0; ip < met->
np; ip++) {
8012 const double p0 = hyam[ip] / 100. + hybm[ip] * met->
ps[ix][iy];
8014 hyam[ip + 1] / 100. + hybm[ip + 1] * met->
ps[ix][iy];
8015 met->
pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
8020 for (
int ix = 0; ix < met->
nx; ix++)
8021 for (
int iy = 0; iy < met->
ny; iy++)
8022 for (
int ip = 1; ip < met->
np; ip++)
8023 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
8024 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
8025 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
8026 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip]))
8027 ERRMSG(
"Pressure profiles are not monotonic!");
8048 for (
int ip = 0; ip < met->
np; ip++)
8049 met->
p[ip] = ctl->
met_p[ip];
8053 for (
int ip = 1; ip < met->
np; ip++)
8054 if (met->
p[ip - 1] < met->
p[ip])
8055 ERRMSG(
"Pressure levels must be descending!");
8064 const char *filename,
8072 int nc_result = nc_open_par(filename, NC_NOWRITE | NC_SHARE, MPI_COMM_WORLD, MPI_INFO_NULL, &ncid);
8073 if (nc_result != NC_NOERR) {
8074 const char* error_msg;
8076 case NC_ENOPAR: error_msg =
"Library was not built with parallel I/O features";
break;
8077 case NC_EPERM: error_msg =
"No permission to access the file";
break;
8078 case NC_ENOTBUILT: error_msg =
"Library was not built with NETCDF4 or PnetCDF";
break;
8079 case NC_EINVAL: error_msg =
"Invalid parameters";
break;
8080 case NC_ENOTNC: error_msg =
"Not a netCDF file";
break;
8081 case NC_ENOMEM: error_msg =
"Out of memory";
break;
8082 case NC_EHDFERR: error_msg =
"HDF5 error";
break;
8083 case NC_EDIMMETA: error_msg =
"Error in netCDF-4 dimension metadata";
break;
8084 default: error_msg = nc_strerror(nc_result);
break;
8086 WARN(
"Cannot open file for parallel access! NetCDF error: %s (code: %d)", error_msg, nc_result);
8090 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
8091 WARN(
"Cannot open file!");
8119 const char *varname,
8120 const char *varname2,
8121 const char *varname3,
8122 const char *varname4,
8123 const char *varname5,
8124 const char *varname6,
8136 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
8137 sprintf(varsel,
"%s", varname);
8138 else if (varname2 != NULL
8139 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
8140 sprintf(varsel,
"%s", varname2);
8141 else if (varname3 != NULL
8142 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
8143 sprintf(varsel,
"%s", varname3);
8144 else if (varname4 != NULL
8145 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
8146 sprintf(varsel,
"%s", varname4);
8147 else if (varname5 != NULL
8148 && nc_inq_varid(ncid, varname5, &varid) == NC_NOERR)
8149 sprintf(varsel,
"%s", varname5);
8150 else if (varname6 != NULL
8151 && nc_inq_varid(ncid, varname6, &varid) == NC_NOERR)
8152 sprintf(varsel,
"%s", varname6);
8159 float fillval, missval;
8160 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8162 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8166 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
8167 varsel, fillval, missval);
8171 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
8172 MPI_Comm_size(MPI_COMM_WORLD, &size);
8176 size_t help_subdomain_start[3];
8177 size_t help_subdomain_count[3];
8179 help_subdomain_start[0] = 0;
8183 help_subdomain_count[0] = 1;
8192 NC(nc_get_vara_float
8193 (ncid, varid, help_subdomain_start, help_subdomain_count, help));
8196 size_t help_halo_bnd_start[3];
8197 size_t help_halo_bnd_count[3];
8199 help_halo_bnd_start[0] = 0;
8203 help_halo_bnd_count[0] = 1;
8208 ALLOC(help_halo,
float,
8209 help_halo_bnd_count[1] * help_halo_bnd_count[2]);
8210 NC(nc_get_vara_float
8211 (ncid, varid, help_halo_bnd_start, help_halo_bnd_count, help_halo));
8217#pragma omp parallel for default(shared) num_threads(12)
8218 for (
int ix = 0; ix < (int) help_subdomain_count[2]; ix++)
8219 for (
int iy = 0; iy < (int) help_subdomain_count[1]; iy++) {
8223 help[
ARRAY_2D(iy, ix, (
int) help_subdomain_count[2])];
8224 if ((fillval == 0 || aux != fillval)
8225 && (missval == 0 || aux != missval)
8226 && fabsf(aux) < 1e14f) {
8233#pragma omp parallel for default(shared) num_threads(12)
8234 for (
int ix = 0; ix < (int) help_halo_bnd_count[2]; ix++)
8235 for (
int iy = 0; iy < (int) help_halo_bnd_count[1]; iy++) {
8239 help_halo[
ARRAY_2D(iy, ix, (
int) help_halo_bnd_count[2])];
8240 if ((fillval == 0 || aux != fillval)
8241 && (missval == 0 || aux != missval)
8242 && fabsf(aux) < 1e14f)
8252#pragma omp parallel for default(shared) num_threads(12)
8253 for (
int iy = 0; iy < met->
ny; iy++)
8254 for (
int ix = 0; ix < met->
nx; ix++) {
8257 const float aux = help[
ARRAY_2D(ix, iy, met->
ny)];
8258 if ((fillval == 0 || aux != fillval)
8259 && (missval == 0 || aux != missval)
8260 && fabsf(aux) < 1e14f)
8261 dest[ix][iy] += scl * aux;
8281 const char *varname,
8282 const char *varname2,
8283 const char *varname3,
8284 const char *varname4,
8297 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
8298 sprintf(varsel,
"%s", varname);
8299 else if (varname2 != NULL
8300 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
8301 sprintf(varsel,
"%s", varname2);
8302 else if (varname3 != NULL
8303 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
8304 sprintf(varsel,
"%s", varname3);
8305 else if (varname4 != NULL
8306 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
8307 sprintf(varsel,
"%s", varname4);
8312 float fillval, missval;
8313 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8315 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8319 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
8320 varsel, fillval, missval);
8322 SELECT_TIMER(
"READ_MET_NC_3D_DD_CP1",
"INPUT", NVTX_READ);
8326 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
8327 MPI_Comm_size(MPI_COMM_WORLD, &size);
8335 SELECT_TIMER(
"READ_MET_NC_3D_DD_CP2",
"INPUT", NVTX_READ);
8338 NC(nc_get_vara_float
8343 ALLOC(help_halo,
float,
8347 SELECT_TIMER(
"READ_MET_NC_3D_DD_CP3",
"INPUT", NVTX_READ);
8350 NC(nc_get_vara_float(ncid,
8356 SELECT_TIMER(
"READ_MET_NC_3D_DD_CP4",
"INPUT", NVTX_READ);
8361#pragma omp parallel for default(shared) num_threads(12)
8364 for (
int ip = 0; ip < met->
np; ip++) {
8368 if ((fillval == 0 || aux != fillval)
8369 && (missval == 0 || aux != missval)
8370 && fabsf(aux) < 1e14f)
8376#pragma omp parallel for default(shared) num_threads(12)
8379 for (
int ip = 0; ip < met->
np; ip++) {
8383 if ((fillval == 0 || aux != fillval)
8384 && (missval == 0 || aux != missval)
8385 && fabsf(aux) < 1e14f)
8394#pragma omp parallel for default(shared) num_threads(12)
8395 for (
int ip = 0; ip < met->
np; ip++)
8398 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
8399 if ((fillval == 0 || aux != fillval)
8400 && (missval == 0 || aux != missval)
8401 && fabsf(aux) < 1e14f)
8407#pragma omp parallel for default(shared) num_threads(12)
8408 for (
int ip = 0; ip < met->
np; ip++)
8411 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
8412 if ((fillval == 0 || aux != fillval)
8413 && (missval == 0 || aux != missval)
8414 && fabsf(aux) < 1e14f)
8434 const char *filename,
8439 size_t filename_len = strlen(filename) + 1;
8440 char sf_filename[filename_len];
8441 char ml_filename[filename_len];
8442 strcpy(sf_filename, filename);
8443 strcpy(ml_filename, filename);
8448 FILE *ml_file = fopen(ml_filename,
"rb");
8449 FILE *sf_file = fopen(sf_filename,
"rb");
8450 if (ml_file == NULL || sf_file == NULL) {
8451 if (ml_file != NULL) {
8453 WARN(
"Cannot open file: %s", sf_filename);
8455 if (sf_file != NULL) {
8457 WARN(
"Cannot open file: %s", ml_filename);
8463 int ml_num_messages = 0, err = 0;
8464 ECC(codes_count_in_file(0, ml_file, &ml_num_messages));
8465 codes_handle **ml_handles =
8466 (codes_handle **) malloc(
sizeof(codes_handle *) *
8467 (size_t) ml_num_messages);
8468 for (
int i = 0; i < ml_num_messages; i++) {
8469 codes_handle *h = NULL;
8470 if ((h = codes_grib_handle_new_from_file(0, ml_file, &err)) != NULL)
8475 int sf_num_messages = 0;
8476 ECC(codes_count_in_file(0, sf_file, &sf_num_messages));
8477 codes_handle **sf_handles =
8478 (codes_handle **) malloc(
sizeof(codes_handle *) *
8479 (size_t) sf_num_messages);
8480 for (
int i = 0; i < sf_num_messages; i++) {
8481 codes_handle *h = NULL;
8482 if ((h = codes_grib_handle_new_from_file(0, sf_file, &err)) != NULL)
8491 read_met_grib_grid(ml_handles, ml_num_messages, met);
8494 read_met_grib_surface(sf_handles, sf_num_messages, ctl, met);
8495 for (
int i = 0; i < sf_num_messages; i++)
8496 codes_handle_delete(sf_handles[i]);
8500 size_t value_count = 0;
8501 ECC(codes_get_size(ml_handles[0],
"pv", &value_count));
8502 if (value_count % 2 != 0)
8503 ERRMSG(
"Unexpected pv array length!");
8504 size_t nlevels = value_count / 2 - 1;
8506 ALLOC(values,
double,
8508 ECC(codes_get_double_array(ml_handles[0],
"pv", values, &value_count));
8509 double *a_vals = values;
8510 double *b_vals = values + nlevels;
8511 if (met->
npl > (
int) nlevels)
8512 ERRMSG(
"met->npl exceeds number of pressure levels in GRIB!");
8513 for (
int nx = 0; nx < met->
nx; nx++)
8514 for (
int ny = 0; ny < met->
ny; ny++)
8515 for (
int level = 0; level <= met->
npl; level++) {
8516 const float p1 = (float) (a_vals[level] * 0.01f +
8517 met->
ps[nx][ny] * b_vals[level]);
8518 const float p2 = (float) (a_vals[level + 1] * 0.01f +
8519 met->
ps[nx][ny] * b_vals[level + 1]);
8520 met->
pl[nx][ny][level] = 0.5f * (p1 + p2);
8525 read_met_grib_levels(ml_handles, ml_num_messages, ctl, met);
8526 for (
int i = 0; i < ml_num_messages; i++)
8527 codes_handle_delete(ml_handles[i]);
8538void read_met_grib_grid(
8539 codes_handle **handles,
8544 SELECT_TIMER(
"READ_MET_GRIB_GRID",
"INPUT", NVTX_READ);
8545 LOG(2,
"Read meteo grid information...");
8548 char datestr[
LEN], timestr[
LEN];
8549 size_t s_date =
sizeof(datestr);
8550 ECC(codes_get_string(handles[0],
"dataDate", datestr, &s_date));
8551 size_t s_time =
sizeof(timestr);
8552 ECC(codes_get_string(handles[0],
"dataTime", timestr, &s_time));
8553 int year, month, day, hour;
8554 if (sscanf(datestr,
"%4d%2d%2d", &year, &month, &day) != 3)
8555 ERRMSG(
"Failed to parse dataDate: %s", datestr);
8556 if (sscanf(timestr,
"%2d", &hour) != 1)
8557 ERRMSG(
"Failed to parse dataTime: %s", timestr);
8559 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)", met->
time, year, month,
8563 long count_lat = 0, count_lon = 0;
8564 ECC(codes_get_long(handles[0],
"Nj", &count_lat));
8565 ECC(codes_get_long(handles[0],
"Ni", &count_lon));
8566 met->
ny = (int) count_lat;
8567 met->
nx = (int) count_lon;
8570 LOG(2,
"Number of longitudes: %d", met->
nx);
8571 if (met->
nx < 2 || met->
nx >
EX)
8572 ERRMSG(
"Number of longitudes out of range!");
8573 LOG(2,
"Number of latitudes: %d", met->
ny);
8574 if (met->
ny < 2 || met->
ny >
EY)
8575 ERRMSG(
"Number of latitudes out of range!");
8577 double first_lon, last_lon, first_lat, last_lat, inc_lon, inc_lat;
8578 ECC(codes_get_double
8579 (handles[0],
"longitudeOfFirstGridPointInDegrees", &first_lon));
8580 ECC(codes_get_double
8581 (handles[0],
"latitudeOfFirstGridPointInDegrees", &first_lat));
8582 ECC(codes_get_double
8583 (handles[0],
"longitudeOfLastGridPointInDegrees", &last_lon));
8584 ECC(codes_get_double
8585 (handles[0],
"latitudeOfLastGridPointInDegrees", &last_lat));
8586 ECC(codes_get_double(handles[0],
"iDirectionIncrementInDegrees", &inc_lon));
8587 ECC(codes_get_double(handles[0],
"jDirectionIncrementInDegrees", &inc_lat));
8589 long jscanpos, iscanneg;
8590 ECC(codes_get_long(handles[0],
"iScansNegatively", &iscanneg));
8591 ECC(codes_get_long(handles[0],
"jScansPositively", &jscanpos));
8596 for (
double i = first_lon; i <= last_lon + 1e-6; i += inc_lon) {
8597 met->
lon[counter] = i;
8600 for (
double i = first_lon; i > last_lon - 1e-6; i -= inc_lon) {
8601 met->
lon[counter] = i;
8607 for (
double i = first_lat; i > last_lat - 1e-6; i -= inc_lat) {
8608 met->
lat[counter] = i;
8611 for (
double i = first_lat; i <= last_lat + 1e-6; i += inc_lat) {
8612 met->
lat[counter] = i;
8617 LOG(2,
"Longitudes: %g, %g ... %g deg",
8619 LOG(2,
"Latitudes: %g, %g ... %g deg",
8624 for (
int i = 0; i < count_handles; i++) {
8626 ECC(codes_get_long(handles[i],
"level", &level));
8627 if (level > max_level)
8628 max_level = (int) level;
8630 met->
npl = max_level;
8633 LOG(2,
"Number of levels: %d", met->
npl);
8635 ERRMSG(
"Number of levels out of range!");
8642void read_met_grib_levels(
8643 codes_handle **handles,
8644 const int num_messages,
8649 SELECT_TIMER(
"READ_MET_GRIB_LEVELS",
"INPUT", NVTX_READ);
8650 LOG(2,
"Read level data...");
8653 int t_flag = 0, u_flag = 0, v_flag = 0, w_flag = 0, o3_flag = 0, h2o_flag =
8654 0, lwc_flag = 0, rwc_flag = 0, iwc_flag = 0, swc_flag = 0, cc_flag = 0;
8657 for (
int i = 0; i < num_messages; i++) {
8659 size_t max_size =
LEN;
8660 char short_name[max_size];
8666 ECC(codes_get_long(handles[i],
"level", ¤t_level));
8670 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
8671 ECC(codes_get_size(handles[i],
"values", &value_count));
8672 ALLOC(values,
double,
8674 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
8682 ECC_READ_3D(
"w", current_level, met->
w, 0.01f, w_flag);
8700 if (t_flag != met->
npl)
8701 ERRMSG(
"Cannot read temperature!");
8702 if (u_flag != met->
npl)
8703 ERRMSG(
"Cannot read zonal wind!");
8704 if (v_flag != met->
npl)
8705 ERRMSG(
"Cannot read meridional wind!");
8706 if (w_flag != met->
npl)
8707 WARN(
"Cannot read vertical velocity!");
8708 if (h2o_flag != met->
npl)
8709 WARN(
"Cannot read specific humidity!");
8710 if (o3_flag != met->
npl)
8711 WARN(
"Cannot read ozone data!");
8712 if (lwc_flag != met->
npl)
8713 WARN(
"Cannot read cloud liquid water content!");
8714 if (rwc_flag != met->
npl)
8715 WARN(
"Cannot read cloud rain water content!");
8716 if (iwc_flag != met->
npl)
8717 WARN(
"Cannot read cloud ice water content!");
8718 if (swc_flag != met->
npl)
8719 WARN(
"Cannot read cloud snow water content!");
8720 if (cc_flag != met->
npl)
8721 WARN(
"Cannot read cloud cover!");
8724 for (
int ix = 0; ix < met->
nx; ix++)
8725 for (
int iy = 0; iy < met->
ny; iy++)
8726 for (
int ip = 1; ip < met->
np; ip++)
8727 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
8728 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
8729 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
8730 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip])) {
8731 LOG(1,
"%f %f %f %f", met->
pl[ix][iy][0], met->
pl[ix][iy][1],
8732 met->
pl[ix][iy][ip - 1], met->
pl[ix][iy][ip]);
8733 ERRMSG(
"Pressure profiles are not monotonic!");
8754 for (
int ip = 0; ip < met->
np; ip++)
8755 met->
p[ip] = ctl->
met_p[ip];
8759 for (
int ip = 1; ip < met->
np; ip++)
8760 if (met->
p[ip - 1] < met->
p[ip])
8761 ERRMSG(
"Pressure levels must be descending!");
8768void read_met_grib_surface(
8769 codes_handle **handles,
8770 const int num_messages,
8775 SELECT_TIMER(
"READ_MET_GRIB_SURFACE",
"INPUT", NVTX_READ);
8776 LOG(2,
"Read surface data...");
8779 int sp_flag = 0, z_flag = 0, t_flag = 0, u_flag = 0, v_flag = 0, lsm_flag =
8780 0, sst_flag = 0, cape_flag = 0, cin_flag = 0, pbl_flag = 0;
8783 for (
int i = 0; i < num_messages; i++) {
8785 size_t max_size =
LEN, value_count;
8787 char short_name[max_size];
8790 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
8791 ECC(codes_get_size(handles[i],
"values", &value_count));
8792 double *values = (
double *) malloc(value_count *
sizeof(
double));
8793 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
8831 WARN(
"Cannot read surface pressure data!");
8833 WARN(
"Cannot read surface geopotential height!");
8835 WARN(
"Cannot read surface temperature!");
8837 WARN(
"Cannot read surface zonal wind!");
8839 WARN(
"Cannot read surface meridional wind!");
8841 WARN(
"Cannot read land-sea mask!");
8843 WARN(
"Cannot read sea surface temperature!");
8846 WARN(
"Cannot read CAPE!");
8848 WARN(
"Cannot read convective inhibition!");
8850 if (ctl->
met_pbl == 0 && pbl_flag == 0)
8851 WARN(
"Cannot read planetary boundary layer!");
8861 const char *varname) {
8863 double aux[
EP], p[
EP];
8867 LOG(2,
"Interpolate meteo data to pressure levels: %s", varname);
8870#pragma omp parallel for default(shared) private(aux,p) collapse(2)
8871 for (
int ix = 0; ix < met->
nx; ix++)
8872 for (
int iy = 0; iy < met->
ny; iy++) {
8875 for (
int ip = 0; ip < met->
np; ip++)
8876 p[ip] = met->
pl[ix][iy][ip];
8879 for (
int ip = 0; ip < ctl->
met_np; ip++) {
8880 double pt = ctl->
met_p[ip];
8881 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
8883 else if ((pt > p[met->
np - 1] && p[1] > p[0])
8884 || (pt < p[met->
np - 1] && p[1] < p[0]))
8885 pt = p[met->
np - 1];
8887 aux[ip] =
LIN(p[ip2], var[ix][iy][ip2],
8888 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
8892 for (
int ip = 0; ip < ctl->
met_np; ip++)
8893 var[ix][iy][ip] = (
float) aux[ip];
8908 SELECT_TIMER(
"READ_MET_MONOTONIZE",
"METPROC", NVTX_READ);
8909 LOG(2,
"Make zeta profiles monotone...");
8912#pragma omp parallel for default(shared) collapse(2)
8913 for (
int i = 0; i < met->
nx; i++)
8914 for (
int j = 0; j < met->
ny; j++) {
8917 while (k < met->npl) {
8918 if ((met->
zetal[i][j][k - 1] >= met->
zetal[i][j][k])) {
8924 while ((met->
zetal[i][j][k - 1] >=
8925 met->
zetal[i][j][k + l]) & (k + l < met->npl));
8930 (float) (met->
zetal[i][j][k + l] - met->
zetal[i][j][k - 1])
8933 for (
int m = k; m < k + l; m++) {
8934 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
8935 met->
zetal[i][j][m] = s * d + met->
zetal[i][j][k - 1];
8947#pragma omp parallel for default(shared) collapse(2)
8948 for (
int i = 0; i < met->
nx; i++)
8949 for (
int j = 0; j < met->
ny; j++) {
8952 while (k < met->npl) {
8953 if ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k])) {
8960 while ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k + l]) & (k + l <
8965 float s = (float) (met->
pl[i][j][k + l] - met->
pl[i][j][k - 1])
8968 for (
int m = k; m < k + l; m++) {
8969 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
8970 met->
pl[i][j][m] = s * d + met->
pl[i][j][k - 1];
8985 const char *filename,
8992 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
8993 WARN(
"Cannot open file!");
9017 const char *varname,
9018 const char *varname2,
9019 const char *varname3,
9020 const char *varname4,
9021 const char *varname5,
9022 const char *varname6,
9031 float offset, scalfac;
9036 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
9037 sprintf(varsel,
"%s", varname);
9038 else if (varname2 != NULL
9039 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
9040 sprintf(varsel,
"%s", varname2);
9041 else if (varname3 != NULL
9042 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
9043 sprintf(varsel,
"%s", varname3);
9044 else if (varname4 != NULL
9045 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
9046 sprintf(varsel,
"%s", varname4);
9047 else if (varname5 != NULL
9048 && nc_inq_varid(ncid, varname5, &varid) == NC_NOERR)
9049 sprintf(varsel,
"%s", varname5);
9050 else if (varname6 != NULL
9051 && nc_inq_varid(ncid, varname6, &varid) == NC_NOERR)
9052 sprintf(varsel,
"%s", varname6);
9058 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
9059 && nc_get_att_float(ncid, varid,
"scale_factor",
9060 &scalfac) == NC_NOERR) {
9068 short fillval, missval;
9069 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9071 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9075 LOG(2,
"Read 2-D variable: %s"
9076 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
9077 varsel, fillval, missval, scalfac, offset);
9080 NC(nc_get_var_short(ncid, varid, help));
9084 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
9088#pragma omp parallel for default(shared)
9089 for (
int ix = 0; ix < met->
nx; ix++)
9090 for (
int iy = 0; iy < met->
ny; iy++) {
9093 const short aux = help[
ARRAY_2D(iy, ix, met->
nx)];
9094 if ((fillval == 0 || aux != fillval)
9095 && (missval == 0 || aux != missval)
9096 && fabsf(aux * scalfac + offset) < 1e14f)
9097 dest[ix][iy] += scl * (aux * scalfac + offset);
9116 float fillval, missval;
9117 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9119 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9123 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
9124 varsel, fillval, missval);
9127 NC(nc_get_var_float(ncid, varid, help));
9134#pragma omp parallel for default(shared)
9135 for (
int ix = 0; ix < met->
nx; ix++)
9136 for (
int iy = 0; iy < met->
ny; iy++) {
9139 const float aux = help[
ARRAY_2D(iy, ix, met->
nx)];
9140 if ((fillval == 0 || aux != fillval)
9141 && (missval == 0 || aux != missval)
9142 && fabsf(aux) < 1e14f)
9143 dest[ix][iy] += scl * aux;
9153#pragma omp parallel for default(shared)
9154 for (
int iy = 0; iy < met->
ny; iy++)
9155 for (
int ix = 0; ix < met->
nx; ix++) {
9158 const float aux = help[
ARRAY_2D(ix, iy, met->
ny)];
9159 if ((fillval == 0 || aux != fillval)
9160 && (missval == 0 || aux != missval)
9161 && fabsf(aux) < 1e14f)
9162 dest[ix][iy] += scl * aux;
9181 const char *varname,
9182 const char *varname2,
9183 const char *varname3,
9184 const char *varname4,
9192 float offset, scalfac;
9197 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
9198 sprintf(varsel,
"%s", varname);
9199 else if (varname2 != NULL
9200 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
9201 sprintf(varsel,
"%s", varname2);
9202 else if (varname3 != NULL
9203 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
9204 sprintf(varsel,
"%s", varname3);
9205 else if (varname4 != NULL
9206 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
9207 sprintf(varsel,
"%s", varname4);
9213 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
9214 && nc_get_att_float(ncid, varid,
"scale_factor",
9215 &scalfac) == NC_NOERR) {
9223 short fillval, missval;
9224 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9226 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9230 LOG(2,
"Read 3-D variable: %s "
9231 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
9232 varsel, fillval, missval, scalfac, offset);
9235 NC(nc_get_var_short(ncid, varid, help));
9239 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
9243#pragma omp parallel for default(shared)
9244 for (
int ix = 0; ix < met->
nx; ix++)
9245 for (
int iy = 0; iy < met->
ny; iy++)
9246 for (
int ip = 0; ip < met->
np; ip++) {
9247 const short aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
9248 if ((fillval == 0 || aux != fillval)
9249 && (missval == 0 || aux != missval)
9250 && fabsf(aux * scalfac + offset) < 1e14f)
9251 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
9253 dest[ix][iy][ip] = NAN;
9270 float fillval, missval;
9271 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9273 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9277 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
9278 varsel, fillval, missval);
9281 NC(nc_get_var_float(ncid, varid, help));
9288#pragma omp parallel for default(shared)
9289 for (
int ix = 0; ix < met->
nx; ix++)
9290 for (
int iy = 0; iy < met->
ny; iy++)
9291 for (
int ip = 0; ip < met->
np; ip++) {
9292 const float aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
9293 if ((fillval == 0 || aux != fillval)
9294 && (missval == 0 || aux != missval)
9295 && fabsf(aux) < 1e14f)
9296 dest[ix][iy][ip] = scl * aux;
9298 dest[ix][iy][ip] = NAN;
9306#pragma omp parallel for default(shared)
9307 for (
int ip = 0; ip < met->
np; ip++)
9308 for (
int iy = 0; iy < met->
ny; iy++)
9309 for (
int ix = 0; ix < met->
nx; ix++) {
9310 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9311 if ((fillval == 0 || aux != fillval)
9312 && (missval == 0 || aux != missval)
9313 && fabsf(aux) < 1e14f)
9314 dest[ix][iy][ip] = scl * aux;
9316 dest[ix][iy][ip] = NAN;
9332 const char *filename,
9337 char levname[
LEN], tstr[10];
9339 double rtime = 0, r, r2;
9341 int varid, ndims, dimids[NC_MAX_DIMS], year2, mon2, day2, hour2, min2, sec2,
9342 year, mon, day, hour, min, sec;
9348 LOG(2,
"Read meteo grid information...");
9357 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
9358 if (nc_inq_varid(ncid,
"time", &varid) == NC_NOERR) {
9359 NC(nc_get_var_double(ncid, varid, &rtime));
9360 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
9361 WARN(
"Time information in meteo file does not match filename!");
9363 WARN(
"Time information in meteo file is missing!");
9374 sprintf(tstr,
"19%.2s", &filename[strlen(filename) - 11]);
9376 sprintf(tstr,
"20%.2s", &filename[strlen(filename) - 11]);
9378 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 9]);
9380 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 7]);
9382 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 5]);
9388 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
9389 || day < 1 || day > 31 || hour < 0 || hour > 23)
9390 ERRMSG(
"Cannot read time from filename!");
9391 jsec2time(met->
time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
9392 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
9393 met->
time, year2, mon2, day2, hour2, min2);
9397 LOG(2,
"Number of longitudes: %d", met->
nx);
9400 LOG(2,
"Number of latitudes: %d", met->
ny);
9404 LOG(2,
"Longitudes: %g, %g ... %g deg",
9407 LOG(2,
"Latitudes: %g, %g ... %g deg",
9411 for (
int ix = 2; ix < met->
nx; ix++)
9413 (fabs(met->
lon[ix] - met->
lon[ix - 1]) -
9414 fabs(met->
lon[1] - met->
lon[0])) > 0.001)
9415 ERRMSG(
"No regular grid spacing in longitudes!");
9416 for (
int iy = 2; iy < met->
ny; iy++)
9418 (fabs(met->
lat[iy] - met->
lat[iy - 1]) -
9419 fabs(met->
lat[1] - met->
lat[0])) > 0.001) {
9420 WARN(
"No regular grid spacing in latitudes!");
9425 if (nc_inq_varid(ncid,
"u", &varid) != NC_NOERR)
9426 if (nc_inq_varid(ncid,
"U", &varid) != NC_NOERR)
9428 (
"Variable 'u' or 'U' not found, cannot determine vertical dimension!");
9430 NC(nc_inq_varndims(ncid, varid, &ndims));
9431 NC(nc_inq_vardimid(ncid, varid, dimids));
9435 (ncid, dimids[ctl->
met_convention == 0 ? 1 : 3], levname, &dimlen));
9436 }
else if (ndims == 3) {
9438 (ncid, dimids[ctl->
met_convention == 0 ? 0 : 2], levname, &dimlen));
9440 ERRMSG(
"Cannot determine vertical dimension!")
9441 met->
np = (int) dimlen;
9443 LOG(2,
"Number of levels: %d", met->
np);
9444 if (met->
np < 2 || met->
np >
EP)
9445 ERRMSG(
"Number of levels out of range!");
9450 for (
int ip = 0; ip < met->
np; ip++)
9452 LOG(2,
"Altitude levels: %g, %g ... %g km",
9453 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
9454 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
9455 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
9459 if (strcasecmp(levname,
"hybrid") == 0)
9471 SELECT_TIMER(
"READ_MET_NC_LEVELS",
"INPUT", NVTX_READ);
9472 LOG(2,
"Read level data...");
9475 if (!
read_met_nc_3d(ncid,
"t",
"T",
"temp",
"TEMP", ctl, met, met->
t, 1.0))
9476 ERRMSG(
"Cannot read temperature!");
9479 if (!
read_met_nc_3d(ncid,
"u",
"U", NULL, NULL, ctl, met, met->
u, 1.0))
9480 ERRMSG(
"Cannot read zonal wind!");
9481 if (!
read_met_nc_3d(ncid,
"v",
"V", NULL, NULL, ctl, met, met->
v, 1.0))
9482 ERRMSG(
"Cannot read meridional wind!");
9484 (ncid,
"w",
"W",
"omega",
"OMEGA", ctl, met, met->
w, 0.01f))
9485 WARN(
"Cannot read vertical velocity!");
9490 (ncid,
"q",
"Q",
"sh",
"SH", ctl, met, met->
h2o, (
float) (
MA /
MH2O)))
9491 WARN(
"Cannot read specific humidity!");
9494 (ncid,
"rh",
"RH", NULL, NULL, ctl, met, met->
h2o, 0.01f))
9495 WARN(
"Cannot read relative humidity!");
9496#pragma omp parallel for default(shared) collapse(2)
9497 for (
int ix = 0; ix < met->
nx; ix++)
9498 for (
int iy = 0; iy < met->
ny; iy++)
9499 for (
int ip = 0; ip < met->
np; ip++) {
9500 double pw = met->
h2o[ix][iy][ip] *
PSAT(met->
t[ix][iy][ip]);
9501 met->
h2o[ix][iy][ip] =
9502 (float) (pw / (met->
p[ip] - (1.0 -
EPS) * pw));
9508 (ncid,
"o3",
"O3", NULL, NULL, ctl, met, met->
o3, (
float) (
MA /
MO3)))
9509 WARN(
"Cannot read ozone data!");
9513 (ncid,
"clwc",
"CLWC", NULL, NULL, ctl, met, met->
lwc, 1.0))
9514 WARN(
"Cannot read cloud liquid water content!");
9516 (ncid,
"crwc",
"CRWC", NULL, NULL, ctl, met, met->
rwc, 1.0))
9517 WARN(
"Cannot read cloud rain water content!");
9519 (ncid,
"ciwc",
"CIWC", NULL, NULL, ctl, met, met->
iwc, 1.0))
9520 WARN(
"Cannot read cloud ice water content!");
9522 (ncid,
"cswc",
"CSWC", NULL, NULL, ctl, met, met->
swc, 1.0))
9523 WARN(
"Cannot read cloud snow water content!");
9525 WARN(
"Cannot read cloud cover!");
9529 (ncid,
"ZETA",
"zeta", NULL, NULL, ctl, met, met->
zetal, 1.0))
9530 WARN(
"Cannot read ZETA!");
9532 (ncid,
"ZETA_DOT_TOT",
"ZETA_DOT_clr",
"zeta_dot_clr",
9533 NULL, ctl, met, met->
zeta_dotl, 0.00001157407f))
9534 WARN(
"Cannot read ZETA_DOT!");
9538 for (
int ix = 0; ix < met->
nx; ix++)
9539 for (
int iy = 0; iy < met->
ny; iy++)
9540 for (
int ip = 0; ip < met->
np; ip++) {
9541 met->
ul[ix][iy][ip] = met->
u[ix][iy][ip];
9542 met->
vl[ix][iy][ip] = met->
v[ix][iy][ip];
9543 met->
wl[ix][iy][ip] = met->
w[ix][iy][ip];
9556 (ncid,
"pl",
"PL",
"pressure",
"PRESSURE", ctl, met, met->
pl,
9559 (ncid,
"press",
"PRESS", NULL, NULL, ctl, met, met->
pl, 1.0))
9560 ERRMSG(
"Cannot read pressure on model levels!");
9567 double hyam[
EP], hybm[
EP];
9572 if (nc_inq_varid(ncid,
"hyam", &varid) == NC_NOERR
9573 && nc_inq_varid(ncid,
"hybm", &varid) == NC_NOERR) {
9576 }
else if (nc_inq_varid(ncid,
"a_hybrid_level", &varid) == NC_NOERR
9577 && nc_inq_varid(ncid,
"b_hybrid_level",
9578 &varid) == NC_NOERR) {
9582 ERRMSG(
"Cannot read a and b level coefficients from netCDF file!");
9590 ERRMSG(
"Mismatch in number of model levels!");
9593 for (
int ip = 0; ip < met->
np; ip++) {
9600 for (
int ix = 0; ix < met->
nx; ix++)
9601 for (
int iy = 0; iy < met->
ny; iy++)
9602 for (
int ip = 0; ip < met->
np; ip++)
9603 met->
pl[ix][iy][ip] =
9604 (
float) (hyam[ip] / 100. + hybm[ip] * met->
ps[ix][iy]);
9611 double hyam[
EP], hybm[
EP];
9614 for (
int ip = 0; ip < met->
np + 1; ip++) {
9621 ERRMSG(
"Mismatch in number of model levels!");
9624#pragma omp parallel for default(shared) collapse(2)
9625 for (
int ix = 0; ix < met->
nx; ix++)
9626 for (
int iy = 0; iy < met->
ny; iy++)
9627 for (
int ip = 0; ip < met->
np; ip++) {
9628 double p0 = hyam[ip] / 100. + hybm[ip] * met->
ps[ix][iy];
9629 double p1 = hyam[ip + 1] / 100. + hybm[ip + 1] * met->
ps[ix][iy];
9630 met->
pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
9635 for (
int ix = 0; ix < met->
nx; ix++)
9636 for (
int iy = 0; iy < met->
ny; iy++)
9637 for (
int ip = 1; ip < met->
np; ip++)
9638 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
9639 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
9640 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
9641 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip]))
9642 ERRMSG(
"Pressure profiles are not monotonic!");
9649 if (met->
pl[0][0][0] <= 0)
9650 ERRMSG(
"Pressure on model levels is missing, check MET_VERT_COORD!");
9667 for (
int ip = 0; ip < met->
np; ip++)
9668 met->
p[ip] = ctl->
met_p[ip];
9672 for (
int ip = 1; ip < met->
np; ip++)
9673 if (met->
p[ip - 1] < met->
p[ip])
9674 ERRMSG(
"Pressure levels must be descending!");
9685 SELECT_TIMER(
"READ_MET_NC_SURFACE",
"INPUT", NVTX_READ);
9686 LOG(2,
"Read surface data...");
9690 (ncid,
"lnsp",
"LNSP", NULL, NULL, NULL, NULL, ctl, met, met->
ps,
9692 for (
int ix = 0; ix < met->
nx; ix++)
9693 for (
int iy = 0; iy < met->
ny; iy++)
9694 met->
ps[ix][iy] = (
float) (exp(met->
ps[ix][iy]) / 100.);
9697 (ncid,
"ps",
"PS",
"sp",
"SP", NULL, NULL, ctl, met, met->
ps, 0.01f,
9699 WARN(
"Cannot not read surface pressure data (use lowest level)!");
9700 for (
int ix = 0; ix < met->
nx; ix++)
9701 for (
int iy = 0; iy < met->
ny; iy++)
9703 = (ctl->
met_np > 0 ? (
float) ctl->
met_p[0] : (
float) met->
p[0]);
9711 (ncid,
"z",
"Z", NULL, NULL, NULL, NULL, ctl, met, met->
zs,
9712 (
float) (1. / (1000. *
G0)), 1))
9714 (ncid,
"zm",
"ZM", NULL, NULL, NULL, NULL, ctl, met, met->
zs,
9715 (
float) (1. / 1000.), 1))
9716 WARN(
"Cannot read surface geopotential height!");
9727 memcpy(help, met->
pl,
sizeof(met->
pl));
9729 (ncid,
"gph",
"GPH", NULL, NULL, ctl, met, met->
pl,
9730 (
float) (1e-3 /
G0)))
9731 ERRMSG(
"Cannot read geopotential height!");
9732 for (
int ix = 0; ix < met->
nx; ix++)
9733 for (
int iy = 0; iy < met->
ny; iy++)
9734 met->
zs[ix][iy] = met->
pl[ix][iy][0];
9735 memcpy(met->
pl, help,
sizeof(met->
pl));
9741 (ncid,
"t2m",
"T2M",
"2t",
"2T",
"t2",
"T2", ctl, met, met->
ts, 1.0, 1))
9742 WARN(
"Cannot read surface temperature!");
9746 (ncid,
"u10m",
"U10M",
"10u",
"10U",
"u10",
"U10", ctl, met, met->
us,
9748 WARN(
"Cannot read surface zonal wind!");
9752 (ncid,
"v10m",
"V10M",
"10v",
"10V",
"v10",
"V10", ctl, met, met->
vs,
9754 WARN(
"Cannot read surface meridional wind!");
9758 (ncid,
"iews",
"IEWS", NULL, NULL, NULL, NULL, ctl, met, met->
ess,
9760 WARN(
"Cannot read eastward turbulent surface stress!");
9764 (ncid,
"inss",
"INSS", NULL, NULL, NULL, NULL, ctl, met, met->
nss,
9766 WARN(
"Cannot read nothward turbulent surface stress!");
9770 (ncid,
"ishf",
"ISHF", NULL, NULL, NULL, NULL, ctl, met, met->
shf,
9772 WARN(
"Cannot read surface sensible heat flux!");
9776 (ncid,
"lsm",
"LSM", NULL, NULL, NULL, NULL, ctl, met, met->
lsm, 1.0,
9778 WARN(
"Cannot read land-sea mask!");
9782 (ncid,
"sstk",
"SSTK",
"sst",
"SST", NULL, NULL, ctl, met, met->
sst,
9784 WARN(
"Cannot read sea surface temperature!");
9789 (ncid,
"blp",
"BLP", NULL, NULL, NULL, NULL, ctl, met, met->
pbl,
9791 WARN(
"Cannot read planetary boundary layer pressure!");
9794 (ncid,
"blh",
"BLH", NULL, NULL, NULL, NULL, ctl, met, met->
pbl,
9796 WARN(
"Cannot read planetary boundary layer height!");
9801 (ncid,
"cape",
"CAPE", NULL, NULL, NULL, NULL, ctl, met, met->
cape,
9803 WARN(
"Cannot read CAPE!");
9808 (ncid,
"cin",
"CIN", NULL, NULL, NULL, NULL, ctl, met, met->
cin,
9810 WARN(
"Cannot read convective inhibition!");
9821 LOG(2,
"Calculate planetary boundary layer...");
9827#pragma omp parallel for default(shared) collapse(2)
9828 for (
int ix = 0; ix < met->
nx; ix++)
9829 for (
int iy = 0; iy < met->
ny; iy++) {
9832 const float z = met->
zs[ix][iy] + met->
pbl[ix][iy];
9835 (float) (
LIN(met->
z[ix][iy][ip], met->
p[ip],
9836 met->
z[ix][iy][ip + 1], met->
p[ip + 1], z));
9845 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
9848#pragma omp parallel for default(shared) collapse(2)
9849 for (
int ix = 0; ix < met->
nx; ix++)
9850 for (
int iy = 0; iy < met->
ny; iy++) {
9853 const double pbl_bot = met->
ps[ix][iy] * exp(-dz /
H0);
9857 for (ip = 1; ip < met->
np; ip++)
9858 if (met->
p[ip] < pbl_bot)
9862 const double h2os =
LIN(met->
p[ip - 1], met->
h2o[ix][iy][ip - 1],
9863 met->
p[ip], met->
h2o[ix][iy][ip], pbl_bot);
9864 const double tvs =
THETAVIRT(pbl_bot, met->
ts[ix][iy], h2os);
9870 for (; ip < met->
np; ip++) {
9873 double vh2 =
SQR(met->
u[ix][iy][ip] - met->
us[ix][iy])
9874 +
SQR(met->
v[ix][iy][ip] - met->
vs[ix][iy]);
9875 vh2 =
MAX(vh2,
SQR(umin));
9879 G0 * 1e3 * (met->
z[ix][iy][ip] - met->
zs[ix][iy]) / tvs
9881 met->
h2o[ix][iy][ip]) - tvs) / vh2;
9884 if (rib >= rib_crit) {
9885 met->
pbl[ix][iy] = (float) (
LIN(rib_old, met->
p[ip - 1],
9886 rib, met->
p[ip], rib_crit));
9887 if (met->
pbl[ix][iy] > pbl_bot)
9888 met->
pbl[ix][iy] = (float) pbl_bot;
9903 const double dtheta = 2.0, zmin = 0.1;
9906#pragma omp parallel for default(shared) collapse(2)
9907 for (
int ix = 0; ix < met->
nx; ix++)
9908 for (
int iy = 0; iy < met->
ny; iy++) {
9911 const double theta0 =
THETA(met->
ps[ix][iy], met->
ts[ix][iy]);
9915 for (ip = met->
np - 2; ip > 0; ip--)
9916 if (met->
p[ip] >= 300.)
9917 if (met->
p[ip] > met->
ps[ix][iy]
9918 ||
THETA(met->
p[ip], met->
t[ix][iy][ip]) <= theta0 + dtheta)
9923 = (float) (
LIN(
THETA(met->
p[ip + 1], met->
t[ix][iy][ip + 1]),
9925 THETA(met->
p[ip], met->
t[ix][iy][ip]),
9926 met->
p[ip], theta0 + dtheta));
9929 double pbl_min = met->
ps[ix][iy] * exp(-zmin /
H0);
9930 if (met->
pbl[ix][iy] > pbl_min || met->
p[ip] > met->
ps[ix][iy])
9931 met->
pbl[ix][iy] = (float) pbl_min;
9936#pragma omp parallel for default(shared) collapse(2)
9937 for (
int ix = 0; ix < met->
nx; ix++)
9938 for (
int iy = 0; iy < met->
ny; iy++) {
9942 met->
pbl[ix][iy] =
MIN(met->
pbl[ix][iy], (
float) pbl_min);
9946 met->
pbl[ix][iy] =
MAX(met->
pbl[ix][iy], (
float) pbl_max);
9956 SELECT_TIMER(
"READ_MET_PERIODIC",
"METPROC", NVTX_READ);
9957 LOG(2,
"Apply periodic boundary conditions...");
9960 if (!(fabs(met->
lon[met->
nx - 1] - met->
lon[0]
9961 + met->
lon[1] - met->
lon[0] - 360) < 0.01))
9965 if ((++met->
nx) >=
EX)
9966 ERRMSG(
"Cannot create periodic boundary conditions!");
9972#pragma omp parallel for default(shared)
9973 for (
int iy = 0; iy < met->
ny; iy++) {
9974 met->
ps[met->
nx - 1][iy] = met->
ps[0][iy];
9975 met->
zs[met->
nx - 1][iy] = met->
zs[0][iy];
9976 met->
ts[met->
nx - 1][iy] = met->
ts[0][iy];
9977 met->
us[met->
nx - 1][iy] = met->
us[0][iy];
9978 met->
vs[met->
nx - 1][iy] = met->
vs[0][iy];
9979 met->
ess[met->
nx - 1][iy] = met->
ess[0][iy];
9980 met->
nss[met->
nx - 1][iy] = met->
nss[0][iy];
9981 met->
shf[met->
nx - 1][iy] = met->
shf[0][iy];
9982 met->
lsm[met->
nx - 1][iy] = met->
lsm[0][iy];
9983 met->
sst[met->
nx - 1][iy] = met->
sst[0][iy];
9984 met->
pbl[met->
nx - 1][iy] = met->
pbl[0][iy];
9985 met->
cape[met->
nx - 1][iy] = met->
cape[0][iy];
9986 met->
cin[met->
nx - 1][iy] = met->
cin[0][iy];
9987 for (
int ip = 0; ip < met->
np; ip++) {
9988 met->
t[met->
nx - 1][iy][ip] = met->
t[0][iy][ip];
9989 met->
u[met->
nx - 1][iy][ip] = met->
u[0][iy][ip];
9990 met->
v[met->
nx - 1][iy][ip] = met->
v[0][iy][ip];
9991 met->
w[met->
nx - 1][iy][ip] = met->
w[0][iy][ip];
9992 met->
h2o[met->
nx - 1][iy][ip] = met->
h2o[0][iy][ip];
9993 met->
o3[met->
nx - 1][iy][ip] = met->
o3[0][iy][ip];
9994 met->
lwc[met->
nx - 1][iy][ip] = met->
lwc[0][iy][ip];
9995 met->
rwc[met->
nx - 1][iy][ip] = met->
rwc[0][iy][ip];
9996 met->
iwc[met->
nx - 1][iy][ip] = met->
iwc[0][iy][ip];
9997 met->
swc[met->
nx - 1][iy][ip] = met->
swc[0][iy][ip];
9998 met->
cc[met->
nx - 1][iy][ip] = met->
cc[0][iy][ip];
10000 for (
int ip = 0; ip < met->
npl; ip++) {
10001 met->
ul[met->
nx - 1][iy][ip] = met->
ul[0][iy][ip];
10002 met->
vl[met->
nx - 1][iy][ip] = met->
vl[0][iy][ip];
10003 met->
wl[met->
nx - 1][iy][ip] = met->
wl[0][iy][ip];
10004 met->
pl[met->
nx - 1][iy][ip] = met->
pl[0][iy][ip];
10005 met->
zetal[met->
nx - 1][iy][ip] = met->
zetal[0][iy][ip];
10017 SELECT_TIMER(
"READ_MET_POLAR_WINDS",
"METPROC", NVTX_READ);
10018 LOG(2,
"Apply fix for polar winds...");
10021 if (fabs(met->
lat[0]) < 89.999 || fabs(met->
lat[met->
ny - 1]) < 89.999)
10025 for (
int ihem = 0; ihem < 2; ihem++) {
10028 int i89 = 1, i90 = 0, sign = 1;
10033 if (met->
lat[i90] < 0)
10037 double clon[
EX], slon[
EX];
10038#pragma omp parallel for default(shared)
10039 for (
int ix = 0; ix < met->
nx; ix++) {
10040 clon[ix] = cos(sign *
DEG2RAD(met->
lon[ix]));
10041 slon[ix] = sin(sign *
DEG2RAD(met->
lon[ix]));
10045#pragma omp parallel for default(shared)
10046 for (
int ip = 0; ip < met->
np; ip++) {
10049 double vel89x = 0, vel89y = 0;
10050 for (
int ix = 0; ix < met->
nx; ix++) {
10052 (met->
u[ix][i89][ip] * clon[ix] -
10053 met->
v[ix][i89][ip] * slon[ix]) / met->
nx;
10055 (met->
u[ix][i89][ip] * slon[ix] +
10056 met->
v[ix][i89][ip] * clon[ix]) / met->
nx;
10060 for (
int ix = 0; ix < met->
nx; ix++) {
10061 met->
u[ix][i90][ip]
10062 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
10063 met->
v[ix][i90][ip]
10064 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
10079 LOG(2,
"Calculate potential vorticity...");
10082#pragma omp parallel for default(shared)
10083 for (
int ip = 0; ip < met->
np; ip++)
10084 pows[ip] = pow(1000. / met->
p[ip], 0.286);
10087#pragma omp parallel for default(shared)
10088 for (
int ix = 0; ix < met->
nx; ix++) {
10091 const int ix0 =
MAX(ix - 1, 0);
10092 const int ix1 =
MIN(ix + 1, met->
nx - 1);
10095 for (
int iy = 0; iy < met->
ny; iy++) {
10098 const int iy0 =
MAX(iy - 1, 0);
10099 const int iy1 =
MIN(iy + 1, met->
ny - 1);
10102 const double latr = 0.5 * (met->
lat[iy1] + met->
lat[iy0]);
10103 const double dx = 1000. *
DEG2DX(met->
lon[ix1] - met->
lon[ix0], latr);
10104 const double dy = 1000. *
DEG2DY(met->
lat[iy1] - met->
lat[iy0]);
10105 const double c0 = cos(
DEG2RAD(met->
lat[iy0]));
10106 const double c1 = cos(
DEG2RAD(met->
lat[iy1]));
10107 const double cr = cos(
DEG2RAD(latr));
10108 const double vort = 2 * 7.2921e-5 * sin(
DEG2RAD(latr));
10111 for (
int ip = 0; ip < met->
np; ip++) {
10115 = (met->
t[ix1][iy][ip] - met->
t[ix0][iy][ip]) * pows[ip] / dx;
10116 const double dvdx = (met->
v[ix1][iy][ip] - met->
v[ix0][iy][ip]) / dx;
10120 = (met->
t[ix][iy1][ip] - met->
t[ix][iy0][ip]) * pows[ip] / dy;
10122 = (met->
u[ix][iy1][ip] * c1 - met->
u[ix][iy0][ip] * c0) / dy;
10125 const int ip0 =
MAX(ip - 1, 0);
10126 const int ip1 =
MIN(ip + 1, met->
np - 1);
10129 double dtdp, dudp, dvdp;
10130 const double dp0 = 100. * (met->
p[ip] - met->
p[ip0]);
10131 const double dp1 = 100. * (met->
p[ip1] - met->
p[ip]);
10132 if (ip != ip0 && ip != ip1) {
10133 double denom = dp0 * dp1 * (dp0 + dp1);
10134 dtdp = (dp0 * dp0 * met->
t[ix][iy][ip1] * pows[ip1]
10135 - dp1 * dp1 * met->
t[ix][iy][ip0] * pows[ip0]
10136 + (dp1 * dp1 - dp0 * dp0) * met->
t[ix][iy][ip] * pows[ip])
10138 dudp = (dp0 * dp0 * met->
u[ix][iy][ip1]
10139 - dp1 * dp1 * met->
u[ix][iy][ip0]
10140 + (dp1 * dp1 - dp0 * dp0) * met->
u[ix][iy][ip])
10142 dvdp = (dp0 * dp0 * met->
v[ix][iy][ip1]
10143 - dp1 * dp1 * met->
v[ix][iy][ip0]
10144 + (dp1 * dp1 - dp0 * dp0) * met->
v[ix][iy][ip])
10147 const double denom = dp0 + dp1;
10149 (met->
t[ix][iy][ip1] * pows[ip1] -
10150 met->
t[ix][iy][ip0] * pows[ip0]) / denom;
10151 dudp = (met->
u[ix][iy][ip1] - met->
u[ix][iy][ip0]) / denom;
10152 dvdp = (met->
v[ix][iy][ip1] - met->
v[ix][iy][ip0]) / denom;
10156 met->
pv[ix][iy][ip] = (float)
10158 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
10164#pragma omp parallel for default(shared)
10165 for (
int ix = 0; ix < met->
nx; ix++)
10166 for (
int ip = 0; ip < met->
np; ip++) {
10168 = met->
pv[ix][1][ip]
10169 = met->
pv[ix][2][ip];
10170 met->
pv[ix][met->
ny - 1][ip]
10171 = met->
pv[ix][met->
ny - 2][ip]
10172 = met->
pv[ix][met->
ny - 3][ip];
10183 LOG(2,
"Calculate total column ozone...");
10186#pragma omp parallel for default(shared) collapse(2)
10187 for (
int ix = 0; ix < met->
nx; ix++)
10188 for (
int iy = 0; iy < met->
ny; iy++) {
10192 for (
int ip = 1; ip < met->
np; ip++)
10193 if (met->
p[ip - 1] <= met->
ps[ix][iy]) {
10195 0.5 * (met->
o3[ix][iy][ip - 1] + met->
o3[ix][iy][ip]);
10196 const double dp = met->
p[ip - 1] - met->
p[ip];
10197 cd += vmr *
MO3 /
MA * dp * 1e2 /
G0;
10201 met->
o3c[ix][iy] = (float) (cd / 2.1415e-5);
10219 SELECT_TIMER(
"READ_MET_SAMPLE",
"METPROC", NVTX_READ);
10220 LOG(2,
"Downsampling of meteo data...");
10226 help->
nx = met->
nx;
10227 help->
ny = met->
ny;
10228 help->
np = met->
np;
10229 memcpy(help->
lon, met->
lon,
sizeof(met->
lon));
10230 memcpy(help->
lat, met->
lat,
sizeof(met->
lat));
10231 memcpy(help->
p, met->
p,
sizeof(met->
p));
10234 for (
int ix = 0; ix < met->
nx; ix += ctl->
met_dx) {
10235 for (
int iy = 0; iy < met->
ny; iy += ctl->
met_dy) {
10236 for (
int ip = 0; ip < met->
np; ip += ctl->
met_dp) {
10237 help->
ps[ix][iy] = 0;
10238 help->
zs[ix][iy] = 0;
10239 help->
ts[ix][iy] = 0;
10240 help->
us[ix][iy] = 0;
10241 help->
vs[ix][iy] = 0;
10242 help->
ess[ix][iy] = 0;
10243 help->
nss[ix][iy] = 0;
10244 help->
shf[ix][iy] = 0;
10245 help->
lsm[ix][iy] = 0;
10246 help->
sst[ix][iy] = 0;
10247 help->
pbl[ix][iy] = 0;
10248 help->
cape[ix][iy] = 0;
10249 help->
cin[ix][iy] = 0;
10250 help->
t[ix][iy][ip] = 0;
10251 help->
u[ix][iy][ip] = 0;
10252 help->
v[ix][iy][ip] = 0;
10253 help->
w[ix][iy][ip] = 0;
10254 help->
h2o[ix][iy][ip] = 0;
10255 help->
o3[ix][iy][ip] = 0;
10256 help->
lwc[ix][iy][ip] = 0;
10257 help->
rwc[ix][iy][ip] = 0;
10258 help->
iwc[ix][iy][ip] = 0;
10259 help->
swc[ix][iy][ip] = 0;
10260 help->
cc[ix][iy][ip] = 0;
10262 for (
int ix2 = ix - ctl->
met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
10267 else if (ix3 >= met->
nx)
10270 for (
int iy2 =
MAX(iy - ctl->
met_sy + 1, 0);
10271 iy2 <=
MIN(iy + ctl->
met_sy - 1, met->
ny - 1); iy2++)
10272 for (
int ip2 =
MAX(ip - ctl->
met_sp + 1, 0);
10273 ip2 <=
MIN(ip + ctl->
met_sp - 1, met->
np - 1); ip2++) {
10275 (1.0f - (float) abs(ix - ix2) / (float) ctl->
met_sx)
10276 * (1.0f - (float) abs(iy - iy2) / (float) ctl->
met_sy)
10277 * (1.0f - (float) abs(ip - ip2) / (float) ctl->
met_sp);
10278 help->
ps[ix][iy] += w * met->
ps[ix3][iy2];
10279 help->
zs[ix][iy] += w * met->
zs[ix3][iy2];
10280 help->
ts[ix][iy] += w * met->
ts[ix3][iy2];
10281 help->
us[ix][iy] += w * met->
us[ix3][iy2];
10282 help->
vs[ix][iy] += w * met->
vs[ix3][iy2];
10283 help->
ess[ix][iy] += w * met->
ess[ix3][iy2];
10284 help->
nss[ix][iy] += w * met->
nss[ix3][iy2];
10285 help->
shf[ix][iy] += w * met->
shf[ix3][iy2];
10286 help->
lsm[ix][iy] += w * met->
lsm[ix3][iy2];
10287 help->
sst[ix][iy] += w * met->
sst[ix3][iy2];
10288 help->
pbl[ix][iy] += w * met->
pbl[ix3][iy2];
10289 help->
cape[ix][iy] += w * met->
cape[ix3][iy2];
10290 help->
cin[ix][iy] += w * met->
cin[ix3][iy2];
10291 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip2];
10292 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip2];
10293 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip2];
10294 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip2];
10295 help->
h2o[ix][iy][ip] += w * met->
h2o[ix3][iy2][ip2];
10296 help->
o3[ix][iy][ip] += w * met->
o3[ix3][iy2][ip2];
10297 help->
lwc[ix][iy][ip] += w * met->
lwc[ix3][iy2][ip2];
10298 help->
rwc[ix][iy][ip] += w * met->
rwc[ix3][iy2][ip2];
10299 help->
iwc[ix][iy][ip] += w * met->
iwc[ix3][iy2][ip2];
10300 help->
swc[ix][iy][ip] += w * met->
swc[ix3][iy2][ip2];
10301 help->
cc[ix][iy][ip] += w * met->
cc[ix3][iy2][ip2];
10305 help->
ps[ix][iy] /= wsum;
10306 help->
zs[ix][iy] /= wsum;
10307 help->
ts[ix][iy] /= wsum;
10308 help->
us[ix][iy] /= wsum;
10309 help->
vs[ix][iy] /= wsum;
10310 help->
ess[ix][iy] /= wsum;
10311 help->
nss[ix][iy] /= wsum;
10312 help->
shf[ix][iy] /= wsum;
10313 help->
lsm[ix][iy] /= wsum;
10314 help->
sst[ix][iy] /= wsum;
10315 help->
pbl[ix][iy] /= wsum;
10316 help->
cape[ix][iy] /= wsum;
10317 help->
cin[ix][iy] /= wsum;
10318 help->
t[ix][iy][ip] /= wsum;
10319 help->
u[ix][iy][ip] /= wsum;
10320 help->
v[ix][iy][ip] /= wsum;
10321 help->
w[ix][iy][ip] /= wsum;
10322 help->
h2o[ix][iy][ip] /= wsum;
10323 help->
o3[ix][iy][ip] /= wsum;
10324 help->
lwc[ix][iy][ip] /= wsum;
10325 help->
rwc[ix][iy][ip] /= wsum;
10326 help->
iwc[ix][iy][ip] /= wsum;
10327 help->
swc[ix][iy][ip] /= wsum;
10328 help->
cc[ix][iy][ip] /= wsum;
10335 for (
int ix = 0; ix < help->
nx; ix += ctl->
met_dx) {
10336 met->
lon[met->
nx] = help->
lon[ix];
10338 for (
int iy = 0; iy < help->
ny; iy += ctl->
met_dy) {
10339 met->
lat[met->
ny] = help->
lat[iy];
10340 met->
ps[met->
nx][met->
ny] = help->
ps[ix][iy];
10341 met->
zs[met->
nx][met->
ny] = help->
zs[ix][iy];
10342 met->
ts[met->
nx][met->
ny] = help->
ts[ix][iy];
10343 met->
us[met->
nx][met->
ny] = help->
us[ix][iy];
10344 met->
vs[met->
nx][met->
ny] = help->
vs[ix][iy];
10345 met->
ess[met->
nx][met->
ny] = help->
ess[ix][iy];
10346 met->
nss[met->
nx][met->
ny] = help->
nss[ix][iy];
10347 met->
shf[met->
nx][met->
ny] = help->
shf[ix][iy];
10348 met->
lsm[met->
nx][met->
ny] = help->
lsm[ix][iy];
10349 met->
sst[met->
nx][met->
ny] = help->
sst[ix][iy];
10350 met->
pbl[met->
nx][met->
ny] = help->
pbl[ix][iy];
10352 met->
cin[met->
nx][met->
ny] = help->
cin[ix][iy];
10354 for (
int ip = 0; ip < help->
np; ip += ctl->
met_dp) {
10355 met->
p[met->
np] = help->
p[ip];
10356 met->
t[met->
nx][met->
ny][met->
np] = help->
t[ix][iy][ip];
10357 met->
u[met->
nx][met->
ny][met->
np] = help->
u[ix][iy][ip];
10358 met->
v[met->
nx][met->
ny][met->
np] = help->
v[ix][iy][ip];
10359 met->
w[met->
nx][met->
ny][met->
np] = help->
w[ix][iy][ip];
10360 met->
h2o[met->
nx][met->
ny][met->
np] = help->
h2o[ix][iy][ip];
10361 met->
o3[met->
nx][met->
ny][met->
np] = help->
o3[ix][iy][ip];
10362 met->
lwc[met->
nx][met->
ny][met->
np] = help->
lwc[ix][iy][ip];
10363 met->
rwc[met->
nx][met->
ny][met->
np] = help->
rwc[ix][iy][ip];
10364 met->
iwc[met->
nx][met->
ny][met->
np] = help->
iwc[ix][iy][ip];
10365 met->
swc[met->
nx][met->
ny][met->
np] = help->
swc[ix][iy][ip];
10366 met->
cc[met->
nx][met->
ny][met->
np] = help->
cc[ix][iy][ip];
10385 double p2[200], pv[
EP], pv2[200], t[
EP], t2[200], th[
EP],
10386 th2[200], z[
EP], z2[200];
10390 LOG(2,
"Calculate tropopause...");
10393#pragma omp parallel for default(shared)
10394 for (
int iz = 0; iz < met->
np; iz++)
10395 z[iz] =
Z(met->
p[iz]);
10396#pragma omp parallel for default(shared)
10397 for (
int iz = 0; iz <= 190; iz++) {
10398 z2[iz] = 4.5 + 0.1 * iz;
10399 p2[iz] =
P(z2[iz]);
10404#pragma omp parallel for default(shared) collapse(2)
10405 for (
int ix = 0; ix < met->
nx; ix++)
10406 for (
int iy = 0; iy < met->
ny; iy++)
10407 met->
pt[ix][iy] = NAN;
10411#pragma omp parallel for default(shared) collapse(2)
10412 for (
int ix = 0; ix < met->
nx; ix++)
10413 for (
int iy = 0; iy < met->
ny; iy++)
10421#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10422 for (
int ix = 0; ix < met->
nx; ix++)
10423 for (
int iy = 0; iy < met->
ny; iy++) {
10426 for (
int iz = 0; iz < met->
np; iz++)
10427 t[iz] = met->
t[ix][iy][iz];
10431 int iz = (int) gsl_stats_min_index(t2, 1, 171);
10432 if (iz > 0 && iz < 170)
10433 met->
pt[ix][iy] = (float) p2[iz];
10435 met->
pt[ix][iy] = NAN;
10443#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10444 for (
int ix = 0; ix < met->
nx; ix++)
10445 for (
int iy = 0; iy < met->
ny; iy++) {
10449 for (iz = 0; iz < met->
np; iz++)
10450 t[iz] = met->
t[ix][iy][iz];
10454 met->
pt[ix][iy] = NAN;
10455 for (iz = 0; iz <= 170; iz++) {
10457 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10458 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10463 if (iz > 0 && iz < 170)
10464 met->
pt[ix][iy] = (float) p2[iz];
10471 met->
pt[ix][iy] = NAN;
10472 for (; iz <= 170; iz++) {
10474 for (
int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
10475 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
10482 for (; iz <= 170; iz++) {
10484 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10485 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10490 if (iz > 0 && iz < 170)
10491 met->
pt[ix][iy] = (float) p2[iz];
10503#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
10504 for (
int ix = 0; ix < met->
nx; ix++)
10505 for (
int iy = 0; iy < met->
ny; iy++) {
10508 for (
int iz = 0; iz < met->
np; iz++)
10509 pv[iz] = met->
pv[ix][iy][iz];
10513 for (
int iz = 0; iz < met->
np; iz++)
10514 th[iz] =
THETA(met->
p[iz], met->
t[ix][iy][iz]);
10518 met->
pt[ix][iy] = NAN;
10519 for (
int iz = 0; iz <= 170; iz++)
10522 if (iz > 0 && iz < 170)
10523 met->
pt[ix][iy] = (float) p2[iz];
10530 ERRMSG(
"Cannot calculate tropopause!");
10533#pragma omp parallel for default(shared) collapse(2)
10534 for (
int ix = 0; ix < met->
nx; ix++)
10535 for (
int iy = 0; iy < met->
ny; iy++) {
10536 double h2ot, tt, zt;
10539 met->
lat[iy], &tt, ci, cw, 1);
10541 met->
lat[iy], &zt, ci, cw, 0);
10543 met->
lat[iy], &h2ot, ci, cw, 0);
10544 met->
tt[ix][iy] = (float) tt;
10545 met->
zt[ix][iy] = (float) zt;
10546 met->
h2ot[ix][iy] = (float) h2ot;
10553 const char *filename,
10563 LOG(1,
"Read observation data: %s", filename);
10567 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
10569 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
10571 ERRMSG(
"Set OBS_TYPE to 0 or 1!");
10574 for (
int i = 1; i < *nobs; i++)
10575 if (rt[i] < rt[i - 1])
10576 ERRMSG(
"Time must be ascending!");
10581 LOG(2,
"Number of observations: %d", *nobs);
10582 gsl_stats_minmax(&mini, &maxi, rt, 1, (
size_t) n);
10583 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
10584 gsl_stats_minmax(&mini, &maxi, rz, 1, (
size_t) n);
10585 LOG(2,
"Altitude range: %g ... %g km", mini, maxi);
10586 gsl_stats_minmax(&mini, &maxi, rlon, 1, (
size_t) n);
10587 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
10588 gsl_stats_minmax(&mini, &maxi, rlat, 1, (
size_t) n);
10589 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
10590 gsl_stats_minmax(&mini, &maxi, robs, 1, (
size_t) n);
10591 LOG(2,
"Observation range: %g ... %g", mini, maxi);
10597 const char *filename,
10607 if (!(in = fopen(filename,
"r")))
10608 ERRMSG(
"Cannot open file!");
10612 while (fgets(line,
LEN, in))
10613 if (sscanf(line,
"%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
10614 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
10615 if ((++(*nobs)) >=
NOBS)
10616 ERRMSG(
"Too many observations!");
10625 const char *filename,
10636 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
10637 ERRMSG(
"Cannot open file!");
10648 NC(nc_close(ncid));
10654 const char *filename,
10657 const char *varname,
10659 const char *defvalue,
10664 char fullname1[
LEN], fullname2[
LEN], rval[
LEN];
10666 int contain = 0, i;
10669 if (filename[strlen(filename) - 1] !=
'-')
10670 if (!(in = fopen(filename,
"r")))
10671 ERRMSG(
"Cannot open file!");
10675 sprintf(fullname1,
"%s[%d]", varname, arridx);
10676 sprintf(fullname2,
"%s[*]", varname);
10678 sprintf(fullname1,
"%s", varname);
10679 sprintf(fullname2,
"%s", varname);
10684 char dummy[
LEN], line[
LEN], rvarname[
LEN];
10685 while (fgets(line,
LEN, in)) {
10686 if (sscanf(line,
"%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
10687 if (strcasecmp(rvarname, fullname1) == 0 ||
10688 strcasecmp(rvarname, fullname2) == 0) {
10694 for (i = 1; i < argc - 1; i++)
10695 if (strcasecmp(argv[i], fullname1) == 0 ||
10696 strcasecmp(argv[i], fullname2) == 0) {
10697 sprintf(rval,
"%s", argv[i + 1]);
10708 if (strlen(defvalue) > 0)
10709 sprintf(rval,
"%s", defvalue);
10711 ERRMSG(
"Missing variable %s!\n", fullname1);
10715 LOG(1,
"%s = %s", fullname1, rval);
10719 sprintf(value,
"%s", rval);
10729 const double rhop) {
10732 const double rp_help = rp * 1e-6;
10735 const double rho =
RHO(p, T);
10738 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
10741 const double v = sqrt(8. *
KB * T / (M_PI * 4.8096e-26));
10744 const double lambda = 2. * eta / (rho * v);
10747 const double K = lambda / rp_help;
10750 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
10753 return 2. *
SQR(rp_help) * (rhop - rho) *
G0 / (9. * eta) * G;
10765 const int method) {
10771 gsl_interp_accel *acc = gsl_interp_accel_alloc();
10772 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (
size_t) n);
10775 gsl_spline_init(s, x, y, (
size_t) n);
10776 for (
int i = 0; i < n2; i++)
10779 else if (x2[i] >= x[n - 1])
10782 y2[i] = gsl_spline_eval(s, x2[i], acc);
10785 gsl_spline_free(s);
10786 gsl_interp_accel_free(acc);
10791 for (
int i = 0; i < n2; i++)
10794 else if (x2[i] >= x[n - 1])
10798 y2[i] =
LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
10812 float mean = 0, var = 0;
10814 for (
int i = 0; i < n; ++i) {
10816 var +=
SQR(data[i]);
10819 var = var / (float) n -
SQR(mean / (
float) n);
10821 return (var > 0 ? sqrtf(var) : 0);
10829 const double lat) {
10832 const double D = sec / 86400 - 0.5;
10835 const double g =
DEG2RAD(357.529 + 0.98560028 * D);
10836 const double q = 280.459 + 0.98564736 * D;
10837 const double L =
DEG2RAD(q + 1.915 * sin(g) + 0.020 * sin(2 * g));
10840 const double e =
DEG2RAD(23.439 - 0.00000036 * D);
10843 const double sindec = sin(e) * sin(L);
10846 const double ra = atan2(cos(e) * sin(L), cos(L));
10849 const double GMST = 18.697374558 + 24.06570982441908 * D;
10852 const double LST = GMST + lon / 15;
10855 const double h = LST / 12 * M_PI - ra;
10858 const double lat_help =
DEG2RAD(lat);
10861 return acos(sin(lat_help) * sindec +
10862 cos(lat_help) * sqrt(1 -
SQR(sindec)) * cos(h));
10874 const double remain,
10886 t1.tm_year = year - 1900;
10887 t1.tm_mon = mon - 1;
10893 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
10901 const int output) {
10908 static int iname = -1, igroup = -1, nname, ngroup, ct_name[
NTIMER];
10911 t1 = omp_get_wtime();
10916 rt_name[iname] += dt;
10917 rt_min[iname] = (ct_name[iname] <= 0 ? dt :
MIN(rt_min[iname], dt));
10918 rt_max[iname] = (ct_name[iname] <= 0 ? dt :
MAX(rt_max[iname], dt));
10922 rt_group[igroup] += t1 - t0;
10926 for (
int i = 0; i < nname; i++)
10927 LOG(1,
"TIMER_%s = %.3f s (min= %g s, mean= %g s,"
10928 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
10929 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
10930 for (
int i = 0; i < ngroup; i++)
10931 LOG(1,
"TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
10932 double total = 0.0;
10933 for (
int i = 0; i < nname; i++)
10934 total += rt_name[i];
10935 LOG(1,
"TIMER_TOTAL = %.3f s", total);
10939 for (iname = 0; iname < nname; iname++)
10940 if (strcasecmp(name, names[iname]) == 0)
10942 for (igroup = 0; igroup < ngroup; igroup++)
10943 if (strcasecmp(group, groups[igroup]) == 0)
10947 if (iname >= nname) {
10948 sprintf(names[iname],
"%s", name);
10949 if ((++nname) >=
NTIMER)
10950 ERRMSG(
"Too many timers!");
10954 if (igroup >= ngroup) {
10955 sprintf(groups[igroup],
"%s", group);
10956 if ((++ngroup) >=
NTIMER)
10957 ERRMSG(
"Too many groups!");
10967 const char *filename,
10968 const int offset) {
10975 int len = (int) strlen(filename);
10976 sprintf(tstr,
"%.4s", &filename[len - offset]);
10977 int year = atoi(tstr);
10978 sprintf(tstr,
"%.2s", &filename[len - offset + 5]);
10979 int mon = atoi(tstr);
10980 sprintf(tstr,
"%.2s", &filename[len - offset + 8]);
10981 int day = atoi(tstr);
10982 sprintf(tstr,
"%.2s", &filename[len - offset + 11]);
10983 int hour = atoi(tstr);
10984 sprintf(tstr,
"%.2s", &filename[len - offset + 14]);
10985 int min = atoi(tstr);
10988 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
10989 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
10990 ERRMSG(
"Cannot read time from filename!");
10993 time2jsec(year, mon, day, hour, min, 0, 0.0, &t);
11010 const double p1 = pt * 0.866877899;
11011 const double p0 = pt / 0.866877899;
11014 if (atm->
p[ip] > p0)
11016 else if (atm->
p[ip] < p1)
11019 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
11025 const char *filename,
11033 const double t0 = t - 0.5 * ctl->
dt_mod;
11034 const double t1 = t + 0.5 * ctl->
dt_mod;
11040 if (!(out = popen(
"gnuplot",
"w")))
11041 ERRMSG(
"Cannot create pipe to gnuplot!");
11044 fprintf(out,
"set out \"%s.png\"\n", filename);
11048 int year, mon, day, hour, min, sec;
11049 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11050 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
11051 year, mon, day, hour, min);
11056 ERRMSG(
"Cannot open file!");
11058 while (fgets(line,
LEN, in))
11059 fprintf(out,
"%s", line);
11066 if (!(out = fopen(filename,
"w")))
11067 ERRMSG(
"Cannot create file!");
11072 "# $1 = time [s]\n"
11073 "# $2 = altitude [km]\n"
11074 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
11075 for (
int iq = 0; iq < ctl->
nq; iq++)
11076 fprintf(out,
"# $%i = %s [%s]\n", iq + 5, ctl->
qnt_name[iq],
11078 fprintf(out,
"\n");
11081 for (
int ip = 0; ip < atm->
np; ip += ctl->
atm_stride) {
11088 fprintf(out,
"%.2f %g %g %g", atm->
time[ip],
Z(atm->
p[ip]),
11089 atm->
lon[ip], atm->
lat[ip]);
11090 for (
int iq = 0; iq < ctl->
nq; iq++) {
11095 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
11097 fprintf(out,
"\n");
11107 const char *filename,
11109 const atm_t *atm) {
11114 if (!(out = fopen(filename,
"w")))
11115 ERRMSG(
"Cannot create file!");
11139 for (
int iq = 0; iq < ctl->
nq; iq++)
11157 const char *filename,
11159 const atm_t *atm) {
11161 int tid, pid, ncid, varid;
11162 size_t start[2], count[2];
11165 nc_create(filename, NC_NETCDF4, &ncid);
11168 NC(nc_def_dim(ncid,
"time", 1, &tid));
11169 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11172 int dim_ids[2] = { tid, pid };
11173 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11174 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11175 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
11177 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
11179 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
11182 for (
int iq = 0; iq < ctl->
nq; iq++)
11192 NC(nc_enddef(ncid));
11200 for (
int iq = 0; iq < ctl->
nq; iq++)
11204 NC(nc_close(ncid));
11210 const char *dirname,
11216 static size_t out_cnt = 0;
11218 double r, r_start, r_stop;
11219 int year, mon, day, hour, min, sec;
11220 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
11221 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
11222 char filename_out[2 *
LEN] =
"traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
11224 int ncid, varid, tid, pid, cid;
11232 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11234 &min_start, &sec_start, &r_start);
11236 &min_stop, &sec_stop, &r_stop);
11238 sprintf(filename_out,
11239 "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc", dirname,
11240 year_start % 100, mon_start, day_start, hour_start,
11241 year_stop % 100, mon_stop, day_stop, hour_stop);
11242 LOG(1,
"Write traj file: %s", filename_out);
11245 start[0] = out_cnt;
11248 count[1] = (size_t) atm->
np;
11251 if (out_cnt == 0) {
11254 nc_create(filename_out, NC_NETCDF4, &ncid);
11257 NC(nc_def_dim(ncid,
"time", NC_UNLIMITED, &tid));
11258 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11259 NC(nc_def_dim(ncid,
"TMDT", 7, &cid));
11264 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11265 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11266 NC_DEF_VAR(
"LAT", NC_DOUBLE, 2, dim_ids,
"Latitude",
"deg",
11268 NC_DEF_VAR(
"LON", NC_DOUBLE, 2, dim_ids,
"Longitude",
"deg",
11270 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 2, dim_ids,
"Pressure",
"hPa",
11272 NC_DEF_VAR(
"ZETA", NC_DOUBLE, 2, dim_ids,
"Zeta",
"K",
11274 for (
int iq = 0; iq < ctl->
nq; iq++)
11284 NC(nc_enddef(ncid));
11285 NC(nc_close(ncid));
11292 NC(nc_open(filename_out, NC_WRITE, &ncid));
11304 for (
int iq = 0; iq < ctl->
nq; iq++)
11308 NC(nc_close(ncid));
11311 if ((year == year_stop) && (mon == mon_stop)
11312 && (day == day_stop) && (hour == hour_stop)) {
11315 char filename_init[2 *
LEN] =
"./init_fix_YYYYMMDDHH.nc";
11316 sprintf(filename_init,
"%s/init_fix_%02d%02d%02d%02d.nc",
11317 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
11318 LOG(1,
"Write init file: %s", filename_init);
11321 nc_create(filename_init, NC_NETCDF4, &ncid);
11324 NC(nc_def_dim(ncid,
"time", 1, &tid));
11325 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11330 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11331 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11332 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
11334 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
11336 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
11339 for (
int iq = 0; iq < ctl->
nq; iq++)
11349 NC(nc_enddef(ncid));
11357 for (
int iq = 0; iq < ctl->
nq; iq++)
11361 NC(nc_close(ncid));
11368 const char *filename,
11370 const atm_t *atm) {
11372 int ncid, obsid, varid;
11374 size_t start[2], count[2];
11377 NC(nc_create(filename, NC_NETCDF4, &ncid));
11380 NC(nc_def_dim(ncid,
"obs", (
size_t) atm->
np, &obsid));
11383 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &obsid,
"time",
11384 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11385 NC_DEF_VAR(
"press", NC_DOUBLE, 1, &obsid,
"pressure",
"hPa",
11387 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &obsid,
"longitude",
"degrees_east",
11389 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &obsid,
"latitude",
"degrees_north",
11391 for (
int iq = 0; iq < ctl->
nq; iq++)
11400 NC(nc_enddef(ncid));
11407 for (
int iq = 0; iq < ctl->
nq; iq++)
11411 NC(nc_close(ncid));
11417 const char *filename,
11424 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
11427 static int *obscount, nobs, nk;
11431 const int ensemble = (ctl->
nens > 0);
11437 if (ctl->
qnt_m < 0)
11438 ERRMSG(
"Need quantity mass!");
11441 ERRMSG(
"Missing ensemble IDs!");
11443 ERRMSG(
"Too many ensembles!");
11450 ALLOC(area,
double,
11456 ALLOC(rlon,
double,
11458 ALLOC(rlat,
double,
11460 ALLOC(robs,
double,
11471 LOG(1,
"Write CSI%s data: %s", ensemble ?
" ensemble" :
"", filename);
11472 if (!(out = fopen(filename,
"w")))
11473 ERRMSG(
"Cannot create file!");
11477 "# $1 = time [s]\n"
11478 "# $2 = ensemble ID\n"
11479 "# $3 = number of hits (cx)\n"
11480 "# $4 = number of misses (cy)\n"
11481 "# $5 = number of false alarms (cz)\n"
11482 "# $6 = number of observations (cx + cy)\n"
11483 "# $7 = number of forecasts (cx + cz)\n"
11484 "# $8 = bias (%%)\n"
11485 "# $9 = POD (%%)\n"
11486 "# $10 = FAR (%%)\n"
11487 "# $11 = CSI (%%)\n"
11488 "# $12 = hits by random chance\n"
11489 "# $13 = ETS (%%)\n"
11490 "# $14 = Pearson R\n"
11491 "# $15 = Spearman R\n"
11492 "# $16 = mean error [kg/m²]\n"
11493 "# $17 = RMSE [kg/m²]\n"
11494 "# $18 = MAE [kg/m²]\n"
11495 "# $19 = log-likelihood\n" "# $20 = number of points\n\n");
11503 for (
int iy = 0; iy < ctl->
csi_ny; iy++) {
11504 const double lat = ctl->
csi_lat0 + dlat * (iy + 0.5);
11505 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.0) * cos(
DEG2RAD(lat));
11510 const double t0 = t - 0.5 * ctl->
dt_mod;
11511 const double t1 = t + 0.5 * ctl->
dt_mod;
11515 ALLOC(modmean,
double,
11516 (ensemble ? ctl->
nens : 1) * grid_size);
11517 ALLOC(obsmean,
double,
11519 ALLOC(obscount,
int,
11521 ALLOC(obsstd,
double,
11525 for (
int i = 0; i < (ensemble ? ctl->
nens : 1); i++)
11526 ct[i] = cx[i] = cy[i] = cz[i] = n[i] = 0;
11529 for (
int i = 0; i < nobs; i++) {
11530 if (rt[i] < t0 || rt[i] >= t1 || !isfinite(robs[i]))
11534 const int ix = (int) ((rlon[i] - ctl->
csi_lon0) / dlon);
11535 const int iy = (int) ((rlat[i] - ctl->
csi_lat0) / dlat);
11536 const int iz = (int) ((rz[i] - ctl->
csi_z0) / dz);
11537 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
11543 obsmean[idx] += robs[i];
11544 obsstd[idx] +=
SQR(robs[i]);
11549 for (
int ip = 0; ip < atm->
np; ip++) {
11552 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11556 int ens_id = ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
11557 if (ens_id < 0 || ens_id >= (ensemble ? ctl->
nens : 1))
11558 ERRMSG(
"Ensemble ID out of range!");
11561 const int ix = (int) ((atm->
lon[ip] - ctl->
csi_lon0) / dlon);
11562 const int iy = (int) ((atm->
lat[ip] - ctl->
csi_lat0) / dlat);
11563 const int iz = (int) ((
Z(atm->
p[ip]) - ctl->
csi_z0) / dz);
11564 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
11576 for (
int ix = 0; ix < ctl->
csi_nx; ix++)
11577 for (
int iy = 0; iy < ctl->
csi_ny; iy++)
11578 for (
int iz = 0; iz < ctl->
csi_nz; iz++) {
11582 if (obscount[idx]) {
11583 obsmean[idx] /= obscount[idx];
11584 obsstd[idx] = sqrt(obsstd[idx] -
SQR(obsmean[idx]));
11588 for (
int e = 0; e < (ensemble ? ctl->
nens : 1); e++) {
11589 const int midx = e * grid_size + idx;
11590 if (modmean[midx] > 0)
11591 modmean[midx] /= (1e6 * area[iy]);
11595 if (obscount[idx]) {
11598 for (
int e = 0; e < (ensemble ? ctl->
nens : 1); e++) {
11599 const int midx = e * grid_size + idx;
11612 x[n[e]] = modmean[midx];
11613 y[n[e]] = obsmean[idx];
11615 obsstdn[n[e]] = obsstd[idx];
11616 if ((++n[e]) >=
NCSI)
11617 ERRMSG(
"Too many points for statistics!");
11625 for (
int e = 0; e < (ensemble ? ctl->
nens : 1); e++) {
11632 static double work[2 *
NCSI], work2[2 *
NCSI];
11633 const int n_obs = cx[e] + cy[e];
11634 const int n_for = cx[e] + cz[e];
11635 const double cx_rd = (ct[e] > 0) ? (1. * n_obs * n_for) / ct[e] : NAN;
11636 const double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
11637 const double pod = (n_obs > 0) ? 100. * cx[e] / n_obs : NAN;
11638 const double far = (n_for > 0) ? 100. * cz[e] / n_for : NAN;
11640 (cx[e] + cy[e] + cz[e] >
11641 0) ? 100. * cx[e] / (cx[e] + cy[e] + cz[e]) : NAN;
11643 (cx[e] + cy[e] + cz[e] - cx_rd >
11644 0) ? 100. * (cx[e] - cx_rd) / (cx[e] + cy[e] + cz[e] - cx_rd) : NAN;
11645 const double rho_p = gsl_stats_correlation(x, 1, y, 1, (
size_t) n[e]);
11646 const double rho_s =
11647 gsl_stats_spearman(x, 1, y, 1, (
size_t) n[e], work);
11648 for (
int i = 0; i < n[e]; i++) {
11649 work[i] = x[i] - y[i];
11650 work2[i] = (obsstdn[i] != 0) ? work[i] / obsstdn[i] : 0;
11652 const double mean = gsl_stats_mean(work, 1, (
size_t) n[e]);
11653 const double rmse =
11654 gsl_stats_sd_with_fixed_mean(work, 1, (
size_t) n[e], 0.0);
11655 const double absdev = gsl_stats_absdev_m(work, 1, (
size_t) n[e], 0.0);
11656 const double loglikelihood =
11657 gsl_stats_tss(work2, 1, (
size_t) n[e]) * -0.5;
11661 "%.2f %d %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n",
11662 t, ensemble ? e : -999, cx[e], cy[e], cz[e], n_obs, n_for, bias,
11663 pod, far, csi, cx_rd, ets, rho_p, rho_s, mean, rmse, absdev,
11664 loglikelihood, n[e]);
11667 ct[e] = cx[e] = cy[e] = cz[e] = n[e] = 0;
11696 const char *filename,
11706 static int n[
NENS];
11713 ERRMSG(
"Missing ensemble IDs!");
11716 const double t0 = t - 0.5 * ctl->
dt_mod;
11717 const double t1 = t + 0.5 * ctl->
dt_mod;
11720 for (
int i = 0; i <
NENS; i++) {
11721 for (
int iq = 0; iq < ctl->
nq; iq++)
11722 qm[iq][i] = qs[iq][i] = 0;
11723 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
11728 for (
int ip = 0; ip < atm->
np; ip++) {
11731 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11736 ERRMSG(
"Ensemble ID is out of range!");
11740 for (
int iq = 0; iq < ctl->
nq; iq++) {
11741 qm[iq][ctl->
qnt_ens] += atm->
q[iq][ip];
11752 LOG(1,
"Write ensemble data: %s", filename);
11753 if (!(out = fopen(filename,
"w")))
11754 ERRMSG(
"Cannot create file!");
11758 "# $1 = time [s]\n"
11759 "# $2 = altitude [km]\n"
11760 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
11761 for (
int iq = 0; iq < ctl->
nq; iq++)
11762 fprintf(out,
"# $%d = %s (mean) [%s]\n", 5 + iq,
11764 for (
int iq = 0; iq < ctl->
nq; iq++)
11765 fprintf(out,
"# $%d = %s (sigma) [%s]\n", 5 + ctl->
nq + iq,
11767 fprintf(out,
"# $%d = number of members\n\n", 5 + 2 * ctl->
nq);
11770 for (
int i = 0; i <
NENS; i++)
11772 cart2geo(xm[i], &dummy, &lon, &lat);
11773 fprintf(out,
"%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
11774 for (
int iq = 0; iq < ctl->
nq; iq++) {
11776 fprintf(out, ctl->
qnt_format[iq], qm[iq][i] / n[i]);
11778 for (
int iq = 0; iq < ctl->
nq; iq++) {
11780 double var = qs[iq][i] / n[i] -
SQR(qm[iq][i] / n[i]);
11781 fprintf(out, ctl->
qnt_format[iq], (var > 0 ? sqrt(var) : 0));
11783 fprintf(out,
" %d\n", n[i]);
11793 const char *filename,
11800 static double kz[
EP], kw[
EP];
11804 double *cd, *mean[
NQ], *sigma[
NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
11806 int *ixs, *iys, *izs, *np;
11812 LOG(1,
"Write grid data: %s", filename);
11825 for (
int iq = 0; iq < ctl->
nq; iq++) {
11826 ALLOC(mean[iq],
double,
11828 ALLOC(sigma[iq],
double,
11831 ALLOC(vmr_impl,
double,
11839 ALLOC(area,
double,
11841 ALLOC(press,
double,
11858#pragma omp parallel
for default(shared)
11859 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
11860 z[iz] = ctl->
grid_z0 + dz * (iz + 0.5);
11861 press[iz] =
P(z[iz]);
11865 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
11866 lon[ix] = ctl->
grid_lon0 + dlon * (ix + 0.5);
11867#pragma omp parallel for default(shared)
11868 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
11869 lat[iy] = ctl->
grid_lat0 + dlat * (iy + 0.5);
11870 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
11874 const double t0 = t - 0.5 * ctl->
dt_mod;
11875 const double t1 = t + 0.5 * ctl->
dt_mod;
11878#pragma omp parallel for default(shared)
11879 for (
int ip = 0; ip < atm->
np; ip++) {
11880 ixs[ip] = (int) ((atm->
lon[ip] - ctl->
grid_lon0) / dlon);
11881 iys[ip] = (int) ((atm->
lat[ip] - ctl->
grid_lat0) / dlat);
11882 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
grid_z0) / dz);
11883 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
11884 || ixs[ip] < 0 || ixs[ip] >= ctl->
grid_nx
11885 || iys[ip] < 0 || iys[ip] >= ctl->
grid_ny
11886 || izs[ip] < 0 || izs[ip] >= ctl->
grid_nz)
11891 for (
int ip = 0; ip < atm->
np; ip++)
11892 if (izs[ip] >= 0) {
11897 for (
int iq = 0; iq < ctl->
nq; iq++) {
11898 mean[iq][idx] += kernel * atm->
q[iq][ip];
11899 sigma[iq][idx] +=
SQR(kernel * atm->
q[iq][ip]);
11904#pragma omp parallel for default(shared)
11905 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
11906 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
11907 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
11914 if (ctl->
qnt_m >= 0)
11915 cd[idx] = mean[ctl->
qnt_m][idx] / (1e6 * area[iy]);
11918 vmr_impl[idx] = NAN;
11919 if (ctl->
qnt_m >= 0 && ctl->
molmass > 0 && met0 != NULL
11922 if (mean[ctl->
qnt_m][idx] > 0) {
11928 lon[ix], lat[iy], &temp, ci, cw, 1);
11932 MA / ctl->
molmass * cd[idx] / (
RHO(press[iz], temp) * dz * 1e3);
11938 for (
int iq = 0; iq < ctl->
nq; iq++) {
11939 mean[iq][idx] /= np[idx];
11940 const double var = sigma[iq][idx] / np[idx] -
SQR(mean[iq][idx]);
11941 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
11943 for (
int iq = 0; iq < ctl->
nq; iq++) {
11944 mean[iq][idx] = NAN;
11945 sigma[iq][idx] = NAN;
11952 t, z, lon, lat, area, dz, np);
11957 t, z, lon, lat, area, dz, np);
11961 ERRMSG(
"Grid data format GRID_TYPE unknown!");
11965 for (
int iq = 0; iq < ctl->
nq; iq++) {
11984 const char *filename,
11989 const double *vmr_impl,
11994 const double *area,
12004 if (!(out = popen(
"gnuplot",
"w")))
12005 ERRMSG(
"Cannot create pipe to gnuplot!");
12008 fprintf(out,
"set out \"%s.png\"\n", filename);
12012 int year, mon, day, hour, min, sec;
12013 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
12014 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
12015 year, mon, day, hour, min);
12021 ERRMSG(
"Cannot open file!");
12022 while (fgets(line,
LEN, in))
12023 fprintf(out,
"%s", line);
12030 if (!(out = fopen(filename,
"w")))
12031 ERRMSG(
"Cannot create file!");
12036 "# $1 = time [s]\n"
12037 "# $2 = altitude [km]\n"
12038 "# $3 = longitude [deg]\n"
12039 "# $4 = latitude [deg]\n"
12040 "# $5 = surface area [km^2]\n"
12041 "# $6 = layer depth [km]\n"
12042 "# $7 = column density (implicit) [kg/m^2]\n"
12043 "# $8 = volume mixing ratio (implicit) [ppv]\n"
12044 "# $9 = number of particles [1]\n");
12045 for (
int iq = 0; iq < ctl->
nq; iq++)
12046 fprintf(out,
"# $%i = %s (mean) [%s]\n", 10 + iq, ctl->
qnt_name[iq],
12049 for (
int iq = 0; iq < ctl->
nq; iq++)
12050 fprintf(out,
"# $%i = %s (stddev) [%s]\n", 10 + ctl->
nq + iq,
12052 fprintf(out,
"\n");
12055 for (
int ix = 0; ix < ctl->
grid_nx; ix++) {
12057 fprintf(out,
"\n");
12058 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
12060 fprintf(out,
"\n");
12061 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
12064 fprintf(out,
"%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
12065 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
12066 for (
int iq = 0; iq < ctl->
nq; iq++) {
12068 fprintf(out, ctl->
qnt_format[iq], mean[iq][idx]);
12071 for (
int iq = 0; iq < ctl->
nq; iq++) {
12073 fprintf(out, ctl->
qnt_format[iq], sigma[iq][idx]);
12075 fprintf(out,
"\n");
12088 const char *filename,
12093 const double *vmr_impl,
12098 const double *area,
12102 char longname[2 *
LEN], varname[2 *
LEN];
12106 int *help2, ncid, dimid[10], varid;
12108 size_t start[2], count[2];
12111 ALLOC(help,
double,
12117 NC(nc_create(filename, NC_NETCDF4, &ncid));
12120 NC(nc_def_dim(ncid,
"time", 1, &dimid[0]));
12121 NC(nc_def_dim(ncid,
"z", (
size_t) ctl->
grid_nz, &dimid[1]));
12122 NC(nc_def_dim(ncid,
"lat", (
size_t) ctl->
grid_ny, &dimid[2]));
12123 NC(nc_def_dim(ncid,
"lon", (
size_t) ctl->
grid_nx, &dimid[3]));
12124 NC(nc_def_dim(ncid,
"dz", 1, &dimid[4]));
12127 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &dimid[0],
"time",
12128 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
12129 NC_DEF_VAR(
"z", NC_DOUBLE, 1, &dimid[1],
"altitude",
"km", 0, 0);
12130 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &dimid[2],
"latitude",
"degrees_north", 0,
12132 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &dimid[3],
"longitude",
"degrees_east", 0,
12134 NC_DEF_VAR(
"dz", NC_DOUBLE, 1, &dimid[1],
"layer depth",
"km", 0, 0);
12135 NC_DEF_VAR(
"area", NC_DOUBLE, 1, &dimid[2],
"surface area",
"km**2", 0, 0);
12137 NC_DEF_VAR(
"cd", NC_FLOAT, 4, dimid,
"column density",
"kg m**-2",
12140 "volume mixing ratio (implicit)",
"ppv", ctl->
grid_nc_level, 0);
12141 NC_DEF_VAR(
"np", NC_INT, 4, dimid,
"number of particles",
"1", 0, 0);
12142 for (
int iq = 0; iq < ctl->
nq; iq++) {
12143 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
12144 sprintf(longname,
"%s (mean)", ctl->
qnt_longname[iq]);
12148 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
12149 sprintf(longname,
"%s (stddev)", ctl->
qnt_longname[iq]);
12155 NC(nc_enddef(ncid));
12165 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12166 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12167 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12172 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12173 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12174 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12179 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12180 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12181 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12186 for (
int iq = 0; iq < ctl->
nq; iq++) {
12187 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
12188 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12189 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12190 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12197 for (
int iq = 0; iq < ctl->
nq; iq++) {
12198 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
12199 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12200 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12201 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12208 NC(nc_close(ncid));
12218 const char *filename,
12224 if (!(out = fopen(filename,
"w")))
12225 ERRMSG(
"Cannot create file!");
12315 ERRMSG(
"Number of meteo variables doesn't match!");
12333 const char *varname) {
12342 for (
int ix = 0; ix < met->
nx; ix++)
12343 for (
int iy = 0; iy < met->
ny; iy++)
12344 help[
ARRAY_2D(ix, iy, met->
ny)] = var[ix][iy];
12347 LOG(2,
"Write 2-D variable: %s (uncompressed)", varname);
12349 (
size_t) (met->
nx * met->
ny),
12363 const char *varname,
12364 const int precision,
12365 const double tolerance) {
12374#pragma omp parallel for default(shared) collapse(2)
12375 for (
int ix = 0; ix < met->
nx; ix++)
12376 for (
int iy = 0; iy < met->
ny; iy++)
12377 for (
int ip = 0; ip < met->
np; ip++)
12378 help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)] = var[ix][iy][ip];
12382 LOG(2,
"Write 3-D variable: %s (uncompressed)", varname);
12384 (
size_t) (met->
nx * met->
ny * met->
np),
12391 (
size_t) met->
np, 0, out);
12399 FWRITE(&tolerance,
double,
12403 tolerance, 0, out);
12418 (
size_t) met->
np, 0, out);
12428 FWRITE(&tolerance,
double,
12432 tolerance, 0, out);
12438 ERRMSG(
"MET_TYPE not supported!");
12439 LOG(3,
"%d %g", precision, tolerance);
12449 const char *filename,
12455 size_t start[4], count[4];
12456 nc_create(filename, NC_NETCDF4, &ncid);
12459 int tid, lonid, latid, levid;
12460 NC(nc_def_dim(ncid,
"time", 1, &tid));
12461 NC(nc_def_dim(ncid,
"lon", (
size_t) met->
nx, &lonid));
12462 NC(nc_def_dim(ncid,
"lat", (
size_t) met->
ny, &latid));
12463 NC(nc_def_dim(ncid,
"lev", (
size_t) met->
np, &levid));
12466 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"time",
12467 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
12468 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &lonid,
"longitude",
"degrees_east", 0, 0);
12469 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &latid,
"latitude",
"degrees_north", 0, 0);
12470 NC_DEF_VAR(
"lev", NC_DOUBLE, 1, &levid,
"pressure",
"Pa", 0, 0);
12473 int dimid2[2] = { latid, lonid };
12474 NC_DEF_VAR(
"sp", NC_FLOAT, 2, dimid2,
"Surface pressure",
"Pa",
12476 NC_DEF_VAR(
"z", NC_FLOAT, 2, dimid2,
"Geopotential",
"m**2 s**-2",
12478 NC_DEF_VAR(
"t2m", NC_FLOAT, 2, dimid2,
"2 metre temperature",
"K",
12480 NC_DEF_VAR(
"u10m", NC_FLOAT, 2, dimid2,
"10 metre U wind component",
12482 NC_DEF_VAR(
"v10m", NC_FLOAT, 2, dimid2,
"10 metre V wind component",
12485 "Instantaneous eastward turbulent surface stress",
"N m**-2",
12488 "Instantaneous northward turbulent surface stress",
"N m**-2",
12491 "Instantaneous surface sensible heat flux",
"W m**-1",
12493 NC_DEF_VAR(
"lsm", NC_FLOAT, 2, dimid2,
"Land/sea mask",
"-",
12495 NC_DEF_VAR(
"sstk", NC_FLOAT, 2, dimid2,
"Sea surface temperature",
"K",
12497 NC_DEF_VAR(
"blp", NC_FLOAT, 2, dimid2,
"Boundary layer pressure",
"Pa",
12499 NC_DEF_VAR(
"pt", NC_FLOAT, 2, dimid2,
"Tropopause pressure",
"Pa",
12501 NC_DEF_VAR(
"tt", NC_FLOAT, 2, dimid2,
"Tropopause temperature",
"K",
12503 NC_DEF_VAR(
"zt", NC_FLOAT, 2, dimid2,
"Tropopause height",
"m",
12505 NC_DEF_VAR(
"h2ot", NC_FLOAT, 2, dimid2,
"Tropopause water vapor",
"ppv",
12507 NC_DEF_VAR(
"pct", NC_FLOAT, 2, dimid2,
"Cloud top pressure",
"Pa",
12509 NC_DEF_VAR(
"pcb", NC_FLOAT, 2, dimid2,
"Cloud bottom pressure",
"Pa",
12511 NC_DEF_VAR(
"cl", NC_FLOAT, 2, dimid2,
"Total column cloud water",
12514 "Pressure at lifted condensation level (LCL)",
"Pa",
12517 "Pressure at level of free convection (LFC)",
"Pa",
12520 "Pressure at equilibrium level (EL)",
"Pa", ctl->
met_nc_level,
12523 "Convective available potential energy",
"J kg**-1",
12525 NC_DEF_VAR(
"cin", NC_FLOAT, 2, dimid2,
"Convective inhibition",
12527 NC_DEF_VAR(
"o3c", NC_FLOAT, 2, dimid2,
"Total column ozone",
"DU",
12531 int dimid3[3] = { levid, latid, lonid };
12532 NC_DEF_VAR(
"t", NC_FLOAT, 3, dimid3,
"Temperature",
"K",
12534 NC_DEF_VAR(
"u", NC_FLOAT, 3, dimid3,
"U velocity",
"m s**-1",
12536 NC_DEF_VAR(
"v", NC_FLOAT, 3, dimid3,
"V velocity",
"m s**-1",
12538 NC_DEF_VAR(
"w", NC_FLOAT, 3, dimid3,
"Vertical velocity",
"Pa s**-1",
12540 NC_DEF_VAR(
"q", NC_FLOAT, 3, dimid3,
"Specific humidity",
"kg kg**-1",
12542 NC_DEF_VAR(
"o3", NC_FLOAT, 3, dimid3,
"Ozone mass mixing ratio",
12544 NC_DEF_VAR(
"clwc", NC_FLOAT, 3, dimid3,
"Cloud liquid water content",
12546 NC_DEF_VAR(
"crwc", NC_FLOAT, 3, dimid3,
"Cloud rain water content",
12548 NC_DEF_VAR(
"ciwc", NC_FLOAT, 3, dimid3,
"Cloud ice water content",
12550 NC_DEF_VAR(
"cswc", NC_FLOAT, 3, dimid3,
"Cloud snow water content",
12552 NC_DEF_VAR(
"cc", NC_FLOAT, 3, dimid3,
"Cloud cover",
"-",
12556 NC(nc_enddef(ncid));
12563 for (
int ip = 0; ip < met->
np; ip++)
12564 phelp[ip] = 100. * met->
p[ip];
12607 NC(nc_close(ncid));
12614 const char *varname,
12620 size_t start[4], count[4];
12628 for (
int ix = 0; ix < met->
nx; ix++)
12629 for (
int iy = 0; iy < met->
ny; iy++)
12630 help[
ARRAY_2D(iy, ix, met->
nx)] = scl * var[ix][iy];
12643 const char *varname,
12649 size_t start[4], count[4];
12657 for (
int ix = 0; ix < met->
nx; ix++)
12658 for (
int iy = 0; iy < met->
ny; iy++)
12659 for (
int ip = 0; ip < met->
np; ip++)
12660 help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)] = scl * var[ix][iy][ip];
12672 const char *filename,
12681 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
12682 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
12684 static int nobs, *obscount, ip, okay;
12693 if (ctl->
qnt_m < 0)
12694 ERRMSG(
"Need quantity mass!");
12698 ERRMSG(
"Specify molar mass!");
12705 ALLOC(area,
double,
12709 ALLOC(press,
double,
12715 ALLOC(rlon,
double,
12717 ALLOC(rlat,
double,
12719 ALLOC(robs,
double,
12726 LOG(1,
"Write profile data: %s", filename);
12727 if (!(out = fopen(filename,
"w")))
12728 ERRMSG(
"Cannot create file!");
12732 "# $1 = time [s]\n"
12733 "# $2 = altitude [km]\n"
12734 "# $3 = longitude [deg]\n"
12735 "# $4 = latitude [deg]\n"
12736 "# $5 = pressure [hPa]\n"
12737 "# $6 = temperature [K]\n"
12738 "# $7 = volume mixing ratio [ppv]\n"
12739 "# $8 = H2O volume mixing ratio [ppv]\n"
12740 "# $9 = O3 volume mixing ratio [ppv]\n"
12741 "# $10 = observed BT index [K]\n"
12742 "# $11 = number of observations\n");
12750 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
12751 z[iz] = ctl->
prof_z0 + dz * (iz + 0.5);
12752 press[iz] =
P(z[iz]);
12756 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
12757 lon[ix] = ctl->
prof_lon0 + dlon * (ix + 0.5);
12758 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
12759 lat[iy] = ctl->
prof_lat0 + dlat * (iy + 0.5);
12760 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
12765 const double t0 = t - 0.5 * ctl->
dt_mod;
12766 const double t1 = t + 0.5 * ctl->
dt_mod;
12769 ALLOC(mass,
double,
12771 ALLOC(obsmean,
double,
12773 ALLOC(obscount,
int,
12777 for (
int i = 0; i < nobs; i++) {
12782 else if (rt[i] >= t1)
12786 if (!isfinite(robs[i]))
12790 const int ix = (int) ((rlon[i] - ctl->
prof_lon0) / dlon);
12791 const int iy = (int) ((rlat[i] - ctl->
prof_lat0) / dlat);
12794 if (ix < 0 || ix >= ctl->
prof_nx || iy < 0 || iy >= ctl->
prof_ny)
12799 obsmean[idx] += robs[i];
12804 for (ip = 0; ip < atm->
np; ip++) {
12807 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
12811 const int ix = (int) ((atm->
lon[ip] - ctl->
prof_lon0) / dlon);
12812 const int iy = (int) ((atm->
lat[ip] - ctl->
prof_lat0) / dlat);
12813 const int iz = (int) ((
Z(atm->
p[ip]) - ctl->
prof_z0) / dz);
12816 if (ix < 0 || ix >= ctl->
prof_nx ||
12822 mass[idx] += atm->
q[ctl->
qnt_m][ip];
12826 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
12827 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
12829 if (obscount[idx2] > 0) {
12833 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
12835 if (mass[idx3] > 0) {
12844 fprintf(out,
"\n");
12847 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
12852 lon[ix], lat[iy], &temp, ci, cw, 1);
12854 lon[ix], lat[iy], &h2o, ci, cw, 0);
12856 lon[ix], lat[iy], &o3, ci, cw, 0);
12861 / (
RHO(press[iz], temp) * area[iy] * dz * 1e9);
12864 fprintf(out,
"%.2f %g %g %g %g %g %g %g %g %g %d\n",
12865 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
12866 obsmean[idx2] / obscount[idx2], obscount[idx2]);
12899 const char *filename,
12908 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[
EP],
12911 static int nobs, nk;
12924 ALLOC(rlon,
double,
12926 ALLOC(rlat,
double,
12928 ALLOC(robs,
double,
12939 LOG(1,
"Write sample data: %s", filename);
12940 if (!(out = fopen(filename,
"w")))
12941 ERRMSG(
"Cannot create file!");
12945 "# $1 = time [s]\n"
12946 "# $2 = altitude [km]\n"
12947 "# $3 = longitude [deg]\n"
12948 "# $4 = latitude [deg]\n"
12949 "# $5 = surface area [km^2]\n"
12950 "# $6 = layer depth [km]\n"
12951 "# $7 = number of particles [1]\n"
12952 "# $8 = column density [kg/m^2]\n"
12953 "# $9 = volume mixing ratio [ppv]\n"
12954 "# $10 = observed BT index [K]\n\n");
12959 area = M_PI * rmax2;
12963 const double t0 = t - 0.5 * ctl->
dt_mod;
12964 const double t1 = t + 0.5 * ctl->
dt_mod;
12967 for (
int i = 0; i < nobs; i++) {
12972 else if (rt[i] >= t1)
12977 geo2cart(0, rlon[i], rlat[i], x0);
12980 const double rp =
P(rz[i]);
12981 const double ptop =
P(rz[i] + ctl->
sample_dz);
12982 const double pbot =
P(rz[i] - ctl->
sample_dz);
12990 for (
int ip = 0; ip < atm->
np; ip++) {
12993 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
12997 if (fabs(rlat[i] - atm->
lat[ip]) > dlat)
13003 if (
DIST2(x0, x1) > rmax2)
13008 if (atm->
p[ip] > pbot || atm->
p[ip] < ptop)
13012 if (ctl->
qnt_m >= 0)
13019 const double cd = mass / (1e6 * area);
13030 rlon[i], rlat[i], &temp, ci, cw, 1);
13039 fprintf(out,
"%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
13040 rlon[i], rlat[i], area, ctl->
sample_dz, np, cd, vmr, robs[i]);
13061 const char *filename,
13068 static double rmax2, x0[3], x1[3];
13077 LOG(1,
"Write station data: %s", filename);
13080 if (!(out = fopen(filename,
"w")))
13081 ERRMSG(
"Cannot create file!");
13085 "# $1 = time [s]\n"
13086 "# $2 = altitude [km]\n"
13087 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
13088 for (
int iq = 0; iq < ctl->
nq; iq++)
13089 fprintf(out,
"# $%i = %s [%s]\n", (iq + 5),
13091 fprintf(out,
"\n");
13099 const double t0 = t - 0.5 * ctl->
dt_mod;
13100 const double t1 = t + 0.5 * ctl->
dt_mod;
13103 for (
int ip = 0; ip < atm->
np; ip++) {
13106 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13122 if (
DIST2(x0, x1) > rmax2)
13130 fprintf(out,
"%.2f %g %g %g",
13131 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]);
13132 for (
int iq = 0; iq < ctl->
nq; iq++) {
13134 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
13136 fprintf(out,
"\n");
13147 const char *filename,
13158 LOG(1,
"Write VTK data: %s", filename);
13161 const double t0 = t - 0.5 * ctl->
dt_mod;
13162 const double t1 = t + 0.5 * ctl->
dt_mod;
13165 if (!(out = fopen(filename,
"w")))
13166 ERRMSG(
"Cannot create file!");
13170 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13171 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13178 "# vtk DataFile Version 3.0\n"
13179 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
13182 fprintf(out,
"POINTS %d float\n", np);
13184 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13185 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13189 const double coslat = cos(
DEG2RAD(atm->
lat[ip]));
13190 const double x = radius * coslat * cos(
DEG2RAD(atm->
lon[ip]));
13191 const double y = radius * coslat * sin(
DEG2RAD(atm->
lon[ip]));
13192 const double z = radius * sin(
DEG2RAD(atm->
lat[ip]));
13193 fprintf(out,
"%g %g %g\n", x, y, z);
13196 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13197 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13199 fprintf(out,
"%g %g %g\n", atm->
lon[ip], atm->
lat[ip],
13204 fprintf(out,
"POINT_DATA %d\n", np);
13205 for (
int iq = 0; iq < ctl->
nq; iq++) {
13206 fprintf(out,
"SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
13208 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13209 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13211 fprintf(out,
"%g\n", atm->
q[iq][ip]);
13234 int npart = *nparticles;
13235#pragma acc enter data create( nparticles, particles[:DD_NPART])
13236#pragma acc update device( nparticles)
13237#pragma acc parallel loop present( atm, ctl, particles, cache, nparticles)
13239 for (
int ip = atm->
np; ip < atm->np + *nparticles; ip++)
13244 particles[ip - atm->
np].
time = atm->
time[ip];
13245 particles[ip - atm->
np].
lon = atm->
lon[ip];
13246 particles[ip - atm->
np].
lat = atm->
lat[ip];
13247 particles[ip - atm->
np].
p = atm->
p[ip];
13249 for (
int iq = 0; iq < ctl->
nq; iq++)
13250 particles[ip - atm->
np].q[iq] = atm->
q[iq][ip];
13256#pragma acc update host( particles[:npart])
13257#pragma acc exit data delete( nparticles, particles)
13275 int npart = *nparticles;
13276#pragma acc enter data create(nparticles, particles[:DD_NPART])
13277#pragma acc update device(particles[:npart], nparticles)
13278#pragma acc data present(atm, ctl, cache, particles, nparticles)
13279#pragma acc parallel loop
13281 for (
int ip = atm->
np; ip < atm->np + *nparticles; ip++) {
13283 atm->
time[ip] = particles[ip - atm->
np].
time;
13284 atm->
lon[ip] = particles[ip - atm->
np].
lon;
13285 atm->
lat[ip] = particles[ip - atm->
np].
lat;
13286 atm->
p[ip] = particles[ip - atm->
np].
p;
13288 for (
int iq = 0; iq < ctl->
nq; iq++)
13289 atm->
q[iq][ip] = particles[ip - atm->
np].q[iq];
13295#pragma acc exit data delete(nparticles, particles)
13299 atm->
np += *nparticles;
13301#pragma acc update device(atm->np)
13304 ERRMSG(
"Number of particles to high. Increase NP!");
13311void dd_register_MPI_type_particle(
13312 MPI_Datatype *MPI_Particle) {
13313 MPI_Datatype types[5] = { MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE,
13314 MPI_DOUBLE, MPI_DOUBLE
13316 int blocklengths[5] = { 1, 1, 1, 1,
NQ };
13317 MPI_Aint displacements[5] = { offsetof(
particle_t, time),
13323 MPI_Type_create_struct(5, blocklengths, displacements, types, MPI_Particle);
13324 MPI_Type_commit(MPI_Particle);
13331void dd_get_rect_neighbour(
13335 SELECT_TIMER(
"DD_GET_RECT_NEIGHBOUR",
"DD", NVTX_GPU);
13337 if (mpi_info->
rank + 1 == mpi_info->
size) {
13340 mpi_info->neighbours[1] =
DD_SPOLE;
13341 mpi_info->neighbours[2] =
13344 mpi_info->neighbours[3] =
13347 mpi_info->neighbours[4] =
DD_SPOLE;
13348 mpi_info->neighbours[5] =
13351 mpi_info->neighbours[6] = mpi_info->
rank - 1;
13352 mpi_info->neighbours[7] =
DD_SPOLE;
13354 }
else if (mpi_info->
rank ==
13358 mpi_info->neighbours[1] =
13360 mpi_info->neighbours[2] =
DD_NPOLE;
13362 mpi_info->neighbours[3] =
13365 mpi_info->neighbours[4] =
13368 mpi_info->neighbours[5] =
DD_NPOLE;
13370 mpi_info->neighbours[6] =
DD_NPOLE;
13371 mpi_info->neighbours[7] = mpi_info->
rank + 1;
13373 }
else if (mpi_info->
rank == 0) {
13375 mpi_info->neighbours[0] =
13377 mpi_info->neighbours[1] =
13379 mpi_info->neighbours[2] =
DD_NPOLE;
13382 mpi_info->neighbours[4] =
13384 mpi_info->neighbours[5] =
DD_NPOLE;
13386 mpi_info->neighbours[6] =
DD_NPOLE;
13387 mpi_info->neighbours[7] = mpi_info->
rank + 1;
13391 mpi_info->neighbours[0] =
13393 mpi_info->neighbours[1] =
DD_SPOLE;
13394 mpi_info->neighbours[2] =
13398 mpi_info->neighbours[4] =
DD_SPOLE;
13399 mpi_info->neighbours[5] =
13402 mpi_info->neighbours[6] = mpi_info->
rank - 1;
13403 mpi_info->neighbours[7] =
DD_SPOLE;
13408 mpi_info->neighbours[1] =
13410 mpi_info->neighbours[2] =
DD_NPOLE;
13413 mpi_info->neighbours[4] =
13415 mpi_info->neighbours[5] =
DD_NPOLE;
13417 mpi_info->neighbours[6] =
DD_NPOLE;
13418 mpi_info->neighbours[7] = mpi_info->
rank + 1;
13423 mpi_info->neighbours[1] =
DD_SPOLE;
13424 mpi_info->neighbours[2] =
13428 mpi_info->neighbours[4] =
DD_SPOLE;
13429 mpi_info->neighbours[5] =
13432 mpi_info->neighbours[6] = mpi_info->
rank - 1;
13433 mpi_info->neighbours[7] =
DD_SPOLE;
13437 mpi_info->neighbours[0] =
13439 mpi_info->neighbours[1] =
13441 mpi_info->neighbours[2] =
13445 mpi_info->neighbours[4] =
13447 mpi_info->neighbours[5] =
13450 mpi_info->neighbours[6] = mpi_info->
rank - 1;
13451 mpi_info->neighbours[7] = mpi_info->
rank + 1;
13453 }
else if (mpi_info->
rank + 1 >
13457 mpi_info->neighbours[1] =
13459 mpi_info->neighbours[2] =
13462 mpi_info->neighbours[3] =
13465 mpi_info->neighbours[4] =
13468 mpi_info->neighbours[5] =
13471 mpi_info->neighbours[6] = mpi_info->
rank - 1;
13472 mpi_info->neighbours[7] = mpi_info->
rank + 1;
13484 mpi_info->neighbours[6] = mpi_info->
rank - 1;
13485 mpi_info->neighbours[7] = mpi_info->
rank + 1;
13494void dd_communicate_particles(
13497 MPI_Datatype MPI_Particle,
13514 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
13518 MPI_Request requests_snd_nbr[8] =
13519 { MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL,
13520 MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL
13522 MPI_Request requests_rcv_nbr[8] =
13523 { MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL,
13524 MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL
13526 MPI_Request requests_snd_part[8] =
13527 { MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL,
13528 MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL
13530 MPI_Request requests_rcv_part[8] =
13531 { MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL,
13532 MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL
13534 MPI_Status states[8];
13537 for (
int idest = 0; idest < nneighbours; idest++) {
13540 if (neighbours[idest] < 0)
13546 for (
int ip = 0; ip < *nparticles; ip++)
13549 nbs[idest] = help_sum;
13553 MPI_Isend(&nbs[idest], 1, MPI_INT,
13554 neighbours[idest], 0, MPI_COMM_WORLD, &requests_snd_nbr[idest]);
13557 if (nbs[idest] == 0)
13566 for (
int ip = 0; ip < *nparticles; ip++) {
13567 if ((
int) particles[ip].q[ctl.
qnt_destination] == neighbours[idest]) {
13568 memcpy(&send_buffers[idest][ibs], &particles[ip],
sizeof(
particle_t));
13572 if (ibs == nbs[idest])
13579 MPI_Isend(send_buffers[idest], nbs[idest], MPI_Particle,
13580 neighbours[idest], 1, MPI_COMM_WORLD,
13581 &requests_snd_part[idest]);
13587 for (
int isourc = 0; isourc < nneighbours; isourc++) {
13590 if (neighbours[isourc] < 0) {
13591 requests_rcv_nbr[isourc] = MPI_REQUEST_NULL;
13596 MPI_Irecv(&nbr[isourc], 1, MPI_INT, neighbours[isourc], 0, MPI_COMM_WORLD,
13597 &requests_rcv_nbr[isourc]);
13602 MPI_Waitall(nneighbours, requests_rcv_nbr, states);
13605 for (
int isourc = 0; isourc < nneighbours; isourc++) {
13608 if ((neighbours[isourc] < 0) || (nbr[isourc] == 0)) {
13609 requests_rcv_part[isourc] = MPI_REQUEST_NULL;
13616 MPI_Irecv(recieve_buffers[isourc], nbr[isourc], MPI_Particle,
13617 neighbours[isourc], 1, MPI_COMM_WORLD,
13618 &requests_rcv_part[isourc]);
13623 MPI_Waitall(nneighbours, requests_rcv_part, states);
13631 for (
int isourc = 0; isourc < nneighbours; isourc++) {
13634 if (neighbours[isourc] < 0)
13638 for (
int ip = 0; ip < nbr[isourc]; ip++) {
13639 memcpy(&particles[ip + api], &recieve_buffers[isourc][ip],
13645 api += nbr[isourc];
13654 MPI_Waitall(nneighbours, requests_snd_part, states);
13655 MPI_Waitall(nneighbours, requests_snd_nbr, states);
13658 for (
int i = 0; i < nneighbours; i++) {
13660 if ((send_buffers[i] != NULL) && (nbs[i] != 0)) {
13661 free(send_buffers[i]);
13662 send_buffers[i] = NULL;
13665 if ((recieve_buffers[i] != NULL) && (nbr[i] != 0)) {
13666 free(recieve_buffers[i]);
13667 recieve_buffers[i] = NULL;
13681void dd_assign_rect_subdomains_atm(
13688 SELECT_TIMER(
"DD_ASSIGN_RECT_SUBDOMAINS",
"DD", NVTX_GPU);
13692#pragma acc enter data create(mpi_info)
13693#pragma acc update device(mpi_info->rank)
13694#pragma acc data present(atm, ctl, mpi_info, met)
13695#pragma acc parallel loop independent gang vector
13697 for (
int ip = 0; ip < atm->
np; ip++) {
13699 double lont = atm->
lon[ip];
13715#pragma acc exit data delete(mpi_info)
13721#pragma acc enter data create(mpi_info)
13722#pragma acc update device(mpi_info->neighbours[:DD_NNMAX], mpi_info->rank, mpi_info->size)
13723#pragma acc data present(atm, met, ctl, mpi_info)
13724#pragma acc parallel loop independent gang vector
13726 for (
int ip = 0; ip < atm->
np; ip++) {
13732 double lont = atm->
lon[ip];
13733 double latt = atm->
lat[ip];
13749 bound = (lont - lon_max > 90) ? 1 : 0;
13751 bound = (lon_min - lont > 90) ? 1 : 0;
13754 if ((lont >= lon_max) && (latt >= lat_max)) {
13757 }
else if ((lont >= lon_max) && (latt <= lat_min)) {
13760 }
else if ((lont <= lon_min) && (latt >= lat_max)) {
13763 }
else if ((lont <= lon_min) && (latt <= lat_min)) {
13766 }
else if (lont >= lon_max) {
13769 }
else if (lont <= lon_min) {
13772 }
else if (latt <= lat_min) {
13775 }
else if (latt >= lat_max) {
13783 if ((lont >= lon_max) && (latt >= lat_max)) {
13786 }
else if ((lont >= lon_max) && (latt <= lat_min)) {
13789 }
else if ((lont <= lon_min) && (latt >= lat_max)) {
13792 }
else if ((lont <= lon_min) && (latt <= lat_min)) {
13795 }
else if (lont >= lon_max) {
13798 }
else if (lont <= lon_min) {
13801 }
else if (latt <= lat_min) {
13804 }
else if (latt >= lat_max) {
13814#pragma acc exit data delete(mpi_info)
13828 int *dd_init_flg) {
13831 if (mpi_info->
size !=
13833 ERRMSG(
"The number of tasks and subdomains is not identical.");
13836 dd_register_MPI_type_particle(&mpi_info->MPI_Particle);
13839 dd_get_rect_neighbour(*ctl, mpi_info);
13842 dd_assign_rect_subdomains_atm(atm, *met, ctl, mpi_info, 1);
13859 int nparticles = 0;
13864 dd_assign_rect_subdomains_atm(atm, *met, ctl, mpi_info, 0);
13867 dd_sort(ctl, *met, atm, &nparticles, &mpi_info->
rank);
13875 dd_communicate_particles(particles, &nparticles, mpi_info->MPI_Particle,
13904 const int np = atm->
np;
13905 double *restrict
const a = (
double *) malloc((
size_t) np *
sizeof(double));
13906 int *restrict
const p = (
int *) malloc((
size_t) np *
sizeof(int));
13907 double amax = (met0->
nx * met0->
ny + met0->
ny) * met0->
np + met0->
np;
13910#pragma acc enter data create(a[0:np],p[0:np],amax, rank)
13911#pragma acc update device(rank, amax)
13912#pragma acc data present(ctl,met0,atm,a,p,amax,rank)
13917#pragma acc parallel loop independent gang vector
13919#pragma omp parallel for default(shared)
13921 for (
int ip = 0; ip < np; ip++) {
13939#pragma acc host_data use_device(a,p)
13941 thrustSortWrapper(a, np, p);
13944 ERRMSG(
"GSL sort fallback not available on GPU, use THRUST!");
13946 gsl_sort_index((
size_t *) p, a, 1, (
size_t) np);
13954 for (
int iq = 0; iq < ctl->
nq; iq++)
13960#pragma acc parallel loop reduction(+:npt) present(atm, rank, ctl)
13962 for (
int ip = 0; ip < np; ip++)
13968 int nparticlest = 0;
13970#pragma acc parallel loop reduction(+:nparticlest) present(atm, rank, ctl)
13972 for (
int ip = npt; ip < np; ip++)
13978 *nparticles = nparticlest;
13981#pragma acc update device(atm->np)
13986 (
"Number of particles to send and recieve to small. Increase DD_NPART!");
13990#pragma acc exit data delete(a,p,amax, rank)
void read_met_geopot(const ctl_t *ctl, met_t *met)
Calculates geopotential heights from meteorological data.
void read_met_nc_surface(const int ncid, const ctl_t *ctl, met_t *met)
Reads surface meteorological data from a netCDF file and stores it in the meteorological data structu...
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.
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 mptrac_alloc(ctl_t **ctl, cache_t **cache, clim_t **clim, met_t **met0, met_t **met1, atm_t **atm)
Allocates and initializes memory resources for MPTRAC.
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.
int mptrac_read_met(const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met)
Reads meteorological data from a file, supporting multiple formats and MPI broadcasting.
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_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.
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, float dest[EX][EY], const float scl, const int init)
Reads a 2-dimensional meteorological variable from a NetCDF file.
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 mptrac_get_met(ctl_t *ctl, clim_t *clim, const double t, met_t **met0, met_t **met1)
Retrieves meteorological data for the specified time.
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 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)
Reads global meteorological information from a grib file.
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 intpol_met_4d_coord(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 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 intpol_met_space_3d_ml(const met_t *met, float zs[EX][EY][EP], float array[EX][EY][EP], const double z, const double lon, const double lat, double *var)
Interpolates meteorological data in 3D space.
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(const char *filename, const int ncid, const ctl_t *ctl, met_t *met)
Reads meteorological grid information from a NetCDF file.
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.
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 intpol_met_time_3d_ml(const met_t *met0, float zs0[EX][EY][EP], float array0[EX][EY][EP], const met_t *met1, float zs1[EX][EY][EP], float array1[EX][EY][EP], const double ts, const double p, const double lon, const double lat, double *var)
Interpolates meteorological data in both space and time.
void module_convection(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Performs convective mixing of atmospheric particles.
void read_kernel(const char *filename, double kz[EP], double kw[EP], int *nk)
Reads kernel function data from a file and populates the provided arrays.
void module_bound_cond(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Apply boundary conditions to particles based on meteorological and climatological data.
double scan_ctl(const char *filename, int argc, char *argv[], const char *varname, const int arridx, const char *defvalue, char *value)
Scans a control file or command-line arguments for a specified variable.
void module_advect_init(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Initializes the advection module by setting up pressure fields.
void module_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).
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, float dest[EX][EY][EP], const float scl)
Reads a 3-dimensional meteorological variable from a NetCDF file.
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 mptrac_free(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Frees memory resources allocated for MPTRAC.
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_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.
int read_met_nc(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a NetCDF file and processes it.
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 mptrac_run_timestep(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t **met0, met_t **met1, atm_t *atm, double t)
Executes a single timestep of the MPTRAC model simulation.
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.
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 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.
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.
void read_met_nc_levels(const int ncid, const ctl_t *ctl, met_t *met)
Reads meteorological variables at different vertical levels from a NetCDF file.
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.
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
Constants indicating the North pole [-].
#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.
int read_met_nc_dd(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a NetCDF file and processes it.
#define MOLEC_DENS(p, t)
Calculate the density of a gas molecule.
int read_met_nc_3d_dd(const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const ctl_t *ctl, const met_t *met, float dest[EX][EY][EP], const float scl)
Reads a 3-dimensional meteorological variable from a NetCDF file.
#define DD_SPOLE
Constants 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 EP_GLOB
Maximum number of pressure levels for meteo data.
#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 P(z)
Compute pressure at given altitude.
#define LV
Latent heat of vaporization of water [J/kg].
#define EY_GLOB
Maximum number of global latitudes for meteo data.
#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 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.
#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.
void read_met_nc_grid_dd(const char *filename, const int ncid, const ctl_t *ctl, met_t *met)
Reads meteorological grid data from NetCDF files with domain decomposition.
#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.
#define SET_ATM(qnt, val)
Set atmospheric quantity value.
#define CTS
Maximum number of data points of climatological time series.
void read_met_nc_surface_dd(const int ncid, const ctl_t *ctl, met_t *met)
Reads and processes surface meteorological data from NetCDF files with domain decomposition.
#define ECC_READ_2D(variable, target, scaling_factor, found_flag)
Writes 2-D data from a grib message into the meteo struct.
#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 NC_INQ_DIM(dimname, ptr, min, max)
Inquire the length of a dimension in a NetCDF file.
#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.
#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.
#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.
int read_met_nc_2d_dd(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, float dest[EX][EY], const float scl, const int init)
Reads a 2-dimensional meteorological variable from a NetCDF file.
void read_met_nc_levels_dd(const int ncid, const ctl_t *ctl, met_t *met)
Reads and processes meteorological level data from NetCDF files with domain decomposition.
#define ARRHENIUS(a, b, t)
Calculate the Arrhenius rate constant.
#define EX_GLOB
Maximum number of global longitudes for meteo data.
#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 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.
#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 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.
#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 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.
#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
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.
char clim_o1d_filename[LEN]
Filename of O(1D) climatology.
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_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
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 forvelocity 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
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
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.
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].
double subdomain_lon_max
Rectangular grid limit of subdomain.
float cape[EX][EY]
Convective available potential energy [J/kg].
float w[EX][EY][EP]
Vertical velocity [hPa/s].
double subdomain_lat_min
Rectangular grid limit of subdomain.
float pct[EX][EY]
Cloud top pressure [hPa].
double hybrid[EP]
Model hybrid levels.
int nx
Number of longitudes.
double subdomain_lon_min
Rectangular grid limit of subdomain.
int ny_glob
Global sizes of meteo data.
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].
size_t subdomain_start[4]
Hyperslab start and count for subdomain.
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].
int nx_glob
Global sizes of meteo data.
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].
size_t subdomain_count[4]
Hyperslab start and count for subdomain.
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 subdomain_lat_max
Rectangular grid limit of subdomain.
float cl[EX][EY]
Total column cloud water [kg/m^2].
float nss[EX][EY]
Northward turbulent surface stress [N/m^2].
int np_glob
Global sizes of meteo data.
float pl[EX][EY][EP]
Pressure on model levels [hPa].
float plfc[EX][EY]
Pressure at level of free convection (LFC) [hPa].
double lat[EY]
Latitudes [deg].
float swc[EX][EY][EP]
Cloud snow water content [kg/kg].
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).