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 =
NORM(x);
82 *lat =
RAD2DEG(asin(x[2] / radius));
83 *lon =
RAD2DEG(atan2(x[1], x[0]));
98 const double sza_thresh =
DEG2RAD(85.), cos_sza_thresh = cos(sza_thresh);
101 const double oh =
clim_zm(&clim->
oh, t, lat, p);
106 if (sza <= sza_thresh)
121 const double sza_thresh =
DEG2RAD(85.), cos_sza_thresh = cos(sza_thresh);
124 for (
int it = 0; it < clim->
oh.
ntime; it++)
125 for (
int iz = 0; iz < clim->
oh.
np; iz++)
126 for (
int iy = 0; iy < clim->
oh.
nlat; iy++) {
133 for (
double lon = -180; lon < 180; lon += 1.0) {
135 if (sza <= sza_thresh)
143 clim->
oh.
vmr[it][iz][iy] /= (sum / (double) n);
158 if (p < photo->p[photo->
np - 1])
159 p_help = photo->
p[photo->
np - 1];
160 else if (p > photo->
p[0])
161 p_help = photo->
p[0];
164 double sza_help = sza;
165 if (sza < photo->sza[0])
166 sza_help = photo->
sza[0];
167 else if (sza > photo->
sza[photo->
nsza - 1])
168 sza_help = photo->
sza[photo->
nsza - 1];
171 double o3c_help = o3c;
172 if (o3c < photo->o3c[0])
173 o3c_help = photo->
o3c[0];
174 else if (o3c > photo->
o3c[photo->
no3c - 1])
175 o3c_help = photo->
o3c[photo->
no3c - 1];
183 double aux00 =
LIN(photo->
p[ip], rate[ip][isza][io3c],
184 photo->
p[ip + 1], rate[ip + 1][isza][io3c], p_help);
185 double aux01 =
LIN(photo->
p[ip], rate[ip][isza][io3c + 1],
186 photo->
p[ip + 1], rate[ip + 1][isza][io3c + 1], p_help);
187 double aux10 =
LIN(photo->
p[ip], rate[ip][isza + 1][io3c],
188 photo->
p[ip + 1], rate[ip + 1][isza + 1][io3c], p_help);
189 double aux11 =
LIN(photo->
p[ip], rate[ip][isza + 1][io3c + 1],
190 photo->
p[ip + 1], rate[ip + 1][isza + 1][io3c + 1],
192 aux00 =
LIN(photo->
o3c[io3c], aux00, photo->
o3c[io3c + 1], aux01, o3c_help);
193 aux11 =
LIN(photo->
o3c[io3c], aux10, photo->
o3c[io3c + 1], aux11, o3c_help);
194 aux00 =
LIN(photo->
sza[isza], aux00, photo->
sza[isza + 1], aux11, sza_help);
195 return MAX(aux00, 0.0);
206 double sec =
FMOD(t, 365.25 * 86400.);
208 sec += 365.25 * 86400.;
216 clim->
tropo[isec][ilat],
218 clim->
tropo[isec][ilat + 1], lat);
220 clim->
tropo[isec + 1][ilat],
222 clim->
tropo[isec + 1][ilat + 1], lat);
232 LOG(1,
"Initialize tropopause data...");
236 double tropo_time[12] = {
237 1209600.00, 3888000.00, 6393600.00,
238 9072000.00, 11664000.00, 14342400.00,
239 16934400.00, 19612800.00, 22291200.00,
240 24883200.00, 27561600.00, 30153600.00
246 double tropo_lat[73] = {
247 -90, -87.5, -85, -82.5, -80, -77.5, -75, -72.5, -70, -67.5,
248 -65, -62.5, -60, -57.5, -55, -52.5, -50, -47.5, -45, -42.5,
249 -40, -37.5, -35, -32.5, -30, -27.5, -25, -22.5, -20, -17.5,
250 -15, -12.5, -10, -7.5, -5, -2.5, 0, 2.5, 5, 7.5, 10, 12.5,
251 15, 17.5, 20, 22.5, 25, 27.5, 30, 32.5, 35, 37.5, 40, 42.5,
252 45, 47.5, 50, 52.5, 55, 57.5, 60, 62.5, 65, 67.5, 70, 72.5,
253 75, 77.5, 80, 82.5, 85, 87.5, 90
258 double tropo[12][73] = {
259 {324.1, 325.6, 325, 324.3, 322.5, 319.7, 314, 307.2, 301.8, 299.6,
260 297.1, 292.2, 285.6, 276.1, 264, 248.9, 231.9, 213.5, 194.4,
261 175.3, 157, 140.4, 126.7, 116.3, 109.5, 105.4, 103, 101.4, 100.4,
262 99.69, 99.19, 98.84, 98.56, 98.39, 98.39, 98.42, 98.44, 98.54,
263 98.68, 98.81, 98.89, 98.96, 99.12, 99.65, 101.4, 105.4, 113.5, 128,
264 152.1, 184.7, 214, 234.1, 247.3, 255.8, 262.6, 267.7, 271.7, 275,
265 277.2, 279, 280.1, 280.4, 280.6, 280.1, 279.3, 278.3, 276.8, 275.8,
266 275.3, 275.6, 275.4, 274.1, 273.5},
267 {337.3, 338.7, 337.8, 336.4, 333, 328.8, 321.1, 312.6, 306.6, 303.7,
268 300.2, 293.8, 285.4, 273.8, 259.6, 242.7, 224.4, 205.2, 186, 167.5,
269 150.3, 135, 122.8, 113.9, 108.2, 104.7, 102.5, 101.1, 100.2, 99.42,
270 98.88, 98.52, 98.25, 98.09, 98.07, 98.1, 98.12, 98.2, 98.25, 98.27,
271 98.26, 98.27, 98.36, 98.79, 100.2, 104.2, 113.7, 131.2, 159.5, 193,
272 220.4, 238.1, 250.2, 258.1, 264.7, 269.7, 273.7, 277.3, 280.2, 282.8,
273 284.9, 286.5, 288.1, 288.8, 289, 288.5, 287.2, 286.3, 286.1, 287.2,
274 287.5, 286.2, 285.8},
275 {335, 336, 335.7, 335.1, 332.3, 328.1, 320.6, 311.8, 305.1, 301.9,
276 297.6, 290, 280.4, 268.3, 254.6, 239.6, 223.9, 207.9, 192.2, 176.9,
277 161.7, 146.4, 132.2, 120.6, 112.3, 107.2, 104.3, 102.4, 101.3,
278 100.4, 99.86, 99.47, 99.16, 98.97, 98.94, 98.97, 99, 99.09, 99.2,
279 99.31, 99.35, 99.41, 99.51, 99.86, 101.1, 104.9, 114.3, 131, 156.8,
280 186.3, 209.3, 224.6, 236.8, 246.3, 254.9, 262.3, 268.8, 274.8,
281 279.9, 284.6, 288.6, 291.6, 294.9, 297.5, 299.8, 301.8, 303.1,
282 304.3, 304.9, 306, 306.6, 306.2, 306},
283 {306.2, 306.7, 305.7, 307.1, 307.3, 306.4, 301.8, 296.2, 292.4,
284 290.3, 287.1, 280.9, 273.4, 264.3, 254.1, 242.8, 231, 219, 207.2,
285 195.5, 183.3, 169.7, 154.7, 138.7, 124.1, 113.6, 107.8, 104.7,
286 102.8, 101.7, 100.9, 100.4, 100, 99.79, 99.7, 99.66, 99.68, 99.79,
287 99.94, 100.2, 100.5, 100.9, 101.4, 102.1, 103.4, 107, 115.2, 129.1,
288 148.7, 171, 190.8, 205.6, 218.4, 229.4, 239.6, 248.6, 256.5,
289 263.7, 270.3, 276.6, 282.6, 288.1, 294.5, 300.4, 306.3, 311.4,
290 315.1, 318.3, 320.3, 322.2, 322.8, 321.5, 321.1},
291 {266.5, 264.9, 260.8, 261, 262, 263, 261.3, 259.7, 259.2, 259.8,
292 260.1, 258.6, 256.7, 253.6, 249.5, 243.9, 237.4, 230, 222.1, 213.9,
293 205, 194.4, 180.4, 161.8, 140.7, 122.9, 112.1, 106.7, 104.1, 102.7,
294 101.8, 101.4, 101.1, 101, 101, 101, 101.1, 101.2, 101.5, 101.9,
295 102.4, 103, 103.8, 104.9, 106.8, 110.1, 115.6, 124, 135.2, 148.9,
296 165.2, 181.3, 198, 211.8, 223.5, 233.8, 242.9, 251.5, 259, 266.2,
297 273.1, 279.2, 286.2, 292.8, 299.6, 306, 311.1, 315.5, 318.8, 322.6,
298 325.3, 325.8, 325.8},
299 {220.1, 218.1, 210.8, 207.2, 207.6, 210.5, 211.4, 213.5, 217.3,
300 222.4, 227.9, 232.8, 237.4, 240.8, 242.8, 243, 241.5, 238.6, 234.2,
301 228.5, 221, 210.7, 195.1, 172.9, 147.8, 127.6, 115.6, 109.9, 107.1,
302 105.7, 105, 104.8, 104.8, 104.9, 105, 105.1, 105.3, 105.5, 105.8,
303 106.4, 107, 107.6, 108.1, 108.8, 110, 111.8, 114.2, 117.4, 121.6,
304 127.9, 137.3, 151.2, 169.5, 189, 205.8, 218.9, 229.1, 237.8, 245,
305 251.5, 257.1, 262.3, 268.2, 274, 280.4, 286.7, 292.4, 297.9, 302.9,
306 308.5, 312.2, 313.1, 313.3},
307 {187.4, 184.5, 173.3, 166.1, 165.4, 167.8, 169.6, 173.6, 179.6,
308 187.9, 198.9, 210, 220.5, 229.2, 235.7, 239.9, 241.8, 241.6, 239.6,
309 235.8, 229.4, 218.6, 200.9, 175.9, 149.4, 129.4, 118.3, 113.1,
310 110.8, 109.7, 109.3, 109.4, 109.7, 110, 110.2, 110.4, 110.5, 110.7,
311 111, 111.4, 111.8, 112.1, 112.3, 112.7, 113.2, 113.9, 115, 116.4,
312 117.9, 120.4, 124.1, 130.9, 142.2, 159.6, 179.6, 198.5, 212.9,
313 224.2, 232.7, 239.1, 243.8, 247.7, 252.4, 257.3, 263.2, 269.5,
314 275.4, 281.1, 286.3, 292, 296.3, 298.2, 298.8},
315 {166, 166.4, 155.7, 148.3, 147.1, 149, 152.1, 157, 163.6, 172.4,
316 185.3, 199.2, 212.6, 224, 233.2, 239.6, 243.3, 244.6, 243.6, 240.3,
317 233.9, 222.6, 203.7, 177, 149.5, 129.7, 119, 114, 111.7, 110.7,
318 110.3, 110.3, 110.6, 110.9, 111.1, 111.3, 111.5, 111.6, 111.9,
319 112.2, 112.5, 112.6, 112.8, 113, 113.4, 114, 115.1, 116.5, 118.3,
320 120.9, 124.4, 130.2, 139.4, 154.6, 173.8, 193.1, 208.1, 220.4,
321 230.1, 238.2, 244.7, 249.5, 254.5, 259.3, 264.5, 269.4, 273.7,
322 278.2, 282.6, 287.4, 290.9, 292.5, 293},
323 {171.9, 172.8, 166.2, 162.3, 161.4, 162.5, 165.2, 169.6, 175.3,
324 183.1, 193.8, 205.9, 218.3, 229.6, 238.5, 244.3, 246.9, 246.7,
325 243.8, 238.4, 230.2, 217.9, 199.6, 174.9, 148.9, 129.8, 119.5,
326 114.8, 112.3, 110.9, 110.3, 110.1, 110.2, 110.3, 110.4, 110.5,
327 110.6, 110.8, 111, 111.4, 111.8, 112, 112.2, 112.4, 112.9, 113.6,
328 114.7, 116.3, 118.4, 121.9, 127.1, 136.1, 149.8, 168.4, 186.9,
329 203.3, 217, 229.1, 238.7, 247, 254, 259.3, 264.3, 268.3, 272.5,
330 276.6, 280.4, 284.4, 288.4, 293.3, 297.2, 298.7, 299.1},
331 {191.6, 192.2, 189, 188.1, 190.2, 193.7, 197.8, 202.9, 208.5,
332 215.6, 224.2, 233.1, 241.2, 247.3, 250.8, 251.3, 248.9, 244.2,
333 237.3, 228.4, 217.2, 202.9, 184.5, 162.5, 140.7, 124.8, 116.2,
334 111.8, 109.4, 107.9, 107, 106.7, 106.6, 106.6, 106.7, 106.7,
335 106.8, 107, 107.4, 108, 108.7, 109.3, 109.8, 110.4, 111.2,
336 112.4, 114.2, 116.9, 121.1, 127.9, 139.3, 155.2, 173.6, 190.7,
337 206.1, 220.1, 232.3, 243, 251.8, 259.2, 265.7, 270.6, 275.3,
338 279.3, 283.3, 286.9, 289.7, 292.8, 296.1, 300.5, 303.9, 304.8,
340 {241.5, 239.6, 236.8, 237.4, 239.4, 242.3, 244.2, 246.4, 249.2,
341 253.6, 258.6, 262.7, 264.8, 264.2, 260.6, 254.1, 245.5, 235.3,
342 223.9, 211.7, 198.3, 183.1, 165.6, 147.1, 130.5, 118.7, 111.9,
343 108.1, 105.8, 104.3, 103.4, 102.8, 102.5, 102.4, 102.5, 102.5,
344 102.5, 102.7, 103.1, 103.8, 104.6, 105.4, 106.1, 107, 108.2,
345 109.9, 112.8, 117.5, 126, 140.4, 161, 181.9, 201.2, 216.8, 230.4,
346 241.8, 251.4, 259.9, 266.9, 272.8, 277.4, 280.4, 282.9, 284.6,
347 286.1, 287.4, 288.3, 289.5, 290.9, 294.2, 296.9, 297.5, 297.6},
348 {301.2, 300.3, 296.6, 295.4, 295, 294.3, 291.2, 287.4, 284.9, 284.7,
349 284.1, 281.5, 277.1, 270.4, 261.7, 250.6, 237.6, 223.1, 207.9, 192,
350 175.8, 158.8, 142.1, 127.6, 116.8, 109.9, 106, 103.6, 102.1, 101.1,
351 100.4, 99.96, 99.6, 99.37, 99.32, 99.32, 99.31, 99.46, 99.77, 100.2,
352 100.7, 101.3, 101.8, 102.7, 104.1, 106.8, 111.9, 121, 136.7, 160,
353 186.9, 209.9, 228.1, 241.2, 251.5, 259.5, 265.7, 270.9, 274.8, 278,
354 280.3, 281.8, 283, 283.3, 283.7, 283.8, 283, 282.2, 281.2, 281.4,
357 memcpy(clim->
tropo, tropo,
sizeof(clim->
tropo));
360 double tropomin = 1e99, tropomax = -1e99;
362 for (
int iy = 0; iy < clim->
tropo_nlat; iy++) {
363 tropomin =
MIN(tropomin, clim->
tropo[it][iy]);
364 tropomax =
MAX(tropomax, clim->
tropo[it][iy]);
369 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
373 LOG(2,
"Latitudes: %g, %g ... %g deg",
376 LOG(2,
"Tropopause altitude range: %g ... %g hPa",
Z(tropomax),
378 LOG(2,
"Tropopause pressure range: %g ... %g hPa", tropomin, tropomax);
388 if (t <= ts->time[0])
395 ts->
time[idx + 1], ts->
vmr[idx + 1], t);
408 double sec =
FMOD(t, 365.25 * 86400.);
410 sec += 365.25 * 86400.;
414 if (p < zm->p[zm->
np - 1])
415 p_help = zm->
p[zm->
np - 1];
416 else if (p > zm->
p[0])
420 double lat_help = lat;
421 if (lat < zm->lat[0])
422 lat_help = zm->
lat[0];
423 else if (lat > zm->
lat[zm->
nlat - 1])
424 lat_help = zm->
lat[zm->
nlat - 1];
432 double aux00 =
LIN(zm->
p[ip], zm->
vmr[isec][ip][ilat],
433 zm->
p[ip + 1], zm->
vmr[isec][ip + 1][ilat], p_help);
434 double aux01 =
LIN(zm->
p[ip], zm->
vmr[isec][ip][ilat + 1],
435 zm->
p[ip + 1], zm->
vmr[isec][ip + 1][ilat + 1], p_help);
436 double aux10 =
LIN(zm->
p[ip], zm->
vmr[isec + 1][ip][ilat],
437 zm->
p[ip + 1], zm->
vmr[isec + 1][ip + 1][ilat], p_help);
438 double aux11 =
LIN(zm->
p[ip], zm->
vmr[isec + 1][ip][ilat + 1],
439 zm->
p[ip + 1], zm->
vmr[isec + 1][ip + 1][ilat + 1],
441 aux00 =
LIN(zm->
lat[ilat], aux00, zm->
lat[ilat + 1], aux01, lat_help);
442 aux11 =
LIN(zm->
lat[ilat], aux10, zm->
lat[ilat + 1], aux11, lat_help);
443 aux00 =
LIN(zm->
time[isec], aux00, zm->
time[isec + 1], aux11, sec);
445 return MAX(aux00, 0.0);
458 const int decompress,
462 const size_t nxy = nx * ny;
463 double lon[
EX], lat[
EY];
464 for (
size_t ix = 0; ix < nx; ix++)
465 lon[ix] = 360. * (
double) ix / ((double) nx - 1.);
466 for (
size_t iy = 0; iy < ny; iy++)
467 lat[iy] = -(180. * (
double) iy / ((double) ny - 1.) - 90.);
470 const char domain[] =
"[0.0, 360.0]x[-90.0, 90.0]";
473 const int max_level_grid = 7;
474 cms_param_t *cms_param
475 = cms_set_parameters(nx, ny, max_level_grid, Nd0_x, Nd0_y, domain);
478 double cr = 0, t_coars = 0, t_eval = 0;
484 for (
size_t ip = 0; ip < np; ip++) {
487 cms_module_t *cms_ptr = cms_init(cms_param);
492 cms_sol = cms_read_zstd_sol(cms_ptr, inout);
494 cms_sol = cms_read_sol(cms_ptr, inout);
497#pragma omp parallel for default(shared)
498 for (
size_t ix = 0; ix < nx; ix++)
499 for (
size_t iy = 0; iy < ny; iy++) {
501 const double x[] = { lon[ix], lat[iy] };
502 cms_eval(cms_ptr, cms_sol, x, &val);
503 array[
ARRAY_3D(ix, iy, ny, ip, np)] = (float) val;
507 cr += cms_compression_rate(cms_ptr, cms_sol) / (double) np;
510 cms_delete_sol(cms_sol);
511 cms_delete_module(cms_ptr);
515 LOG(2,
"Read 3-D variable: %s (cms, RATIO= %g)", varname, cr);
522 cms_module_t *cms_ptr[
EP];
523 cms_sol_t *cms_sol[
EP];
527 ? (size_t) omp_get_max_threads()
529 for (
size_t ip0 = 0; ip0 < np; ip0 += dip) {
532 double t0 = omp_get_wtime();
535#pragma omp parallel for default(shared)
536 for (
size_t ip = ip0; ip <
MIN(ip0 + dip, np); ip++) {
540 ALLOC(tmp_arr,
float,
544 for (
size_t ix = 0; ix < nx; ++ix)
545 for (
size_t iy = 0; iy < ny; ++iy)
547 array[
ARRAY_3D(ix, iy, ny, ip, np)];
550 cms_ptr[ip] = cms_init(cms_param);
553 cms_sol[ip] = cms_read_arr(cms_ptr[ip], tmp_arr, lon, lat, nx, ny);
556 if (strcasecmp(varname,
"Z") == 0)
558 else if (strcasecmp(varname,
"T") == 0)
560 else if (strcasecmp(varname,
"U") == 0)
562 else if (strcasecmp(varname,
"V") == 0)
564 else if (strcasecmp(varname,
"W") == 0)
566 else if (strcasecmp(varname,
"PV") == 0)
568 else if (strcasecmp(varname,
"H2O") == 0)
570 else if (strcasecmp(varname,
"O3") == 0)
572 else if (strcasecmp(varname,
"LWC") == 0)
574 else if (strcasecmp(varname,
"RWC") == 0)
576 else if (strcasecmp(varname,
"IWC") == 0)
578 else if (strcasecmp(varname,
"SWC") == 0)
580 else if (strcasecmp(varname,
"CC") == 0)
583 ERRMSG(
"Variable name unknown!");
586 cms_coarsening(cms_ptr[ip], cms_sol[ip],
594 t_coars += (omp_get_wtime() - t0);
597 for (
size_t ip = ip0; ip <
MIN(ip0 + dip, np); ip++) {
600 double *tmp_cms, *tmp_org, *tmp_diff;
601 ALLOC(tmp_cms,
double,
603 ALLOC(tmp_org,
double,
605 ALLOC(tmp_diff,
double,
609 t0 = omp_get_wtime();
612#pragma omp parallel for default(shared)
613 for (
size_t ix = 0; ix < nx; ix++)
614 for (
size_t iy = 0; iy < ny; iy++) {
615 const size_t idx =
ARRAY_2D(ix, iy, ny);
616 const double x[] = { lon[ix], lat[iy] };
617 cms_eval(cms_ptr[ip], cms_sol[ip], x, &tmp_cms[idx]);
618 tmp_org[idx] = array[
ARRAY_3D(ix, iy, ny, ip, np)];
619 tmp_diff[idx] = tmp_cms[idx] - tmp_org[idx];
623 t_eval += (omp_get_wtime() - t0);
627 "cmultiscale: var= %s / lev= %lu / ratio= %g / rho= %g"
628 " / mean= %g / sd= %g / min= %g / max= %g", varname, ip,
629 cms_compression_rate(cms_ptr[ip], cms_sol[ip]),
630 gsl_stats_correlation(tmp_cms, 1, tmp_org, 1, nxy),
631 gsl_stats_mean(tmp_diff, 1, nxy), gsl_stats_sd(tmp_diff, 1, nxy),
632 gsl_stats_min(tmp_diff, 1, nxy), gsl_stats_max(tmp_diff, 1, nxy));
635 cr += cms_compression_rate(cms_ptr[ip], cms_sol[ip]) / (double) np;
639 cms_save_zstd_sol(cms_sol[ip], inout, 3);
641 cms_save_sol(cms_sol[ip], inout);
644 cms_delete_sol(cms_sol[ip]);
645 cms_delete_module(cms_ptr[ip]);
653 LOG(2,
"Write 3-D variable: %s"
654 " (cms, RATIO= %g, T_COARS= %g s, T_EVAL= %g s)",
655 varname, cr, t_coars, t_eval);
659 cms_delete_param(cms_param);
670 const int decompress,
673 double min[
EP], max[
EP], off[
EP], scl[
EP];
675 unsigned short *sarray;
678 ALLOC(sarray,
unsigned short,
685 LOG(2,
"Read 3-D variable: %s (pck, RATIO= %g)",
686 varname, (
double)
sizeof(
float) / (
double)
sizeof(
unsigned short));
695 FREAD(sarray,
unsigned short,
700#pragma omp parallel for default(shared)
701 for (
size_t ixy = 0; ixy < nxy; ixy++)
702 for (
size_t iz = 0; iz < nz; iz++)
704 = (
float) (sarray[ixy * nz + iz] * scl[iz] + off[iz]);
711 LOG(2,
"Write 3-D variable: %s (pck, RATIO= %g)",
712 varname, (
double)
sizeof(
float) / (
double)
sizeof(
unsigned short));
715 for (
size_t iz = 0; iz < nz; iz++) {
719 for (
size_t ixy = 1; ixy < nxy; ixy++)
720 for (
size_t iz = 0; iz < nz; iz++) {
721 if (array[ixy * nz + iz] < min[iz])
722 min[iz] = array[ixy * nz + iz];
723 if (array[ixy * nz + iz] > max[iz])
724 max[iz] = array[ixy * nz + iz];
728 for (
size_t iz = 0; iz < nz; iz++) {
729 scl[iz] = (max[iz] - min[iz]) / 65533.;
734#pragma omp parallel for default(shared)
735 for (
size_t ixy = 0; ixy < nxy; ixy++)
736 for (
size_t iz = 0; iz < nz; iz++)
738 sarray[ixy * nz + iz] = (
unsigned short)
739 ((array[ixy * nz + iz] - off[iz]) / scl[iz] + .5);
741 sarray[ixy * nz + iz] = 0;
750 FWRITE(sarray,
unsigned short,
769 const double tolerance,
770 const int decompress,
774 const zfp_type type = zfp_type_float;
776 zfp_field_3d(array, type, (uint) nx, (uint) ny, (uint) nz);
779 zfp_stream *zfp = zfp_stream_open(NULL);
783 double actual_tol = 0;
785 actual_prec = (int) zfp_stream_set_precision(zfp, (uint) precision);
786 else if (tolerance > 0)
787 actual_tol = zfp_stream_set_accuracy(zfp, tolerance);
789 ERRMSG(
"Set precision or tolerance!");
792 const size_t bufsize = zfp_stream_maximum_size(zfp, field);
793 void *buffer = malloc(bufsize);
796 bitstream *stream = stream_open(buffer, bufsize);
797 zfp_stream_set_bit_stream(zfp, stream);
798 zfp_stream_rewind(zfp);
803 FREAD(&zfpsize,
size_t,
806 if (fread(buffer, 1, zfpsize, inout) != zfpsize)
807 ERRMSG(
"Error while reading zfp data!");
808 if (!zfp_decompress(zfp, field)) {
809 ERRMSG(
"Decompression failed!");
811 LOG(2,
"Read 3-D variable: %s "
812 "(zfp, PREC= %d, TOL= %g, RATIO= %g)",
813 varname, actual_prec, actual_tol,
814 ((
double) (nx * ny * nz)) / (
double) zfpsize);
819 zfpsize = zfp_compress(zfp, field);
821 ERRMSG(
"Compression failed!");
826 if (fwrite(buffer, 1, zfpsize, inout) != zfpsize)
827 ERRMSG(
"Error while writing zfp data!");
829 LOG(2,
"Write 3-D variable: %s "
830 "(zfp, PREC= %d, TOL= %g, RATIO= %g)",
831 varname, actual_prec, actual_tol,
832 ((
double) (nx * ny * nz)) / (
double) zfpsize);
836 zfp_field_free(field);
837 zfp_stream_close(zfp);
838 stream_close(stream);
850 const int decompress,
855 const size_t uncomprLen = n *
sizeof(float);
856 size_t comprLen = ZSTD_compressBound(uncomprLen);
860 char *compr = (
char *) calloc((uint) comprLen, 1);
861 char *uncompr = (
char *) array;
865 FREAD(&comprLen,
size_t,
868 if (fread(compr, 1, comprLen, inout) != comprLen)
869 ERRMSG(
"Error while reading zstd data!");
870 compsize = ZSTD_decompress(uncompr, uncomprLen, compr, comprLen);
871 if (ZSTD_isError(compsize)) {
872 ERRMSG(
"Decompression failed!");
874 LOG(2,
"Read 3-D variable: %s (zstd, RATIO= %g)",
875 varname, ((
double) uncomprLen) / (
double) comprLen)
880 compsize = ZSTD_compress(compr, comprLen, uncompr, uncomprLen, level);
881 if (ZSTD_isError(compsize)) {
882 ERRMSG(
"Compression failed!");
887 if (fwrite(compr, 1, compsize, inout) != compsize)
888 ERRMSG(
"Error while writing zstd data!");
890 LOG(2,
"Write 3-D variable: %s (zstd, RATIO= %g)",
891 varname, ((
double) uncomprLen) / (
double) compsize);
908 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
909 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
912 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
913 *doy = d0l[mon - 1] + day - 1;
915 *doy = d0[mon - 1] + day - 1;
927 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
928 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
933 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
934 for (i = 11; i > 0; i--)
938 *day = doy - d0l[i] + 1;
940 for (i = 11; i > 0; i--)
944 *day = doy - d0[i] + 1;
959 ERRMSG(
"Too many data points!");
962 gsl_fft_complex_wavetable *wavetable =
963 gsl_fft_complex_wavetable_alloc((
size_t) n);
964 gsl_fft_complex_workspace *workspace =
965 gsl_fft_complex_workspace_alloc((
size_t) n);
968 for (
int i = 0; i < n; i++) {
969 data[2 * i] = fcReal[i];
970 data[2 * i + 1] = fcImag[i];
974 gsl_fft_complex_forward(data, 1, (
size_t) n, wavetable, workspace);
977 for (
int i = 0; i < n; i++) {
978 fcReal[i] = data[2 * i];
979 fcImag[i] = data[2 * i + 1];
983 gsl_fft_complex_wavetable_free(wavetable);
984 gsl_fft_complex_workspace_free(workspace);
995 const double radius = z +
RE;
996 const double latrad =
DEG2RAD(lat);
997 const double lonrad =
DEG2RAD(lon);
998 const double coslat = cos(latrad);
1000 x[0] = radius * coslat * cos(lonrad);
1001 x[1] = radius * coslat * sin(lonrad);
1002 x[2] = radius * sin(latrad);
1011 const char *metbase,
1012 const double dt_met,
1019 int year, mon, day, hour, min, sec;
1023 t6 = floor(t / dt_met) * dt_met;
1025 t6 = ceil(t / dt_met) * dt_met;
1028 jsec2time(t6, &year, &mon, &day, &hour, &min, &sec, &r);
1033 sprintf(filename,
"%s_YYYY_MM_DD_HH.nc", metbase);
1035 sprintf(filename,
"%s_YYYY_MM_DD_HH.bin", metbase);
1037 sprintf(filename,
"%s_YYYY_MM_DD_HH.pck", metbase);
1039 sprintf(filename,
"%s_YYYY_MM_DD_HH.zfp", metbase);
1041 sprintf(filename,
"%s_YYYY_MM_DD_HH.zstd", metbase);
1043 sprintf(filename,
"%s_YYYY_MM_DD_HH.cms", metbase);
1044 sprintf(repl,
"%d", year);
1046 sprintf(repl,
"%02d", mon);
1048 sprintf(repl,
"%02d", day);
1050 sprintf(repl,
"%02d", hour);
1056 sprintf(filename,
"%s_YYMMDDHH.nc", metbase);
1057 sprintf(repl,
"%d", year);
1059 sprintf(repl,
"%02d", year % 100);
1061 sprintf(repl,
"%02d", mon);
1063 sprintf(repl,
"%02d", day);
1065 sprintf(repl,
"%02d", hour);
1080 for (
int i = 0; i < 3; i++) {
1084 if (!(ch = strstr(orig, search)))
1086 strncpy(buffer, orig, (
size_t) (ch - orig));
1087 buffer[ch - orig] = 0;
1088 sprintf(buffer + (ch - orig),
"%s%s", repl, ch + strlen(search));
1090 strcpy(orig, buffer);
1097 const int met_tropo,
1117#pragma omp parallel for default(shared) private(ci,cw)
1118 for (
int ix = 0; ix < nx; ix++)
1119 for (
int iy = 0; iy < ny; iy++) {
1121 &pt[iy * nx + ix], ci, cw, 1);
1123 &ps[iy * nx + ix], ci, cw, 0);
1125 &zs[iy * nx + ix], ci, cw, 0);
1127 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
1129 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
1131 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
1133 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
1150 *lon2 =
FMOD(lon, 360.);
1151 if (*lon2 < lons[0])
1153 else if (*lon2 > lons[nlon - 1])
1158 if (lats[0] < lats[nlat - 1])
1159 *lat2 =
MIN(
MAX(*lat2, lats[0]), lats[nlat - 1]);
1161 *lat2 =
MIN(
MAX(*lat2, lats[nlat - 1]), lats[0]);
1168 float heights0[
EX][
EY][
EP],
1169 float array0[
EX][
EY][
EP],
1171 float heights1[
EX][
EY][
EP],
1172 float array1[
EX][
EY][
EP],
1174 const double height,
1200 int k_max = ind[0][0];
1201 for (
int i = 0; i < 2; i++)
1202 for (
int j = 0; j < 4; j++) {
1203 if (ci[2] > ind[i][j])
1205 if (k_max < ind[i][j])
1211 cw[0] = (lon2 - met0->
lon[ci[0]]) /
1212 (met0->
lon[ci[0] + 1] - met0->
lon[ci[0]]);
1213 cw[1] = (lat2 - met0->
lat[ci[1]]) /
1214 (met0->
lat[ci[1] + 1] - met0->
lat[ci[1]]);
1217 double height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2]]
1218 - heights0[ci[0]][ci[1]][ci[2]])
1219 + heights0[ci[0]][ci[1]][ci[2]];
1220 double height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2]]
1221 - heights0[ci[0]][ci[1] + 1][ci[2]])
1222 + heights0[ci[0]][ci[1] + 1][ci[2]];
1223 double height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2]]
1224 - heights0[ci[0] + 1][ci[1]][ci[2]])
1225 + heights0[ci[0] + 1][ci[1]][ci[2]];
1226 double height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2]]
1227 - heights0[ci[0] + 1][ci[1] + 1][ci[2]])
1228 + heights0[ci[0] + 1][ci[1] + 1][ci[2]];
1231 double height0 = cw[1] * (height01 - height00) + height00;
1232 double height1 = cw[1] * (height11 - height10) + height10;
1235 double height_bot = cw[0] * (height1 - height0) + height0;
1238 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
1239 - heights0[ci[0]][ci[1]][ci[2] + 1])
1240 + heights0[ci[0]][ci[1]][ci[2] + 1];
1241 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
1242 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
1243 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
1244 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
1245 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
1246 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
1247 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1248 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1249 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1252 height0 = cw[1] * (height01 - height00) + height00;
1253 height1 = cw[1] * (height11 - height10) + height10;
1256 double height_top = cw[0] * (height1 - height0) + height0;
1259 while (((heights0[0][0][0] > heights0[0][0][1]) &&
1260 ((height_bot <= height) || (height_top > height))
1261 && (height_bot >= height) && (ci[2] < k_max))
1263 ((heights0[0][0][0] < heights0[0][0][1]) &&
1264 ((height_bot >= height) || (height_top < height))
1265 && (height_bot <= height) && (ci[2] < k_max))
1269 height_bot = height_top;
1272 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
1273 - heights0[ci[0]][ci[1]][ci[2] + 1])
1274 + heights0[ci[0]][ci[1]][ci[2] + 1];
1275 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
1276 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
1277 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
1278 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
1279 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
1280 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
1281 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1282 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1283 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1286 height0 = cw[1] * (height01 - height00) + height00;
1287 height1 = cw[1] * (height11 - height10) + height10;
1290 height_top = cw[0] * (height1 - height0) + height0;
1294 cw[2] = (height - height_bot)
1295 / (height_top - height_bot);
1299 double array000 = cw[3] * (array1[ci[0]][ci[1]][ci[2]]
1300 - array0[ci[0]][ci[1]][ci[2]])
1301 + array0[ci[0]][ci[1]][ci[2]];
1302 double array100 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2]]
1303 - array0[ci[0] + 1][ci[1]][ci[2]])
1304 + array0[ci[0] + 1][ci[1]][ci[2]];
1305 double array010 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2]]
1306 - array0[ci[0]][ci[1] + 1][ci[2]])
1307 + array0[ci[0]][ci[1] + 1][ci[2]];
1308 double array110 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2]]
1309 - array0[ci[0] + 1][ci[1] + 1][ci[2]])
1310 + array0[ci[0] + 1][ci[1] + 1][ci[2]];
1311 double array001 = cw[3] * (array1[ci[0]][ci[1]][ci[2] + 1]
1312 - array0[ci[0]][ci[1]][ci[2] + 1])
1313 + array0[ci[0]][ci[1]][ci[2] + 1];
1314 double array101 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2] + 1]
1315 - array0[ci[0] + 1][ci[1]][ci[2] + 1])
1316 + array0[ci[0] + 1][ci[1]][ci[2] + 1];
1317 double array011 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2] + 1]
1318 - array0[ci[0]][ci[1] + 1][ci[2] + 1])
1319 + array0[ci[0]][ci[1] + 1][ci[2] + 1];
1320 double array111 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1321 - array0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1322 + array0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1324 double array00 = cw[0] * (array100 - array000) + array000;
1325 double array10 = cw[0] * (array110 - array010) + array010;
1326 double array01 = cw[0] * (array101 - array001) + array001;
1327 double array11 = cw[0] * (array111 - array011) + array011;
1329 double aux0 = cw[1] * (array10 - array00) + array00;
1330 double aux1 = cw[1] * (array11 - array01) + array01;
1333 *var = cw[2] * (aux1 - aux0) + aux0;
1363 cw[0] = (met->
p[ci[0] + 1] - p)
1364 / (met->
p[ci[0] + 1] - met->
p[ci[0]]);
1365 cw[1] = (met->
lon[ci[1] + 1] - lon2)
1366 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
1367 cw[2] = (met->
lat[ci[2] + 1] - lat2)
1368 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
1373 cw[0] * (array[ci[1]][ci[2]][ci[0]] - array[ci[1]][ci[2]][ci[0] + 1])
1374 + array[ci[1]][ci[2]][ci[0] + 1];
1376 cw[0] * (array[ci[1]][ci[2] + 1][ci[0]] -
1377 array[ci[1]][ci[2] + 1][ci[0] + 1])
1378 + array[ci[1]][ci[2] + 1][ci[0] + 1];
1380 cw[0] * (array[ci[1] + 1][ci[2]][ci[0]] -
1381 array[ci[1] + 1][ci[2]][ci[0] + 1])
1382 + array[ci[1] + 1][ci[2]][ci[0] + 1];
1384 cw[0] * (array[ci[1] + 1][ci[2] + 1][ci[0]] -
1385 array[ci[1] + 1][ci[2] + 1][ci[0] + 1])
1386 + array[ci[1] + 1][ci[2] + 1][ci[0] + 1];
1389 aux00 = cw[2] * (aux00 - aux01) + aux01;
1390 aux11 = cw[2] * (aux10 - aux11) + aux11;
1391 *var = cw[1] * (aux00 - aux11) + aux11;
1417 if (z >= zs[ix][iy][iz + 1])
1418 aux00 = array[ix][iy][iz + 1];
1419 else if (z <= zs[ix][iy][iz])
1420 aux00 = array[ix][iy][iz];
1422 aux00 =
LIN(zs[ix][iy][iz], array[ix][iy][iz],
1423 zs[ix][iy][iz + 1], array[ix][iy][iz + 1], z);
1427 if (z >= zs[ix][iy + 1][iz + 1])
1428 aux01 = array[ix][iy + 1][iz + 1];
1429 else if (z <= zs[ix][iy + 1][iz])
1430 aux01 = array[ix][iy + 1][iz];
1432 aux01 =
LIN(zs[ix][iy + 1][iz], array[ix][iy + 1][iz],
1433 zs[ix][iy + 1][iz + 1], array[ix][iy + 1][iz + 1], z);
1437 if (z >= zs[ix + 1][iy][iz + 1])
1438 aux10 = array[ix + 1][iy][iz + 1];
1439 else if (z <= zs[ix + 1][iy][iz])
1440 aux10 = array[ix + 1][iy][iz];
1442 aux10 =
LIN(zs[ix + 1][iy][iz], array[ix + 1][iy][iz],
1443 zs[ix + 1][iy][iz + 1], array[ix + 1][iy][iz + 1], z);
1447 if (z >= zs[ix + 1][iy + 1][iz + 1])
1448 aux11 = array[ix + 1][iy + 1][iz + 1];
1449 else if (z <= zs[ix + 1][iy + 1][iz])
1450 aux11 = array[ix + 1][iy + 1][iz];
1452 aux11 =
LIN(zs[ix + 1][iy + 1][iz], array[ix + 1][iy + 1][iz],
1453 zs[ix + 1][iy + 1][iz + 1], array[ix + 1][iy + 1][iz + 1], z);
1456 double aux0 =
LIN(met->
lat[iy], aux00, met->
lat[iy + 1], aux01, lat2);
1457 double aux1 =
LIN(met->
lat[iy], aux10, met->
lat[iy + 1], aux11, lat2);
1458 *var =
LIN(met->
lon[ix], aux0, met->
lon[ix + 1], aux1, lon2);
1465 float array[
EX][
EY],
1486 cw[1] = (met->
lon[ci[1] + 1] - lon2)
1487 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
1488 cw[2] = (met->
lat[ci[2] + 1] - lat2)
1489 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
1493 double aux00 = array[ci[1]][ci[2]];
1494 double aux01 = array[ci[1]][ci[2] + 1];
1495 double aux10 = array[ci[1] + 1][ci[2]];
1496 double aux11 = array[ci[1] + 1][ci[2] + 1];
1499 if (isfinite(aux00) && isfinite(aux01)
1500 && isfinite(aux10) && isfinite(aux11)) {
1501 aux00 = cw[2] * (aux00 - aux01) + aux01;
1502 aux11 = cw[2] * (aux10 - aux11) + aux11;
1503 *var = cw[1] * (aux00 - aux11) + aux11;
1523 float array0[
EX][
EY][
EP],
1525 float array1[
EX][
EY][
EP],
1542 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
1545 *var = wt * (var0 - var1) + var1;
1553 float array0[
EX][
EY][
EP],
1556 float array1[
EX][
EY][
EP],
1570 *var =
LIN(met0->
time, var0, met1->
time, var1, ts);
1577 float array0[
EX][
EY],
1579 float array1[
EX][
EY],
1595 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
1598 if (isfinite(var0) && isfinite(var1))
1599 *var = wt * (var0 - var1) + var1;
1610 float array0[
EX][
EY],
1612 float array1[
EX][
EY],
1613 const double lons[
EX],
1614 const double lats[
EY],
1624 double aux0, aux1, aux00, aux01, aux10, aux11, mean = 0;
1633 const int ix =
locate_reg(lons, (
int) nlon, lon2);
1634 const int iy =
locate_irr(lats, (
int) nlat, lat2);
1638 for (
int dx = 0; dx < 2; dx++)
1639 for (
int dy = 0; dy < 2; dy++) {
1640 if (isfinite(array0[ix + dx][iy + dy])) {
1641 mean += array0[ix + dx][iy + dy];
1642 *sigma +=
SQR(array0[ix + dx][iy + dy]);
1645 if (isfinite(array1[ix + dx][iy + dy])) {
1646 mean += array1[ix + dx][iy + dy];
1647 *sigma +=
SQR(array1[ix + dx][iy + dy]);
1652 *sigma = sqrt(
MAX(*sigma / n -
SQR(mean / n), 0.0));
1655 if (method == 1 && isfinite(array0[ix][iy])
1656 && isfinite(array0[ix][iy + 1])
1657 && isfinite(array0[ix + 1][iy])
1658 && isfinite(array0[ix + 1][iy + 1])
1659 && isfinite(array1[ix][iy])
1660 && isfinite(array1[ix][iy + 1])
1661 && isfinite(array1[ix + 1][iy])
1662 && isfinite(array1[ix + 1][iy + 1])) {
1664 aux00 =
LIN(lons[ix], array0[ix][iy],
1665 lons[ix + 1], array0[ix + 1][iy], lon2);
1666 aux01 =
LIN(lons[ix], array0[ix][iy + 1],
1667 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
1668 aux0 =
LIN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
1670 aux10 =
LIN(lons[ix], array1[ix][iy],
1671 lons[ix + 1], array1[ix + 1][iy], lon2);
1672 aux11 =
LIN(lons[ix], array1[ix][iy + 1],
1673 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
1674 aux1 =
LIN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
1676 *var =
LIN(time0, aux0, time1, aux1, time);
1681 aux00 =
NN(lons[ix], array0[ix][iy],
1682 lons[ix + 1], array0[ix + 1][iy], lon2);
1683 aux01 =
NN(lons[ix], array0[ix][iy + 1],
1684 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
1685 aux0 =
NN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
1687 aux10 =
NN(lons[ix], array1[ix][iy],
1688 lons[ix + 1], array1[ix + 1][iy], lon2);
1689 aux11 =
NN(lons[ix], array1[ix][iy + 1],
1690 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
1691 aux1 =
NN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
1693 *var =
NN(time0, aux0, time1, aux1, time);
1718 const time_t jsec0 = (time_t) jsec + timegm(&t0);
1719 t1 = gmtime(&jsec0);
1721 *year = t1->tm_year + 1900;
1722 *mon = t1->tm_mon + 1;
1724 *hour = t1->tm_hour;
1727 *remain = jsec - floor(jsec);
1733 const double kz[
EP],
1734 const double kw[
EP],
1743 const double z =
Z(p);
1748 else if (z > kz[nk - 1])
1752 return LIN(kz[idx], kw[idx], kz[idx + 1], kw[idx + 1], z);
1769 const double a =
RA *
SQR(t), r =
SH(h2o) / (1. -
SH(h2o));
1783 const double press[138] = {
1784 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
1785 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
1786 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
1787 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
1788 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
1789 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
1790 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
1791 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
1792 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
1793 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
1794 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
1795 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
1796 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
1797 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
1798 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
1799 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
1800 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
1801 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
1802 1010.8487, 1013.2500, 1044.45
1805 for (
int ip = 0; ip < ctl->
met_np; ip++)
1812 const double press[92] = {
1813 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
1814 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
1815 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
1816 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
1817 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
1819 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
1820 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
1821 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
1822 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
1823 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
1824 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
1825 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
1826 1007.4431, 1010.8487, 1013.2500, 1044.45
1829 for (
int ip = 0; ip < ctl->
met_np; ip++)
1836 const double press[60] = {
1837 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
1838 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
1839 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
1840 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
1841 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
1842 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
1843 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
1844 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1044.45
1847 for (
int ip = 0; ip < ctl->
met_np; ip++)
1854 const double press[147] = {
1855 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
1856 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
1857 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
1858 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
1859 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
1860 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
1861 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
1862 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
1863 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
1864 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
1865 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
1866 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
1867 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
1868 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
1869 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
1870 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
1871 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
1872 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
1873 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73, 1028.85,
1875 1035.09, 1038.21, 1041.33, 1044.45
1878 for (
int ip = 0; ip < ctl->
met_np; ip++)
1885 const double press[101] = {
1886 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
1887 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
1888 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
1889 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
1890 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
1892 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
1893 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
1894 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
1895 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
1896 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
1897 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
1898 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
1899 1007.4431, 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73,
1901 1035.09, 1038.21, 1041.33, 1044.45
1904 for (
int ip = 0; ip < ctl->
met_np; ip++)
1911 const double press[62] = {
1912 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
1913 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
1914 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
1915 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
1916 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
1917 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
1918 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
1919 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1034.86, 1039.65,
1923 for (
int ip = 0; ip < ctl->
met_np; ip++)
1930 const double press[137] = {
1931 0.01, 0.02, 0.031, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861,
1932 0.2499, 0.3299, 0.4288, 0.5496, 0.6952, 0.869, 1.0742,
1933 1.3143, 1.5928, 1.9134, 2.2797, 2.6954, 3.1642, 3.6898,
1934 4.2759, 4.9262, 5.6441, 6.4334, 7.2974, 8.2397, 9.2634,
1935 10.372, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945, 18.9752,
1936 20.761, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
1937 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.199, 54.5299,
1938 57.9834, 61.5607, 65.2695, 69.1187, 73.1187, 77.281, 81.6182,
1939 86.145, 90.8774, 95.828, 101.005, 106.415, 112.068, 117.971,
1940 124.134, 130.564, 137.27, 144.262, 151.549, 159.14, 167.045,
1941 175.273, 183.834, 192.739, 201.997, 211.619, 221.615, 231.995,
1942 242.772, 253.955, 265.556, 277.585, 290.055, 302.976, 316.361,
1943 330.22, 344.566, 359.411, 374.767, 390.645, 407.058, 424.019,
1944 441.539, 459.632, 478.31, 497.584, 517.42, 537.72, 558.343,
1945 579.193, 600.167, 621.162, 642.076, 662.808, 683.262, 703.347,
1946 722.979, 742.086, 760.6, 778.466, 795.64, 812.085, 827.776,
1947 842.696, 856.838, 870.2, 882.791, 894.622, 905.712, 916.081,
1948 925.757, 934.767, 943.14, 950.908, 958.104, 965.299, 972.495,
1949 979.69, 986.886, 994.081, 1001.28, 1008.47, 1015.67, 1022.86,
1950 1030.06, 1037.25, 1044.45
1953 for (
int ip = 0; ip < ctl->
met_np; ip++)
1960 const double press[59] = {
1961 0.1, 0.2, 0.3843, 0.6365, 0.9564, 1.3448, 1.8058, 2.3478,
1962 2.985, 3.7397, 4.6462, 5.7565, 7.1322, 8.8366, 10.9483,
1963 13.5647, 16.8064, 20.8227, 25.7989, 31.9642, 39.6029, 49.0671,
1964 60.1802, 73.0663, 87.7274, 104.229, 122.614, 142.902, 165.089,
1965 189.147, 215.025, 242.652, 272.059, 303.217, 336.044, 370.407,
1966 406.133, 443.009, 480.791, 519.209, 557.973, 596.777, 635.306,
1967 673.24, 710.263, 746.063, 780.346, 812.83, 843.263, 871.42,
1968 897.112, 920.189, 940.551, 958.148, 975.744, 993.341, 1010.94,
1972 for (
int ip = 0; ip < ctl->
met_np; ip++)
1976 ERRMSG(
"Use 0 for l137, 1 for l91, 2 for l60 or values between 3 and 7.")
1989 int i = (ihi + ilo) >> 1;
1991 if (xx[i] < xx[i + 1])
1992 while (ihi > ilo + 1) {
1993 i = (ihi + ilo) >> 1;
1999 while (ihi > ilo + 1) {
2000 i = (ihi + ilo) >> 1;
2020 int i = (ihi + ilo) >> 1;
2022 if (x >= xx[ig] && x < xx[ig + 1])
2025 if (xx[i] < xx[i + 1])
2026 while (ihi > ilo + 1) {
2027 i = (ihi + ilo) >> 1;
2033 while (ihi > ilo + 1) {
2034 i = (ihi + ilo) >> 1;
2052 const int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
2066 float profiles[
EX][
EY][
EP],
2068 const int lon_ap_ind,
2069 const int lat_ap_ind,
2070 const double height_ap,
2076 np, height_ap, ind[0]);
2078 np, height_ap, ind[1]);
2080 np, height_ap, ind[2]);
2099 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2103 double dts, u[4], um = 0, v[4], vm = 0, w[4], wm = 0,
2107 for (
int i = 0; i < ctl->
advect; i++) {
2112 x[0] = atm->
lon[ip];
2113 x[1] = atm->
lat[ip];
2116 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
2117 x[0] = atm->
lon[ip] +
DX2DEG(dts * u[i - 1] / 1000., atm->
lat[ip]);
2118 x[1] = atm->
lat[ip] +
DY2DEG(dts * v[i - 1] / 1000.);
2119 x[2] = atm->
p[ip] + dts * w[i - 1];
2121 const double tm = atm->
time[ip] + dts;
2126 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2128 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2130 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
2136 met1, met1->
pl, met1->
ul,
2137 tm, x[2], x[0], x[1], &u[i]);
2139 met1, met1->
pl, met1->
vl,
2140 tm, x[2], x[0], x[1], &v[i]);
2142 met1, met1->
pl, met1->
wl,
2143 tm, x[2], x[0], x[1], &w[i]);
2149 k = (i == 0 ? 0.0 : 1.0);
2150 else if (ctl->
advect == 4)
2151 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2158 atm->
time[ip] += cache->
dt[ip];
2159 atm->
lon[ip] +=
DX2DEG(cache->
dt[ip] * um / 1000.,
2160 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
2161 atm->
lat[ip] +=
DY2DEG(cache->
dt[ip] * vm / 1000.);
2162 atm->
p[ip] += cache->
dt[ip] * wm;
2170 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2176 atm->
lon[ip], atm->
lat[ip],
2180 double dts, u[4], um = 0, v[4], vm = 0, zeta_dot[4],
2181 zeta_dotm = 0, x[3] = { 0, 0, 0 };
2184 for (
int i = 0; i < ctl->
advect; i++) {
2189 x[0] = atm->
lon[ip];
2190 x[1] = atm->
lat[ip];
2193 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
2194 x[0] = atm->
lon[ip] +
DX2DEG(dts * u[i - 1] / 1000., atm->
lat[ip]);
2195 x[1] = atm->
lat[ip] +
DY2DEG(dts * v[i - 1] / 1000.);
2196 x[2] = atm->
q[ctl->
qnt_zeta][ip] + dts * zeta_dot[i - 1];
2198 const double tm = atm->
time[ip] + dts;
2202 met1->
ul, tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2204 met1->
vl, tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2207 x[1], &zeta_dot[i], ci, cw, 0);
2212 k = (i == 0 ? 0.0 : 1.0);
2213 else if (ctl->
advect == 4)
2214 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2217 zeta_dotm += k * zeta_dot[i];
2221 atm->
time[ip] += cache->
dt[ip];
2222 atm->
lon[ip] +=
DX2DEG(cache->
dt[ip] * um / 1000.,
2223 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
2224 atm->
lat[ip] +=
DY2DEG(cache->
dt[ip] * vm / 1000.);
2225 atm->
q[ctl->
qnt_zeta][ip] += cache->
dt[ip] * zeta_dotm;
2230 atm->
lon[ip], atm->
lat[ip], &atm->
p[ip], ci, cw, 1);
2249 SELECT_TIMER(
"MODULE_ADVECT_INIT",
"PHYSICS", NVTX_GPU);
2258 atm->
lon[ip], atm->
lat[ip], &atm->
p[ip], ci, cw, 1);
2273 SELECT_TIMER(
"MODULE_BOUND_COND",
"PHYSICS", NVTX_GPU);
2283 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2319 if (atm->
p[ip] < pbl)
2371 ERRMSG(
"Molar mass is not defined!");
2377 const int np = atm->
np;
2381 const int ngrid = nx * ny * nz;
2383 double *restrict
const z = (
double *) malloc((
size_t) nz *
sizeof(double));
2384 double *restrict
const press =
2385 (
double *) malloc((
size_t) nz *
sizeof(double));
2386 double *restrict
const mass =
2387 (
double *) calloc((
size_t) ngrid,
sizeof(double));
2388 double *restrict
const area =
2389 (
double *) malloc((
size_t) ny *
sizeof(double));
2390 double *restrict
const lon =
2391 (
double *) malloc((
size_t) nx *
sizeof(double));
2392 double *restrict
const lat =
2393 (
double *) malloc((
size_t) ny *
sizeof(double));
2395 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
2396 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
2397 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
2406#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np],z[0:nz],press[0:nz],mass[0:ngrid],area[0:ny],lon[0:nx],lat[0:ny])
2407#pragma acc data present(ctl,met0,met1,atm,ixs,iys,izs,z,press,mass,area,lon,lat)
2408#pragma acc parallel loop independent gang vector
2410#pragma omp parallel for default(shared)
2412 for (
int iz = 0; iz < nz; iz++) {
2414 press[iz] =
P(z[iz]);
2418 const double t0 = tt - 0.5 * ctl->
dt_mod;
2419 const double t1 = tt + 0.5 * ctl->
dt_mod;
2423#pragma acc parallel loop independent gang vector
2425#pragma omp parallel for default(shared)
2427 for (
int ip = 0; ip < np; ip++) {
2431 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
2432 || ixs[ip] < 0 || ixs[ip] >= nx
2433 || iys[ip] < 0 || iys[ip] >= ny || izs[ip] < 0 || izs[ip] >= nz)
2439#pragma acc parallel loop independent gang vector
2441#pragma omp parallel for default(shared)
2443 for (
int ix = 0; ix < nx; ix++)
2446#pragma acc parallel loop independent gang vector
2448#pragma omp parallel for default(shared)
2450 for (
int iy = 0; iy < ny; iy++) {
2452 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
2457#pragma acc parallel loop independent gang vector
2459 for (
int ip = 0; ip < np; ip++)
2462#pragma acc atomic update
2464 mass[
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz)]
2465 += atm->
q[ctl->
qnt_m][ip];
2469#pragma acc parallel loop independent gang vector
2471#pragma omp parallel for default(shared)
2473 for (
int ip = 0; ip < np; ip++)
2480 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
2483 const double m = mass[
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz)];
2487 / (
RHO(press[izs[ip]], temp) * area[iys[ip]] * dz * 1e9);
2490#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
2520 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2537 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
2539 atm->
lat[ip], atm->
p[ip]));
2541 atm->
lat[ip], atm->
p[ip]));
2543 atm->
lat[ip], atm->
p[ip]));
2557 SELECT_TIMER(
"MODULE_CONVECTION",
"PHYSICS", NVTX_GPU);
2563 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2571 double pbot = ps, ptop = ps;
2588 double cape, cin, pel;
2594 if (isfinite(cape) && cape >= ctl->
conv_cape
2596 ptop = GSL_MIN(ptop, pel);
2600 if (ptop != pbot && atm->
p[ip] >= ptop) {
2605 pbot, atm->
lon[ip], atm->
lat[ip], &tbot, ci, cw, 1);
2607 ptop, atm->
lon[ip], atm->
lat[ip], &ttop, ci, cw, 1);
2608 const double rhobot = pbot / tbot;
2609 const double rhotop = ptop / ttop;
2612 const double rho = rhobot + (rhotop - rhobot) * cache->
rs[ip];
2615 atm->
p[ip] =
LIN(rhobot, pbot, rhotop, ptop, rho);
2633 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
2636 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,clim,atm)") {
2645 const double aux = exp(-cache->
dt[ip] / tdec);
2646 if (ctl->
qnt_m >= 0) {
2649 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
2650 atm->
q[ctl->
qnt_m][ip] *= aux;
2675 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2683 float umean = 0, usig = 0, vmean = 0, vsig = 0, wmean = 0, wsig = 0;
2684 for (
int i = 0; i < 2; i++)
2685 for (
int j = 0; j < 2; j++)
2686 for (
int k = 0; k < 2; k++) {
2687 umean += met0->
u[ix + i][iy + j][iz + k];
2688 usig +=
SQR(met0->
u[ix + i][iy + j][iz + k]);
2689 vmean += met0->
v[ix + i][iy + j][iz + k];
2690 vsig +=
SQR(met0->
v[ix + i][iy + j][iz + k]);
2691 wmean += met0->
w[ix + i][iy + j][iz + k];
2692 wsig +=
SQR(met0->
w[ix + i][iy + j][iz + k]);
2694 umean += met1->
u[ix + i][iy + j][iz + k];
2695 usig +=
SQR(met1->
u[ix + i][iy + j][iz + k]);
2696 vmean += met1->
v[ix + i][iy + j][iz + k];
2697 vsig +=
SQR(met1->
v[ix + i][iy + j][iz + k]);
2698 wmean += met1->
w[ix + i][iy + j][iz + k];
2699 wsig +=
SQR(met1->
w[ix + i][iy + j][iz + k]);
2701 usig = usig / 16.f -
SQR(umean / 16.f);
2702 usig = (usig > 0 ? sqrtf(usig) : 0);
2703 vsig = vsig / 16.f -
SQR(vmean / 16.f);
2704 vsig = (vsig > 0 ? sqrtf(vsig) : 0);
2705 wsig = wsig / 16.f -
SQR(wmean / 16.f);
2706 wsig = (wsig > 0 ? sqrtf(wsig) : 0);
2709 const double r = 1 - 2 * fabs(cache->
dt[ip]) / ctl->
dt_met;
2710 const double r2 = sqrt(1 - r * r);
2714 cache->
uvwp[ip][0] =
2715 (float) (r * cache->
uvwp[ip][0] +
2720 cache->
uvwp[ip][1] =
2721 (float) (r * cache->
uvwp[ip][1] +
2728 cache->
uvwp[ip][2] =
2729 (float) (r * cache->
uvwp[ip][2] +
2731 atm->
p[ip] += cache->
uvwp[ip][2] * cache->
dt[ip];
2752 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2754 double dsigw_dz = 0.0, sig_u = 0.25, sig_w = 0.1,
2755 tau_u = 300., tau_w = 100.;
2764 if (atm->
p[ip] >= pbl) {
2767 const double p =
MIN(atm->
p[ip], ps);
2768 const double zs =
Z(ps);
2769 const double z = 1e3 * (
Z(p) - zs);
2770 const double zi = 1e3 * (
Z(pbl) - zs);
2771 const double zratio = z / zi;
2774 double ess, nss, h2o, t;
2779 const double rho =
RHO(p,
TVIRT(t, h2o));
2780 const double tau = sqrt(
SQR(ess) +
SQR(nss));
2781 const double ustar = sqrt(tau / rho);
2791 sig_u = 1e-2 + 2.0 * ustar * (1.0 - zratio);
2792 sig_w = 1e-2 + 1.3 * ustar * (1.0 - zratio);
2795 dsigw_dz = -1.3 * ustar / zi;
2798 tau_u = 0.07 * zi / sig_u * sqrt(zratio);
2799 tau_w = 0.1 * zi / sig_w * pow(zratio, 0.8);
2806 const double wstar =
2807 pow(
G0 /
THETAVIRT(p, t, h2o) * shf / (rho *
CPD) * zi, 1. / 3.);
2811 + sqrt(0.4 *
SQR(wstar) + (5.0 - 4.0 * zratio) *
SQR(ustar));
2812 sig_w = 1e-2 + sqrt(1.2 *
SQR(wstar) * (1.0 - 0.9 * zratio)
2813 * pow(zratio, 2.0 / 3.0)
2814 + (1.8 - 1.4 * zratio) *
SQR(ustar));
2817 dsigw_dz = 0.5 / sig_w / zi * (-1.4 *
SQR(ustar) +
SQR(wstar)
2819 pow(
MAX(zratio, 1e-3), -1.0 / 3.0)
2820 - 1.8 * pow(zratio, 2.0 / 3.0)));
2823 const double C0 = 3.0;
2825 (1.5 - 1.2 * pow(zratio, 1.0 / 3.0)) *
SQR(wstar) * wstar / zi
2826 +
SQR(ustar) * ustar * (1.0 - 0.8 * zratio) / (
KARMAN * z);
2827 tau_u = 2 *
SQR(sig_u) / (C0 * eps);
2828 tau_w = 2 *
SQR(sig_w) / (C0 * eps);
2833 sig_u =
MAX(sig_u, 0.25);
2834 sig_w =
MAX(sig_w, 0.1);
2835 tau_u =
MAX(tau_u, 300.);
2836 tau_w =
MAX(tau_w, 100.);
2839 const double ru = exp(-fabs(cache->
dt[ip]) / tau_u);
2840 const double ru2 = sqrt(1.0 -
SQR(ru));
2842 = (float) (cache->
uvwp[ip][0] * ru + ru2 * cache->
rs[3 * ip]);
2844 = (float) (cache->
uvwp[ip][1] * ru + ru2 * cache->
rs[3 * ip + 1]);
2846 const double rw = exp(-fabs(cache->
dt[ip]) / tau_w);
2847 const double rw2 = sqrt(1.0 -
SQR(rw));
2849 = (float) (cache->
uvwp[ip][2] * rw + rw2 * cache->
rs[3 * ip + 2]
2850 + sig_w * dsigw_dz * cache->
dt[ip]);
2857 DZ2DP(cache->
uvwp[ip][2] * cache->
dt[ip] / 1000., atm->
p[ip]);
2879 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2888 const double wpbl =
pbl_weight(ctl, atm, ip, pbl, ps);
2889 const double wtrop =
tropo_weight(clim, atm, ip) * (1.0 - wpbl);
2890 const double wstrat = 1.0 - wpbl - wtrop;
2900 const double sigma = sqrt(2.0 * dx * fabs(cache->
dt[ip])) / 1000.;
2902 atm->
lat[ip] +=
DY2DEG(cache->
rs[3 * ip + 1] * sigma);
2907 const double sigma = sqrt(2.0 * dz * fabs(cache->
dt[ip])) / 1000.;
2908 atm->
p[ip] +=
DZ2DP(cache->
rs[3 * ip + 2] * sigma, atm->
p[ip]);
2927 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
2930 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2942 const double dz = 1000. * (
Z(ps - ctl->
dry_depo_dp) -
Z(ps));
2962 const double aux = exp(-cache->
dt[ip] * v_dep / dz);
2963 if (ctl->
qnt_m >= 0) {
2966 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
2967 atm->
q[ctl->
qnt_m][ip] *= aux;
2991 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
2994 const double a = 3.12541941e-06;
2995 const double b = -5.72532259e-01;
2996 const double low = pow(1. / a, 1. / b);
3000 "acc data present(ctl,cache,ctl,met0,met1,atm)") {
3007 if (!(lwc > 0 || rwc > 0))
3018 const double k = 9.1e7 * exp(-29700. /
RI * (1. / t - 1. / 298.15));
3021 const double H_SO2 =
3022 1.3e-2 * exp(2900. * (1. / t - 1. / 298.15)) *
RI * t;
3023 const double K_1S = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
3026 const double H_h2o2 =
3027 8.3e2 * exp(7600. * (1. / t - 1. / 298.15)) *
RI * t;
3033 cor = atm->
q[ctl->
qnt_Cx][ip] >
3034 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
3036 const double h2o2 = H_h2o2
3038 * M * cor * 1000. /
AVO;
3041 const double rho_air = atm->
p[ip] / (
RI * t) *
MA / 10.;
3042 const double CWC = (lwc + rwc) * rho_air / 1e3;
3045 const double rate_coef = k * K_1S * h2o2 * H_SO2 * CWC;
3046 const double aux = exp(-cache->
dt[ip] * rate_coef);
3047 if (ctl->
qnt_m >= 0) {
3050 atm->
q[ctl->
qnt_m][ip] *= aux;
3071 SELECT_TIMER(
"MODULE_ISOSURF_INIT",
"PHYSICS", NVTX_GPU);
3082 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
3085 cache->
iso_var[ip] = atm->
p[ip] / t;
3091 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
3102 LOG(1,
"Read balloon pressure data: %s", ctl->
balloon);
3106 if (!(in = fopen(ctl->
balloon,
"r")))
3107 ERRMSG(
"Cannot open file!");
3111 while (fgets(line,
LEN, in))
3112 if (sscanf(line,
"%lg %lg", &(cache->
iso_ts[cache->
iso_n]),
3115 ERRMSG(
"Too many data points!");
3118 if (cache->
iso_n < 1)
3119 ERRMSG(
"Could not read any data!");
3142 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,met1,atm)") {
3155 atm->
p[ip] = cache->
iso_var[ip] * t;
3161 atm->
p[ip] = 1000. * pow(cache->
iso_var[ip] / t, -1. / 0.286);
3167 atm->
p[ip] = cache->
iso_ps[0];
3194 const int nvar = NVAR, nfix = NFIX, nreact = NREACT;
3195 double rtol[1] = { 1.0e-3 };
3196 double atol[1] = { 1.0 };
3200#pragma acc data copy(rtol,atol,nvar,nfix,nreact)
3203 "acc data present(ctl,cache,clim,met0,met1,atm) ") {
3206 double var[nvar], fix[nfix], rconst[nreact];
3207 for (
int i = 0; i < nvar; i++)
3209 for (
int i = 0; i < nfix; i++)
3211 for (
int i = 0; i < nreact; i++)
3213 kpp_chem_initialize(ctl, clim, met0, met1, atm, var, fix, rconst, ip);
3218 for (
int i = 0; i < 20; i++) {
3225 Rosenbrock(var, fix, rconst, 0, ctl->
dt_kpp,
3226 atol, rtol, &FunTemplate, &JacTemplate, rpar, ipar);
3229 kpp_chem_output2atm(atm, ctl, met0, met1, var, ip);
3250 ERRMSG(
"Need T_ice and T_NAT to calculate T_STS!");
3254 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3256 double ps, ts, zs, us, vs, ess, nss, shf, lsm, sst, pbl, pt, pct, pcb, cl,
3257 plcl, plfc, pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot, o3, lwc,
3258 rwc, iwc, swc, cc, z, zt;
3306 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
3308 atm->
lat[ip], atm->
p[ip]));
3310 atm->
lat[ip], atm->
p[ip]));
3312 atm->
lat[ip], atm->
p[ip]));
3313 SET_ATM(qnt_vh, sqrt(u * u + v * v));
3332 atm->
lat[ip], atm->
p[ip])));
3350 const int np = atm->
np;
3351 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
3352 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
3353 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
3361 const double t0 = t - 0.5 * ctl->
dt_mod;
3362 const double t1 = t + 0.5 * ctl->
dt_mod;
3366#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
3367#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
3368#pragma acc parallel loop independent gang vector
3370#pragma omp parallel for default(shared)
3372 for (
int ip = 0; ip < np; ip++) {
3375 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
mixing_z0) / dz);
3376 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
3377 || ixs[ip] < 0 || ixs[ip] >= ctl->
mixing_nx
3378 || iys[ip] < 0 || iys[ip] >= ctl->
mixing_ny
3379 || izs[ip] < 0 || izs[ip] >= ctl->
mixing_nz)
3384 if (ctl->
qnt_m >= 0)
3421#pragma acc exit data delete(ixs,iys,izs)
3437 const int qnt_idx) {
3440 const int np = atm->
np;
3442 double *restrict
const cmean =
3443 (
double *) malloc((
size_t) ngrid *
sizeof(double));
3444 int *restrict
const count = (
int *) malloc((
size_t) ngrid *
sizeof(int));
3448#pragma acc enter data create(cmean[0:ngrid],count[0:ngrid])
3449#pragma acc data present(ctl,clim,atm,ixs,iys,izs,cmean,count)
3450#pragma acc parallel loop independent gang vector
3455#pragma omp parallel for
3457 for (
int i = 0; i < ngrid; i++) {
3464#pragma acc parallel loop independent gang vector
3466 for (
int ip = 0; ip < np; ip++)
3471#pragma acc atomic update
3473 cmean[idx] += atm->
q[qnt_idx][ip];
3475#pragma acc atomic update
3480#pragma acc parallel loop independent gang vector
3485#pragma omp parallel for
3487 for (
int i = 0; i < ngrid; i++)
3489 cmean[i] /= count[i];
3493#pragma acc parallel loop independent gang vector
3495#pragma omp parallel for
3497 for (
int ip = 0; ip < np; ip++)
3501 double mixparam = 1.0;
3508 atm->
q[qnt_idx][ip] +=
3511 - atm->
q[qnt_idx][ip]) * mixparam;
3516#pragma acc exit data delete(cmean,count)
3537 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3540 const double a = 4.71572206e-08;
3541 const double b = -8.28782867e-01;
3542 const double low = pow(1. / a, 1. / b);
3546 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3572 0 ? pow(298. / t, ctl->
oh_chem[1]) : 1.);
3575 0 ? pow(298. / t, ctl->
oh_chem[3]) : 1.);
3576 const double c = log10(k0 * M / ki);
3577 k = k0 * M / (1. + k0 * M / ki) * pow(0.6, 1. / (1. + c * c));
3586 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
3589 const double rate_coef =
3591 atm->
lat[ip], atm->
p[ip]) * M * cor;
3592 const double aux = exp(-cache->
dt[ip] * rate_coef);
3593 if (ctl->
qnt_m >= 0) {
3596 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
3597 atm->
q[ctl->
qnt_m][ip] *= aux;
3618 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(cache,met0,met1,atm)") {
3629 while (atm->
lat[ip] < -90 || atm->
lat[ip] > 90) {
3630 if (atm->
lat[ip] > 90) {
3631 atm->
lat[ip] = 180 - atm->
lat[ip];
3632 atm->
lon[ip] += 180;
3634 if (atm->
lat[ip] < -90) {
3635 atm->
lat[ip] = -180 - atm->
lat[ip];
3636 atm->
lon[ip] += 180;
3641 while (atm->
lon[ip] < -180)
3642 atm->
lon[ip] += 360;
3643 while (atm->
lon[ip] >= 180)
3644 atm->
lon[ip] -= 360;
3647 if (atm->
p[ip] < met0->
p[met0->
np - 1]) {
3648 atm->
p[ip] = met0->
p[met0->
np - 1];
3649 }
else if (atm->
p[ip] > 300.) {
3651 if (atm->
p[ip] > ps)
3663 gsl_rng_env_setup();
3664 if (omp_get_max_threads() >
NTHREADS)
3665 ERRMSG(
"Too many threads!");
3666 for (
int i = 0; i <
NTHREADS; i++) {
3667 rng[i] = gsl_rng_alloc(gsl_rng_default);
3668 gsl_rng_set(rng[i], gsl_rng_default_seed
3669 + (
long unsigned) (ntask *
NTHREADS + i));
3674 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
3675 CURAND_STATUS_SUCCESS)
3676 ERRMSG(
"Cannot create random number generator!");
3677 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
3678 CURAND_STATUS_SUCCESS)
3679 ERRMSG(
"Cannot set seed for random number generator!");
3682 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
3683 CURAND_STATUS_SUCCESS)
3684 ERRMSG(
"Cannot set stream for random number generator!");
3701#pragma omp parallel for default(shared)
3702 for (
size_t i = 0; i < n; ++i)
3703 rs[i] = gsl_rng_uniform(rng[omp_get_thread_num()]);
3707 else if (method == 1) {
3708#pragma omp parallel for default(shared)
3709 for (
size_t i = 0; i < n; ++i)
3710 rs[i] = gsl_ran_gaussian_ziggurat(rng[omp_get_thread_num()], 1.0);
3716#pragma acc update device(rs[:n])
3724 const uint64_t key = 0xc8e4fd154ce32f6d;
3728#pragma acc data present(rs)
3729#pragma acc parallel loop independent gang vector
3731#pragma omp parallel for default(shared)
3733 for (
size_t i = 0; i < n + 1; ++i) {
3734 uint64_t r, t, x, y, z;
3735 y = x = (rng_ctr + i) * key;
3738 x = (x >> 32) | (x << 32);
3740 x = (x >> 32) | (x << 32);
3742 x = (x >> 32) | (x << 32);
3744 x = (x >> 32) | (x << 32);
3745 r = t ^ ((x * x + y) >> 32);
3746 rs[i] = (double) r / (
double) UINT64_MAX;
3753#pragma acc parallel loop independent gang vector
3755#pragma omp parallel for default(shared)
3757 for (
size_t i = 0; i < n; i += 2) {
3758 const double r = sqrt(-2.0 * log(rs[i]));
3759 const double phi = 2.0 * M_PI * rs[i + 1];
3760 rs[i] = r * cosf((
float) phi);
3761 rs[i + 1] = r * sinf((
float) phi);
3769#pragma acc host_data use_device(rs)
3774 if (curandGenerateUniformDouble(rng_curand, rs, (n < 4 ? 4 : n)) !=
3775 CURAND_STATUS_SUCCESS)
3776 ERRMSG(
"Cannot create random numbers!");
3780 else if (method == 1) {
3781 if (curandGenerateNormalDouble
3782 (rng_curand, rs, (n < 4 ? 4 : n), 0.0,
3783 1.0) != CURAND_STATUS_SUCCESS)
3784 ERRMSG(
"Cannot create random numbers!");
3788 ERRMSG(
"MPTRAC was compiled without cuRAND!");
3806 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3814 const double v_s =
sedi(atm->
p[ip], t, atm->
q[ctl->
qnt_rp][ip],
3818 atm->
p[ip] +=
DZ2DP(v_s * cache->
dt[ip] / 1000., atm->
p[ip]);
3833 const int np = atm->
np;
3834 double *restrict
const a = (
double *) malloc((
size_t) np *
sizeof(double));
3835 int *restrict
const p = (
int *) malloc((
size_t) np *
sizeof(int));
3838#pragma acc enter data create(a[0:np],p[0:np])
3839#pragma acc data present(ctl,met0,atm,a,p)
3844#pragma acc parallel loop independent gang vector
3846#pragma omp parallel for default(shared)
3848 for (
int ip = 0; ip < np; ip++) {
3858#pragma acc host_data use_device(a,p)
3863 ERRMSG(
"MPTRAC was compiled without Thrust library!");
3871 for (
int iq = 0; iq < ctl->
nq; iq++)
3876#pragma acc exit data delete(a,p)
3890 double *restrict
const help =
3891 (
double *) malloc((
size_t) np *
sizeof(double));
3895#pragma acc enter data create(help[0:np])
3896#pragma acc data present(a,p,help)
3897#pragma acc parallel loop independent gang vector
3899#pragma omp parallel for default(shared)
3901 for (
int ip = 0; ip < np; ip++)
3902 help[ip] = a[p[ip]];
3904#pragma acc parallel loop independent gang vector
3906#pragma omp parallel for default(shared)
3908 for (
int ip = 0; ip < np; ip++)
3913#pragma acc exit data delete(help)
3930 const double latmin = gsl_stats_min(met0->
lat, 1, (
size_t) met0->
ny),
3931 latmax = gsl_stats_max(met0->
lat, 1, (
size_t) met0->
ny);
3934 (fabs(met0->
lon[met0->
nx - 1] - met0->
lon[0] - 360.0) >= 0.01);
3937 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,atm)") {
3943 cache->
dt[ip] = t - atm->
time[ip];
3945 cache->
dt[ip] = 0.0;
3948 if (local && (atm->
lon[ip] <= met0->
lon[0]
3949 || atm->
lon[ip] >= met0->
lon[met0->
nx - 1]
3950 || atm->
lat[ip] <= latmin || atm->
lat[ip] >= latmax))
3951 cache->
dt[ip] = 0.0;
3962 SELECT_TIMER(
"MODULE_TIMESTEPS_INIT",
"PHYSICS", NVTX_GPU);
3966 ctl->
t_start = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
3968 ctl->
t_stop = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
3970 ctl->
t_start = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
3972 ctl->
t_stop = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
3977 ERRMSG(
"Nothing to do! Check T_STOP and DIRECTION!");
3997 SELECT_TIMER(
"MODULE_TRACER_CHEM",
"PHYSICS", NVTX_GPU);
4001 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4024 const double K_o1d =
ARRHENIUS(3.30e-10, 0, t) * o1d * M;
4026 atm->
p[ip], sza, o3c);
4027 atm->
q[ctl->
qnt_Cccl4][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4032 const double K_o1d =
ARRHENIUS(2.30e-10, 0, t) * o1d * M;
4034 atm->
p[ip], sza, o3c);
4035 atm->
q[ctl->
qnt_Cccl3f][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4040 const double K_o1d =
ARRHENIUS(1.40e-10, -25, t) * o1d * M;
4042 atm->
p[ip], sza, o3c);
4043 atm->
q[ctl->
qnt_Cccl2f2][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4048 const double K_o1d =
ARRHENIUS(1.19e-10, -20, t) * o1d * M;
4050 atm->
p[ip], sza, o3c);
4051 atm->
q[ctl->
qnt_Cn2o][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4070 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4073 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4079 if (!isfinite(pct) || atm->
p[ip] <= pct)
4095 double lwc, rwc, iwc, swc;
4100 const int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
4114 else if (t <= 238.15)
4134 const double K_1 = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
4135 const double K_2 = 6e-8 * exp(1.12e3 * (1. / t - 1. / 298.15));
4136 h *= (1. + K_1 / H_ion + K_1 * K_2 /
SQR(H_ion));
4140 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
4143 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
4169 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
4172 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
4177 const double aux = exp(-cache->
dt[ip] * lambda);
4178 if (ctl->
qnt_m >= 0) {
4181 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
4182 atm->
q[ctl->
qnt_m][ip] *= aux;
4206 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
4208 if (acc_get_num_devices(acc_device_nvidia) <= 0)
4209 ERRMSG(
"Not running on a GPU device!");
4210 acc_set_device_num(rank % acc_get_num_devices(acc_device_nvidia),
4212 acc_device_t device_type = acc_get_device_type();
4213 acc_init(device_type);
4227 SELECT_TIMER(
"CREATE_DATA_REGION",
"MEMORY", NVTX_GPU);
4228 ctl_t *ctlup = *ctl;
4231 met_t *met0up = *met0;
4232 met_t *met1up = *met1;
4233 atm_t *atmup = *atm;
4234#pragma acc enter data create(ctlup[:1],cacheup[:1],climup[:1],met0up[:1],met1up[:1],atmup[:1])
4250 SELECT_TIMER(
"DELETE_DATA_REGION",
"MEMORY", NVTX_GPU);
4251#pragma acc exit data delete (ctl,cache,clim,met0,met1,atm)
4277 char cachefile[
LEN], cmd[2 *
LEN], filename[
LEN];
4283 if (t == ctl->
t_start || !init) {
4290 ERRMSG(
"Cannot open file!");
4295 ERRMSG(
"Cannot open file!");
4305 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
4306 LOG(1,
"Caching: %s", cachefile);
4307 if (system(cmd) != 0)
4308 WARN(
"Caching command failed!");
4313 if (t > (*met1)->time) {
4323 ERRMSG(
"Cannot open file!");
4333 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
4334 LOG(1,
"Caching: %s", cachefile);
4335 if (system(cmd) != 0)
4336 WARN(
"Caching command failed!");
4341 if (t < (*met0)->time) {
4351 ERRMSG(
"Cannot open file!");
4361 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
4362 LOG(1,
"Caching: %s", cachefile);
4363 if (system(cmd) != 0)
4364 WARN(
"Caching command failed!");
4369 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
4370 if ((*met0)->nx != (*met1)->nx
4371 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
4372 ERRMSG(
"Meteo grid dimensions do not match!");
4373 for (
int ix = 0; ix < (*met0)->nx; ix++)
4374 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
4375 ERRMSG(
"Meteo grid longitudes do not match!");
4376 for (
int iy = 0; iy < (*met0)->ny; iy++)
4377 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
4378 ERRMSG(
"Meteo grid latitudes do not match!");
4379 for (
int ip = 0; ip < (*met0)->np; ip++)
4380 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
4381 ERRMSG(
"Meteo grid pressure levels do not match!");
4407 const char *filename,
4420 LOG(1,
"Read atmospheric data: %s", filename);
4440 ERRMSG(
"Atmospheric data type not supported!");
4448 ERRMSG(
"Can not read any data!");
4452 LOG(2,
"Number of particles: %d", atm->
np);
4453 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
4454 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
4455 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
4456 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
4457 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
4458 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
4459 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
4460 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
4461 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
4462 for (
int iq = 0; iq < ctl->
nq; iq++) {
4464 sprintf(msg,
"Quantity %s range: %s ... %s %s",
4467 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
4468 LOG(2, msg, mini, maxi);
4538 const char *filename,
4547 LOG(1,
"\nMassive-Parallel Trajectory Calculations (MPTRAC)\n"
4548 "(executable: %s | version: %s | compiled: %s, %s)\n",
4549 argv[0], VERSION, __DATE__, __TIME__);
4645 ctl->
nq = (int)
scan_ctl(filename, argc, argv,
"NQ", -1,
"0", NULL);
4647 ERRMSG(
"Too many quantities!");
4648 for (
int iq = 0; iq < ctl->
nq; iq++) {
4654 scan_ctl(filename, argc, argv,
"QNT_FORMAT", iq,
"%g",
4656 if (strcasecmp(ctl->
qnt_name[iq],
"aoa") == 0)
4660 SET_QNT(qnt_idx,
"idx",
"particle index",
"-")
4661 SET_QNT(qnt_ens,
"ens",
"ensemble index",
"-")
4662 SET_QNT(qnt_stat,
"stat",
"station flag",
"-")
4663 SET_QNT(qnt_m,
"m",
"mass",
"kg")
4664 SET_QNT(qnt_vmr,
"vmr",
"volume mixing ratio",
"ppv")
4665 SET_QNT(qnt_rp,
"rp",
"particle radius",
"microns")
4666 SET_QNT(qnt_rhop,
"rhop",
"particle density",
"kg/m^3")
4667 SET_QNT(qnt_ps,
"ps",
"surface pressure",
"hPa")
4668 SET_QNT(qnt_ts,
"ts",
"surface temperature",
"K")
4669 SET_QNT(qnt_zs,
"zs",
"surface height",
"km")
4670 SET_QNT(qnt_us,
"us",
"surface zonal wind",
"m/s")
4671 SET_QNT(qnt_vs,
"vs",
"surface meridional wind",
"m/s")
4672 SET_QNT(qnt_ess,
"ess",
"eastward turbulent surface stress",
"N/m^2")
4673 SET_QNT(qnt_nss,
"nss",
"northward turbulent surface stress",
"N/m^2")
4674 SET_QNT(qnt_shf,
"shf",
"surface sensible heat flux",
"W/m^2")
4675 SET_QNT(qnt_lsm,
"lsm",
"land-sea mask",
"1")
4676 SET_QNT(qnt_sst,
"sst",
"sea surface temperature",
"K")
4677 SET_QNT(qnt_pbl,
"pbl",
"planetary boundary layer",
"hPa")
4678 SET_QNT(qnt_pt,
"pt",
"tropopause pressure",
"hPa")
4679 SET_QNT(qnt_tt,
"tt",
"tropopause temperature",
"K")
4680 SET_QNT(qnt_zt,
"zt",
"tropopause geopotential height",
"km")
4681 SET_QNT(qnt_h2ot,
"h2ot",
"tropopause water vapor",
"ppv")
4682 SET_QNT(qnt_zg,
"zg",
"geopotential height",
"km")
4683 SET_QNT(qnt_p,
"p",
"pressure",
"hPa")
4684 SET_QNT(qnt_t,
"t",
"temperature",
"K")
4685 SET_QNT(qnt_rho,
"rho",
"air density",
"kg/m^3")
4686 SET_QNT(qnt_u,
"u",
"zonal wind",
"m/s")
4687 SET_QNT(qnt_v,
"v",
"meridional wind",
"m/s")
4688 SET_QNT(qnt_w,
"w",
"vertical velocity",
"hPa/s")
4689 SET_QNT(qnt_h2o,
"h2o",
"water vapor",
"ppv")
4690 SET_QNT(qnt_o3,
"o3",
"ozone",
"ppv")
4691 SET_QNT(qnt_lwc,
"lwc",
"cloud liquid water content",
"kg/kg")
4692 SET_QNT(qnt_rwc,
"rwc",
"cloud rain water content",
"kg/kg")
4693 SET_QNT(qnt_iwc,
"iwc",
"cloud ice water content",
"kg/kg")
4694 SET_QNT(qnt_swc,
"swc",
"cloud snow water content",
"kg/kg")
4695 SET_QNT(qnt_cc,
"cc",
"cloud cover",
"1")
4696 SET_QNT(qnt_pct,
"pct",
"cloud top pressure",
"hPa")
4697 SET_QNT(qnt_pcb,
"pcb",
"cloud bottom pressure",
"hPa")
4698 SET_QNT(qnt_cl,
"cl",
"total column cloud water",
"kg/m^2")
4699 SET_QNT(qnt_plcl,
"plcl",
"lifted condensation level",
"hPa")
4700 SET_QNT(qnt_plfc,
"plfc",
"level of free convection",
"hPa")
4701 SET_QNT(qnt_pel,
"pel",
"equilibrium level",
"hPa")
4702 SET_QNT(qnt_cape,
"cape",
"convective available potential energy",
4704 SET_QNT(qnt_cin,
"cin",
"convective inhibition",
"J/kg")
4705 SET_QNT(qnt_o3c,
"o3c",
"total column ozone",
"DU")
4706 SET_QNT(qnt_hno3,
"hno3",
"nitric acid",
"ppv")
4707 SET_QNT(qnt_oh,
"oh",
"hydroxyl radical",
"ppv")
4708 SET_QNT(qnt_h2o2,
"h2o2",
"hydrogen peroxide",
"ppv")
4709 SET_QNT(qnt_ho2,
"ho2",
"hydroperoxyl radical",
"ppv")
4710 SET_QNT(qnt_o1d,
"o1d",
"atomic oxygen",
"ppv")
4711 SET_QNT(qnt_mloss_oh,
"mloss_oh",
"mass loss due to OH chemistry",
"kg")
4712 SET_QNT(qnt_mloss_h2o2,
"mloss_h2o2",
"mass loss due to H2O2 chemistry",
4714 SET_QNT(qnt_mloss_kpp,
"mloss_kpp",
"mass loss due to kpp chemistry",
4716 SET_QNT(qnt_mloss_wet,
"mloss_wet",
"mass loss due to wet deposition",
4718 SET_QNT(qnt_mloss_dry,
"mloss_dry",
"mass loss due to dry deposition",
4720 SET_QNT(qnt_mloss_decay,
"mloss_decay",
4721 "mass loss due to exponential decay",
"kg")
4722 SET_QNT(qnt_loss_rate,
"loss_rate",
"total loss rate",
"s^-1")
4723 SET_QNT(qnt_psat,
"psat",
"saturation pressure over water",
"hPa")
4724 SET_QNT(qnt_psice,
"psice",
"saturation pressure over ice",
"hPa")
4725 SET_QNT(qnt_pw,
"pw",
"partial water vapor pressure",
"hPa")
4726 SET_QNT(qnt_sh,
"sh",
"specific humidity",
"kg/kg")
4727 SET_QNT(qnt_rh,
"rh",
"relative humidity",
"%%")
4728 SET_QNT(qnt_rhice,
"rhice",
"relative humidity over ice",
"%%")
4729 SET_QNT(qnt_theta,
"theta",
"potential temperature",
"K")
4730 SET_QNT(qnt_zeta,
"zeta",
"zeta coordinate",
"K")
4731 SET_QNT(qnt_zeta_d,
"zeta_d",
"diagnosed zeta coordinate",
"K")
4732 SET_QNT(qnt_tvirt,
"tvirt",
"virtual temperature",
"K")
4733 SET_QNT(qnt_lapse,
"lapse",
"temperature lapse rate",
"K/km")
4734 SET_QNT(qnt_vh,
"vh",
"horizontal velocity",
"m/s")
4735 SET_QNT(qnt_vz,
"vz",
"vertical velocity",
"m/s")
4736 SET_QNT(qnt_pv,
"pv",
"potential vorticity",
"PVU")
4737 SET_QNT(qnt_tdew,
"tdew",
"dew point temperature",
"K")
4738 SET_QNT(qnt_tice,
"tice",
"frost point temperature",
"K")
4739 SET_QNT(qnt_tsts,
"tsts",
"STS existence temperature",
"K")
4740 SET_QNT(qnt_tnat,
"tnat",
"NAT existence temperature",
"K")
4741 SET_QNT(qnt_Cx,
"Cx",
"Trace species x volume mixing ratio",
"ppv")
4742 SET_QNT(qnt_Ch2o,
"Ch2o",
"H2O volume mixing ratio",
"ppv")
4743 SET_QNT(qnt_Co3,
"Co3",
"O3 volume mixing ratio",
"ppv")
4744 SET_QNT(qnt_Cco,
"Cco",
"CO volume mixing ratio",
"ppv")
4745 SET_QNT(qnt_Coh,
"Coh",
"HO volume mixing ratio",
"ppv")
4746 SET_QNT(qnt_Ch,
"Ch",
"H radical volume mixing ratio",
"ppv")
4747 SET_QNT(qnt_Cho2,
"Cho2",
"HO2 volume mixing ratio",
"ppv")
4748 SET_QNT(qnt_Ch2o2,
"Ch2o2",
"H2O2 volume mixing ratio",
"ppv")
4749 SET_QNT(qnt_Co1d,
"Co1d",
"O(1D) volume mixing ratio",
"ppv")
4750 SET_QNT(qnt_Co3p,
"Co3p",
"O(3P) radical volume mixing ratio",
"ppv")
4751 SET_QNT(qnt_Cccl4,
"Cccl4",
"CCl4 (CFC-10) volume mixing ratio",
"ppv")
4752 SET_QNT(qnt_Cccl3f,
"Cccl3f",
"CCl3F (CFC-11) volume mixing ratio",
4754 SET_QNT(qnt_Cccl2f2,
"Cccl2f2",
"CCl2F2 (CFC-12) volume mixing ratio",
4756 SET_QNT(qnt_Cn2o,
"Cn2o",
"N2O volume mixing ratio",
"ppv")
4757 SET_QNT(qnt_Csf6,
"Csf6",
"SF6 volume mixing ratio",
"ppv")
4758 SET_QNT(qnt_aoa,
"aoa",
"age of air",
"s")
4764 (int)
scan_ctl(filename, argc, argv,
"ADVECT_VERT_COORD", -1,
"0", NULL);
4766 ERRMSG(
"Set ADVECT_VERT_COORD to 0, 1, or 2!");
4768 (int)
scan_ctl(filename, argc, argv,
"MET_VERT_COORD", -1,
"0", NULL);
4770 ERRMSG(
"Set MET_VERT_COORD to 0, 1, 2, 3, or 4!");
4772 ERRMSG(
"Please add zeta to your quantities for diabatic calculations!");
4775 (
"Using ADVECT_VERT_COORD = 2 requires meteo data on model levels!");
4779 (int)
scan_ctl(filename, argc, argv,
"DIRECTION", -1,
"1", NULL);
4781 ERRMSG(
"Set DIRECTION to -1 or 1!");
4782 ctl->
t_stop =
scan_ctl(filename, argc, argv,
"T_STOP", -1,
"1e100", NULL);
4783 ctl->
dt_mod =
scan_ctl(filename, argc, argv,
"DT_MOD", -1,
"180", NULL);
4787 ctl->
dt_met =
scan_ctl(filename, argc, argv,
"DT_MET", -1,
"3600", NULL);
4789 (int)
scan_ctl(filename, argc, argv,
"MET_CONVENTION", -1,
"0", NULL);
4791 (int)
scan_ctl(filename, argc, argv,
"MET_TYPE", -1,
"0", NULL);
4794 (
"Please use meteo files in netcdf format for diabatic calculations.");
4796 (int)
scan_ctl(filename, argc, argv,
"MET_CLAMS", -1,
"0", NULL);
4798 (int)
scan_ctl(filename, argc, argv,
"MET_NC_SCALE", -1,
"1", NULL);
4800 (int)
scan_ctl(filename, argc, argv,
"MET_NC_LEVEL", -1,
"0", NULL);
4802 (int)
scan_ctl(filename, argc, argv,
"MET_NC_QUANT", -1,
"0", NULL);
4804 (int)
scan_ctl(filename, argc, argv,
"MET_ZSTD_LEVEL", -1,
"0", NULL);
4806 (int)
scan_ctl(filename, argc, argv,
"MET_ZFP_PREC", -1,
"8", NULL);
4808 scan_ctl(filename, argc, argv,
"MET_ZFP_TOL_T", -1,
"5.0", NULL);
4810 scan_ctl(filename, argc, argv,
"MET_ZFP_TOL_Z", -1,
"0.5", NULL);
4812 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_BATCH", -1,
"-1", NULL);
4814 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ZSTD", -1,
"1", NULL);
4816 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_HEUR", -1,
"1", NULL);
4818 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_Z", -1,
"1.0", NULL);
4820 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_T", -1,
"0.05", NULL);
4822 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_U", -1,
"0.05", NULL);
4824 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_V", -1,
"0.05", NULL);
4826 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_W", -1,
"1.0", NULL);
4828 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_PV", -1,
"1.0", NULL);
4830 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_H2O", -1,
"1.0", NULL);
4832 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_O3", -1,
"1.0", NULL);
4834 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_LWC", -1,
"1.0", NULL);
4836 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_RWC", -1,
"1.0", NULL);
4838 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_IWC", -1,
"1.0", NULL);
4840 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_SWC", -1,
"1.0", NULL);
4842 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_CC", -1,
"1.0", NULL);
4843 ctl->
met_dx = (int)
scan_ctl(filename, argc, argv,
"MET_DX", -1,
"1", NULL);
4844 ctl->
met_dy = (int)
scan_ctl(filename, argc, argv,
"MET_DY", -1,
"1", NULL);
4845 ctl->
met_dp = (int)
scan_ctl(filename, argc, argv,
"MET_DP", -1,
"1", NULL);
4847 ERRMSG(
"MET_DX, MET_DY, and MET_DP need to be greater than zero!");
4848 ctl->
met_sx = (int)
scan_ctl(filename, argc, argv,
"MET_SX", -1,
"1", NULL);
4849 ctl->
met_sy = (int)
scan_ctl(filename, argc, argv,
"MET_SY", -1,
"1", NULL);
4850 ctl->
met_sp = (int)
scan_ctl(filename, argc, argv,
"MET_SP", -1,
"1", NULL);
4852 ERRMSG(
"MET_SX, MET_SY, and MET_SP need to be greater than zero!");
4854 scan_ctl(filename, argc, argv,
"MET_DETREND", -1,
"-999", NULL);
4855 ctl->
met_np = (int)
scan_ctl(filename, argc, argv,
"MET_NP", -1,
"0", NULL);
4857 ERRMSG(
"Too many pressure levels!");
4859 (int)
scan_ctl(filename, argc, argv,
"MET_PRESS_LEVEL_DEF", -1,
"-1",
4865 for (
int ip = 0; ip < ctl->
met_np; ip++)
4867 scan_ctl(filename, argc, argv,
"MET_P", ip,
"", NULL);
4871 (int)
scan_ctl(filename, argc, argv,
"MET_NLEV", -1,
"0", NULL);
4873 ERRMSG(
"Too many model levels!");
4874 for (
int ip = 0; ip < ctl->
met_nlev; ip++) {
4876 scan_ctl(filename, argc, argv,
"MET_LEV_HYAM", ip,
"", NULL);
4878 scan_ctl(filename, argc, argv,
"MET_LEV_HYBM", ip,
"", NULL);
4881 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SX", -1,
"-1", NULL);
4883 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SY", -1,
"-1", NULL);
4885 (int)
scan_ctl(filename, argc, argv,
"MET_RELHUM", -1,
"0", NULL);
4887 (int)
scan_ctl(filename, argc, argv,
"MET_CAPE", -1,
"1", NULL);
4889 ERRMSG(
"Set MET_CAPE to 0 or 1!");
4891 (int)
scan_ctl(filename, argc, argv,
"MET_PBL", -1,
"3", NULL);
4893 ERRMSG(
"Set MET_PBL to 0 ... 3!");
4895 scan_ctl(filename, argc, argv,
"MET_PBL_MIN", -1,
"0.1", NULL);
4897 scan_ctl(filename, argc, argv,
"MET_PBL_MAX", -1,
"5.0", NULL);
4899 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO", -1,
"3", NULL);
4901 ERRMSG(
"Set MET_TROPO to 0 ... 5!");
4903 scan_ctl(filename, argc, argv,
"MET_TROPO_PV", -1,
"3.5", NULL);
4905 scan_ctl(filename, argc, argv,
"MET_TROPO_THETA", -1,
"380", NULL);
4907 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO_SPLINE", -1,
"1", NULL);
4909 scan_ctl(filename, argc, argv,
"MET_DT_OUT", -1,
"0.1", NULL);
4911 (int)
scan_ctl(filename, argc, argv,
"MET_CACHE", -1,
"0", NULL);
4913 (int)
scan_ctl(filename, argc, argv,
"MET_MPI_SHARE", -1,
"0", NULL);
4916 ctl->
sort_dt =
scan_ctl(filename, argc, argv,
"SORT_DT", -1,
"-999", NULL);
4920 (int)
scan_ctl(filename, argc, argv,
"ISOSURF", -1,
"0", NULL);
4925 (int)
scan_ctl(filename, argc, argv,
"RNG_TYPE", -1,
"1", NULL);
4927 ERRMSG(
"Set RNG_TYPE to 0, 1, or 2!");
4930 ctl->
advect = (int)
scan_ctl(filename, argc, argv,
"ADVECT", -1,
"2", NULL);
4933 ERRMSG(
"Set ADVECT to 0, 1, 2, or 4!");
4937 = (int)
scan_ctl(filename, argc, argv,
"DIFFUSION", -1,
"0", NULL);
4939 ERRMSG(
"Set DIFFUSION to 0, 1 or 2!");
4941 scan_ctl(filename, argc, argv,
"TURB_DX_PBL", -1,
"50", NULL);
4943 scan_ctl(filename, argc, argv,
"TURB_DX_TROP", -1,
"50", NULL);
4945 scan_ctl(filename, argc, argv,
"TURB_DX_STRAT", -1,
"0", NULL);
4947 scan_ctl(filename, argc, argv,
"TURB_DZ_PBL", -1,
"0", NULL);
4949 scan_ctl(filename, argc, argv,
"TURB_DZ_TROP", -1,
"0", NULL);
4951 scan_ctl(filename, argc, argv,
"TURB_DZ_STRAT", -1,
"0.1", NULL);
4953 scan_ctl(filename, argc, argv,
"TURB_MESOX", -1,
"0.16", NULL);
4955 scan_ctl(filename, argc, argv,
"TURB_MESOZ", -1,
"0.16", NULL);
4959 = (int)
scan_ctl(filename, argc, argv,
"CONV_MIX_PBL", -1,
"0", NULL);
4961 =
scan_ctl(filename, argc, argv,
"CONV_PBL_TRANS", -1,
"0", NULL);
4963 =
scan_ctl(filename, argc, argv,
"CONV_CAPE", -1,
"-999", NULL);
4965 =
scan_ctl(filename, argc, argv,
"CONV_CIN", -1,
"-999", NULL);
4966 ctl->
conv_dt =
scan_ctl(filename, argc, argv,
"CONV_DT", -1,
"-999", NULL);
4970 scan_ctl(filename, argc, argv,
"BOUND_MASS", -1,
"-999", NULL);
4972 scan_ctl(filename, argc, argv,
"BOUND_MASS_TREND", -1,
"0", NULL);
4974 scan_ctl(filename, argc, argv,
"BOUND_VMR", -1,
"-999", NULL);
4976 scan_ctl(filename, argc, argv,
"BOUND_VMR_TREND", -1,
"0", NULL);
4978 scan_ctl(filename, argc, argv,
"BOUND_LAT0", -1,
"-999", NULL);
4980 scan_ctl(filename, argc, argv,
"BOUND_LAT1", -1,
"-999", NULL);
4982 scan_ctl(filename, argc, argv,
"BOUND_P0", -1,
"-999", NULL);
4984 scan_ctl(filename, argc, argv,
"BOUND_P1", -1,
"-999", NULL);
4986 scan_ctl(filename, argc, argv,
"BOUND_DPS", -1,
"-999", NULL);
4988 scan_ctl(filename, argc, argv,
"BOUND_DZS", -1,
"-999", NULL);
4990 scan_ctl(filename, argc, argv,
"BOUND_ZETAS", -1,
"-999", NULL);
4992 (int)
scan_ctl(filename, argc, argv,
"BOUND_PBL", -1,
"0", NULL);
4996 if (strcasecmp(ctl->
species,
"CF2Cl2") == 0) {
5000 }
else if (strcasecmp(ctl->
species,
"CFCl3") == 0) {
5004 }
else if (strcasecmp(ctl->
species,
"CH4") == 0) {
5011 }
else if (strcasecmp(ctl->
species,
"CO") == 0) {
5020 }
else if (strcasecmp(ctl->
species,
"CO2") == 0) {
5024 }
else if (strcasecmp(ctl->
species,
"H2O") == 0) {
5026 }
else if (strcasecmp(ctl->
species,
"N2O") == 0) {
5030 }
else if (strcasecmp(ctl->
species,
"NH3") == 0) {
5037 }
else if (strcasecmp(ctl->
species,
"HNO3") == 0) {
5041 }
else if (strcasecmp(ctl->
species,
"NO") == 0) {
5050 }
else if (strcasecmp(ctl->
species,
"NO2") == 0) {
5059 }
else if (strcasecmp(ctl->
species,
"O3") == 0) {
5066 }
else if (strcasecmp(ctl->
species,
"SF6") == 0) {
5070 }
else if (strcasecmp(ctl->
species,
"SO2") == 0) {
5083 sprintf(defstr,
"%g", ctl->
molmass);
5084 ctl->
molmass =
scan_ctl(filename, argc, argv,
"MOLMASS", -1, defstr, NULL);
5089 (int)
scan_ctl(filename, argc, argv,
"OH_CHEM_REACTION", -1, defstr,
5091 for (
int ip = 0; ip < 4; ip++) {
5092 sprintf(defstr,
"%g", ctl->
oh_chem[ip]);
5094 scan_ctl(filename, argc, argv,
"OH_CHEM", ip, defstr, NULL);
5097 scan_ctl(filename, argc, argv,
"OH_CHEM_BETA", -1,
"0", NULL);
5101 (int)
scan_ctl(filename, argc, argv,
"H2O2_CHEM_REACTION", -1,
"0", NULL);
5105 (int)
scan_ctl(filename, argc, argv,
"KPP_CHEM", -1,
"0", NULL);
5106 ctl->
dt_kpp =
scan_ctl(filename, argc, argv,
"DT_KPP", -1,
"1800", NULL);
5110 (int)
scan_ctl(filename, argc, argv,
"TRACER_CHEM", -1,
"0", NULL);
5113 for (
int ip = 0; ip < 2; ip++) {
5116 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_H", ip, defstr, NULL);
5118 for (
int ip = 0; ip < 1; ip++) {
5121 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_H", ip, defstr, NULL);
5124 scan_ctl(filename, argc, argv,
"WET_DEPO_SO2_PH", -1,
"0", NULL);
5126 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_A", -1,
"0", NULL);
5128 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_B", -1,
"0", NULL);
5130 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_A", -1,
"0", NULL);
5132 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_B", -1,
"0", NULL);
5134 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 0,
"0.5", NULL);
5136 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 1,
"0.36", NULL);
5138 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_RET_RATIO", -1,
"1", NULL);
5140 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_RET_RATIO", -1,
"1", NULL);
5144 scan_ctl(filename, argc, argv,
"DRY_DEPO_VDEP", -1,
"0", NULL);
5146 scan_ctl(filename, argc, argv,
"DRY_DEPO_DP", -1,
"30", NULL);
5149 scan_ctl(filename, argc, argv,
"CLIM_PHOTO", -1,
5150 "../../data/clams_photolysis_rates.nc", ctl->
clim_photo);
5151 scan_ctl(filename, argc, argv,
"CLIM_HNO3_FILENAME", -1,
5153 scan_ctl(filename, argc, argv,
"CLIM_OH_FILENAME", -1,
5155 scan_ctl(filename, argc, argv,
"CLIM_H2O2_FILENAME", -1,
5157 scan_ctl(filename, argc, argv,
"CLIM_HO2_FILENAME", -1,
5159 scan_ctl(filename, argc, argv,
"CLIM_O1D_FILENAME", -1,
5161 scan_ctl(filename, argc, argv,
"CLIM_CCL4_TIMESERIES", -1,
5163 scan_ctl(filename, argc, argv,
"CLIM_CCL3F_TIMESERIES", -1,
5165 scan_ctl(filename, argc, argv,
"CLIM_CCL2F2_TIMESERIES", -1,
5167 scan_ctl(filename, argc, argv,
"CLIM_N2O_TIMESERIES", -1,
5169 scan_ctl(filename, argc, argv,
"CLIM_SF6_TIMESERIES", -1,
5174 scan_ctl(filename, argc, argv,
"MIXING_DT", -1,
"3600.", NULL);
5176 scan_ctl(filename, argc, argv,
"MIXING_TROP", -1,
"-999", NULL);
5178 scan_ctl(filename, argc, argv,
"MIXING_STRAT", -1,
"-999", NULL);
5180 scan_ctl(filename, argc, argv,
"MIXING_Z0", -1,
"-5", NULL);
5182 scan_ctl(filename, argc, argv,
"MIXING_Z1", -1,
"85", NULL);
5184 (int)
scan_ctl(filename, argc, argv,
"MIXING_NZ", -1,
"90", NULL);
5186 scan_ctl(filename, argc, argv,
"MIXING_LON0", -1,
"-180", NULL);
5188 scan_ctl(filename, argc, argv,
"MIXING_LON1", -1,
"180", NULL);
5190 (int)
scan_ctl(filename, argc, argv,
"MIXING_NX", -1,
"360", NULL);
5192 scan_ctl(filename, argc, argv,
"MIXING_LAT0", -1,
"-90", NULL);
5194 scan_ctl(filename, argc, argv,
"MIXING_LAT1", -1,
"90", NULL);
5196 (int)
scan_ctl(filename, argc, argv,
"MIXING_NY", -1,
"180", NULL);
5200 scan_ctl(filename, argc, argv,
"CHEMGRID_Z0", -1,
"-5", NULL);
5202 scan_ctl(filename, argc, argv,
"CHEMGRID_Z1", -1,
"85", NULL);
5204 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NZ", -1,
"90", NULL);
5206 scan_ctl(filename, argc, argv,
"CHEMGRID_LON0", -1,
"-180", NULL);
5208 scan_ctl(filename, argc, argv,
"CHEMGRID_LON1", -1,
"180", NULL);
5210 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NX", -1,
"360", NULL);
5212 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT0", -1,
"-90", NULL);
5214 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT1", -1,
"90", NULL);
5216 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NY", -1,
"180", NULL);
5221 =
scan_ctl(filename, argc, argv,
"TDEC_STRAT", -1,
"0", NULL);
5224 ctl->
psc_h2o =
scan_ctl(filename, argc, argv,
"PSC_H2O", -1,
"4e-6", NULL);
5226 scan_ctl(filename, argc, argv,
"PSC_HNO3", -1,
"9e-9", NULL);
5232 scan_ctl(filename, argc, argv,
"ATM_DT_OUT", -1,
"86400", NULL);
5234 (int)
scan_ctl(filename, argc, argv,
"ATM_FILTER", -1,
"0", NULL);
5236 (int)
scan_ctl(filename, argc, argv,
"ATM_STRIDE", -1,
"1", NULL);
5238 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE", -1,
"0", NULL);
5240 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE_OUT", -1,
"-1", NULL);
5244 (int)
scan_ctl(filename, argc, argv,
"ATM_NC_LEVEL", -1,
"0", NULL);
5245 for (
int iq = 0; iq < ctl->
nq; iq++)
5247 (
int)
scan_ctl(filename, argc, argv,
"ATM_NC_QUANT", iq,
"0", NULL);
5249 (int)
scan_ctl(filename, argc, argv,
"OBS_TYPE", -1,
"0", NULL);
5255 scan_ctl(filename, argc, argv,
"CSI_DT_OUT", -1,
"86400", NULL);
5258 scan_ctl(filename, argc, argv,
"CSI_OBSMIN", -1,
"0", NULL);
5260 scan_ctl(filename, argc, argv,
"CSI_MODMIN", -1,
"0", NULL);
5261 ctl->
csi_z0 =
scan_ctl(filename, argc, argv,
"CSI_Z0", -1,
"-5", NULL);
5262 ctl->
csi_z1 =
scan_ctl(filename, argc, argv,
"CSI_Z1", -1,
"85", NULL);
5263 ctl->
csi_nz = (int)
scan_ctl(filename, argc, argv,
"CSI_NZ", -1,
"1", NULL);
5265 scan_ctl(filename, argc, argv,
"CSI_LON0", -1,
"-180", NULL);
5266 ctl->
csi_lon1 =
scan_ctl(filename, argc, argv,
"CSI_LON1", -1,
"180", NULL);
5268 (int)
scan_ctl(filename, argc, argv,
"CSI_NX", -1,
"360", NULL);
5269 ctl->
csi_lat0 =
scan_ctl(filename, argc, argv,
"CSI_LAT0", -1,
"-90", NULL);
5270 ctl->
csi_lat1 =
scan_ctl(filename, argc, argv,
"CSI_LAT1", -1,
"90", NULL);
5272 (int)
scan_ctl(filename, argc, argv,
"CSI_NY", -1,
"180", NULL);
5277 scan_ctl(filename, argc, argv,
"ENS_DT_OUT", -1,
"86400", NULL);
5280 scan_ctl(filename, argc, argv,
"GRID_BASENAME", -1,
"-",
5285 scan_ctl(filename, argc, argv,
"GRID_DT_OUT", -1,
"86400", NULL);
5287 (int)
scan_ctl(filename, argc, argv,
"GRID_SPARSE", -1,
"0", NULL);
5289 (int)
scan_ctl(filename, argc, argv,
"GRID_NC_LEVEL", -1,
"0", NULL);
5290 for (
int iq = 0; iq < ctl->
nq; iq++)
5292 (
int)
scan_ctl(filename, argc, argv,
"GRID_NC_QUANT", iq,
"0", NULL);
5294 (int)
scan_ctl(filename, argc, argv,
"GRID_STDDEV", -1,
"0", NULL);
5295 ctl->
grid_z0 =
scan_ctl(filename, argc, argv,
"GRID_Z0", -1,
"-5", NULL);
5296 ctl->
grid_z1 =
scan_ctl(filename, argc, argv,
"GRID_Z1", -1,
"85", NULL);
5298 (int)
scan_ctl(filename, argc, argv,
"GRID_NZ", -1,
"1", NULL);
5300 scan_ctl(filename, argc, argv,
"GRID_LON0", -1,
"-180", NULL);
5302 scan_ctl(filename, argc, argv,
"GRID_LON1", -1,
"180", NULL);
5304 (int)
scan_ctl(filename, argc, argv,
"GRID_NX", -1,
"360", NULL);
5306 scan_ctl(filename, argc, argv,
"GRID_LAT0", -1,
"-90", NULL);
5308 scan_ctl(filename, argc, argv,
"GRID_LAT1", -1,
"90", NULL);
5310 (int)
scan_ctl(filename, argc, argv,
"GRID_NY", -1,
"180", NULL);
5312 (int)
scan_ctl(filename, argc, argv,
"GRID_TYPE", -1,
"0", NULL);
5315 scan_ctl(filename, argc, argv,
"PROF_BASENAME", -1,
"-",
5318 ctl->
prof_z0 =
scan_ctl(filename, argc, argv,
"PROF_Z0", -1,
"0", NULL);
5319 ctl->
prof_z1 =
scan_ctl(filename, argc, argv,
"PROF_Z1", -1,
"60", NULL);
5321 (int)
scan_ctl(filename, argc, argv,
"PROF_NZ", -1,
"60", NULL);
5323 scan_ctl(filename, argc, argv,
"PROF_LON0", -1,
"-180", NULL);
5325 scan_ctl(filename, argc, argv,
"PROF_LON1", -1,
"180", NULL);
5327 (int)
scan_ctl(filename, argc, argv,
"PROF_NX", -1,
"360", NULL);
5329 scan_ctl(filename, argc, argv,
"PROF_LAT0", -1,
"-90", NULL);
5331 scan_ctl(filename, argc, argv,
"PROF_LAT1", -1,
"90", NULL);
5333 (int)
scan_ctl(filename, argc, argv,
"PROF_NY", -1,
"180", NULL);
5336 scan_ctl(filename, argc, argv,
"SAMPLE_BASENAME", -1,
"-",
5338 scan_ctl(filename, argc, argv,
"SAMPLE_KERNEL", -1,
"-",
5340 scan_ctl(filename, argc, argv,
"SAMPLE_OBSFILE", -1,
"-",
5343 scan_ctl(filename, argc, argv,
"SAMPLE_DX", -1,
"50", NULL);
5345 scan_ctl(filename, argc, argv,
"SAMPLE_DZ", -1,
"-999", NULL);
5348 scan_ctl(filename, argc, argv,
"STAT_BASENAME", -1,
"-",
5352 ctl->
stat_r =
scan_ctl(filename, argc, argv,
"STAT_R", -1,
"50", NULL);
5354 scan_ctl(filename, argc, argv,
"STAT_T0", -1,
"-1e100", NULL);
5355 ctl->
stat_t1 =
scan_ctl(filename, argc, argv,
"STAT_T1", -1,
"1e100", NULL);
5360 scan_ctl(filename, argc, argv,
"VTK_DT_OUT", -1,
"86400", NULL);
5362 (int)
scan_ctl(filename, argc, argv,
"VTK_STRIDE", -1,
"1", NULL);
5364 scan_ctl(filename, argc, argv,
"VTK_SCALE", -1,
"1.0", NULL);
5366 scan_ctl(filename, argc, argv,
"VTK_OFFSET", -1,
"0.0", NULL);
5368 (int)
scan_ctl(filename, argc, argv,
"VTK_SPHERE", -1,
"0", NULL);
5374 const char *filename,
5380 LOG(1,
"Read meteo data: %s", filename);
5386 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
5406 ERRMSG(
"MET_TYPE not implemented!");
5415 LOG(2,
"Broadcast data on rank %d...", rank);
5544 ERRMSG(
"Code was compiled without KPP!");
5577#pragma acc update device(ctl[:1])
5581 if (cache != NULL) {
5584#pragma acc update device(cache[:1])
5591#pragma acc update device(clim[:1])
5598 met_t *met0up = *met0;
5599#pragma acc update device(met0up[:1])
5606 met_t *met1up = *met1;
5607#pragma acc update device(met1up[:1])
5614#pragma acc update device(atm[:1])
5633#pragma acc update host(ctl[:1])
5637 if (cache != NULL) {
5640#pragma acc update host(cache[:1])
5647#pragma acc update host(clim[:1])
5654 met_t *met0up = *met0;
5655#pragma acc update host(met0up[:1])
5662 met_t *met1up = *met1;
5663#pragma acc update host(met1up[:1])
5670#pragma acc update host(atm[:1])
5678 const char *filename,
5687 LOG(1,
"Write atmospheric data: %s", filename);
5711 ERRMSG(
"Atmospheric data type not supported!");
5715 LOG(2,
"Number of particles: %d", atm->
np);
5716 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
5717 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
5718 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
5719 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
5720 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
5721 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
5722 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
5723 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
5724 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
5725 for (
int iq = 0; iq < ctl->
nq; iq++) {
5727 sprintf(msg,
"Quantity %s range: %s ... %s %s",
5730 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
5731 LOG(2, msg, mini, maxi);
5738 const char *filename,
5746 LOG(1,
"Write meteo data: %s", filename);
5751 ERRMSG(
"MPTRAC was compiled without zfp compression!");
5755 ERRMSG(
"MPTRAC was compiled without zstd compression!");
5759 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
5772 ERRMSG(
"MET_TYPE not implemented!");
5778 const char *dirname,
5785 char ext[10], filename[2 *
LEN];
5789 int year, mon, day, hour, min, sec;
5792 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
5807 sprintf(ext,
"tab");
5809 sprintf(ext,
"bin");
5812 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
5813 dirname, ctl->
atm_basename, year, mon, day, hour, min, ext);
5819 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
5822 write_grid(filename, ctl, met0, met1, atm, t);
5827 sprintf(filename,
"%s/%s.tab", dirname, ctl->
csi_basename);
5833 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.tab",
5834 dirname, ctl->
ens_basename, year, mon, day, hour, min);
5840 sprintf(filename,
"%s/%s.tab", dirname, ctl->
prof_basename);
5841 write_prof(filename, ctl, met0, met1, atm, t);
5852 sprintf(filename,
"%s/%s.tab", dirname, ctl->
stat_basename);
5861 sprintf(filename,
"%s/%s_%05d.vtk", dirname, ctl->
vtk_basename, ++nvtk);
5871 const double hno3) {
5874 const double h2o_help =
MAX(h2o, 0.1e-6);
5877 const double p_hno3 = hno3 * p / 1.333224;
5878 const double p_h2o = h2o_help * p / 1.333224;
5879 const double a = 0.009179 - 0.00088 * log10(p_h2o);
5880 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
5881 const double c = -11397.0 / a;
5882 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
5883 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
5901 const double p0 = pbl;
5904 if (atm->
p[ip] > p0)
5906 else if (atm->
p[ip] < p1)
5909 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
5915 const char *filename,
5921 if (!(in = fopen(filename,
"r"))) {
5922 WARN(
"Cannot open file!");
5928 while (fgets(line,
LEN, in)) {
5932 TOK(line, tok,
"%lg", atm->
time[atm->
np]);
5933 TOK(NULL, tok,
"%lg", atm->
p[atm->
np]);
5934 TOK(NULL, tok,
"%lg", atm->
lon[atm->
np]);
5935 TOK(NULL, tok,
"%lg", atm->
lat[atm->
np]);
5936 for (
int iq = 0; iq < ctl->
nq; iq++)
5937 TOK(NULL, tok,
"%lg", atm->
q[iq][atm->
np]);
5940 atm->
p[atm->
np] =
P(atm->
p[atm->
np]);
5943 if ((++atm->
np) >
NP)
5944 ERRMSG(
"Too many data points!");
5957 const char *filename,
5963 if (!(in = fopen(filename,
"r")))
5968 FREAD(&version,
int,
5972 ERRMSG(
"Wrong version of binary data!");
5990 for (
int iq = 0; iq < ctl->
nq; iq++)
5991 FREAD(atm->
q[iq],
double,
6001 ERRMSG(
"Error while reading binary data!");
6013 const char *filename,
6020 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
6027 if (nc_inq_varid(ncid,
"TIME_INIT", &varid) == NC_NOERR) {
6028 NC(nc_get_var_double(ncid, varid, atm->
time));
6030 WARN(
"TIME_INIT not found use time instead!");
6033 for (
int ip = 0; ip < atm->
np; ip++) {
6034 atm->
time[ip] = time_init;
6046 if (nc_inq_varid(ncid,
"PRESS_INIT", &varid) == NC_NOERR) {
6047 NC(nc_get_var_double(ncid, varid, atm->
p));
6049 WARN(
"PRESS_INIT not found use PRESS instead!");
6050 nc_inq_varid(ncid,
"PRESS", &varid);
6051 NC(nc_get_var_double(ncid, varid, atm->
p));
6069 const char *filename,
6076 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
6089 for (
int iq = 0; iq < ctl->
nq; iq++)
6102 const char *filename,
6108 LOG(1,
"Read photolysis rates: %s", filename);
6111 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
6112 WARN(
"Photolysis rate data are missing!");
6119 if (photo->
p[0] < photo->
p[1])
6120 ERRMSG(
"Pressure data are not descending!");
6125 if (photo->
o3c[0] > photo->
o3c[1])
6126 ERRMSG(
"Total column ozone data are not ascending!");
6131 if (photo->
sza[0] > photo->
sza[1])
6132 ERRMSG(
"Solar zenith angle data are not ascending!");
6149 LOG(2,
"Number of pressure levels: %d", photo->
np);
6150 LOG(2,
"Altitude levels: %g, %g ... %g km",
6151 Z(photo->
p[0]),
Z(photo->
p[1]),
Z(photo->
p[photo->
np - 1]));
6152 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
6153 photo->
p[0], photo->
p[1], photo->
p[photo->
np - 1]);
6154 LOG(2,
"Number of solar zenith angles: %d", photo->
nsza);
6155 LOG(2,
"Solar zenith angles: %g, %g ... %g deg",
6158 LOG(2,
"Number of total column ozone values: %d", photo->
no3c);
6159 LOG(2,
"Total column ozone: %g, %g ... %g DU",
6161 LOG(2,
"N2O photolysis rate: %g, %g ... %g s**-1",
6162 photo->
n2o[0][0][0], photo->
n2o[1][0][0],
6163 photo->
n2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
6164 LOG(2,
"CCl4 photolysis rate: %g, %g ... %g s**-1",
6165 photo->
ccl4[0][0][0], photo->
ccl4[1][0][0],
6167 LOG(2,
"CFC-11 photolysis rate: %g, %g ... %g s**-1",
6168 photo->
ccl3f[0][0][0], photo->
ccl3f[1][0][0],
6170 LOG(2,
"CFC-12 photolysis rate: %g, %g ... %g s**-1",
6173 LOG(2,
"O2 photolysis rate: %g, %g ... %g s**-1",
6174 photo->
o2[0][0][0], photo->
o2[1][0][0],
6175 photo->
o2[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
6176 LOG(2,
"O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
6177 photo->
o3_1[0][0][0], photo->
o3_1[1][0][0],
6179 LOG(2,
"O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
6180 photo->
o3_2[0][0][0], photo->
o3_2[1][0][0],
6182 LOG(2,
"H2O2 photolysis rate: %g, %g ... %g s**-1",
6183 photo->
h2o2[0][0][0], photo->
h2o2[1][0][0],
6185 LOG(2,
"H2O photolysis rate: %g, %g ... %g s**-1",
6186 photo->
h2o[0][0][0], photo->
h2o[1][0][0],
6187 photo->
h2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
6194 const char *varname,
6208 for (
int ip = 0; ip < photo->
np; ip++)
6209 for (
int is = 0; is < photo->
nsza; is++)
6210 for (
int io = 0; io < photo->
no3c; io++)
6221 const char *filename,
6225 LOG(1,
"Read climatological time series: %s", filename);
6229 if (!(in = fopen(filename,
"r"))) {
6230 WARN(
"Cannot open file!");
6237 while (fgets(line,
LEN, in))
6238 if (sscanf(line,
"%lg %lg", &ts->
time[nh], &ts->
vmr[nh]) == 2) {
6241 ts->
time[nh] = (ts->
time[nh] - 2000.0) * 365.25 * 86400.;
6244 if (nh > 0 && ts->
time[nh] <= ts->
time[nh - 1])
6245 ERRMSG(
"Time series must be ascending!");
6249 ERRMSG(
"Too many data points!");
6258 ERRMSG(
"Not enough data points!");
6261 LOG(2,
"Number of time steps: %d", ts->
ntime);
6262 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s", ts->
time[0], ts->
time[1],
6264 LOG(2,
"Volume mixing ratio range: %g ... %g ppv",
6265 gsl_stats_min(ts->
vmr, 1, (
size_t) nh), gsl_stats_max(ts->
vmr, 1,
6275 const char *filename,
6276 const char *varname,
6279 int ncid, varid, it, iy, iz, iz2, nt;
6281 double *help, varmin = 1e99, varmax = -1e99;
6284 LOG(1,
"Read %s data: %s", varname, filename);
6287 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
6288 WARN(
"%s climatology data are missing!", varname);
6295 if (zm->
p[0] < zm->
p[1])
6296 ERRMSG(
"Pressure data are not descending!");
6301 if (zm->
lat[0] > zm->
lat[1])
6302 ERRMSG(
"Latitude data are not ascending!");
6306 zm->
time[0] = 1209600.00;
6307 zm->
time[1] = 3888000.00;
6308 zm->
time[2] = 6393600.00;
6309 zm->
time[3] = 9072000.00;
6310 zm->
time[4] = 11664000.00;
6311 zm->
time[5] = 14342400.00;
6312 zm->
time[6] = 16934400.00;
6313 zm->
time[7] = 19612800.00;
6314 zm->
time[8] = 22291200.00;
6315 zm->
time[9] = 24883200.00;
6316 zm->
time[10] = 27561600.00;
6317 zm->
time[11] = 30153600.00;
6326 for (it = 0; it < zm->
ntime; it++)
6327 for (iz = 0; iz < zm->
np; iz++)
6328 for (iy = 0; iy < zm->
nlat; iy++)
6333 for (it = 0; it < zm->
ntime; it++)
6334 for (iy = 0; iy < zm->
nlat; iy++)
6335 for (iz = 0; iz < zm->
np; iz++) {
6336 if (zm->
vmr[it][iz][iy] < 0) {
6337 for (iz2 = 0; iz2 < zm->
np; iz2++)
6338 if (zm->
vmr[it][iz2][iy] >= 0) {
6339 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
6342 for (iz2 = zm->
np - 1; iz2 >= 0; iz2--)
6343 if (zm->
vmr[it][iz2][iy] >= 0) {
6344 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
6348 varmin =
MIN(varmin, zm->
vmr[it][iz][iy]);
6349 varmax =
MAX(varmax, zm->
vmr[it][iz][iy]);
6356 LOG(2,
"Number of time steps: %d", zm->
ntime);
6357 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
6359 LOG(2,
"Number of pressure levels: %d", zm->
np);
6360 LOG(2,
"Altitude levels: %g, %g ... %g km",
6361 Z(zm->
p[0]),
Z(zm->
p[1]),
Z(zm->
p[zm->
np - 1]));
6362 LOG(2,
"Pressure levels: %g, %g ... %g hPa", zm->
p[0],
6363 zm->
p[1], zm->
p[zm->
np - 1]);
6364 LOG(2,
"Number of latitudes: %d", zm->
nlat);
6365 LOG(2,
"Latitudes: %g, %g ... %g deg",
6367 LOG(2,
"%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
6374 const char *filename,
6380 LOG(1,
"Read kernel function: %s", filename);
6384 if (!(in = fopen(filename,
"r")))
6385 ERRMSG(
"Cannot open file!");
6390 while (fgets(line,
LEN, in))
6391 if (sscanf(line,
"%lg %lg", &kz[n], &kw[n]) == 2) {
6392 if (n > 0 && kz[n] < kz[n - 1])
6393 ERRMSG(
"Height levels must be ascending!");
6395 ERRMSG(
"Too many height levels!");
6404 ERRMSG(
"Not enough height levels!");
6407 const double kmax = gsl_stats_max(kw, 1, (
size_t) n);
6408 for (
int iz = 0; iz < n; iz++)
6415 const char *filename,
6423 int year, mon, day, hour, min, sec;
6429 if (!(in = fopen(filename,
"r"))) {
6430 WARN(
"Cannot open file!");
6436 FREAD(&met_type,
int,
6440 ERRMSG(
"Wrong MET_TYPE of binary data!");
6444 FREAD(&version,
int,
6448 ERRMSG(
"Wrong version of binary data!");
6454 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
6455 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
6456 met->
time, year, mon, day, hour, min);
6457 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
6458 || day < 1 || day > 31 || hour < 0 || hour > 23)
6459 ERRMSG(
"Error while reading time!");
6465 LOG(2,
"Number of longitudes: %d", met->
nx);
6466 if (met->
nx < 2 || met->
nx >
EX)
6467 ERRMSG(
"Number of longitudes out of range!");
6472 LOG(2,
"Number of latitudes: %d", met->
ny);
6473 if (met->
ny < 2 || met->
ny >
EY)
6474 ERRMSG(
"Number of latitudes out of range!");
6479 LOG(2,
"Number of levels: %d", met->
np);
6480 if (met->
np < 2 || met->
np >
EP)
6481 ERRMSG(
"Number of levels out of range!");
6487 LOG(2,
"Longitudes: %g, %g ... %g deg",
6493 LOG(2,
"Latitudes: %g, %g ... %g deg",
6499 LOG(2,
"Altitude levels: %g, %g ... %g km",
6500 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
6501 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
6502 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
6551 ERRMSG(
"Error while reading binary data!");
6566 const char *varname) {
6575 LOG(2,
"Read 2-D variable: %s (uncompressed)", varname);
6577 (
size_t) (met->
nx * met->
ny),
6581 for (
int ix = 0; ix < met->
nx; ix++)
6582 for (
int iy = 0; iy < met->
ny; iy++)
6583 var[ix][iy] = help[
ARRAY_2D(ix, iy, met->
ny)];
6596 const char *varname,
6597 const float bound_min,
6598 const float bound_max) {
6608 LOG(2,
"Read 3-D variable: %s (uncompressed)", varname);
6610 (
size_t) (met->
nx * met->
ny * met->
np),
6617 (
size_t) met->
np, 1, in);
6623 FREAD(&precision,
int,
6628 FREAD(&tolerance,
double,
6635 ERRMSG(
"MPTRAC was compiled without zfp compression!");
6645 ERRMSG(
"MPTRAC was compiled without zstd compression!");
6653 (
size_t) met->
np, 1, in);
6655 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
6660#pragma omp parallel for default(shared) collapse(2)
6661 for (
int ix = 0; ix < met->
nx; ix++)
6662 for (
int iy = 0; iy < met->
ny; iy++)
6663 for (
int ip = 0; ip < met->
np; ip++) {
6664 var[ix][iy][ip] = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
6665 if (var[ix][iy][ip] < bound_min)
6666 var[ix][iy][ip] = bound_min;
6667 else if (var[ix][iy][ip] > bound_max)
6668 var[ix][iy][ip] = bound_max;
6688 LOG(2,
"Calculate CAPE...");
6691 const double pfac = 1.01439, dz0 =
RI /
MA /
G0 * log(pfac);
6694#pragma omp parallel for default(shared) collapse(2)
6695 for (
int ix = 0; ix < met->
nx; ix++)
6696 for (
int iy = 0; iy < met->
ny; iy++) {
6700 double h2o = 0, t, theta = 0;
6701 double pbot =
MIN(met->
ps[ix][iy], met->
p[0]);
6702 double ptop = pbot - 50.;
6703 for (
int ip = 0; ip < met->
np; ip++) {
6704 if (met->
p[ip] <= pbot) {
6705 theta +=
THETA(met->
p[ip], met->
t[ix][iy][ip]);
6706 h2o += met->
h2o[ix][iy][ip];
6709 if (met->
p[ip] < ptop && n > 0)
6716 met->
plcl[ix][iy] = NAN;
6717 met->
plfc[ix][iy] = NAN;
6718 met->
pel[ix][iy] = NAN;
6719 met->
cape[ix][iy] = NAN;
6720 met->
cin[ix][iy] = NAN;
6726 pbot = met->
ps[ix][iy];
6728 met->
plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
6729 t = theta / pow(1000. / met->
plcl[ix][iy], 0.286);
6730 if (
RH(met->
plcl[ix][iy], t, h2o) > 100.)
6731 ptop = met->
plcl[ix][iy];
6733 pbot = met->
plcl[ix][iy];
6734 }
while (pbot - ptop > 0.1);
6738 double dcape, dz, h2o_env, t_env;
6739 double p = met->
ps[ix][iy];
6740 met->
cape[ix][iy] = met->
cin[ix][iy] = 0;
6742 dz = dz0 *
TVIRT(t, h2o);
6744 t = theta / pow(1000. / p, 0.286);
6748 &h2o_env, ci, cw, 0);
6749 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
6750 TVIRT(t_env, h2o_env) * dz;
6752 met->
cin[ix][iy] += fabsf((
float) dcape);
6753 }
while (p > met->
plcl[ix][iy]);
6758 p = met->
plcl[ix][iy];
6759 t = theta / pow(1000. / p, 0.286);
6762 dz = dz0 *
TVIRT(t, h2o);
6765 double psat =
PSAT(t);
6766 h2o = psat / (p - (1. -
EPS) * psat);
6770 &h2o_env, ci, cw, 0);
6771 double dcape_old = dcape;
6772 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
6773 TVIRT(t_env, h2o_env) * dz;
6775 met->
cape[ix][iy] += (float) dcape;
6776 if (!isfinite(met->
plfc[ix][iy]))
6777 met->
plfc[ix][iy] = (
float) p;
6778 }
else if (dcape_old > 0)
6779 met->
pel[ix][iy] = (float) p;
6780 if (dcape < 0 && !isfinite(met->
plfc[ix][iy]))
6781 met->
cin[ix][iy] += fabsf((
float) dcape);
6785 if (!isfinite(met->
plfc[ix][iy]))
6786 met->
cin[ix][iy] = NAN;
6797 LOG(2,
"Calculate cloud data...");
6800 const double ccmin = 0.01, cwmin = 1e-6;
6803#pragma omp parallel for default(shared) collapse(2)
6804 for (
int ix = 0; ix < met->
nx; ix++)
6805 for (
int iy = 0; iy < met->
ny; iy++) {
6808 met->
pct[ix][iy] = NAN;
6809 met->
pcb[ix][iy] = NAN;
6810 met->
cl[ix][iy] = 0;
6813 for (
int ip = 0; ip < met->
np - 1; ip++) {
6816 if (met->
p[ip] > met->
ps[ix][iy] || met->
p[ip] <
P(20.))
6820 if (met->
cc[ix][iy][ip] > ccmin
6821 && (met->
lwc[ix][iy][ip] > cwmin
6822 || met->
rwc[ix][iy][ip] > cwmin
6823 || met->
iwc[ix][iy][ip] > cwmin
6824 || met->
swc[ix][iy][ip] > cwmin)) {
6828 = (float) (0.5 * (met->
p[ip] + (
float) met->
p[ip + 1]));
6831 if (!isfinite(met->
pcb[ix][iy]))
6833 = (
float) (0.5 * (met->
p[ip] + met->
p[
MAX(ip - 1, 0)]));
6837 met->
cl[ix][iy] += (float)
6838 (0.5 * (met->
lwc[ix][iy][ip] + met->
lwc[ix][iy][ip + 1]
6839 + met->
rwc[ix][iy][ip] + met->
rwc[ix][iy][ip + 1]
6840 + met->
iwc[ix][iy][ip] + met->
iwc[ix][iy][ip + 1]
6841 + met->
swc[ix][iy][ip] + met->
swc[ix][iy][ip + 1])
6842 * 100. * (met->
p[ip] - met->
p[ip + 1]) /
G0);
6860 SELECT_TIMER(
"READ_MET_DETREND",
"METPROC", NVTX_READ);
6861 LOG(2,
"Detrend meteo data...");
6868 const double tssq = 2. *
SQR(sigma);
6871 int sy = (int) (3. *
DY2DEG(sigma) / fabs(met->
lat[1] - met->
lat[0]));
6875#pragma omp parallel for default(shared) collapse(2)
6876 for (
int ix = 0; ix < met->
nx; ix++) {
6877 for (
int iy = 0; iy < met->
ny; iy++) {
6885 (int) (3. *
DX2DEG(sigma, met->
lat[iy]) /
6886 fabs(met->
lon[1] - met->
lon[0]));
6891 for (
int ip = 0; ip < met->
np; ip++) {
6892 help->
t[ix][iy][ip] = 0;
6893 help->
u[ix][iy][ip] = 0;
6894 help->
v[ix][iy][ip] = 0;
6895 help->
w[ix][iy][ip] = 0;
6899 for (
int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
6903 else if (ix3 >= met->
nx)
6905 for (
int iy2 =
MAX(iy - sy, 0);
6906 iy2 <=
MIN(iy + sy, met->
ny - 1); iy2++) {
6913 const float w = (float) exp(-
DIST2(x0, x1) / tssq);
6917 for (
int ip = 0; ip < met->
np; ip++) {
6918 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip];
6919 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip];
6920 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip];
6921 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip];
6927 for (
int ip = 0; ip < met->
np; ip++) {
6928 help->
t[ix][iy][ip] /= wsum;
6929 help->
u[ix][iy][ip] /= wsum;
6930 help->
v[ix][iy][ip] /= wsum;
6931 help->
w[ix][iy][ip] /= wsum;
6937#pragma omp parallel for default(shared) collapse(3)
6938 for (
int ix = 0; ix < met->
nx; ix++)
6939 for (
int iy = 0; iy < met->
ny; iy++)
6940 for (
int ip = 0; ip < met->
np; ip++) {
6941 met->
t[ix][iy][ip] -= help->
t[ix][iy][ip];
6942 met->
u[ix][iy][ip] -= help->
u[ix][iy][ip];
6943 met->
v[ix][iy][ip] -= help->
v[ix][iy][ip];
6944 met->
w[ix][iy][ip] -= help->
w[ix][iy][ip];
6957 SELECT_TIMER(
"READ_MET_EXTRAPOLATE",
"METPROC", NVTX_READ);
6958 LOG(2,
"Extrapolate meteo data...");
6961#pragma omp parallel for default(shared) collapse(2)
6962 for (
int ix = 0; ix < met->
nx; ix++)
6963 for (
int iy = 0; iy < met->
ny; iy++) {
6967 for (ip0 = met->
np - 1; ip0 >= 0; ip0--)
6968 if (!isfinite(met->
t[ix][iy][ip0])
6969 || !isfinite(met->
u[ix][iy][ip0])
6970 || !isfinite(met->
v[ix][iy][ip0])
6971 || !isfinite(met->
w[ix][iy][ip0]))
6975 for (
int ip = ip0; ip >= 0; ip--) {
6976 met->
t[ix][iy][ip] = met->
t[ix][iy][ip + 1];
6977 met->
u[ix][iy][ip] = met->
u[ix][iy][ip + 1];
6978 met->
v[ix][iy][ip] = met->
v[ix][iy][ip + 1];
6979 met->
w[ix][iy][ip] = met->
w[ix][iy][ip + 1];
6980 met->
h2o[ix][iy][ip] = met->
h2o[ix][iy][ip + 1];
6981 met->
o3[ix][iy][ip] = met->
o3[ix][iy][ip + 1];
6982 met->
lwc[ix][iy][ip] = met->
lwc[ix][iy][ip + 1];
6983 met->
rwc[ix][iy][ip] = met->
rwc[ix][iy][ip + 1];
6984 met->
iwc[ix][iy][ip] = met->
iwc[ix][iy][ip + 1];
6985 met->
swc[ix][iy][ip] = met->
swc[ix][iy][ip + 1];
6986 met->
cc[ix][iy][ip] = met->
cc[ix][iy][ip + 1];
7005 LOG(2,
"Calculate geopotential heights...");
7012#pragma omp parallel for default(shared)
7013 for (
int ip = 0; ip < met->
np; ip++)
7014 logp[ip] = log(met->
p[ip]);
7017#pragma omp parallel for default(shared) collapse(2)
7018 for (
int ix = 0; ix < met->
nx; ix++)
7019 for (
int iy = 0; iy < met->
ny; iy++) {
7022 const double zs = met->
zs[ix][iy];
7023 const double lnps = log(met->
ps[ix][iy]);
7027 const double ts =
LIN(met->
p[ip0], met->
t[ix][iy][ip0], met->
p[ip0 + 1],
7028 met->
t[ix][iy][ip0 + 1], met->
ps[ix][iy]);
7030 LIN(met->
p[ip0], met->
h2o[ix][iy][ip0], met->
p[ip0 + 1],
7031 met->
h2o[ix][iy][ip0 + 1], met->
ps[ix][iy]);
7034 met->
z[ix][iy][ip0 + 1]
7036 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
7037 met->
t[ix][iy][ip0 + 1], met->
h2o[ix][iy][ip0 + 1]));
7038 for (
int ip = ip0 + 2; ip < met->
np; ip++)
7040 = (
float) (met->
z[ix][iy][ip - 1] +
7041 ZDIFF(logp[ip - 1], met->
t[ix][iy][ip - 1],
7042 met->
h2o[ix][iy][ip - 1], logp[ip],
7043 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
7048 ZDIFF(lnps, ts, h2os, logp[ip0],
7049 met->
t[ix][iy][ip0], met->
h2o[ix][iy][ip0]));
7050 for (
int ip = ip0 - 1; ip >= 0; ip--)
7052 = (
float) (met->
z[ix][iy][ip + 1] +
7053 ZDIFF(logp[ip + 1], met->
t[ix][iy][ip + 1],
7054 met->
h2o[ix][iy][ip + 1], logp[ip],
7055 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
7059 if (dx == 0 || dy == 0)
7063 if (dx < 0 || dy < 0) {
7064 if (fabs(met->
lon[1] - met->
lon[0]) < 0.5) {
7074 float ws[dx + 1][dy + 1];
7075#pragma omp parallel for default(shared) collapse(2)
7076 for (
int ix = 0; ix <= dx; ix++)
7077 for (
int iy = 0; iy < dy; iy++)
7078 ws[ix][iy] = (1.0f - (
float) ix / (float) dx)
7079 * (1.0f - (float) iy / (
float) dy);
7082#pragma omp parallel for default(shared) collapse(3)
7083 for (
int ix = 0; ix < met->
nx; ix++)
7084 for (
int iy = 0; iy < met->
ny; iy++)
7085 for (
int ip = 0; ip < met->
np; ip++)
7086 help[
ARRAY_3D(ip, ix, met->
nx, iy, met->
ny)] = met->
z[ix][iy][ip];
7089#pragma omp parallel for default(shared) collapse(3)
7090 for (
int ip = 0; ip < met->
np; ip++)
7091 for (
int ix = 0; ix < met->
nx; ix++)
7092 for (
int iy = 0; iy < met->
ny; iy++) {
7093 float res = 0, wsum = 0;
7094 int iy0 =
MAX(iy - dy + 1, 0);
7095 int iy1 =
MIN(iy + dy - 1, met->
ny - 1);
7096 for (
int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
7100 else if (ix3 >= met->
nx)
7102 for (
int iy2 = iy0; iy2 <= iy1; ++iy2)
7103 if (isfinite(help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)])) {
7104 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
7105 res += w * help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)];
7110 met->
z[ix][iy][ip] = res / wsum;
7112 met->
z[ix][iy][ip] = NAN;
7122 const char *filename,
7127 char levname[
LEN], tstr[10];
7129 double rtime = 0, r, r2;
7131 int varid, year2, mon2, day2, hour2, min2, sec2,
7132 year, mon, day, hour, min, sec;
7138 LOG(2,
"Read meteo grid information...");
7147 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
7148 if (nc_inq_varid(ncid,
"time", &varid) == NC_NOERR) {
7149 NC(nc_get_var_double(ncid, varid, &rtime));
7150 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
7151 WARN(
"Time information in meteo file does not match filename!");
7153 WARN(
"Time information in meteo file is missing!");
7164 sprintf(tstr,
"19%.2s", &filename[strlen(filename) - 11]);
7166 sprintf(tstr,
"20%.2s", &filename[strlen(filename) - 11]);
7168 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 9]);
7170 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 7]);
7172 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 5]);
7178 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
7179 || day < 1 || day > 31 || hour < 0 || hour > 23)
7180 ERRMSG(
"Cannot read time from filename!");
7181 jsec2time(met->
time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
7182 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
7183 met->
time, year2, mon2, day2, hour2, min2);
7187 LOG(2,
"Number of longitudes: %d", met->
nx);
7190 LOG(2,
"Number of latitudes: %d", met->
ny);
7193 sprintf(levname,
"lev");
7194 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR)
7195 sprintf(levname,
"plev");
7196 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR)
7197 sprintf(levname,
"hybrid");
7198 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR)
7199 sprintf(levname,
"hybrid_level");
7203 sprintf(levname,
"lev_2");
7204 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR) {
7205 sprintf(levname,
"plev");
7206 NC(nc_inq_dimid(ncid, levname, &dimid2));
7208 NC(nc_inq_dimlen(ncid, dimid2, &np));
7211 LOG(2,
"Number of levels: %d", met->
np);
7212 if (met->
np < 2 || met->
np >
EP)
7213 ERRMSG(
"Number of levels out of range!");
7217 LOG(2,
"Longitudes: %g, %g ... %g deg",
7220 LOG(2,
"Latitudes: %g, %g ... %g deg",
7224 for (
int ix = 2; ix < met->
nx; ix++)
7226 (fabs(met->
lon[ix] - met->
lon[ix - 1]) -
7227 fabs(met->
lon[1] - met->
lon[0])) > 0.001)
7228 ERRMSG(
"No regular grid spacing in longitudes!");
7229 for (
int iy = 2; iy < met->
ny; iy++)
7231 (fabs(met->
lat[iy] - met->
lat[iy - 1]) -
7232 fabs(met->
lat[1] - met->
lat[0])) > 0.001) {
7233 WARN(
"No regular grid spacing in latitudes!");
7240 for (
int ip = 0; ip < met->
np; ip++)
7242 LOG(2,
"Altitude levels: %g, %g ... %g km",
7243 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
7244 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
7245 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
7249 if (strcasecmp(levname,
"hybrid") == 0)
7262 LOG(2,
"Read level data...");
7265 if (!
read_met_nc_3d(ncid,
"t",
"T",
"temp",
"TEMP", ctl, met, met->
t, 1.0))
7266 ERRMSG(
"Cannot read temperature!");
7269 if (!
read_met_nc_3d(ncid,
"u",
"U", NULL, NULL, ctl, met, met->
u, 1.0))
7270 ERRMSG(
"Cannot read zonal wind!");
7271 if (!
read_met_nc_3d(ncid,
"v",
"V", NULL, NULL, ctl, met, met->
v, 1.0))
7272 ERRMSG(
"Cannot read meridional wind!");
7274 (ncid,
"w",
"W",
"omega",
"OMEGA", ctl, met, met->
w, 0.01f))
7275 WARN(
"Cannot read vertical velocity!");
7280 (ncid,
"q",
"Q",
"sh",
"SH", ctl, met, met->
h2o, (
float) (
MA /
MH2O)))
7281 WARN(
"Cannot read specific humidity!");
7284 (ncid,
"rh",
"RH", NULL, NULL, ctl, met, met->
h2o, 0.01f))
7285 WARN(
"Cannot read relative humidity!");
7286#pragma omp parallel for default(shared) collapse(2)
7287 for (
int ix = 0; ix < met->
nx; ix++)
7288 for (
int iy = 0; iy < met->
ny; iy++)
7289 for (
int ip = 0; ip < met->
np; ip++) {
7290 double pw = met->
h2o[ix][iy][ip] *
PSAT(met->
t[ix][iy][ip]);
7291 met->
h2o[ix][iy][ip] =
7292 (float) (pw / (met->
p[ip] - (1.0 -
EPS) * pw));
7298 (ncid,
"o3",
"O3", NULL, NULL, ctl, met, met->
o3, (
float) (
MA /
MO3)))
7299 WARN(
"Cannot read ozone data!");
7303 (ncid,
"clwc",
"CLWC", NULL, NULL, ctl, met, met->
lwc, 1.0))
7304 WARN(
"Cannot read cloud liquid water content!");
7306 (ncid,
"crwc",
"CRWC", NULL, NULL, ctl, met, met->
rwc, 1.0))
7307 WARN(
"Cannot read cloud rain water content!");
7309 (ncid,
"ciwc",
"CIWC", NULL, NULL, ctl, met, met->
iwc, 1.0))
7310 WARN(
"Cannot read cloud ice water content!");
7312 (ncid,
"cswc",
"CSWC", NULL, NULL, ctl, met, met->
swc, 1.0))
7313 WARN(
"Cannot read cloud snow water content!");
7315 WARN(
"Cannot read cloud cover!");
7319 (ncid,
"ZETA",
"zeta", NULL, NULL, ctl, met, met->
zetal, 1.0))
7320 WARN(
"Cannot read ZETA!");
7322 (ncid,
"ZETA_DOT_TOT",
"ZETA_DOT_clr",
"zeta_dot_clr",
7323 NULL, ctl, met, met->
zeta_dotl, 0.00001157407f))
7324 WARN(
"Cannot read ZETA_DOT!");
7328 for (
int ix = 0; ix < met->
nx; ix++)
7329 for (
int iy = 0; iy < met->
ny; iy++)
7330 for (
int ip = 0; ip < met->
np; ip++) {
7331 met->
ul[ix][iy][ip] = met->
u[ix][iy][ip];
7332 met->
vl[ix][iy][ip] = met->
v[ix][iy][ip];
7333 met->
wl[ix][iy][ip] = met->
w[ix][iy][ip];
7346 (ncid,
"pl",
"PL",
"pressure",
"PRESSURE", ctl, met, met->
pl,
7349 (ncid,
"press",
"PRESS", NULL, NULL, ctl, met, met->
pl, 1.0))
7350 ERRMSG(
"Cannot read pressure on model levels!");
7357 double hyam[
EP], hybm[
EP];
7362 if (nc_inq_varid(ncid,
"hyam", &varid) == NC_NOERR
7363 && nc_inq_varid(ncid,
"hybm", &varid) == NC_NOERR) {
7366 }
else if (nc_inq_varid(ncid,
"a_hybrid_level", &varid) == NC_NOERR
7367 && nc_inq_varid(ncid,
"b_hybrid_level",
7368 &varid) == NC_NOERR) {
7372 ERRMSG(
"Cannot read a and b level coefficients from netCDF file!");
7380 ERRMSG(
"Mismatch in number of model levels!");
7383 for (
int ip = 0; ip < met->
np; ip++) {
7390 for (
int ix = 0; ix < met->
nx; ix++)
7391 for (
int iy = 0; iy < met->
ny; iy++)
7392 for (
int ip = 0; ip < met->
np; ip++)
7393 met->
pl[ix][iy][ip] =
7394 (
float) (hyam[ip] / 100. + hybm[ip] * met->
ps[ix][iy]);
7401 double hyam[
EP], hybm[
EP];
7404 for (
int ip = 0; ip < met->
np + 1; ip++) {
7411 ERRMSG(
"Mismatch in number of model levels!");
7414#pragma omp parallel for default(shared) collapse(2)
7415 for (
int ix = 0; ix < met->
nx; ix++)
7416 for (
int iy = 0; iy < met->
ny; iy++)
7417 for (
int ip = 0; ip < met->
np; ip++) {
7418 double p0 = hyam[ip] / 100. + hybm[ip] * met->
ps[ix][iy];
7419 double p1 = hyam[ip + 1] / 100. + hybm[ip + 1] * met->
ps[ix][iy];
7420 met->
pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
7425 for (
int ix = 0; ix < met->
nx; ix++)
7426 for (
int iy = 0; iy < met->
ny; iy++)
7427 for (
int ip = 1; ip < met->
np; ip++)
7428 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
7429 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
7430 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
7431 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip]))
7432 ERRMSG(
"Pressure profiles are not monotonic!");
7439 if (met->
pl[0][0][0] <= 0)
7440 ERRMSG(
"Pressure on model levels is missing, check MET_VERT_COORD!");
7457 for (
int ip = 0; ip < met->
np; ip++)
7458 met->
p[ip] = ctl->
met_p[ip];
7462 for (
int ip = 1; ip < met->
np; ip++)
7463 if (met->
p[ip - 1] < met->
p[ip])
7464 ERRMSG(
"Pressure levels must be descending!");
7473 const char *varname) {
7475 double aux[
EP], p[
EP];
7479 LOG(2,
"Interpolate meteo data to pressure levels: %s", varname);
7482#pragma omp parallel for default(shared) private(aux,p) collapse(2)
7483 for (
int ix = 0; ix < met->
nx; ix++)
7484 for (
int iy = 0; iy < met->
ny; iy++) {
7487 for (
int ip = 0; ip < met->
np; ip++)
7488 p[ip] = met->
pl[ix][iy][ip];
7491 for (
int ip = 0; ip < ctl->
met_np; ip++) {
7492 double pt = ctl->
met_p[ip];
7493 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
7495 else if ((pt > p[met->
np - 1] && p[1] > p[0])
7496 || (pt < p[met->
np - 1] && p[1] < p[0]))
7497 pt = p[met->
np - 1];
7499 aux[ip] =
LIN(p[ip2], var[ix][iy][ip2],
7500 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
7504 for (
int ip = 0; ip < ctl->
met_np; ip++)
7505 var[ix][iy][ip] = (
float) aux[ip];
7520 SELECT_TIMER(
"READ_MET_MONOTONIZE",
"METPROC", NVTX_READ);
7521 LOG(2,
"Make zeta profiles monotone...");
7524#pragma omp parallel for default(shared) collapse(2)
7525 for (
int i = 0; i < met->
nx; i++)
7526 for (
int j = 0; j < met->
ny; j++) {
7529 while (k < met->npl) {
7530 if ((met->
zetal[i][j][k - 1] >= met->
zetal[i][j][k])) {
7536 while ((met->
zetal[i][j][k - 1] >=
7537 met->
zetal[i][j][k + l]) & (k + l < met->npl));
7542 (float) (met->
zetal[i][j][k + l] - met->
zetal[i][j][k - 1])
7545 for (
int m = k; m < k + l; m++) {
7546 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
7547 met->
zetal[i][j][m] = s * d + met->
zetal[i][j][k - 1];
7559#pragma omp parallel for default(shared) collapse(2)
7560 for (
int i = 0; i < met->
nx; i++)
7561 for (
int j = 0; j < met->
ny; j++) {
7564 while (k < met->npl) {
7565 if ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k])) {
7572 while ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k + l]) & (k + l <
7577 float s = (float) (met->
pl[i][j][k + l] - met->
pl[i][j][k - 1])
7580 for (
int m = k; m < k + l; m++) {
7581 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
7582 met->
pl[i][j][m] = s * d + met->
pl[i][j][k - 1];
7597 const char *filename,
7605 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
7606 WARN(
"Cannot open file!");
7669 const char *varname,
7670 const char *varname2,
7671 const char *varname3,
7672 const char *varname4,
7673 const char *varname5,
7674 const char *varname6,
7683 float offset, scalfac;
7688 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
7689 sprintf(varsel,
"%s", varname);
7690 else if (varname2 != NULL
7691 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
7692 sprintf(varsel,
"%s", varname2);
7693 else if (varname3 != NULL
7694 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
7695 sprintf(varsel,
"%s", varname3);
7696 else if (varname4 != NULL
7697 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
7698 sprintf(varsel,
"%s", varname4);
7699 else if (varname5 != NULL
7700 && nc_inq_varid(ncid, varname5, &varid) == NC_NOERR)
7701 sprintf(varsel,
"%s", varname5);
7702 else if (varname6 != NULL
7703 && nc_inq_varid(ncid, varname6, &varid) == NC_NOERR)
7704 sprintf(varsel,
"%s", varname6);
7710 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
7711 && nc_get_att_float(ncid, varid,
"scale_factor",
7712 &scalfac) == NC_NOERR) {
7720 short fillval, missval;
7721 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
7723 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
7727 LOG(2,
"Read 2-D variable: %s"
7728 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
7729 varsel, fillval, missval, scalfac, offset);
7732 NC(nc_get_var_short(ncid, varid, help));
7736 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
7739#pragma omp parallel for default(shared) num_threads(12)
7740 for (
int ix = 0; ix < met->
nx; ix++)
7741 for (
int iy = 0; iy < met->
ny; iy++) {
7744 const short aux = help[
ARRAY_2D(iy, ix, met->
nx)];
7745 if ((fillval == 0 || aux != fillval)
7746 && (missval == 0 || aux != missval)
7747 && fabsf(aux * scalfac + offset) < 1e14f)
7748 dest[ix][iy] += scl * (aux * scalfac + offset);
7766 float fillval, missval;
7767 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
7769 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
7773 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
7774 varsel, fillval, missval);
7777 NC(nc_get_var_float(ncid, varid, help));
7783#pragma omp parallel for default(shared) num_threads(12)
7784 for (
int ix = 0; ix < met->
nx; ix++)
7785 for (
int iy = 0; iy < met->
ny; iy++) {
7788 const float aux = help[
ARRAY_2D(iy, ix, met->
nx)];
7789 if ((fillval == 0 || aux != fillval)
7790 && (missval == 0 || aux != missval)
7791 && fabsf(aux) < 1e14f)
7792 dest[ix][iy] += scl * aux;
7800#pragma omp parallel for default(shared) num_threads(12)
7801 for (
int iy = 0; iy < met->
ny; iy++)
7802 for (
int ix = 0; ix < met->
nx; ix++) {
7805 const float aux = help[
ARRAY_2D(ix, iy, met->
ny)];
7806 if ((fillval == 0 || aux != fillval)
7807 && (missval == 0 || aux != missval)
7808 && fabsf(aux) < 1e14f)
7809 dest[ix][iy] += scl * aux;
7827 const char *varname,
7828 const char *varname2,
7829 const char *varname3,
7830 const char *varname4,
7838 float offset, scalfac;
7843 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
7844 sprintf(varsel,
"%s", varname);
7845 else if (varname2 != NULL
7846 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
7847 sprintf(varsel,
"%s", varname2);
7848 else if (varname3 != NULL
7849 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
7850 sprintf(varsel,
"%s", varname3);
7851 else if (varname4 != NULL
7852 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
7853 sprintf(varsel,
"%s", varname4);
7859 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
7860 && nc_get_att_float(ncid, varid,
"scale_factor",
7861 &scalfac) == NC_NOERR) {
7869 short fillval, missval;
7870 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
7872 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
7876 LOG(2,
"Read 3-D variable: %s "
7877 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
7878 varsel, fillval, missval, scalfac, offset);
7881 NC(nc_get_var_short(ncid, varid, help));
7885 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
7888#pragma omp parallel for default(shared) num_threads(12)
7889 for (
int ix = 0; ix < met->
nx; ix++)
7890 for (
int iy = 0; iy < met->
ny; iy++)
7891 for (
int ip = 0; ip < met->
np; ip++) {
7892 const short aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
7893 if ((fillval == 0 || aux != fillval)
7894 && (missval == 0 || aux != missval)
7895 && fabsf(aux * scalfac + offset) < 1e14f)
7896 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
7898 dest[ix][iy][ip] = NAN;
7914 float fillval, missval;
7915 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
7917 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
7921 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
7922 varsel, fillval, missval);
7925 NC(nc_get_var_float(ncid, varid, help));
7931#pragma omp parallel for default(shared) num_threads(12)
7932 for (
int ix = 0; ix < met->
nx; ix++)
7933 for (
int iy = 0; iy < met->
ny; iy++)
7934 for (
int ip = 0; ip < met->
np; ip++) {
7935 const float aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
7936 if ((fillval == 0 || aux != fillval)
7937 && (missval == 0 || aux != missval)
7938 && fabsf(aux) < 1e14f)
7939 dest[ix][iy][ip] = scl * aux;
7941 dest[ix][iy][ip] = NAN;
7947#pragma omp parallel for default(shared) num_threads(12)
7948 for (
int ip = 0; ip < met->
np; ip++)
7949 for (
int iy = 0; iy < met->
ny; iy++)
7950 for (
int ix = 0; ix < met->
nx; ix++) {
7951 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
7952 if ((fillval == 0 || aux != fillval)
7953 && (missval == 0 || aux != missval)
7954 && fabsf(aux) < 1e14f)
7955 dest[ix][iy][ip] = scl * aux;
7957 dest[ix][iy][ip] = NAN;
7977 LOG(2,
"Calculate planetary boundary layer...");
7983#pragma omp parallel for default(shared) collapse(2)
7984 for (
int ix = 0; ix < met->
nx; ix++)
7985 for (
int iy = 0; iy < met->
ny; iy++) {
7988 const float z = met->
zs[ix][iy] + met->
pbl[ix][iy];
7991 (float) (
LIN(met->
z[ix][iy][ip], met->
p[ip],
7992 met->
z[ix][iy][ip + 1], met->
p[ip + 1], z));
8001 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
8004#pragma omp parallel for default(shared) collapse(2)
8005 for (
int ix = 0; ix < met->
nx; ix++)
8006 for (
int iy = 0; iy < met->
ny; iy++) {
8009 const double pbl_bot = met->
ps[ix][iy] * exp(-dz /
H0);
8013 for (ip = 1; ip < met->
np; ip++)
8014 if (met->
p[ip] < pbl_bot)
8018 const double h2os =
LIN(met->
p[ip - 1], met->
h2o[ix][iy][ip - 1],
8019 met->
p[ip], met->
h2o[ix][iy][ip], pbl_bot);
8020 const double tvs =
THETAVIRT(pbl_bot, met->
ts[ix][iy], h2os);
8026 for (; ip < met->
np; ip++) {
8029 double vh2 =
SQR(met->
u[ix][iy][ip] - met->
us[ix][iy])
8030 +
SQR(met->
v[ix][iy][ip] - met->
vs[ix][iy]);
8031 vh2 =
MAX(vh2,
SQR(umin));
8035 G0 * 1e3 * (met->
z[ix][iy][ip] - met->
zs[ix][iy]) / tvs
8037 met->
h2o[ix][iy][ip]) - tvs) / vh2;
8040 if (rib >= rib_crit) {
8041 met->
pbl[ix][iy] = (float) (
LIN(rib_old, met->
p[ip - 1],
8042 rib, met->
p[ip], rib_crit));
8043 if (met->
pbl[ix][iy] > pbl_bot)
8044 met->
pbl[ix][iy] = (float) pbl_bot;
8059 const double dtheta = 2.0, zmin = 0.1;
8062#pragma omp parallel for default(shared) collapse(2)
8063 for (
int ix = 0; ix < met->
nx; ix++)
8064 for (
int iy = 0; iy < met->
ny; iy++) {
8067 const double theta0 =
THETA(met->
ps[ix][iy], met->
ts[ix][iy]);
8071 for (ip = met->
np - 2; ip > 0; ip--)
8072 if (met->
p[ip] >= 300.)
8073 if (met->
p[ip] > met->
ps[ix][iy]
8074 ||
THETA(met->
p[ip], met->
t[ix][iy][ip]) <= theta0 + dtheta)
8079 = (float) (
LIN(
THETA(met->
p[ip + 1], met->
t[ix][iy][ip + 1]),
8081 THETA(met->
p[ip], met->
t[ix][iy][ip]),
8082 met->
p[ip], theta0 + dtheta));
8085 double pbl_min = met->
ps[ix][iy] * exp(-zmin /
H0);
8086 if (met->
pbl[ix][iy] > pbl_min || met->
p[ip] > met->
ps[ix][iy])
8087 met->
pbl[ix][iy] = (float) pbl_min;
8092#pragma omp parallel for default(shared) collapse(2)
8093 for (
int ix = 0; ix < met->
nx; ix++)
8094 for (
int iy = 0; iy < met->
ny; iy++) {
8098 met->
pbl[ix][iy] =
MIN(met->
pbl[ix][iy], (
float) pbl_min);
8102 met->
pbl[ix][iy] =
MAX(met->
pbl[ix][iy], (
float) pbl_max);
8112 SELECT_TIMER(
"READ_MET_PERIODIC",
"METPROC", NVTX_READ);
8113 LOG(2,
"Apply periodic boundary conditions...");
8116 if (!(fabs(met->
lon[met->
nx - 1] - met->
lon[0]
8117 + met->
lon[1] - met->
lon[0] - 360) < 0.01))
8121 if ((++met->
nx) >=
EX)
8122 ERRMSG(
"Cannot create periodic boundary conditions!");
8128#pragma omp parallel for default(shared)
8129 for (
int iy = 0; iy < met->
ny; iy++) {
8130 met->
ps[met->
nx - 1][iy] = met->
ps[0][iy];
8131 met->
zs[met->
nx - 1][iy] = met->
zs[0][iy];
8132 met->
ts[met->
nx - 1][iy] = met->
ts[0][iy];
8133 met->
us[met->
nx - 1][iy] = met->
us[0][iy];
8134 met->
vs[met->
nx - 1][iy] = met->
vs[0][iy];
8135 met->
ess[met->
nx - 1][iy] = met->
ess[0][iy];
8136 met->
nss[met->
nx - 1][iy] = met->
nss[0][iy];
8137 met->
shf[met->
nx - 1][iy] = met->
shf[0][iy];
8138 met->
lsm[met->
nx - 1][iy] = met->
lsm[0][iy];
8139 met->
sst[met->
nx - 1][iy] = met->
sst[0][iy];
8140 met->
pbl[met->
nx - 1][iy] = met->
pbl[0][iy];
8141 met->
cape[met->
nx - 1][iy] = met->
cape[0][iy];
8142 met->
cin[met->
nx - 1][iy] = met->
cin[0][iy];
8143 for (
int ip = 0; ip < met->
np; ip++) {
8144 met->
t[met->
nx - 1][iy][ip] = met->
t[0][iy][ip];
8145 met->
u[met->
nx - 1][iy][ip] = met->
u[0][iy][ip];
8146 met->
v[met->
nx - 1][iy][ip] = met->
v[0][iy][ip];
8147 met->
w[met->
nx - 1][iy][ip] = met->
w[0][iy][ip];
8148 met->
h2o[met->
nx - 1][iy][ip] = met->
h2o[0][iy][ip];
8149 met->
o3[met->
nx - 1][iy][ip] = met->
o3[0][iy][ip];
8150 met->
lwc[met->
nx - 1][iy][ip] = met->
lwc[0][iy][ip];
8151 met->
rwc[met->
nx - 1][iy][ip] = met->
rwc[0][iy][ip];
8152 met->
iwc[met->
nx - 1][iy][ip] = met->
iwc[0][iy][ip];
8153 met->
swc[met->
nx - 1][iy][ip] = met->
swc[0][iy][ip];
8154 met->
cc[met->
nx - 1][iy][ip] = met->
cc[0][iy][ip];
8156 for (
int ip = 0; ip < met->
npl; ip++) {
8157 met->
ul[met->
nx - 1][iy][ip] = met->
ul[0][iy][ip];
8158 met->
vl[met->
nx - 1][iy][ip] = met->
vl[0][iy][ip];
8159 met->
wl[met->
nx - 1][iy][ip] = met->
wl[0][iy][ip];
8160 met->
pl[met->
nx - 1][iy][ip] = met->
pl[0][iy][ip];
8161 met->
zetal[met->
nx - 1][iy][ip] = met->
zetal[0][iy][ip];
8173 SELECT_TIMER(
"READ_MET_POLAR_WINDS",
"METPROC", NVTX_READ);
8174 LOG(2,
"Apply fix for polar winds...");
8177 if (fabs(met->
lat[0]) < 89.999 || fabs(met->
lat[met->
ny - 1]) < 89.999)
8181 for (
int ihem = 0; ihem < 2; ihem++) {
8184 int i89 = 1, i90 = 0, sign = 1;
8189 if (met->
lat[i90] < 0)
8193 double clon[
EX], slon[
EX];
8194#pragma omp parallel for default(shared)
8195 for (
int ix = 0; ix < met->
nx; ix++) {
8196 clon[ix] = cos(sign *
DEG2RAD(met->
lon[ix]));
8197 slon[ix] = sin(sign *
DEG2RAD(met->
lon[ix]));
8201#pragma omp parallel for default(shared)
8202 for (
int ip = 0; ip < met->
np; ip++) {
8205 double vel89x = 0, vel89y = 0;
8206 for (
int ix = 0; ix < met->
nx; ix++) {
8208 (met->
u[ix][i89][ip] * clon[ix] -
8209 met->
v[ix][i89][ip] * slon[ix]) / met->
nx;
8211 (met->
u[ix][i89][ip] * slon[ix] +
8212 met->
v[ix][i89][ip] * clon[ix]) / met->
nx;
8216 for (
int ix = 0; ix < met->
nx; ix++) {
8218 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
8220 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
8235 LOG(2,
"Calculate potential vorticity...");
8238#pragma omp parallel for default(shared)
8239 for (
int ip = 0; ip < met->
np; ip++)
8240 pows[ip] = pow(1000. / met->
p[ip], 0.286);
8243#pragma omp parallel for default(shared)
8244 for (
int ix = 0; ix < met->
nx; ix++) {
8247 const int ix0 =
MAX(ix - 1, 0);
8248 const int ix1 =
MIN(ix + 1, met->
nx - 1);
8251 for (
int iy = 0; iy < met->
ny; iy++) {
8254 const int iy0 =
MAX(iy - 1, 0);
8255 const int iy1 =
MIN(iy + 1, met->
ny - 1);
8258 const double latr = 0.5 * (met->
lat[iy1] + met->
lat[iy0]);
8259 const double dx = 1000. *
DEG2DX(met->
lon[ix1] - met->
lon[ix0], latr);
8260 const double dy = 1000. *
DEG2DY(met->
lat[iy1] - met->
lat[iy0]);
8261 const double c0 = cos(
DEG2RAD(met->
lat[iy0]));
8262 const double c1 = cos(
DEG2RAD(met->
lat[iy1]));
8263 const double cr = cos(
DEG2RAD(latr));
8264 const double vort = 2 * 7.2921e-5 * sin(
DEG2RAD(latr));
8267 for (
int ip = 0; ip < met->
np; ip++) {
8271 = (met->
t[ix1][iy][ip] - met->
t[ix0][iy][ip]) * pows[ip] / dx;
8272 const double dvdx = (met->
v[ix1][iy][ip] - met->
v[ix0][iy][ip]) / dx;
8276 = (met->
t[ix][iy1][ip] - met->
t[ix][iy0][ip]) * pows[ip] / dy;
8278 = (met->
u[ix][iy1][ip] * c1 - met->
u[ix][iy0][ip] * c0) / dy;
8281 const int ip0 =
MAX(ip - 1, 0);
8282 const int ip1 =
MIN(ip + 1, met->
np - 1);
8285 double dtdp, dudp, dvdp;
8286 const double dp0 = 100. * (met->
p[ip] - met->
p[ip0]);
8287 const double dp1 = 100. * (met->
p[ip1] - met->
p[ip]);
8288 if (ip != ip0 && ip != ip1) {
8289 double denom = dp0 * dp1 * (dp0 + dp1);
8290 dtdp = (dp0 * dp0 * met->
t[ix][iy][ip1] * pows[ip1]
8291 - dp1 * dp1 * met->
t[ix][iy][ip0] * pows[ip0]
8292 + (dp1 * dp1 - dp0 * dp0) * met->
t[ix][iy][ip] * pows[ip])
8294 dudp = (dp0 * dp0 * met->
u[ix][iy][ip1]
8295 - dp1 * dp1 * met->
u[ix][iy][ip0]
8296 + (dp1 * dp1 - dp0 * dp0) * met->
u[ix][iy][ip])
8298 dvdp = (dp0 * dp0 * met->
v[ix][iy][ip1]
8299 - dp1 * dp1 * met->
v[ix][iy][ip0]
8300 + (dp1 * dp1 - dp0 * dp0) * met->
v[ix][iy][ip])
8303 const double denom = dp0 + dp1;
8305 (met->
t[ix][iy][ip1] * pows[ip1] -
8306 met->
t[ix][iy][ip0] * pows[ip0]) / denom;
8307 dudp = (met->
u[ix][iy][ip1] - met->
u[ix][iy][ip0]) / denom;
8308 dvdp = (met->
v[ix][iy][ip1] - met->
v[ix][iy][ip0]) / denom;
8312 met->
pv[ix][iy][ip] = (float)
8314 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
8320#pragma omp parallel for default(shared)
8321 for (
int ix = 0; ix < met->
nx; ix++)
8322 for (
int ip = 0; ip < met->
np; ip++) {
8324 = met->
pv[ix][1][ip]
8325 = met->
pv[ix][2][ip];
8326 met->
pv[ix][met->
ny - 1][ip]
8327 = met->
pv[ix][met->
ny - 2][ip]
8328 = met->
pv[ix][met->
ny - 3][ip];
8339 LOG(2,
"Calculate total column ozone...");
8342#pragma omp parallel for default(shared) collapse(2)
8343 for (
int ix = 0; ix < met->
nx; ix++)
8344 for (
int iy = 0; iy < met->
ny; iy++) {
8348 for (
int ip = 1; ip < met->
np; ip++)
8349 if (met->
p[ip - 1] <= met->
ps[ix][iy]) {
8351 0.5 * (met->
o3[ix][iy][ip - 1] + met->
o3[ix][iy][ip]);
8352 const double dp = met->
p[ip - 1] - met->
p[ip];
8353 cd += vmr *
MO3 /
MA * dp * 1e2 /
G0;
8357 met->
o3c[ix][iy] = (float) (cd / 2.1415e-5);
8376 LOG(2,
"Downsampling of meteo data...");
8385 memcpy(help->
lon, met->
lon,
sizeof(met->
lon));
8386 memcpy(help->
lat, met->
lat,
sizeof(met->
lat));
8387 memcpy(help->
p, met->
p,
sizeof(met->
p));
8390 for (
int ix = 0; ix < met->
nx; ix += ctl->
met_dx) {
8391 for (
int iy = 0; iy < met->
ny; iy += ctl->
met_dy) {
8392 for (
int ip = 0; ip < met->
np; ip += ctl->
met_dp) {
8393 help->
ps[ix][iy] = 0;
8394 help->
zs[ix][iy] = 0;
8395 help->
ts[ix][iy] = 0;
8396 help->
us[ix][iy] = 0;
8397 help->
vs[ix][iy] = 0;
8398 help->
ess[ix][iy] = 0;
8399 help->
nss[ix][iy] = 0;
8400 help->
shf[ix][iy] = 0;
8401 help->
lsm[ix][iy] = 0;
8402 help->
sst[ix][iy] = 0;
8403 help->
pbl[ix][iy] = 0;
8404 help->
cape[ix][iy] = 0;
8405 help->
cin[ix][iy] = 0;
8406 help->
t[ix][iy][ip] = 0;
8407 help->
u[ix][iy][ip] = 0;
8408 help->
v[ix][iy][ip] = 0;
8409 help->
w[ix][iy][ip] = 0;
8410 help->
h2o[ix][iy][ip] = 0;
8411 help->
o3[ix][iy][ip] = 0;
8412 help->
lwc[ix][iy][ip] = 0;
8413 help->
rwc[ix][iy][ip] = 0;
8414 help->
iwc[ix][iy][ip] = 0;
8415 help->
swc[ix][iy][ip] = 0;
8416 help->
cc[ix][iy][ip] = 0;
8418 for (
int ix2 = ix - ctl->
met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
8423 else if (ix3 >= met->
nx)
8426 for (
int iy2 =
MAX(iy - ctl->
met_sy + 1, 0);
8427 iy2 <=
MIN(iy + ctl->
met_sy - 1, met->
ny - 1); iy2++)
8428 for (
int ip2 =
MAX(ip - ctl->
met_sp + 1, 0);
8429 ip2 <=
MIN(ip + ctl->
met_sp - 1, met->
np - 1); ip2++) {
8430 float w = (1.0f - (float) abs(ix - ix2) / (float) ctl->
met_sx)
8431 * (1.0f - (float) abs(iy - iy2) / (float) ctl->
met_sy)
8432 * (1.0f - (float) abs(ip - ip2) / (float) ctl->
met_sp);
8433 help->
ps[ix][iy] += w * met->
ps[ix3][iy2];
8434 help->
zs[ix][iy] += w * met->
zs[ix3][iy2];
8435 help->
ts[ix][iy] += w * met->
ts[ix3][iy2];
8436 help->
us[ix][iy] += w * met->
us[ix3][iy2];
8437 help->
vs[ix][iy] += w * met->
vs[ix3][iy2];
8438 help->
ess[ix][iy] += w * met->
ess[ix3][iy2];
8439 help->
nss[ix][iy] += w * met->
nss[ix3][iy2];
8440 help->
shf[ix][iy] += w * met->
shf[ix3][iy2];
8441 help->
lsm[ix][iy] += w * met->
lsm[ix3][iy2];
8442 help->
sst[ix][iy] += w * met->
sst[ix3][iy2];
8443 help->
pbl[ix][iy] += w * met->
pbl[ix3][iy2];
8444 help->
cape[ix][iy] += w * met->
cape[ix3][iy2];
8445 help->
cin[ix][iy] += w * met->
cin[ix3][iy2];
8446 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip2];
8447 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip2];
8448 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip2];
8449 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip2];
8450 help->
h2o[ix][iy][ip] += w * met->
h2o[ix3][iy2][ip2];
8451 help->
o3[ix][iy][ip] += w * met->
o3[ix3][iy2][ip2];
8452 help->
lwc[ix][iy][ip] += w * met->
lwc[ix3][iy2][ip2];
8453 help->
rwc[ix][iy][ip] += w * met->
rwc[ix3][iy2][ip2];
8454 help->
iwc[ix][iy][ip] += w * met->
iwc[ix3][iy2][ip2];
8455 help->
swc[ix][iy][ip] += w * met->
swc[ix3][iy2][ip2];
8456 help->
cc[ix][iy][ip] += w * met->
cc[ix3][iy2][ip2];
8460 help->
ps[ix][iy] /= wsum;
8461 help->
zs[ix][iy] /= wsum;
8462 help->
ts[ix][iy] /= wsum;
8463 help->
us[ix][iy] /= wsum;
8464 help->
vs[ix][iy] /= wsum;
8465 help->
ess[ix][iy] /= wsum;
8466 help->
nss[ix][iy] /= wsum;
8467 help->
shf[ix][iy] /= wsum;
8468 help->
lsm[ix][iy] /= wsum;
8469 help->
sst[ix][iy] /= wsum;
8470 help->
pbl[ix][iy] /= wsum;
8471 help->
cape[ix][iy] /= wsum;
8472 help->
cin[ix][iy] /= wsum;
8473 help->
t[ix][iy][ip] /= wsum;
8474 help->
u[ix][iy][ip] /= wsum;
8475 help->
v[ix][iy][ip] /= wsum;
8476 help->
w[ix][iy][ip] /= wsum;
8477 help->
h2o[ix][iy][ip] /= wsum;
8478 help->
o3[ix][iy][ip] /= wsum;
8479 help->
lwc[ix][iy][ip] /= wsum;
8480 help->
rwc[ix][iy][ip] /= wsum;
8481 help->
iwc[ix][iy][ip] /= wsum;
8482 help->
swc[ix][iy][ip] /= wsum;
8483 help->
cc[ix][iy][ip] /= wsum;
8490 for (
int ix = 0; ix < help->
nx; ix += ctl->
met_dx) {
8493 for (
int iy = 0; iy < help->
ny; iy += ctl->
met_dy) {
8495 met->
ps[met->
nx][met->
ny] = help->
ps[ix][iy];
8496 met->
zs[met->
nx][met->
ny] = help->
zs[ix][iy];
8497 met->
ts[met->
nx][met->
ny] = help->
ts[ix][iy];
8498 met->
us[met->
nx][met->
ny] = help->
us[ix][iy];
8499 met->
vs[met->
nx][met->
ny] = help->
vs[ix][iy];
8500 met->
ess[met->
nx][met->
ny] = help->
ess[ix][iy];
8501 met->
nss[met->
nx][met->
ny] = help->
nss[ix][iy];
8502 met->
shf[met->
nx][met->
ny] = help->
shf[ix][iy];
8503 met->
lsm[met->
nx][met->
ny] = help->
lsm[ix][iy];
8504 met->
sst[met->
nx][met->
ny] = help->
sst[ix][iy];
8505 met->
pbl[met->
nx][met->
ny] = help->
pbl[ix][iy];
8507 met->
cin[met->
nx][met->
ny] = help->
cin[ix][iy];
8509 for (
int ip = 0; ip < help->
np; ip += ctl->
met_dp) {
8510 met->
p[met->
np] = help->
p[ip];
8511 met->
t[met->
nx][met->
ny][met->
np] = help->
t[ix][iy][ip];
8512 met->
u[met->
nx][met->
ny][met->
np] = help->
u[ix][iy][ip];
8513 met->
v[met->
nx][met->
ny][met->
np] = help->
v[ix][iy][ip];
8514 met->
w[met->
nx][met->
ny][met->
np] = help->
w[ix][iy][ip];
8515 met->
h2o[met->
nx][met->
ny][met->
np] = help->
h2o[ix][iy][ip];
8516 met->
o3[met->
nx][met->
ny][met->
np] = help->
o3[ix][iy][ip];
8517 met->
lwc[met->
nx][met->
ny][met->
np] = help->
lwc[ix][iy][ip];
8518 met->
rwc[met->
nx][met->
ny][met->
np] = help->
rwc[ix][iy][ip];
8519 met->
iwc[met->
nx][met->
ny][met->
np] = help->
iwc[ix][iy][ip];
8520 met->
swc[met->
nx][met->
ny][met->
np] = help->
swc[ix][iy][ip];
8521 met->
cc[met->
nx][met->
ny][met->
np] = help->
cc[ix][iy][ip];
8542 LOG(2,
"Read surface data...");
8546 (ncid,
"lnsp",
"LNSP", NULL, NULL, NULL, NULL, ctl, met, met->
ps, 1.0f,
8548 for (
int ix = 0; ix < met->
nx; ix++)
8549 for (
int iy = 0; iy < met->
ny; iy++)
8550 met->
ps[ix][iy] = (
float) (exp(met->
ps[ix][iy]) / 100.);
8553 (ncid,
"ps",
"PS",
"sp",
"SP", NULL, NULL, ctl, met, met->
ps, 0.01f,
8555 WARN(
"Cannot not read surface pressure data (use lowest level)!");
8556 for (
int ix = 0; ix < met->
nx; ix++)
8557 for (
int iy = 0; iy < met->
ny; iy++)
8559 = (ctl->
met_np > 0 ? (
float) ctl->
met_p[0] : (
float) met->
p[0]);
8567 (ncid,
"z",
"Z", NULL, NULL, NULL, NULL, ctl, met, met->
zs,
8568 (
float) (1. / (1000. *
G0)), 1))
8570 (ncid,
"zm",
"ZM", NULL, NULL, NULL, NULL, ctl, met, met->
zs,
8571 (
float) (1. / 1000.), 1))
8572 WARN(
"Cannot read surface geopotential height!");
8583 memcpy(help, met->
pl,
sizeof(met->
pl));
8585 (ncid,
"gph",
"GPH", NULL, NULL, ctl, met, met->
pl,
8586 (
float) (1e-3 /
G0)))
8587 ERRMSG(
"Cannot read geopotential height!");
8588 for (
int ix = 0; ix < met->
nx; ix++)
8589 for (
int iy = 0; iy < met->
ny; iy++)
8590 met->
zs[ix][iy] = met->
pl[ix][iy][0];
8591 memcpy(met->
pl, help,
sizeof(met->
pl));
8597 (ncid,
"t2m",
"T2M",
"2t",
"2T",
"t2",
"T2", ctl, met, met->
ts, 1.0, 1))
8598 WARN(
"Cannot read surface temperature!");
8602 (ncid,
"u10m",
"U10M",
"10u",
"10U",
"u10",
"U10", ctl, met, met->
us,
8604 WARN(
"Cannot read surface zonal wind!");
8608 (ncid,
"v10m",
"V10M",
"10v",
"10V",
"v10",
"V10", ctl, met, met->
vs,
8610 WARN(
"Cannot read surface meridional wind!");
8614 (ncid,
"iews",
"IEWS", NULL, NULL, NULL, NULL, ctl, met, met->
ess, 1.0,
8616 WARN(
"Cannot read eastward turbulent surface stress!");
8620 (ncid,
"inss",
"INSS", NULL, NULL, NULL, NULL, ctl, met, met->
nss, 1.0,
8622 WARN(
"Cannot read nothward turbulent surface stress!");
8626 (ncid,
"ishf",
"ISHF", NULL, NULL, NULL, NULL, ctl, met, met->
shf, 1.0,
8628 WARN(
"Cannot read surface sensible heat flux!");
8632 (ncid,
"lsm",
"LSM", NULL, NULL, NULL, NULL, ctl, met, met->
lsm, 1.0,
8634 WARN(
"Cannot read land-sea mask!");
8638 (ncid,
"sstk",
"SSTK",
"sst",
"SST", NULL, NULL, ctl, met, met->
sst,
8640 WARN(
"Cannot read sea surface temperature!");
8645 (ncid,
"blp",
"BLP", NULL, NULL, NULL, NULL, ctl, met, met->
pbl,
8647 WARN(
"Cannot read planetary boundary layer pressure!");
8650 (ncid,
"blh",
"BLH", NULL, NULL, NULL, NULL, ctl, met, met->
pbl,
8652 WARN(
"Cannot read planetary boundary layer height!");
8657 (ncid,
"cape",
"CAPE", NULL, NULL, NULL, NULL, ctl, met, met->
cape,
8659 WARN(
"Cannot read CAPE!");
8664 (ncid,
"cin",
"CIN", NULL, NULL, NULL, NULL, ctl, met, met->
cin,
8666 WARN(
"Cannot read convective inhibition!");
8676 double p2[200], pv[
EP], pv2[200], t[
EP], t2[200], th[
EP],
8677 th2[200], z[
EP], z2[200];
8681 LOG(2,
"Calculate tropopause...");
8684#pragma omp parallel for default(shared)
8685 for (
int iz = 0; iz < met->
np; iz++)
8686 z[iz] =
Z(met->
p[iz]);
8687#pragma omp parallel for default(shared)
8688 for (
int iz = 0; iz <= 190; iz++) {
8689 z2[iz] = 4.5 + 0.1 * iz;
8695#pragma omp parallel for default(shared) collapse(2)
8696 for (
int ix = 0; ix < met->
nx; ix++)
8697 for (
int iy = 0; iy < met->
ny; iy++)
8698 met->
pt[ix][iy] = NAN;
8702#pragma omp parallel for default(shared) collapse(2)
8703 for (
int ix = 0; ix < met->
nx; ix++)
8704 for (
int iy = 0; iy < met->
ny; iy++)
8712#pragma omp parallel for default(shared) private(t,t2) collapse(2)
8713 for (
int ix = 0; ix < met->
nx; ix++)
8714 for (
int iy = 0; iy < met->
ny; iy++) {
8717 for (
int iz = 0; iz < met->
np; iz++)
8718 t[iz] = met->
t[ix][iy][iz];
8722 int iz = (int) gsl_stats_min_index(t2, 1, 171);
8723 if (iz > 0 && iz < 170)
8724 met->
pt[ix][iy] = (float) p2[iz];
8726 met->
pt[ix][iy] = NAN;
8734#pragma omp parallel for default(shared) private(t,t2) collapse(2)
8735 for (
int ix = 0; ix < met->
nx; ix++)
8736 for (
int iy = 0; iy < met->
ny; iy++) {
8740 for (iz = 0; iz < met->
np; iz++)
8741 t[iz] = met->
t[ix][iy][iz];
8745 met->
pt[ix][iy] = NAN;
8746 for (iz = 0; iz <= 170; iz++) {
8748 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
8749 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
8754 if (iz > 0 && iz < 170)
8755 met->
pt[ix][iy] = (float) p2[iz];
8762 met->
pt[ix][iy] = NAN;
8763 for (; iz <= 170; iz++) {
8765 for (
int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
8766 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
8773 for (; iz <= 170; iz++) {
8775 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
8776 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
8781 if (iz > 0 && iz < 170)
8782 met->
pt[ix][iy] = (float) p2[iz];
8794#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
8795 for (
int ix = 0; ix < met->
nx; ix++)
8796 for (
int iy = 0; iy < met->
ny; iy++) {
8799 for (
int iz = 0; iz < met->
np; iz++)
8800 pv[iz] = met->
pv[ix][iy][iz];
8804 for (
int iz = 0; iz < met->
np; iz++)
8805 th[iz] =
THETA(met->
p[iz], met->
t[ix][iy][iz]);
8809 met->
pt[ix][iy] = NAN;
8810 for (
int iz = 0; iz <= 170; iz++)
8813 if (iz > 0 && iz < 170)
8814 met->
pt[ix][iy] = (float) p2[iz];
8821 ERRMSG(
"Cannot calculate tropopause!");
8824#pragma omp parallel for default(shared) collapse(2)
8825 for (
int ix = 0; ix < met->
nx; ix++)
8826 for (
int iy = 0; iy < met->
ny; iy++) {
8827 double h2ot, tt, zt;
8830 met->
lat[iy], &tt, ci, cw, 1);
8832 met->
lat[iy], &zt, ci, cw, 0);
8834 met->
lat[iy], &h2ot, ci, cw, 0);
8835 met->
tt[ix][iy] = (float) tt;
8836 met->
zt[ix][iy] = (float) zt;
8837 met->
h2ot[ix][iy] = (float) h2ot;
8844 const char *filename,
8854 LOG(1,
"Read observation data: %s", filename);
8858 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
8860 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
8862 ERRMSG(
"Set OBS_TYPE to 0 or 1!");
8865 for (
int i = 1; i < *nobs; i++)
8866 if (rt[i] < rt[i - 1])
8867 ERRMSG(
"Time must be ascending!");
8872 LOG(2,
"Number of observations: %d", *nobs);
8873 gsl_stats_minmax(&mini, &maxi, rt, 1, (
size_t) n);
8874 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
8875 gsl_stats_minmax(&mini, &maxi, rz, 1, (
size_t) n);
8876 LOG(2,
"Altitude range: %g ... %g km", mini, maxi);
8877 gsl_stats_minmax(&mini, &maxi, rlon, 1, (
size_t) n);
8878 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
8879 gsl_stats_minmax(&mini, &maxi, rlat, 1, (
size_t) n);
8880 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
8881 gsl_stats_minmax(&mini, &maxi, robs, 1, (
size_t) n);
8882 LOG(2,
"Observation range: %g ... %g", mini, maxi);
8888 const char *filename,
8898 if (!(in = fopen(filename,
"r")))
8899 ERRMSG(
"Cannot open file!");
8903 while (fgets(line,
LEN, in))
8904 if (sscanf(line,
"%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
8905 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
8906 if ((++(*nobs)) >=
NOBS)
8907 ERRMSG(
"Too many observations!");
8916 const char *filename,
8927 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
8928 ERRMSG(
"Cannot open file!");
8945 const char *filename,
8948 const char *varname,
8950 const char *defvalue,
8955 char fullname1[
LEN], fullname2[
LEN], rval[
LEN];
8960 if (filename[strlen(filename) - 1] !=
'-')
8961 if (!(in = fopen(filename,
"r")))
8962 ERRMSG(
"Cannot open file!");
8966 sprintf(fullname1,
"%s[%d]", varname, arridx);
8967 sprintf(fullname2,
"%s[*]", varname);
8969 sprintf(fullname1,
"%s", varname);
8970 sprintf(fullname2,
"%s", varname);
8975 char dummy[
LEN], line[
LEN], rvarname[
LEN];
8976 while (fgets(line,
LEN, in)) {
8977 if (sscanf(line,
"%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
8978 if (strcasecmp(rvarname, fullname1) == 0 ||
8979 strcasecmp(rvarname, fullname2) == 0) {
8985 for (i = 1; i < argc - 1; i++)
8986 if (strcasecmp(argv[i], fullname1) == 0 ||
8987 strcasecmp(argv[i], fullname2) == 0) {
8988 sprintf(rval,
"%s", argv[i + 1]);
8999 if (strlen(defvalue) > 0)
9000 sprintf(rval,
"%s", defvalue);
9002 ERRMSG(
"Missing variable %s!\n", fullname1);
9006 LOG(1,
"%s = %s", fullname1, rval);
9010 sprintf(value,
"%s", rval);
9020 const double rhop) {
9023 const double rp_help = rp * 1e-6;
9026 const double rho =
RHO(p, T);
9029 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
9032 const double v = sqrt(8. *
KB * T / (M_PI * 4.8096e-26));
9035 const double lambda = 2. * eta / (rho * v);
9038 const double K = lambda / rp_help;
9041 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
9044 return 2. *
SQR(rp_help) * (rhop - rho) *
G0 / (9. * eta) * G;
9062 gsl_interp_accel *acc = gsl_interp_accel_alloc();
9063 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (
size_t) n);
9066 gsl_spline_init(s, x, y, (
size_t) n);
9067 for (
int i = 0; i < n2; i++)
9070 else if (x2[i] >= x[n - 1])
9073 y2[i] = gsl_spline_eval(s, x2[i], acc);
9077 gsl_interp_accel_free(acc);
9082 for (
int i = 0; i < n2; i++)
9085 else if (x2[i] >= x[n - 1])
9089 y2[i] =
LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
9103 float mean = 0, var = 0;
9105 for (
int i = 0; i < n; ++i) {
9107 var +=
SQR(data[i]);
9110 var = var / (float) n -
SQR(mean / (
float) n);
9112 return (var > 0 ? sqrtf(var) : 0);
9123 const double D = sec / 86400 - 0.5;
9126 const double g =
DEG2RAD(357.529 + 0.98560028 * D);
9127 const double q = 280.459 + 0.98564736 * D;
9128 const double L =
DEG2RAD(q + 1.915 * sin(g) + 0.020 * sin(2 * g));
9131 const double e =
DEG2RAD(23.439 - 0.00000036 * D);
9134 const double sindec = sin(e) * sin(L);
9137 const double ra = atan2(cos(e) * sin(L), cos(L));
9140 const double GMST = 18.697374558 + 24.06570982441908 * D;
9143 const double LST = GMST + lon / 15;
9146 const double h = LST / 12 * M_PI - ra;
9149 const double lat_help =
DEG2RAD(lat);
9152 return acos(sin(lat_help) * sindec +
9153 cos(lat_help) * sqrt(1 -
SQR(sindec)) * cos(h));
9165 const double remain,
9177 t1.tm_year = year - 1900;
9178 t1.tm_mon = mon - 1;
9184 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
9199 static int iname = -1, igroup = -1, nname, ngroup, ct_name[
NTIMER];
9202 t1 = omp_get_wtime();
9207 rt_name[iname] += dt;
9208 rt_min[iname] = (ct_name[iname] <= 0 ? dt :
MIN(rt_min[iname], dt));
9209 rt_max[iname] = (ct_name[iname] <= 0 ? dt :
MAX(rt_max[iname], dt));
9213 rt_group[igroup] += t1 - t0;
9217 for (
int i = 0; i < nname; i++)
9218 LOG(1,
"TIMER_%s = %.3f s (min= %g s, mean= %g s,"
9219 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
9220 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
9221 for (
int i = 0; i < ngroup; i++)
9222 LOG(1,
"TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
9224 for (
int i = 0; i < nname; i++)
9225 total += rt_name[i];
9226 LOG(1,
"TIMER_TOTAL = %.3f s", total);
9230 for (iname = 0; iname < nname; iname++)
9231 if (strcasecmp(name, names[iname]) == 0)
9233 for (igroup = 0; igroup < ngroup; igroup++)
9234 if (strcasecmp(group, groups[igroup]) == 0)
9238 if (iname >= nname) {
9239 sprintf(names[iname],
"%s", name);
9241 ERRMSG(
"Too many timers!");
9245 if (igroup >= ngroup) {
9246 sprintf(groups[igroup],
"%s", group);
9247 if ((++ngroup) >=
NTIMER)
9248 ERRMSG(
"Too many groups!");
9258 const char *filename,
9266 int len = (int) strlen(filename);
9267 sprintf(tstr,
"%.4s", &filename[len - offset]);
9268 int year = atoi(tstr);
9269 sprintf(tstr,
"%.2s", &filename[len - offset + 5]);
9270 int mon = atoi(tstr);
9271 sprintf(tstr,
"%.2s", &filename[len - offset + 8]);
9272 int day = atoi(tstr);
9273 sprintf(tstr,
"%.2s", &filename[len - offset + 11]);
9274 int hour = atoi(tstr);
9275 sprintf(tstr,
"%.2s", &filename[len - offset + 14]);
9276 int min = atoi(tstr);
9279 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
9280 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
9281 ERRMSG(
"Cannot read time from filename!");
9284 time2jsec(year, mon, day, hour, min, 0, 0.0, &t);
9301 const double p1 = pt * 0.866877899;
9302 const double p0 = pt / 0.866877899;
9305 if (atm->
p[ip] > p0)
9307 else if (atm->
p[ip] < p1)
9310 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
9316 const char *filename,
9324 const double t0 = t - 0.5 * ctl->
dt_mod;
9325 const double t1 = t + 0.5 * ctl->
dt_mod;
9331 if (!(out = popen(
"gnuplot",
"w")))
9332 ERRMSG(
"Cannot create pipe to gnuplot!");
9335 fprintf(out,
"set out \"%s.png\"\n", filename);
9339 int year, mon, day, hour, min, sec;
9340 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
9341 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
9342 year, mon, day, hour, min);
9347 ERRMSG(
"Cannot open file!");
9349 while (fgets(line,
LEN, in))
9350 fprintf(out,
"%s", line);
9357 if (!(out = fopen(filename,
"w")))
9358 ERRMSG(
"Cannot create file!");
9364 "# $2 = altitude [km]\n"
9365 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
9366 for (
int iq = 0; iq < ctl->
nq; iq++)
9367 fprintf(out,
"# $%i = %s [%s]\n", iq + 5, ctl->
qnt_name[iq],
9372 for (
int ip = 0; ip < atm->
np; ip += ctl->
atm_stride) {
9379 fprintf(out,
"%.2f %g %g %g", atm->
time[ip],
Z(atm->
p[ip]),
9380 atm->
lon[ip], atm->
lat[ip]);
9381 for (
int iq = 0; iq < ctl->
nq; iq++) {
9386 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
9398 const char *filename,
9405 if (!(out = fopen(filename,
"w")))
9406 ERRMSG(
"Cannot create file!");
9430 for (
int iq = 0; iq < ctl->
nq; iq++)
9448 const char *filename,
9452 int tid, pid, ncid, varid;
9453 size_t start[2], count[2];
9456 nc_create(filename, NC_NETCDF4, &ncid);
9459 NC(nc_def_dim(ncid,
"time", 1, &tid));
9460 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
9463 int dim_ids[2] = { tid, pid };
9464 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
9465 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
9466 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
9468 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
9470 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
9473 for (
int iq = 0; iq < ctl->
nq; iq++)
9483 NC(nc_enddef(ncid));
9491 for (
int iq = 0; iq < ctl->
nq; iq++)
9501 const char *dirname,
9507 static size_t out_cnt = 0;
9509 double r, r_start, r_stop;
9510 int year, mon, day, hour, min, sec;
9511 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
9512 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
9513 char filename_out[2 *
LEN] =
"traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
9515 int ncid, varid, tid, pid, cid;
9523 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
9525 &min_start, &sec_start, &r_start);
9527 &min_stop, &sec_stop, &r_stop);
9529 sprintf(filename_out,
"%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc",
9531 year_start % 100, mon_start, day_start, hour_start,
9532 year_stop % 100, mon_stop, day_stop, hour_stop);
9533 LOG(1,
"Write traj file: %s", filename_out);
9539 count[1] = (size_t) atm->
np;
9545 nc_create(filename_out, NC_NETCDF4, &ncid);
9548 NC(nc_def_dim(ncid,
"time", NC_UNLIMITED, &tid));
9549 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
9550 NC(nc_def_dim(ncid,
"TMDT", 7, &cid));
9555 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
9556 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
9557 NC_DEF_VAR(
"LAT", NC_DOUBLE, 2, dim_ids,
"Latitude",
"deg",
9559 NC_DEF_VAR(
"LON", NC_DOUBLE, 2, dim_ids,
"Longitude",
"deg",
9561 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 2, dim_ids,
"Pressure",
"hPa",
9563 NC_DEF_VAR(
"ZETA", NC_DOUBLE, 2, dim_ids,
"Zeta",
"K",
9565 for (
int iq = 0; iq < ctl->
nq; iq++)
9575 NC(nc_enddef(ncid));
9583 NC(nc_open(filename_out, NC_WRITE, &ncid));
9595 for (
int iq = 0; iq < ctl->
nq; iq++)
9602 if ((year == year_stop) && (mon == mon_stop)
9603 && (day == day_stop) && (hour == hour_stop)) {
9606 char filename_init[2 *
LEN] =
"./init_fix_YYYYMMDDHH.nc";
9607 sprintf(filename_init,
"%s/init_fix_%02d%02d%02d%02d.nc",
9608 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
9609 LOG(1,
"Write init file: %s", filename_init);
9612 nc_create(filename_init, NC_NETCDF4, &ncid);
9615 NC(nc_def_dim(ncid,
"time", 1, &tid));
9616 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
9621 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
9622 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
9623 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
9625 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
9627 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
9630 for (
int iq = 0; iq < ctl->
nq; iq++)
9640 NC(nc_enddef(ncid));
9648 for (
int iq = 0; iq < ctl->
nq; iq++)
9659 const char *filename,
9663 int ncid, obsid, varid;
9665 size_t start[2], count[2];
9668 NC(nc_create(filename, NC_NETCDF4, &ncid));
9671 NC(nc_def_dim(ncid,
"obs", (
size_t) atm->
np, &obsid));
9674 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &obsid,
"time",
9675 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
9676 NC_DEF_VAR(
"press", NC_DOUBLE, 1, &obsid,
"pressure",
"hPa",
9678 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &obsid,
"longitude",
"degrees_east",
9680 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &obsid,
"latitude",
"degrees_north",
9682 for (
int iq = 0; iq < ctl->
nq; iq++)
9691 NC(nc_enddef(ncid));
9698 for (
int iq = 0; iq < ctl->
nq; iq++)
9708 const char *filename,
9715 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
9718 static int *obscount, ct, cx, cy, cz, ip, ix, iy, iz, n, nobs, nk;
9728 ERRMSG(
"Need quantity mass!");
9752 LOG(1,
"Write CSI data: %s", filename);
9753 if (!(out = fopen(filename,
"w")))
9754 ERRMSG(
"Cannot create file!");
9759 "# $2 = number of hits (cx)\n"
9760 "# $3 = number of misses (cy)\n"
9761 "# $4 = number of false alarms (cz)\n"
9762 "# $5 = number of observations (cx + cy)\n"
9763 "# $6 = number of forecasts (cx + cz)\n"
9764 "# $7 = bias (ratio of forecasts and observations) [%%]\n"
9765 "# $8 = probability of detection (POD) [%%]\n"
9766 "# $9 = false alarm rate (FAR) [%%]\n"
9767 "# $10 = critical success index (CSI) [%%]\n");
9769 "# $11 = hits associated with random chance\n"
9770 "# $12 = equitable threat score (ETS) [%%]\n"
9771 "# $13 = Pearson linear correlation coefficient\n"
9772 "# $14 = Spearman rank-order correlation coefficient\n"
9773 "# $15 = column density mean error (F - O) [kg/m^2]\n"
9774 "# $16 = column density root mean square error (RMSE) [kg/m^2]\n"
9775 "# $17 = column density mean absolute error [kg/m^2]\n"
9776 "# $18 = log-likelihood function\n"
9777 "# $19 = number of data points\n\n");
9785 for (iy = 0; iy < ctl->
csi_ny; iy++) {
9786 const double lat = ctl->
csi_lat0 + dlat * (iy + 0.5);
9787 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat));
9792 const double t0 = t - 0.5 * ctl->
dt_mod;
9793 const double t1 = t + 0.5 * ctl->
dt_mod;
9796 ALLOC(modmean,
double,
9798 ALLOC(obsmean,
double,
9800 ALLOC(obscount,
int,
9802 ALLOC(obsstd,
double,
9806 for (
int i = 0; i < nobs; i++) {
9811 else if (rt[i] >= t1)
9815 if (!isfinite(robs[i]))
9819 ix = (int) ((rlon[i] - ctl->
csi_lon0) / dlon);
9820 iy = (int) ((rlat[i] - ctl->
csi_lat0) / dlat);
9821 iz = (int) ((rz[i] - ctl->
csi_z0) / dz);
9824 if (ix < 0 || ix >= ctl->
csi_nx ||
9825 iy < 0 || iy >= ctl->
csi_ny || iz < 0 || iz >= ctl->
csi_nz)
9830 obsmean[idx] += robs[i];
9831 obsstd[idx] +=
SQR(robs[i]);
9836 for (ip = 0; ip < atm->
np; ip++) {
9839 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
9843 ix = (int) ((atm->
lon[ip] - ctl->
csi_lon0) / dlon);
9844 iy = (int) ((atm->
lat[ip] - ctl->
csi_lat0) / dlat);
9845 iz = (int) ((
Z(atm->
p[ip]) - ctl->
csi_z0) / dz);
9848 if (ix < 0 || ix >= ctl->
csi_nx ||
9849 iy < 0 || iy >= ctl->
csi_ny || iz < 0 || iz >= ctl->
csi_nz)
9855 * atm->
q[ctl->
qnt_m][ip];
9859 for (ix = 0; ix < ctl->
csi_nx; ix++)
9860 for (iy = 0; iy < ctl->
csi_ny; iy++)
9861 for (iz = 0; iz < ctl->
csi_nz; iz++) {
9865 if (obscount[idx] > 0) {
9866 obsmean[idx] /= obscount[idx];
9867 obsstd[idx] -=
SQR(obsmean[idx]);
9868 obsstd[idx] = sqrt(obsstd[idx]);
9872 if (modmean[idx] > 0)
9873 modmean[idx] /= (1e6 * area[iy]);
9876 if (obscount[idx] > 0) {
9890 if (obscount[idx] > 0
9893 x[n] = modmean[idx];
9894 y[n] = obsmean[idx];
9896 obsstdn[n] = obsstd[idx];
9898 ERRMSG(
"Too many data points to calculate statistics!");
9907 static double work[2 *
NCSI], work2[2 *
NCSI];;
9908 const int n_obs = cx + cy;
9909 const int n_for = cx + cz;
9910 const double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
9911 const double pod = (n_obs > 0) ? (100. * cx) / n_obs : NAN;
9912 const double far = (n_for > 0) ? (100. * cz) / n_for : NAN;
9914 (cx + cy + cz > 0) ? (100. * cx) / (cx + cy + cz) : NAN;
9915 const double cx_rd = (ct > 0) ? (1. * n_obs * n_for) / ct : NAN;
9916 const double ets = (cx + cy + cz - cx_rd > 0) ?
9917 (100. * (cx - cx_rd)) / (cx + cy + cz - cx_rd) : NAN;
9918 const double rho_p =
9919 (n > 0) ? gsl_stats_correlation(x, 1, y, 1, (
size_t) n) : NAN;
9920 const double rho_s =
9921 (n > 0) ? gsl_stats_spearman(x, 1, y, 1, (
size_t) n, work) : NAN;
9922 for (
int i = 0; i < n; i++) {
9923 work[i] = x[i] - y[i];
9924 work2[i] = (obsstdn[i] != 0) ? (x[i] - y[i]) / obsstdn[i] : 0;
9926 const double mean = (n > 0) ? gsl_stats_mean(work, 1, (
size_t) n) : NAN;
9928 (n > 0) ? gsl_stats_sd_with_fixed_mean(work, 1, (
size_t) n,
9930 const double absdev =
9931 (n > 0) ? gsl_stats_absdev_m(work, 1, (
size_t) n, 0.0) : NAN;
9932 const double loglikelihood =
9933 (n > 0) ? gsl_stats_tss(work2, 1, (
size_t) n) * (-0.5) : GSL_NAN;
9937 "%.2f %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n", t,
9938 cx, cy, cz, n_obs, n_for, bias, pod, far, csi, cx_rd, ets, rho_p,
9939 rho_s, mean, rmse, absdev, loglikelihood, n);
9942 n = ct = cx = cy = cz = 0;
9970 const char *filename,
9987 ERRMSG(
"Missing ensemble IDs!");
9990 const double t0 = t - 0.5 * ctl->
dt_mod;
9991 const double t1 = t + 0.5 * ctl->
dt_mod;
9994 for (
int i = 0; i <
NENS; i++) {
9995 for (
int iq = 0; iq < ctl->
nq; iq++)
9996 qm[iq][i] = qs[iq][i] = 0;
9997 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
10002 for (
int ip = 0; ip < atm->
np; ip++) {
10005 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
10010 ERRMSG(
"Ensemble ID is out of range!");
10014 for (
int iq = 0; iq < ctl->
nq; iq++) {
10015 qm[iq][ctl->
qnt_ens] += atm->
q[iq][ip];
10026 LOG(1,
"Write ensemble data: %s", filename);
10027 if (!(out = fopen(filename,
"w")))
10028 ERRMSG(
"Cannot create file!");
10032 "# $1 = time [s]\n"
10033 "# $2 = altitude [km]\n"
10034 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
10035 for (
int iq = 0; iq < ctl->
nq; iq++)
10036 fprintf(out,
"# $%d = %s (mean) [%s]\n", 5 + iq,
10038 for (
int iq = 0; iq < ctl->
nq; iq++)
10039 fprintf(out,
"# $%d = %s (sigma) [%s]\n", 5 + ctl->
nq + iq,
10041 fprintf(out,
"# $%d = number of members\n\n", 5 + 2 * ctl->
nq);
10044 for (
int i = 0; i <
NENS; i++)
10046 cart2geo(xm[i], &dummy, &lon, &lat);
10047 fprintf(out,
"%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
10048 for (
int iq = 0; iq < ctl->
nq; iq++) {
10050 fprintf(out, ctl->
qnt_format[iq], qm[iq][i] / n[i]);
10052 for (
int iq = 0; iq < ctl->
nq; iq++) {
10054 double var = qs[iq][i] / n[i] -
SQR(qm[iq][i] / n[i]);
10055 fprintf(out, ctl->
qnt_format[iq], (var > 0 ? sqrt(var) : 0));
10057 fprintf(out,
" %d\n", n[i]);
10067 const char *filename,
10074 static double kz[
EP], kw[
EP];
10078 double *cd, *mean[
NQ], *sigma[
NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
10080 int *ixs, *iys, *izs, *np;
10086 LOG(1,
"Write grid data: %s", filename);
10099 for (
int iq = 0; iq < ctl->
nq; iq++) {
10100 ALLOC(mean[iq],
double,
10102 ALLOC(sigma[iq],
double,
10105 ALLOC(vmr_impl,
double,
10113 ALLOC(area,
double,
10115 ALLOC(press,
double,
10132#pragma omp parallel
for default(shared)
10133 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
10134 z[iz] = ctl->
grid_z0 + dz * (iz + 0.5);
10135 press[iz] =
P(z[iz]);
10139 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
10140 lon[ix] = ctl->
grid_lon0 + dlon * (ix + 0.5);
10141#pragma omp parallel for default(shared)
10142 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
10143 lat[iy] = ctl->
grid_lat0 + dlat * (iy + 0.5);
10144 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
10148 const double t0 = t - 0.5 * ctl->
dt_mod;
10149 const double t1 = t + 0.5 * ctl->
dt_mod;
10152#pragma omp parallel for default(shared)
10153 for (
int ip = 0; ip < atm->
np; ip++) {
10154 ixs[ip] = (int) ((atm->
lon[ip] - ctl->
grid_lon0) / dlon);
10155 iys[ip] = (int) ((atm->
lat[ip] - ctl->
grid_lat0) / dlat);
10156 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
grid_z0) / dz);
10157 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
10158 || ixs[ip] < 0 || ixs[ip] >= ctl->
grid_nx
10159 || iys[ip] < 0 || iys[ip] >= ctl->
grid_ny
10160 || izs[ip] < 0 || izs[ip] >= ctl->
grid_nz)
10165 for (
int ip = 0; ip < atm->
np; ip++)
10166 if (izs[ip] >= 0) {
10171 for (
int iq = 0; iq < ctl->
nq; iq++) {
10172 mean[iq][idx] += kernel * atm->
q[iq][ip];
10173 sigma[iq][idx] +=
SQR(kernel * atm->
q[iq][ip]);
10178#pragma omp parallel for default(shared)
10179 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
10180 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
10181 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
10188 if (ctl->
qnt_m >= 0)
10189 cd[idx] = mean[ctl->
qnt_m][idx] / (1e6 * area[iy]);
10192 vmr_impl[idx] = NAN;
10193 if (ctl->
qnt_m >= 0 && ctl->
molmass > 0 && met0 != NULL
10196 if (mean[ctl->
qnt_m][idx] > 0) {
10202 lon[ix], lat[iy], &temp, ci, cw, 1);
10206 MA / ctl->
molmass * cd[idx] / (
RHO(press[iz], temp) * dz * 1e3);
10212 for (
int iq = 0; iq < ctl->
nq; iq++) {
10213 mean[iq][idx] /= np[idx];
10214 double var = sigma[iq][idx] / np[idx] -
SQR(mean[iq][idx]);
10215 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
10217 for (
int iq = 0; iq < ctl->
nq; iq++) {
10218 mean[iq][idx] = NAN;
10219 sigma[iq][idx] = NAN;
10226 t, z, lon, lat, area, dz, np);
10231 t, z, lon, lat, area, dz, np);
10235 ERRMSG(
"Grid data format GRID_TYPE unknown!");
10239 for (
int iq = 0; iq < ctl->
nq; iq++) {
10258 const char *filename,
10263 const double *vmr_impl,
10268 const double *area,
10278 if (!(out = popen(
"gnuplot",
"w")))
10279 ERRMSG(
"Cannot create pipe to gnuplot!");
10282 fprintf(out,
"set out \"%s.png\"\n", filename);
10286 int year, mon, day, hour, min, sec;
10287 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
10288 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
10289 year, mon, day, hour, min);
10295 ERRMSG(
"Cannot open file!");
10296 while (fgets(line,
LEN, in))
10297 fprintf(out,
"%s", line);
10304 if (!(out = fopen(filename,
"w")))
10305 ERRMSG(
"Cannot create file!");
10310 "# $1 = time [s]\n"
10311 "# $2 = altitude [km]\n"
10312 "# $3 = longitude [deg]\n"
10313 "# $4 = latitude [deg]\n"
10314 "# $5 = surface area [km^2]\n"
10315 "# $6 = layer depth [km]\n"
10316 "# $7 = column density (implicit) [kg/m^2]\n"
10317 "# $8 = volume mixing ratio (implicit) [ppv]\n"
10318 "# $9 = number of particles [1]\n");
10319 for (
int iq = 0; iq < ctl->
nq; iq++)
10320 fprintf(out,
"# $%i = %s (mean) [%s]\n", 10 + iq, ctl->
qnt_name[iq],
10323 for (
int iq = 0; iq < ctl->
nq; iq++)
10324 fprintf(out,
"# $%i = %s (stddev) [%s]\n", 10 + ctl->
nq + iq,
10326 fprintf(out,
"\n");
10329 for (
int ix = 0; ix < ctl->
grid_nx; ix++) {
10331 fprintf(out,
"\n");
10332 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
10334 fprintf(out,
"\n");
10335 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
10338 fprintf(out,
"%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
10339 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
10340 for (
int iq = 0; iq < ctl->
nq; iq++) {
10342 fprintf(out, ctl->
qnt_format[iq], mean[iq][idx]);
10345 for (
int iq = 0; iq < ctl->
nq; iq++) {
10347 fprintf(out, ctl->
qnt_format[iq], sigma[iq][idx]);
10349 fprintf(out,
"\n");
10362 const char *filename,
10367 const double *vmr_impl,
10372 const double *area,
10376 char longname[2 *
LEN], varname[2 *
LEN];
10380 int *help2, ncid, dimid[10], varid;
10382 size_t start[2], count[2];
10385 ALLOC(help,
double,
10391 NC(nc_create(filename, NC_NETCDF4, &ncid));
10394 NC(nc_def_dim(ncid,
"time", 1, &dimid[0]));
10395 NC(nc_def_dim(ncid,
"z", (
size_t) ctl->
grid_nz, &dimid[1]));
10396 NC(nc_def_dim(ncid,
"lat", (
size_t) ctl->
grid_ny, &dimid[2]));
10397 NC(nc_def_dim(ncid,
"lon", (
size_t) ctl->
grid_nx, &dimid[3]));
10398 NC(nc_def_dim(ncid,
"dz", 1, &dimid[4]));
10401 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &dimid[0],
"time",
10402 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
10403 NC_DEF_VAR(
"z", NC_DOUBLE, 1, &dimid[1],
"altitude",
"km", 0, 0);
10404 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &dimid[2],
"latitude",
"degrees_north", 0,
10406 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &dimid[3],
"longitude",
"degrees_east", 0,
10408 NC_DEF_VAR(
"dz", NC_DOUBLE, 1, &dimid[1],
"layer depth",
"km", 0, 0);
10409 NC_DEF_VAR(
"area", NC_DOUBLE, 1, &dimid[2],
"surface area",
"km**2", 0, 0);
10411 NC_DEF_VAR(
"cd", NC_FLOAT, 4, dimid,
"column density",
"kg m**-2",
10413 NC_DEF_VAR(
"vmr_impl", NC_FLOAT, 4, dimid,
"volume mixing ratio (implicit)",
10415 NC_DEF_VAR(
"np", NC_INT, 4, dimid,
"number of particles",
"1", 0, 0);
10416 for (
int iq = 0; iq < ctl->
nq; iq++) {
10417 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
10418 sprintf(longname,
"%s (mean)", ctl->
qnt_longname[iq]);
10422 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
10423 sprintf(longname,
"%s (stddev)", ctl->
qnt_longname[iq]);
10429 NC(nc_enddef(ncid));
10439 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
10440 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
10441 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
10446 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
10447 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
10448 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
10453 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
10454 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
10455 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
10460 for (
int iq = 0; iq < ctl->
nq; iq++) {
10461 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
10462 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
10463 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
10464 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
10471 for (
int iq = 0; iq < ctl->
nq; iq++) {
10472 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
10473 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
10474 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
10475 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
10482 NC(nc_close(ncid));
10492 const char *filename,
10498 if (!(out = fopen(filename,
"w")))
10499 ERRMSG(
"Cannot create file!");
10596 const char *varname) {
10605 for (
int ix = 0; ix < met->
nx; ix++)
10606 for (
int iy = 0; iy < met->
ny; iy++)
10607 help[
ARRAY_2D(ix, iy, met->
ny)] = var[ix][iy];
10610 LOG(2,
"Write 2-D variable: %s (uncompressed)", varname);
10612 (
size_t) (met->
nx * met->
ny),
10626 const char *varname,
10627 const int precision,
10628 const double tolerance) {
10637#pragma omp parallel for default(shared) collapse(2)
10638 for (
int ix = 0; ix < met->
nx; ix++)
10639 for (
int iy = 0; iy < met->
ny; iy++)
10640 for (
int ip = 0; ip < met->
np; ip++)
10641 help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)] = var[ix][iy][ip];
10645 LOG(2,
"Write 3-D variable: %s (uncompressed)", varname);
10647 (
size_t) (met->
nx * met->
ny * met->
np),
10654 (
size_t) met->
np, 0, out);
10662 FWRITE(&tolerance,
double,
10666 tolerance, 0, out);
10681 (
size_t) met->
np, 0, out);
10687 ERRMSG(
"MET_TYPE not supported!");
10688 LOG(3,
"%d %g", precision, tolerance);
10698 const char *filename,
10704 size_t start[4], count[4];
10705 nc_create(filename, NC_NETCDF4, &ncid);
10708 int tid, lonid, latid, levid;
10709 NC(nc_def_dim(ncid,
"time", 1, &tid));
10710 NC(nc_def_dim(ncid,
"lon", (
size_t) met->
nx, &lonid));
10711 NC(nc_def_dim(ncid,
"lat", (
size_t) met->
ny, &latid));
10712 NC(nc_def_dim(ncid,
"lev", (
size_t) met->
np, &levid));
10715 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"time",
10716 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
10717 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &lonid,
"longitude",
"degrees_east", 0, 0);
10718 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &latid,
"latitude",
"degrees_north", 0, 0);
10719 NC_DEF_VAR(
"lev", NC_DOUBLE, 1, &levid,
"pressure",
"Pa", 0, 0);
10722 int dimid2[2] = { latid, lonid };
10723 NC_DEF_VAR(
"sp", NC_FLOAT, 2, dimid2,
"Surface pressure",
"Pa",
10725 NC_DEF_VAR(
"z", NC_FLOAT, 2, dimid2,
"Geopotential",
"m**2 s**-2",
10727 NC_DEF_VAR(
"t2m", NC_FLOAT, 2, dimid2,
"2 metre temperature",
"K",
10729 NC_DEF_VAR(
"u10m", NC_FLOAT, 2, dimid2,
"10 metre U wind component",
10731 NC_DEF_VAR(
"v10m", NC_FLOAT, 2, dimid2,
"10 metre V wind component",
10734 "Instantaneous eastward turbulent surface stress",
"N m**-2",
10737 "Instantaneous northward turbulent surface stress",
"N m**-2",
10740 "Instantaneous surface sensible heat flux",
"W m**-1",
10742 NC_DEF_VAR(
"lsm", NC_FLOAT, 2, dimid2,
"Land/sea mask",
"-",
10744 NC_DEF_VAR(
"sstk", NC_FLOAT, 2, dimid2,
"Sea surface temperature",
"K",
10746 NC_DEF_VAR(
"blp", NC_FLOAT, 2, dimid2,
"Boundary layer pressure",
"Pa",
10748 NC_DEF_VAR(
"pt", NC_FLOAT, 2, dimid2,
"Tropopause pressure",
"Pa",
10750 NC_DEF_VAR(
"tt", NC_FLOAT, 2, dimid2,
"Tropopause temperature",
"K",
10752 NC_DEF_VAR(
"zt", NC_FLOAT, 2, dimid2,
"Tropopause height",
"m",
10754 NC_DEF_VAR(
"h2ot", NC_FLOAT, 2, dimid2,
"Tropopause water vapor",
"ppv",
10756 NC_DEF_VAR(
"pct", NC_FLOAT, 2, dimid2,
"Cloud top pressure",
"Pa",
10758 NC_DEF_VAR(
"pcb", NC_FLOAT, 2, dimid2,
"Cloud bottom pressure",
"Pa",
10760 NC_DEF_VAR(
"cl", NC_FLOAT, 2, dimid2,
"Total column cloud water",
"kg m**2",
10763 "Pressure at lifted condensation level (LCL)",
"Pa",
10766 "Pressure at level of free convection (LFC)",
"Pa",
10768 NC_DEF_VAR(
"pel", NC_FLOAT, 2, dimid2,
"Pressure at equilibrium level (EL)",
10771 "Convective available potential energy",
"J kg**-1",
10773 NC_DEF_VAR(
"cin", NC_FLOAT, 2, dimid2,
"Convective inhibition",
"J kg**-1",
10775 NC_DEF_VAR(
"o3c", NC_FLOAT, 2, dimid2,
"Total column ozone",
"DU",
10779 int dimid3[3] = { levid, latid, lonid };
10780 NC_DEF_VAR(
"t", NC_FLOAT, 3, dimid3,
"Temperature",
"K",
10782 NC_DEF_VAR(
"u", NC_FLOAT, 3, dimid3,
"U velocity",
"m s**-1",
10784 NC_DEF_VAR(
"v", NC_FLOAT, 3, dimid3,
"V velocity",
"m s**-1",
10786 NC_DEF_VAR(
"w", NC_FLOAT, 3, dimid3,
"Vertical velocity",
"Pa s**-1",
10788 NC_DEF_VAR(
"q", NC_FLOAT, 3, dimid3,
"Specific humidity",
"kg kg**-1",
10790 NC_DEF_VAR(
"o3", NC_FLOAT, 3, dimid3,
"Ozone mass mixing ratio",
10792 NC_DEF_VAR(
"clwc", NC_FLOAT, 3, dimid3,
"Cloud liquid water content",
10794 NC_DEF_VAR(
"crwc", NC_FLOAT, 3, dimid3,
"Cloud rain water content",
10796 NC_DEF_VAR(
"ciwc", NC_FLOAT, 3, dimid3,
"Cloud ice water content",
10798 NC_DEF_VAR(
"cswc", NC_FLOAT, 3, dimid3,
"Cloud snow water content",
10800 NC_DEF_VAR(
"cc", NC_FLOAT, 3, dimid3,
"Cloud cover",
"-",
10804 NC(nc_enddef(ncid));
10811 for (
int ip = 0; ip < met->
np; ip++)
10812 phelp[ip] = 100. * met->
p[ip];
10855 NC(nc_close(ncid));
10862 const char *varname,
10868 size_t start[4], count[4];
10876 for (
int ix = 0; ix < met->
nx; ix++)
10877 for (
int iy = 0; iy < met->
ny; iy++)
10878 help[
ARRAY_2D(iy, ix, met->
nx)] = scl * var[ix][iy];
10891 const char *varname,
10897 size_t start[4], count[4];
10905 for (
int ix = 0; ix < met->
nx; ix++)
10906 for (
int iy = 0; iy < met->
ny; iy++)
10907 for (
int ip = 0; ip < met->
np; ip++)
10908 help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)] = scl * var[ix][iy][ip];
10920 const char *filename,
10929 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
10930 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
10932 static int nobs, *obscount, ip, okay;
10941 if (ctl->
qnt_m < 0)
10942 ERRMSG(
"Need quantity mass!");
10946 ERRMSG(
"Specify molar mass!");
10953 ALLOC(area,
double,
10957 ALLOC(press,
double,
10963 ALLOC(rlon,
double,
10965 ALLOC(rlat,
double,
10967 ALLOC(robs,
double,
10974 LOG(1,
"Write profile data: %s", filename);
10975 if (!(out = fopen(filename,
"w")))
10976 ERRMSG(
"Cannot create file!");
10980 "# $1 = time [s]\n"
10981 "# $2 = altitude [km]\n"
10982 "# $3 = longitude [deg]\n"
10983 "# $4 = latitude [deg]\n"
10984 "# $5 = pressure [hPa]\n"
10985 "# $6 = temperature [K]\n"
10986 "# $7 = volume mixing ratio [ppv]\n"
10987 "# $8 = H2O volume mixing ratio [ppv]\n"
10988 "# $9 = O3 volume mixing ratio [ppv]\n"
10989 "# $10 = observed BT index [K]\n"
10990 "# $11 = number of observations\n");
10998 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
10999 z[iz] = ctl->
prof_z0 + dz * (iz + 0.5);
11000 press[iz] =
P(z[iz]);
11004 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
11005 lon[ix] = ctl->
prof_lon0 + dlon * (ix + 0.5);
11006 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
11007 lat[iy] = ctl->
prof_lat0 + dlat * (iy + 0.5);
11008 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
11013 const double t0 = t - 0.5 * ctl->
dt_mod;
11014 const double t1 = t + 0.5 * ctl->
dt_mod;
11017 ALLOC(mass,
double,
11019 ALLOC(obsmean,
double,
11021 ALLOC(obscount,
int,
11025 for (
int i = 0; i < nobs; i++) {
11030 else if (rt[i] >= t1)
11034 if (!isfinite(robs[i]))
11038 int ix = (int) ((rlon[i] - ctl->
prof_lon0) / dlon);
11039 int iy = (int) ((rlat[i] - ctl->
prof_lat0) / dlat);
11042 if (ix < 0 || ix >= ctl->
prof_nx || iy < 0 || iy >= ctl->
prof_ny)
11047 obsmean[idx] += robs[i];
11052 for (ip = 0; ip < atm->
np; ip++) {
11055 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11059 int ix = (int) ((atm->
lon[ip] - ctl->
prof_lon0) / dlon);
11060 int iy = (int) ((atm->
lat[ip] - ctl->
prof_lat0) / dlat);
11061 int iz = (int) ((
Z(atm->
p[ip]) - ctl->
prof_z0) / dz);
11064 if (ix < 0 || ix >= ctl->
prof_nx ||
11070 mass[idx] += atm->
q[ctl->
qnt_m][ip];
11074 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
11075 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
11077 if (obscount[idx2] > 0) {
11081 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
11083 if (mass[idx3] > 0) {
11092 fprintf(out,
"\n");
11095 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
11100 lon[ix], lat[iy], &temp, ci, cw, 1);
11102 lon[ix], lat[iy], &h2o, ci, cw, 0);
11104 lon[ix], lat[iy], &o3, ci, cw, 0);
11109 / (
RHO(press[iz], temp) * area[iy] * dz * 1e9);
11112 fprintf(out,
"%.2f %g %g %g %g %g %g %g %g %g %d\n",
11113 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
11114 obsmean[idx2] / obscount[idx2], obscount[idx2]);
11147 const char *filename,
11156 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[
EP],
11159 static int nobs, nk;
11172 ALLOC(rlon,
double,
11174 ALLOC(rlat,
double,
11176 ALLOC(robs,
double,
11187 LOG(1,
"Write sample data: %s", filename);
11188 if (!(out = fopen(filename,
"w")))
11189 ERRMSG(
"Cannot create file!");
11193 "# $1 = time [s]\n"
11194 "# $2 = altitude [km]\n"
11195 "# $3 = longitude [deg]\n"
11196 "# $4 = latitude [deg]\n"
11197 "# $5 = surface area [km^2]\n"
11198 "# $6 = layer depth [km]\n"
11199 "# $7 = number of particles [1]\n"
11200 "# $8 = column density [kg/m^2]\n"
11201 "# $9 = volume mixing ratio [ppv]\n"
11202 "# $10 = observed BT index [K]\n\n");
11207 area = M_PI * rmax2;
11211 const double t0 = t - 0.5 * ctl->
dt_mod;
11212 const double t1 = t + 0.5 * ctl->
dt_mod;
11215 for (
int i = 0; i < nobs; i++) {
11220 else if (rt[i] >= t1)
11225 geo2cart(0, rlon[i], rlat[i], x0);
11228 const double rp =
P(rz[i]);
11229 const double ptop =
P(rz[i] + ctl->
sample_dz);
11230 const double pbot =
P(rz[i] - ctl->
sample_dz);
11238 for (
int ip = 0; ip < atm->
np; ip++) {
11241 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11245 if (fabs(rlat[i] - atm->
lat[ip]) > dlat)
11251 if (
DIST2(x0, x1) > rmax2)
11256 if (atm->
p[ip] > pbot || atm->
p[ip] < ptop)
11260 if (ctl->
qnt_m >= 0)
11267 const double cd = mass / (1e6 * area);
11278 rlon[i], rlat[i], &temp, ci, cw, 1);
11287 fprintf(out,
"%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
11288 rlon[i], rlat[i], area, ctl->
sample_dz, np, cd, vmr, robs[i]);
11309 const char *filename,
11316 static double rmax2, x0[3], x1[3];
11325 LOG(1,
"Write station data: %s", filename);
11328 if (!(out = fopen(filename,
"w")))
11329 ERRMSG(
"Cannot create file!");
11333 "# $1 = time [s]\n"
11334 "# $2 = altitude [km]\n"
11335 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
11336 for (
int iq = 0; iq < ctl->
nq; iq++)
11337 fprintf(out,
"# $%i = %s [%s]\n", (iq + 5),
11339 fprintf(out,
"\n");
11347 const double t0 = t - 0.5 * ctl->
dt_mod;
11348 const double t1 = t + 0.5 * ctl->
dt_mod;
11351 for (
int ip = 0; ip < atm->
np; ip++) {
11354 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11370 if (
DIST2(x0, x1) > rmax2)
11378 fprintf(out,
"%.2f %g %g %g",
11379 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]);
11380 for (
int iq = 0; iq < ctl->
nq; iq++) {
11382 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
11384 fprintf(out,
"\n");
11395 const char *filename,
11406 LOG(1,
"Write VTK data: %s", filename);
11409 const double t0 = t - 0.5 * ctl->
dt_mod;
11410 const double t1 = t + 0.5 * ctl->
dt_mod;
11413 if (!(out = fopen(filename,
"w")))
11414 ERRMSG(
"Cannot create file!");
11418 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
11419 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11426 "# vtk DataFile Version 3.0\n"
11427 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
11430 fprintf(out,
"POINTS %d float\n", np);
11432 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
11433 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11437 const double coslat = cos(
DEG2RAD(atm->
lat[ip]));
11438 const double x = radius * coslat * cos(
DEG2RAD(atm->
lon[ip]));
11439 const double y = radius * coslat * sin(
DEG2RAD(atm->
lon[ip]));
11440 const double z = radius * sin(
DEG2RAD(atm->
lat[ip]));
11441 fprintf(out,
"%g %g %g\n", x, y, z);
11444 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
11445 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11447 fprintf(out,
"%g %g %g\n", atm->
lon[ip], atm->
lat[ip],
11452 fprintf(out,
"POINT_DATA %d\n", np);
11453 for (
int iq = 0; iq < ctl->
nq; iq++) {
11454 fprintf(out,
"SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
11456 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
11457 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11459 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_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 read_met_levels(const int ncid, const ctl_t *ctl, met_t *met)
Reads meteorological variables at different vertical levels from a NetCDF file.
int read_met_nc(const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met)
Reads meteorological data from a NetCDF file and processes it.
void write_atm_clams_traj(const char *dirname, const ctl_t *ctl, const atm_t *atm, const double t)
Writes CLaMS trajectory data to a NetCDF file.
void write_met_nc_2d(const int ncid, const char *varname, met_t *met, float var[EX][EY], const float scl)
Writes a 2D meteorological variable to a NetCDF file.
void mptrac_alloc(ctl_t **ctl, cache_t **cache, clim_t **clim, met_t **met0, met_t **met1, atm_t **atm)
Allocates and initializes memory resources for MPTRAC.
void read_met_sample(const ctl_t *ctl, met_t *met)
Downsamples meteorological data based on specified parameters.
void write_met_bin_3d(FILE *out, const ctl_t *ctl, met_t *met, float var[EX][EY][EP], const char *varname, const int precision, const double tolerance)
Writes a 3-dimensional meteorological variable to a binary file.
void read_obs(const char *filename, const ctl_t *ctl, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from a file and stores it in arrays.
void module_advect(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Advances particle positions using different advection schemes.
void module_timesteps(const ctl_t *ctl, cache_t *cache, met_t *met0, atm_t *atm, const double t)
Calculate time steps for air parcels based on specified conditions.
int mptrac_read_met(const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met)
Reads meteorological data from a file, supporting multiple formats and MPI broadcasting.
void module_meteo(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Update atmospheric properties using meteorological data.
void read_clim_photo(const char *filename, clim_photo_t *photo)
Reads photolysis rates from a NetCDF file and populates the given photolysis structure.
void read_met_cloud(met_t *met)
Calculates cloud-related variables for each grid point.
void module_decay(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, atm_t *atm)
Simulate exponential decay processes for atmospheric particles.
double sedi(const double p, const double T, const double rp, const double rhop)
Calculates the sedimentation velocity of a particle in air.
void intpol_met_space_2d(const met_t *met, float array[EX][EY], const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables in 2D space.
int read_atm_nc(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a generic netCDF file and populates the given atmospheric structure.
void read_met_pbl(const ctl_t *ctl, met_t *met)
Computes the planetary boundary layer (PBL) pressure based on meteorological data.
void read_met_detrend(const ctl_t *ctl, met_t *met)
Detrends meteorological data.
int read_met_nc_2d(const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const char *varname5, const char *varname6, const ctl_t *ctl, const met_t *met, float dest[EX][EY], const float scl, const int init)
Reads a 2-dimensional meteorological variable from a NetCDF file.
void read_met_tropo(const ctl_t *ctl, const clim_t *clim, met_t *met)
Calculates the tropopause and related meteorological variables based on various methods and stores th...
void read_obs_asc(const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from an ASCII file.
void module_chem_init(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Initializes the chemistry modules by setting atmospheric composition.
int locate_reg(const double *xx, const int n, const double x)
Locate the index of the interval containing a given value in a regular grid.
void get_tropo(const int met_tropo, ctl_t *ctl, clim_t *clim, met_t *met, const double *lons, const int nx, const double *lats, const int ny, double *pt, double *zt, double *tt, double *qt, double *o3t, double *ps, double *zs)
Calculate tropopause data.
void mptrac_get_met(ctl_t *ctl, clim_t *clim, const double t, met_t **met0, met_t **met1)
Retrieves meteorological data for the specified time.
void read_met_monotonize(const ctl_t *ctl, met_t *met)
Makes zeta and pressure profiles monotone.
int read_clim_ts(const char *filename, clim_ts_t *ts)
Reads a climatological time series from a file and populates the given time series structure.
void read_met_periodic(met_t *met)
Applies periodic boundary conditions to meteorological data along longitudinal axis.
void module_timesteps_init(ctl_t *ctl, const atm_t *atm)
Initialize start time and time interval for time-stepping.
void write_ens(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes ensemble data to a file.
void module_mixing(const ctl_t *ctl, const clim_t *clim, atm_t *atm, const double t)
Update atmospheric properties through interparcel mixing.
double clim_zm(const clim_zm_t *zm, const double t, const double lat, const double p)
Interpolates monthly mean zonal mean climatological variables.
void 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_grid(const char *filename, const int ncid, const ctl_t *ctl, met_t *met)
Reads meteorological grid information from a NetCDF file.
void read_met_bin_2d(FILE *in, const met_t *met, float var[EX][EY], const char *varname)
Reads a 2-dimensional meteorological variable from a binary file and stores it in the provided array.
int locate_irr(const double *xx, const int n, const double x)
Locate the index of the interval containing a given value in a sorted array.
void module_isosurf_init(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Initialize the isosurface module based on atmospheric data.
void level_definitions(ctl_t *ctl)
Defines pressure levels for meteorological data.
void intpol_met_4d_coord(const met_t *met0, float heights0[EX][EY][EP], float array0[EX][EY][EP], const met_t *met1, float heights1[EX][EY][EP], float array1[EX][EY][EP], const double ts, const double height, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables to a given position and time.
void write_grid_asc(const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
Writes grid data to an ASCII file.
void mptrac_update_device(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
Updates device memory for specified data structures.
void time2jsec(const int year, const int mon, const int day, const int hour, const int min, const int sec, const double remain, double *jsec)
Converts time components to seconds since January 1, 2000, 12:00:00 UTC.
void mptrac_init(ctl_t *ctl, cache_t *cache, clim_t *clim, atm_t *atm, const int ntask)
Initializes the MPTRAC model and its associated components.
void intpol_met_time_3d(const met_t *met0, float array0[EX][EY][EP], const met_t *met1, float array1[EX][EY][EP], const double ts, const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological data in 3D space and time.
void intpol_met_space_3d_ml(const met_t *met, float zs[EX][EY][EP], float array[EX][EY][EP], const double z, const double lon, const double lat, double *var)
Interpolates meteorological data in 3D space.
void fft_help(double *fcReal, double *fcImag, const int n)
Computes the Fast Fourier Transform (FFT) of a complex sequence.
void module_wet_depo(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Perform wet deposition calculations for air parcels.
void compress_pck(const char *varname, float *array, const size_t nxy, const size_t nz, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats.
double nat_temperature(const double p, const double h2o, const double hno3)
Calculates the nitric acid trihydrate (NAT) temperature.
void spline(const double *x, const double *y, const int n, const double *x2, double *y2, const int n2, const int method)
Performs spline interpolation or linear interpolation.
void module_chem_grid(const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double tt)
Calculate grid data for chemistry modules.
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 module_sedi(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate sedimentation of particles in the atmosphere.
void timer(const char *name, const char *group, const int output)
Measures and reports elapsed time for named and grouped timers.
void write_atm_asc(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes air parcel data to an ASCII file or gnuplot.
void intpol_met_space_3d(const met_t *met, float array[EX][EY][EP], const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables in 3D space.
void read_met_surface(const int ncid, const ctl_t *ctl, met_t *met)
Reads surface meteorological data from a netCDF file and stores it in the meteorological data structu...
void intpol_met_time_3d_ml(const met_t *met0, float zs0[EX][EY][EP], float array0[EX][EY][EP], const met_t *met1, float zs1[EX][EY][EP], float array1[EX][EY][EP], const double ts, const double p, const double lon, const double lat, double *var)
Interpolates meteorological data in both space and time.
void module_convection(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Performs convective mixing of atmospheric particles.
void read_kernel(const char *filename, double kz[EP], double kw[EP], int *nk)
Reads kernel function data from a file and populates the provided arrays.
void module_bound_cond(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Apply boundary conditions to particles based on meteorological and climatological data.
double scan_ctl(const char *filename, int argc, char *argv[], const char *varname, const int arridx, const char *defvalue, char *value)
Scans a control file or command-line arguments for a specified variable.
void module_advect_init(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Initializes the advection module by setting up pressure fields.
void module_sort_help(double *a, const int *p, const int np)
Reorder an array based on a given permutation.
float stddev(const float *data, const int n)
Calculates the standard deviation of a set of data.
void intpol_tropo_3d(const double time0, float array0[EX][EY], const double time1, float array1[EX][EY], const double lons[EX], const double lats[EY], const int nlon, const int nlat, const double time, const double lon, const double lat, const int method, double *var, double *sigma)
Interpolates tropopause data in 3D (latitude, longitude, and time).
int read_met_nc_3d(const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const ctl_t *ctl, const met_t *met, float dest[EX][EY][EP], const float scl)
Reads a 3-dimensional meteorological variable from a NetCDF file.
void read_met_bin_3d(FILE *in, const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname, const float bound_min, const float bound_max)
Reads 3D meteorological data from a binary file, potentially using different compression methods.
int locate_irr_float(const float *xx, const int n, const double x, const int ig)
Locate the index of the interval containing a given value in an irregularly spaced array.
double time_from_filename(const char *filename, const int offset)
Extracts and converts a timestamp from a filename to Julian seconds.
void write_prof(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes profile data to a specified file.
void mptrac_read_clim(const ctl_t *ctl, clim_t *clim)
Reads various climatological data and populates the given climatology structure.
double tropo_weight(const clim_t *clim, const atm_t *atm, const int ip)
Computes a weighting factor based on tropopause pressure.
void write_met_nc(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a NetCDF file.
void module_rng_init(const int ntask)
Initialize random number generators for parallel tasks.
int mptrac_read_atm(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a specified file into the given atmospheric structure.
void mptrac_update_host(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
Updates host memory for specified data structures.
void mptrac_write_output(const char *dirname, const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double t)
Writes various types of output data to files in a specified directory.
double clim_oh(const ctl_t *ctl, const clim_t *clim, const double t, const double lon, const double lat, const double p)
Calculates the hydroxyl radical (OH) concentration from climatology data, with an optional diurnal co...
void read_met_ozone(met_t *met)
Calculates the total column ozone from meteorological ozone data.
void mptrac_free(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Frees memory resources allocated for MPTRAC.
void clim_tropo_init(clim_t *clim)
Initializes the tropopause data in the climatology structure.
void module_rng(const ctl_t *ctl, double *rs, const size_t n, const int method)
Generate random numbers using various methods and distributions.
void get_met_help(const ctl_t *ctl, const double t, const int direct, const char *metbase, const double dt_met, char *filename)
Generates a formatted filename for meteorological data files based on the input parameters.
void write_station(const char *filename, const ctl_t *ctl, atm_t *atm, const double t)
Writes station data to a specified file.
void cart2geo(const double *x, double *z, double *lon, double *lat)
State variables of cuRAND random number generator.
double sza_calc(const double sec, const double lon, const double lat)
Calculates the solar zenith angle.
void 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)
Perform interparcel mixing for a specific quantity.
void doy2day(const int year, const int doy, int *mon, int *day)
Converts a given day of the year (DOY) to a date (month and day).
void intpol_met_time_2d(const met_t *met0, float array0[EX][EY], const met_t *met1, float array1[EX][EY], const double ts, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological data in 2D space and time.
void module_position(const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Update the positions and pressure levels of atmospheric particles.
void clim_oh_diurnal_correction(const ctl_t *ctl, clim_t *clim)
Applies a diurnal correction to the hydroxyl radical (OH) concentration in climatology data.
void locate_vert(float profiles[EX][EY][EP], const int np, const int lon_ap_ind, const int lat_ap_ind, const double height_ap, int *ind)
Locate the four vertical indizes of a box for a given height value.
void write_met_bin_2d(FILE *out, met_t *met, float var[EX][EY], const char *varname)
Writes a 2-dimensional meteorological variable to a binary file.
void read_met_pv(met_t *met)
Calculates potential vorticity (PV) from meteorological data.
int read_atm_bin(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a binary file and populates the given atmospheric structure.
void get_met_replace(char *orig, char *search, char *repl)
Replaces occurrences of a substring in a string with another substring.
void module_diff_meso(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate mesoscale diffusion for atmospheric particles.
void module_sort(const ctl_t *ctl, met_t *met0, atm_t *atm)
Sort particles according to box index.
double clim_ts(const clim_ts_t *ts, const double t)
Interpolates a time series of climatological variables.
void jsec2time(const double jsec, int *year, int *mon, int *day, int *hour, int *min, int *sec, double *remain)
Converts Julian seconds to calendar date and time components.
int read_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a binary file.
void mptrac_run_timestep(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t **met0, met_t **met1, atm_t *atm, double t)
Executes a single timestep of the MPTRAC model simulation.
void write_atm_clams(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a NetCDF file in the CLaMS format.
void module_diff_turb(const ctl_t *ctl, cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Applies turbulent diffusion processes to atmospheric particles.
int read_atm_clams(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads atmospheric data from a CLAMS NetCDF file.
void write_vtk(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes VTK (Visualization Toolkit) data to a specified file.
void module_tracer_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Simulate chemical reactions involving long-lived atmospheric tracers.
void mptrac_read_ctl(const char *filename, int argc, char *argv[], ctl_t *ctl)
Reads control parameters from a configuration file and populates the given structure.
void read_met_polar_winds(met_t *met)
Applies a fix for polar winds in meteorological data.
void module_h2o2_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Perform chemical reactions involving H2O2 within cloud particles.
void write_grid_nc(const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
Writes grid data to a NetCDF file.
double pbl_weight(const ctl_t *ctl, const atm_t *atm, const int ip, const double pbl, const double ps)
Computes a weighting factor based on planetary boundary layer pressure.
void module_diff_pbl(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Computes particle diffusion within the planetary boundary layer (PBL).
void write_met_nc_3d(const int ncid, const char *varname, met_t *met, float var[EX][EY][EP], const float scl)
Writes a 3D meteorological variable to a NetCDF file.
void module_isosurf(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Apply the isosurface module to adjust atmospheric properties.
void module_oh_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Perform hydroxyl chemistry calculations for atmospheric particles.
void geo2cart(const double z, const double lon, const double lat, double *x)
Converts geographic coordinates (longitude, latitude, altitude) to Cartesian coordinates.
double kernel_weight(const double kz[EP], const double kw[EP], const int nk, const double p)
Calculates the kernel weight based on altitude and given kernel data.
int read_atm_asc(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from an ASCII file and populates the given atmospheric structure.
void intpol_check_lon_lat(const double *lons, const int nlon, const double *lats, const int nlat, const double lon, const double lat, double *lon2, double *lat2)
Adjusts longitude and latitude to ensure they fall within valid bounds.
void write_sample(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes sample data to a specified file.
void write_grid(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes grid data to a file in ASCII or netCDF format.
void module_dry_depo(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate dry deposition of atmospheric particles.
void write_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data in binary format to a specified file.
void write_atm_bin(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a binary file.
void read_met_cape(const ctl_t *ctl, const clim_t *clim, met_t *met)
Calculates Convective Available Potential Energy (CAPE) for each grid point.
void mptrac_write_met(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a file, supporting multiple formats and compression options.
double lapse_rate(const double t, const double h2o)
Calculates the moist adiabatic lapse rate in Kelvin per kilometer.
void write_csi(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes Critical Success Index (CSI) data to a file.
void write_atm_nc(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a NetCDF file.
MPTRAC library declarations.
#define NN(x0, y0, x1, y1, x)
Perform nearest-neighbor interpolation.
void compress_zstd(const char *varname, float *array, const size_t n, const int decompress, const int level, FILE *inout)
Compresses or decompresses a float array using Zstandard (ZSTD).
#define LEN
Maximum length of ASCII data lines.
#define RE
Mean radius of Earth [km].
#define TVIRT(t, h2o)
Compute virtual temperature.
#define 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 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 RA
Specific gas constant of dry air [J/(kg K)].
#define KARMAN
Karman's constant.
#define INTPOL_INIT
Initialize arrays for interpolation.
#define MIN(a, b)
Macro to determine the minimum of two values.
#define ERRMSG(...)
Print an error message with contextual information and terminate the program.
#define NC_PUT_INT(varname, ptr, hyperslab)
Write integer data to a NetCDF variable.
void compress_cms(const ctl_t *ctl, const char *varname, float *array, const size_t nx, const size_t ny, const size_t np, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using a custom multiscale compression algorithm.
void compress_zfp(const char *varname, float *array, const int nx, const int ny, const int nz, const int precision, const double tolerance, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using the ZFP library.
#define EY
Maximum number of latitudes for meteo data.
#define SH(h2o)
Compute specific humidity from water vapor volume mixing ratio.
#define INTPOL_3D(var, init)
Perform 3D interpolation for a meteorological variable.
#define NOBS
Maximum number of observation data points.
#define NTHREADS
Maximum number of OpenMP threads.
#define ARRAY_2D(ix, iy, ny)
Macro for computing the linear index of a 2D array element.
#define Z(p)
Convert pressure to altitude.
#define P(z)
Compute pressure at given altitude.
#define LV
Latent heat of vaporization of water [J/kg].
#define G0
Standard gravity [m/s^2].
#define CP
Maximum number of pressure levels for climatological data.
#define NQ
Maximum number of quantities per data point.
#define FREAD(ptr, type, size, in)
Read data from a file stream and store it in memory.
#define DX2DEG(dx, lat)
Convert a distance in kilometers to degrees longitude at a given latitude.
#define DEG2DY(dlat)
Convert a latitude difference to a distance in the y-direction (north-south).
#define EX
Maximum number of longitudes for meteo data.
#define EPS
Ratio of the specific gas constant of dry air and water vapor [1].
#define PSICE(t)
Compute saturation pressure over ice (WMO, 2018).
#define THETA(p, t)
Compute potential temperature.
#define RI
Ideal gas constant [J/(mol K)].
#define NORM(a)
Compute the norm (magnitude) of a vector.
#define SET_QNT(qnt, name, longname, unit)
Set atmospheric quantity index.
#define TICE(p, h2o)
Calculate frost point temperature (WMO, 2018).
#define TOK(line, tok, format, var)
Get string tokens.
#define ZDIFF(lnp0, t0, h2o0, lnp1, t1, h2o1)
Calculate geopotential height difference.
#define THETAVIRT(p, t, h2o)
Compute virtual potential temperature.
#define DZ2DP(dz, p)
Convert a change in altitude to a change in pressure.
#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.
#define SET_ATM(qnt, val)
Set atmospheric quantity value.
#define CTS
Maximum number of data points of climatological time series.
#define DEG2RAD(deg)
Converts degrees to radians.
void broadcast_large_data(void *data, size_t N)
Broadcasts large data across all processes in an MPI communicator.
#define MO3
Molar mass of ozone [g/mol].
#define SQR(x)
Compute the square of a value.
#define RAD2DEG(rad)
Converts radians to degrees.
#define NC_INQ_DIM(dimname, ptr, min, max)
Inquire the length of a dimension in a NetCDF file.
#define NP
Maximum number of atmospheric data points.
#define NTIMER
Maximum number of timers.
#define SELECT_TIMER(id, group, color)
Select and start a timer with specific attributes.
#define INTPOL_2D(var, init)
Perform 2D interpolation for a meteorological variable.
#define RH(p, t, h2o)
Compute relative humidity over water.
#define NC_PUT_FLOAT(varname, ptr, hyperslab)
Write a float array to a NetCDF file.
#define CY
Maximum number of latitudes for climatological data.
#define LOG(level,...)
Print a log message with a specified logging level.
void thrustSortWrapper(double *__restrict__ c, int n, int *__restrict__ index)
Wrapper to Thrust sorting function.
#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.
#define NC_PUT_DOUBLE(varname, ptr, hyperslab)
Write double precision data to a NetCDF variable.
#define LIN(x0, y0, x1, y1, x)
Linear interpolation.
#define DIST2(a, b)
Calculate the squared Euclidean distance between two points in Cartesian coordinates.
#define DEG2DX(dlon, lat)
Convert a longitude difference to a distance in the x-direction (east-west) at a specific latitude.
#define CPD
Specific heat of dry air at constant pressure [J/(kg K)].
#define CSZA
Maximum number of solar zenith angles for climatological data.
#define DY2DEG(dy)
Convert a distance in kilometers to degrees latitude.
#define MAX(a, b)
Macro to determine the maximum of two values.
#define 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).
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).
int qnt_lwc
Quantity array index for cloud liquid water content.
double turb_mesoz
Vertical scaling factor for mesoscale wind fluctuations.
int grid_nc_level
zlib compression level of netCDF grid data files (0=off).
int grid_nx
Number of longitudes of gridded data.
int atm_type
Type of atmospheric data files (0=ASCII, 1=binary, 2=netCDF, 3=CLaMS_traj, 4=CLaMS_pos).
double bound_mass
Boundary conditions mass per particle [kg].
double grid_lat0
Lower latitude of gridded data [deg].
int qnt_ts
Quantity array index for surface temperature.
int qnt_loss_rate
Quantity array index for total loss rate.
double met_cms_eps_h2o
cmultiscale compression epsilon for water vapor.
int qnt_plfc
Quantity array index for pressure at level of free convection (LCF).
double grid_lon0
Lower longitude of gridded data [deg].
int qnt_o1d
Quantity array index for O(1D) volume mixing ratio (climatology).
int met_tropo_spline
Tropopause interpolation method (0=linear, 1=spline).
char sample_kernel[LEN]
Kernel data file for sample output.
int qnt_tvirt
Quantity array index for virtual temperature.
double dt_met
Time step of meteo data [s].
char clim_ho2_filename[LEN]
Filename of HO2 climatology.
double chemgrid_lat1
Upper latitude of chemistry grid [deg].
int met_geopot_sy
Latitudinal smoothing of geopotential heights.
char grid_gpfile[LEN]
Gnuplot file for gridded data.
double met_cms_eps_u
cmultiscale compression epsilon for zonal wind.
double turb_dx_strat
Horizontal turbulent diffusion coefficient (stratosphere) [m^2/s].
int qnt_vmr
Quantity array index for volume mixing ratio.
int qnt_lsm
Quantity array index for land-sea mask.
int qnt_theta
Quantity array index for potential temperature.
double bound_lat1
Boundary conditions maximum longitude [deg].
double stat_t1
Stop time for station output [s].
char csi_kernel[LEN]
Kernel data file for CSI output.
double turb_dx_trop
Horizontal turbulent diffusion coefficient (troposphere) [m^2/s].
int grid_type
Type of grid data files (0=ASCII, 1=netCDF).
double csi_lon0
Lower longitude of gridded CSI data [deg].
int qnt_pbl
Quantity array index for boundary layer pressure.
double oh_chem[4]
Coefficients for OH reaction rate (A, E/R or k0, n, kinf, m).
int grid_stddev
Include standard deviations in grid output (0=no, 1=yes).
int qnt_psice
Quantity array index for saturation pressure over ice.
double chemgrid_lon0
Lower longitude of chemistry grid [deg].
int bound_pbl
Boundary conditions planetary boundary layer (0=no, 1=yes).
int qnt_mloss_wet
Quantity array index for total mass loss due to wet deposition.
int met_geopot_sx
Longitudinal smoothing of geopotential heights.
int met_sy
Smoothing for latitudes.
int qnt_ps
Quantity array index for surface pressure.
int rng_type
Random number generator (0=GSL, 1=Squares, 2=cuRAND).
char prof_obsfile[LEN]
Observation data file for profile output.
int isosurf
Isosurface parameter (0=none, 1=pressure, 2=density, 3=theta, 4=balloon).
double bound_p1
Boundary conditions top pressure [hPa].
int qnt_zs
Quantity array index for surface geopotential height.
int prof_nz
Number of altitudes of gridded profile data.
double csi_dt_out
Time step for CSI output [s].
int met_cape
Convective available potential energy data (0=file, 1=calculate).
double csi_modmin
Minimum column density to trigger detection [kg/m^2].
int met_sx
Smoothing for longitudes.
double chemgrid_lon1
Upper longitude of chemistry grid [deg].
double turb_mesox
Horizontal scaling factor for mesoscale wind fluctuations.
double met_cms_eps_iwc
cmultiscale compression epsilon for cloud ice water content.
double met_cms_eps_swc
cmultiscale compression epsilon for cloud snow water content.
char grid_kernel[LEN]
Kernel data file for grid output.
int met_zfp_prec
ZFP compression precision for all variables, except z and T.
double met_cms_eps_v
cmultiscale compression epsilon for meridional wind.
double prof_z0
Lower altitude of gridded profile data [km].
int qnt_w
Quantity array index for vertical velocity.
double bound_vmr
Boundary conditions volume mixing ratio [ppv].
double met_tropo_pv
Dynamical tropopause potential vorticity threshold [PVU].
int prof_nx
Number of longitudes of gridded profile data.
int qnt_stat
Quantity array index for station flag.
int met_tropo
Tropopause definition (0=none, 1=clim, 2=cold point, 3=WMO_1st, 4=WMO_2nd, 5=dynamical).
int qnt_rp
Quantity array index for particle radius.
int met_mpi_share
Use MPI to share meteo (0=no, 1=yes).
double mixing_strat
Interparcel exchange parameter for mixing in the stratosphere.
int qnt_vz
Quantity array index for vertical velocity.
int qnt_ho2
Quantity array index for HO2 volume mixing ratio (climatology).
double csi_z1
Upper altitude of gridded CSI data [km].
double stat_t0
Start time for station output [s].
double oh_chem_beta
Beta parameter for diurnal variablity of OH.
char clim_o1d_filename[LEN]
Filename of O(1D) climatology.
char clim_photo[LEN]
Filename of photolysis rates climatology.
double wet_depo_so2_ph
pH value used to calculate effective Henry constant of SO2.
double mixing_z0
Lower altitude of mixing grid [km].
int qnt_mloss_decay
Quantity array index for total mass loss due to exponential decay.
int atm_type_out
Type of atmospheric data files for output (-1=same as ATM_TYPE, 0=ASCII, 1=binary,...
int met_nlev
Number of meteo data model levels.
double dt_kpp
Time step for KPP chemistry [s].
char csi_basename[LEN]
Basename of CSI data files.
double dry_depo_dp
Dry deposition surface layer [hPa].
int qnt_shf
Quantity array index for surface sensible heat flux.
int qnt_vs
Quantity array index for surface meridional wind.
int qnt_Cco
Quantity array index for CO volume mixing ratio (chemistry code).
double vtk_dt_out
Time step for VTK data output [s].
double t_stop
Stop time of simulation [s].
double conv_dt
Time interval for convection module [s].
char sample_obsfile[LEN]
Observation data file for sample output.
int qnt_hno3
Quantity array index for HNO3 volume mixing ratio (climatology).
char grid_basename[LEN]
Basename of grid data files.
int met_clams
Read MPTRAC or CLaMS meteo data (0=MPTRAC, 1=CLaMS).
int 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 mixing_ny
Number of latitudes of mixing grid.
int met_convention
Meteo data layout (0=[lev, lat, lon], 1=[lon, lat, lev]).
int qnt_zeta_d
Quantity array index for diagnosed zeta vertical coordinate.
char clim_h2o2_filename[LEN]
Filename of H2O2 climatology.
int tracer_chem
Switch for first order tracer chemistry module (0=off, 1=on).
double dt_mod
Time step of simulation [s].
int diffusion
Diffusion scheme (0=off, 1=fixed-K, 2=PBL).
int qnt_tnat
Quantity array index for T_NAT.
int qnt_tice
Quantity array index for T_ice.
int qnt_zg
Quantity array index for geopotential height.
double vtk_offset
Vertical offset for VTK data [km].
int qnt_v
Quantity array index for meridional wind.
int qnt_mloss_dry
Quantity array index for total mass loss due to dry deposition.
double bound_vmr_trend
Boundary conditions volume mixing ratio trend [ppv/s].
int met_cache
Preload meteo data into disk cache (0=no, 1=yes).
int qnt_oh
Quantity array index for OH volume mixing ratio (climatology).
char qnt_unit[NQ][LEN]
Quantity units.
int qnt_Ch
Quantity array index for H volume mixing ratio (chemistry code).
int met_press_level_def
Use predefined pressure levels or not.
int oh_chem_reaction
Reaction type for OH chemistry (0=none, 2=bimolecular, 3=termolecular).
int qnt_h2o
Quantity array index for water vapor volume mixing ratio.
int prof_ny
Number of latitudes of gridded profile data.
int qnt_rhice
Quantity array index for relative humidity over ice.
int qnt_rho
Quantity array index for density of air.
double sample_dz
Layer depth for sample output [km].
double tdec_strat
Life time of particles in the stratosphere [s].
int obs_type
Type of observation data files (0=ASCII, 1=netCDF).
int grid_nc_quant[NQ]
Number of digits for quantization of netCDF grid data files (0=off).
double met_cms_eps_lwc
cmultiscale compression epsilon for cloud liquid water content.
int qnt_us
Quantity array index for surface zonal wind.
double met_cms_eps_z
cmultiscale compression epsilon for geopotential height.
double grid_lon1
Upper longitude of gridded data [deg].
int qnt_Cn2o
Quantity array index for N2O volume mixing ratio (chemistry code).
int qnt_Cccl3f
Quantity array index for CFC-11 volume mixing ratio (chemistry code).
char qnt_name[NQ][LEN]
Quantity names.
char atm_basename[LEN]
Basename of atmospheric data files.
double mixing_lat0
Lower latitude of mixing grid [deg].
int qnt_pt
Quantity array index for tropopause pressure.
int qnt_cl
Quantity array index for total column cloud water.
int advect
Advection scheme (0=off, 1=Euler, 2=midpoint, 4=Runge-Kutta).
double prof_z1
Upper altitude of gridded profile data [km].
double met_lev_hyam[EP]
Meteo data model level a coefficients.
int qnt_t
Quantity array index for temperature.
int atm_filter
Time filter for atmospheric data output (0=none, 1=missval, 2=remove).
int kpp_chem
Switch for KPP chemistry module (0=off, 1=on).
int qnt_zeta
Quantity array index for zeta vertical coordinate.
double conv_pbl_trans
Depth of PBL transition layer (fraction of PBL depth).
char ens_basename[LEN]
Basename of ensemble data file.
double wet_depo_pre[2]
Coefficients for precipitation calculation.
int met_vert_coord
Vertical coordinate of input meteo data (0=plev, 1=mlev_p_file, 2=mlev_ab_file, 3=mlev_ab_full,...
double csi_z0
Lower altitude of gridded CSI data [km].
int qnt_lapse
Quantity array index for lapse rate.
double stat_lat
Latitude of station [deg].
int qnt_Cho2
Quantity array index for HO2 volume mixing ratio (chemistry code).
double wet_depo_bc_h[2]
Coefficients for wet deposition below cloud (Henry's law: Hb, Cb).
int grid_ny
Number of latitudes of gridded data.
int qnt_Csf6
Quantity array index for SF6 volume mixing ratio (chemistry code).
int qnt_Ch2o
Quantity array index for H2O volume mixing ratio (chemistry code).
double met_detrend
FWHM of horizontal Gaussian used for detrending [km].
int conv_mix_pbl
Vertical mixing in the PBL (0=off, 1=on).
char metbase[LEN]
Basename for meteo data.
double bound_dps
Boundary conditions surface layer depth [hPa].
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).
double bound_mass_trend
Boundary conditions mass per particle trend [kg/s].
int mixing_nz
Number of altitudes of mixing grid.
int qnt_o3c
Quantity array index for total column ozone.
double bound_p0
Boundary conditions bottom pressure [hPa].
double mixing_lon0
Lower longitude of mixing grid [deg].
char clim_ccl4_timeseries[LEN]
Filename of CFC-10 time series.
int qnt_Co3
Quantity array index for O3 volume mixing ratio (chemistry code).
int qnt_tsts
Quantity array index for T_STS.
int grid_nz
Number of altitudes of gridded data.
char clim_oh_filename[LEN]
Filename of OH climatology.
int qnt_nss
Quantity array index for northward turbulent surface stress.
double ens_dt_out
Time step for ensemble output [s].
char sample_basename[LEN]
Basename of sample data file.
int atm_stride
Particle index stride for atmospheric data files.
int met_relhum
Try to read relative humidity (0=no, 1=yes).
double mixing_lat1
Upper latitude of mixing grid [deg].
double atm_dt_out
Time step for atmospheric data output [s].
char clim_sf6_timeseries[LEN]
Filename of SF6 time series.
double prof_lat1
Upper latitude of gridded profile data [deg].
int met_cms_batch
cmultiscale batch size.
double psc_h2o
H2O volume mixing ratio for PSC analysis.
int met_sp
Smoothing for pressure levels.
double prof_lon0
Lower longitude of gridded profile data [deg].
int chemgrid_nx
Number of longitudes of chemistry grid.
int qnt_pct
Quantity array index for cloud top pressure.
int qnt_mloss_kpp
Quantity array index for total mass loss due to KPP chemistry.
int qnt_psat
Quantity array index for saturation pressure over water.
double met_lev_hybm[EP]
Meteo data model level b coefficients.
double prof_lat0
Lower latitude of gridded profile data [deg].
int qnt_cin
Quantity array index for convective inhibition (CIN).
double psc_hno3
HNO3 volume mixing ratio for PSC analysis.
double prof_lon1
Upper longitude of gridded profile data [deg].
double met_cms_eps_rwc
cmultiscale compression epsilon for cloud rain water content.
int met_nc_quant
Number of digits for quantization of netCDF meteo files (0=off).
int h2o2_chem_reaction
Reaction type for H2O2 chemistry (0=none, 1=SO2).
int qnt_Co3p
Quantity array index for O(3P) volume mixing ratio (chemistry code).
int atm_nc_quant[NQ]
Number of digits for quantization of netCDF atmospheric data files (0=off).
double wet_depo_bc_ret_ratio
Coefficients for wet deposition below cloud: retention ratio.
int chemgrid_ny
Number of latitudes of chemistry grid.
char clim_ccl3f_timeseries[LEN]
Filename of CFC-11 time series.
double met_cms_eps_o3
cmultiscale compression epsilon for ozone.
int met_cms_zstd
cmultiscale zstd compression (0=off, 1=on).
int grid_sparse
Sparse output in grid data files (0=no, 1=yes).
char vtk_basename[LEN]
Basename of VTK data files.
double dry_depo_vdep
Dry deposition velocity [m/s].
int qnt_tt
Quantity array index for tropopause temperature.
int met_np
Number of target pressure levels.
int qnt_ens
Quantity array index for ensemble IDs.
int met_nc_level
zlib compression level of netCDF meteo files (0=off).
double met_zfp_tol_t
ZFP compression tolerance for temperature.
double mixing_dt
Time interval for mixing [s].
int qnt_mloss_h2o2
Quantity array index for total mass loss due to H2O2 chemistry.
double met_zfp_tol_z
ZFP compression tolerance for geopotential height.
double vtk_scale
Vertical scaling factor for VTK data.
char clim_ccl2f2_timeseries[LEN]
Filename of CFC-12 time series.
double met_cms_eps_w
cmultiscale compression epsilon for vertical velocity.
double wet_depo_ic_h[2]
Coefficients for wet deposition in cloud (Henry's law: Hb, Cb).
double turb_dx_pbl
Horizontal turbulent diffusion coefficient (PBL) [m^2/s].
double conv_cin
CIN threshold for convection module [J/kg].
int qnt_pv
Quantity array index for potential vorticity.
int advect_vert_coord
Vertical velocity of air parcels (0=omega_on_plev, 1=zetadot_on_mlev, 2=omega_on_mlev).
int qnt_mloss_oh
Quantity array index for total mass loss due to OH chemistry.
int qnt_Ch2o2
Quantity array index for H2O2 volume mixing ratio (chemistry code).
int qnt_sst
Quantity array index for sea surface temperature.
double mixing_lon1
Upper longitude of mixing grid [deg].
int atm_nc_level
zlib compression level of netCDF atmospheric data files (0=off).
char clim_hno3_filename[LEN]
Filename of HNO3 climatology.
int met_cms_heur
cmultiscale coarsening heuristics (0=default, 1=mean diff, 2=median diff, 3=max diff).
double wet_depo_ic_ret_ratio
Coefficients for wet deposition in cloud: retention ratio.
int qnt_sh
Quantity array index for specific humidity.
int qnt_ess
Quantity array index for eastward turbulent surface stress.
double wet_depo_ic_b
Coefficient B for wet deposition in cloud (exponential form).
double wet_depo_bc_b
Coefficient B for wet deposition below cloud (exponential form).
int met_dy
Stride for latitudes.
int qnt_Cx
Quantity array index for trace species x volume mixing ratio (chemistry code).
double turb_dz_strat
Vertical turbulent diffusion coefficient (stratosphere) [m^2/s].
double bound_zetas
Boundary conditions surface layer zeta [K].
int 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 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).
int qnt_cc
Quantity array index for cloud cover.
int qnt_plcl
Quantity array index for pressure at lifted condensation level (LCL).
double grid_dt_out
Time step for gridded data output [s].
int qnt_tdew
Quantity array index for dew point temperature.
float zt[EX][EY]
Tropopause geopotential height [km].
float sst[EX][EY]
Sea surface temperature [K].
float rwc[EX][EY][EP]
Cloud rain water content [kg/kg].
float o3c[EX][EY]
Total column ozone [DU].
float zeta_dotl[EX][EY][EP]
Vertical velocity on model levels [K/s].
float h2o[EX][EY][EP]
Water vapor volume mixing ratio [1].
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]
Longitude [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].
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 lat[EY]
Latitude [deg].
float swc[EX][EY][EP]
Cloud snow water content [kg/kg].
float zetal[EX][EY][EP]
Zeta on model levels [K].
double p[EP]
Pressure levels [hPa].