35static uint64_t rng_ctr;
39static curandGenerator_t rng_curand;
49#define CHUNK_SIZE 2147483647
52 MPI_Bcast(&N, 1, MPI_UINT64_T, 0, MPI_COMM_WORLD);
55 const size_t num_chunks = (N + CHUNK_SIZE - 1) / CHUNK_SIZE;
58 for (
size_t i = 0; i < num_chunks; i++) {
61 const size_t start = i * CHUNK_SIZE;
62 const size_t end = (start + CHUNK_SIZE > N) ? N : start + CHUNK_SIZE;
63 const size_t chunk_size = end - start;
66 MPI_Bcast((
char *) data + start, (
int) chunk_size, MPI_BYTE, 0,
80 const double radius = sqrt(
DOTP(x, x));
82 *lat =
RAD2DEG(asin(x[2] / radius));
83 *lon =
RAD2DEG(atan2(x[1], x[0]));
98 const double sza_thresh =
DEG2RAD(85.), csza_thresh = cos(sza_thresh);
101 const double oh =
clim_zm(&clim->
oh, t, lat, p);
108 const double csza =
cos_sza(t, lon, lat);
109 const double denom = (csza >= csza_thresh) ? csza : csza_thresh;
120 const double sza_thresh =
DEG2RAD(85.), csza_thresh = cos(sza_thresh);
123 for (
int it = 0; it < clim->
oh.
ntime; it++)
124 for (
int iz = 0; iz < clim->
oh.
np; iz++)
125 for (
int iy = 0; iy < clim->
oh.
nlat; iy++) {
132 for (
double lon = -180; lon < 180; lon += 1.0) {
135 const double denom = (csza >= csza_thresh) ? csza : csza_thresh;
141 clim->
oh.
vmr[it][iz][iy] /= (sum / (double) n);
156 if (p < photo->p[photo->
np - 1])
157 p_help = photo->
p[photo->
np - 1];
158 else if (p > photo->
p[0])
159 p_help = photo->
p[0];
162 double sza_help = sza;
163 if (sza < photo->sza[0])
164 sza_help = photo->
sza[0];
165 else if (sza > photo->
sza[photo->
nsza - 1])
166 sza_help = photo->
sza[photo->
nsza - 1];
169 double o3c_help = o3c;
170 if (o3c < photo->o3c[0])
171 o3c_help = photo->
o3c[0];
172 else if (o3c > photo->
o3c[photo->
no3c - 1])
173 o3c_help = photo->
o3c[photo->
no3c - 1];
181 const double aux00 =
LIN(photo->
p[ip], rate[ip][isza][io3c],
182 photo->
p[ip + 1], rate[ip + 1][isza][io3c],
184 const double aux01 =
LIN(photo->
p[ip], rate[ip][isza][io3c + 1],
185 photo->
p[ip + 1], rate[ip + 1][isza][io3c + 1],
187 const double aux10 =
LIN(photo->
p[ip], rate[ip][isza + 1][io3c],
188 photo->
p[ip + 1], rate[ip + 1][isza + 1][io3c],
190 const double aux11 =
LIN(photo->
p[ip], rate[ip][isza + 1][io3c + 1],
191 photo->
p[ip + 1], rate[ip + 1][isza + 1][io3c + 1],
194 LIN(photo->
o3c[io3c], aux00, photo->
o3c[io3c + 1], aux01, o3c_help);
196 LIN(photo->
o3c[io3c], aux10, photo->
o3c[io3c + 1], aux11, o3c_help);
198 LIN(photo->
sza[isza], aux0, photo->
sza[isza + 1], aux1, sza_help);
199 return MAX(aux, 0.0);
210 double sec =
FMOD(t, 365.25 * 86400.);
212 sec += 365.25 * 86400.;
220 clim->
tropo[isec][ilat],
222 clim->
tropo[isec][ilat + 1], lat);
224 clim->
tropo[isec + 1][ilat],
226 clim->
tropo[isec + 1][ilat + 1], lat);
236 LOG(1,
"Initialize tropopause data...");
240 double tropo_time[12] = {
241 1209600.00, 3888000.00, 6393600.00,
242 9072000.00, 11664000.00, 14342400.00,
243 16934400.00, 19612800.00, 22291200.00,
244 24883200.00, 27561600.00, 30153600.00
250 const double tropo_lat[73] = {
251 -90, -87.5, -85, -82.5, -80, -77.5, -75, -72.5, -70, -67.5,
252 -65, -62.5, -60, -57.5, -55, -52.5, -50, -47.5, -45, -42.5,
253 -40, -37.5, -35, -32.5, -30, -27.5, -25, -22.5, -20, -17.5,
254 -15, -12.5, -10, -7.5, -5, -2.5, 0, 2.5, 5, 7.5, 10, 12.5,
255 15, 17.5, 20, 22.5, 25, 27.5, 30, 32.5, 35, 37.5, 40, 42.5,
256 45, 47.5, 50, 52.5, 55, 57.5, 60, 62.5, 65, 67.5, 70, 72.5,
257 75, 77.5, 80, 82.5, 85, 87.5, 90
262 const double tropo[12][73] = {
263 {324.1, 325.6, 325, 324.3, 322.5, 319.7, 314, 307.2, 301.8, 299.6,
264 297.1, 292.2, 285.6, 276.1, 264, 248.9, 231.9, 213.5, 194.4,
265 175.3, 157, 140.4, 126.7, 116.3, 109.5, 105.4, 103, 101.4, 100.4,
266 99.69, 99.19, 98.84, 98.56, 98.39, 98.39, 98.42, 98.44, 98.54,
267 98.68, 98.81, 98.89, 98.96, 99.12, 99.65, 101.4, 105.4, 113.5, 128,
268 152.1, 184.7, 214, 234.1, 247.3, 255.8, 262.6, 267.7, 271.7, 275,
269 277.2, 279, 280.1, 280.4, 280.6, 280.1, 279.3, 278.3, 276.8, 275.8,
270 275.3, 275.6, 275.4, 274.1, 273.5},
271 {337.3, 338.7, 337.8, 336.4, 333, 328.8, 321.1, 312.6, 306.6, 303.7,
272 300.2, 293.8, 285.4, 273.8, 259.6, 242.7, 224.4, 205.2, 186, 167.5,
273 150.3, 135, 122.8, 113.9, 108.2, 104.7, 102.5, 101.1, 100.2, 99.42,
274 98.88, 98.52, 98.25, 98.09, 98.07, 98.1, 98.12, 98.2, 98.25, 98.27,
275 98.26, 98.27, 98.36, 98.79, 100.2, 104.2, 113.7, 131.2, 159.5, 193,
276 220.4, 238.1, 250.2, 258.1, 264.7, 269.7, 273.7, 277.3, 280.2, 282.8,
277 284.9, 286.5, 288.1, 288.8, 289, 288.5, 287.2, 286.3, 286.1, 287.2,
278 287.5, 286.2, 285.8},
279 {335, 336, 335.7, 335.1, 332.3, 328.1, 320.6, 311.8, 305.1, 301.9,
280 297.6, 290, 280.4, 268.3, 254.6, 239.6, 223.9, 207.9, 192.2, 176.9,
281 161.7, 146.4, 132.2, 120.6, 112.3, 107.2, 104.3, 102.4, 101.3,
282 100.4, 99.86, 99.47, 99.16, 98.97, 98.94, 98.97, 99, 99.09, 99.2,
283 99.31, 99.35, 99.41, 99.51, 99.86, 101.1, 104.9, 114.3, 131, 156.8,
284 186.3, 209.3, 224.6, 236.8, 246.3, 254.9, 262.3, 268.8, 274.8,
285 279.9, 284.6, 288.6, 291.6, 294.9, 297.5, 299.8, 301.8, 303.1,
286 304.3, 304.9, 306, 306.6, 306.2, 306},
287 {306.2, 306.7, 305.7, 307.1, 307.3, 306.4, 301.8, 296.2, 292.4,
288 290.3, 287.1, 280.9, 273.4, 264.3, 254.1, 242.8, 231, 219, 207.2,
289 195.5, 183.3, 169.7, 154.7, 138.7, 124.1, 113.6, 107.8, 104.7,
290 102.8, 101.7, 100.9, 100.4, 100, 99.79, 99.7, 99.66, 99.68, 99.79,
291 99.94, 100.2, 100.5, 100.9, 101.4, 102.1, 103.4, 107, 115.2, 129.1,
292 148.7, 171, 190.8, 205.6, 218.4, 229.4, 239.6, 248.6, 256.5,
293 263.7, 270.3, 276.6, 282.6, 288.1, 294.5, 300.4, 306.3, 311.4,
294 315.1, 318.3, 320.3, 322.2, 322.8, 321.5, 321.1},
295 {266.5, 264.9, 260.8, 261, 262, 263, 261.3, 259.7, 259.2, 259.8,
296 260.1, 258.6, 256.7, 253.6, 249.5, 243.9, 237.4, 230, 222.1, 213.9,
297 205, 194.4, 180.4, 161.8, 140.7, 122.9, 112.1, 106.7, 104.1, 102.7,
298 101.8, 101.4, 101.1, 101, 101, 101, 101.1, 101.2, 101.5, 101.9,
299 102.4, 103, 103.8, 104.9, 106.8, 110.1, 115.6, 124, 135.2, 148.9,
300 165.2, 181.3, 198, 211.8, 223.5, 233.8, 242.9, 251.5, 259, 266.2,
301 273.1, 279.2, 286.2, 292.8, 299.6, 306, 311.1, 315.5, 318.8, 322.6,
302 325.3, 325.8, 325.8},
303 {220.1, 218.1, 210.8, 207.2, 207.6, 210.5, 211.4, 213.5, 217.3,
304 222.4, 227.9, 232.8, 237.4, 240.8, 242.8, 243, 241.5, 238.6, 234.2,
305 228.5, 221, 210.7, 195.1, 172.9, 147.8, 127.6, 115.6, 109.9, 107.1,
306 105.7, 105, 104.8, 104.8, 104.9, 105, 105.1, 105.3, 105.5, 105.8,
307 106.4, 107, 107.6, 108.1, 108.8, 110, 111.8, 114.2, 117.4, 121.6,
308 127.9, 137.3, 151.2, 169.5, 189, 205.8, 218.9, 229.1, 237.8, 245,
309 251.5, 257.1, 262.3, 268.2, 274, 280.4, 286.7, 292.4, 297.9, 302.9,
310 308.5, 312.2, 313.1, 313.3},
311 {187.4, 184.5, 173.3, 166.1, 165.4, 167.8, 169.6, 173.6, 179.6,
312 187.9, 198.9, 210, 220.5, 229.2, 235.7, 239.9, 241.8, 241.6, 239.6,
313 235.8, 229.4, 218.6, 200.9, 175.9, 149.4, 129.4, 118.3, 113.1,
314 110.8, 109.7, 109.3, 109.4, 109.7, 110, 110.2, 110.4, 110.5, 110.7,
315 111, 111.4, 111.8, 112.1, 112.3, 112.7, 113.2, 113.9, 115, 116.4,
316 117.9, 120.4, 124.1, 130.9, 142.2, 159.6, 179.6, 198.5, 212.9,
317 224.2, 232.7, 239.1, 243.8, 247.7, 252.4, 257.3, 263.2, 269.5,
318 275.4, 281.1, 286.3, 292, 296.3, 298.2, 298.8},
319 {166, 166.4, 155.7, 148.3, 147.1, 149, 152.1, 157, 163.6, 172.4,
320 185.3, 199.2, 212.6, 224, 233.2, 239.6, 243.3, 244.6, 243.6, 240.3,
321 233.9, 222.6, 203.7, 177, 149.5, 129.7, 119, 114, 111.7, 110.7,
322 110.3, 110.3, 110.6, 110.9, 111.1, 111.3, 111.5, 111.6, 111.9,
323 112.2, 112.5, 112.6, 112.8, 113, 113.4, 114, 115.1, 116.5, 118.3,
324 120.9, 124.4, 130.2, 139.4, 154.6, 173.8, 193.1, 208.1, 220.4,
325 230.1, 238.2, 244.7, 249.5, 254.5, 259.3, 264.5, 269.4, 273.7,
326 278.2, 282.6, 287.4, 290.9, 292.5, 293},
327 {171.9, 172.8, 166.2, 162.3, 161.4, 162.5, 165.2, 169.6, 175.3,
328 183.1, 193.8, 205.9, 218.3, 229.6, 238.5, 244.3, 246.9, 246.7,
329 243.8, 238.4, 230.2, 217.9, 199.6, 174.9, 148.9, 129.8, 119.5,
330 114.8, 112.3, 110.9, 110.3, 110.1, 110.2, 110.3, 110.4, 110.5,
331 110.6, 110.8, 111, 111.4, 111.8, 112, 112.2, 112.4, 112.9, 113.6,
332 114.7, 116.3, 118.4, 121.9, 127.1, 136.1, 149.8, 168.4, 186.9,
333 203.3, 217, 229.1, 238.7, 247, 254, 259.3, 264.3, 268.3, 272.5,
334 276.6, 280.4, 284.4, 288.4, 293.3, 297.2, 298.7, 299.1},
335 {191.6, 192.2, 189, 188.1, 190.2, 193.7, 197.8, 202.9, 208.5,
336 215.6, 224.2, 233.1, 241.2, 247.3, 250.8, 251.3, 248.9, 244.2,
337 237.3, 228.4, 217.2, 202.9, 184.5, 162.5, 140.7, 124.8, 116.2,
338 111.8, 109.4, 107.9, 107, 106.7, 106.6, 106.6, 106.7, 106.7,
339 106.8, 107, 107.4, 108, 108.7, 109.3, 109.8, 110.4, 111.2,
340 112.4, 114.2, 116.9, 121.1, 127.9, 139.3, 155.2, 173.6, 190.7,
341 206.1, 220.1, 232.3, 243, 251.8, 259.2, 265.7, 270.6, 275.3,
342 279.3, 283.3, 286.9, 289.7, 292.8, 296.1, 300.5, 303.9, 304.8,
344 {241.5, 239.6, 236.8, 237.4, 239.4, 242.3, 244.2, 246.4, 249.2,
345 253.6, 258.6, 262.7, 264.8, 264.2, 260.6, 254.1, 245.5, 235.3,
346 223.9, 211.7, 198.3, 183.1, 165.6, 147.1, 130.5, 118.7, 111.9,
347 108.1, 105.8, 104.3, 103.4, 102.8, 102.5, 102.4, 102.5, 102.5,
348 102.5, 102.7, 103.1, 103.8, 104.6, 105.4, 106.1, 107, 108.2,
349 109.9, 112.8, 117.5, 126, 140.4, 161, 181.9, 201.2, 216.8, 230.4,
350 241.8, 251.4, 259.9, 266.9, 272.8, 277.4, 280.4, 282.9, 284.6,
351 286.1, 287.4, 288.3, 289.5, 290.9, 294.2, 296.9, 297.5, 297.6},
352 {301.2, 300.3, 296.6, 295.4, 295, 294.3, 291.2, 287.4, 284.9, 284.7,
353 284.1, 281.5, 277.1, 270.4, 261.7, 250.6, 237.6, 223.1, 207.9, 192,
354 175.8, 158.8, 142.1, 127.6, 116.8, 109.9, 106, 103.6, 102.1, 101.1,
355 100.4, 99.96, 99.6, 99.37, 99.32, 99.32, 99.31, 99.46, 99.77, 100.2,
356 100.7, 101.3, 101.8, 102.7, 104.1, 106.8, 111.9, 121, 136.7, 160,
357 186.9, 209.9, 228.1, 241.2, 251.5, 259.5, 265.7, 270.9, 274.8, 278,
358 280.3, 281.8, 283, 283.3, 283.7, 283.8, 283, 282.2, 281.2, 281.4,
361 memcpy(clim->
tropo, tropo,
sizeof(clim->
tropo));
364 double tropomin = 1e99, tropomax = -1e99;
366 for (
int iy = 0; iy < clim->
tropo_nlat; iy++) {
367 tropomin =
MIN(tropomin, clim->
tropo[it][iy]);
368 tropomax =
MAX(tropomax, clim->
tropo[it][iy]);
373 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
377 LOG(2,
"Latitudes: %g, %g ... %g deg",
380 LOG(2,
"Tropopause altitude range: %g ... %g hPa",
Z(tropomax),
382 LOG(2,
"Tropopause pressure range: %g ... %g hPa", tropomin, tropomax);
392 if (t <= ts->time[0])
399 ts->
time[idx + 1], ts->
vmr[idx + 1], t);
412 double sec =
FMOD(t, 365.25 * 86400.);
414 sec += 365.25 * 86400.;
418 if (p < zm->p[zm->
np - 1])
419 p_help = zm->
p[zm->
np - 1];
420 else if (p > zm->
p[0])
424 double lat_help = lat;
425 if (lat < zm->lat[0])
426 lat_help = zm->
lat[0];
427 else if (lat > zm->
lat[zm->
nlat - 1])
428 lat_help = zm->
lat[zm->
nlat - 1];
436 const double aux00 =
LIN(zm->
p[ip], zm->
vmr[isec][ip][ilat],
437 zm->
p[ip + 1], zm->
vmr[isec][ip + 1][ilat],
439 const double aux01 =
LIN(zm->
p[ip], zm->
vmr[isec][ip][ilat + 1],
440 zm->
p[ip + 1], zm->
vmr[isec][ip + 1][ilat + 1],
442 const double aux10 =
LIN(zm->
p[ip], zm->
vmr[isec + 1][ip][ilat],
443 zm->
p[ip + 1], zm->
vmr[isec + 1][ip + 1][ilat],
445 const double aux11 =
LIN(zm->
p[ip], zm->
vmr[isec + 1][ip][ilat + 1],
446 zm->
p[ip + 1], zm->
vmr[isec + 1][ip + 1][ilat + 1],
449 LIN(zm->
lat[ilat], aux00, zm->
lat[ilat + 1], aux01, lat_help);
451 LIN(zm->
lat[ilat], aux10, zm->
lat[ilat + 1], aux11, lat_help);
452 const double aux =
LIN(zm->
time[isec], aux0, zm->
time[isec + 1], aux1, sec);
453 return MAX(aux, 0.0);
467 const int decompress,
471 const size_t nxy = nx * ny;
472 double lon[
EX], lat[
EY];
473 for (
size_t ix = 0; ix < nx; ix++)
474 lon[ix] = 360. * (
double) ix / ((double) nx - 1.);
475 for (
size_t iy = 0; iy < ny; iy++)
476 lat[iy] = 90. - 180. * (
double) iy / ((double) ny - 1.);
479 const char domain[] =
"[0.0, 360.0]x[-90.0, 90.0]";
483 cms_param_t *cms_param
484 = cms_set_parameters(nx, ny, max_level_grid, Nd0_x, Nd0_y, domain);
487 double cr = 0, t_coars = 0, t_eval = 0;
493 for (
size_t ip = 0; ip < np; ip++) {
496 cms_module_t *cms_ptr = cms_init(cms_param);
501 cms_sol = cms_read_zstd_sol(cms_ptr, inout);
503 cms_sol = cms_read_sol(cms_ptr, inout);
506#pragma omp parallel for collapse(2) default(shared)
507 for (
size_t ix = 0; ix < nx; ix++)
508 for (
size_t iy = 0; iy < ny; iy++) {
510 const double x[] = { lon[ix], lat[iy] };
511 cms_eval(cms_ptr, cms_sol, x, &val);
512 array[
ARRAY_3D(ix, iy, ny, ip, np)] = (float) val;
516 cr += 1.0 / cms_compression_rate(cms_ptr, cms_sol);
519 cms_delete_sol(cms_sol);
520 cms_delete_module(cms_ptr);
524 LOG(2,
"Read 3-D variable: %s (CMS, RATIO= %g)", varname,
532 cms_module_t *cms_ptr[
EP];
533 cms_sol_t *cms_sol[
EP];
537 ? (size_t) omp_get_max_threads()
539 for (
size_t ip0 = 0; ip0 < np; ip0 += dip) {
542 double t0 = omp_get_wtime();
545#pragma omp parallel for default(shared)
546 for (
size_t ip = ip0; ip <
MIN(ip0 + dip, np); ip++) {
550 ALLOC(tmp_arr,
float,
554 for (
size_t ix = 0; ix < nx; ++ix)
555 for (
size_t iy = 0; iy < ny; ++iy)
557 array[
ARRAY_3D(ix, iy, ny, ip, np)];
560 double c_thresh_test;
561 if (strcasecmp(varname,
"Z") == 0)
563 else if (strcasecmp(varname,
"T") == 0)
565 else if (strcasecmp(varname,
"U") == 0)
567 else if (strcasecmp(varname,
"V") == 0)
569 else if (strcasecmp(varname,
"W") == 0)
571 else if (strcasecmp(varname,
"PV") == 0)
573 else if (strcasecmp(varname,
"H2O") == 0)
575 else if (strcasecmp(varname,
"O3") == 0)
577 else if (strcasecmp(varname,
"LWC") == 0)
579 else if (strcasecmp(varname,
"RWC") == 0)
581 else if (strcasecmp(varname,
"IWC") == 0)
583 else if (strcasecmp(varname,
"SWC") == 0)
585 else if (strcasecmp(varname,
"CC") == 0)
588 ERRMSG(
"Variable name unknown!");
591 cms_ptr[ip] = cms_init(cms_param);
595 cms_read_arr_new(cms_ptr[ip], tmp_arr, lon, lat,
596 nx, ny, c_thresh_test);
603 t_coars += (omp_get_wtime() - t0);
606 for (
size_t ip = ip0; ip <
MIN(ip0 + dip, np); ip++) {
609 double *tmp_cms, *tmp_org, *tmp_diff;
610 ALLOC(tmp_cms,
double,
612 ALLOC(tmp_org,
double,
614 ALLOC(tmp_diff,
double,
618 t0 = omp_get_wtime();
621#pragma omp parallel for collapse(2) default(shared)
622 for (
size_t ix = 0; ix < nx; ix++)
623 for (
size_t iy = 0; iy < ny; iy++) {
624 const size_t idx =
ARRAY_2D(ix, iy, ny);
625 const double x[] = { lon[ix], lat[iy] };
626 cms_eval(cms_ptr[ip], cms_sol[ip], x, &tmp_cms[idx]);
627 tmp_org[idx] = array[
ARRAY_3D(ix, iy, ny, ip, np)];
628 tmp_diff[idx] = tmp_cms[idx] - tmp_org[idx];
632 t_eval += (omp_get_wtime() - t0);
635 const double bias = gsl_stats_mean(tmp_diff, 1, nxy);
636 const double stddev = gsl_stats_sd_m(tmp_diff, 1, nxy, bias);
639 gsl_stats_max(tmp_org, 1, nxy) - gsl_stats_min(tmp_org, 1, nxy);
640 const double nrmse = (range > 0 ? rmse / range : NAN);
642 "cmultiscale: var= %s / lev= %lu / plev= %g / ratio= %g / rho= %g"
643 " / mean= %g / sd= %g / min= %g / max= %g / NRMSE= %g", varname,
644 ip, plev[ip], cms_compression_rate(cms_ptr[ip], cms_sol[ip]),
645 gsl_stats_correlation(tmp_cms, 1, tmp_org, 1, nxy), bias,
stddev,
646 gsl_stats_min(tmp_diff, 1, nxy), gsl_stats_max(tmp_diff, 1, nxy),
650 cr += 1.0 / cms_compression_rate(cms_ptr[ip], cms_sol[ip]);
654 cms_save_zstd_sol(cms_sol[ip], inout, 3);
656 cms_save_sol(cms_sol[ip], inout);
659 cms_delete_sol(cms_sol[ip]);
660 cms_delete_module(cms_ptr[ip]);
668 LOG(2,
"Write 3-D variable: %s"
669 " (CMS, RATIO= %g, T_COARS= %g s, T_EVAL= %g s)",
670 varname, (
double) np / cr, t_coars, t_eval);
674 cms_delete_param(cms_param);
685 const int decompress,
688 double min[
EP], max[
EP], off[
EP], scl[
EP];
690 unsigned short *sarray;
693 ALLOC(sarray,
unsigned short,
700 LOG(2,
"Read 3-D variable: %s (pck, RATIO= %g)",
701 varname, (
double)
sizeof(
float) / (
double)
sizeof(
unsigned short));
710 FREAD(sarray,
unsigned short,
715#pragma omp parallel for default(shared)
716 for (
size_t ixy = 0; ixy < nxy; ixy++)
717 for (
size_t iz = 0; iz < nz; iz++)
719 = (
float) (sarray[ixy * nz + iz] * scl[iz] + off[iz]);
726 LOG(2,
"Write 3-D variable: %s (pck, RATIO= %g)",
727 varname, (
double)
sizeof(
float) / (
double)
sizeof(
unsigned short));
730 for (
size_t iz = 0; iz < nz; iz++) {
734 for (
size_t ixy = 1; ixy < nxy; ixy++)
735 for (
size_t iz = 0; iz < nz; iz++) {
736 if (array[ixy * nz + iz] < min[iz])
737 min[iz] = array[ixy * nz + iz];
738 if (array[ixy * nz + iz] > max[iz])
739 max[iz] = array[ixy * nz + iz];
743 for (
size_t iz = 0; iz < nz; iz++) {
744 scl[iz] = (max[iz] - min[iz]) / 65533.;
749#pragma omp parallel for default(shared)
750 for (
size_t ixy = 0; ixy < nxy; ixy++)
751 for (
size_t iz = 0; iz < nz; iz++)
753 sarray[ixy * nz + iz] = (
unsigned short)
754 ((array[ixy * nz + iz] - off[iz]) / scl[iz] + .5);
756 sarray[ixy * nz + iz] = 0;
765 FWRITE(sarray,
unsigned short,
788 if ((precision > 0) == (tolerance > 0.0))
789 ERRMSG(
"Exactly one of precision or tolerance must be set for SZ3!");
791 size_t r1 = (size_t) nx, r2 = (
size_t) ny, r3 = (size_t) nz,
792 outSize = 0, total_elems = r1 * r2 * r3;
794 unsigned char *bytes = NULL;
800 FREAD(&sz3size,
size_t,
805 FREAD(bytes,
unsigned char,
809 void *outData = SZ_decompress(SZ_FLOAT, bytes, sz3size, 0, 0, r3, r2, r1);
811 ERRMSG(
"Decompression failed!");
813 memcpy(array, outData, total_elems *
sizeof(
float));
818 LOG(2,
"Read 3-D variable: %s (SZ3, PREC=%d, TOL=%g, RATIO=%g)",
819 varname, precision, tolerance,
820 (
double) (total_elems *
sizeof(
float)) / (
double) sz3size);
826 const int errBoundMode = (precision > 0) ? REL : ABS;
827 const double absBound = (errBoundMode == ABS) ? tolerance : 0.0;
828 const double relBound =
829 (errBoundMode == REL) ? pow(2.0, -(
double) precision) : 0.0;
831 bytes = SZ_compress_args(SZ_FLOAT, array, &outSize,
832 errBoundMode, absBound, relBound, 0.0,
834 if (!bytes || outSize == 0)
835 ERRMSG(
"Compression failed!");
840 FWRITE(bytes,
unsigned char,
846 LOG(2,
"Write 3-D variable: %s (SZ3, PREC=%d, TOL=%g, RATIO=%g)",
847 varname, precision, tolerance,
848 (
double) (total_elems *
sizeof(
float)) / (
double) outSize);
863 const double tolerance,
864 const int decompress,
868 const size_t snx = (size_t) nx;
869 const size_t sny = (size_t) ny;
870 const size_t snz = (size_t) nz;
871 const zfp_type type = zfp_type_float;
872 zfp_field *field = zfp_field_3d(array, type, snx, sny, snz);
875 zfp_stream *zfp = zfp_stream_open(NULL);
877 ERRMSG(
"Failed to allocate zfp structures!");
881 double actual_tol = 0;
882 if ((precision > 0 && tolerance > 0) || (precision <= 0 && tolerance <= 0)) {
883 ERRMSG(
"Exactly one of precision or tolerance must be set for zfp!");
884 }
else if (precision > 0)
886 (int) zfp_stream_set_precision(zfp, (
unsigned int) precision);
887 else if (tolerance > 0)
888 actual_tol = zfp_stream_set_accuracy(zfp, tolerance);
891 const size_t bufsize = zfp_stream_maximum_size(zfp, field);
897 bitstream *stream = stream_open(buffer, bufsize);
898 zfp_stream_set_bit_stream(zfp, stream);
899 zfp_stream_rewind(zfp);
904 FREAD(&zfpsize,
size_t,
907 if (zfpsize > bufsize)
908 ERRMSG(
"Compressed data size exceeds allocated buffer!");
909 FREAD(buffer,
unsigned char,
912 if (!zfp_decompress(zfp, field))
913 ERRMSG(
"Decompression failed!");
915 ((double) (snx * sny * snz *
sizeof(
float))) / (double) zfpsize;
916 const double bpv = (8.0 * (double) zfpsize) / (double) (snx * sny * snz);
918 "Read 3-D variable: %s (ZFP, PREC= %d, TOL= %g, RATIO= %g, BPV= %g)",
919 varname, actual_prec, actual_tol, cr, bpv);
924 zfpsize = zfp_compress(zfp, field);
926 ERRMSG(
"Compression failed!");
931 FWRITE(buffer,
unsigned char,
936 ((double) (snx * sny * snz *
sizeof(
float))) / (double) zfpsize;
937 const double bpv = (8.0 * (double) zfpsize) / (double) (snx * sny * snz);
939 "Write 3-D variable: %s (ZFP, PREC= %d, TOL= %g, RATIO= %g, BPV= %g)",
940 varname, actual_prec, actual_tol, cr, bpv);
944 zfp_field_free(field);
945 stream_close(stream);
946 zfp_stream_close(zfp);
958 const int decompress,
963 const size_t uncomprLen = n *
sizeof(float);
964 size_t compsize, comprLen = ZSTD_compressBound(uncomprLen);
967 char *compr = calloc(comprLen, 1);
969 ERRMSG(
"Memory allocation failed!");
970 char *uncompr = (
char *) array;
974 FREAD(&comprLen,
size_t,
977 FREAD(compr,
unsigned char,
980 compsize = ZSTD_decompress(uncompr, uncomprLen, compr, comprLen);
981 if (ZSTD_isError(compsize) || compsize != uncomprLen)
982 ERRMSG(
"Decompression failed or size mismatch!");
983 LOG(2,
"Read 3-D variable: %s (ZSTD, RATIO= %g)",
984 varname, ((
double) uncomprLen) / (
double) comprLen);
989 compsize = ZSTD_compress(compr, comprLen, uncompr, uncomprLen, level);
990 if (ZSTD_isError(compsize)) {
991 ERRMSG(
"Compression failed!");
996 FWRITE(compr,
unsigned char,
1000 LOG(2,
"Write 3-D variable: %s (ZSTD, RATIO= %g)",
1001 varname, ((
double) uncomprLen) / (
double) compsize);
1017 const double D = sec / 86400 - 0.5;
1020 const double g =
DEG2RAD(357.529 + 0.98560028 * D);
1021 const double q = 280.459 + 0.98564736 * D;
1022 const double L =
DEG2RAD(q + 1.915 * sin(g) + 0.020 * sin(2 * g));
1025 const double e =
DEG2RAD(23.439 - 0.00000036 * D);
1028 const double sindec = sin(e) * sin(L);
1031 const double ra = atan2(cos(e) * sin(L), cos(L));
1034 const double GMST = 18.697374558 + 24.06570982441908 * D;
1037 const double LST = GMST + lon / 15;
1040 const double h = LST / 12 * M_PI - ra;
1043 const double lat_help =
DEG2RAD(lat);
1046 return sin(lat_help) * sindec + cos(lat_help) * sqrt(1 -
1047 SQR(sindec)) * cos(h);
1059 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
1060 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
1063 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
1064 *doy = d0l[mon - 1] + day - 1;
1066 *doy = d0[mon - 1] + day - 1;
1083 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
1092 const int ix0 = zonal_rank * nx_block;
1093 const int iy0 = merid_rank * ny_block;
1095 const int ix1 = ix0 + nx_block
1099 const int iy1 = iy0 + ny_block
1105#pragma acc update device(dd->nx_glob, dd->ny_glob, \
1106 dd->lon_glob[:dd->nx_glob], \
1107 dd->lat_glob[:dd->ny_glob])
1108#pragma acc data present(atm, ctl, dd)
1109#pragma acc parallel loop independent gang vector
1111 for (
int ip = 0; ip < atm->
np; ip++) {
1118 double lon = atm->
lon[ip];
1119 double lat = atm->
lat[ip];
1125 const int inside = (ix >= ix0 && ix < ix1 && iy >= iy0 && iy < iy1);
1160 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
1164#pragma acc enter data create(npart, particles[:npart])
1165#pragma acc update device(npart, particles[:npart])
1166#pragma acc parallel loop present(atm, ctl, particles, cache, npart)
1168 for (
int ip = atm->
np; ip < atm->np + npart; ip++)
1173 particles[ip - atm->
np].
time = atm->
time[ip];
1174 particles[ip - atm->
np].
lon = atm->
lon[ip];
1175 particles[ip - atm->
np].
lat = atm->
lat[ip];
1176 particles[ip - atm->
np].
p = atm->
p[ip];
1177 for (
int iq = 0; iq < ctl->
nq; iq++)
1178 particles[ip - atm->
np].q[iq] = atm->
q[iq][ip];
1184#pragma acc update host( particles[:npart])
1185#pragma acc exit data delete(npart, particles)
1208 int zonal_rank = ix / nx_block;
1214 int merid_rank = iy / ny_block;
1237 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
1238 MPI_Comm_size(MPI_COMM_WORLD, &size);
1240 int *send_counts, *recv_counts;
1241 int *send_displs, *recv_displs;
1247 ALLOC(send_counts,
int,
1249 ALLOC(recv_counts,
int,
1251 ALLOC(send_displs,
int,
1253 ALLOC(recv_displs,
int,
1259 for (
int ip = 0; ip < *npart; ip++) {
1263 if (dest < 0 || dest >= size)
1264 ERRMSG(
"Invalid destination rank!");
1265 send_counts[dest]++;
1270 for (
int i = 0; i < size; i++) {
1271 send_displs[i] = nsend;
1272 nsend += send_counts[i];
1276 MPI_Alltoall(send_counts, 1, MPI_INT,
1277 recv_counts, 1, MPI_INT, MPI_COMM_WORLD);
1281 for (
int i = 0; i < size; i++) {
1282 recv_displs[i] = nrecv;
1283 nrecv += recv_counts[i];
1289 for (
int i = 0; i < size; i++)
1290 offsets[i] = send_displs[i];
1293 for (
int ip = 0; ip < *npart; ip++) {
1297 memcpy(&sendbuf[offsets[dest]], &(*particles)[ip],
sizeof(
particle_t));
1302 MPI_Alltoallv(sendbuf,
1307 recv_counts, recv_displs, dd->MPI_Particle, MPI_COMM_WORLD);
1310 if (nrecv > *capacity) {
1311 const int newcap = nrecv + nrecv / 2 + 1;
1313 realloc(*particles, (
size_t) newcap *
sizeof(
particle_t));
1315 ERRMSG(
"Out of memory!");
1321 for (
int ip = 0; ip < nrecv; ip++) {
1322 (*particles)[ip] = recvbuf[ip];
1351 MPI_Comm_size(MPI_COMM_WORLD, &size);
1353 ERRMSG(
"Number of tasks and subdomains is not identical!");
1356 const MPI_Datatype types[5] =
1357 { MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE };
1358 const int blocklengths[5] = { 1, 1, 1, 1,
NQ };
1359 const MPI_Aint displacements[5] =
1364 MPI_Type_create_struct(5, blocklengths, displacements, types,
1366 MPI_Type_commit(&dd->MPI_Particle);
1381 const double lon_min = (dd->
lon_glob[0] < 0) ? -180.0 : 0.0;
1384 *lon =
FMOD(*lon - lon_min, 360.0);
1391 *lat = 180.0 - *lat;
1393 }
else if (*lat < -90.0) {
1394 *lat = -180.0 - *lat;
1399 *lon =
FMOD(*lon - lon_min, 360.0);
1424 if (atm->
np + npart >
NP)
1425 ERRMSG(
"Too many particles. Increase NP!");
1428#pragma acc enter data create(npart, particles[:npart])
1429#pragma acc update device(particles[:npart], npart)
1430#pragma acc data present(atm, ctl, cache, particles, npart)
1431#pragma acc parallel loop
1433 for (
int ip = atm->
np; ip < atm->np + npart; ip++) {
1434 atm->
time[ip] = particles[ip - atm->
np].
time;
1435 atm->
lon[ip] = particles[ip - atm->
np].
lon;
1436 atm->
lat[ip] = particles[ip - atm->
np].
lat;
1437 atm->
p[ip] = particles[ip - atm->
np].
p;
1438 for (
int iq = 0; iq < ctl->
nq; iq++)
1439 atm->
q[iq][ip] = particles[ip - atm->
np].q[iq];
1443#pragma acc exit data delete(npart, particles)
1449#pragma acc update device(atm->np)
1468 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
1471 const int np = atm->
np;
1472 double amax = (met0->
nx * met0->
ny + met0->
ny) * met0->
np + met0->
np;
1474#pragma acc enter data create(amax)
1475#pragma acc update device(amax)
1476#pragma acc data present(ctl,met0,atm,dd,amax)
1481#pragma acc parallel loop independent gang vector
1483#pragma omp parallel for default(shared)
1485 for (
int ip = 0; ip < np; ip++) {
1493 dd->sort_key[ip] = amax + 1;
1495 dd->sort_key[ip] = amax + 2;
1503#pragma acc host_data use_device(dd->sort_key, dd->perm)
1505 thrustSortWrapper(dd->sort_key, np, dd->perm);
1507 size_t *perm_sz = (
size_t *) malloc((
size_t) np *
sizeof(size_t));
1508 if (perm_sz == NULL)
1509 ERRMSG(
"Out of memory!");
1511#pragma acc update self(dd->sort_key[0:np])
1513 gsl_sort_index(perm_sz, dd->sort_key, 1, (
size_t) np);
1514 for (
int ip = 0; ip < np; ++ip)
1515 dd->perm[ip] = (
int) perm_sz[ip];
1518#pragma acc update device(dd->perm[0:np])
1527 for (
int iq = 0; iq < ctl->
nq; iq++)
1533#pragma acc parallel loop reduction(+:nkeep) present(atm, ctl)
1535 for (
int ip = 0; ip < np; ip++)
1543#pragma acc parallel loop reduction(+:nsend) present(atm, ctl)
1545 for (
int ip = nkeep; ip < np; ip++)
1555 for (
int ip = 0; ip < np; ip++)
1561 (
"Rank %d: %d particles have subdomain index -1 and will be lost (kept: %d, to_send: %d, total_before: %d)",
1562 rank, nlost, nkeep, nsend, np);
1566#pragma acc update device(atm->np)
1571#pragma acc exit data delete(amax)
1586#pragma acc data present(dd,a)
1587#pragma acc parallel loop independent gang vector
1589#pragma omp parallel for default(shared)
1591 for (
int ip = 0; ip < np; ip++)
1592 dd->tmp[ip] = a[dd->perm[ip]];
1594#pragma acc parallel loop independent gang vector
1596#pragma omp parallel
for default(shared)
1598 for (
int ip = 0; ip < np; ip++)
1599 a[ip] = dd->tmp[ip];
1612 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
1613 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
1618 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
1619 for (i = 11; i > 0; i--)
1623 *day = doy - d0l[i] + 1;
1625 for (i = 11; i > 0; i--)
1629 *day = doy - d0[i] + 1;
1640 double data[2 *
EX];
1644 ERRMSG(
"Too many data points!");
1647 gsl_fft_complex_wavetable *wavetable =
1648 gsl_fft_complex_wavetable_alloc((
size_t) n);
1649 gsl_fft_complex_workspace *workspace =
1650 gsl_fft_complex_workspace_alloc((
size_t) n);
1653 for (
int i = 0; i < n; i++) {
1654 data[2 * i] = fcReal[i];
1655 data[2 * i + 1] = fcImag[i];
1659 gsl_fft_complex_forward(data, 1, (
size_t) n, wavetable, workspace);
1662 for (
int i = 0; i < n; i++) {
1663 fcReal[i] = data[2 * i];
1664 fcImag[i] = data[2 * i + 1];
1668 gsl_fft_complex_wavetable_free(wavetable);
1669 gsl_fft_complex_workspace_free(workspace);
1680 const double radius = z +
RE;
1681 const double latrad =
DEG2RAD(lat);
1682 const double lonrad =
DEG2RAD(lon);
1683 const double coslat = cos(latrad);
1685 x[0] = radius * coslat * cos(lonrad);
1686 x[1] = radius * coslat * sin(lonrad);
1687 x[2] = radius * sin(latrad);
1696 const char *metbase,
1697 const double dt_met,
1704 int year, mon, day, hour, min, sec;
1708 t6 = floor(t / dt_met) * dt_met;
1710 t6 = ceil(t / dt_met) * dt_met;
1713 jsec2time(t6, &year, &mon, &day, &hour, &min, &sec, &r);
1718 sprintf(filename,
"%s_YYYY_MM_DD_HH.nc", metbase);
1720 sprintf(filename,
"%s_YYYY_MM_DD_HH.bin", metbase);
1722 sprintf(filename,
"%s_YYYY_MM_DD_HH.pck", metbase);
1724 sprintf(filename,
"%s_YYYY_MM_DD_HH.zfp", metbase);
1726 sprintf(filename,
"%s_YYYY_MM_DD_HH.zstd", metbase);
1728 sprintf(filename,
"%s_YYYY_MM_DD_HH.cms", metbase);
1730 sprintf(filename,
"%s_YYYY_MM_DD_HH.sz3", metbase);
1731 sprintf(repl,
"%d", year);
1733 sprintf(repl,
"%02d", mon);
1735 sprintf(repl,
"%02d", day);
1737 sprintf(repl,
"%02d", hour);
1743 sprintf(filename,
"%s_YYMMDDHH.nc", metbase);
1744 sprintf(repl,
"%d", year);
1746 sprintf(repl,
"%02d", year % 100);
1748 sprintf(repl,
"%02d", mon);
1750 sprintf(repl,
"%02d", day);
1752 sprintf(repl,
"%02d", hour);
1767 for (
int i = 0; i < 3; i++) {
1771 if (!(ch = strstr(orig, search)))
1773 strncpy(buffer, orig, (
size_t) (ch - orig));
1774 buffer[ch - orig] = 0;
1775 sprintf(buffer + (ch - orig),
"%s%s", repl, ch + strlen(search));
1777 strcpy(orig, buffer);
1784 const int met_tropo,
1804#pragma omp parallel for default(shared) private(ci,cw)
1805 for (
int ix = 0; ix < nx; ix++)
1806 for (
int iy = 0; iy < ny; iy++) {
1808 &pt[iy * nx + ix], ci, cw, 1);
1810 &ps[iy * nx + ix], ci, cw, 0);
1812 &zs[iy * nx + ix], ci, cw, 0);
1814 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
1816 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
1818 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
1820 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
1837 *lon2 =
FMOD(lon, 360.);
1838 if (*lon2 < lons[0])
1840 else if (*lon2 > lons[nlon - 1])
1845 if (lats[0] < lats[nlat - 1])
1846 *lat2 =
MIN(
MAX(*lat2, lats[0]), lats[nlat - 1]);
1848 *lat2 =
MIN(
MAX(*lat2, lats[nlat - 1]), lats[0]);
1855 float heights0[
EX][
EY][
EP],
1856 float array0[
EX][
EY][
EP],
1858 float heights1[
EX][
EY][
EP],
1859 float array1[
EX][
EY][
EP],
1861 const double height,
1887 int k_max = ind[0][0];
1888 for (
int i = 0; i < 2; i++)
1889 for (
int j = 0; j < 4; j++) {
1890 if (ci[2] > ind[i][j])
1892 if (k_max < ind[i][j])
1898 cw[0] = (lon2 - met0->
lon[ci[0]]) /
1899 (met0->
lon[ci[0] + 1] - met0->
lon[ci[0]]);
1900 cw[1] = (lat2 - met0->
lat[ci[1]]) /
1901 (met0->
lat[ci[1] + 1] - met0->
lat[ci[1]]);
1904 double height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2]]
1905 - heights0[ci[0]][ci[1]][ci[2]])
1906 + heights0[ci[0]][ci[1]][ci[2]];
1907 double height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2]]
1908 - heights0[ci[0]][ci[1] + 1][ci[2]])
1909 + heights0[ci[0]][ci[1] + 1][ci[2]];
1910 double height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2]]
1911 - heights0[ci[0] + 1][ci[1]][ci[2]])
1912 + heights0[ci[0] + 1][ci[1]][ci[2]];
1913 double height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2]]
1914 - heights0[ci[0] + 1][ci[1] + 1][ci[2]])
1915 + heights0[ci[0] + 1][ci[1] + 1][ci[2]];
1918 double height0 = cw[1] * (height01 - height00) + height00;
1919 double height1 = cw[1] * (height11 - height10) + height10;
1922 double height_bot = cw[0] * (height1 - height0) + height0;
1925 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
1926 - heights0[ci[0]][ci[1]][ci[2] + 1])
1927 + heights0[ci[0]][ci[1]][ci[2] + 1];
1928 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
1929 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
1930 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
1931 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
1932 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
1933 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
1934 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1935 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1936 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1939 height0 = cw[1] * (height01 - height00) + height00;
1940 height1 = cw[1] * (height11 - height10) + height10;
1943 double height_top = cw[0] * (height1 - height0) + height0;
1946 while (((heights0[0][0][0] > heights0[0][0][1]) &&
1947 ((height_bot <= height) || (height_top > height))
1948 && (height_bot >= height) && (ci[2] < k_max))
1950 ((heights0[0][0][0] < heights0[0][0][1]) &&
1951 ((height_bot >= height) || (height_top < height))
1952 && (height_bot <= height) && (ci[2] < k_max))
1956 height_bot = height_top;
1959 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
1960 - heights0[ci[0]][ci[1]][ci[2] + 1])
1961 + heights0[ci[0]][ci[1]][ci[2] + 1];
1962 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
1963 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
1964 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
1965 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
1966 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
1967 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
1968 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1969 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1970 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1973 height0 = cw[1] * (height01 - height00) + height00;
1974 height1 = cw[1] * (height11 - height10) + height10;
1977 height_top = cw[0] * (height1 - height0) + height0;
1981 cw[2] = (height - height_bot)
1982 / (height_top - height_bot);
1986 const double array000 = cw[3] * (array1[ci[0]][ci[1]][ci[2]]
1987 - array0[ci[0]][ci[1]][ci[2]])
1988 + array0[ci[0]][ci[1]][ci[2]];
1989 const double array100 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2]]
1990 - array0[ci[0] + 1][ci[1]][ci[2]])
1991 + array0[ci[0] + 1][ci[1]][ci[2]];
1992 const double array010 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2]]
1993 - array0[ci[0]][ci[1] + 1][ci[2]])
1994 + array0[ci[0]][ci[1] + 1][ci[2]];
1995 const double array110 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2]]
1996 - array0[ci[0] + 1][ci[1] + 1][ci[2]])
1997 + array0[ci[0] + 1][ci[1] + 1][ci[2]];
1998 const double array001 = cw[3] * (array1[ci[0]][ci[1]][ci[2] + 1]
1999 - array0[ci[0]][ci[1]][ci[2] + 1])
2000 + array0[ci[0]][ci[1]][ci[2] + 1];
2001 const double array101 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2] + 1]
2002 - array0[ci[0] + 1][ci[1]][ci[2] + 1])
2003 + array0[ci[0] + 1][ci[1]][ci[2] + 1];
2004 const double array011 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2] + 1]
2005 - array0[ci[0]][ci[1] + 1][ci[2] + 1])
2006 + array0[ci[0]][ci[1] + 1][ci[2] + 1];
2007 const double array111 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
2008 - array0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
2009 + array0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
2011 const double array00 = cw[0] * (array100 - array000) + array000;
2012 const double array10 = cw[0] * (array110 - array010) + array010;
2013 const double array01 = cw[0] * (array101 - array001) + array001;
2014 const double array11 = cw[0] * (array111 - array011) + array011;
2016 const double aux0 = cw[1] * (array10 - array00) + array00;
2017 const double aux1 = cw[1] * (array11 - array01) + array01;
2020 *var = cw[2] * (aux1 - aux0) + aux0;
2050 cw[0] = (met->
p[ci[0] + 1] - p)
2051 / (met->
p[ci[0] + 1] - met->
p[ci[0]]);
2052 cw[1] = (met->
lon[ci[1] + 1] - lon2)
2053 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
2054 cw[2] = (met->
lat[ci[2] + 1] - lat2)
2055 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
2059 const double aux00 =
2060 cw[0] * (array[ci[1]][ci[2]][ci[0]] - array[ci[1]][ci[2]][ci[0] + 1])
2061 + array[ci[1]][ci[2]][ci[0] + 1];
2062 const double aux01 =
2063 cw[0] * (array[ci[1]][ci[2] + 1][ci[0]] -
2064 array[ci[1]][ci[2] + 1][ci[0] + 1])
2065 + array[ci[1]][ci[2] + 1][ci[0] + 1];
2066 const double aux10 =
2067 cw[0] * (array[ci[1] + 1][ci[2]][ci[0]] -
2068 array[ci[1] + 1][ci[2]][ci[0] + 1])
2069 + array[ci[1] + 1][ci[2]][ci[0] + 1];
2070 const double aux11 =
2071 cw[0] * (array[ci[1] + 1][ci[2] + 1][ci[0]] -
2072 array[ci[1] + 1][ci[2] + 1][ci[0] + 1])
2073 + array[ci[1] + 1][ci[2] + 1][ci[0] + 1];
2076 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
2077 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
2078 *var = cw[1] * (aux0 - aux1) + aux1;
2085 float array[
EX][
EY],
2106 cw[1] = (met->
lon[ci[1] + 1] - lon2)
2107 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
2108 cw[2] = (met->
lat[ci[2] + 1] - lat2)
2109 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
2113 const double aux00 = array[ci[1]][ci[2]];
2114 const double aux01 = array[ci[1]][ci[2] + 1];
2115 const double aux10 = array[ci[1] + 1][ci[2]];
2116 const double aux11 = array[ci[1] + 1][ci[2] + 1];
2119 if (isfinite(aux00) && isfinite(aux01)
2120 && isfinite(aux10) && isfinite(aux11)) {
2121 const double aux0 = cw[2] * (aux00 - aux01) + aux01;
2122 const double aux1 = cw[2] * (aux10 - aux11) + aux11;
2123 *var = cw[1] * (aux0 - aux1) + aux1;
2143 float array0[
EX][
EY][
EP],
2145 float array1[
EX][
EY][
EP],
2162 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
2165 *var = wt * (var0 - var1) + var1;
2172 float array0[
EX][
EY],
2174 float array1[
EX][
EY],
2190 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
2193 if (isfinite(var0) && isfinite(var1))
2194 *var = wt * (var0 - var1) + var1;
2205 float array0[
EX][
EY],
2207 float array1[
EX][
EY],
2208 const double lons[
EX],
2209 const double lats[
EY],
2228 const int ix =
locate_reg(lons, (
int) nlon, lon2);
2229 const int iy =
locate_irr(lats, (
int) nlat, lat2);
2233 for (
int dx = 0; dx < 2; dx++)
2234 for (
int dy = 0; dy < 2; dy++) {
2235 if (isfinite(array0[ix + dx][iy + dy])) {
2236 mean += array0[ix + dx][iy + dy];
2237 *sigma +=
SQR(array0[ix + dx][iy + dy]);
2240 if (isfinite(array1[ix + dx][iy + dy])) {
2241 mean += array1[ix + dx][iy + dy];
2242 *sigma +=
SQR(array1[ix + dx][iy + dy]);
2247 *sigma = sqrt(
MAX(*sigma / n -
SQR(mean / n), 0.0));
2250 if (method == 1 && isfinite(array0[ix][iy])
2251 && isfinite(array0[ix][iy + 1])
2252 && isfinite(array0[ix + 1][iy])
2253 && isfinite(array0[ix + 1][iy + 1])
2254 && isfinite(array1[ix][iy])
2255 && isfinite(array1[ix][iy + 1])
2256 && isfinite(array1[ix + 1][iy])
2257 && isfinite(array1[ix + 1][iy + 1])) {
2259 const double aux00 =
LIN(lons[ix], array0[ix][iy],
2260 lons[ix + 1], array0[ix + 1][iy], lon2);
2261 const double aux01 =
LIN(lons[ix], array0[ix][iy + 1],
2262 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
2263 const double aux0 =
LIN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
2265 const double aux10 =
LIN(lons[ix], array1[ix][iy],
2266 lons[ix + 1], array1[ix + 1][iy], lon2);
2267 const double aux11 =
LIN(lons[ix], array1[ix][iy + 1],
2268 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
2269 const double aux1 =
LIN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
2271 *var =
LIN(time0, aux0, time1, aux1, time);
2276 const double aux00 =
NN(lons[ix], array0[ix][iy],
2277 lons[ix + 1], array0[ix + 1][iy], lon2);
2278 const double aux01 =
NN(lons[ix], array0[ix][iy + 1],
2279 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
2280 const double aux0 =
NN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
2282 const double aux10 =
NN(lons[ix], array1[ix][iy],
2283 lons[ix + 1], array1[ix + 1][iy], lon2);
2284 const double aux11 =
NN(lons[ix], array1[ix][iy + 1],
2285 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
2286 const double aux1 =
NN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
2288 *var =
NN(time0, aux0, time1, aux1, time);
2313 const time_t jsec0 = (time_t) jsec + timegm(&t0);
2314 t1 = gmtime(&jsec0);
2316 *year = t1->tm_year + 1900;
2317 *mon = t1->tm_mon + 1;
2319 *hour = t1->tm_hour;
2322 *remain = jsec - floor(jsec);
2328 const double kz[
EP],
2329 const double kw[
EP],
2338 const double z =
Z(p);
2343 else if (z > kz[nk - 1])
2347 return LIN(kz[idx], kw[idx], kz[idx + 1], kw[idx + 1], z);
2364 const double a =
RA *
SQR(t), r =
SH(h2o) / (1. -
SH(h2o));
2377 (
"MET_PRESS_LEVEL_DEF=0 is disabled. Use 3 for the extended L137 set.");
2382 (
"MET_PRESS_LEVEL_DEF=1 is disabled. Use 4 for the extended L91 set.");
2387 (
"MET_PRESS_LEVEL_DEF=2 is disabled. Use 5 for the extended L60 set.");
2393 const double press[147] = {
2394 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
2395 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
2396 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
2397 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
2398 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2399 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
2400 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
2401 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
2402 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
2403 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
2404 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
2405 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
2406 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
2407 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
2408 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
2409 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
2410 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
2411 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
2412 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73, 1028.85,
2414 1035.09, 1038.21, 1041.33, 1044.45
2417 for (
int ip = 0; ip < ctl->
met_np; ip++)
2424 const double press[101] = {
2425 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
2426 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
2427 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
2428 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
2429 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
2431 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
2432 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
2433 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
2434 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
2435 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
2436 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
2437 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
2438 1007.4431, 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73,
2440 1035.09, 1038.21, 1041.33, 1044.45
2443 for (
int ip = 0; ip < ctl->
met_np; ip++)
2450 const double press[62] = {
2451 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
2452 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
2453 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
2454 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
2455 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
2456 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
2457 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
2458 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1034.86, 1039.65,
2462 for (
int ip = 0; ip < ctl->
met_np; ip++)
2469 const double press[137] = {
2470 0.01, 0.02, 0.031, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861,
2471 0.2499, 0.3299, 0.4288, 0.5496, 0.6952, 0.869, 1.0742,
2472 1.3143, 1.5928, 1.9134, 2.2797, 2.6954, 3.1642, 3.6898,
2473 4.2759, 4.9262, 5.6441, 6.4334, 7.2974, 8.2397, 9.2634,
2474 10.372, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945, 18.9752,
2475 20.761, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
2476 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.199, 54.5299,
2477 57.9834, 61.5607, 65.2695, 69.1187, 73.1187, 77.281, 81.6182,
2478 86.145, 90.8774, 95.828, 101.005, 106.415, 112.068, 117.971,
2479 124.134, 130.564, 137.27, 144.262, 151.549, 159.14, 167.045,
2480 175.273, 183.834, 192.739, 201.997, 211.619, 221.615, 231.995,
2481 242.772, 253.955, 265.556, 277.585, 290.055, 302.976, 316.361,
2482 330.22, 344.566, 359.411, 374.767, 390.645, 407.058, 424.019,
2483 441.539, 459.632, 478.31, 497.584, 517.42, 537.72, 558.343,
2484 579.193, 600.167, 621.162, 642.076, 662.808, 683.262, 703.347,
2485 722.979, 742.086, 760.6, 778.466, 795.64, 812.085, 827.776,
2486 842.696, 856.838, 870.2, 882.791, 894.622, 905.712, 916.081,
2487 925.757, 934.767, 943.14, 950.908, 958.104, 965.299, 972.495,
2488 979.69, 986.886, 994.081, 1001.28, 1008.47, 1015.67, 1022.86,
2489 1030.06, 1037.25, 1044.45
2492 for (
int ip = 0; ip < ctl->
met_np; ip++)
2499 const double press[59] = {
2500 0.1, 0.2, 0.3843, 0.6365, 0.9564, 1.3448, 1.8058, 2.3478,
2501 2.985, 3.7397, 4.6462, 5.7565, 7.1322, 8.8366, 10.9483,
2502 13.5647, 16.8064, 20.8227, 25.7989, 31.9642, 39.6029, 49.0671,
2503 60.1802, 73.0663, 87.7274, 104.229, 122.614, 142.902, 165.089,
2504 189.147, 215.025, 242.652, 272.059, 303.217, 336.044, 370.407,
2505 406.133, 443.009, 480.791, 519.209, 557.973, 596.777, 635.306,
2506 673.24, 710.263, 746.063, 780.346, 812.83, 843.263, 871.42,
2507 897.112, 920.189, 940.551, 958.148, 975.744, 993.341, 1010.94,
2511 for (
int ip = 0; ip < ctl->
met_np; ip++)
2515 ERRMSG(
"Use values between 3 and 7.");
2519 ERRMSG(
"Recompile with larger EP to use this pressure level definition!");
2531 int i = (ihi + ilo) >> 1;
2533 if (xx[i] < xx[i + 1])
2534 while (ihi > ilo + 1) {
2535 i = (ihi + ilo) >> 1;
2541 while (ihi > ilo + 1) {
2542 i = (ihi + ilo) >> 1;
2562 int i = (ihi + ilo) >> 1;
2564 if ((xx[ig] <= x && x < xx[ig + 1]) || (xx[ig] >= x && x > xx[ig + 1]))
2567 if (xx[i] < xx[i + 1])
2568 while (ihi > ilo + 1) {
2569 i = (ihi + ilo) >> 1;
2575 while (ihi > ilo + 1) {
2576 i = (ihi + ilo) >> 1;
2594 const int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
2608 float profiles[
EX][
EY][
EP],
2610 const int lon_ap_ind,
2611 const int lat_ap_ind,
2612 const double height_ap,
2618 np, height_ap, ind[0]);
2620 np, height_ap, ind[1]);
2622 np, height_ap, ind[2]);
2641 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2645 double dts, u[4], um = 0, v[4], vm = 0, w[4], wm = 0,
2649 for (
int i = 0; i < ctl->
advect; i++) {
2654 x[0] = atm->
lon[ip];
2655 x[1] = atm->
lat[ip];
2658 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
2659 x[0] = atm->
lon[ip] +
DX2DEG(dts * u[i - 1] / 1000., atm->
lat[ip]);
2660 x[1] = atm->
lat[ip] +
DY2DEG(dts * v[i - 1] / 1000.);
2661 x[2] = atm->
p[ip] + dts * w[i - 1];
2663 const double tm = atm->
time[ip] + dts;
2668 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2670 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2672 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
2678 met1, met1->
pl, met1->
ul,
2679 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2681 met1, met1->
pl, met1->
vl,
2682 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2684 met1, met1->
pl, met1->
wl,
2685 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
2691 k = (i == 0 ? 0.0 : 1.0);
2692 else if (ctl->
advect == 4)
2693 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2700 atm->
time[ip] += cache->
dt[ip];
2701 atm->
lon[ip] +=
DX2DEG(cache->
dt[ip] * um / 1000.,
2702 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
2703 atm->
lat[ip] +=
DY2DEG(cache->
dt[ip] * vm / 1000.);
2704 atm->
p[ip] += cache->
dt[ip] * wm;
2716 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2722 atm->
time[ip], atm->
p[ip],
2723 atm->
lon[ip], atm->
lat[ip],
2724 &atm->
q[qnt][ip], ci, cw, 1);
2727 double dts, u[4], um = 0, v[4], vm = 0, wdot[4],
2728 wdotm = 0, x[3] = { 0, 0, 0 };
2731 for (
int i = 0; i < ctl->
advect; i++) {
2736 x[0] = atm->
lon[ip];
2737 x[1] = atm->
lat[ip];
2738 x[2] = atm->
q[qnt][ip];
2740 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
2741 x[0] = atm->
lon[ip] +
DX2DEG(dts * u[i - 1] / 1000., atm->
lat[ip]);
2742 x[1] = atm->
lat[ip] +
DY2DEG(dts * v[i - 1] / 1000.);
2743 x[2] = atm->
q[qnt][ip] + dts * wdot[i - 1];
2746 const double tm = atm->
time[ip] + dts;
2751 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2754 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2757 tm, x[2], x[0], x[1], &wdot[i], ci, cw, 0);
2762 k = (i == 0 ? 0.0 : 1.0);
2763 else if (ctl->
advect == 4)
2764 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2768 wdotm += k * wdot[i];
2772 atm->
time[ip] += cache->
dt[ip];
2773 atm->
lon[ip] +=
DX2DEG(cache->
dt[ip] * um / 1000.,
2774 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
2775 atm->
lat[ip] +=
DY2DEG(cache->
dt[ip] * vm / 1000.);
2776 atm->
q[qnt][ip] += cache->
dt[ip] * wdotm;
2782 atm->
q[qnt][ip], atm->
lon[ip], atm->
lat[ip],
2783 &atm->
p[ip], ci, cw, 1);
2811 atm->
lon[ip], atm->
lat[ip], &atm->
p[ip], ci, cw, 1);
2836 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2872 if (atm->
p[ip] < pbl)
2924 ERRMSG(
"Molar mass is not defined!");
2930 const int ensemble_mode = (ctl->
nens > 0);
2931 const int np = atm->
np;
2935 const int ngrid = nx * ny * nz;
2936 const int nens = ensemble_mode ? ctl->
nens : 1;
2938 double *restrict
const z = (
double *) malloc((
size_t) nz *
sizeof(double));
2939 double *restrict
const press =
2940 (
double *) malloc((
size_t) nz *
sizeof(double));
2941 double *restrict
const mass =
2942 (
double *) calloc((
size_t) ngrid * (size_t) nens,
sizeof(
double));
2943 double *restrict
const area =
2944 (
double *) malloc((
size_t) ny *
sizeof(double));
2945 double *restrict
const lon =
2946 (
double *) malloc((
size_t) nx *
sizeof(double));
2947 double *restrict
const lat =
2948 (
double *) malloc((
size_t) ny *
sizeof(double));
2950 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
2951 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
2952 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
2961#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])
2962#pragma acc data present(ctl,met0,met1,atm,ixs,iys,izs,z,press,mass,area,lon,lat)
2963#pragma acc parallel loop independent gang vector
2965#pragma omp parallel for default(shared)
2967 for (
int iz = 0; iz < nz; iz++) {
2969 press[iz] =
P(z[iz]);
2973 const double t0 = tt - 0.5 * ctl->
dt_mod;
2974 const double t1 = tt + 0.5 * ctl->
dt_mod;
2978#pragma acc parallel loop independent gang vector
2980#pragma omp parallel for default(shared)
2982 for (
int ip = 0; ip < np; ip++) {
2986 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
2987 || ixs[ip] < 0 || ixs[ip] >= nx
2988 || iys[ip] < 0 || iys[ip] >= ny || izs[ip] < 0 || izs[ip] >= nz)
2994#pragma acc parallel loop independent gang vector
2996#pragma omp parallel for default(shared)
2998 for (
int ix = 0; ix < nx; ix++)
3002#pragma acc parallel loop independent gang vector
3004#pragma omp parallel for default(shared)
3006 for (
int iy = 0; iy < ny; iy++) {
3008 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
3013#pragma acc parallel loop independent gang vector
3015 for (
int ip = 0; ip < np; ip++) {
3017 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
3018 if (ensemble_mode) {
3019 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
3020 mass_idx += ens * ngrid;
3023#pragma acc atomic update
3025 mass[mass_idx] += atm->
q[ctl->
qnt_m][ip];
3031#pragma acc parallel loop independent gang vector
3033#pragma omp parallel for default(shared)
3035 for (
int ip = 0; ip < np; ip++)
3043 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
3046 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
3047 if (ensemble_mode) {
3048 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
3049 mass_idx += ens * ngrid;
3053 const double m = mass[mass_idx];
3055 / (
RHO(press[izs[ip]], temp) * area[iys[ip]] * dz * 1e9);
3060#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
3088 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3105 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
3107 atm->
lat[ip], atm->
p[ip]));
3109 atm->
lat[ip], atm->
p[ip]));
3111 atm->
lat[ip], atm->
p[ip]));
3131 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3139 double pbot = ps, ptop = ps;
3156 double cape, cin, pel;
3162 if (isfinite(cape) && cape >= ctl->
conv_cape
3164 ptop = GSL_MIN(ptop, pel);
3168 if (ptop != pbot && atm->
p[ip] >= ptop) {
3173 pbot, atm->
lon[ip], atm->
lat[ip], &tbot, ci, cw, 1);
3175 atm->
lon[ip], atm->
lat[ip], &ttop, ci, cw, 1);
3176 const double rhobot = pbot / tbot;
3177 const double rhotop = ptop / ttop;
3180 const double rho = rhobot + (rhotop - rhobot) * cache->
rs[ip];
3183 atm->
p[ip] =
LIN(rhobot, pbot, rhotop, ptop, rho);
3202 int npart = 0, capacity = 0;
3209 dd_sort(ctl, *met, atm, dd, &npart);
3212 if (npart > capacity) {
3213 const int newcap = npart + npart / 2 + 1;
3215 realloc(particles, (
size_t) newcap *
sizeof(
particle_t));
3217 ERRMSG(
"Out of memory!");
3249 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3252 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,clim,atm)") {
3261 const double aux = exp(-cache->
dt[ip] / tdec);
3262 if (ctl->
qnt_m >= 0) {
3265 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
3266 atm->
q[ctl->
qnt_m][ip] *= aux;
3291 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3299 float umean = 0, usig = 0, vmean = 0, vsig = 0, wmean = 0, wsig = 0;
3300 for (
int i = 0; i < 2; i++)
3301 for (
int j = 0; j < 2; j++)
3302 for (
int k = 0; k < 2; k++) {
3303 umean += met0->
u[ix + i][iy + j][iz + k];
3304 usig +=
SQR(met0->
u[ix + i][iy + j][iz + k]);
3305 vmean += met0->
v[ix + i][iy + j][iz + k];
3306 vsig +=
SQR(met0->
v[ix + i][iy + j][iz + k]);
3307 wmean += met0->
w[ix + i][iy + j][iz + k];
3308 wsig +=
SQR(met0->
w[ix + i][iy + j][iz + k]);
3310 umean += met1->
u[ix + i][iy + j][iz + k];
3311 usig +=
SQR(met1->
u[ix + i][iy + j][iz + k]);
3312 vmean += met1->
v[ix + i][iy + j][iz + k];
3313 vsig +=
SQR(met1->
v[ix + i][iy + j][iz + k]);
3314 wmean += met1->
w[ix + i][iy + j][iz + k];
3315 wsig +=
SQR(met1->
w[ix + i][iy + j][iz + k]);
3317 usig = usig / 16.f -
SQR(umean / 16.f);
3318 usig = (usig > 0 ? sqrtf(usig) : 0);
3319 vsig = vsig / 16.f -
SQR(vmean / 16.f);
3320 vsig = (vsig > 0 ? sqrtf(vsig) : 0);
3321 wsig = wsig / 16.f -
SQR(wmean / 16.f);
3322 wsig = (wsig > 0 ? sqrtf(wsig) : 0);
3325 const double r = 1 - 2 * fabs(cache->
dt[ip]) / ctl->
dt_met;
3326 const double r2 = sqrt(1 - r * r);
3330 cache->
uvwp[ip][0] =
3331 (float) (r * cache->
uvwp[ip][0] +
3336 cache->
uvwp[ip][1] =
3337 (float) (r * cache->
uvwp[ip][1] +
3344 cache->
uvwp[ip][2] =
3345 (float) (r * cache->
uvwp[ip][2] +
3347 atm->
p[ip] += cache->
uvwp[ip][2] * cache->
dt[ip];
3368 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3370 double dsigw_dz = 0.0, sig_u = 0.25, sig_w = 0.1,
3371 tau_u = 300., tau_w = 100.;
3380 if (atm->
p[ip] >= pbl) {
3383 const double p =
MIN(atm->
p[ip], ps);
3384 const double zs =
Z(ps);
3385 const double z = 1e3 * (
Z(p) - zs);
3386 const double zi = 1e3 * (
Z(pbl) - zs);
3387 const double zratio = z / zi;
3390 double ess, nss, h2o, t;
3395 const double rho =
RHO(p,
TVIRT(t, h2o));
3396 const double tau = sqrt(
SQR(ess) +
SQR(nss));
3397 const double ustar = sqrt(tau / rho);
3407 sig_u = 1e-2 + 2.0 * ustar * (1.0 - zratio);
3408 sig_w = 1e-2 + 1.3 * ustar * (1.0 - zratio);
3411 dsigw_dz = -1.3 * ustar / zi;
3414 tau_u = 0.07 * zi / sig_u * sqrt(zratio);
3415 tau_w = 0.1 * zi / sig_w * pow(zratio, 0.8);
3422 const double wstar =
3423 pow(
G0 /
THETAVIRT(p, t, h2o) * shf / (rho *
CPD) * zi, 1. / 3.);
3427 + sqrt(0.4 *
SQR(wstar) + (5.0 - 4.0 * zratio) *
SQR(ustar));
3428 sig_w = 1e-2 + sqrt(1.2 *
SQR(wstar) * (1.0 - 0.9 * zratio)
3429 * pow(zratio, 2.0 / 3.0)
3430 + (1.8 - 1.4 * zratio) *
SQR(ustar));
3433 dsigw_dz = 0.5 / sig_w / zi * (-1.4 *
SQR(ustar) +
SQR(wstar)
3435 pow(
MAX(zratio, 1e-3), -1.0 / 3.0)
3436 - 1.8 * pow(zratio, 2.0 / 3.0)));
3439 const double C0 = 3.0;
3441 (1.5 - 1.2 * pow(zratio, 1.0 / 3.0)) *
SQR(wstar) * wstar / zi
3442 +
SQR(ustar) * ustar * (1.0 - 0.8 * zratio) / (
KARMAN * z);
3443 tau_u = 2 *
SQR(sig_u) / (C0 * eps);
3444 tau_w = 2 *
SQR(sig_w) / (C0 * eps);
3449 sig_u =
MAX(sig_u, 0.25);
3450 sig_w =
MAX(sig_w, 0.1);
3451 tau_u =
MAX(tau_u, 300.);
3452 tau_w =
MAX(tau_w, 100.);
3455 const double ru = exp(-fabs(cache->
dt[ip]) / tau_u);
3456 const double ru2 = sqrt(1.0 -
SQR(ru));
3458 = (float) (cache->
uvwp[ip][0] * ru + ru2 * cache->
rs[3 * ip]);
3460 = (float) (cache->
uvwp[ip][1] * ru + ru2 * cache->
rs[3 * ip + 1]);
3462 const double rw = exp(-fabs(cache->
dt[ip]) / tau_w);
3463 const double rw2 = sqrt(1.0 -
SQR(rw));
3465 = (float) (cache->
uvwp[ip][2] * rw + rw2 * cache->
rs[3 * ip + 2]
3466 + sig_w * dsigw_dz * cache->
dt[ip]);
3473 DZ2DP(cache->
uvwp[ip][2] * cache->
dt[ip] / 1000., atm->
p[ip]);
3495 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3504 const double wpbl =
pbl_weight(ctl, atm, ip, pbl, ps);
3505 const double wtrop =
tropo_weight(clim, atm, ip) * (1.0 - wpbl);
3506 const double wstrat = 1.0 - wpbl - wtrop;
3516 const double sigma = sqrt(2.0 * dx * fabs(cache->
dt[ip])) / 1000.;
3518 atm->
lat[ip] +=
DY2DEG(cache->
rs[3 * ip + 1] * sigma);
3523 const double sigma = sqrt(2.0 * dz * fabs(cache->
dt[ip])) / 1000.;
3524 atm->
p[ip] +=
DZ2DP(cache->
rs[3 * ip + 2] * sigma, atm->
p[ip]);
3543 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3546 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3558 const double dz = 1000. * (
Z(ps - ctl->
dry_depo_dp) -
Z(ps));
3578 const double aux = exp(-cache->
dt[ip] * v_dep / dz);
3579 if (ctl->
qnt_m >= 0) {
3582 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
3583 atm->
q[ctl->
qnt_m][ip] *= aux;
3607 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3610 const double a = 3.12541941e-06;
3611 const double b = -5.72532259e-01;
3612 const double low = pow(1. / a, 1. / b);
3615 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3622 if (!(lwc > 0 || rwc > 0))
3633 const double k = 9.1e7 * exp(-29700. /
RI * (1. / t - 1. / 298.15));
3636 const double H_SO2 =
3637 1.3e-2 * exp(2900. * (1. / t - 1. / 298.15)) *
RI * t;
3638 const double K_1S = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
3641 const double H_h2o2 =
3642 8.3e2 * exp(7600. * (1. / t - 1. / 298.15)) *
RI * t;
3648 cor = atm->
q[ctl->
qnt_Cx][ip] >
3649 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
3651 const double h2o2 = H_h2o2
3653 * M * cor * 1000. /
AVO;
3656 const double rho_air = atm->
p[ip] / (
RI * t) *
MA / 10.;
3657 const double CWC = (lwc + rwc) * rho_air / 1e3;
3660 const double rate_coef = k * K_1S * h2o2 * H_SO2 * CWC;
3661 const double aux = exp(-cache->
dt[ip] * rate_coef);
3662 if (ctl->
qnt_m >= 0) {
3665 atm->
q[ctl->
qnt_m][ip] *= aux;
3697 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
3700 cache->
iso_var[ip] = atm->
p[ip] / t;
3706 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
3717 LOG(1,
"Read balloon pressure data: %s", ctl->
balloon);
3721 if (!(in = fopen(ctl->
balloon,
"r")))
3722 ERRMSG(
"Cannot open file!");
3726 while (fgets(line,
LEN, in))
3727 if (sscanf(line,
"%lg %lg", &(cache->
iso_ts[cache->
iso_n]),
3730 ERRMSG(
"Too many data points!");
3733 if (cache->
iso_n < 1)
3734 ERRMSG(
"Could not read any data!");
3757 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,met1,atm)") {
3770 atm->
p[ip] = cache->
iso_var[ip] * t;
3776 atm->
p[ip] = 1000. * pow(cache->
iso_var[ip] / t, -1. / 0.286);
3782 atm->
p[ip] = cache->
iso_ps[0];
3810 const int nvar = NVAR, nfix = NFIX, nreact = NREACT;
3811 double rtol[1] = { 1.0e-3 };
3812 double atol[1] = { 1.0 };
3816#pragma acc data copy(rtol,atol,nvar,nfix,nreact)
3819 "acc data present(ctl,cache,clim,met0,met1,atm) ") {
3822 double var[nvar], fix[nfix], rconst[nreact];
3823 for (
int i = 0; i < nvar; i++)
3825 for (
int i = 0; i < nfix; i++)
3827 for (
int i = 0; i < nreact; i++)
3829 kpp_chem_initialize(ctl, clim, met0, met1, atm, var, fix, rconst, ip);
3834 for (
int i = 0; i < 20; i++) {
3841 Rosenbrock(var, fix, rconst, 0, ctl->
dt_kpp,
3842 atol, rtol, &FunTemplate, &JacTemplate, rpar, ipar);
3845 kpp_chem_output2atm(atm, ctl, met0, met1, var, ip);
3866 ERRMSG(
"Need T_ice and T_NAT to calculate T_STS!");
3870 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3872 double ps, ts, zs, us, vs, ess, nss, shf, lsm, sst, pbl, pt, pct, pcb,
3873 cl, plcl, plfc, pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot,
3874 o3, lwc, rwc, iwc, swc, cc, z, zt;
3922 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
3924 atm->
lat[ip], atm->
p[ip]));
3926 atm->
lat[ip], atm->
p[ip]));
3928 atm->
lat[ip], atm->
p[ip]));
3929 SET_ATM(qnt_vh, sqrt(u * u + v * v));
3951 atm->
lat[ip], atm->
p[ip])));
3969 const int np = atm->
np;
3970 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
3971 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
3972 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
3980 const double t0 = t - 0.5 * ctl->
dt_mod;
3981 const double t1 = t + 0.5 * ctl->
dt_mod;
3985#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
3986#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
3987#pragma acc parallel loop independent gang vector
3989#pragma omp parallel for default(shared)
3991 for (
int ip = 0; ip < np; ip++) {
3994 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
mixing_z0) / dz);
3995 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
3996 || ixs[ip] < 0 || ixs[ip] >= ctl->
mixing_nx
3997 || iys[ip] < 0 || iys[ip] >= ctl->
mixing_ny
3998 || izs[ip] < 0 || izs[ip] >= ctl->
mixing_nz)
4003 const int use_ensemble = (ctl->
nens > 0);
4005 const int quantities[] = {
4013 const int n_qnt =
sizeof(quantities) /
sizeof(quantities[0]);
4015 for (
int i = 0; i < n_qnt; i++)
4016 if (quantities[i] >= 0)
4022#pragma acc exit data delete(ixs,iys,izs)
4039 const int use_ensemble) {
4041 const int np = atm->
np;
4043 const int nens = use_ensemble ? ctl->
nens : 1;
4044 const int total_grid = ngrid * nens;
4046 double *restrict
const cmean =
4047 (
double *) malloc((
size_t) total_grid *
sizeof(double));
4048 int *restrict
const count =
4049 (
int *) malloc((
size_t) total_grid *
sizeof(int));
4053#pragma acc enter data create(cmean[0:total_grid],count[0:total_grid])
4054#pragma acc data present(ctl,clim,atm,ixs,iys,izs,cmean,count)
4055#pragma acc parallel loop independent gang vector
4060#pragma omp parallel for
4062 for (
int i = 0; i < total_grid; i++) {
4069#pragma acc parallel loop independent gang vector
4071 for (
int ip = 0; ip < np; ip++)
4073 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
4078#pragma acc atomic update
4080 cmean[idx] += atm->
q[qnt_idx][ip];
4082#pragma acc atomic update
4089#pragma acc parallel loop independent gang vector
4094#pragma omp parallel for
4096 for (
int i = 0; i < total_grid; i++)
4098 cmean[i] /= count[i];
4102#pragma acc parallel loop independent gang vector
4104#pragma omp parallel for
4106 for (
int ip = 0; ip < np; ip++) {
4108 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
4110 double mixparam = 1.0;
4119 atm->
q[qnt_idx][ip] += (cmean[idx] - atm->
q[qnt_idx][ip]) * mixparam;
4125#pragma acc exit data delete(cmean,count)
4146 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4149 const double a = 4.71572206e-08;
4150 const double b = -8.28782867e-01;
4151 const double low = pow(1. / a, 1. / b);
4155 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4181 0 ? pow(298. / t, ctl->
oh_chem[1]) : 1.);
4184 0 ? pow(298. / t, ctl->
oh_chem[3]) : 1.);
4185 const double c = log10(k0 * M / ki);
4186 k = k0 * M / (1. + k0 * M / ki) * pow(0.6, 1. / (1. + c * c));
4195 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
4198 const double rate_coef =
4200 atm->
lat[ip], atm->
p[ip]) * M * cor;
4201 const double aux = exp(-cache->
dt[ip] * rate_coef);
4202 if (ctl->
qnt_m >= 0) {
4205 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
4206 atm->
q[ctl->
qnt_m][ip] *= aux;
4227 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(cache,met0,met1,atm)") {
4238 while (atm->
lat[ip] < -90 || atm->
lat[ip] > 90) {
4239 if (atm->
lat[ip] > 90) {
4240 atm->
lat[ip] = 180 - atm->
lat[ip];
4241 atm->
lon[ip] += 180;
4243 if (atm->
lat[ip] < -90) {
4244 atm->
lat[ip] = -180 - atm->
lat[ip];
4245 atm->
lon[ip] += 180;
4250 while (atm->
lon[ip] < -180)
4251 atm->
lon[ip] += 360;
4252 while (atm->
lon[ip] >= 180)
4253 atm->
lon[ip] -= 360;
4256 if (atm->
p[ip] < met0->
p[met0->
np - 1]) {
4257 atm->
p[ip] = met0->
p[met0->
np - 1];
4258 }
else if (atm->
p[ip] > 300.) {
4260 if (atm->
p[ip] > ps)
4277 const double lambda_rn222 = log(2.0) / (3.8235 * 86400.0);
4278 const double lambda_pb210 = log(2.0) / (22.3 * 365.25 * 86400.0);
4279 const double lambda_be7 = log(2.0) / (53.22 * 86400.0);
4280 const double lambda_cs137 = log(2.0) / (30.05 * 365.25 * 86400.0);
4281 const double lambda_i131 = log(2.0) / (8.02 * 86400.0);
4282 const double lambda_xe133 = log(2.0) / (5.2474 * 86400.0);
4288 const double dt = cache->
dt[ip];
4292 atm->
q[ctl->
qnt_Apb210][ip] *= exp(-dt * lambda_pb210);
4297 const double aux = exp(-dt * lambda_rn222);
4298 const double lost = old * (1.0 - aux);
4303 atm->
q[ctl->
qnt_Apb210][ip] += lost * lambda_pb210 / lambda_rn222;
4308 atm->
q[ctl->
qnt_Abe7][ip] *= exp(-dt * lambda_be7);
4312 atm->
q[ctl->
qnt_Acs137][ip] *= exp(-dt * lambda_cs137);
4316 atm->
q[ctl->
qnt_Ai131][ip] *= exp(-dt * lambda_i131);
4320 atm->
q[ctl->
qnt_Axe133][ip] *= exp(-dt * lambda_xe133);
4330 gsl_rng_env_setup();
4331 if (omp_get_max_threads() >
NTHREADS)
4332 ERRMSG(
"Too many threads!");
4333 for (
int i = 0; i <
NTHREADS; i++) {
4334 rng[i] = gsl_rng_alloc(gsl_rng_default);
4335 gsl_rng_set(rng[i], gsl_rng_default_seed
4336 + (
long unsigned) (ntask *
NTHREADS + i));
4341 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
4342 CURAND_STATUS_SUCCESS)
4343 ERRMSG(
"Cannot create random number generator!");
4344 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
4345 CURAND_STATUS_SUCCESS)
4346 ERRMSG(
"Cannot set seed for random number generator!");
4349 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
4350 CURAND_STATUS_SUCCESS)
4351 ERRMSG(
"Cannot set stream for random number generator!");
4368#pragma omp parallel for default(shared)
4369 for (
size_t i = 0; i < n; ++i)
4370 rs[i] = gsl_rng_uniform(rng[omp_get_thread_num()]);
4374 else if (method == 1) {
4375#pragma omp parallel for default(shared)
4376 for (
size_t i = 0; i < n; ++i)
4377 rs[i] = gsl_ran_gaussian_ziggurat(rng[omp_get_thread_num()], 1.0);
4383#pragma acc update device(rs[:n])
4391 const uint64_t key = 0xc8e4fd154ce32f6d;
4395#pragma acc data present(rs)
4396#pragma acc parallel loop independent gang vector
4398#pragma omp parallel for default(shared)
4400 for (
size_t i = 0; i < n + 1; ++i) {
4401 uint64_t r, t, x, y, z;
4402 y = x = (rng_ctr + i) * key;
4405 x = (x >> 32) | (x << 32);
4407 x = (x >> 32) | (x << 32);
4409 x = (x >> 32) | (x << 32);
4411 x = (x >> 32) | (x << 32);
4412 r = t ^ ((x * x + y) >> 32);
4413 rs[i] = (double) r / (
double) UINT64_MAX;
4420#pragma acc parallel loop independent gang vector
4422#pragma omp parallel for default(shared)
4424 for (
size_t i = 0; i < n; i += 2) {
4425 const double r = sqrt(-2.0 * log(rs[i]));
4426 const double phi = 2.0 * M_PI * rs[i + 1];
4427 rs[i] = r * cosf((
float) phi);
4428 rs[i + 1] = r * sinf((
float) phi);
4436#pragma acc host_data use_device(rs)
4441 if (curandGenerateUniformDouble(rng_curand, rs, (n < 4 ? 4 : n)) !=
4442 CURAND_STATUS_SUCCESS)
4443 ERRMSG(
"Cannot create random numbers!");
4447 else if (method == 1) {
4448 if (curandGenerateNormalDouble
4449 (rng_curand, rs, (n < 4 ? 4 : n), 0.0,
4450 1.0) != CURAND_STATUS_SUCCESS)
4451 ERRMSG(
"Cannot create random numbers!");
4455 ERRMSG(
"MPTRAC was compiled without cuRAND!");
4473 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4481 const double v_s =
sedi(atm->
p[ip], t, atm->
q[ctl->
qnt_rp][ip],
4485 atm->
p[ip] +=
DZ2DP(v_s * cache->
dt[ip] / 1000., atm->
p[ip]);
4500 const int np = atm->
np;
4501 double *restrict
const a = (
double *) malloc((
size_t) np *
sizeof(double));
4502 int *restrict
const p = (
int *) malloc((
size_t) np *
sizeof(int));
4503 if (a == NULL || p == NULL)
4504 ERRMSG(
"Out of memory!");
4507#pragma acc enter data create(a[0:np],p[0:np])
4508#pragma acc data present(ctl,met0,atm,a,p)
4513#pragma acc parallel loop independent gang vector
4515#pragma omp parallel for default(shared)
4517 for (
int ip = 0; ip < np; ip++) {
4528#pragma acc host_data use_device(a,p)
4530 thrustSortWrapper(a, np, p);
4532 size_t *perm_sz = (
size_t *) malloc((
size_t) np *
sizeof(size_t));
4533 if (perm_sz == NULL)
4534 ERRMSG(
"Out of memory!");
4536#pragma acc update self(a[0:np])
4538 gsl_sort_index(perm_sz, a, 1, (
size_t) np);
4539 for (
int ip = 0; ip < np; ++ip)
4540 p[ip] = (
int) perm_sz[ip];
4543#pragma acc update device(p[0:np])
4552 for (
int iq = 0; iq < ctl->
nq; iq++)
4557#pragma acc exit data delete(a,p)
4571 double *restrict
const help =
4572 (
double *) malloc((
size_t) np *
sizeof(double));
4574 ERRMSG(
"Out of memory!");
4578#pragma acc enter data create(help[0:np])
4579#pragma acc data present(a,p,help)
4580#pragma acc parallel loop independent gang vector
4582#pragma omp parallel for default(shared)
4584 for (
int ip = 0; ip < np; ip++)
4585 help[ip] = a[p[ip]];
4587#pragma acc parallel loop independent gang vector
4589#pragma omp parallel for default(shared)
4591 for (
int ip = 0; ip < np; ip++)
4596#pragma acc exit data delete(help)
4613 const double latmin = gsl_stats_min(met0->
lat, 1, (
size_t) met0->
ny),
4614 latmax = gsl_stats_max(met0->
lat, 1, (
size_t) met0->
ny);
4617 (fabs(met0->
lon[met0->
nx - 1] - met0->
lon[0] - 360.0) >= 0.01);
4620 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,atm)") {
4626 cache->
dt[ip] = t - atm->
time[ip];
4628 cache->
dt[ip] = 0.0;
4637 if (local && (atm->
lon[ip] <= met0->
lon[0]
4638 || atm->
lon[ip] >= met0->
lon[met0->
nx - 1]
4639 || atm->
lat[ip] <= latmin || atm->
lat[ip] >= latmax))
4640 cache->
dt[ip] = 0.0;
4659 ctl->
t_start = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
4661 ctl->
t_stop = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
4663 ctl->
t_start = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
4665 ctl->
t_stop = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
4670 ERRMSG(
"Nothing to do! Check T_STOP and DIRECTION!");
4694 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4718 const double K_o1d =
ARRHENIUS(3.30e-10, 0, t) * o1d * M;
4720 atm->
p[ip], sza, o3c);
4721 atm->
q[ctl->
qnt_Cccl4][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4726 const double K_o1d =
ARRHENIUS(2.30e-10, 0, t) * o1d * M;
4728 atm->
p[ip], sza, o3c);
4729 atm->
q[ctl->
qnt_Cccl3f][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4734 const double K_o1d =
ARRHENIUS(1.40e-10, -25, t) * o1d * M;
4736 atm->
p[ip], sza, o3c);
4737 atm->
q[ctl->
qnt_Cccl2f2][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4742 const double K_o1d =
ARRHENIUS(1.19e-10, -20, t) * o1d * M;
4744 atm->
p[ip], sza, o3c);
4745 atm->
q[ctl->
qnt_Cn2o][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4764 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4767 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4773 if (!isfinite(pct) || atm->
p[ip] <= pct)
4789 double lwc, rwc, iwc, swc;
4794 const int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
4808 else if (t <= 238.15)
4828 const double K_1 = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
4829 const double K_2 = 6e-8 * exp(1.12e3 * (1. / t - 1. / 298.15));
4830 h *= (1. + K_1 / H_ion + K_1 * K_2 /
SQR(H_ion));
4834 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
4837 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
4863 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
4866 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
4871 const double aux = exp(-cache->
dt[ip] * lambda);
4872 if (ctl->
qnt_m >= 0) {
4875 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
4876 atm->
q[ctl->
qnt_m][ip] *= aux;
4901 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
4903 if (acc_get_num_devices(acc_device_nvidia) <= 0)
4904 ERRMSG(
"Not running on a GPU device!");
4905 acc_set_device_num(rank % acc_get_num_devices(acc_device_nvidia),
4907 acc_device_t device_type = acc_get_device_type();
4908 acc_init(device_type);
4924 ctl_t *ctlup = *ctl;
4927 met_t *met0up = *met0;
4928 met_t *met1up = *met1;
4929 atm_t *atmup = *atm;
4930#pragma acc enter data create(ctlup[:1],cacheup[:1],climup[:1],met0up[:1],met1up[:1],atmup[:1])
4933#pragma acc enter data create(ddup[:1])
4952#pragma acc exit data delete(ctl,cache,clim,met0,met1,atm)
4954#pragma acc exit data delete(dd)
4969 MPI_Type_free(&dd->MPI_Particle);
4988 char cachefile[
LEN], cmd[2 *
LEN], filename[
LEN];
4994 if (t == ctl->
t_start || !init) {
5001 ERRMSG(
"Cannot open file!");
5006 ERRMSG(
"Cannot open file!");
5016 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5017 LOG(1,
"Caching: %s", cachefile);
5018 if (system(cmd) != 0)
5019 WARN(
"Caching command failed!");
5024 if (t > (*met1)->time) {
5034 ERRMSG(
"Cannot open file!");
5044 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5045 LOG(1,
"Caching: %s", cachefile);
5046 if (system(cmd) != 0)
5047 WARN(
"Caching command failed!");
5052 if (t < (*met0)->time) {
5062 ERRMSG(
"Cannot open file!");
5072 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
5073 LOG(1,
"Caching: %s", cachefile);
5074 if (system(cmd) != 0)
5075 WARN(
"Caching command failed!");
5080 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
5081 if ((*met0)->nx != (*met1)->nx
5082 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
5083 ERRMSG(
"Meteo grid dimensions do not match!");
5084 for (
int ix = 0; ix < (*met0)->nx; ix++)
5085 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
5086 ERRMSG(
"Meteo grid longitudes do not match!");
5087 for (
int iy = 0; iy < (*met0)->ny; iy++)
5088 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
5089 ERRMSG(
"Meteo grid latitudes do not match!");
5090 for (
int ip = 0; ip < (*met0)->np; ip++)
5091 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
5092 ERRMSG(
"Meteo grid pressure levels do not match!");
5118 const char *filename,
5131 LOG(1,
"Read atmospheric data: %s", filename);
5151 ERRMSG(
"Atmospheric data type not supported!");
5159 ERRMSG(
"Can not read any data!");
5163 LOG(2,
"Number of particles: %d", atm->
np);
5164 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
5165 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
5166 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
5167 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
5168 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
5169 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
5170 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
5171 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
5172 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
5173 for (
int iq = 0; iq < ctl->
nq; iq++) {
5175 sprintf(msg,
"Quantity %s range: %s ... %s %s",
5178 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
5179 LOG(2, msg, mini, maxi);
5249 const char *filename,
5258 LOG(1,
"\nMassive-Parallel Trajectory Calculations (MPTRAC)\n"
5259 "(executable: %s | version: %s | compiled: %s, %s)\n",
5260 argv[0], VERSION, __DATE__, __TIME__);
5367 ctl->
nq = (int)
scan_ctl(filename, argc, argv,
"NQ", -1,
"0", NULL);
5369 ERRMSG(
"Too many quantities!");
5370 for (
int iq = 0; iq < ctl->
nq; iq++) {
5376 scan_ctl(filename, argc, argv,
"QNT_FORMAT", iq,
"%g",
5378 if (strcasecmp(ctl->
qnt_name[iq],
"aoa") == 0)
5382 SET_QNT(qnt_idx,
"idx",
"particle index",
"-")
5383 SET_QNT(qnt_ens,
"ens",
"ensemble index",
"-")
5384 SET_QNT(qnt_stat,
"stat",
"station flag",
"-")
5385 SET_QNT(qnt_m,
"m",
"mass",
"kg")
5386 SET_QNT(qnt_vmr,
"vmr",
"volume mixing ratio",
"ppv")
5387 SET_QNT(qnt_rp,
"rp",
"particle radius",
"microns")
5388 SET_QNT(qnt_rhop,
"rhop",
"particle density",
"kg/m^3")
5389 SET_QNT(qnt_ps,
"ps",
"surface pressure",
"hPa")
5390 SET_QNT(qnt_ts,
"ts",
"surface temperature",
"K")
5391 SET_QNT(qnt_zs,
"zs",
"surface height",
"km")
5392 SET_QNT(qnt_us,
"us",
"surface zonal wind",
"m/s")
5393 SET_QNT(qnt_vs,
"vs",
"surface meridional wind",
"m/s")
5394 SET_QNT(qnt_ess,
"ess",
"eastward turbulent surface stress",
"N/m^2")
5395 SET_QNT(qnt_nss,
"nss",
"northward turbulent surface stress",
"N/m^2")
5396 SET_QNT(qnt_shf,
"shf",
"surface sensible heat flux",
"W/m^2")
5397 SET_QNT(qnt_lsm,
"lsm",
"land-sea mask",
"1")
5398 SET_QNT(qnt_sst,
"sst",
"sea surface temperature",
"K")
5399 SET_QNT(qnt_pbl,
"pbl",
"planetary boundary layer",
"hPa")
5400 SET_QNT(qnt_pt,
"pt",
"tropopause pressure",
"hPa")
5401 SET_QNT(qnt_tt,
"tt",
"tropopause temperature",
"K")
5402 SET_QNT(qnt_zt,
"zt",
"tropopause geopotential height",
"km")
5403 SET_QNT(qnt_h2ot,
"h2ot",
"tropopause water vapor",
"ppv")
5404 SET_QNT(qnt_zg,
"zg",
"geopotential height",
"km")
5405 SET_QNT(qnt_p,
"p",
"pressure",
"hPa")
5406 SET_QNT(qnt_t,
"t",
"temperature",
"K")
5407 SET_QNT(qnt_rho,
"rho",
"air density",
"kg/m^3")
5408 SET_QNT(qnt_u,
"u",
"zonal wind",
"m/s")
5409 SET_QNT(qnt_v,
"v",
"meridional wind",
"m/s")
5410 SET_QNT(qnt_w,
"w",
"vertical velocity",
"hPa/s")
5411 SET_QNT(qnt_h2o,
"h2o",
"water vapor",
"ppv")
5412 SET_QNT(qnt_o3,
"o3",
"ozone",
"ppv")
5413 SET_QNT(qnt_lwc,
"lwc",
"cloud liquid water content",
"kg/kg")
5414 SET_QNT(qnt_rwc,
"rwc",
"cloud rain water content",
"kg/kg")
5415 SET_QNT(qnt_iwc,
"iwc",
"cloud ice water content",
"kg/kg")
5416 SET_QNT(qnt_swc,
"swc",
"cloud snow water content",
"kg/kg")
5417 SET_QNT(qnt_cc,
"cc",
"cloud cover",
"1")
5418 SET_QNT(qnt_pct,
"pct",
"cloud top pressure",
"hPa")
5419 SET_QNT(qnt_pcb,
"pcb",
"cloud bottom pressure",
"hPa")
5420 SET_QNT(qnt_cl,
"cl",
"total column cloud water",
"kg/m^2")
5421 SET_QNT(qnt_plcl,
"plcl",
"lifted condensation level",
"hPa")
5422 SET_QNT(qnt_plfc,
"plfc",
"level of free convection",
"hPa")
5423 SET_QNT(qnt_pel,
"pel",
"equilibrium level",
"hPa")
5424 SET_QNT(qnt_cape,
"cape",
"convective available potential energy",
5426 SET_QNT(qnt_cin,
"cin",
"convective inhibition",
"J/kg")
5427 SET_QNT(qnt_o3c,
"o3c",
"total column ozone",
"DU")
5428 SET_QNT(qnt_hno3,
"hno3",
"nitric acid",
"ppv")
5429 SET_QNT(qnt_oh,
"oh",
"hydroxyl radical",
"ppv")
5430 SET_QNT(qnt_h2o2,
"h2o2",
"hydrogen peroxide",
"ppv")
5431 SET_QNT(qnt_ho2,
"ho2",
"hydroperoxyl radical",
"ppv")
5432 SET_QNT(qnt_o1d,
"o1d",
"atomic oxygen",
"ppv")
5433 SET_QNT(qnt_mloss_oh,
"mloss_oh",
"mass loss due to OH chemistry",
"kg")
5434 SET_QNT(qnt_mloss_h2o2,
"mloss_h2o2",
5435 "mass loss due to H2O2 chemistry",
"kg")
5436 SET_QNT(qnt_mloss_kpp,
"mloss_kpp",
"mass loss due to kpp chemistry",
5438 SET_QNT(qnt_mloss_wet,
"mloss_wet",
"mass loss due to wet deposition",
5440 SET_QNT(qnt_mloss_dry,
"mloss_dry",
"mass loss due to dry deposition",
5442 SET_QNT(qnt_mloss_decay,
"mloss_decay",
5443 "mass loss due to exponential decay",
"kg")
5444 SET_QNT(qnt_loss_rate,
"loss_rate",
"total loss rate",
"s^-1")
5445 SET_QNT(qnt_psat,
"psat",
"saturation pressure over water",
"hPa")
5446 SET_QNT(qnt_psice,
"psice",
"saturation pressure over ice",
"hPa")
5447 SET_QNT(qnt_pw,
"pw",
"partial water vapor pressure",
"hPa")
5448 SET_QNT(qnt_sh,
"sh",
"specific humidity",
"kg/kg")
5449 SET_QNT(qnt_rh,
"rh",
"relative humidity",
"%%")
5450 SET_QNT(qnt_rhice,
"rhice",
"relative humidity over ice",
"%%")
5451 SET_QNT(qnt_theta,
"theta",
"potential temperature",
"K")
5452 SET_QNT(qnt_zeta,
"zeta",
"zeta coordinate",
"K")
5453 SET_QNT(qnt_zeta_d,
"zeta_d",
"diagnosed zeta coordinate",
"K")
5454 SET_QNT(qnt_zeta_dot,
"zeta_dot",
"velocity of zeta coordinate",
5456 SET_QNT(qnt_eta,
"eta",
"eta coordinate",
"1")
5457 SET_QNT(qnt_eta_dot,
"eta_dot",
"velocity of eta coordinate",
"1/s")
5458 SET_QNT(qnt_tvirt,
"tvirt",
"virtual temperature",
"K")
5459 SET_QNT(qnt_lapse,
"lapse",
"temperature lapse rate",
"K/km")
5460 SET_QNT(qnt_vh,
"vh",
"horizontal velocity",
"m/s")
5461 SET_QNT(qnt_vz,
"vz",
"vertical velocity",
"m/s")
5462 SET_QNT(qnt_pv,
"pv",
"potential vorticity",
"PVU")
5463 SET_QNT(qnt_tdew,
"tdew",
"dew point temperature",
"K")
5464 SET_QNT(qnt_tice,
"tice",
"frost point temperature",
"K")
5465 SET_QNT(qnt_tsts,
"tsts",
"STS existence temperature",
"K")
5466 SET_QNT(qnt_tnat,
"tnat",
"NAT existence temperature",
"K")
5467 SET_QNT(qnt_Cx,
"Cx",
"Trace species x volume mixing ratio",
"ppv")
5468 SET_QNT(qnt_Ch2o,
"Ch2o",
"H2O volume mixing ratio",
"ppv")
5469 SET_QNT(qnt_Co3,
"Co3",
"O3 volume mixing ratio",
"ppv")
5470 SET_QNT(qnt_Cco,
"Cco",
"CO volume mixing ratio",
"ppv")
5471 SET_QNT(qnt_Coh,
"Coh",
"HO volume mixing ratio",
"ppv")
5472 SET_QNT(qnt_Ch,
"Ch",
"H radical volume mixing ratio",
"ppv")
5473 SET_QNT(qnt_Cho2,
"Cho2",
"HO2 volume mixing ratio",
"ppv")
5474 SET_QNT(qnt_Ch2o2,
"Ch2o2",
"H2O2 volume mixing ratio",
"ppv")
5475 SET_QNT(qnt_Co1d,
"Co1d",
"O(1D) volume mixing ratio",
"ppv")
5476 SET_QNT(qnt_Co3p,
"Co3p",
"O(3P) radical volume mixing ratio",
"ppv")
5477 SET_QNT(qnt_Cccl4,
"Cccl4",
"CCl4 (CFC-10) volume mixing ratio",
"ppv")
5478 SET_QNT(qnt_Cccl3f,
"Cccl3f",
"CCl3F (CFC-11) volume mixing ratio",
5480 SET_QNT(qnt_Cccl2f2,
"Cccl2f2",
"CCl2F2 (CFC-12) volume mixing ratio",
5482 SET_QNT(qnt_Cn2o,
"Cn2o",
"N2O volume mixing ratio",
"ppv")
5483 SET_QNT(qnt_Csf6,
"Csf6",
"SF6 volume mixing ratio",
"ppv")
5484 SET_QNT(qnt_aoa,
"aoa",
"age of air",
"s")
5485 SET_QNT(qnt_Arn222,
"Arn222",
"Rn-222 activity",
"Bq")
5486 SET_QNT(qnt_Apb210,
"Apb210",
"Pb-210 activity",
"Bq")
5487 SET_QNT(qnt_Abe7,
"Abe7",
"Be-7 activity",
"Bq")
5488 SET_QNT(qnt_Acs137,
"Acs137",
"Cs-137 activity",
"Bq")
5489 SET_QNT(qnt_Ai131,
"Ai131",
"I-131 activity",
"Bq")
5490 SET_QNT(qnt_Axe133,
"Axe133",
"Xe-133 activity",
"Bq")
5491 SET_QNT(qnt_subdomain,
"subdomain",
"current subdomain index",
"-")
5492 SET_QNT(qnt_destination,
"destination",
5493 "subdomain index of destination",
"-")
5499 (int)
scan_ctl(filename, argc, argv,
"ADVECT_VERT_COORD", -1,
"0", NULL);
5501 ERRMSG(
"ADVECT_VERT_COORD must be 0, 1, 2, or 3!");
5504 ERRMSG(
"Add quantity zeta for diabatic advection!");
5506 ERRMSG(
"Add quantity eta for etadot avection!");
5509 (int)
scan_ctl(filename, argc, argv,
"MET_VERT_COORD", -1,
"0", NULL);
5511 ERRMSG(
"MET_VERT_COORD must be 0, 1, 2, 3, or 4!");
5515 (
"Using ADVECT_VERT_COORD = 2 requires meteo data on model levels!");
5518 (
"Using ADVECT_VERT_COORD = 3 requires A and B model level coefficients!");
5522 (int)
scan_ctl(filename, argc, argv,
"DIRECTION", -1,
"1", NULL);
5524 ERRMSG(
"Set DIRECTION to -1 or 1!");
5525 ctl->
t_stop =
scan_ctl(filename, argc, argv,
"T_STOP", -1,
"1e100", NULL);
5526 ctl->
dt_mod =
scan_ctl(filename, argc, argv,
"DT_MOD", -1,
"180", NULL);
5530 ctl->
dt_met =
scan_ctl(filename, argc, argv,
"DT_MET", -1,
"3600", NULL);
5532 (int)
scan_ctl(filename, argc, argv,
"MET_CONVENTION", -1,
"0", NULL);
5534 (int)
scan_ctl(filename, argc, argv,
"MET_TYPE", -1,
"0", NULL);
5537 (
"Please use meteo files in netcdf format for diabatic calculations.");
5540 (
"Please use meteo files in netcdf format for etadot calculations.");
5542 (int)
scan_ctl(filename, argc, argv,
"MET_CLAMS", -1,
"0", NULL);
5544 (int)
scan_ctl(filename, argc, argv,
"MET_NC_SCALE", -1,
"1", NULL);
5546 (int)
scan_ctl(filename, argc, argv,
"MET_NC_LEVEL", -1,
"0", NULL);
5548 (int)
scan_ctl(filename, argc, argv,
"MET_NC_QUANT", -1,
"0", NULL);
5550 (int)
scan_ctl(filename, argc, argv,
"MET_ZSTD_LEVEL", -1,
"0", NULL);
5551 for (
int i = 0; i <
METVAR; i++) {
5552 char defprec[
LEN] =
"0", deftol[
LEN] =
"0.0";
5554 sprintf(deftol,
"0.5");
5556 sprintf(deftol,
"5.0");
5558 sprintf(defprec,
"8");
5560 (int)
scan_ctl(filename, argc, argv,
"MET_COMP_PREC", i, defprec, NULL);
5562 scan_ctl(filename, argc, argv,
"MET_COMP_TOL", i, deftol, NULL);
5565 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_BATCH", -1,
"-1", NULL);
5567 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ZSTD", -1,
"1", NULL);
5569 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ND0X", -1,
"48", NULL);
5571 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ND0Y", -1,
"24", NULL);
5573 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_MAXLEV", -1,
"6", NULL);
5575 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_Z", -1,
"1.0", NULL);
5577 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_T", -1,
"0.05", NULL);
5579 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_U", -1,
"0.05", NULL);
5581 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_V", -1,
"0.05", NULL);
5583 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_W", -1,
"1.0", NULL);
5585 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_PV", -1,
"1.0", NULL);
5587 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_H2O", -1,
"1.0", NULL);
5589 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_O3", -1,
"1.0", NULL);
5591 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_LWC", -1,
"1.0", NULL);
5593 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_RWC", -1,
"1.0", NULL);
5595 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_IWC", -1,
"1.0", NULL);
5597 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_SWC", -1,
"1.0", NULL);
5599 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_CC", -1,
"1.0", NULL);
5600 ctl->
met_dx = (int)
scan_ctl(filename, argc, argv,
"MET_DX", -1,
"1", NULL);
5601 ctl->
met_dy = (int)
scan_ctl(filename, argc, argv,
"MET_DY", -1,
"1", NULL);
5602 ctl->
met_dp = (int)
scan_ctl(filename, argc, argv,
"MET_DP", -1,
"1", NULL);
5604 ERRMSG(
"MET_DX, MET_DY, and MET_DP need to be greater than zero!");
5605 ctl->
met_sx = (int)
scan_ctl(filename, argc, argv,
"MET_SX", -1,
"1", NULL);
5606 ctl->
met_sy = (int)
scan_ctl(filename, argc, argv,
"MET_SY", -1,
"1", NULL);
5607 ctl->
met_sp = (int)
scan_ctl(filename, argc, argv,
"MET_SP", -1,
"1", NULL);
5609 ERRMSG(
"MET_SX, MET_SY, and MET_SP need to be greater than zero!");
5611 scan_ctl(filename, argc, argv,
"MET_DETREND", -1,
"-999", NULL);
5612 ctl->
met_np = (int)
scan_ctl(filename, argc, argv,
"MET_NP", -1,
"0", NULL);
5614 ERRMSG(
"Too many pressure levels!");
5616 (int)
scan_ctl(filename, argc, argv,
"MET_PRESS_LEVEL_DEF", -1,
"-1",
5622 for (
int ip = 0; ip < ctl->
met_np; ip++)
5624 scan_ctl(filename, argc, argv,
"MET_P", ip,
"", NULL);
5628 (int)
scan_ctl(filename, argc, argv,
"MET_NLEV", -1,
"0", NULL);
5630 ERRMSG(
"Too many model levels!");
5631 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
5633 scan_ctl(filename, argc, argv,
"MET_LEV_HYAM", ip,
"", NULL);
5634 for (
int ip = 0; ip < ctl->
met_nlev; ip++)
5636 scan_ctl(filename, argc, argv,
"MET_LEV_HYBM", ip,
"", NULL);
5638 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SX", -1,
"-1", NULL);
5640 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SY", -1,
"-1", NULL);
5642 (int)
scan_ctl(filename, argc, argv,
"MET_RELHUM", -1,
"0", NULL);
5644 (int)
scan_ctl(filename, argc, argv,
"MET_CAPE", -1,
"1", NULL);
5646 ERRMSG(
"Set MET_CAPE to 0 or 1!");
5648 (int)
scan_ctl(filename, argc, argv,
"MET_PBL", -1,
"3", NULL);
5650 ERRMSG(
"Set MET_PBL to 0 ... 3!");
5652 scan_ctl(filename, argc, argv,
"MET_PBL_MIN", -1,
"0.1", NULL);
5654 scan_ctl(filename, argc, argv,
"MET_PBL_MAX", -1,
"5.0", NULL);
5656 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO", -1,
"3", NULL);
5658 ERRMSG(
"Set MET_TROPO to 0 ... 5!");
5660 scan_ctl(filename, argc, argv,
"MET_TROPO_PV", -1,
"3.5", NULL);
5662 scan_ctl(filename, argc, argv,
"MET_TROPO_THETA", -1,
"380", NULL);
5664 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO_SPLINE", -1,
"1", NULL);
5666 scan_ctl(filename, argc, argv,
"MET_DT_OUT", -1,
"0.1", NULL);
5668 (int)
scan_ctl(filename, argc, argv,
"MET_CACHE", -1,
"0", NULL);
5670 (int)
scan_ctl(filename, argc, argv,
"MET_MPI_SHARE", -1,
"0", NULL);
5673 ctl->
sort_dt =
scan_ctl(filename, argc, argv,
"SORT_DT", -1,
"-999", NULL);
5677 (int)
scan_ctl(filename, argc, argv,
"ISOSURF", -1,
"0", NULL);
5682 (int)
scan_ctl(filename, argc, argv,
"RNG_TYPE", -1,
"1", NULL);
5684 ERRMSG(
"Set RNG_TYPE to 0, 1, or 2!");
5687 ctl->
advect = (int)
scan_ctl(filename, argc, argv,
"ADVECT", -1,
"2", NULL);
5691 ERRMSG(
"Set ADVECT to 0, 1, 2, or 4!");
5695 = (int)
scan_ctl(filename, argc, argv,
"DIFFUSION", -1,
"0", NULL);
5697 ERRMSG(
"Set DIFFUSION to 0, 1 or 2!");
5699 scan_ctl(filename, argc, argv,
"TURB_DX_PBL", -1,
"50", NULL);
5701 scan_ctl(filename, argc, argv,
"TURB_DX_TROP", -1,
"50", NULL);
5703 scan_ctl(filename, argc, argv,
"TURB_DX_STRAT", -1,
"0", NULL);
5705 scan_ctl(filename, argc, argv,
"TURB_DZ_PBL", -1,
"0", NULL);
5707 scan_ctl(filename, argc, argv,
"TURB_DZ_TROP", -1,
"0", NULL);
5709 scan_ctl(filename, argc, argv,
"TURB_DZ_STRAT", -1,
"0.1", NULL);
5711 scan_ctl(filename, argc, argv,
"TURB_MESOX", -1,
"0.16", NULL);
5713 scan_ctl(filename, argc, argv,
"TURB_MESOZ", -1,
"0.16", NULL);
5717 = (int)
scan_ctl(filename, argc, argv,
"CONV_MIX_PBL", -1,
"0", NULL);
5719 =
scan_ctl(filename, argc, argv,
"CONV_PBL_TRANS", -1,
"0", NULL);
5721 =
scan_ctl(filename, argc, argv,
"CONV_CAPE", -1,
"-999", NULL);
5723 =
scan_ctl(filename, argc, argv,
"CONV_CIN", -1,
"-999", NULL);
5724 ctl->
conv_dt =
scan_ctl(filename, argc, argv,
"CONV_DT", -1,
"-999", NULL);
5728 scan_ctl(filename, argc, argv,
"BOUND_MASS", -1,
"-999", NULL);
5730 scan_ctl(filename, argc, argv,
"BOUND_MASS_TREND", -1,
"0", NULL);
5732 scan_ctl(filename, argc, argv,
"BOUND_VMR", -1,
"-999", NULL);
5734 scan_ctl(filename, argc, argv,
"BOUND_VMR_TREND", -1,
"0", NULL);
5736 scan_ctl(filename, argc, argv,
"BOUND_LAT0", -1,
"-999", NULL);
5738 scan_ctl(filename, argc, argv,
"BOUND_LAT1", -1,
"-999", NULL);
5740 scan_ctl(filename, argc, argv,
"BOUND_P0", -1,
"-999", NULL);
5742 scan_ctl(filename, argc, argv,
"BOUND_P1", -1,
"-999", NULL);
5744 scan_ctl(filename, argc, argv,
"BOUND_DPS", -1,
"-999", NULL);
5746 scan_ctl(filename, argc, argv,
"BOUND_DZS", -1,
"-999", NULL);
5748 scan_ctl(filename, argc, argv,
"BOUND_ZETAS", -1,
"-999", NULL);
5750 (int)
scan_ctl(filename, argc, argv,
"BOUND_PBL", -1,
"0", NULL);
5754 if (strcasecmp(ctl->
species,
"CF2Cl2") == 0) {
5758 }
else if (strcasecmp(ctl->
species,
"CFCl3") == 0) {
5762 }
else if (strcasecmp(ctl->
species,
"CH4") == 0) {
5769 }
else if (strcasecmp(ctl->
species,
"CO") == 0) {
5778 }
else if (strcasecmp(ctl->
species,
"CO2") == 0) {
5782 }
else if (strcasecmp(ctl->
species,
"H2O") == 0) {
5784 }
else if (strcasecmp(ctl->
species,
"N2O") == 0) {
5788 }
else if (strcasecmp(ctl->
species,
"NH3") == 0) {
5795 }
else if (strcasecmp(ctl->
species,
"HNO3") == 0) {
5799 }
else if (strcasecmp(ctl->
species,
"NO") == 0) {
5808 }
else if (strcasecmp(ctl->
species,
"NO2") == 0) {
5817 }
else if (strcasecmp(ctl->
species,
"O3") == 0) {
5824 }
else if (strcasecmp(ctl->
species,
"SF6") == 0) {
5828 }
else if (strcasecmp(ctl->
species,
"SO2") == 0) {
5841 sprintf(defstr,
"%g", ctl->
molmass);
5842 ctl->
molmass =
scan_ctl(filename, argc, argv,
"MOLMASS", -1, defstr, NULL);
5847 (int)
scan_ctl(filename, argc, argv,
"OH_CHEM_REACTION", -1, defstr,
5849 for (
int ip = 0; ip < 4; ip++) {
5850 sprintf(defstr,
"%g", ctl->
oh_chem[ip]);
5852 scan_ctl(filename, argc, argv,
"OH_CHEM", ip, defstr, NULL);
5855 scan_ctl(filename, argc, argv,
"OH_CHEM_BETA", -1,
"0", NULL);
5859 (int)
scan_ctl(filename, argc, argv,
"H2O2_CHEM_REACTION", -1,
"0", NULL);
5863 (int)
scan_ctl(filename, argc, argv,
"KPP_CHEM", -1,
"0", NULL);
5864 ctl->
dt_kpp =
scan_ctl(filename, argc, argv,
"DT_KPP", -1,
"1800", NULL);
5868 (int)
scan_ctl(filename, argc, argv,
"TRACER_CHEM", -1,
"0", NULL);
5872 (int)
scan_ctl(filename, argc, argv,
"RADIO_DECAY", -1,
"0", NULL);
5875 for (
int ip = 0; ip < 2; ip++) {
5878 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_H", ip, defstr, NULL);
5880 for (
int ip = 0; ip < 1; ip++) {
5883 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_H", ip, defstr, NULL);
5886 scan_ctl(filename, argc, argv,
"WET_DEPO_SO2_PH", -1,
"0", NULL);
5888 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_A", -1,
"0", NULL);
5890 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_B", -1,
"0", NULL);
5892 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_A", -1,
"0", NULL);
5894 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_B", -1,
"0", NULL);
5896 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 0,
"0.5", NULL);
5898 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 1,
"0.36", NULL);
5900 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_RET_RATIO", -1,
"1", NULL);
5902 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_RET_RATIO", -1,
"1", NULL);
5906 scan_ctl(filename, argc, argv,
"DRY_DEPO_VDEP", -1,
"0", NULL);
5908 scan_ctl(filename, argc, argv,
"DRY_DEPO_DP", -1,
"30", NULL);
5911 scan_ctl(filename, argc, argv,
"CLIM_PHOTO", -1,
5912 "../../data/clams_photolysis_rates.nc", ctl->
clim_photo);
5913 scan_ctl(filename, argc, argv,
"CLIM_HNO3_FILENAME", -1,
5915 scan_ctl(filename, argc, argv,
"CLIM_OH_FILENAME", -1,
5917 scan_ctl(filename, argc, argv,
"CLIM_H2O2_FILENAME", -1,
5919 scan_ctl(filename, argc, argv,
"CLIM_HO2_FILENAME", -1,
5921 scan_ctl(filename, argc, argv,
"CLIM_O1D_FILENAME", -1,
5923 scan_ctl(filename, argc, argv,
"CLIM_CCL4_TIMESERIES", -1,
5925 scan_ctl(filename, argc, argv,
"CLIM_CCL3F_TIMESERIES", -1,
5927 scan_ctl(filename, argc, argv,
"CLIM_CCL2F2_TIMESERIES", -1,
5929 scan_ctl(filename, argc, argv,
"CLIM_N2O_TIMESERIES", -1,
5931 scan_ctl(filename, argc, argv,
"CLIM_SF6_TIMESERIES", -1,
5936 scan_ctl(filename, argc, argv,
"MIXING_DT", -1,
"3600.", NULL);
5938 scan_ctl(filename, argc, argv,
"MIXING_TROP", -1,
"-999", NULL);
5940 scan_ctl(filename, argc, argv,
"MIXING_STRAT", -1,
"-999", NULL);
5942 scan_ctl(filename, argc, argv,
"MIXING_Z0", -1,
"-5", NULL);
5944 scan_ctl(filename, argc, argv,
"MIXING_Z1", -1,
"85", NULL);
5946 (int)
scan_ctl(filename, argc, argv,
"MIXING_NZ", -1,
"90", NULL);
5948 scan_ctl(filename, argc, argv,
"MIXING_LON0", -1,
"-180", NULL);
5950 scan_ctl(filename, argc, argv,
"MIXING_LON1", -1,
"180", NULL);
5952 (int)
scan_ctl(filename, argc, argv,
"MIXING_NX", -1,
"360", NULL);
5954 scan_ctl(filename, argc, argv,
"MIXING_LAT0", -1,
"-90", NULL);
5956 scan_ctl(filename, argc, argv,
"MIXING_LAT1", -1,
"90", NULL);
5958 (int)
scan_ctl(filename, argc, argv,
"MIXING_NY", -1,
"180", NULL);
5962 scan_ctl(filename, argc, argv,
"CHEMGRID_Z0", -1,
"-5", NULL);
5964 scan_ctl(filename, argc, argv,
"CHEMGRID_Z1", -1,
"85", NULL);
5966 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NZ", -1,
"90", NULL);
5968 scan_ctl(filename, argc, argv,
"CHEMGRID_LON0", -1,
"-180", NULL);
5970 scan_ctl(filename, argc, argv,
"CHEMGRID_LON1", -1,
"180", NULL);
5972 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NX", -1,
"360", NULL);
5974 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT0", -1,
"-90", NULL);
5976 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT1", -1,
"90", NULL);
5978 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NY", -1,
"180", NULL);
5983 scan_ctl(filename, argc, argv,
"TDEC_STRAT", -1,
"0", NULL);
5986 ctl->
psc_h2o =
scan_ctl(filename, argc, argv,
"PSC_H2O", -1,
"4e-6", NULL);
5988 scan_ctl(filename, argc, argv,
"PSC_HNO3", -1,
"9e-9", NULL);
5994 scan_ctl(filename, argc, argv,
"ATM_DT_OUT", -1,
"86400", NULL);
5996 (int)
scan_ctl(filename, argc, argv,
"ATM_FILTER", -1,
"0", NULL);
5998 (int)
scan_ctl(filename, argc, argv,
"ATM_STRIDE", -1,
"1", NULL);
6000 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE", -1,
"0", NULL);
6002 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE_OUT", -1,
"-1", NULL);
6006 (int)
scan_ctl(filename, argc, argv,
"ATM_NC_LEVEL", -1,
"0", NULL);
6007 for (
int iq = 0; iq < ctl->
nq; iq++)
6009 (
int)
scan_ctl(filename, argc, argv,
"ATM_NC_QUANT", iq,
"0", NULL);
6011 (int)
scan_ctl(filename, argc, argv,
"OBS_TYPE", -1,
"0", NULL);
6017 scan_ctl(filename, argc, argv,
"CSI_DT_OUT", -1,
"86400", NULL);
6020 scan_ctl(filename, argc, argv,
"CSI_OBSMIN", -1,
"0", NULL);
6022 scan_ctl(filename, argc, argv,
"CSI_MODMIN", -1,
"0", NULL);
6023 ctl->
csi_z0 =
scan_ctl(filename, argc, argv,
"CSI_Z0", -1,
"-5", NULL);
6024 ctl->
csi_z1 =
scan_ctl(filename, argc, argv,
"CSI_Z1", -1,
"85", NULL);
6025 ctl->
csi_nz = (int)
scan_ctl(filename, argc, argv,
"CSI_NZ", -1,
"1", NULL);
6027 scan_ctl(filename, argc, argv,
"CSI_LON0", -1,
"-180", NULL);
6028 ctl->
csi_lon1 =
scan_ctl(filename, argc, argv,
"CSI_LON1", -1,
"180", NULL);
6030 (int)
scan_ctl(filename, argc, argv,
"CSI_NX", -1,
"360", NULL);
6031 ctl->
csi_lat0 =
scan_ctl(filename, argc, argv,
"CSI_LAT0", -1,
"-90", NULL);
6032 ctl->
csi_lat1 =
scan_ctl(filename, argc, argv,
"CSI_LAT1", -1,
"90", NULL);
6034 (int)
scan_ctl(filename, argc, argv,
"CSI_NY", -1,
"180", NULL);
6037 ctl->
nens = (int)
scan_ctl(filename, argc, argv,
"NENS", -1,
"0", NULL);
6040 scan_ctl(filename, argc, argv,
"ENS_DT_OUT", -1,
"86400", NULL);
6043 scan_ctl(filename, argc, argv,
"GRID_BASENAME", -1,
"-",
6048 scan_ctl(filename, argc, argv,
"GRID_DT_OUT", -1,
"86400", NULL);
6050 (int)
scan_ctl(filename, argc, argv,
"GRID_SPARSE", -1,
"0", NULL);
6052 (int)
scan_ctl(filename, argc, argv,
"GRID_NC_LEVEL", -1,
"0", NULL);
6053 for (
int iq = 0; iq < ctl->
nq; iq++)
6055 (
int)
scan_ctl(filename, argc, argv,
"GRID_NC_QUANT", iq,
"0", NULL);
6057 (int)
scan_ctl(filename, argc, argv,
"GRID_STDDEV", -1,
"0", NULL);
6058 ctl->
grid_z0 =
scan_ctl(filename, argc, argv,
"GRID_Z0", -1,
"-5", NULL);
6059 ctl->
grid_z1 =
scan_ctl(filename, argc, argv,
"GRID_Z1", -1,
"85", NULL);
6061 (int)
scan_ctl(filename, argc, argv,
"GRID_NZ", -1,
"1", NULL);
6063 scan_ctl(filename, argc, argv,
"GRID_LON0", -1,
"-180", NULL);
6065 scan_ctl(filename, argc, argv,
"GRID_LON1", -1,
"180", NULL);
6067 (int)
scan_ctl(filename, argc, argv,
"GRID_NX", -1,
"360", NULL);
6069 scan_ctl(filename, argc, argv,
"GRID_LAT0", -1,
"-90", NULL);
6071 scan_ctl(filename, argc, argv,
"GRID_LAT1", -1,
"90", NULL);
6073 (int)
scan_ctl(filename, argc, argv,
"GRID_NY", -1,
"180", NULL);
6075 (int)
scan_ctl(filename, argc, argv,
"GRID_TYPE", -1,
"0", NULL);
6078 scan_ctl(filename, argc, argv,
"PROF_BASENAME", -1,
"-",
6081 ctl->
prof_z0 =
scan_ctl(filename, argc, argv,
"PROF_Z0", -1,
"0", NULL);
6082 ctl->
prof_z1 =
scan_ctl(filename, argc, argv,
"PROF_Z1", -1,
"60", NULL);
6084 (int)
scan_ctl(filename, argc, argv,
"PROF_NZ", -1,
"60", NULL);
6086 scan_ctl(filename, argc, argv,
"PROF_LON0", -1,
"-180", NULL);
6088 scan_ctl(filename, argc, argv,
"PROF_LON1", -1,
"180", NULL);
6090 (int)
scan_ctl(filename, argc, argv,
"PROF_NX", -1,
"360", NULL);
6092 scan_ctl(filename, argc, argv,
"PROF_LAT0", -1,
"-90", NULL);
6094 scan_ctl(filename, argc, argv,
"PROF_LAT1", -1,
"90", NULL);
6096 (int)
scan_ctl(filename, argc, argv,
"PROF_NY", -1,
"180", NULL);
6099 scan_ctl(filename, argc, argv,
"SAMPLE_BASENAME", -1,
"-",
6101 scan_ctl(filename, argc, argv,
"SAMPLE_KERNEL", -1,
"-",
6103 scan_ctl(filename, argc, argv,
"SAMPLE_OBSFILE", -1,
"-",
6106 scan_ctl(filename, argc, argv,
"SAMPLE_DX", -1,
"50", NULL);
6108 scan_ctl(filename, argc, argv,
"SAMPLE_DZ", -1,
"-999", NULL);
6111 scan_ctl(filename, argc, argv,
"STAT_BASENAME", -1,
"-",
6115 ctl->
stat_r =
scan_ctl(filename, argc, argv,
"STAT_R", -1,
"50", NULL);
6117 scan_ctl(filename, argc, argv,
"STAT_T0", -1,
"-1e100", NULL);
6118 ctl->
stat_t1 =
scan_ctl(filename, argc, argv,
"STAT_T1", -1,
"1e100", NULL);
6123 scan_ctl(filename, argc, argv,
"VTK_DT_OUT", -1,
"86400", NULL);
6125 (int)
scan_ctl(filename, argc, argv,
"VTK_STRIDE", -1,
"1", NULL);
6127 scan_ctl(filename, argc, argv,
"VTK_SCALE", -1,
"1.0", NULL);
6129 scan_ctl(filename, argc, argv,
"VTK_OFFSET", -1,
"0.0", NULL);
6131 (int)
scan_ctl(filename, argc, argv,
"VTK_SPHERE", -1,
"0", NULL);
6134 ctl->
dd = (int)
scan_ctl(filename, argc, argv,
"DD", -1,
"0", NULL);
6136 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_MERIDIONAL", -1,
6137 (ctl->
dd == 1) ?
"2" :
"1", NULL);
6139 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_ZONAL", -1,
6140 (ctl->
dd == 1) ?
"2" :
"1", NULL);
6143 else if (ctl->
dd == 1)
6144 ERRMSG(
"Please provide zonal and meridional subdomain numbers!");
6146 (int)
scan_ctl(filename, argc, argv,
"DD_HALOS_SIZE", -1,
"1", NULL);
6152 const char *filename,
6159 LOG(1,
"Read meteo data: %s", filename);
6165 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
6193 ERRMSG(
"MET_TYPE not implemented!");
6247 LOG(2,
"Broadcast data on rank %d...", rank);
6381 ERRMSG(
"Code was compiled without DD!");
6393 ERRMSG(
"Code was compiled without KPP!");
6426#pragma acc update device(ctl[:1])
6430 if (cache != NULL) {
6433#pragma acc update device(cache[:1])
6440#pragma acc update device(clim[:1])
6447 met_t *met0up = *met0;
6448#pragma acc update device(met0up[:1])
6455 met_t *met1up = *met1;
6456#pragma acc update device(met1up[:1])
6463#pragma acc update device(atm[:1])
6482#pragma acc update host(ctl[:1])
6486 if (cache != NULL) {
6489#pragma acc update host(cache[:1])
6496#pragma acc update host(clim[:1])
6503 met_t *met0up = *met0;
6504#pragma acc update host(met0up[:1])
6511 met_t *met1up = *met1;
6512#pragma acc update host(met1up[:1])
6519#pragma acc update host(atm[:1])
6527 const char *filename,
6536 LOG(1,
"Write atmospheric data: %s", filename);
6560 ERRMSG(
"Atmospheric data type not supported!");
6564 LOG(2,
"Number of particles: %d", atm->
np);
6565 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
6566 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
6567 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
6568 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
6569 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
6570 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
6571 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
6572 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
6573 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
6574 for (
int iq = 0; iq < ctl->
nq; iq++) {
6576 sprintf(msg,
"Quantity %s range: %s ... %s %s",
6579 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
6580 LOG(2, msg, mini, maxi);
6587 const char *filename,
6595 LOG(1,
"Write meteo data: %s", filename);
6600 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
6604 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
6608 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
6612 ERRMSG(
"MPTRAC was compiled without SZ3 compression!");
6625 ERRMSG(
"MET_TYPE not implemented!");
6631 const char *dirname,
6638 char ext[10], filename[2 *
LEN];
6642 int year, mon, day, hour, min, sec;
6645 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
6660 sprintf(ext,
"tab");
6662 sprintf(ext,
"bin");
6665 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6666 dirname, ctl->
atm_basename, year, mon, day, hour, min, ext);
6672 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
6675 write_grid(filename, ctl, met0, met1, atm, t);
6680 sprintf(filename,
"%s/%s.tab", dirname, ctl->
csi_basename);
6686 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.tab",
6687 dirname, ctl->
ens_basename, year, mon, day, hour, min);
6693 sprintf(filename,
"%s/%s.tab", dirname, ctl->
prof_basename);
6694 write_prof(filename, ctl, met0, met1, atm, t);
6705 sprintf(filename,
"%s/%s.tab", dirname, ctl->
stat_basename);
6714 sprintf(filename,
"%s/%s_%05d.vtk", dirname, ctl->
vtk_basename, ++nvtk);
6724 const double hno3) {
6727 const double h2o_help =
MAX(h2o, 0.1e-6);
6730 const double p_hno3 = hno3 * p / 1.333224;
6731 const double p_h2o = h2o_help * p / 1.333224;
6732 const double a = 0.009179 - 0.00088 * log10(p_h2o);
6733 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
6734 const double c = -11397.0 / a;
6735 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
6736 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
6754 const double p0 = pbl;
6757 if (atm->
p[ip] > p0)
6759 else if (atm->
p[ip] < p1)
6762 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
6768 const char *filename,
6774 if (!(in = fopen(filename,
"r"))) {
6775 WARN(
"Cannot open file!");
6781 while (fgets(line,
LEN, in)) {
6785 TOK(line, tok,
"%lg", atm->
time[atm->
np]);
6786 TOK(NULL, tok,
"%lg", atm->
p[atm->
np]);
6787 TOK(NULL, tok,
"%lg", atm->
lon[atm->
np]);
6788 TOK(NULL, tok,
"%lg", atm->
lat[atm->
np]);
6789 for (
int iq = 0; iq < ctl->
nq; iq++)
6790 TOK(NULL, tok,
"%lg", atm->
q[iq][atm->
np]);
6793 atm->
p[atm->
np] =
P(atm->
p[atm->
np]);
6796 if ((++atm->
np) >
NP)
6797 ERRMSG(
"Too many data points!");
6810 const char *filename,
6816 if (!(in = fopen(filename,
"r")))
6821 FREAD(&version,
int,
6825 ERRMSG(
"Wrong version of binary data!");
6843 for (
int iq = 0; iq < ctl->
nq; iq++)
6844 FREAD(atm->
q[iq],
double,
6854 ERRMSG(
"Error while reading binary data!");
6866 const char *filename,
6873 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
6880 if (nc_inq_varid(ncid,
"TIME_INIT", &varid) == NC_NOERR) {
6881 NC(nc_get_var_double(ncid, varid, atm->
time));
6883 WARN(
"TIME_INIT not found use time instead!");
6886 for (
int ip = 0; ip < atm->
np; ip++) {
6887 atm->
time[ip] = time_init;
6899 if (nc_inq_varid(ncid,
"PRESS_INIT", &varid) == NC_NOERR) {
6900 NC(nc_get_var_double(ncid, varid, atm->
p));
6902 WARN(
"PRESS_INIT not found use PRESS instead!");
6903 nc_inq_varid(ncid,
"PRESS", &varid);
6904 NC(nc_get_var_double(ncid, varid, atm->
p));
6909 for (
int iq = 0; iq < ctl->
nq; iq++)
6926 const char *filename,
6933 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
6946 for (
int iq = 0; iq < ctl->
nq; iq++)
6959 const char *filename,
6965 LOG(1,
"Read photolysis rates: %s", filename);
6968 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
6969 WARN(
"Photolysis rate data are missing!");
6976 if (photo->
p[0] < photo->
p[1])
6977 ERRMSG(
"Pressure data are not descending!");
6982 if (photo->
o3c[0] > photo->
o3c[1])
6983 ERRMSG(
"Total column ozone data are not ascending!");
6988 if (photo->
sza[0] > photo->
sza[1])
6989 ERRMSG(
"Solar zenith angle data are not ascending!");
7006 LOG(2,
"Number of pressure levels: %d", photo->
np);
7007 LOG(2,
"Altitude levels: %g, %g ... %g km",
7008 Z(photo->
p[0]),
Z(photo->
p[1]),
Z(photo->
p[photo->
np - 1]));
7009 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
7010 photo->
p[0], photo->
p[1], photo->
p[photo->
np - 1]);
7011 LOG(2,
"Number of solar zenith angles: %d", photo->
nsza);
7012 LOG(2,
"Solar zenith angles: %g, %g ... %g deg",
7015 LOG(2,
"Number of total column ozone values: %d", photo->
no3c);
7016 LOG(2,
"Total column ozone: %g, %g ... %g DU",
7018 LOG(2,
"N2O photolysis rate: %g, %g ... %g s**-1",
7019 photo->
n2o[0][0][0], photo->
n2o[1][0][0],
7020 photo->
n2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7021 LOG(2,
"CCl4 photolysis rate: %g, %g ... %g s**-1",
7022 photo->
ccl4[0][0][0], photo->
ccl4[1][0][0],
7024 LOG(2,
"CFC-11 photolysis rate: %g, %g ... %g s**-1",
7025 photo->
ccl3f[0][0][0], photo->
ccl3f[1][0][0],
7027 LOG(2,
"CFC-12 photolysis rate: %g, %g ... %g s**-1",
7030 LOG(2,
"O2 photolysis rate: %g, %g ... %g s**-1",
7031 photo->
o2[0][0][0], photo->
o2[1][0][0],
7032 photo->
o2[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7033 LOG(2,
"O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
7034 photo->
o3_1[0][0][0], photo->
o3_1[1][0][0],
7036 LOG(2,
"O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
7037 photo->
o3_2[0][0][0], photo->
o3_2[1][0][0],
7039 LOG(2,
"H2O2 photolysis rate: %g, %g ... %g s**-1",
7040 photo->
h2o2[0][0][0], photo->
h2o2[1][0][0],
7042 LOG(2,
"H2O photolysis rate: %g, %g ... %g s**-1",
7043 photo->
h2o[0][0][0], photo->
h2o[1][0][0],
7044 photo->
h2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
7051 const char *varname,
7065 for (
int ip = 0; ip < photo->
np; ip++)
7066 for (
int is = 0; is < photo->
nsza; is++)
7067 for (
int io = 0; io < photo->
no3c; io++)
7078 const char *filename,
7082 LOG(1,
"Read climatological time series: %s", filename);
7086 if (!(in = fopen(filename,
"r"))) {
7087 WARN(
"Cannot open file!");
7094 while (fgets(line,
LEN, in))
7095 if (sscanf(line,
"%lg %lg", &ts->
time[nh], &ts->
vmr[nh]) == 2) {
7098 ts->
time[nh] = (ts->
time[nh] - 2000.0) * 365.25 * 86400.;
7101 if (nh > 0 && ts->
time[nh] <= ts->
time[nh - 1])
7102 ERRMSG(
"Time series must be ascending!");
7106 ERRMSG(
"Too many data points!");
7115 ERRMSG(
"Not enough data points!");
7118 LOG(2,
"Number of time steps: %d", ts->
ntime);
7119 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s", ts->
time[0], ts->
time[1],
7121 LOG(2,
"Volume mixing ratio range: %g ... %g ppv",
7122 gsl_stats_min(ts->
vmr, 1, (
size_t) nh), gsl_stats_max(ts->
vmr, 1,
7132 const char *filename,
7133 const char *varname,
7136 int ncid, varid, it, iy, iz, iz2, nt;
7138 double *help, varmin = 1e99, varmax = -1e99;
7141 LOG(1,
"Read %s data: %s", varname, filename);
7144 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
7145 WARN(
"%s climatology data are missing!", varname);
7152 if (zm->
p[0] < zm->
p[1])
7153 ERRMSG(
"Pressure data are not descending!");
7158 if (zm->
lat[0] > zm->
lat[1])
7159 ERRMSG(
"Latitude data are not ascending!");
7163 zm->
time[0] = 1209600.00;
7164 zm->
time[1] = 3888000.00;
7165 zm->
time[2] = 6393600.00;
7166 zm->
time[3] = 9072000.00;
7167 zm->
time[4] = 11664000.00;
7168 zm->
time[5] = 14342400.00;
7169 zm->
time[6] = 16934400.00;
7170 zm->
time[7] = 19612800.00;
7171 zm->
time[8] = 22291200.00;
7172 zm->
time[9] = 24883200.00;
7173 zm->
time[10] = 27561600.00;
7174 zm->
time[11] = 30153600.00;
7183 for (it = 0; it < zm->
ntime; it++)
7184 for (iz = 0; iz < zm->
np; iz++)
7185 for (iy = 0; iy < zm->
nlat; iy++)
7190 for (it = 0; it < zm->
ntime; it++)
7191 for (iy = 0; iy < zm->
nlat; iy++)
7192 for (iz = 0; iz < zm->
np; iz++) {
7193 if (zm->
vmr[it][iz][iy] < 0) {
7194 for (iz2 = 0; iz2 < zm->
np; iz2++)
7195 if (zm->
vmr[it][iz2][iy] >= 0) {
7196 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
7199 for (iz2 = zm->
np - 1; iz2 >= 0; iz2--)
7200 if (zm->
vmr[it][iz2][iy] >= 0) {
7201 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
7205 varmin =
MIN(varmin, zm->
vmr[it][iz][iy]);
7206 varmax =
MAX(varmax, zm->
vmr[it][iz][iy]);
7213 LOG(2,
"Number of time steps: %d", zm->
ntime);
7214 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
7216 LOG(2,
"Number of pressure levels: %d", zm->
np);
7217 LOG(2,
"Altitude levels: %g, %g ... %g km",
7218 Z(zm->
p[0]),
Z(zm->
p[1]),
Z(zm->
p[zm->
np - 1]));
7219 LOG(2,
"Pressure levels: %g, %g ... %g hPa", zm->
p[0],
7220 zm->
p[1], zm->
p[zm->
np - 1]);
7221 LOG(2,
"Number of latitudes: %d", zm->
nlat);
7222 LOG(2,
"Latitudes: %g, %g ... %g deg",
7224 LOG(2,
"%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
7231 const char *filename,
7237 LOG(1,
"Read kernel function: %s", filename);
7241 if (!(in = fopen(filename,
"r")))
7242 ERRMSG(
"Cannot open file!");
7247 while (fgets(line,
LEN, in))
7248 if (sscanf(line,
"%lg %lg", &kz[n], &kw[n]) == 2) {
7249 if (n > 0 && kz[n] < kz[n - 1])
7250 ERRMSG(
"Height levels must be ascending!");
7252 ERRMSG(
"Too many height levels!");
7261 ERRMSG(
"Not enough height levels!");
7264 const double kmax = gsl_stats_max(kw, 1, (
size_t) n);
7265 for (
int iz = 0; iz < n; iz++)
7272 const char *filename,
7280 int year, mon, day, hour, min, sec;
7286 if (!(in = fopen(filename,
"r"))) {
7287 WARN(
"Cannot open file!");
7293 FREAD(&met_type,
int,
7297 ERRMSG(
"Wrong MET_TYPE of binary data!");
7301 FREAD(&version,
int,
7305 ERRMSG(
"Wrong version of binary data!");
7311 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
7312 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
7313 met->
time, year, mon, day, hour, min);
7314 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
7315 || day < 1 || day > 31 || hour < 0 || hour > 23)
7316 ERRMSG(
"Error while reading time!");
7322 LOG(2,
"Number of longitudes: %d", met->
nx);
7323 if (met->
nx < 2 || met->
nx >
EX)
7324 ERRMSG(
"Number of longitudes out of range!");
7329 LOG(2,
"Number of latitudes: %d", met->
ny);
7330 if (met->
ny < 2 || met->
ny >
EY)
7331 ERRMSG(
"Number of latitudes out of range!");
7336 LOG(2,
"Number of levels: %d", met->
np);
7337 if (met->
np < 2 || met->
np >
EP)
7338 ERRMSG(
"Number of levels out of range!");
7344 LOG(2,
"Longitudes: %g, %g ... %g deg",
7350 LOG(2,
"Latitudes: %g, %g ... %g deg",
7356 LOG(2,
"Altitude levels: %g, %g ... %g km",
7357 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
7358 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
7359 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
7408 ERRMSG(
"Error while reading binary data!");
7423 const char *varname) {
7432 LOG(2,
"Read 2-D variable: %s (uncompressed)", varname);
7434 (
size_t) (met->
nx * met->
ny),
7438 for (
int ix = 0; ix < met->
nx; ix++)
7439 for (
int iy = 0; iy < met->
ny; iy++)
7440 var[ix][iy] = help[
ARRAY_2D(ix, iy, met->
ny)];
7453 const char *varname,
7454 const float bound_min,
7455 const float bound_max) {
7465 LOG(2,
"Read 3-D variable: %s (uncompressed)", varname);
7467 (
size_t) (met->
nx * met->
ny * met->
np),
7474 (
size_t) met->
np, 1, in);
7480 FREAD(&precision,
int,
7485 FREAD(&tolerance,
double,
7492 ERRMSG(
"MPTRAC was compiled without ZFP compression!");
7502 ERRMSG(
"MPTRAC was compiled without ZSTD compression!");
7510 (
size_t) met->
np, met->
p, 1, in);
7512 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
7520 FREAD(&precision,
int,
7525 FREAD(&tolerance,
double,
7532 ERRMSG(
"MPTRAC was compiled without sz3 compression!");
7537#pragma omp parallel for default(shared) collapse(2)
7538 for (
int ix = 0; ix < met->
nx; ix++)
7539 for (
int iy = 0; iy < met->
ny; iy++)
7540 for (
int ip = 0; ip < met->
np; ip++) {
7541 var[ix][iy][ip] = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
7542 if (var[ix][iy][ip] < bound_min)
7543 var[ix][iy][ip] = bound_min;
7544 else if (var[ix][iy][ip] > bound_max)
7545 var[ix][iy][ip] = bound_max;
7565 LOG(2,
"Calculate CAPE...");
7568 const double pfac = 1.01439, dz0 =
RI /
MA /
G0 * log(pfac);
7571#pragma omp parallel for default(shared) collapse(2)
7572 for (
int ix = 0; ix < met->
nx; ix++)
7573 for (
int iy = 0; iy < met->
ny; iy++) {
7577 double h2o = 0, t, theta = 0;
7578 double pbot =
MIN(met->
ps[ix][iy], met->
p[0]);
7579 double ptop = pbot - 50.;
7580 for (
int ip = 0; ip < met->
np; ip++) {
7581 if (met->
p[ip] <= pbot) {
7582 theta +=
THETA(met->
p[ip], met->
t[ix][iy][ip]);
7583 h2o += met->
h2o[ix][iy][ip];
7586 if (met->
p[ip] < ptop && n > 0)
7593 met->
plcl[ix][iy] = NAN;
7594 met->
plfc[ix][iy] = NAN;
7595 met->
pel[ix][iy] = NAN;
7596 met->
cape[ix][iy] = NAN;
7597 met->
cin[ix][iy] = NAN;
7603 pbot = met->
ps[ix][iy];
7605 met->
plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
7606 t = theta / pow(1000. / met->
plcl[ix][iy], 0.286);
7607 if (
RH(met->
plcl[ix][iy], t, h2o) > 100.)
7608 ptop = met->
plcl[ix][iy];
7610 pbot = met->
plcl[ix][iy];
7611 }
while (pbot - ptop > 0.1);
7615 double dcape, dz, h2o_env, t_env;
7616 double p = met->
ps[ix][iy];
7617 met->
cape[ix][iy] = met->
cin[ix][iy] = 0;
7619 dz = dz0 *
TVIRT(t, h2o);
7621 t = theta / pow(1000. / p, 0.286);
7625 &h2o_env, ci, cw, 0);
7626 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
7627 TVIRT(t_env, h2o_env) * dz;
7629 met->
cin[ix][iy] += fabsf((
float) dcape);
7630 }
while (p > met->
plcl[ix][iy]);
7635 p = met->
plcl[ix][iy];
7636 t = theta / pow(1000. / p, 0.286);
7639 dz = dz0 *
TVIRT(t, h2o);
7642 double psat =
PSAT(t);
7643 h2o = psat / (p - (1. -
EPS) * psat);
7647 &h2o_env, ci, cw, 0);
7648 double dcape_old = dcape;
7649 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
7650 TVIRT(t_env, h2o_env) * dz;
7652 met->
cape[ix][iy] += (float) dcape;
7653 if (!isfinite(met->
plfc[ix][iy]))
7654 met->
plfc[ix][iy] = (
float) p;
7655 }
else if (dcape_old > 0)
7656 met->
pel[ix][iy] = (float) p;
7657 if (dcape < 0 && !isfinite(met->
plfc[ix][iy]))
7658 met->
cin[ix][iy] += fabsf((
float) dcape);
7662 if (!isfinite(met->
plfc[ix][iy]))
7663 met->
cin[ix][iy] = NAN;
7674 LOG(2,
"Calculate cloud data...");
7677 const double ccmin = 0.01, cwmin = 1e-6;
7680#pragma omp parallel for default(shared) collapse(2)
7681 for (
int ix = 0; ix < met->
nx; ix++)
7682 for (
int iy = 0; iy < met->
ny; iy++) {
7685 met->
pct[ix][iy] = NAN;
7686 met->
pcb[ix][iy] = NAN;
7687 met->
cl[ix][iy] = 0;
7690 for (
int ip = 0; ip < met->
np - 1; ip++) {
7693 if (met->
p[ip] > met->
ps[ix][iy] || met->
p[ip] <
P(20.))
7697 if (met->
cc[ix][iy][ip] > ccmin
7698 && (met->
lwc[ix][iy][ip] > cwmin
7699 || met->
rwc[ix][iy][ip] > cwmin
7700 || met->
iwc[ix][iy][ip] > cwmin
7701 || met->
swc[ix][iy][ip] > cwmin)) {
7705 = (float) (0.5 * (met->
p[ip] + (
float) met->
p[ip + 1]));
7708 if (!isfinite(met->
pcb[ix][iy]))
7710 = (
float) (0.5 * (met->
p[ip] + met->
p[
MAX(ip - 1, 0)]));
7714 met->
cl[ix][iy] += (float)
7715 (0.5 * (met->
lwc[ix][iy][ip] + met->
lwc[ix][iy][ip + 1]
7716 + met->
rwc[ix][iy][ip] + met->
rwc[ix][iy][ip + 1]
7717 + met->
iwc[ix][iy][ip] + met->
iwc[ix][iy][ip + 1]
7718 + met->
swc[ix][iy][ip] + met->
swc[ix][iy][ip + 1])
7719 * 100. * (met->
p[ip] - met->
p[ip + 1]) /
G0);
7738 LOG(2,
"Detrend meteo data...");
7745 const double tssq = 2. *
SQR(sigma);
7748 int sy = (int) (3. *
DY2DEG(sigma) / fabs(met->
lat[1] - met->
lat[0]));
7752#pragma omp parallel for default(shared) collapse(2)
7753 for (
int ix = 0; ix < met->
nx; ix++) {
7754 for (
int iy = 0; iy < met->
ny; iy++) {
7762 (int) (3. *
DX2DEG(sigma, met->
lat[iy]) /
7763 fabs(met->
lon[1] - met->
lon[0]));
7768 for (
int ip = 0; ip < met->
np; ip++) {
7769 help->
t[ix][iy][ip] = 0;
7770 help->
u[ix][iy][ip] = 0;
7771 help->
v[ix][iy][ip] = 0;
7772 help->
w[ix][iy][ip] = 0;
7776 for (
int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
7780 else if (ix3 >= met->
nx)
7782 for (
int iy2 =
MAX(iy - sy, 0);
7783 iy2 <=
MIN(iy + sy, met->
ny - 1); iy2++) {
7790 const float w = (float) exp(-
DIST2(x0, x1) / tssq);
7794 for (
int ip = 0; ip < met->
np; ip++) {
7795 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip];
7796 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip];
7797 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip];
7798 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip];
7804 for (
int ip = 0; ip < met->
np; ip++) {
7805 help->
t[ix][iy][ip] /= wsum;
7806 help->
u[ix][iy][ip] /= wsum;
7807 help->
v[ix][iy][ip] /= wsum;
7808 help->
w[ix][iy][ip] /= wsum;
7814#pragma omp parallel for default(shared) collapse(3)
7815 for (
int ix = 0; ix < met->
nx; ix++)
7816 for (
int iy = 0; iy < met->
ny; iy++)
7817 for (
int ip = 0; ip < met->
np; ip++) {
7818 met->
t[ix][iy][ip] -= help->
t[ix][iy][ip];
7819 met->
u[ix][iy][ip] -= help->
u[ix][iy][ip];
7820 met->
v[ix][iy][ip] -= help->
v[ix][iy][ip];
7821 met->
w[ix][iy][ip] -= help->
w[ix][iy][ip];
7835 LOG(2,
"Extrapolate meteo data...");
7838#pragma omp parallel for default(shared) collapse(2)
7839 for (
int ix = 0; ix < met->
nx; ix++)
7840 for (
int iy = 0; iy < met->
ny; iy++) {
7844 for (ip0 = met->
np - 1; ip0 >= 0; ip0--)
7845 if (!isfinite(met->
t[ix][iy][ip0])
7846 || !isfinite(met->
u[ix][iy][ip0])
7847 || !isfinite(met->
v[ix][iy][ip0])
7848 || !isfinite(met->
w[ix][iy][ip0]))
7852 for (
int ip = ip0; ip >= 0; ip--) {
7853 met->
t[ix][iy][ip] = met->
t[ix][iy][ip + 1];
7854 met->
u[ix][iy][ip] = met->
u[ix][iy][ip + 1];
7855 met->
v[ix][iy][ip] = met->
v[ix][iy][ip + 1];
7856 met->
w[ix][iy][ip] = met->
w[ix][iy][ip + 1];
7857 met->
h2o[ix][iy][ip] = met->
h2o[ix][iy][ip + 1];
7858 met->
o3[ix][iy][ip] = met->
o3[ix][iy][ip + 1];
7859 met->
lwc[ix][iy][ip] = met->
lwc[ix][iy][ip + 1];
7860 met->
rwc[ix][iy][ip] = met->
rwc[ix][iy][ip + 1];
7861 met->
iwc[ix][iy][ip] = met->
iwc[ix][iy][ip + 1];
7862 met->
swc[ix][iy][ip] = met->
swc[ix][iy][ip + 1];
7863 met->
cc[ix][iy][ip] = met->
cc[ix][iy][ip + 1];
7882 LOG(2,
"Calculate geopotential heights...");
7889#pragma omp parallel for default(shared)
7890 for (
int ip = 0; ip < met->
np; ip++)
7891 logp[ip] = log(met->
p[ip]);
7894#pragma omp parallel for default(shared) collapse(2)
7895 for (
int ix = 0; ix < met->
nx; ix++)
7896 for (
int iy = 0; iy < met->
ny; iy++) {
7899 const double zs = met->
zs[ix][iy];
7900 const double lnps = log(met->
ps[ix][iy]);
7904 const double ts =
LIN(met->
p[ip0], met->
t[ix][iy][ip0], met->
p[ip0 + 1],
7905 met->
t[ix][iy][ip0 + 1], met->
ps[ix][iy]);
7907 LIN(met->
p[ip0], met->
h2o[ix][iy][ip0], met->
p[ip0 + 1],
7908 met->
h2o[ix][iy][ip0 + 1], met->
ps[ix][iy]);
7911 met->
z[ix][iy][ip0 + 1]
7913 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
7914 met->
t[ix][iy][ip0 + 1], met->
h2o[ix][iy][ip0 + 1]));
7915 for (
int ip = ip0 + 2; ip < met->
np; ip++)
7917 = (
float) (met->
z[ix][iy][ip - 1] +
7918 ZDIFF(logp[ip - 1], met->
t[ix][iy][ip - 1],
7919 met->
h2o[ix][iy][ip - 1], logp[ip],
7920 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
7925 ZDIFF(lnps, ts, h2os, logp[ip0],
7926 met->
t[ix][iy][ip0], met->
h2o[ix][iy][ip0]));
7927 for (
int ip = ip0 - 1; ip >= 0; ip--)
7929 = (
float) (met->
z[ix][iy][ip + 1] +
7930 ZDIFF(logp[ip + 1], met->
t[ix][iy][ip + 1],
7931 met->
h2o[ix][iy][ip + 1], logp[ip],
7932 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
7936 if (dx == 0 || dy == 0)
7940 if (dx < 0 || dy < 0) {
7941 if (fabs(met->
lon[1] - met->
lon[0]) < 0.5) {
7951 float ws[dx + 1][dy + 1];
7952#pragma omp parallel for default(shared) collapse(2)
7953 for (
int ix = 0; ix <= dx; ix++)
7954 for (
int iy = 0; iy < dy; iy++)
7955 ws[ix][iy] = (1.0f - (
float) ix / (float) dx)
7956 * (1.0f - (float) iy / (
float) dy);
7959#pragma omp parallel for default(shared) collapse(3)
7960 for (
int ix = 0; ix < met->
nx; ix++)
7961 for (
int iy = 0; iy < met->
ny; iy++)
7962 for (
int ip = 0; ip < met->
np; ip++)
7963 help[
ARRAY_3D(ip, ix, met->
nx, iy, met->
ny)] = met->
z[ix][iy][ip];
7966#pragma omp parallel for default(shared) collapse(3)
7967 for (
int ip = 0; ip < met->
np; ip++)
7968 for (
int ix = 0; ix < met->
nx; ix++)
7969 for (
int iy = 0; iy < met->
ny; iy++) {
7970 float res = 0, wsum = 0;
7971 int iy0 =
MAX(iy - dy + 1, 0);
7972 int iy1 =
MIN(iy + dy - 1, met->
ny - 1);
7973 for (
int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
7977 else if (ix3 >= met->
nx)
7979 for (
int iy2 = iy0; iy2 <= iy1; ++iy2)
7980 if (isfinite(help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)])) {
7981 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
7982 res += w * help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)];
7987 met->
z[ix][iy][ip] = res / wsum;
7989 met->
z[ix][iy][ip] = NAN;
7999 const char *filename,
8005 char levname[
LEN], tstr[10];
8007 double rtime = 0, r, r2;
8009 int varid, ndims, dimids[NC_MAX_DIMS], year2, mon2, day2, hour2, min2, sec2,
8010 year, mon, day, hour, min, sec;
8016 LOG(2,
"Read meteo grid information...");
8025 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
8026 if (nc_inq_varid(ncid,
"time", &varid) == NC_NOERR) {
8027 NC(nc_get_var_double(ncid, varid, &rtime));
8028 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
8029 WARN(
"Time information in meteo file does not match filename!");
8031 WARN(
"Time information in meteo file is missing!");
8042 sprintf(tstr,
"19%.2s", &filename[strlen(filename) - 11]);
8044 sprintf(tstr,
"20%.2s", &filename[strlen(filename) - 11]);
8046 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 9]);
8048 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 7]);
8050 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 5]);
8056 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
8057 || day < 1 || day > 31 || hour < 0 || hour > 23)
8058 ERRMSG(
"Cannot read time from filename!");
8059 jsec2time(met->
time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
8060 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
8061 met->
time, year2, mon2, day2, hour2, min2);
8064 if (nc_inq_varid(ncid,
"u", &varid) != NC_NOERR)
8065 if (nc_inq_varid(ncid,
"U", &varid) != NC_NOERR)
8067 (
"Variable 'u' or 'U' not found, cannot determine vertical dimension!");
8069 NC(nc_inq_varndims(ncid, varid, &ndims));
8070 NC(nc_inq_vardimid(ncid, varid, dimids));
8074 (ncid, dimids[ctl->
met_convention == 0 ? 1 : 3], levname, &dimlen));
8075 }
else if (ndims == 3) {
8077 (ncid, dimids[ctl->
met_convention == 0 ? 0 : 2], levname, &dimlen));
8079 ERRMSG(
"Cannot determine vertical dimension!")
8080 met->
np = (int) dimlen;
8082 LOG(2,
"Number of levels: %d", met->
np);
8083 if (met->
np < 2 || met->
np >
EP)
8084 ERRMSG(
"Number of levels out of range!");
8090 LOG(2,
"Number of longitudes: %d", met->
nx);
8093 LOG(2,
"Number of latitudes: %d", met->
ny);
8097 LOG(2,
"Longitudes: %g, %g ... %g deg",
8100 LOG(2,
"Latitudes: %g, %g ... %g deg",
8113 for (
int ip = 0; ip < met->
np; ip++)
8115 LOG(2,
"Altitude levels: %g, %g ... %g km",
8116 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
8117 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
8118 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
8122 if (strcasecmp(levname,
"hybrid") == 0)
8134 ERRMSG(
"You need to specify MET_NLEV, MET_LEV_HYAM, and MET_LEV_HYBM!");
8135 for (
int ip = 0; ip < ctl->
met_nlev; ip++) {
8143 met->
eta[k] = met->
hyam[k] / 100000.0 + met->
hybm[k];
8145 ERRMSG(
"Eta levels must be ascending!");
8149 for (
int ix = 2; ix < met->
nx; ix++)
8151 (fabs(met->
lon[ix] - met->
lon[ix - 1]) -
8152 fabs(met->
lon[1] - met->
lon[0])) > 0.001)
8153 ERRMSG(
"No regular grid spacing in longitudes!");
8154 for (
int iy = 2; iy < met->
ny; iy++)
8156 (fabs(met->
lat[iy] - met->
lat[iy - 1]) -
8157 fabs(met->
lat[1] - met->
lat[0])) > 0.001) {
8158 WARN(
"No regular grid spacing in latitudes!");
8173 LOG(2,
"Read surface data...");
8177 (ncid,
"lnsp",
"LNSP", NULL, NULL, NULL, NULL, ctl, met, dd, met->
ps,
8179 for (
int ix = 0; ix < met->
nx; ix++)
8180 for (
int iy = 0; iy < met->
ny; iy++)
8181 met->
ps[ix][iy] = (
float) (exp(met->
ps[ix][iy]) / 100.);
8184 (ncid,
"ps",
"PS",
"sp",
"SP", NULL, NULL, ctl, met, dd, met->
ps,
8186 WARN(
"Cannot not read surface pressure data (use lowest level)!");
8187 for (
int ix = 0; ix < met->
nx; ix++)
8188 for (
int iy = 0; iy < met->
ny; iy++)
8190 = (ctl->
met_np > 0 ? (
float) ctl->
met_p[0] : (
float) met->
p[0]);
8198 (ncid,
"z",
"Z", NULL, NULL, NULL, NULL, ctl, met, dd, met->
zs,
8199 (
float) (1. / (1000. *
G0)), 1))
8201 (ncid,
"zm",
"ZM", NULL, NULL, NULL, NULL, ctl, met, dd, met->
zs,
8202 (
float) (1. / 1000.), 1))
8203 WARN(
"Cannot read surface geopotential height!");
8214 memcpy(help, met->
pl,
sizeof(met->
pl));
8216 (ncid,
"gph",
"GPH", NULL, NULL, ctl, met, dd, met->
pl,
8217 (
float) (1e-3 /
G0)))
8218 ERRMSG(
"Cannot read geopotential height!");
8219 for (
int ix = 0; ix < met->
nx; ix++)
8220 for (
int iy = 0; iy < met->
ny; iy++)
8221 met->
zs[ix][iy] = met->
pl[ix][iy][0];
8222 memcpy(met->
pl, help,
sizeof(met->
pl));
8228 (ncid,
"t2m",
"T2M",
"2t",
"2T",
"t2",
"T2", ctl, met, dd, met->
ts, 1.0,
8230 WARN(
"Cannot read surface temperature!");
8234 (ncid,
"u10m",
"U10M",
"10u",
"10U",
"u10",
"U10", ctl, met, dd,
8236 WARN(
"Cannot read surface zonal wind!");
8240 (ncid,
"v10m",
"V10M",
"10v",
"10V",
"v10",
"V10", ctl, met, dd,
8242 WARN(
"Cannot read surface meridional wind!");
8246 (ncid,
"iews",
"IEWS", NULL, NULL, NULL, NULL, ctl, met, dd, met->
ess,
8248 WARN(
"Cannot read eastward turbulent surface stress!");
8252 (ncid,
"inss",
"INSS", NULL, NULL, NULL, NULL, ctl, met, dd, met->
nss,
8254 WARN(
"Cannot read nothward turbulent surface stress!");
8258 (ncid,
"ishf",
"ISHF", NULL, NULL, NULL, NULL, ctl, met, dd, met->
shf,
8260 WARN(
"Cannot read surface sensible heat flux!");
8264 (ncid,
"lsm",
"LSM", NULL, NULL, NULL, NULL, ctl, met, dd, met->
lsm,
8266 WARN(
"Cannot read land-sea mask!");
8270 (ncid,
"sstk",
"SSTK",
"sst",
"SST", NULL, NULL, ctl, met, dd, met->
sst,
8272 WARN(
"Cannot read sea surface temperature!");
8277 (ncid,
"blp",
"BLP", NULL, NULL, NULL, NULL, ctl, met, dd, met->
pbl,
8279 WARN(
"Cannot read planetary boundary layer pressure!");
8282 (ncid,
"blh",
"BLH", NULL, NULL, NULL, NULL, ctl, met, dd, met->
pbl,
8284 WARN(
"Cannot read planetary boundary layer height!");
8289 (ncid,
"cape",
"CAPE", NULL, NULL, NULL, NULL, ctl, met, dd,
8291 WARN(
"Cannot read CAPE!");
8296 (ncid,
"cin",
"CIN", NULL, NULL, NULL, NULL, ctl, met, dd, met->
cin,
8298 WARN(
"Cannot read convective inhibition!");
8311 LOG(2,
"Read level data...");
8315 (ncid,
"t",
"T",
"temp",
"TEMP", ctl, met, dd, met->
t, 1.0))
8316 ERRMSG(
"Cannot read temperature!");
8319 if (!
read_met_nc_3d(ncid,
"u",
"U", NULL, NULL, ctl, met, dd, met->
u, 1.0))
8320 ERRMSG(
"Cannot read zonal wind!");
8321 if (!
read_met_nc_3d(ncid,
"v",
"V", NULL, NULL, ctl, met, dd, met->
v, 1.0))
8322 ERRMSG(
"Cannot read meridional wind!");
8324 (ncid,
"w",
"W",
"omega",
"OMEGA", ctl, met, dd, met->
w, 0.01f))
8325 WARN(
"Cannot read vertical velocity!");
8330 (ncid,
"q",
"Q",
"sh",
"SH", ctl, met, dd, met->
h2o,
8332 WARN(
"Cannot read specific humidity!");
8335 (ncid,
"rh",
"RH", NULL, NULL, ctl, met, dd, met->
h2o, 0.01f))
8336 WARN(
"Cannot read relative humidity!");
8337#pragma omp parallel for default(shared) collapse(2)
8338 for (
int ix = 0; ix < met->
nx; ix++)
8339 for (
int iy = 0; iy < met->
ny; iy++)
8340 for (
int ip = 0; ip < met->
np; ip++) {
8341 double pw = met->
h2o[ix][iy][ip] *
PSAT(met->
t[ix][iy][ip]);
8342 met->
h2o[ix][iy][ip] =
8343 (float) (pw / (met->
p[ip] - (1.0 -
EPS) * pw));
8349 (ncid,
"o3",
"O3", NULL, NULL, ctl, met, dd, met->
o3,
8350 (
float) (
MA /
MO3)))
8351 WARN(
"Cannot read ozone data!");
8355 (ncid,
"clwc",
"CLWC", NULL, NULL, ctl, met, dd, met->
lwc, 1.0))
8356 WARN(
"Cannot read cloud liquid water content!");
8358 (ncid,
"crwc",
"CRWC", NULL, NULL, ctl, met, dd, met->
rwc, 1.0))
8359 WARN(
"Cannot read cloud rain water content!");
8361 (ncid,
"ciwc",
"CIWC", NULL, NULL, ctl, met, dd, met->
iwc, 1.0))
8362 WARN(
"Cannot read cloud ice water content!");
8364 (ncid,
"cswc",
"CSWC", NULL, NULL, ctl, met, dd, met->
swc, 1.0))
8365 WARN(
"Cannot read cloud snow water content!");
8367 (ncid,
"cc",
"CC", NULL, NULL, ctl, met, dd, met->
cc, 1.0))
8368 WARN(
"Cannot read cloud cover!");
8373 (ncid,
"ZETA",
"zeta", NULL, NULL, ctl, met, dd, met->
zetal, 1.0))
8374 WARN(
"Cannot read ZETA!");
8376 (ncid,
"ZETA_DOT_TOT",
"ZETA_DOT_clr",
"zeta_dot_clr",
8377 NULL, ctl, met, dd, met->
zeta_dotl, 0.00001157407f))
8378 WARN(
"Cannot read ZETA_DOT!");
8383#pragma omp parallel for default(shared)
8384 for (
int ix = 0; ix < met->
nx; ix++)
8385 for (
int iy = 0; iy < met->
ny; iy++)
8386 for (
int ip = 0; ip < met->
np; ip++)
8387 met->
zetal[ix][iy][ip] =
8388 (
float) (met->
hyam[ip] / 100000.0 + met->
hybm[ip]);
8390 (ncid,
"etadot",
"ETADOT", NULL, NULL, ctl, met, dd, met->
zeta_dotl,
8392 WARN(
"Cannot read eta vertical velocity!");
8397#pragma omp parallel for default(shared)
8398 for (
int ix = 0; ix < met->
nx; ix++)
8399 for (
int iy = 0; iy < met->
ny; iy++)
8400 for (
int ip = 0; ip < met->
np; ip++) {
8401 met->
ul[ix][iy][ip] = met->
u[ix][iy][ip];
8402 met->
vl[ix][iy][ip] = met->
v[ix][iy][ip];
8403 met->
wl[ix][iy][ip] = met->
w[ix][iy][ip];
8416 (ncid,
"pl",
"PL",
"pressure",
"PRESSURE", ctl, met, dd, met->
pl,
8419 (ncid,
"press",
"PRESS", NULL, NULL, ctl, met, dd, met->
pl, 1.0))
8420 ERRMSG(
"Cannot read pressure on model levels!");
8428 ERRMSG(
"Mismatch in number of model levels!");
8431 for (
int ix = 0; ix < met->
nx; ix++)
8432 for (
int iy = 0; iy < met->
ny; iy++)
8433 for (
int ip = 0; ip < met->
np; ip++)
8434 met->
pl[ix][iy][ip] =
8435 (
float) (met->
hyam[ip] / 100. +
8436 met->
hybm[ip] * met->
ps[ix][iy]);
8444 ERRMSG(
"Mismatch in number of model levels!");
8447#pragma omp parallel for default(shared) collapse(2)
8448 for (
int ix = 0; ix < met->
nx; ix++)
8449 for (
int iy = 0; iy < met->
ny; iy++)
8450 for (
int ip = 0; ip < met->
np; ip++) {
8452 met->
hyam[ip] / 100. + met->
hybm[ip] * met->
ps[ix][iy];
8454 met->
hyam[ip + 1] / 100. + met->
hybm[ip + 1] * met->
ps[ix][iy];
8455 met->
pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
8460 for (
int ix = 0; ix < met->
nx; ix++)
8461 for (
int iy = 0; iy < met->
ny; iy++)
8462 for (
int ip = 1; ip < met->
np; ip++)
8463 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
8464 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
8465 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
8466 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip]))
8467 ERRMSG(
"Pressure profiles are not monotonic!");
8488 for (
int ip = 0; ip < met->
np; ip++)
8489 met->
p[ip] = ctl->
met_p[ip];
8493 for (
int ip = 1; ip < met->
np; ip++)
8494 if (met->
p[ip - 1] < met->
p[ip])
8495 ERRMSG(
"Pressure levels must be descending!");
8502 const char *varname,
8503 const char *varname2,
8504 const char *varname3,
8505 const char *varname4,
8506 const char *varname5,
8507 const char *varname6,
8517 float offset, scalfac;
8522 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
8523 sprintf(varsel,
"%s", varname);
8524 else if (varname2 != NULL
8525 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
8526 sprintf(varsel,
"%s", varname2);
8527 else if (varname3 != NULL
8528 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
8529 sprintf(varsel,
"%s", varname3);
8530 else if (varname4 != NULL
8531 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
8532 sprintf(varsel,
"%s", varname4);
8533 else if (varname5 != NULL
8534 && nc_inq_varid(ncid, varname5, &varid) == NC_NOERR)
8535 sprintf(varsel,
"%s", varname5);
8536 else if (varname6 != NULL
8537 && nc_inq_varid(ncid, varname6, &varid) == NC_NOERR)
8538 sprintf(varsel,
"%s", varname6);
8544 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
8545 && nc_get_att_float(ncid, varid,
"scale_factor",
8546 &scalfac) == NC_NOERR) {
8554 short fillval, missval;
8555 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8557 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8561 LOG(2,
"Read 2-D variable: %s"
8562 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
8563 varsel, fillval, missval, scalfac, offset);
8566 NC(nc_get_var_short(ncid, varid, help));
8570 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
8574#pragma omp parallel for default(shared)
8575 for (
int ix = 0; ix < met->
nx; ix++)
8576 for (
int iy = 0; iy < met->
ny; iy++) {
8579 const short aux = help[
ARRAY_2D(iy, ix, met->
nx)];
8580 if ((fillval == 0 || aux != fillval)
8581 && (missval == 0 || aux != missval)
8582 && fabsf(aux * scalfac + offset) < 1e14f)
8583 dest[ix][iy] += scl * (aux * scalfac + offset);
8594 else if (!ctl->
dd) {
8602 float fillval, missval;
8603 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8605 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8609 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
8610 varsel, fillval, missval);
8613 NC(nc_get_var_float(ncid, varid, help));
8620#pragma omp parallel for default(shared)
8621 for (
int ix = 0; ix < met->
nx; ix++)
8622 for (
int iy = 0; iy < met->
ny; iy++) {
8625 const float aux = help[
ARRAY_2D(iy, ix, met->
nx)];
8626 if ((fillval == 0 || aux != fillval)
8627 && (missval == 0 || aux != missval)
8628 && fabsf(aux) < 1e14f)
8629 dest[ix][iy] += scl * aux;
8639#pragma omp parallel for default(shared)
8640 for (
int iy = 0; iy < met->
ny; iy++)
8641 for (
int ix = 0; ix < met->
nx; ix++) {
8644 const float aux = help[
ARRAY_2D(ix, iy, met->
ny)];
8645 if ((fillval == 0 || aux != fillval)
8646 && (missval == 0 || aux != missval)
8647 && fabsf(aux) < 1e14f)
8648 dest[ix][iy] += scl * aux;
8663 float fillval, missval;
8664 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8666 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8670 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
8671 varsel, fillval, missval);
8675 size_t help_subdomain_start[3];
8676 size_t help_subdomain_count[3];
8678 help_subdomain_start[0] = 0;
8687 help_subdomain_count[0] = 1;
8701 nc_var_par_access(ncid, varid, NC_COLLECTIVE);
8703 NC(nc_get_vara_float
8704 (ncid, varid, help_subdomain_start, help_subdomain_count, help));
8707 size_t help_halo_bnd_start[3];
8708 size_t help_halo_bnd_count[3];
8710 help_halo_bnd_start[0] = 0;
8719 help_halo_bnd_count[0] = 1;
8729 ALLOC(help_halo,
float,
8730 help_halo_bnd_count[1] * help_halo_bnd_count[2]);
8733 nc_var_par_access(ncid, varid, NC_COLLECTIVE);
8735 NC(nc_get_vara_float
8736 (ncid, varid, help_halo_bnd_start, help_halo_bnd_count, help_halo));
8743#pragma omp parallel for default(shared)
8744 for (
int ix = 0; ix < (int) help_subdomain_count[2]; ix++)
8745 for (
int iy = 0; iy < (int) help_subdomain_count[1]; iy++) {
8749 help[
ARRAY_2D(iy, ix, (
int) help_subdomain_count[2])];
8750 if ((fillval == 0 || aux != fillval)
8751 && (missval == 0 || aux != missval)
8752 && fabsf(aux) < 1e14f) {
8758#pragma omp parallel for default(shared)
8759 for (
int ix = 0; ix < (int) help_halo_bnd_count[2]; ix++)
8760 for (
int iy = 0; iy < (int) help_halo_bnd_count[1]; iy++) {
8764 help_halo[
ARRAY_2D(iy, ix, (
int) help_halo_bnd_count[2])];
8765 if ((fillval == 0 || aux != fillval)
8766 && (missval == 0 || aux != missval)
8767 && fabsf(aux) < 1e14f)
8779#pragma omp parallel for default(shared)
8780 for (
int ix = 0; ix < (int) help_subdomain_count[1]; ix++)
8781 for (
int iy = 0; iy < (int) help_subdomain_count[2]; iy++) {
8785 help[
ARRAY_2D(ix, iy, (
int) help_subdomain_count[1])];
8786 if ((fillval == 0 || aux != fillval)
8787 && (missval == 0 || aux != missval)
8788 && fabsf(aux) < 1e14f)
8794#pragma omp parallel for default(shared)
8795 for (
int ix = 0; ix < (int) help_halo_bnd_count[1]; ix++)
8796 for (
int iy = 0; iy < (int) help_halo_bnd_count[2]; iy++) {
8800 help_halo[
ARRAY_2D(ix, iy, (
int) help_halo_bnd_count[1])];
8801 if ((fillval == 0 || aux != fillval)
8802 && (missval == 0 || aux != missval)
8803 && fabsf(aux) < 1e14f)
8824 const char *varname,
8825 const char *varname2,
8826 const char *varname3,
8827 const char *varname4,
8838 float offset, scalfac;
8843 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
8844 sprintf(varsel,
"%s", varname);
8845 else if (varname2 != NULL
8846 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
8847 sprintf(varsel,
"%s", varname2);
8848 else if (varname3 != NULL
8849 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
8850 sprintf(varsel,
"%s", varname3);
8851 else if (varname4 != NULL
8852 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
8853 sprintf(varsel,
"%s", varname4);
8859 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
8860 && nc_get_att_float(ncid, varid,
"scale_factor",
8861 &scalfac) == NC_NOERR) {
8869 short fillval, missval;
8870 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8872 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8876 LOG(2,
"Read 3-D variable: %s "
8877 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
8878 varsel, fillval, missval, scalfac, offset);
8881 NC(nc_get_var_short(ncid, varid, help));
8885 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
8889#pragma omp parallel for default(shared)
8890 for (
int ix = 0; ix < met->
nx; ix++)
8891 for (
int iy = 0; iy < met->
ny; iy++)
8892 for (
int ip = 0; ip < met->
np; ip++) {
8893 const short aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
8894 if ((fillval == 0 || aux != fillval)
8895 && (missval == 0 || aux != missval)
8896 && fabsf(aux * scalfac + offset) < 1e14f)
8897 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
8899 dest[ix][iy][ip] = NAN;
8908 else if (!ctl->
dd) {
8916 float fillval, missval;
8917 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8919 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8923 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
8924 varsel, fillval, missval);
8927 NC(nc_get_var_float(ncid, varid, help));
8934#pragma omp parallel for default(shared)
8935 for (
int ix = 0; ix < met->
nx; ix++)
8936 for (
int iy = 0; iy < met->
ny; iy++)
8937 for (
int ip = 0; ip < met->
np; ip++) {
8938 const float aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
8939 if ((fillval == 0 || aux != fillval)
8940 && (missval == 0 || aux != missval)
8941 && fabsf(aux) < 1e14f)
8942 dest[ix][iy][ip] = scl * aux;
8944 dest[ix][iy][ip] = NAN;
8952#pragma omp parallel for default(shared)
8953 for (
int ip = 0; ip < met->
np; ip++)
8954 for (
int iy = 0; iy < met->
ny; iy++)
8955 for (
int ix = 0; ix < met->
nx; ix++) {
8956 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
8957 if ((fillval == 0 || aux != fillval)
8958 && (missval == 0 || aux != missval)
8959 && fabsf(aux) < 1e14f)
8960 dest[ix][iy][ip] = scl * aux;
8962 dest[ix][iy][ip] = NAN;
8975 float fillval, missval;
8976 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8978 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8982 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
8983 varsel, fillval, missval);
8988 size_t help_subdomain_start[4];
8989 size_t help_subdomain_count[4];
8990 size_t help_halo_bnd_start[4];
8991 size_t help_halo_bnd_count[4];
8994 for (
int i = 0; i < 4; i++) {
9032 nc_var_par_access(ncid, varid, NC_COLLECTIVE);
9034 NC(nc_get_vara_float
9035 (ncid, varid, help_subdomain_start, help_subdomain_count, help));
9039 ALLOC(help_halo,
float,
9047 nc_var_par_access(ncid, varid, NC_COLLECTIVE);
9049 NC(nc_get_vara_float(ncid,
9051 help_halo_bnd_start, help_halo_bnd_count,
9061#pragma omp parallel for default(shared)
9064 for (
int ip = 0; ip < met->
np; ip++) {
9068 if ((fillval == 0 || aux != fillval)
9069 && (missval == 0 || aux != missval)
9070 && fabsf(aux) < 1e14f)
9076#pragma omp parallel for default(shared)
9079 for (
int ip = 0; ip < met->
np; ip++) {
9083 if ((fillval == 0 || aux != fillval)
9084 && (missval == 0 || aux != missval)
9085 && fabsf(aux) < 1e14f)
9096#pragma omp parallel for default(shared)
9097 for (
int ip = 0; ip < met->
np; ip++)
9103 if ((fillval == 0 || aux != fillval)
9104 && (missval == 0 || aux != missval)
9105 && fabsf(aux) < 1e14f)
9111#pragma omp parallel for default(shared)
9112 for (
int ip = 0; ip < met->
np; ip++)
9118 if ((fillval == 0 || aux != fillval)
9119 && (missval == 0 || aux != missval)
9120 && fabsf(aux) < 1e14f)
9141 const char *filename,
9146 size_t filename_len = strlen(filename) + 1;
9147 char sf_filename[filename_len];
9148 char ml_filename[filename_len];
9149 strcpy(sf_filename, filename);
9150 strcpy(ml_filename, filename);
9155 FILE *ml_file = fopen(ml_filename,
"rb");
9156 FILE *sf_file = fopen(sf_filename,
"rb");
9157 if (ml_file == NULL || sf_file == NULL) {
9158 if (ml_file != NULL) {
9160 WARN(
"Cannot open file: %s", sf_filename);
9162 if (sf_file != NULL) {
9164 WARN(
"Cannot open file: %s", ml_filename);
9170 int ml_num_messages = 0, err = 0;
9171 ECC(codes_count_in_file(0, ml_file, &ml_num_messages));
9174 (size_t) ml_num_messages);
9175 for (
int i = 0; i < ml_num_messages; i++) {
9177 if ((h = codes_grib_handle_new_from_file(0, ml_file, &err)) != NULL)
9182 int sf_num_messages = 0;
9183 ECC(codes_count_in_file(0, sf_file, &sf_num_messages));
9186 (size_t) sf_num_messages);
9187 for (
int i = 0; i < sf_num_messages; i++) {
9189 if ((h = codes_grib_handle_new_from_file(0, sf_file, &err)) != NULL)
9202 for (
int i = 0; i < sf_num_messages; i++)
9203 codes_handle_delete(sf_handles[i]);
9207 size_t value_count = 0;
9208 ECC(codes_get_size(ml_handles[0],
"pv", &value_count));
9209 if (value_count % 2 != 0)
9210 ERRMSG(
"Unexpected pv array length!");
9211 size_t nlevels = value_count / 2 - 1;
9213 ALLOC(values,
double,
9215 ECC(codes_get_double_array(ml_handles[0],
"pv", values, &value_count));
9216 double *a_vals = values;
9217 double *b_vals = values + nlevels;
9218 if (met->
npl > (
int) nlevels)
9219 ERRMSG(
"met->npl exceeds number of pressure levels in GRIB!");
9220 for (
int nx = 0; nx < met->
nx; nx++)
9221 for (
int ny = 0; ny < met->
ny; ny++)
9222 for (
int level = 0; level <= met->
npl; level++) {
9223 const float p1 = (float) (a_vals[level] * 0.01f +
9224 met->
ps[nx][ny] * b_vals[level]);
9225 const float p2 = (float) (a_vals[level + 1] * 0.01f +
9226 met->
ps[nx][ny] * b_vals[level + 1]);
9227 met->
pl[nx][ny][level] = 0.5f * (p1 + p2);
9233 for (
int i = 0; i < ml_num_messages; i++)
9234 codes_handle_delete(ml_handles[i]);
9252 LOG(2,
"Read meteo grid information...");
9255 char datestr[
LEN], timestr[
LEN];
9256 size_t s_date =
sizeof(datestr);
9257 ECC(codes_get_string(handles[0],
"dataDate", datestr, &s_date));
9258 size_t s_time =
sizeof(timestr);
9259 ECC(codes_get_string(handles[0],
"dataTime", timestr, &s_time));
9260 int year, month, day, hour;
9261 if (sscanf(datestr,
"%4d%2d%2d", &year, &month, &day) != 3)
9262 ERRMSG(
"Failed to parse dataDate: %s", datestr);
9263 if (sscanf(timestr,
"%2d", &hour) != 1)
9264 ERRMSG(
"Failed to parse dataTime: %s", timestr);
9266 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)", met->
time, year, month,
9270 long count_lat = 0, count_lon = 0;
9271 ECC(codes_get_long(handles[0],
"Nj", &count_lat));
9272 ECC(codes_get_long(handles[0],
"Ni", &count_lon));
9273 met->
ny = (int) count_lat;
9274 met->
nx = (int) count_lon;
9277 LOG(2,
"Number of longitudes: %d", met->
nx);
9278 if (met->
nx < 2 || met->
nx >
EX)
9279 ERRMSG(
"Number of longitudes out of range!");
9280 LOG(2,
"Number of latitudes: %d", met->
ny);
9281 if (met->
ny < 2 || met->
ny >
EY)
9282 ERRMSG(
"Number of latitudes out of range!");
9284 double first_lon, last_lon, first_lat, last_lat, inc_lon, inc_lat;
9285 ECC(codes_get_double
9286 (handles[0],
"longitudeOfFirstGridPointInDegrees", &first_lon));
9287 ECC(codes_get_double
9288 (handles[0],
"latitudeOfFirstGridPointInDegrees", &first_lat));
9289 ECC(codes_get_double
9290 (handles[0],
"longitudeOfLastGridPointInDegrees", &last_lon));
9291 ECC(codes_get_double
9292 (handles[0],
"latitudeOfLastGridPointInDegrees", &last_lat));
9293 ECC(codes_get_double(handles[0],
"iDirectionIncrementInDegrees", &inc_lon));
9294 ECC(codes_get_double(handles[0],
"jDirectionIncrementInDegrees", &inc_lat));
9296 long jscanpos, iscanneg;
9297 ECC(codes_get_long(handles[0],
"iScansNegatively", &iscanneg));
9298 ECC(codes_get_long(handles[0],
"jScansPositively", &jscanpos));
9303 for (
double i = first_lon; i <= last_lon + 1e-6; i += inc_lon) {
9304 met->
lon[counter] = i;
9307 for (
double i = first_lon; i > last_lon - 1e-6; i -= inc_lon) {
9308 met->
lon[counter] = i;
9314 for (
double i = first_lat; i > last_lat - 1e-6; i -= inc_lat) {
9315 met->
lat[counter] = i;
9318 for (
double i = first_lat; i <= last_lat + 1e-6; i += inc_lat) {
9319 met->
lat[counter] = i;
9324 LOG(2,
"Longitudes: %g, %g ... %g deg",
9326 LOG(2,
"Latitudes: %g, %g ... %g deg",
9331 for (
int i = 0; i < count_handles; i++) {
9333 ECC(codes_get_long(handles[i],
"level", &level));
9334 if (level > max_level)
9335 max_level = (int) level;
9337 met->
npl = max_level;
9340 LOG(2,
"Number of levels: %d", met->
npl);
9342 ERRMSG(
"Number of levels out of range!");
9351 const int num_messages,
9357 LOG(2,
"Read level data...");
9360 int t_flag = 0, u_flag = 0, v_flag = 0, w_flag = 0, o3_flag = 0, h2o_flag =
9361 0, lwc_flag = 0, rwc_flag = 0, iwc_flag = 0, swc_flag = 0, cc_flag = 0;
9364 for (
int i = 0; i < num_messages; i++) {
9366 size_t max_size =
LEN;
9367 char short_name[max_size];
9373 ECC(codes_get_long(handles[i],
"level", ¤t_level));
9377 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
9378 ECC(codes_get_size(handles[i],
"values", &value_count));
9379 ALLOC(values,
double,
9381 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
9389 ECC_READ_3D(
"w", current_level, met->
w, 0.01f, w_flag);
9407 if (t_flag != met->
npl)
9408 ERRMSG(
"Cannot read temperature!");
9409 if (u_flag != met->
npl)
9410 ERRMSG(
"Cannot read zonal wind!");
9411 if (v_flag != met->
npl)
9412 ERRMSG(
"Cannot read meridional wind!");
9413 if (w_flag != met->
npl)
9414 WARN(
"Cannot read vertical velocity!");
9415 if (h2o_flag != met->
npl)
9416 WARN(
"Cannot read specific humidity!");
9417 if (o3_flag != met->
npl)
9418 WARN(
"Cannot read ozone data!");
9419 if (lwc_flag != met->
npl)
9420 WARN(
"Cannot read cloud liquid water content!");
9421 if (rwc_flag != met->
npl)
9422 WARN(
"Cannot read cloud rain water content!");
9423 if (iwc_flag != met->
npl)
9424 WARN(
"Cannot read cloud ice water content!");
9425 if (swc_flag != met->
npl)
9426 WARN(
"Cannot read cloud snow water content!");
9427 if (cc_flag != met->
npl)
9428 WARN(
"Cannot read cloud cover!");
9431 for (
int ix = 0; ix < met->
nx; ix++)
9432 for (
int iy = 0; iy < met->
ny; iy++)
9433 for (
int ip = 1; ip < met->
np; ip++)
9434 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
9435 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
9436 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
9437 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip])) {
9438 LOG(1,
"%f %f %f %f", met->
pl[ix][iy][0], met->
pl[ix][iy][1],
9439 met->
pl[ix][iy][ip - 1], met->
pl[ix][iy][ip]);
9440 ERRMSG(
"Pressure profiles are not monotonic!");
9461 for (
int ip = 0; ip < met->
np; ip++)
9462 met->
p[ip] = ctl->
met_p[ip];
9466 for (
int ip = 1; ip < met->
np; ip++)
9467 if (met->
p[ip - 1] < met->
p[ip])
9468 ERRMSG(
"Pressure levels must be descending!");
9477 const int num_messages,
9483 LOG(2,
"Read surface data...");
9486 int sp_flag = 0, z_flag = 0, t_flag = 0, u_flag = 0, v_flag = 0, lsm_flag =
9487 0, sst_flag = 0, cape_flag = 0, cin_flag = 0, pbl_flag = 0;
9490 for (
int i = 0; i < num_messages; i++) {
9492 size_t max_size =
LEN, value_count;
9494 char short_name[max_size];
9497 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
9498 ECC(codes_get_size(handles[i],
"values", &value_count));
9499 double *values = (
double *) malloc(value_count *
sizeof(
double));
9500 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
9538 WARN(
"Cannot read surface pressure data!");
9540 WARN(
"Cannot read surface geopotential height!");
9542 WARN(
"Cannot read surface temperature!");
9544 WARN(
"Cannot read surface zonal wind!");
9546 WARN(
"Cannot read surface meridional wind!");
9548 WARN(
"Cannot read land-sea mask!");
9550 WARN(
"Cannot read sea surface temperature!");
9553 WARN(
"Cannot read CAPE!");
9555 WARN(
"Cannot read convective inhibition!");
9557 if (ctl->
met_pbl == 0 && pbl_flag == 0)
9558 WARN(
"Cannot read planetary boundary layer!");
9568 const char *varname) {
9570 double aux[
EP], p[
EP];
9574 LOG(2,
"Interpolate meteo data to pressure levels: %s", varname);
9577#pragma omp parallel for default(shared) private(aux,p) collapse(2)
9578 for (
int ix = 0; ix < met->
nx; ix++)
9579 for (
int iy = 0; iy < met->
ny; iy++) {
9582 for (
int ip = 0; ip < met->
np; ip++)
9583 p[ip] = met->
pl[ix][iy][ip];
9586 for (
int ip = 0; ip < ctl->
met_np; ip++) {
9587 double pt = ctl->
met_p[ip];
9588 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
9590 else if ((pt > p[met->
np - 1] && p[1] > p[0])
9591 || (pt < p[met->
np - 1] && p[1] < p[0]))
9592 pt = p[met->
np - 1];
9594 aux[ip] =
LIN(p[ip2], var[ix][iy][ip2],
9595 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
9599 for (
int ip = 0; ip < ctl->
met_np; ip++)
9600 var[ix][iy][ip] = (
float) aux[ip];
9616 LOG(2,
"Make zeta profiles monotone...");
9619#pragma omp parallel for default(shared) collapse(2)
9620 for (
int i = 0; i < met->
nx; i++)
9621 for (
int j = 0; j < met->
ny; j++) {
9624 while (k < met->npl) {
9625 if ((met->
zetal[i][j][k - 1] >= met->
zetal[i][j][k])) {
9631 while ((met->
zetal[i][j][k - 1] >=
9632 met->
zetal[i][j][k + l]) & (k + l < met->npl));
9637 (float) (met->
zetal[i][j][k + l] - met->
zetal[i][j][k - 1])
9640 for (
int m = k; m < k + l; m++) {
9641 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
9642 met->
zetal[i][j][m] = s * d + met->
zetal[i][j][k - 1];
9654#pragma omp parallel for default(shared) collapse(2)
9655 for (
int i = 0; i < met->
nx; i++)
9656 for (
int j = 0; j < met->
ny; j++) {
9659 while (k < met->npl) {
9660 if ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k])) {
9667 while ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k + l]) & (k + l <
9672 float s = (float) (met->
pl[i][j][k + l] - met->
pl[i][j][k - 1])
9675 for (
int m = k; m < k + l; m++) {
9676 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
9677 met->
pl[i][j][m] = s * d + met->
pl[i][j][k - 1];
9692 const char *filename,
9703 (filename, NC_NOWRITE | NC_SHARE, MPI_COMM_WORLD, MPI_INFO_NULL,
9707 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
9708 WARN(
"Cannot open file!");
9740 int rank = 0, size = 1;
9742 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
9743 MPI_Comm_size(MPI_COMM_WORLD, &size);
9750 LOG(2,
"Number of longitudes: %d", dd->
nx_glob);
9751 LOG(2,
"Number of latitudes: %d", dd->
ny_glob);
9755 ERRMSG(
"Global grid is too large!");
9758 ERRMSG(
"Too many zonal subdomains for global x grid!");
9761 ERRMSG(
"Too many meridional subdomains for global y grid!");
9767 LOG(2,
"Longitudes: %g, %g ... %g deg",
9769 LOG(2,
"Latitudes: %g, %g ... %g deg",
9777 const int left = (zonal_rank == 0);
9779 const int top = (merid_rank == 0);
9786 const int ix0 = zonal_rank * nx_block;
9787 const int iy0 = merid_rank * ny_block;
9789 int nx_core = nx_block;
9790 int ny_core = ny_block;
9813 if (!left && !right) {
9816 }
else if (left ^ right) {
9822 if (!top && !bottom) {
9825 }
else if (top ^ bottom) {
9832 double lon_shift = 0.0;
9850 lon_shift = left ? -360.0 : 360.0;
9883 LOG(2,
"Define subdomain properties.");
9884 LOG(2,
"MPI information: Rank %d, Size %d", rank, size);
9885 LOG(2,
"Edge position: l=%d,r=%d,t=%d,b=%d", left, right, top, bottom);
9886 LOG(2,
"Total size for subdomain meteo data: nx %d ny %d np %d",
9887 met->
nx, met->
ny, met->
np);
9888 LOG(2,
"Hyperslab sizes for boundary halos: nx %d ny %d np %d",
9891 LOG(2,
"Hyperslab sizes for subdomain and inner halos: nx %d ny %d np %d",
9894 LOG(2,
"Subdomain start: nx %ld ny %ld np %ld",
9896 LOG(2,
"Boundary halo start: nx %ld ny %ld np %ld",
9899 LOG(2,
"%d Subdomain longitudes: %g, %g ... %g deg",
9900 rank, met->
lon[0], met->
lon[1], met->
lon[met->
nx - 1]);
9901 LOG(2,
"%d Subdomain latitudes: %g, %g ... %g deg",
9902 rank, met->
lat[0], met->
lat[1], met->
lat[met->
ny - 1]);
9913 LOG(2,
"Calculate planetary boundary layer...");
9919#pragma omp parallel for default(shared) collapse(2)
9920 for (
int ix = 0; ix < met->
nx; ix++)
9921 for (
int iy = 0; iy < met->
ny; iy++) {
9924 const float z = met->
zs[ix][iy] + met->
pbl[ix][iy];
9927 (float) (
LIN(met->
z[ix][iy][ip], met->
p[ip],
9928 met->
z[ix][iy][ip + 1], met->
p[ip + 1], z));
9937 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
9940#pragma omp parallel for default(shared) collapse(2)
9941 for (
int ix = 0; ix < met->
nx; ix++)
9942 for (
int iy = 0; iy < met->
ny; iy++) {
9945 const double pbl_bot = met->
ps[ix][iy] * exp(-dz /
H0);
9949 for (ip = 1; ip < met->
np; ip++)
9950 if (met->
p[ip] < pbl_bot)
9954 const double h2os =
LIN(met->
p[ip - 1], met->
h2o[ix][iy][ip - 1],
9955 met->
p[ip], met->
h2o[ix][iy][ip], pbl_bot);
9956 const double tvs =
THETAVIRT(pbl_bot, met->
ts[ix][iy], h2os);
9962 for (; ip < met->
np; ip++) {
9965 double vh2 =
SQR(met->
u[ix][iy][ip] - met->
us[ix][iy])
9966 +
SQR(met->
v[ix][iy][ip] - met->
vs[ix][iy]);
9967 vh2 =
MAX(vh2,
SQR(umin));
9971 G0 * 1e3 * (met->
z[ix][iy][ip] - met->
zs[ix][iy]) / tvs
9973 met->
h2o[ix][iy][ip]) - tvs) / vh2;
9976 if (rib >= rib_crit) {
9977 met->
pbl[ix][iy] = (float) (
LIN(rib_old, met->
p[ip - 1],
9978 rib, met->
p[ip], rib_crit));
9979 if (met->
pbl[ix][iy] > pbl_bot)
9980 met->
pbl[ix][iy] = (float) pbl_bot;
9995 const double dtheta = 2.0, zmin = 0.1;
9998#pragma omp parallel for default(shared) collapse(2)
9999 for (
int ix = 0; ix < met->
nx; ix++)
10000 for (
int iy = 0; iy < met->
ny; iy++) {
10003 const double theta0 =
THETA(met->
ps[ix][iy], met->
ts[ix][iy]);
10007 for (ip = met->
np - 2; ip > 0; ip--)
10008 if (met->
p[ip] >= 300.)
10009 if (met->
p[ip] > met->
ps[ix][iy]
10010 ||
THETA(met->
p[ip], met->
t[ix][iy][ip]) <= theta0 + dtheta)
10015 = (float) (
LIN(
THETA(met->
p[ip + 1], met->
t[ix][iy][ip + 1]),
10017 THETA(met->
p[ip], met->
t[ix][iy][ip]),
10018 met->
p[ip], theta0 + dtheta));
10021 double pbl_min = met->
ps[ix][iy] * exp(-zmin /
H0);
10022 if (met->
pbl[ix][iy] > pbl_min || met->
p[ip] > met->
ps[ix][iy])
10023 met->
pbl[ix][iy] = (float) pbl_min;
10028#pragma omp parallel for default(shared) collapse(2)
10029 for (
int ix = 0; ix < met->
nx; ix++)
10030 for (
int iy = 0; iy < met->
ny; iy++) {
10034 met->
pbl[ix][iy] =
MIN(met->
pbl[ix][iy], (
float) pbl_min);
10038 met->
pbl[ix][iy] =
MAX(met->
pbl[ix][iy], (
float) pbl_max);
10049 LOG(2,
"Apply periodic boundary conditions...");
10052 if (!(fabs(met->
lon[met->
nx - 1] - met->
lon[0]
10053 + met->
lon[1] - met->
lon[0] - 360) < 0.01))
10057 if ((++met->
nx) >=
EX)
10058 ERRMSG(
"Cannot create periodic boundary conditions!");
10061 met->
lon[met->
nx - 1] = met->
lon[met->
nx - 2] + met->
lon[1] - met->
lon[0];
10064#pragma omp parallel for default(shared)
10065 for (
int iy = 0; iy < met->
ny; iy++) {
10066 met->
ps[met->
nx - 1][iy] = met->
ps[0][iy];
10067 met->
zs[met->
nx - 1][iy] = met->
zs[0][iy];
10068 met->
ts[met->
nx - 1][iy] = met->
ts[0][iy];
10069 met->
us[met->
nx - 1][iy] = met->
us[0][iy];
10070 met->
vs[met->
nx - 1][iy] = met->
vs[0][iy];
10071 met->
ess[met->
nx - 1][iy] = met->
ess[0][iy];
10072 met->
nss[met->
nx - 1][iy] = met->
nss[0][iy];
10073 met->
shf[met->
nx - 1][iy] = met->
shf[0][iy];
10074 met->
lsm[met->
nx - 1][iy] = met->
lsm[0][iy];
10075 met->
sst[met->
nx - 1][iy] = met->
sst[0][iy];
10076 met->
pbl[met->
nx - 1][iy] = met->
pbl[0][iy];
10077 met->
cape[met->
nx - 1][iy] = met->
cape[0][iy];
10078 met->
cin[met->
nx - 1][iy] = met->
cin[0][iy];
10079 for (
int ip = 0; ip < met->
np; ip++) {
10080 met->
t[met->
nx - 1][iy][ip] = met->
t[0][iy][ip];
10081 met->
u[met->
nx - 1][iy][ip] = met->
u[0][iy][ip];
10082 met->
v[met->
nx - 1][iy][ip] = met->
v[0][iy][ip];
10083 met->
w[met->
nx - 1][iy][ip] = met->
w[0][iy][ip];
10084 met->
h2o[met->
nx - 1][iy][ip] = met->
h2o[0][iy][ip];
10085 met->
o3[met->
nx - 1][iy][ip] = met->
o3[0][iy][ip];
10086 met->
lwc[met->
nx - 1][iy][ip] = met->
lwc[0][iy][ip];
10087 met->
rwc[met->
nx - 1][iy][ip] = met->
rwc[0][iy][ip];
10088 met->
iwc[met->
nx - 1][iy][ip] = met->
iwc[0][iy][ip];
10089 met->
swc[met->
nx - 1][iy][ip] = met->
swc[0][iy][ip];
10090 met->
cc[met->
nx - 1][iy][ip] = met->
cc[0][iy][ip];
10092 for (
int ip = 0; ip < met->
npl; ip++) {
10093 met->
ul[met->
nx - 1][iy][ip] = met->
ul[0][iy][ip];
10094 met->
vl[met->
nx - 1][iy][ip] = met->
vl[0][iy][ip];
10095 met->
wl[met->
nx - 1][iy][ip] = met->
wl[0][iy][ip];
10096 met->
pl[met->
nx - 1][iy][ip] = met->
pl[0][iy][ip];
10097 met->
zetal[met->
nx - 1][iy][ip] = met->
zetal[0][iy][ip];
10110 LOG(2,
"Apply fix for polar winds...");
10113 if (fabs(met->
lat[0]) < 89.999 || fabs(met->
lat[met->
ny - 1]) < 89.999)
10117 for (
int ihem = 0; ihem < 2; ihem++) {
10120 int i89 = 1, i90 = 0, sign = 1;
10125 if (met->
lat[i90] < 0)
10129 double clon[
EX], slon[
EX];
10130#pragma omp parallel for default(shared)
10131 for (
int ix = 0; ix < met->
nx; ix++) {
10132 clon[ix] = cos(sign *
DEG2RAD(met->
lon[ix]));
10133 slon[ix] = sin(sign *
DEG2RAD(met->
lon[ix]));
10137#pragma omp parallel for default(shared)
10138 for (
int ip = 0; ip < met->
np; ip++) {
10141 double vel89x = 0, vel89y = 0;
10142 for (
int ix = 0; ix < met->
nx; ix++) {
10144 (met->
u[ix][i89][ip] * clon[ix] -
10145 met->
v[ix][i89][ip] * slon[ix]) / met->
nx;
10147 (met->
u[ix][i89][ip] * slon[ix] +
10148 met->
v[ix][i89][ip] * clon[ix]) / met->
nx;
10152 for (
int ix = 0; ix < met->
nx; ix++) {
10153 met->
u[ix][i90][ip]
10154 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
10155 met->
v[ix][i90][ip]
10156 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
10171 LOG(2,
"Calculate potential vorticity...");
10174#pragma omp parallel for default(shared)
10175 for (
int ip = 0; ip < met->
np; ip++)
10176 pows[ip] = pow(1000. / met->
p[ip], 0.286);
10179#pragma omp parallel for default(shared)
10180 for (
int ix = 0; ix < met->
nx; ix++) {
10183 const int ix0 =
MAX(ix - 1, 0);
10184 const int ix1 =
MIN(ix + 1, met->
nx - 1);
10187 for (
int iy = 0; iy < met->
ny; iy++) {
10190 const int iy0 =
MAX(iy - 1, 0);
10191 const int iy1 =
MIN(iy + 1, met->
ny - 1);
10194 const double latr = 0.5 * (met->
lat[iy1] + met->
lat[iy0]);
10195 const double dx = 1000. *
DEG2DX(met->
lon[ix1] - met->
lon[ix0], latr);
10196 const double dy = 1000. *
DEG2DY(met->
lat[iy1] - met->
lat[iy0]);
10197 const double c0 = cos(
DEG2RAD(met->
lat[iy0]));
10198 const double c1 = cos(
DEG2RAD(met->
lat[iy1]));
10199 const double cr = cos(
DEG2RAD(latr));
10200 const double vort = 2 * 7.2921e-5 * sin(
DEG2RAD(latr));
10203 for (
int ip = 0; ip < met->
np; ip++) {
10207 = (met->
t[ix1][iy][ip] - met->
t[ix0][iy][ip]) * pows[ip] / dx;
10208 const double dvdx = (met->
v[ix1][iy][ip] - met->
v[ix0][iy][ip]) / dx;
10212 = (met->
t[ix][iy1][ip] - met->
t[ix][iy0][ip]) * pows[ip] / dy;
10214 = (met->
u[ix][iy1][ip] * c1 - met->
u[ix][iy0][ip] * c0) / dy;
10217 const int ip0 =
MAX(ip - 1, 0);
10218 const int ip1 =
MIN(ip + 1, met->
np - 1);
10221 double dtdp, dudp, dvdp;
10222 const double dp0 = 100. * (met->
p[ip] - met->
p[ip0]);
10223 const double dp1 = 100. * (met->
p[ip1] - met->
p[ip]);
10224 if (ip != ip0 && ip != ip1) {
10225 double denom = dp0 * dp1 * (dp0 + dp1);
10226 dtdp = (dp0 * dp0 * met->
t[ix][iy][ip1] * pows[ip1]
10227 - dp1 * dp1 * met->
t[ix][iy][ip0] * pows[ip0]
10228 + (dp1 * dp1 - dp0 * dp0) * met->
t[ix][iy][ip] * pows[ip])
10230 dudp = (dp0 * dp0 * met->
u[ix][iy][ip1]
10231 - dp1 * dp1 * met->
u[ix][iy][ip0]
10232 + (dp1 * dp1 - dp0 * dp0) * met->
u[ix][iy][ip])
10234 dvdp = (dp0 * dp0 * met->
v[ix][iy][ip1]
10235 - dp1 * dp1 * met->
v[ix][iy][ip0]
10236 + (dp1 * dp1 - dp0 * dp0) * met->
v[ix][iy][ip])
10239 const double denom = dp0 + dp1;
10241 (met->
t[ix][iy][ip1] * pows[ip1] -
10242 met->
t[ix][iy][ip0] * pows[ip0]) / denom;
10243 dudp = (met->
u[ix][iy][ip1] - met->
u[ix][iy][ip0]) / denom;
10244 dvdp = (met->
v[ix][iy][ip1] - met->
v[ix][iy][ip0]) / denom;
10248 met->
pv[ix][iy][ip] = (float)
10250 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
10256#pragma omp parallel for default(shared)
10257 for (
int ix = 0; ix < met->
nx; ix++)
10258 for (
int ip = 0; ip < met->
np; ip++) {
10260 = met->
pv[ix][1][ip]
10261 = met->
pv[ix][2][ip];
10262 met->
pv[ix][met->
ny - 1][ip]
10263 = met->
pv[ix][met->
ny - 2][ip]
10264 = met->
pv[ix][met->
ny - 3][ip];
10275 LOG(2,
"Calculate total column ozone...");
10278#pragma omp parallel for default(shared) collapse(2)
10279 for (
int ix = 0; ix < met->
nx; ix++)
10280 for (
int iy = 0; iy < met->
ny; iy++) {
10284 for (
int ip = 1; ip < met->
np; ip++)
10285 if (met->
p[ip - 1] <= met->
ps[ix][iy]) {
10287 0.5 * (met->
o3[ix][iy][ip - 1] + met->
o3[ix][iy][ip]);
10288 const double dp = met->
p[ip - 1] - met->
p[ip];
10289 cd += vmr *
MO3 /
MA * dp * 1e2 /
G0;
10293 met->
o3c[ix][iy] = (float) (cd / 2.1415e-5);
10312 LOG(2,
"Downsampling of meteo data...");
10318 help->
nx = met->
nx;
10319 help->
ny = met->
ny;
10320 help->
np = met->
np;
10321 memcpy(help->
lon, met->
lon,
sizeof(met->
lon));
10322 memcpy(help->
lat, met->
lat,
sizeof(met->
lat));
10323 memcpy(help->
p, met->
p,
sizeof(met->
p));
10326 for (
int ix = 0; ix < met->
nx; ix += ctl->
met_dx) {
10327 for (
int iy = 0; iy < met->
ny; iy += ctl->
met_dy) {
10328 for (
int ip = 0; ip < met->
np; ip += ctl->
met_dp) {
10329 help->
ps[ix][iy] = 0;
10330 help->
zs[ix][iy] = 0;
10331 help->
ts[ix][iy] = 0;
10332 help->
us[ix][iy] = 0;
10333 help->
vs[ix][iy] = 0;
10334 help->
ess[ix][iy] = 0;
10335 help->
nss[ix][iy] = 0;
10336 help->
shf[ix][iy] = 0;
10337 help->
lsm[ix][iy] = 0;
10338 help->
sst[ix][iy] = 0;
10339 help->
pbl[ix][iy] = 0;
10340 help->
cape[ix][iy] = 0;
10341 help->
cin[ix][iy] = 0;
10342 help->
t[ix][iy][ip] = 0;
10343 help->
u[ix][iy][ip] = 0;
10344 help->
v[ix][iy][ip] = 0;
10345 help->
w[ix][iy][ip] = 0;
10346 help->
h2o[ix][iy][ip] = 0;
10347 help->
o3[ix][iy][ip] = 0;
10348 help->
lwc[ix][iy][ip] = 0;
10349 help->
rwc[ix][iy][ip] = 0;
10350 help->
iwc[ix][iy][ip] = 0;
10351 help->
swc[ix][iy][ip] = 0;
10352 help->
cc[ix][iy][ip] = 0;
10354 for (
int ix2 = ix - ctl->
met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
10359 else if (ix3 >= met->
nx)
10362 for (
int iy2 =
MAX(iy - ctl->
met_sy + 1, 0);
10363 iy2 <=
MIN(iy + ctl->
met_sy - 1, met->
ny - 1); iy2++)
10364 for (
int ip2 =
MAX(ip - ctl->
met_sp + 1, 0);
10365 ip2 <=
MIN(ip + ctl->
met_sp - 1, met->
np - 1); ip2++) {
10367 (1.0f - (float) abs(ix - ix2) / (float) ctl->
met_sx)
10368 * (1.0f - (float) abs(iy - iy2) / (float) ctl->
met_sy)
10369 * (1.0f - (float) abs(ip - ip2) / (float) ctl->
met_sp);
10370 help->
ps[ix][iy] += w * met->
ps[ix3][iy2];
10371 help->
zs[ix][iy] += w * met->
zs[ix3][iy2];
10372 help->
ts[ix][iy] += w * met->
ts[ix3][iy2];
10373 help->
us[ix][iy] += w * met->
us[ix3][iy2];
10374 help->
vs[ix][iy] += w * met->
vs[ix3][iy2];
10375 help->
ess[ix][iy] += w * met->
ess[ix3][iy2];
10376 help->
nss[ix][iy] += w * met->
nss[ix3][iy2];
10377 help->
shf[ix][iy] += w * met->
shf[ix3][iy2];
10378 help->
lsm[ix][iy] += w * met->
lsm[ix3][iy2];
10379 help->
sst[ix][iy] += w * met->
sst[ix3][iy2];
10380 help->
pbl[ix][iy] += w * met->
pbl[ix3][iy2];
10381 help->
cape[ix][iy] += w * met->
cape[ix3][iy2];
10382 help->
cin[ix][iy] += w * met->
cin[ix3][iy2];
10383 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip2];
10384 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip2];
10385 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip2];
10386 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip2];
10387 help->
h2o[ix][iy][ip] += w * met->
h2o[ix3][iy2][ip2];
10388 help->
o3[ix][iy][ip] += w * met->
o3[ix3][iy2][ip2];
10389 help->
lwc[ix][iy][ip] += w * met->
lwc[ix3][iy2][ip2];
10390 help->
rwc[ix][iy][ip] += w * met->
rwc[ix3][iy2][ip2];
10391 help->
iwc[ix][iy][ip] += w * met->
iwc[ix3][iy2][ip2];
10392 help->
swc[ix][iy][ip] += w * met->
swc[ix3][iy2][ip2];
10393 help->
cc[ix][iy][ip] += w * met->
cc[ix3][iy2][ip2];
10397 help->
ps[ix][iy] /= wsum;
10398 help->
zs[ix][iy] /= wsum;
10399 help->
ts[ix][iy] /= wsum;
10400 help->
us[ix][iy] /= wsum;
10401 help->
vs[ix][iy] /= wsum;
10402 help->
ess[ix][iy] /= wsum;
10403 help->
nss[ix][iy] /= wsum;
10404 help->
shf[ix][iy] /= wsum;
10405 help->
lsm[ix][iy] /= wsum;
10406 help->
sst[ix][iy] /= wsum;
10407 help->
pbl[ix][iy] /= wsum;
10408 help->
cape[ix][iy] /= wsum;
10409 help->
cin[ix][iy] /= wsum;
10410 help->
t[ix][iy][ip] /= wsum;
10411 help->
u[ix][iy][ip] /= wsum;
10412 help->
v[ix][iy][ip] /= wsum;
10413 help->
w[ix][iy][ip] /= wsum;
10414 help->
h2o[ix][iy][ip] /= wsum;
10415 help->
o3[ix][iy][ip] /= wsum;
10416 help->
lwc[ix][iy][ip] /= wsum;
10417 help->
rwc[ix][iy][ip] /= wsum;
10418 help->
iwc[ix][iy][ip] /= wsum;
10419 help->
swc[ix][iy][ip] /= wsum;
10420 help->
cc[ix][iy][ip] /= wsum;
10427 for (
int ix = 0; ix < help->
nx; ix += ctl->
met_dx) {
10428 met->
lon[met->
nx] = help->
lon[ix];
10430 for (
int iy = 0; iy < help->
ny; iy += ctl->
met_dy) {
10431 met->
lat[met->
ny] = help->
lat[iy];
10432 met->
ps[met->
nx][met->
ny] = help->
ps[ix][iy];
10433 met->
zs[met->
nx][met->
ny] = help->
zs[ix][iy];
10434 met->
ts[met->
nx][met->
ny] = help->
ts[ix][iy];
10435 met->
us[met->
nx][met->
ny] = help->
us[ix][iy];
10436 met->
vs[met->
nx][met->
ny] = help->
vs[ix][iy];
10437 met->
ess[met->
nx][met->
ny] = help->
ess[ix][iy];
10438 met->
nss[met->
nx][met->
ny] = help->
nss[ix][iy];
10439 met->
shf[met->
nx][met->
ny] = help->
shf[ix][iy];
10440 met->
lsm[met->
nx][met->
ny] = help->
lsm[ix][iy];
10441 met->
sst[met->
nx][met->
ny] = help->
sst[ix][iy];
10442 met->
pbl[met->
nx][met->
ny] = help->
pbl[ix][iy];
10444 met->
cin[met->
nx][met->
ny] = help->
cin[ix][iy];
10446 for (
int ip = 0; ip < help->
np; ip += ctl->
met_dp) {
10447 met->
p[met->
np] = help->
p[ip];
10448 met->
t[met->
nx][met->
ny][met->
np] = help->
t[ix][iy][ip];
10449 met->
u[met->
nx][met->
ny][met->
np] = help->
u[ix][iy][ip];
10450 met->
v[met->
nx][met->
ny][met->
np] = help->
v[ix][iy][ip];
10451 met->
w[met->
nx][met->
ny][met->
np] = help->
w[ix][iy][ip];
10452 met->
h2o[met->
nx][met->
ny][met->
np] = help->
h2o[ix][iy][ip];
10453 met->
o3[met->
nx][met->
ny][met->
np] = help->
o3[ix][iy][ip];
10454 met->
lwc[met->
nx][met->
ny][met->
np] = help->
lwc[ix][iy][ip];
10455 met->
rwc[met->
nx][met->
ny][met->
np] = help->
rwc[ix][iy][ip];
10456 met->
iwc[met->
nx][met->
ny][met->
np] = help->
iwc[ix][iy][ip];
10457 met->
swc[met->
nx][met->
ny][met->
np] = help->
swc[ix][iy][ip];
10458 met->
cc[met->
nx][met->
ny][met->
np] = help->
cc[ix][iy][ip];
10477 double p2[200], pv[
EP], pv2[200], t[
EP], t2[200], th[
EP],
10478 th2[200], z[
EP], z2[200];
10482 LOG(2,
"Calculate tropopause...");
10485#pragma omp parallel for default(shared)
10486 for (
int iz = 0; iz < met->
np; iz++)
10487 z[iz] =
Z(met->
p[iz]);
10488#pragma omp parallel for default(shared)
10489 for (
int iz = 0; iz <= 190; iz++) {
10490 z2[iz] = 4.5 + 0.1 * iz;
10491 p2[iz] =
P(z2[iz]);
10496#pragma omp parallel for default(shared) collapse(2)
10497 for (
int ix = 0; ix < met->
nx; ix++)
10498 for (
int iy = 0; iy < met->
ny; iy++)
10499 met->
pt[ix][iy] = NAN;
10503#pragma omp parallel for default(shared) collapse(2)
10504 for (
int ix = 0; ix < met->
nx; ix++)
10505 for (
int iy = 0; iy < met->
ny; iy++)
10513#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10514 for (
int ix = 0; ix < met->
nx; ix++)
10515 for (
int iy = 0; iy < met->
ny; iy++) {
10518 for (
int iz = 0; iz < met->
np; iz++)
10519 t[iz] = met->
t[ix][iy][iz];
10523 int iz = (int) gsl_stats_min_index(t2, 1, 171);
10524 if (iz > 0 && iz < 170)
10525 met->
pt[ix][iy] = (float) p2[iz];
10527 met->
pt[ix][iy] = NAN;
10535#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10536 for (
int ix = 0; ix < met->
nx; ix++)
10537 for (
int iy = 0; iy < met->
ny; iy++) {
10541 for (iz = 0; iz < met->
np; iz++)
10542 t[iz] = met->
t[ix][iy][iz];
10546 met->
pt[ix][iy] = NAN;
10547 for (iz = 0; iz <= 170; iz++) {
10549 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10550 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10555 if (iz > 0 && iz < 170)
10556 met->
pt[ix][iy] = (float) p2[iz];
10563 met->
pt[ix][iy] = NAN;
10564 for (; iz <= 170; iz++) {
10566 for (
int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
10567 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
10574 for (; iz <= 170; iz++) {
10576 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10577 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10582 if (iz > 0 && iz < 170)
10583 met->
pt[ix][iy] = (float) p2[iz];
10595#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
10596 for (
int ix = 0; ix < met->
nx; ix++)
10597 for (
int iy = 0; iy < met->
ny; iy++) {
10600 for (
int iz = 0; iz < met->
np; iz++)
10601 pv[iz] = met->
pv[ix][iy][iz];
10605 for (
int iz = 0; iz < met->
np; iz++)
10606 th[iz] =
THETA(met->
p[iz], met->
t[ix][iy][iz]);
10610 met->
pt[ix][iy] = NAN;
10611 for (
int iz = 0; iz <= 170; iz++)
10614 if (iz > 0 && iz < 170)
10615 met->
pt[ix][iy] = (float) p2[iz];
10622 ERRMSG(
"Cannot calculate tropopause!");
10625#pragma omp parallel for default(shared) collapse(2)
10626 for (
int ix = 0; ix < met->
nx; ix++)
10627 for (
int iy = 0; iy < met->
ny; iy++) {
10628 double h2ot, tt, zt;
10631 met->
lat[iy], &tt, ci, cw, 1);
10633 met->
lat[iy], &zt, ci, cw, 0);
10635 met->
lat[iy], &h2ot, ci, cw, 0);
10636 met->
tt[ix][iy] = (float) tt;
10637 met->
zt[ix][iy] = (float) zt;
10638 met->
h2ot[ix][iy] = (float) h2ot;
10645 const char *filename,
10655 LOG(1,
"Read observation data: %s", filename);
10659 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
10661 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
10663 ERRMSG(
"Set OBS_TYPE to 0 or 1!");
10666 for (
int i = 1; i < *nobs; i++)
10667 if (rt[i] < rt[i - 1])
10668 ERRMSG(
"Time must be ascending!");
10673 LOG(2,
"Number of observations: %d", *nobs);
10674 gsl_stats_minmax(&mini, &maxi, rt, 1, (
size_t) n);
10675 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
10676 gsl_stats_minmax(&mini, &maxi, rz, 1, (
size_t) n);
10677 LOG(2,
"Altitude range: %g ... %g km", mini, maxi);
10678 gsl_stats_minmax(&mini, &maxi, rlon, 1, (
size_t) n);
10679 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
10680 gsl_stats_minmax(&mini, &maxi, rlat, 1, (
size_t) n);
10681 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
10682 gsl_stats_minmax(&mini, &maxi, robs, 1, (
size_t) n);
10683 LOG(2,
"Observation range: %g ... %g", mini, maxi);
10689 const char *filename,
10699 if (!(in = fopen(filename,
"r")))
10700 ERRMSG(
"Cannot open file!");
10704 while (fgets(line,
LEN, in))
10705 if (sscanf(line,
"%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
10706 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
10707 if ((++(*nobs)) >=
NOBS)
10708 ERRMSG(
"Too many observations!");
10717 const char *filename,
10728 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
10729 ERRMSG(
"Cannot open file!");
10740 NC(nc_close(ncid));
10746 const char *filename,
10749 const char *varname,
10751 const char *defvalue,
10756 char fullname1[
LEN], fullname2[
LEN], rval[
LEN];
10758 int contain = 0, i;
10761 if (filename[strlen(filename) - 1] !=
'-')
10762 if (!(in = fopen(filename,
"r")))
10763 ERRMSG(
"Cannot open file!");
10767 sprintf(fullname1,
"%s[%d]", varname, arridx);
10768 sprintf(fullname2,
"%s[*]", varname);
10770 sprintf(fullname1,
"%s", varname);
10771 sprintf(fullname2,
"%s", varname);
10776 char dummy[
LEN], line[
LEN], rvarname[
LEN];
10777 while (fgets(line,
LEN, in)) {
10778 if (sscanf(line,
"%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
10779 if (strcasecmp(rvarname, fullname1) == 0 ||
10780 strcasecmp(rvarname, fullname2) == 0) {
10786 for (i = 1; i < argc - 1; i++)
10787 if (strcasecmp(argv[i], fullname1) == 0 ||
10788 strcasecmp(argv[i], fullname2) == 0) {
10789 sprintf(rval,
"%s", argv[i + 1]);
10800 if (strlen(defvalue) > 0)
10801 sprintf(rval,
"%s", defvalue);
10803 ERRMSG(
"Missing variable %s!\n", fullname1);
10807 LOG(1,
"%s = %s", fullname1, rval);
10811 sprintf(value,
"%s", rval);
10821 const double rhop) {
10824 const double rp_help = rp * 1e-6;
10827 const double rho =
RHO(p, T);
10830 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
10833 const double v = sqrt(8. *
KB * T / (M_PI * 4.8096e-26));
10836 const double lambda = 2. * eta / (rho * v);
10839 const double K = lambda / rp_help;
10842 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
10845 return 2. *
SQR(rp_help) * (rhop - rho) *
G0 / (9. * eta) * G;
10857 const int method) {
10863 gsl_interp_accel *acc = gsl_interp_accel_alloc();
10864 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (
size_t) n);
10867 gsl_spline_init(s, x, y, (
size_t) n);
10868 for (
int i = 0; i < n2; i++)
10871 else if (x2[i] >= x[n - 1])
10874 y2[i] = gsl_spline_eval(s, x2[i], acc);
10877 gsl_spline_free(s);
10878 gsl_interp_accel_free(acc);
10883 for (
int i = 0; i < n2; i++)
10886 else if (x2[i] >= x[n - 1])
10890 y2[i] =
LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
10904 float mean = 0, var = 0;
10906 for (
int i = 0; i < n; ++i) {
10908 var +=
SQR(data[i]);
10911 var = var / (float) n -
SQR(mean / (
float) n);
10913 return (var > 0 ? sqrtf(var) : 0);
10925 const double remain,
10937 t1.tm_year = year - 1900;
10938 t1.tm_mon = mon - 1;
10944 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
10952 const int output) {
10959 static int iname = -1, igroup = -1, nname, ngroup, ct_name[
NTIMER];
10962 t1 = omp_get_wtime();
10967 rt_name[iname] += dt;
10968 rt_min[iname] = (ct_name[iname] <= 0 ? dt :
MIN(rt_min[iname], dt));
10969 rt_max[iname] = (ct_name[iname] <= 0 ? dt :
MAX(rt_max[iname], dt));
10973 rt_group[igroup] += t1 - t0;
10977 for (
int i = 0; i < nname; i++)
10978 LOG(1,
"TIMER_%s = %.3f s (min= %g s, mean= %g s,"
10979 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
10980 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
10981 for (
int i = 0; i < ngroup; i++)
10982 LOG(1,
"TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
10983 double total = 0.0;
10984 for (
int i = 0; i < nname; i++)
10985 total += rt_name[i];
10986 LOG(1,
"TIMER_TOTAL = %.3f s", total);
10990 for (iname = 0; iname < nname; iname++)
10991 if (strcasecmp(name, names[iname]) == 0)
10993 for (igroup = 0; igroup < ngroup; igroup++)
10994 if (strcasecmp(group, groups[igroup]) == 0)
10998 if (iname >= nname) {
10999 sprintf(names[iname],
"%s", name);
11000 if ((++nname) >=
NTIMER)
11001 ERRMSG(
"Too many timers!");
11005 if (igroup >= ngroup) {
11006 sprintf(groups[igroup],
"%s", group);
11007 if ((++ngroup) >=
NTIMER)
11008 ERRMSG(
"Too many groups!");
11018 const char *filename,
11019 const int offset) {
11026 int len = (int) strlen(filename);
11027 sprintf(tstr,
"%.4s", &filename[len - offset]);
11028 int year = atoi(tstr);
11029 sprintf(tstr,
"%.2s", &filename[len - offset + 5]);
11030 int mon = atoi(tstr);
11031 sprintf(tstr,
"%.2s", &filename[len - offset + 8]);
11032 int day = atoi(tstr);
11033 sprintf(tstr,
"%.2s", &filename[len - offset + 11]);
11034 int hour = atoi(tstr);
11035 sprintf(tstr,
"%.2s", &filename[len - offset + 14]);
11036 int min = atoi(tstr);
11039 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
11040 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
11041 ERRMSG(
"Cannot read time from filename!");
11044 time2jsec(year, mon, day, hour, min, 0, 0.0, &t);
11061 const double p1 = pt * 0.866877899;
11062 const double p0 = pt / 0.866877899;
11065 if (atm->
p[ip] > p0)
11067 else if (atm->
p[ip] < p1)
11070 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
11076 const char *filename,
11084 const double t0 = t - 0.5 * ctl->
dt_mod;
11085 const double t1 = t + 0.5 * ctl->
dt_mod;
11091 if (!(out = popen(
"gnuplot",
"w")))
11092 ERRMSG(
"Cannot create pipe to gnuplot!");
11095 fprintf(out,
"set out \"%s.png\"\n", filename);
11099 int year, mon, day, hour, min, sec;
11100 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11101 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
11102 year, mon, day, hour, min);
11107 ERRMSG(
"Cannot open file!");
11109 while (fgets(line,
LEN, in))
11110 fprintf(out,
"%s", line);
11117 if (!(out = fopen(filename,
"w")))
11118 ERRMSG(
"Cannot create file!");
11123 "# $1 = time [s]\n"
11124 "# $2 = altitude [km]\n"
11125 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
11126 for (
int iq = 0; iq < ctl->
nq; iq++)
11127 fprintf(out,
"# $%i = %s [%s]\n", iq + 5, ctl->
qnt_name[iq],
11129 fprintf(out,
"\n");
11132 for (
int ip = 0; ip < atm->
np; ip += ctl->
atm_stride) {
11139 fprintf(out,
"%.2f %g %g %g", atm->
time[ip],
Z(atm->
p[ip]),
11140 atm->
lon[ip], atm->
lat[ip]);
11141 for (
int iq = 0; iq < ctl->
nq; iq++) {
11146 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
11148 fprintf(out,
"\n");
11158 const char *filename,
11160 const atm_t *atm) {
11165 if (!(out = fopen(filename,
"w")))
11166 ERRMSG(
"Cannot create file!");
11190 for (
int iq = 0; iq < ctl->
nq; iq++)
11208 const char *filename,
11210 const atm_t *atm) {
11212 int tid, pid, ncid, varid;
11213 size_t start[2], count[2];
11216 NC(nc_create(filename, NC_NETCDF4, &ncid));
11219 NC(nc_def_dim(ncid,
"time", 1, &tid));
11220 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11223 int dim_ids[2] = { tid, pid };
11224 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11225 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11226 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
11228 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
11230 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
11233 for (
int iq = 0; iq < ctl->
nq; iq++)
11243 NC(nc_enddef(ncid));
11251 for (
int iq = 0; iq < ctl->
nq; iq++)
11255 NC(nc_close(ncid));
11261 const char *dirname,
11267 static size_t out_cnt = 0;
11269 double r, r_start, r_stop;
11270 int year, mon, day, hour, min, sec;
11271 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
11272 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
11273 char filename_out[2 *
LEN] =
"traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
11275 int ncid, varid, tid, pid, cid;
11283 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11285 &min_start, &sec_start, &r_start);
11287 &min_stop, &sec_stop, &r_stop);
11289 sprintf(filename_out,
11290 "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc", dirname,
11291 year_start % 100, mon_start, day_start, hour_start,
11292 year_stop % 100, mon_stop, day_stop, hour_stop);
11293 LOG(1,
"Write traj file: %s", filename_out);
11296 start[0] = out_cnt;
11299 count[1] = (size_t) atm->
np;
11302 if (out_cnt == 0) {
11305 NC(nc_create(filename_out, NC_NETCDF4, &ncid));
11308 NC(nc_def_dim(ncid,
"time", NC_UNLIMITED, &tid));
11309 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11310 NC(nc_def_dim(ncid,
"TMDT", 7, &cid));
11315 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11316 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11317 NC_DEF_VAR(
"LAT", NC_DOUBLE, 2, dim_ids,
"Latitude",
"deg",
11319 NC_DEF_VAR(
"LON", NC_DOUBLE, 2, dim_ids,
"Longitude",
"deg",
11321 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 2, dim_ids,
"Pressure",
"hPa",
11323 NC_DEF_VAR(
"ZETA", NC_DOUBLE, 2, dim_ids,
"Zeta",
"K",
11325 for (
int iq = 0; iq < ctl->
nq; iq++)
11335 NC(nc_enddef(ncid));
11336 NC(nc_close(ncid));
11343 NC(nc_open(filename_out, NC_WRITE, &ncid));
11355 for (
int iq = 0; iq < ctl->
nq; iq++)
11359 NC(nc_close(ncid));
11362 if ((year == year_stop) && (mon == mon_stop)
11363 && (day == day_stop) && (hour == hour_stop)) {
11366 char filename_init[2 *
LEN] =
"./init_fix_YYYYMMDDHH.nc";
11367 sprintf(filename_init,
"%s/init_fix_%02d%02d%02d%02d.nc",
11368 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
11369 LOG(1,
"Write init file: %s", filename_init);
11372 NC(nc_create(filename_init, NC_NETCDF4, &ncid));
11375 NC(nc_def_dim(ncid,
"time", 1, &tid));
11376 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11381 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11382 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11383 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
11385 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
11387 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
11390 for (
int iq = 0; iq < ctl->
nq; iq++)
11400 NC(nc_enddef(ncid));
11408 for (
int iq = 0; iq < ctl->
nq; iq++)
11412 NC(nc_close(ncid));
11419 const char *filename,
11421 const atm_t *atm) {
11423 int ncid, obsid, varid;
11425 size_t start[2], count[2];
11428 NC(nc_create(filename, NC_NETCDF4, &ncid));
11431 NC(nc_def_dim(ncid,
"obs", (
size_t) atm->
np, &obsid));
11434 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &obsid,
"time",
11435 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11436 NC_DEF_VAR(
"press", NC_DOUBLE, 1, &obsid,
"pressure",
"hPa",
11438 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &obsid,
"longitude",
"degrees_east",
11440 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &obsid,
"latitude",
"degrees_north",
11442 for (
int iq = 0; iq < ctl->
nq; iq++)
11451 NC(nc_enddef(ncid));
11458 for (
int iq = 0; iq < ctl->
nq; iq++)
11462 NC(nc_close(ncid));
11468 const char *filename,
11475 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
11478 static int *obscount, nobs, nk;
11482 const int ensemble = (ctl->
nens > 0);
11488 if (ctl->
qnt_m < 0)
11489 ERRMSG(
"Need quantity mass!");
11492 ERRMSG(
"Missing ensemble IDs!");
11494 ERRMSG(
"Too many ensembles!");
11501 ALLOC(area,
double,
11507 ALLOC(rlon,
double,
11509 ALLOC(rlat,
double,
11511 ALLOC(robs,
double,
11522 LOG(1,
"Write CSI%s data: %s", ensemble ?
" ensemble" :
"", filename);
11523 if (!(out = fopen(filename,
"w")))
11524 ERRMSG(
"Cannot create file!");
11528 "# $1 = time [s]\n"
11529 "# $2 = ensemble ID\n"
11530 "# $3 = number of hits (cx)\n"
11531 "# $4 = number of misses (cy)\n"
11532 "# $5 = number of false alarms (cz)\n"
11533 "# $6 = number of observations (cx + cy)\n"
11534 "# $7 = number of forecasts (cx + cz)\n"
11535 "# $8 = bias (%%)\n"
11536 "# $9 = POD (%%)\n"
11537 "# $10 = FAR (%%)\n"
11538 "# $11 = CSI (%%)\n"
11539 "# $12 = hits by random chance\n"
11540 "# $13 = ETS (%%)\n"
11541 "# $14 = Pearson R\n"
11542 "# $15 = Spearman R\n"
11543 "# $16 = mean error [kg/m²]\n"
11544 "# $17 = RMSE [kg/m²]\n"
11545 "# $18 = MAE [kg/m²]\n"
11546 "# $19 = log-likelihood\n" "# $20 = number of points\n\n");
11554 for (
int iy = 0; iy < ctl->
csi_ny; iy++) {
11555 const double lat = ctl->
csi_lat0 + dlat * (iy + 0.5);
11556 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.0) * cos(
DEG2RAD(lat));
11561 const double t0 = t - 0.5 * ctl->
dt_mod;
11562 const double t1 = t + 0.5 * ctl->
dt_mod;
11566 ALLOC(modmean,
double,
11567 (ensemble ? ctl->
nens : 1) * grid_size);
11568 ALLOC(obsmean,
double,
11570 ALLOC(obscount,
int,
11572 ALLOC(obsstd,
double,
11576 for (
int i = 0; i < (ensemble ? ctl->
nens : 1); i++)
11577 ct[i] = cx[i] = cy[i] = cz[i] = n[i] = 0;
11580 for (
int i = 0; i < nobs; i++) {
11581 if (rt[i] < t0 || rt[i] >= t1 || !isfinite(robs[i]))
11585 const int ix = (int) ((rlon[i] - ctl->
csi_lon0) / dlon);
11586 const int iy = (int) ((rlat[i] - ctl->
csi_lat0) / dlat);
11587 const int iz = (int) ((rz[i] - ctl->
csi_z0) / dz);
11588 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
11594 obsmean[idx] += robs[i];
11595 obsstd[idx] +=
SQR(robs[i]);
11600 for (
int ip = 0; ip < atm->
np; ip++) {
11603 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11607 int ens_id = ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
11608 if (ens_id < 0 || ens_id >= (ensemble ? ctl->
nens : 1))
11609 ERRMSG(
"Ensemble ID out of range!");
11612 const int ix = (int) ((atm->
lon[ip] - ctl->
csi_lon0) / dlon);
11613 const int iy = (int) ((atm->
lat[ip] - ctl->
csi_lat0) / dlat);
11614 const int iz = (int) ((
Z(atm->
p[ip]) - ctl->
csi_z0) / dz);
11615 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
11625 for (
int e = 0; e < (ensemble ? ctl->
nens : 1); e++) {
11627 for (
int ix = 0; ix < ctl->
csi_nx; ix++)
11628 for (
int iy = 0; iy < ctl->
csi_ny; iy++)
11629 for (
int iz = 0; iz < ctl->
csi_nz; iz++) {
11634 if (obscount[idx]) {
11635 obsmean[idx] /= obscount[idx];
11637 sqrt(obsstd[idx] / obscount[idx] -
SQR(obsmean[idx]));
11641 const int midx = e * grid_size + idx;
11642 if (modmean[midx] > 0)
11643 modmean[midx] /= (1e6 * area[iy]);
11646 if (obscount[idx]) {
11661 x[n[e]] = modmean[midx];
11662 y[n[e]] = obsmean[idx];
11664 obsstdn[n[e]] = obsstd[idx];
11665 if ((++n[e]) >=
NCSI)
11666 ERRMSG(
"Too many points for statistics!");
11678 static double work[2 *
NCSI], work2[2 *
NCSI];
11679 const int n_obs = cx[e] + cy[e];
11680 const int n_for = cx[e] + cz[e];
11681 const double cx_rd = (ct[e] > 0) ? (1. * n_obs * n_for) / ct[e] : NAN;
11682 const double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
11683 const double pod = (n_obs > 0) ? 100. * cx[e] / n_obs : NAN;
11684 const double far = (n_for > 0) ? 100. * cz[e] / n_for : NAN;
11686 (cx[e] + cy[e] + cz[e] >
11687 0) ? 100. * cx[e] / (cx[e] + cy[e] + cz[e]) : NAN;
11689 (cx[e] + cy[e] + cz[e] - cx_rd >
11690 0) ? 100. * (cx[e] - cx_rd) / (cx[e] + cy[e] + cz[e] - cx_rd) : NAN;
11691 const double rho_p = gsl_stats_correlation(x, 1, y, 1, (
size_t) n[e]);
11692 const double rho_s =
11693 gsl_stats_spearman(x, 1, y, 1, (
size_t) n[e], work);
11694 for (
int i = 0; i < n[e]; i++) {
11695 work[i] = x[i] - y[i];
11696 work2[i] = (obsstdn[i] != 0) ? work[i] / obsstdn[i] : 0;
11698 const double mean = gsl_stats_mean(work, 1, (
size_t) n[e]);
11699 const double rmse =
11700 gsl_stats_sd_with_fixed_mean(work, 1, (
size_t) n[e], 0.0);
11701 const double absdev = gsl_stats_absdev_m(work, 1, (
size_t) n[e], 0.0);
11702 const double loglikelihood =
11703 gsl_stats_tss_m(work2, 1, (
size_t) n[e], 0.0) * -0.5;
11707 "%.2f %d %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n",
11708 t, ensemble ? e : -999, cx[e], cy[e], cz[e], n_obs, n_for, bias,
11709 pod, far, csi, cx_rd, ets, rho_p, rho_s, mean, rmse, absdev,
11710 loglikelihood, n[e]);
11713 for (
int i = 0; i < n[e]; i++)
11714 work[i] = work2[i] = x[i] = y[i] = obsstdn[i] = 0;
11715 ct[e] = cx[e] = cy[e] = cz[e] = n[e] = 0;
11743 const char *filename,
11753 static int n[
NENS];
11760 ERRMSG(
"Missing ensemble IDs!");
11763 const double t0 = t - 0.5 * ctl->
dt_mod;
11764 const double t1 = t + 0.5 * ctl->
dt_mod;
11767 for (
int i = 0; i <
NENS; i++) {
11768 for (
int iq = 0; iq < ctl->
nq; iq++)
11769 qm[iq][i] = qs[iq][i] = 0;
11770 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
11775 for (
int ip = 0; ip < atm->
np; ip++) {
11778 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11783 ERRMSG(
"Ensemble ID is out of range!");
11787 for (
int iq = 0; iq < ctl->
nq; iq++) {
11788 qm[iq][ctl->
qnt_ens] += atm->
q[iq][ip];
11799 LOG(1,
"Write ensemble data: %s", filename);
11800 if (!(out = fopen(filename,
"w")))
11801 ERRMSG(
"Cannot create file!");
11805 "# $1 = time [s]\n"
11806 "# $2 = altitude [km]\n"
11807 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
11808 for (
int iq = 0; iq < ctl->
nq; iq++)
11809 fprintf(out,
"# $%d = %s (mean) [%s]\n", 5 + iq,
11811 for (
int iq = 0; iq < ctl->
nq; iq++)
11812 fprintf(out,
"# $%d = %s (sigma) [%s]\n", 5 + ctl->
nq + iq,
11814 fprintf(out,
"# $%d = number of members\n\n", 5 + 2 * ctl->
nq);
11817 for (
int i = 0; i <
NENS; i++)
11819 cart2geo(xm[i], &dummy, &lon, &lat);
11820 fprintf(out,
"%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
11821 for (
int iq = 0; iq < ctl->
nq; iq++) {
11823 fprintf(out, ctl->
qnt_format[iq], qm[iq][i] / n[i]);
11825 for (
int iq = 0; iq < ctl->
nq; iq++) {
11827 double var = qs[iq][i] / n[i] -
SQR(qm[iq][i] / n[i]);
11828 fprintf(out, ctl->
qnt_format[iq], (var > 0 ? sqrt(var) : 0));
11830 fprintf(out,
" %d\n", n[i]);
11840 const char *filename,
11847 static double kz[
EP], kw[
EP];
11851 double *cd, *mean[
NQ], *sigma[
NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
11853 int *ixs, *iys, *izs, *np;
11859 LOG(1,
"Write grid data: %s", filename);
11872 for (
int iq = 0; iq < ctl->
nq; iq++) {
11873 ALLOC(mean[iq],
double,
11875 ALLOC(sigma[iq],
double,
11878 ALLOC(vmr_impl,
double,
11886 ALLOC(area,
double,
11888 ALLOC(press,
double,
11905#pragma omp parallel
for default(shared)
11906 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
11907 z[iz] = ctl->
grid_z0 + dz * (iz + 0.5);
11908 press[iz] =
P(z[iz]);
11912 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
11913 lon[ix] = ctl->
grid_lon0 + dlon * (ix + 0.5);
11914#pragma omp parallel for default(shared)
11915 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
11916 lat[iy] = ctl->
grid_lat0 + dlat * (iy + 0.5);
11917 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
11921 const double t0 = t - 0.5 * ctl->
dt_mod;
11922 const double t1 = t + 0.5 * ctl->
dt_mod;
11925#pragma omp parallel for default(shared)
11926 for (
int ip = 0; ip < atm->
np; ip++) {
11927 ixs[ip] = (int) ((atm->
lon[ip] - ctl->
grid_lon0) / dlon);
11928 iys[ip] = (int) ((atm->
lat[ip] - ctl->
grid_lat0) / dlat);
11929 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
grid_z0) / dz);
11930 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
11931 || ixs[ip] < 0 || ixs[ip] >= ctl->
grid_nx
11932 || iys[ip] < 0 || iys[ip] >= ctl->
grid_ny
11933 || izs[ip] < 0 || izs[ip] >= ctl->
grid_nz)
11938 for (
int ip = 0; ip < atm->
np; ip++)
11939 if (izs[ip] >= 0) {
11944 for (
int iq = 0; iq < ctl->
nq; iq++) {
11945 mean[iq][idx] += kernel * atm->
q[iq][ip];
11946 sigma[iq][idx] +=
SQR(kernel * atm->
q[iq][ip]);
11951#pragma omp parallel for default(shared)
11952 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
11953 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
11954 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
11961 if (ctl->
qnt_m >= 0)
11962 cd[idx] = mean[ctl->
qnt_m][idx] / (1e6 * area[iy]);
11965 vmr_impl[idx] = NAN;
11966 if (ctl->
qnt_m >= 0 && ctl->
molmass > 0 && met0 != NULL
11969 if (mean[ctl->
qnt_m][idx] > 0) {
11975 lon[ix], lat[iy], &temp, ci, cw, 1);
11979 MA / ctl->
molmass * cd[idx] / (
RHO(press[iz], temp) * dz * 1e3);
11985 for (
int iq = 0; iq < ctl->
nq; iq++) {
11986 mean[iq][idx] /= np[idx];
11987 const double var = sigma[iq][idx] / np[idx] -
SQR(mean[iq][idx]);
11988 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
11990 for (
int iq = 0; iq < ctl->
nq; iq++) {
11991 mean[iq][idx] = NAN;
11992 sigma[iq][idx] = NAN;
11999 t, z, lon, lat, area, dz, np);
12004 t, z, lon, lat, area, dz, np);
12008 ERRMSG(
"Grid data format GRID_TYPE unknown!");
12012 for (
int iq = 0; iq < ctl->
nq; iq++) {
12031 const char *filename,
12036 const double *vmr_impl,
12041 const double *area,
12051 if (!(out = popen(
"gnuplot",
"w")))
12052 ERRMSG(
"Cannot create pipe to gnuplot!");
12055 fprintf(out,
"set out \"%s.png\"\n", filename);
12059 int year, mon, day, hour, min, sec;
12060 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
12061 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
12062 year, mon, day, hour, min);
12068 ERRMSG(
"Cannot open file!");
12069 while (fgets(line,
LEN, in))
12070 fprintf(out,
"%s", line);
12077 if (!(out = fopen(filename,
"w")))
12078 ERRMSG(
"Cannot create file!");
12083 "# $1 = time [s]\n"
12084 "# $2 = altitude [km]\n"
12085 "# $3 = longitude [deg]\n"
12086 "# $4 = latitude [deg]\n"
12087 "# $5 = surface area [km^2]\n"
12088 "# $6 = layer depth [km]\n"
12089 "# $7 = column density (implicit) [kg/m^2]\n"
12090 "# $8 = volume mixing ratio (implicit) [ppv]\n"
12091 "# $9 = number of particles [1]\n");
12092 for (
int iq = 0; iq < ctl->
nq; iq++)
12093 fprintf(out,
"# $%i = %s (mean) [%s]\n", 10 + iq, ctl->
qnt_name[iq],
12096 for (
int iq = 0; iq < ctl->
nq; iq++)
12097 fprintf(out,
"# $%i = %s (stddev) [%s]\n", 10 + ctl->
nq + iq,
12099 fprintf(out,
"\n");
12102 for (
int ix = 0; ix < ctl->
grid_nx; ix++) {
12104 fprintf(out,
"\n");
12105 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
12107 fprintf(out,
"\n");
12108 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
12111 fprintf(out,
"%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
12112 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
12113 for (
int iq = 0; iq < ctl->
nq; iq++) {
12115 fprintf(out, ctl->
qnt_format[iq], mean[iq][idx]);
12118 for (
int iq = 0; iq < ctl->
nq; iq++) {
12120 fprintf(out, ctl->
qnt_format[iq], sigma[iq][idx]);
12122 fprintf(out,
"\n");
12135 const char *filename,
12140 const double *vmr_impl,
12145 const double *area,
12149 char longname[2 *
LEN], varname[2 *
LEN];
12153 int *help2, ncid, dimid[10], varid;
12155 size_t start[2], count[2];
12158 ALLOC(help,
double,
12164 NC(nc_create(filename, NC_NETCDF4, &ncid));
12167 NC(nc_def_dim(ncid,
"time", 1, &dimid[0]));
12168 NC(nc_def_dim(ncid,
"z", (
size_t) ctl->
grid_nz, &dimid[1]));
12169 NC(nc_def_dim(ncid,
"lat", (
size_t) ctl->
grid_ny, &dimid[2]));
12170 NC(nc_def_dim(ncid,
"lon", (
size_t) ctl->
grid_nx, &dimid[3]));
12171 NC(nc_def_dim(ncid,
"dz", 1, &dimid[4]));
12174 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &dimid[0],
"time",
12175 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
12176 NC_DEF_VAR(
"z", NC_DOUBLE, 1, &dimid[1],
"altitude",
"km", 0, 0);
12177 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &dimid[2],
"latitude",
"degrees_north", 0,
12179 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &dimid[3],
"longitude",
"degrees_east", 0,
12181 NC_DEF_VAR(
"dz", NC_DOUBLE, 1, &dimid[1],
"layer depth",
"km", 0, 0);
12182 NC_DEF_VAR(
"area", NC_DOUBLE, 1, &dimid[2],
"surface area",
"km**2", 0, 0);
12184 NC_DEF_VAR(
"cd", NC_FLOAT, 4, dimid,
"column density",
"kg m**-2",
12187 "volume mixing ratio (implicit)",
"ppv", ctl->
grid_nc_level, 0);
12188 NC_DEF_VAR(
"np", NC_INT, 4, dimid,
"number of particles",
"1", 0, 0);
12189 for (
int iq = 0; iq < ctl->
nq; iq++) {
12190 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
12191 sprintf(longname,
"%s (mean)", ctl->
qnt_longname[iq]);
12195 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
12196 sprintf(longname,
"%s (stddev)", ctl->
qnt_longname[iq]);
12202 NC(nc_enddef(ncid));
12212 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12213 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12214 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12219 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12220 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12221 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12226 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12227 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12228 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12233 for (
int iq = 0; iq < ctl->
nq; iq++) {
12234 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
12235 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12236 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12237 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12244 for (
int iq = 0; iq < ctl->
nq; iq++) {
12245 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
12246 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12247 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12248 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12255 NC(nc_close(ncid));
12265 const char *filename,
12271 if (!(out = fopen(filename,
"w")))
12272 ERRMSG(
"Cannot create file!");
12362 ERRMSG(
"Number of meteo variables doesn't match!");
12380 const char *varname) {
12389 for (
int ix = 0; ix < met->
nx; ix++)
12390 for (
int iy = 0; iy < met->
ny; iy++)
12391 help[
ARRAY_2D(ix, iy, met->
ny)] = var[ix][iy];
12394 LOG(2,
"Write 2-D variable: %s (uncompressed)", varname);
12396 (
size_t) (met->
nx * met->
ny),
12410 const char *varname,
12411 const int precision,
12412 const double tolerance) {
12421#pragma omp parallel for default(shared) collapse(2)
12422 for (
int ix = 0; ix < met->
nx; ix++)
12423 for (
int iy = 0; iy < met->
ny; iy++)
12424 for (
int ip = 0; ip < met->
np; ip++)
12425 help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)] = var[ix][iy][ip];
12429 LOG(2,
"Write 3-D variable: %s (uncompressed)", varname);
12431 (
size_t) (met->
nx * met->
ny * met->
np),
12438 (
size_t) met->
np, 0, out);
12446 FWRITE(&tolerance,
double,
12450 tolerance, 0, out);
12465 (
size_t) met->
np, met->
p, 0, out);
12475 FWRITE(&tolerance,
double,
12479 tolerance, 0, out);
12485 ERRMSG(
"MET_TYPE not supported!");
12488 LOG(3,
"%d %g", precision, tolerance);
12498 const char *filename,
12504 size_t start[4], count[4];
12505 NC(nc_create(filename, NC_NETCDF4, &ncid));
12508 int tid, lonid, latid, levid;
12509 NC(nc_def_dim(ncid,
"time", 1, &tid));
12510 NC(nc_def_dim(ncid,
"lon", (
size_t) met->
nx, &lonid));
12511 NC(nc_def_dim(ncid,
"lat", (
size_t) met->
ny, &latid));
12512 NC(nc_def_dim(ncid,
"lev", (
size_t) met->
np, &levid));
12515 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"time",
12516 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
12517 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &lonid,
"longitude",
"degrees_east", 0, 0);
12518 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &latid,
"latitude",
"degrees_north", 0, 0);
12519 NC_DEF_VAR(
"lev", NC_DOUBLE, 1, &levid,
"pressure",
"Pa", 0, 0);
12522 int dimid2[2] = { latid, lonid };
12523 NC_DEF_VAR(
"sp", NC_FLOAT, 2, dimid2,
"Surface pressure",
"Pa",
12525 NC_DEF_VAR(
"z", NC_FLOAT, 2, dimid2,
"Geopotential",
"m**2 s**-2",
12527 NC_DEF_VAR(
"t2m", NC_FLOAT, 2, dimid2,
"2 metre temperature",
"K",
12529 NC_DEF_VAR(
"u10m", NC_FLOAT, 2, dimid2,
"10 metre U wind component",
12531 NC_DEF_VAR(
"v10m", NC_FLOAT, 2, dimid2,
"10 metre V wind component",
12534 "Instantaneous eastward turbulent surface stress",
"N m**-2",
12537 "Instantaneous northward turbulent surface stress",
"N m**-2",
12540 "Instantaneous surface sensible heat flux",
"W m**-1",
12542 NC_DEF_VAR(
"lsm", NC_FLOAT, 2, dimid2,
"Land/sea mask",
"-",
12544 NC_DEF_VAR(
"sstk", NC_FLOAT, 2, dimid2,
"Sea surface temperature",
"K",
12546 NC_DEF_VAR(
"blp", NC_FLOAT, 2, dimid2,
"Boundary layer pressure",
"Pa",
12548 NC_DEF_VAR(
"pt", NC_FLOAT, 2, dimid2,
"Tropopause pressure",
"Pa",
12550 NC_DEF_VAR(
"tt", NC_FLOAT, 2, dimid2,
"Tropopause temperature",
"K",
12552 NC_DEF_VAR(
"zt", NC_FLOAT, 2, dimid2,
"Tropopause height",
"m",
12554 NC_DEF_VAR(
"h2ot", NC_FLOAT, 2, dimid2,
"Tropopause water vapor",
"ppv",
12556 NC_DEF_VAR(
"pct", NC_FLOAT, 2, dimid2,
"Cloud top pressure",
"Pa",
12558 NC_DEF_VAR(
"pcb", NC_FLOAT, 2, dimid2,
"Cloud bottom pressure",
"Pa",
12560 NC_DEF_VAR(
"cl", NC_FLOAT, 2, dimid2,
"Total column cloud water",
12563 "Pressure at lifted condensation level (LCL)",
"Pa",
12566 "Pressure at level of free convection (LFC)",
"Pa",
12569 "Pressure at equilibrium level (EL)",
"Pa", ctl->
met_nc_level,
12572 "Convective available potential energy",
"J kg**-1",
12574 NC_DEF_VAR(
"cin", NC_FLOAT, 2, dimid2,
"Convective inhibition",
12576 NC_DEF_VAR(
"o3c", NC_FLOAT, 2, dimid2,
"Total column ozone",
"DU",
12580 int dimid3[3] = { levid, latid, lonid };
12581 NC_DEF_VAR(
"t", NC_FLOAT, 3, dimid3,
"Temperature",
"K",
12583 NC_DEF_VAR(
"u", NC_FLOAT, 3, dimid3,
"U velocity",
"m s**-1",
12585 NC_DEF_VAR(
"v", NC_FLOAT, 3, dimid3,
"V velocity",
"m s**-1",
12587 NC_DEF_VAR(
"w", NC_FLOAT, 3, dimid3,
"Vertical velocity",
"Pa s**-1",
12589 NC_DEF_VAR(
"q", NC_FLOAT, 3, dimid3,
"Specific humidity",
"kg kg**-1",
12591 NC_DEF_VAR(
"o3", NC_FLOAT, 3, dimid3,
"Ozone mass mixing ratio",
12593 NC_DEF_VAR(
"clwc", NC_FLOAT, 3, dimid3,
"Cloud liquid water content",
12595 NC_DEF_VAR(
"crwc", NC_FLOAT, 3, dimid3,
"Cloud rain water content",
12597 NC_DEF_VAR(
"ciwc", NC_FLOAT, 3, dimid3,
"Cloud ice water content",
12599 NC_DEF_VAR(
"cswc", NC_FLOAT, 3, dimid3,
"Cloud snow water content",
12601 NC_DEF_VAR(
"cc", NC_FLOAT, 3, dimid3,
"Cloud cover",
"-",
12605 NC(nc_enddef(ncid));
12612 for (
int ip = 0; ip < met->
np; ip++)
12613 phelp[ip] = 100. * met->
p[ip];
12656 NC(nc_close(ncid));
12663 const char *varname,
12669 size_t start[4], count[4];
12677 for (
int ix = 0; ix < met->
nx; ix++)
12678 for (
int iy = 0; iy < met->
ny; iy++)
12679 help[
ARRAY_2D(iy, ix, met->
nx)] = scl * var[ix][iy];
12692 const char *varname,
12698 size_t start[4], count[4];
12706 for (
int ix = 0; ix < met->
nx; ix++)
12707 for (
int iy = 0; iy < met->
ny; iy++)
12708 for (
int ip = 0; ip < met->
np; ip++)
12709 help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)] = scl * var[ix][iy][ip];
12721 const char *filename,
12730 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
12731 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
12733 static int nobs, *obscount, ip, okay;
12742 if (ctl->
qnt_m < 0)
12743 ERRMSG(
"Need quantity mass!");
12747 ERRMSG(
"Specify molar mass!");
12754 ALLOC(area,
double,
12758 ALLOC(press,
double,
12764 ALLOC(rlon,
double,
12766 ALLOC(rlat,
double,
12768 ALLOC(robs,
double,
12775 LOG(1,
"Write profile data: %s", filename);
12776 if (!(out = fopen(filename,
"w")))
12777 ERRMSG(
"Cannot create file!");
12781 "# $1 = time [s]\n"
12782 "# $2 = altitude [km]\n"
12783 "# $3 = longitude [deg]\n"
12784 "# $4 = latitude [deg]\n"
12785 "# $5 = pressure [hPa]\n"
12786 "# $6 = temperature [K]\n"
12787 "# $7 = volume mixing ratio [ppv]\n"
12788 "# $8 = H2O volume mixing ratio [ppv]\n"
12789 "# $9 = O3 volume mixing ratio [ppv]\n"
12790 "# $10 = observed BT index [K]\n"
12791 "# $11 = number of observations\n");
12799 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
12800 z[iz] = ctl->
prof_z0 + dz * (iz + 0.5);
12801 press[iz] =
P(z[iz]);
12805 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
12806 lon[ix] = ctl->
prof_lon0 + dlon * (ix + 0.5);
12807 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
12808 lat[iy] = ctl->
prof_lat0 + dlat * (iy + 0.5);
12809 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
12814 const double t0 = t - 0.5 * ctl->
dt_mod;
12815 const double t1 = t + 0.5 * ctl->
dt_mod;
12818 ALLOC(mass,
double,
12820 ALLOC(obsmean,
double,
12822 ALLOC(obscount,
int,
12826 for (
int i = 0; i < nobs; i++) {
12831 else if (rt[i] >= t1)
12835 if (!isfinite(robs[i]))
12839 const int ix = (int) ((rlon[i] - ctl->
prof_lon0) / dlon);
12840 const int iy = (int) ((rlat[i] - ctl->
prof_lat0) / dlat);
12843 if (ix < 0 || ix >= ctl->
prof_nx || iy < 0 || iy >= ctl->
prof_ny)
12848 obsmean[idx] += robs[i];
12853 for (ip = 0; ip < atm->
np; ip++) {
12856 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
12860 const int ix = (int) ((atm->
lon[ip] - ctl->
prof_lon0) / dlon);
12861 const int iy = (int) ((atm->
lat[ip] - ctl->
prof_lat0) / dlat);
12862 const int iz = (int) ((
Z(atm->
p[ip]) - ctl->
prof_z0) / dz);
12865 if (ix < 0 || ix >= ctl->
prof_nx ||
12871 mass[idx] += atm->
q[ctl->
qnt_m][ip];
12875 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
12876 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
12878 if (obscount[idx2] > 0) {
12882 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
12884 if (mass[idx3] > 0) {
12893 fprintf(out,
"\n");
12896 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
12901 lon[ix], lat[iy], &temp, ci, cw, 1);
12903 lon[ix], lat[iy], &h2o, ci, cw, 0);
12905 lon[ix], lat[iy], &o3, ci, cw, 0);
12910 / (
RHO(press[iz], temp) * area[iy] * dz * 1e9);
12913 fprintf(out,
"%.2f %g %g %g %g %g %g %g %g %g %d\n",
12914 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
12915 obsmean[idx2] / obscount[idx2], obscount[idx2]);
12948 const char *filename,
12957 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[
EP],
12960 static int nobs, nk;
12973 ALLOC(rlon,
double,
12975 ALLOC(rlat,
double,
12977 ALLOC(robs,
double,
12988 LOG(1,
"Write sample data: %s", filename);
12989 if (!(out = fopen(filename,
"w")))
12990 ERRMSG(
"Cannot create file!");
12994 "# $1 = time [s]\n"
12995 "# $2 = altitude [km]\n"
12996 "# $3 = longitude [deg]\n"
12997 "# $4 = latitude [deg]\n"
12998 "# $5 = surface area [km^2]\n"
12999 "# $6 = layer depth [km]\n"
13000 "# $7 = number of particles [1]\n"
13001 "# $8 = column density [kg/m^2]\n"
13002 "# $9 = volume mixing ratio [ppv]\n"
13003 "# $10 = observed BT index [K]\n\n");
13008 area = M_PI * rmax2;
13012 const double t0 = t - 0.5 * ctl->
dt_mod;
13013 const double t1 = t + 0.5 * ctl->
dt_mod;
13016 for (
int i = 0; i < nobs; i++) {
13021 else if (rt[i] >= t1)
13026 geo2cart(0, rlon[i], rlat[i], x0);
13029 const double rp =
P(rz[i]);
13030 const double ptop =
P(rz[i] + ctl->
sample_dz);
13031 const double pbot =
P(rz[i] - ctl->
sample_dz);
13039 for (
int ip = 0; ip < atm->
np; ip++) {
13042 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13046 if (fabs(rlat[i] - atm->
lat[ip]) > dlat)
13052 if (
DIST2(x0, x1) > rmax2)
13057 if (atm->
p[ip] > pbot || atm->
p[ip] < ptop)
13061 if (ctl->
qnt_m >= 0)
13068 const double cd = mass / (1e6 * area);
13079 rlon[i], rlat[i], &temp, ci, cw, 1);
13088 fprintf(out,
"%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
13089 rlon[i], rlat[i], area, ctl->
sample_dz, np, cd, vmr, robs[i]);
13110 const char *filename,
13117 static double rmax2, x0[3], x1[3];
13126 LOG(1,
"Write station data: %s", filename);
13129 if (!(out = fopen(filename,
"w")))
13130 ERRMSG(
"Cannot create file!");
13134 "# $1 = time [s]\n"
13135 "# $2 = altitude [km]\n"
13136 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
13137 for (
int iq = 0; iq < ctl->
nq; iq++)
13138 fprintf(out,
"# $%i = %s [%s]\n", (iq + 5),
13140 fprintf(out,
"\n");
13148 const double t0 = t - 0.5 * ctl->
dt_mod;
13149 const double t1 = t + 0.5 * ctl->
dt_mod;
13152 for (
int ip = 0; ip < atm->
np; ip++) {
13155 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13171 if (
DIST2(x0, x1) > rmax2)
13179 fprintf(out,
"%.2f %g %g %g",
13180 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]);
13181 for (
int iq = 0; iq < ctl->
nq; iq++) {
13183 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
13185 fprintf(out,
"\n");
13196 const char *filename,
13207 LOG(1,
"Write VTK data: %s", filename);
13210 const double t0 = t - 0.5 * ctl->
dt_mod;
13211 const double t1 = t + 0.5 * ctl->
dt_mod;
13214 if (!(out = fopen(filename,
"w")))
13215 ERRMSG(
"Cannot create file!");
13219 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13220 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13227 "# vtk DataFile Version 3.0\n"
13228 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
13231 fprintf(out,
"POINTS %d float\n", np);
13233 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13234 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13238 const double coslat = cos(
DEG2RAD(atm->
lat[ip]));
13239 const double x = radius * coslat * cos(
DEG2RAD(atm->
lon[ip]));
13240 const double y = radius * coslat * sin(
DEG2RAD(atm->
lon[ip]));
13241 const double z = radius * sin(
DEG2RAD(atm->
lat[ip]));
13242 fprintf(out,
"%g %g %g\n", x, y, z);
13245 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13246 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13248 fprintf(out,
"%g %g %g\n", atm->
lon[ip], atm->
lat[ip],
13253 fprintf(out,
"POINT_DATA %d\n", np);
13254 for (
int iq = 0; iq < ctl->
nq; iq++) {
13255 fprintf(out,
"SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
13257 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13258 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13260 fprintf(out,
"%g\n", atm->
q[iq][ip]);
void read_met_geopot(const ctl_t *ctl, met_t *met)
Calculates geopotential heights from meteorological data.
void mptrac_alloc(ctl_t **ctl, cache_t **cache, clim_t **clim, met_t **met0, met_t **met1, atm_t **atm, dd_t **dd)
Allocates and initializes memory resources for MPTRAC.
void mptrac_write_atm(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes air parcel data to a file in various formats.
void day2doy(const int year, const int mon, const int day, int *doy)
Get day of year from date.
void read_met_extrapolate(met_t *met)
Extrapolates meteorological data.
void write_atm_clams_traj(const char *dirname, const ctl_t *ctl, const atm_t *atm, const double t)
Writes CLaMS trajectory data to a NetCDF file.
int read_met_nc_2d(const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const char *varname5, const char *varname6, const ctl_t *ctl, const met_t *met, dd_t *dd, float dest[EX][EY], const float scl, const int init)
Reads a 2-dimensional meteorological variable from a NetCDF file.
void write_met_nc_2d(const int ncid, const char *varname, met_t *met, float var[EX][EY], const float scl)
Writes a 2D meteorological variable to a NetCDF file.
void read_met_sample(const ctl_t *ctl, met_t *met)
Downsamples meteorological data based on specified parameters.
void write_met_bin_3d(FILE *out, const ctl_t *ctl, met_t *met, float var[EX][EY][EP], const char *varname, const int precision, const double tolerance)
Writes a 3-dimensional meteorological variable to a binary file.
void read_obs(const char *filename, const ctl_t *ctl, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from a file and stores it in arrays.
void module_advect(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Advances particle positions using different advection schemes.
void module_timesteps(const ctl_t *ctl, cache_t *cache, met_t *met0, atm_t *atm, const double t)
Calculate time steps for air parcels based on specified conditions.
void module_meteo(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Update atmospheric properties using meteorological data.
void read_clim_photo(const char *filename, clim_photo_t *photo)
Reads photolysis rates from a NetCDF file and populates the given photolysis structure.
void read_met_cloud(met_t *met)
Calculates cloud-related variables for each grid point.
void module_decay(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, atm_t *atm)
Simulate exponential decay processes for atmospheric particles.
double sedi(const double p, const double T, const double rp, const double rhop)
Calculates the sedimentation velocity of a particle in air.
double cos_sza(const double sec, const double lon, const double lat)
Calculates the cosine of the solar zenith angle.
void intpol_met_space_2d(const met_t *met, float array[EX][EY], const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables in 2D space.
int read_met_nc_3d(const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const ctl_t *ctl, const met_t *met, dd_t *dd, float dest[EX][EY][EP], const float scl)
Reads a 3-dimensional meteorological variable from a NetCDF file.
int read_atm_nc(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a generic netCDF file and populates the given atmospheric structure.
void read_met_pbl(const ctl_t *ctl, met_t *met)
Computes the planetary boundary layer (PBL) pressure based on meteorological data.
void read_met_detrend(const ctl_t *ctl, met_t *met)
Detrends meteorological data.
void read_met_tropo(const ctl_t *ctl, const clim_t *clim, met_t *met)
Calculates the tropopause and related meteorological variables based on various methods and stores th...
void read_obs_asc(const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from an ASCII file.
void module_chem_init(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Initializes the chemistry modules by setting atmospheric composition.
int locate_reg(const double *xx, const int n, const double x)
Locate the index of the interval containing a given value in a regular grid.
void read_met_nc_levels(const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads and processes meteorological level data from NetCDF files with domain decomposition.
void read_met_monotonize(const ctl_t *ctl, met_t *met)
Makes zeta and pressure profiles monotone.
int read_clim_ts(const char *filename, clim_ts_t *ts)
Reads a climatological time series from a file and populates the given time series structure.
void read_met_periodic(met_t *met)
Applies periodic boundary conditions to meteorological data along longitudinal axis.
void mptrac_run_timestep(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t **met0, met_t **met1, atm_t *atm, double t, dd_t *dd)
Executes a single timestep of the MPTRAC model simulation.
void module_timesteps_init(ctl_t *ctl, const atm_t *atm)
Initialize start time and time interval for time-stepping.
void write_ens(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes ensemble data to a file.
void module_mixing(const ctl_t *ctl, const clim_t *clim, atm_t *atm, const double t)
Update atmospheric properties through interparcel mixing.
double clim_zm(const clim_zm_t *zm, const double t, const double lat, const double p)
Interpolates monthly mean zonal mean climatological variables.
void module_mixing_help(const ctl_t *ctl, const clim_t *clim, atm_t *atm, const int *ixs, const int *iys, const int *izs, const int qnt_idx, const int use_ensemble)
Perform subgrid-scale interparcel mixing of a given quantity.
void read_clim_photo_help(const int ncid, const char *varname, const clim_photo_t *photo, double var[CP][CSZA][CO3])
Reads a 3D climatological photochemistry variable from a NetCDF file.
void read_met_ml2pl(const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname)
Interpolates meteorological data to specified pressure levels.
double clim_tropo(const clim_t *clim, const double t, const double lat)
Calculates the tropopause pressure based on climatological data.
void read_obs_nc(const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from a NetCDF file.
void read_met_bin_2d(FILE *in, const met_t *met, float var[EX][EY], const char *varname)
Reads a 2-dimensional meteorological variable from a binary file and stores it in the provided array.
int locate_irr(const double *xx, const int n, const double x)
Locate the index of the interval containing a given value in a sorted array.
void module_isosurf_init(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Initialize the isosurface module based on atmospheric data.
void level_definitions(ctl_t *ctl)
Defines pressure levels for meteorological data.
void write_grid_asc(const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
Writes grid data to an ASCII file.
void mptrac_update_device(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
Updates device memory for specified data structures.
void time2jsec(const int year, const int mon, const int day, const int hour, const int min, const int sec, const double remain, double *jsec)
Converts time components to seconds since January 1, 2000, 12:00:00 UTC.
void mptrac_init(ctl_t *ctl, cache_t *cache, clim_t *clim, atm_t *atm, const int ntask)
Initializes the MPTRAC model and its associated components.
void intpol_met_time_3d(const met_t *met0, float array0[EX][EY][EP], const met_t *met1, float array1[EX][EY][EP], const double ts, const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological data in 3D space and time.
void get_met_filename(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 fft_help(double *fcReal, double *fcImag, const int n)
Computes the Fast Fourier Transform (FFT) of a complex sequence.
void module_wet_depo(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Perform wet deposition calculations for air parcels.
void compress_pck(const char *varname, float *array, const size_t nxy, const size_t nz, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats.
double nat_temperature(const double p, const double h2o, const double hno3)
Calculates the nitric acid trihydrate (NAT) temperature.
void spline(const double *x, const double *y, const int n, const double *x2, double *y2, const int n2, const int method)
Performs spline interpolation or linear interpolation.
void module_chem_grid(const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double tt)
Computes gridded chemical tracer concentrations (volume mixing ratio) from individual air parcel mass...
double clim_photo(const double rate[CP][CSZA][CO3], const clim_photo_t *photo, const double p, const double sza, const double o3c)
Calculates the photolysis rate for a given set of atmospheric conditions.
void read_clim_zm(const char *filename, const char *varname, clim_zm_t *zm)
Reads zonally averaged climatological data from a netCDF file and populates the given structure.
void read_met_nc_grid_dd_naive(dd_t *dd, const ctl_t *ctl, met_t *met, const int ncid)
Read meteorological grid information and construct the domain-decomposed grid with halo regions.
void module_sedi(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate sedimentation of particles in the atmosphere.
int read_met_nc(const char *filename, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads meteorological data from a NetCDF file and processes it.
void timer(const char *name, const char *group, const int output)
Measures and reports elapsed time for named and grouped timers.
void write_atm_asc(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes air parcel data to an ASCII file or gnuplot.
void intpol_met_space_3d(const met_t *met, float array[EX][EY][EP], const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables in 3D space.
void module_sort(const ctl_t *ctl, const met_t *met0, atm_t *atm)
Sort particles according to box index.
void module_convection(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Performs convective mixing of atmospheric particles.
void read_kernel(const char *filename, double kz[EP], double kw[EP], int *nk)
Reads kernel function data from a file and populates the provided arrays.
void module_bound_cond(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Apply boundary conditions to particles based on meteorological and climatological data.
double scan_ctl(const char *filename, int argc, char *argv[], const char *varname, const int arridx, const char *defvalue, char *value)
Scans a control file or command-line arguments for a specified variable.
void module_advect_init(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Initializes the advection module by setting up pressure fields.
void module_radio_decay(const ctl_t *ctl, const cache_t *cache, atm_t *atm)
Apply radioactive decay to atmospheric tracer species.
void mptrac_get_met(ctl_t *ctl, clim_t *clim, const double t, met_t **met0, met_t **met1, dd_t *dd)
Retrieves meteorological data for the specified time.
void module_sort_help(double *a, const int *p, const int np)
Reorder an array based on a given permutation.
float stddev(const float *data, const int n)
Calculates the standard deviation of a set of data.
void intpol_tropo_3d(const double time0, float array0[EX][EY], const double time1, float array1[EX][EY], const double lons[EX], const double lats[EY], const int nlon, const int nlat, const double time, const double lon, const double lat, const int method, double *var, double *sigma)
Interpolates tropopause data in 3D (latitude, longitude, and time).
void read_met_bin_3d(FILE *in, const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname, const float bound_min, const float bound_max)
Reads 3D meteorological data from a binary file, potentially using different compression methods.
int locate_irr_float(const float *xx, const int n, const double x, const int ig)
Locate the index of the interval containing a given value in an irregularly spaced array.
double time_from_filename(const char *filename, const int offset)
Extracts and converts a timestamp from a filename to Julian seconds.
void write_prof(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes profile data to a specified file.
void mptrac_read_clim(const ctl_t *ctl, clim_t *clim)
Reads various climatological data and populates the given climatology structure.
double tropo_weight(const clim_t *clim, const atm_t *atm, const int ip)
Computes a weighting factor based on tropopause pressure.
void write_met_nc(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a NetCDF file.
void module_rng_init(const int ntask)
Initialize random number generators for parallel tasks.
int mptrac_read_atm(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a specified file into the given atmospheric structure.
void mptrac_update_host(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
Updates host memory for specified data structures.
void mptrac_write_output(const char *dirname, const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double t)
Writes various types of output data to files in a specified directory.
double clim_oh(const ctl_t *ctl, const clim_t *clim, const double t, const double lon, const double lat, const double p)
Calculates the hydroxyl radical (OH) concentration from climatology data, with an optional diurnal co...
void read_met_ozone(met_t *met)
Calculates the total column ozone from meteorological ozone data.
void read_met_nc_surface(const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads and processes surface meteorological data from NetCDF files with domain decomposition.
void clim_tropo_init(clim_t *clim)
Initializes the tropopause data in the climatology structure.
void module_rng(const ctl_t *ctl, double *rs, const size_t n, const int method)
Generate random numbers using various methods and distributions.
void write_station(const char *filename, const ctl_t *ctl, atm_t *atm, const double t)
Writes station data to a specified file.
void cart2geo(const double *x, double *z, double *lon, double *lat)
State variables of cuRAND random number generator.
void doy2day(const int year, const int doy, int *mon, int *day)
Converts a given day of the year (DOY) to a date (month and day).
void intpol_met_4d_zeta(const met_t *met0, float heights0[EX][EY][EP], float array0[EX][EY][EP], const met_t *met1, float heights1[EX][EY][EP], float array1[EX][EY][EP], const double ts, const double height, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables to a given position and time.
void intpol_met_time_2d(const met_t *met0, float array0[EX][EY], const met_t *met1, float array1[EX][EY], const double ts, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological data in 2D space and time.
void module_position(const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Update the positions and pressure levels of atmospheric particles.
void clim_oh_diurnal_correction(const ctl_t *ctl, clim_t *clim)
Applies a diurnal correction to the hydroxyl radical (OH) concentration in climatology data.
void locate_vert(float profiles[EX][EY][EP], const int np, const int lon_ap_ind, const int lat_ap_ind, const double height_ap, int *ind)
Locate the four vertical indizes of a box for a given height value.
void write_met_bin_2d(FILE *out, met_t *met, float var[EX][EY], const char *varname)
Writes a 2-dimensional meteorological variable to a binary file.
void read_met_pv(met_t *met)
Calculates potential vorticity (PV) from meteorological data.
int read_atm_bin(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a binary file and populates the given atmospheric structure.
void 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.
double clim_ts(const clim_ts_t *ts, const double t)
Interpolates a time series of climatological variables.
void jsec2time(const double jsec, int *year, int *mon, int *day, int *hour, int *min, int *sec, double *remain)
Converts Julian seconds to calendar date and time components.
int read_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a binary file.
void write_atm_clams(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a NetCDF file in the CLaMS format.
void get_met_replace(char *orig, const char *search, const char *repl)
Replaces occurrences of a substring in a string with another substring.
void module_diff_turb(const ctl_t *ctl, cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Applies turbulent diffusion processes to atmospheric particles.
int read_atm_clams(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads atmospheric data from a CLAMS NetCDF file.
int mptrac_read_met(const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met, dd_t *dd)
Reads meteorological data from a file, supporting multiple formats and MPI broadcasting.
void write_vtk(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes VTK (Visualization Toolkit) data to a specified file.
void module_tracer_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Simulate chemical reactions involving long-lived atmospheric tracers.
void mptrac_read_ctl(const char *filename, int argc, char *argv[], ctl_t *ctl)
Reads control parameters from a configuration file and populates the given structure.
void mptrac_free(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm, dd_t *dd)
Frees memory resources allocated for MPTRAC.
void read_met_polar_winds(met_t *met)
Applies a fix for polar winds in meteorological data.
void module_h2o2_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Perform chemical reactions involving H2O2 within cloud particles.
void write_grid_nc(const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
Writes grid data to a NetCDF file.
double pbl_weight(const ctl_t *ctl, const atm_t *atm, const int ip, const double pbl, const double ps)
Computes a weighting factor based on planetary boundary layer pressure.
void module_diff_pbl(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Computes particle diffusion within the planetary boundary layer (PBL).
void write_met_nc_3d(const int ncid, const char *varname, met_t *met, float var[EX][EY][EP], const float scl)
Writes a 3D meteorological variable to a NetCDF file.
void module_isosurf(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Apply the isosurface module to adjust atmospheric properties.
void module_oh_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Perform hydroxyl chemistry calculations for atmospheric particles.
void geo2cart(const double z, const double lon, const double lat, double *x)
Converts geographic coordinates (longitude, latitude, altitude) to Cartesian coordinates.
void read_met_nc_grid(const char *filename, const int ncid, const ctl_t *ctl, met_t *met, dd_t *dd)
Reads meteorological grid data from NetCDF files with domain decomposition.
void get_tropo(const int met_tropo, ctl_t *ctl, const 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.
double kernel_weight(const double kz[EP], const double kw[EP], const int nk, const double p)
Calculates the kernel weight based on altitude and given kernel data.
int read_atm_asc(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from an ASCII file and populates the given atmospheric structure.
void intpol_check_lon_lat(const double *lons, const int nlon, const double *lats, const int nlat, const double lon, const double lat, double *lon2, double *lat2)
Adjusts longitude and latitude to ensure they fall within valid bounds.
void write_sample(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes sample data to a specified file.
void write_grid(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes grid data to a file in ASCII or netCDF format.
void module_dry_depo(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate dry deposition of atmospheric particles.
void write_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data in binary format to a specified file.
void write_atm_bin(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a binary file.
void read_met_cape(const ctl_t *ctl, const clim_t *clim, met_t *met)
Calculates Convective Available Potential Energy (CAPE) for each grid point.
void mptrac_write_met(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a file, supporting multiple formats and compression options.
double lapse_rate(const double t, const double h2o)
Calculates the moist adiabatic lapse rate in Kelvin per kilometer.
void write_csi(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes Critical Success Index (CSI) data to a file.
void write_atm_nc(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a NetCDF file.
MPTRAC library declarations.
#define NN(x0, y0, x1, y1, x)
Perform nearest-neighbor interpolation.
void dd_init(const ctl_t *ctl, dd_t *dd, atm_t *atm)
Initialize the domain decomposition infrastructure.
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.
void read_met_grib_surface(codes_handle **handles, const int num_messages, const ctl_t *ctl, met_t *met)
Reads surface meteorological data from a grib file and stores it in the meteorological data structure...
#define ARRAY_3D(ix, iy, ny, iz, nz)
Compute the linear index of a 3D array element.
#define PARTICLE_LOOP(ip0, ip1, check_dt,...)
Loop over particle indices with OpenACC acceleration.
#define MA
Molar mass of dry air [g/mol].
#define AVO
Avogadro constant [1/mol].
#define KB
Boltzmann constant [kg m^2/(K s^2)].
#define MH2O
Molar mass of water vapor [g/mol].
#define METVAR
Number of 3-D meteorological variables.
#define NENS
Maximum number of data points for ensemble analysis.
#define FWRITE(ptr, type, size, out)
Write data from memory to a file stream.
#define PW(p, h2o)
Calculate partial water vapor pressure.
#define H0
Scale height [km].
#define NC_PUT_ATT_GLOBAL(attname, text)
Add a global text attribute to a NetCDF file.
#define MOLEC_DENS(p, t)
Calculate the density of a gas molecule.
#define LAPSE(p1, t1, p2, t2)
Calculate lapse rate.
#define NC(cmd)
Execute a NetCDF command and check for errors.
#define SELECT_TIMER(id, group)
Select and start a timer with specific attributes.
#define ECC_READ_3D(variable, level, target, scaling_factor, found_flag)
Writes 3D data from a grib message into the meteo struct.
void compress_cms(const ctl_t *ctl, const char *varname, float *array, const size_t nx, const size_t ny, const size_t np, const double *plev, const int decompress, FILE *inout)
Compresses or decompresses a 3-D meteorological field using cmultiscale.
#define DOTP(a, b)
Calculate the dot product of two vectors.
#define RA
Specific gas constant of dry air [J/(kg K)].
int dd_calc_subdomain_from_coords(const ctl_t *ctl, const dd_t *dd, const double lon, const double lat)
Determine MPI subdomain from particle coordinates.
#define DD_EY_GLOB
Maximum number of latitudes of global 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_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.
#define SH(h2o)
Compute specific humidity from water vapor volume mixing ratio.
#define INTPOL_3D(var, init)
Perform 3D interpolation for a meteorological variable.
#define NOBS
Maximum number of observation data points.
#define NTHREADS
Maximum number of OpenMP threads.
#define ARRAY_2D(ix, iy, ny)
Macro for computing the linear index of a 2D array element.
#define Z(p)
Convert pressure to altitude.
#define codes_handle
Placeholder when ECCODES is not available.
#define P(z)
Compute pressure at given altitude.
#define LV
Latent heat of vaporization of water [J/kg].
#define G0
Standard gravity [m/s^2].
#define CP
Maximum number of pressure levels for climatological data.
#define NQ
Maximum number of quantities per data point.
void dd_assign_subdomains(const ctl_t *ctl, const dd_t *dd, atm_t *atm, const int init)
Assign or update particle subdomain ownership.
#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.
void dd_normalize_lon_lat(const dd_t *dd, double *lon, double *lat)
Normalize geographic coordinates to the global grid convention.
#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.
void dd_sort(const ctl_t *ctl, const met_t *met0, atm_t *atm, dd_t *dd, int *npart)
Sort local atmospheric particles and determine export counts for domain decomposition.
void dd_particles2atm(const ctl_t *ctl, cache_t *cache, const particle_t *particles, const int npart, atm_t *atm)
Copy received particles from the communication buffer into the atmospheric state.
#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.
#define WARN(...)
Print a warning message with contextual information.
#define ZETA(ps, p, t)
Computes the value of the zeta vertical coordinate.
#define RHICE(p, t, h2o)
Compute relative humidity over ice.
#define INTPOL_TIME_ALL(time, p, lon, lat)
Interpolate multiple meteorological variables in time.
#define ALLOC(ptr, type, n)
Allocate memory for a pointer with error handling.
void read_met_grib_levels(codes_handle **handles, const int num_messages, const ctl_t *ctl, met_t *met)
Reads meteorological variables at different vertical levels from a grib file.
#define SET_ATM(qnt, val)
Set atmospheric quantity value.
#define CTS
Maximum number of data points of climatological time series.
#define ECC_READ_2D(variable, target, scaling_factor, found_flag)
Writes 2-D data from a grib message into the meteo struct.
#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.
void dd_atm2particles(const ctl_t *ctl, cache_t *cache, atm_t *atm, particle_t *particles, const int npart)
Copy migratable atmospheric particles from the ATM state into a particle buffer.
#define NP
Maximum number of atmospheric data points.
#define NTIMER
Maximum number of timers.
void dd_communicate_particles(const ctl_t *ctl, const dd_t *dd, particle_t **particles, int *npart, int *capacity)
Exchange particles between MPI ranks according to their destination rank.
#define INTPOL_2D(var, init)
Perform 2D interpolation for a meteorological variable.
#define RH(p, t, h2o)
Compute relative humidity over water.
void module_dd(const ctl_t *ctl, cache_t *cache, dd_t *dd, atm_t *atm, met_t **met)
Perform domain decomposition and exchange particles between MPI ranks.
#define NC_PUT_FLOAT(varname, ptr, hyperslab)
Write a float array to a NetCDF file.
#define DD_EX_GLOB
Maximum number of longitudes of global meteo data.
#define CY
Maximum number of latitudes for climatological data.
void dd_sort_help(double *a, dd_t *dd, const int np)
Apply the sorting permutation to a particle data array.
#define LOG(level,...)
Print a log message with a specified logging level.
#define NC_DEF_VAR(varname, type, ndims, dims, long_name, units, level, quant)
Define a NetCDF variable with attributes.
#define TDEW(p, h2o)
Calculate dew point temperature.
#define ARRHENIUS(a, b, t)
Calculate the Arrhenius rate constant.
#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 RHO(p, t)
Compute density of air.
void module_kpp_chem(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
KPP chemistry module.
#define CO3
Maximum number of total column ozone data for climatological data.
void read_met_grib_grid(codes_handle **handles, int count_handles, met_t *met)
Reads global meteorological information from a grib file.
void compress_sz3(const char *varname, float *array, const int nx, const int ny, const int nz, const int precision, const double tolerance, const int decompress, FILE *inout)
Compresses or decompresses a 3-D float array using the SZ3 library.
#define NC_PUT_DOUBLE(varname, ptr, hyperslab)
Write double precision data to a NetCDF variable.
#define ECC(cmd)
Execute an ECCODES command and check for errors.
#define LIN(x0, y0, x1, y1, x)
Linear interpolation.
#define DIST2(a, b)
Calculate the squared Euclidean distance between two points in Cartesian coordinates.
#define NC_INQ_DIM(dimname, ptr, min, max, check)
Inquire the length of a dimension in a NetCDF file.
#define DEG2DX(dlon, lat)
Convert a longitude difference to a distance in the x-direction (east-west) at a specific latitude.
#define CPD
Specific heat of dry air at constant pressure [J/(kg K)].
#define CSZA
Maximum number of solar zenith angles for climatological data.
#define DY2DEG(dy)
Convert a distance in kilometers to degrees latitude.
#define MAX(a, b)
Macro to determine the maximum of two values.
#define FMOD(x, y)
Calculate the floating-point remainder of dividing x by y.
double lat[NP]
Latitude [deg].
double lon[NP]
Longitude [deg].
int np
Number of air parcels.
double q[NQ][NP]
Quantity data (for various, user-defined attributes).
double p[NP]
Pressure [hPa].
double dt[NP]
Timesteps [s].
double iso_ts[NP]
Isosurface balloon time [s].
int iso_n
Isosurface balloon number of data points.
double iso_ps[NP]
Isosurface balloon pressure [hPa].
double rs[3 *NP+1]
Random numbers.
float uvwp[NP][3]
Wind perturbations [m/s].
double iso_var[NP]
Isosurface variables.
Climatological data in the form of photolysis rates.
int nsza
Number of solar zenith angles.
double sza[CSZA]
Solar zenith angle [rad].
double o3_1[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O1d + O2) [1/s].
double p[CP]
Pressure [hPa].
double ccl2f2[CP][CSZA][CO3]
CCl2F2 photolysis rate [1/s].
double o2[CP][CSZA][CO3]
O2 photolysis rate [1/s].
double ccl3f[CP][CSZA][CO3]
CCl3F photolysis rate [1/s].
double n2o[CP][CSZA][CO3]
N2O photolysis rate [1/s].
double h2o2[CP][CSZA][CO3]
H2O2 photolysis rate [1/s].
double h2o[CP][CSZA][CO3]
H2O photolysis rate [1/s].
double ccl4[CP][CSZA][CO3]
CCl4 photolysis rate [1/s].
double o3_2[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O3p + O2) [1/s].
double o3c[CO3]
Total column ozone [DU].
int np
Number of pressure levels.
int no3c
Number of total ozone columns.
clim_ts_t ccl2f2
CFC-12 time series.
clim_photo_t photo
Photolysis rates.
clim_zm_t ho2
HO2 zonal means.
clim_zm_t hno3
HNO3 zonal means.
int tropo_ntime
Number of tropopause timesteps.
clim_ts_t sf6
SF6 time series.
clim_ts_t ccl4
CFC-10 time series.
clim_ts_t ccl3f
CFC-11 time series.
clim_zm_t o1d
O(1D) zonal means.
double tropo_lat[73]
Tropopause latitudes [deg].
clim_zm_t h2o2
H2O2 zonal means.
int tropo_nlat
Number of tropopause latitudes.
clim_zm_t oh
OH zonal means.
double tropo[12][73]
Tropopause pressure values [hPa].
double tropo_time[12]
Tropopause time steps [s].
clim_ts_t n2o
N2O time series.
Climatological data in the form of time series.
double vmr[CTS]
Volume mixing ratio [ppv].
double time[CTS]
Time [s].
int ntime
Number of timesteps.
Climatological data in the form of zonal means.
int np
Number of pressure levels.
double p[CP]
Pressure [hPa].
double vmr[CT][CP][CY]
Volume mixing ratio [ppv].
int ntime
Number of timesteps.
int nlat
Number of latitudes.
double lat[CY]
Latitude [deg].
double grid_z0
Lower altitude of gridded data [km].
int qnt_o3
Quantity array index for ozone volume mixing ratio.
double csi_lat1
Upper latitude of gridded CSI data [deg].
char csi_obsfile[LEN]
Observation data file for CSI analysis.
int qnt_Coh
Quantity array index for OH volume mixing ratio (chemistry code).
double wet_depo_ic_a
Coefficient A for wet deposition in cloud (exponential form).
int met_nc_scale
Check netCDF scaling factors (0=no, 1=yes).
int qnt_pel
Quantity array index for pressure at equilibrium level (EL).
int csi_nz
Number of altitudes of gridded CSI data.
double molmass
Molar mass [g/mol].
int qnt_p
Quantity array index for pressure.
int qnt_Cccl2f2
Quantity array index for CFC-12 volume mixing ratio (chemistry code).
int dd_halos_size
Domain decomposition size of halos given in grid-points.
char atm_gpfile[LEN]
Gnuplot file for atmospheric data.
int mixing_nx
Number of longitudes of mixing grid.
double chemgrid_z1
Upper altitude of chemistry grid [km].
char qnt_format[NQ][LEN]
Quantity output format.
int qnt_m
Quantity array index for mass.
int qnt_aoa
Quantity array index for age of air.
int qnt_rhop
Quantity array index for particle density.
int qnt_swc
Quantity array index for cloud snow water content.
double csi_obsmin
Minimum observation index to trigger detection.
int qnt_pcb
Quantity array index for cloud bottom pressure.
char clim_n2o_timeseries[LEN]
Filename of N2O time series.
double bound_dzs
Boundary conditions surface layer depth [km].
double csi_lon1
Upper longitude of gridded CSI data [deg].
int qnt_u
Quantity array index for zonal wind.
double stat_lon
Longitude of station [deg].
double mixing_trop
Interparcel exchange parameter for mixing in the troposphere.
double sort_dt
Time step for sorting of particle data [s].
double mixing_z1
Upper altitude of mixing grid [km].
double stat_r
Search radius around station [km].
double wet_depo_bc_a
Coefficient A for wet deposition below cloud (exponential form).
int met_zstd_level
ZSTD compression level (from -5 to 22).
int csi_ny
Number of latitudes of gridded CSI data.
int vtk_sphere
Spherical projection for VTK data (0=no, 1=yes).
double chemgrid_z0
Lower altitude of chemistry grid [km].
double met_pbl_min
Minimum depth of planetary boundary layer [km].
int qnt_iwc
Quantity array index for cloud ice water content.
double chemgrid_lat0
Lower latitude of chemistry grid [deg].
double conv_cape
CAPE threshold for convection module [J/kg].
int qnt_Co1d
Quantity array index for O(1D) volume mixing ratio (chemistry code).
double met_cms_eps_pv
cmultiscale compression epsilon for potential vorticity.
int qnt_pw
Quantity array index for partial water vapor pressure.
char prof_basename[LEN]
Basename for profile output file.
double grid_z1
Upper altitude of gridded data [km].
int direction
Direction flag (1=forward calculation, -1=backward calculation).
char balloon[LEN]
Balloon position filename.
int qnt_Cccl4
Quantity array index for CFC-10 volume mixing ratio (chemistry code).
int met_dp
Stride for pressure levels.
double met_dt_out
Time step for sampling of meteo data along trajectories [s].
int qnt_h2o2
Quantity array index for H2O2 volume mixing ratio (climatology).
int qnt_vh
Quantity array index for horizontal wind.
char species[LEN]
Species.
int csi_nx
Number of longitudes of gridded CSI data.
double csi_lat0
Lower latitude of gridded CSI data [deg].
double turb_dz_trop
Vertical turbulent diffusion coefficient (troposphere) [m^2/s].
int met_pbl
Planetary boundary layer data (0=file, 1=z2p, 2=Richardson, 3=theta).
double met_comp_tol[METVAR]
Compression tolerance for SZ3 or ZFP.
int qnt_lwc
Quantity array index for cloud liquid water content.
double turb_mesoz
Vertical scaling factor for mesoscale wind fluctuations.
int grid_nc_level
zlib compression level of netCDF grid data files (0=off).
int grid_nx
Number of longitudes of gridded data.
int atm_type
Type of atmospheric data files (0=ASCII, 1=binary, 2=netCDF, 3=CLaMS_traj, 4=CLaMS_pos).
double bound_mass
Boundary conditions mass per particle [kg].
double grid_lat0
Lower latitude of gridded data [deg].
int qnt_ts
Quantity array index for surface temperature.
int qnt_loss_rate
Quantity array index for total loss rate.
double met_cms_eps_h2o
cmultiscale compression epsilon for water vapor.
int qnt_plfc
Quantity array index for pressure at level of free convection (LCF).
int qnt_Acs137
Quantity array index for radioactive activity of Cs-137.
double grid_lon0
Lower longitude of gridded data [deg].
int qnt_o1d
Quantity array index for O(1D) volume mixing ratio (climatology).
int met_tropo_spline
Tropopause interpolation method (0=linear, 1=spline).
char sample_kernel[LEN]
Kernel data file for sample output.
int qnt_tvirt
Quantity array index for virtual temperature.
double dt_met
Time step of meteo data [s].
char clim_ho2_filename[LEN]
Filename of HO2 climatology.
double chemgrid_lat1
Upper latitude of chemistry grid [deg].
int met_geopot_sy
Latitudinal smoothing of geopotential heights.
char grid_gpfile[LEN]
Gnuplot file for gridded data.
double met_cms_eps_u
cmultiscale compression epsilon for zonal wind.
double turb_dx_strat
Horizontal turbulent diffusion coefficient (stratosphere) [m^2/s].
int qnt_vmr
Quantity array index for volume mixing ratio.
int qnt_lsm
Quantity array index for land-sea mask.
int qnt_theta
Quantity array index for potential temperature.
double bound_lat1
Boundary conditions maximum longitude [deg].
double stat_t1
Stop time for station output [s].
char csi_kernel[LEN]
Kernel data file for CSI output.
double turb_dx_trop
Horizontal turbulent diffusion coefficient (troposphere) [m^2/s].
int grid_type
Type of grid data files (0=ASCII, 1=netCDF).
double csi_lon0
Lower longitude of gridded CSI data [deg].
int qnt_pbl
Quantity array index for boundary layer pressure.
double oh_chem[4]
Coefficients for OH reaction rate (A, E/R or k0, n, kinf, m).
int grid_stddev
Include standard deviations in grid output (0=no, 1=yes).
int qnt_psice
Quantity array index for saturation pressure over ice.
double chemgrid_lon0
Lower longitude of chemistry grid [deg].
int bound_pbl
Boundary conditions planetary boundary layer (0=no, 1=yes).
int qnt_mloss_wet
Quantity array index for total mass loss due to wet deposition.
int radio_decay
Switch for radioactive decay module (0=off, 1=on).
int met_geopot_sx
Longitudinal smoothing of geopotential heights.
int met_sy
Smoothing for latitudes.
int qnt_ps
Quantity array index for surface pressure.
int rng_type
Random number generator (0=GSL, 1=Squares, 2=cuRAND).
char prof_obsfile[LEN]
Observation data file for profile output.
int isosurf
Isosurface parameter (0=none, 1=pressure, 2=density, 3=theta, 4=balloon).
double bound_p1
Boundary conditions top pressure [hPa].
int qnt_zs
Quantity array index for surface geopotential height.
int prof_nz
Number of altitudes of gridded profile data.
double csi_dt_out
Time step for CSI output [s].
int met_cape
Convective available potential energy data (0=file, 1=calculate).
double csi_modmin
Minimum column density to trigger detection [kg/m^2].
int met_sx
Smoothing for longitudes.
double chemgrid_lon1
Upper longitude of chemistry grid [deg].
double turb_mesox
Horizontal scaling factor for mesoscale wind fluctuations.
double met_cms_eps_iwc
cmultiscale compression epsilon for cloud ice water content.
double met_cms_eps_swc
cmultiscale compression epsilon for cloud snow water content.
char grid_kernel[LEN]
Kernel data file for grid output.
double met_cms_eps_v
cmultiscale compression epsilon for meridional wind.
double prof_z0
Lower altitude of gridded profile data [km].
int qnt_w
Quantity array index for vertical velocity.
double bound_vmr
Boundary conditions volume mixing ratio [ppv].
double met_tropo_pv
Dynamical tropopause potential vorticity threshold [PVU].
int prof_nx
Number of longitudes of gridded profile data.
int qnt_stat
Quantity array index for station flag.
int met_tropo
Tropopause definition (0=none, 1=clim, 2=cold point, 3=WMO_1st, 4=WMO_2nd, 5=dynamical).
int qnt_rp
Quantity array index for particle radius.
int met_mpi_share
Use MPI to share meteo (0=no, 1=yes).
double mixing_strat
Interparcel exchange parameter for mixing in the stratosphere.
int qnt_vz
Quantity array index for vertical velocity.
int qnt_ho2
Quantity array index for HO2 volume mixing ratio (climatology).
double csi_z1
Upper altitude of gridded CSI data [km].
double stat_t0
Start time for station output [s].
double oh_chem_beta
Beta parameter for diurnal variablity of OH.
int dd
Domain decomposition (0=no, 1=yes, with 2x2 if not specified).
char clim_o1d_filename[LEN]
Filename of O(1D) climatology.
int qnt_eta
Quantity array index for eta vertical coordinate.
char clim_photo[LEN]
Filename of photolysis rates climatology.
double wet_depo_so2_ph
pH value used to calculate effective Henry constant of SO2.
double mixing_z0
Lower altitude of mixing grid [km].
int qnt_mloss_decay
Quantity array index for total mass loss due to exponential decay.
int atm_type_out
Type of atmospheric data files for output (-1=same as ATM_TYPE, 0=ASCII, 1=binary,...
int met_cms_nd0x
cmultiscale number of cells of coarsest grid in x-direction.
int met_nlev
Number of meteo data model levels.
double dt_kpp
Time step for KPP chemistry [s].
char csi_basename[LEN]
Basename of CSI data files.
double dry_depo_dp
Dry deposition surface layer [hPa].
int qnt_shf
Quantity array index for surface sensible heat flux.
int qnt_vs
Quantity array index for surface meridional wind.
int qnt_Cco
Quantity array index for CO volume mixing ratio (chemistry code).
double vtk_dt_out
Time step for VTK data output [s].
double t_stop
Stop time of simulation [s].
double conv_dt
Time interval for convection module [s].
char sample_obsfile[LEN]
Observation data file for sample output.
int qnt_hno3
Quantity array index for HNO3 volume mixing ratio (climatology).
char grid_basename[LEN]
Basename of grid data files.
int met_clams
Read MPTRAC or CLaMS meteo data (0=MPTRAC, 1=CLaMS).
int met_comp_prec[METVAR]
Compression precision for SZ3 or ZFP.
int qnt_h2ot
Quantity array index for tropopause water vapor volume mixing ratio.
int qnt_rh
Quantity array index for relative humidity over water.
double met_cms_eps_cc
cmultiscale compression epsilon for cloud cover.
double bound_lat0
Boundary conditions minimum longitude [deg].
double met_pbl_max
Maximum depth of planetary boundary layer [km].
int met_dx
Stride for longitudes.
int qnt_destination
Quantity array index for destination subdomain in domain decomposition.
int mixing_ny
Number of latitudes of mixing grid.
int met_convention
Meteo data layout (0=[lev, lat, lon], 1=[lon, lat, lev]).
int qnt_zeta_d
Quantity array index for diagnosed zeta vertical coordinate.
char clim_h2o2_filename[LEN]
Filename of H2O2 climatology.
int tracer_chem
Switch for first order tracer chemistry module (0=off, 1=on).
double dt_mod
Time step of simulation [s].
int diffusion
Diffusion scheme (0=off, 1=fixed-K, 2=PBL).
int qnt_tnat
Quantity array index for T_NAT.
int qnt_eta_dot
Quantity array index for velocity of eta vertical coordinate.
int qnt_tice
Quantity array index for T_ice.
int qnt_zg
Quantity array index for geopotential height.
double vtk_offset
Vertical offset for VTK data [km].
int qnt_v
Quantity array index for meridional wind.
int qnt_mloss_dry
Quantity array index for total mass loss due to dry deposition.
double bound_vmr_trend
Boundary conditions volume mixing ratio trend [ppv/s].
int met_cache
Preload meteo data into disk cache (0=no, 1=yes).
int qnt_oh
Quantity array index for OH volume mixing ratio (climatology).
char qnt_unit[NQ][LEN]
Quantity units.
int qnt_Ch
Quantity array index for H volume mixing ratio (chemistry code).
int met_press_level_def
Use predefined pressure levels or not.
int oh_chem_reaction
Reaction type for OH chemistry (0=none, 2=bimolecular, 3=termolecular).
int qnt_h2o
Quantity array index for water vapor volume mixing ratio.
int prof_ny
Number of latitudes of gridded profile data.
int qnt_rhice
Quantity array index for relative humidity over ice.
int qnt_rho
Quantity array index for density of air.
double sample_dz
Layer depth for sample output [km].
double tdec_strat
Life time of particles in the stratosphere [s].
int obs_type
Type of observation data files (0=ASCII, 1=netCDF).
int grid_nc_quant[NQ]
Number of digits for quantization of netCDF grid data files (0=off).
double met_cms_eps_lwc
cmultiscale compression epsilon for cloud liquid water content.
int qnt_us
Quantity array index for surface zonal wind.
double met_cms_eps_z
cmultiscale compression epsilon for geopotential height.
double grid_lon1
Upper longitude of gridded data [deg].
int qnt_Cn2o
Quantity array index for N2O volume mixing ratio (chemistry code).
int qnt_Cccl3f
Quantity array index for CFC-11 volume mixing ratio (chemistry code).
char qnt_name[NQ][LEN]
Quantity names.
char atm_basename[LEN]
Basename of atmospheric data files.
double mixing_lat0
Lower latitude of mixing grid [deg].
int nens
Number of ensembles.
int qnt_pt
Quantity array index for tropopause pressure.
int qnt_cl
Quantity array index for total column cloud water.
int advect
Advection scheme (0=off, 1=Euler, 2=midpoint, 4=Runge-Kutta).
double prof_z1
Upper altitude of gridded profile data [km].
double met_lev_hyam[EP]
Meteo data model level a coefficients.
int qnt_t
Quantity array index for temperature.
int atm_filter
Time filter for atmospheric data output (0=none, 1=missval, 2=remove).
int kpp_chem
Switch for KPP chemistry module (0=off, 1=on).
int qnt_zeta
Quantity array index for zeta vertical coordinate.
double conv_pbl_trans
Depth of PBL transition layer (fraction of PBL depth).
char ens_basename[LEN]
Basename of ensemble data file.
int qnt_Ai131
Quantity array index for radioactive activity of I-131.
double wet_depo_pre[2]
Coefficients for precipitation calculation.
int met_vert_coord
Vertical coordinate of input meteo data (0=plev, 1=mlev_p_file, 2=mlev_ab_file, 3=mlev_ab_full,...
double csi_z0
Lower altitude of gridded CSI data [km].
int qnt_lapse
Quantity array index for lapse rate.
int qnt_Apb210
Quantity array index for radioactive activity of Pb-210.
double stat_lat
Latitude of station [deg].
int qnt_Cho2
Quantity array index for HO2 volume mixing ratio (chemistry code).
double wet_depo_bc_h[2]
Coefficients for wet deposition below cloud (Henry's law: Hb, Cb).
int grid_ny
Number of latitudes of gridded data.
int qnt_Csf6
Quantity array index for SF6 volume mixing ratio (chemistry code).
int qnt_Ch2o
Quantity array index for H2O volume mixing ratio (chemistry code).
double met_detrend
FWHM of horizontal Gaussian used for detrending [km].
int conv_mix_pbl
Vertical mixing in the PBL (0=off, 1=on).
char metbase[LEN]
Basename for meteo data.
double bound_dps
Boundary conditions surface layer depth [hPa].
double met_cms_eps_t
cmultiscale compression epsilon for temperature.
int chemgrid_nz
Number of altitudes of chemistry grid.
int qnt_cape
Quantity array index for convective available potential energy (CAPE).
int qnt_zeta_dot
Quantity array index for velocity of zeta vertical coordinate.
double bound_mass_trend
Boundary conditions mass per particle trend [kg/s].
int met_cms_nd0y
cmultiscale number of cells of coarsest grid in y-direction.
int mixing_nz
Number of altitudes of mixing grid.
int qnt_o3c
Quantity array index for total column ozone.
double bound_p0
Boundary conditions bottom pressure [hPa].
double mixing_lon0
Lower longitude of mixing grid [deg].
char clim_ccl4_timeseries[LEN]
Filename of CFC-10 time series.
int qnt_Co3
Quantity array index for O3 volume mixing ratio (chemistry code).
int qnt_tsts
Quantity array index for T_STS.
int grid_nz
Number of altitudes of gridded data.
char clim_oh_filename[LEN]
Filename of OH climatology.
int qnt_nss
Quantity array index for northward turbulent surface stress.
double ens_dt_out
Time step for ensemble output [s].
char sample_basename[LEN]
Basename of sample data file.
int atm_stride
Particle index stride for atmospheric data files.
int met_relhum
Try to read relative humidity (0=no, 1=yes).
double mixing_lat1
Upper latitude of mixing grid [deg].
double atm_dt_out
Time step for atmospheric data output [s].
char clim_sf6_timeseries[LEN]
Filename of SF6 time series.
double prof_lat1
Upper latitude of gridded profile data [deg].
int met_cms_batch
cmultiscale batch size.
double psc_h2o
H2O volume mixing ratio for PSC analysis.
int met_sp
Smoothing for pressure levels.
double prof_lon0
Lower longitude of gridded profile data [deg].
int qnt_Axe133
Quantity array index for radioactive activity of Xe-133.
int chemgrid_nx
Number of longitudes of chemistry grid.
int qnt_pct
Quantity array index for cloud top pressure.
int qnt_mloss_kpp
Quantity array index for total mass loss due to KPP chemistry.
int qnt_psat
Quantity array index for saturation pressure over water.
int qnt_subdomain
Quantity array index for current subdomain in domain decomposition.
double met_lev_hybm[EP]
Meteo data model level b coefficients.
double prof_lat0
Lower latitude of gridded profile data [deg].
int qnt_cin
Quantity array index for convective inhibition (CIN).
double psc_hno3
HNO3 volume mixing ratio for PSC analysis.
double prof_lon1
Upper longitude of gridded profile data [deg].
double met_cms_eps_rwc
cmultiscale compression epsilon for cloud rain water content.
int met_nc_quant
Number of digits for quantization of netCDF meteo files (0=off).
int h2o2_chem_reaction
Reaction type for H2O2 chemistry (0=none, 1=SO2).
int qnt_Co3p
Quantity array index for O(3P) volume mixing ratio (chemistry code).
int atm_nc_quant[NQ]
Number of digits for quantization of netCDF atmospheric data files (0=off).
double wet_depo_bc_ret_ratio
Coefficients for wet deposition below cloud: retention ratio.
int chemgrid_ny
Number of latitudes of chemistry grid.
int qnt_Abe7
Quantity array index for radioactive activity of Be-7.
char clim_ccl3f_timeseries[LEN]
Filename of CFC-11 time series.
double met_cms_eps_o3
cmultiscale compression epsilon for ozone.
int met_cms_zstd
cmultiscale ZSTD compression (0=off, 1=on).
int met_cms_maxlev
cmultiscale maximum refinement level.
int grid_sparse
Sparse output in grid data files (0=no, 1=yes).
char vtk_basename[LEN]
Basename of VTK data files.
double dry_depo_vdep
Dry deposition velocity [m/s].
int qnt_tt
Quantity array index for tropopause temperature.
int met_np
Number of target pressure levels.
int qnt_ens
Quantity array index for ensemble IDs.
int met_nc_level
zlib compression level of netCDF meteo files (0=off).
double mixing_dt
Time interval for mixing [s].
int qnt_Arn222
Quantity array index for radioactive activity of Rn-222.
int qnt_mloss_h2o2
Quantity array index for total mass loss due to H2O2 chemistry.
double vtk_scale
Vertical scaling factor for VTK data.
char clim_ccl2f2_timeseries[LEN]
Filename of CFC-12 time series.
double met_cms_eps_w
cmultiscale compression epsilon for vertical velocity.
double wet_depo_ic_h[2]
Coefficients for wet deposition in cloud (Henry's law: Hb, Cb).
double turb_dx_pbl
Horizontal turbulent diffusion coefficient (PBL) [m^2/s].
double conv_cin
CIN threshold for convection module [J/kg].
int qnt_pv
Quantity array index for potential vorticity.
int advect_vert_coord
Vertical velocity of air parcels (0=omega_on_plev, 1=zetadot_on_mlev, 2=omega_on_mlev,...
int qnt_mloss_oh
Quantity array index for total mass loss due to OH chemistry.
int qnt_Ch2o2
Quantity array index for H2O2 volume mixing ratio (chemistry code).
int qnt_sst
Quantity array index for sea surface temperature.
double mixing_lon1
Upper longitude of mixing grid [deg].
int atm_nc_level
zlib compression level of netCDF atmospheric data files (0=off).
char clim_hno3_filename[LEN]
Filename of HNO3 climatology.
double wet_depo_ic_ret_ratio
Coefficients for wet deposition in cloud: retention ratio.
int qnt_sh
Quantity array index for specific humidity.
int qnt_ess
Quantity array index for eastward turbulent surface stress.
double wet_depo_ic_b
Coefficient B for wet deposition in cloud (exponential form).
double wet_depo_bc_b
Coefficient B for wet deposition below cloud (exponential form).
int met_dy
Stride for latitudes.
int qnt_Cx
Quantity array index for trace species x volume mixing ratio (chemistry code).
double turb_dz_strat
Vertical turbulent diffusion coefficient (stratosphere) [m^2/s].
double bound_zetas
Boundary conditions surface layer zeta [K].
int dd_subdomains_zonal
Domain decomposition zonal subdomain number.
int qnt_idx
Quantity array index for air parcel IDs.
double met_tropo_theta
Dynamical tropopause potential temperature threshold [K].
int qnt_rwc
Quantity array index for cloud rain water content.
double t_start
Start time of simulation [s].
char qnt_longname[NQ][LEN]
Quantity long names.
double met_p[EP]
Target pressure levels [hPa].
int nq
Number of quantities.
double tdec_trop
Life time of particles in the troposphere [s].
double sample_dx
Horizontal radius for sample output [km].
int vtk_stride
Particle index stride for VTK data.
char stat_basename[LEN]
Basename of station data file.
double turb_dz_pbl
Vertical turbulent diffusion coefficient (PBL) [m^2/s].
double grid_lat1
Upper latitude of gridded data [deg].
int dd_subdomains_meridional
Domain decomposition meridional subdomain number.
int qnt_zt
Quantity array index for tropopause geopotential height.
int met_type
Type of meteo data files (0=netCDF, 1=binary, 2=pck, 3=ZFP, 4=ZSTD, 5=cms, 6=grib,...
int qnt_cc
Quantity array index for cloud cover.
int qnt_plcl
Quantity array index for pressure at lifted condensation level (LCL).
double grid_dt_out
Time step for gridded data output [s].
int qnt_tdew
Quantity array index for dew point temperature.
Domain decomposition data structure.
size_t halo_bnd_count[4]
Extent of the periodic boundary halo hyperslab.
int halo_offset_end
Offset of the periodic halo block at the end of the local x-array.
int nx_glob
Number of global longitudes.
size_t halo_bnd_start[4]
Start indices of the periodic boundary halo hyperslab.
double lon_glob[DD_EX_GLOB]
Longitudes of the global grid [deg].
double lat_glob[DD_EY_GLOB]
Latitudes of the global grid [deg].
int halo_offset_start
Offset of the periodic halo block at the beginning of the local x-array.
size_t subdomain_count[4]
Extent of the local subdomain hyperslab (including inner halos).
int ny_glob
Number of global latitudes.
size_t subdomain_start[4]
Start indices of the local subdomain hyperslab (including inner halos).
float zt[EX][EY]
Tropopause geopotential height [km].
float sst[EX][EY]
Sea surface temperature [K].
float rwc[EX][EY][EP]
Cloud rain water content [kg/kg].
float o3c[EX][EY]
Total column ozone [DU].
float zeta_dotl[EX][EY][EP]
Vertical velocity on model levels [K/s].
float h2o[EX][EY][EP]
Water vapor volume mixing ratio [1].
float cape[EX][EY]
Convective available potential energy [J/kg].
float w[EX][EY][EP]
Vertical velocity [hPa/s].
float pct[EX][EY]
Cloud top pressure [hPa].
double hybrid[EP]
Model hybrid levels.
int nx
Number of longitudes.
int ny
Number of latitudes.
float shf[EX][EY]
Surface sensible heat flux [W/m^2].
float ps[EX][EY]
Surface pressure [hPa].
float lwc[EX][EY][EP]
Cloud liquid water content [kg/kg].
float us[EX][EY]
Surface zonal wind [m/s].
float wl[EX][EY][EP]
Vertical velocity on model levels [hPa/s].
float vl[EX][EY][EP]
Meridional wind on model levels [m/s].
float zs[EX][EY]
Surface geopotential height [km].
float o3[EX][EY][EP]
Ozone volume mixing ratio [1].
float cc[EX][EY][EP]
Cloud cover [1].
int np
Number of pressure levels.
float t[EX][EY][EP]
Temperature [K].
float ts[EX][EY]
Surface temperature [K].
float u[EX][EY][EP]
Zonal wind [m/s].
float ess[EX][EY]
Eastward turbulent surface stress [N/m^2].
float ul[EX][EY][EP]
Zonal wind on model levels [m/s].
float pcb[EX][EY]
Cloud bottom pressure [hPa].
float pel[EX][EY]
Pressure at equilibrium level (EL) [hPa].
float cin[EX][EY]
Convective inhibition [J/kg].
float plcl[EX][EY]
Pressure at lifted condensation level (LCL) [hPa].
double lon[EX]
Longitudes [deg].
float pt[EX][EY]
Tropopause pressure [hPa].
float tt[EX][EY]
Tropopause temperature [K].
float pbl[EX][EY]
Boundary layer pressure [hPa].
float vs[EX][EY]
Surface meridional wind [m/s].
float z[EX][EY][EP]
Geopotential height [km].
float v[EX][EY][EP]
Meridional wind [m/s].
int npl
Number of model levels.
float lsm[EX][EY]
Land-sea mask [1].
float iwc[EX][EY][EP]
Cloud ice water content [kg/kg].
float h2ot[EX][EY]
Tropopause water vapor volume mixing ratio [ppv].
float pv[EX][EY][EP]
Potential vorticity [PVU].
double eta[EP]
Model level eta values.
float cl[EX][EY]
Total column cloud water [kg/m^2].
float nss[EX][EY]
Northward turbulent surface stress [N/m^2].
float pl[EX][EY][EP]
Pressure on model levels [hPa].
float plfc[EX][EY]
Pressure at level of free convection (LFC) [hPa].
double hyam[EP]
Model level a coefficients [Pa].
double lat[EY]
Latitudes [deg].
float swc[EX][EY][EP]
Cloud snow water content [kg/kg].
double hybm[EP]
Model level b coefficients.
float zetal[EX][EY][EP]
Zeta on model levels [K].
double p[EP]
Pressure levels [hPa].
double lat
Latitude [deg].
double lon
Longitude [deg].
double q[NQ]
Quantity data (for various, user-defined attributes).