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]";
471 const int Nd0_x = 48;
472 const int Nd0_y = 24;
473 const int max_level_grid = 6;
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 double c_thresh_test;
551 if (strcasecmp(varname,
"Z") == 0)
553 else if (strcasecmp(varname,
"T") == 0)
555 else if (strcasecmp(varname,
"U") == 0)
557 else if (strcasecmp(varname,
"V") == 0)
559 else if (strcasecmp(varname,
"W") == 0)
561 else if (strcasecmp(varname,
"PV") == 0)
563 else if (strcasecmp(varname,
"H2O") == 0)
565 else if (strcasecmp(varname,
"O3") == 0)
567 else if (strcasecmp(varname,
"LWC") == 0)
569 else if (strcasecmp(varname,
"RWC") == 0)
571 else if (strcasecmp(varname,
"IWC") == 0)
573 else if (strcasecmp(varname,
"SWC") == 0)
575 else if (strcasecmp(varname,
"CC") == 0)
578 ERRMSG(
"Variable name unknown!");
581 cms_ptr[ip] = cms_init(cms_param);
585 cms_read_arr_new(cms_ptr[ip], tmp_arr, lon, lat,
586 nx, ny, c_thresh_test);
593 t_coars += (omp_get_wtime() - t0);
596 for (
size_t ip = ip0; ip <
MIN(ip0 + dip, np); ip++) {
599 double *tmp_cms, *tmp_org, *tmp_diff;
600 ALLOC(tmp_cms,
double,
602 ALLOC(tmp_org,
double,
604 ALLOC(tmp_diff,
double,
608 t0 = omp_get_wtime();
611#pragma omp parallel for default(shared)
612 for (
size_t ix = 0; ix < nx; ix++)
613 for (
size_t iy = 0; iy < ny; iy++) {
614 const size_t idx =
ARRAY_2D(ix, iy, ny);
615 const double x[] = { lon[ix], lat[iy] };
616 cms_eval(cms_ptr[ip], cms_sol[ip], x, &tmp_cms[idx]);
617 tmp_org[idx] = array[
ARRAY_3D(ix, iy, ny, ip, np)];
618 tmp_diff[idx] = tmp_cms[idx] - tmp_org[idx];
622 t_eval += (omp_get_wtime() - t0);
626 "cmultiscale: var= %s / lev= %lu / ratio= %g / rho= %g"
627 " / mean= %g / sd= %g / min= %g / max= %g", varname, ip,
628 cms_compression_rate(cms_ptr[ip], cms_sol[ip]),
629 gsl_stats_correlation(tmp_cms, 1, tmp_org, 1, nxy),
630 gsl_stats_mean(tmp_diff, 1, nxy), gsl_stats_sd(tmp_diff, 1, nxy),
631 gsl_stats_min(tmp_diff, 1, nxy), gsl_stats_max(tmp_diff, 1, nxy));
634 cr += cms_compression_rate(cms_ptr[ip], cms_sol[ip]) / (double) np;
638 cms_save_zstd_sol(cms_sol[ip], inout, 3);
640 cms_save_sol(cms_sol[ip], inout);
643 cms_delete_sol(cms_sol[ip]);
644 cms_delete_module(cms_ptr[ip]);
652 LOG(2,
"Write 3-D variable: %s"
653 " (cms, RATIO= %g, T_COARS= %g s, T_EVAL= %g s)",
654 varname, cr, t_coars, t_eval);
658 cms_delete_param(cms_param);
669 const int decompress,
672 double min[
EP], max[
EP], off[
EP], scl[
EP];
674 unsigned short *sarray;
677 ALLOC(sarray,
unsigned short,
684 LOG(2,
"Read 3-D variable: %s (pck, RATIO= %g)",
685 varname, (
double)
sizeof(
float) / (
double)
sizeof(
unsigned short));
694 FREAD(sarray,
unsigned short,
699#pragma omp parallel for default(shared)
700 for (
size_t ixy = 0; ixy < nxy; ixy++)
701 for (
size_t iz = 0; iz < nz; iz++)
703 = (
float) (sarray[ixy * nz + iz] * scl[iz] + off[iz]);
710 LOG(2,
"Write 3-D variable: %s (pck, RATIO= %g)",
711 varname, (
double)
sizeof(
float) / (
double)
sizeof(
unsigned short));
714 for (
size_t iz = 0; iz < nz; iz++) {
718 for (
size_t ixy = 1; ixy < nxy; ixy++)
719 for (
size_t iz = 0; iz < nz; iz++) {
720 if (array[ixy * nz + iz] < min[iz])
721 min[iz] = array[ixy * nz + iz];
722 if (array[ixy * nz + iz] > max[iz])
723 max[iz] = array[ixy * nz + iz];
727 for (
size_t iz = 0; iz < nz; iz++) {
728 scl[iz] = (max[iz] - min[iz]) / 65533.;
733#pragma omp parallel for default(shared)
734 for (
size_t ixy = 0; ixy < nxy; ixy++)
735 for (
size_t iz = 0; iz < nz; iz++)
737 sarray[ixy * nz + iz] = (
unsigned short)
738 ((array[ixy * nz + iz] - off[iz]) / scl[iz] + .5);
740 sarray[ixy * nz + iz] = 0;
749 FWRITE(sarray,
unsigned short,
768 const double tolerance,
769 const int decompress,
773 const zfp_type type = zfp_type_float;
775 zfp_field_3d(array, type, (uint) nx, (uint) ny, (uint) nz);
778 zfp_stream *zfp = zfp_stream_open(NULL);
780 ERRMSG(
"Failed to allocate zfp structures!");
784 double actual_tol = 0;
785 if ((precision > 0 && tolerance > 0) || (precision <= 0 && tolerance <= 0)) {
786 ERRMSG(
"Exactly one of precision or tolerance must be set for zfp!");
787 }
else if (precision > 0)
788 actual_prec = (int) zfp_stream_set_precision(zfp, (uint) precision);
789 else if (tolerance > 0)
790 actual_tol = zfp_stream_set_accuracy(zfp, tolerance);
793 const size_t bufsize = zfp_stream_maximum_size(zfp, field);
794 void *buffer = malloc(bufsize);
796 ERRMSG(
"Failed to allocate compression buffer!");
799 bitstream *stream = stream_open(buffer, bufsize);
800 zfp_stream_set_bit_stream(zfp, stream);
801 zfp_stream_rewind(zfp);
806 FREAD(&zfpsize,
size_t,
809 if (zfpsize > bufsize)
810 ERRMSG(
"Compressed data size exceeds allocated buffer!");
811 if (fread(buffer, 1, zfpsize, inout) != zfpsize)
812 ERRMSG(
"Error while reading zfp data!");
813 if (!zfp_decompress(zfp, field)) {
814 ERRMSG(
"Decompression failed!");
816 LOG(2,
"Read 3-D variable: %s "
817 "(zfp, PREC= %d, TOL= %g, RATIO= %g)",
818 varname, actual_prec, actual_tol,
819 ((
double) (nx * ny * nz)) / (
double) zfpsize);
824 zfpsize = zfp_compress(zfp, field);
826 ERRMSG(
"Compression failed!");
831 if (fwrite(buffer, 1, zfpsize, inout) != zfpsize)
832 ERRMSG(
"Error while writing zfp data!");
834 LOG(2,
"Write 3-D variable: %s "
835 "(zfp, PREC= %d, TOL= %g, RATIO= %g)",
836 varname, actual_prec, actual_tol,
837 ((
double) (nx * ny * nz)) / (
double) zfpsize);
841 zfp_field_free(field);
842 zfp_stream_close(zfp);
843 stream_close(stream);
855 const int decompress,
860 const size_t uncomprLen = n *
sizeof(float);
861 size_t comprLen = ZSTD_compressBound(uncomprLen);
865 char *compr = (
char *) calloc((uint) comprLen, 1);
866 char *uncompr = (
char *) array;
870 FREAD(&comprLen,
size_t,
873 if (fread(compr, 1, comprLen, inout) != comprLen)
874 ERRMSG(
"Error while reading zstd data!");
875 compsize = ZSTD_decompress(uncompr, uncomprLen, compr, comprLen);
876 if (ZSTD_isError(compsize)) {
877 ERRMSG(
"Decompression failed!");
879 LOG(2,
"Read 3-D variable: %s (zstd, RATIO= %g)",
880 varname, ((
double) uncomprLen) / (
double) comprLen)
885 compsize = ZSTD_compress(compr, comprLen, uncompr, uncomprLen, level);
886 if (ZSTD_isError(compsize)) {
887 ERRMSG(
"Compression failed!");
892 if (fwrite(compr, 1, compsize, inout) != compsize)
893 ERRMSG(
"Error while writing zstd data!");
895 LOG(2,
"Write 3-D variable: %s (zstd, RATIO= %g)",
896 varname, ((
double) uncomprLen) / (
double) compsize);
913 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
914 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
917 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
918 *doy = d0l[mon - 1] + day - 1;
920 *doy = d0[mon - 1] + day - 1;
932 d0[12] = { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
933 d0l[12] = { 1, 32, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336 };
938 if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
939 for (i = 11; i > 0; i--)
943 *day = doy - d0l[i] + 1;
945 for (i = 11; i > 0; i--)
949 *day = doy - d0[i] + 1;
964 ERRMSG(
"Too many data points!");
967 gsl_fft_complex_wavetable *wavetable =
968 gsl_fft_complex_wavetable_alloc((
size_t) n);
969 gsl_fft_complex_workspace *workspace =
970 gsl_fft_complex_workspace_alloc((
size_t) n);
973 for (
int i = 0; i < n; i++) {
974 data[2 * i] = fcReal[i];
975 data[2 * i + 1] = fcImag[i];
979 gsl_fft_complex_forward(data, 1, (
size_t) n, wavetable, workspace);
982 for (
int i = 0; i < n; i++) {
983 fcReal[i] = data[2 * i];
984 fcImag[i] = data[2 * i + 1];
988 gsl_fft_complex_wavetable_free(wavetable);
989 gsl_fft_complex_workspace_free(workspace);
1000 const double radius = z +
RE;
1001 const double latrad =
DEG2RAD(lat);
1002 const double lonrad =
DEG2RAD(lon);
1003 const double coslat = cos(latrad);
1005 x[0] = radius * coslat * cos(lonrad);
1006 x[1] = radius * coslat * sin(lonrad);
1007 x[2] = radius * sin(latrad);
1016 const char *metbase,
1017 const double dt_met,
1024 int year, mon, day, hour, min, sec;
1028 t6 = floor(t / dt_met) * dt_met;
1030 t6 = ceil(t / dt_met) * dt_met;
1033 jsec2time(t6, &year, &mon, &day, &hour, &min, &sec, &r);
1038 sprintf(filename,
"%s_YYYY_MM_DD_HH.nc", metbase);
1040 sprintf(filename,
"%s_YYYY_MM_DD_HH.bin", metbase);
1042 sprintf(filename,
"%s_YYYY_MM_DD_HH.pck", metbase);
1044 sprintf(filename,
"%s_YYYY_MM_DD_HH.zfp", metbase);
1046 sprintf(filename,
"%s_YYYY_MM_DD_HH.zstd", metbase);
1048 sprintf(filename,
"%s_YYYY_MM_DD_HH.cms", metbase);
1049 sprintf(repl,
"%d", year);
1051 sprintf(repl,
"%02d", mon);
1053 sprintf(repl,
"%02d", day);
1055 sprintf(repl,
"%02d", hour);
1061 sprintf(filename,
"%s_YYMMDDHH.nc", metbase);
1062 sprintf(repl,
"%d", year);
1064 sprintf(repl,
"%02d", year % 100);
1066 sprintf(repl,
"%02d", mon);
1068 sprintf(repl,
"%02d", day);
1070 sprintf(repl,
"%02d", hour);
1085 for (
int i = 0; i < 3; i++) {
1089 if (!(ch = strstr(orig, search)))
1091 strncpy(buffer, orig, (
size_t) (ch - orig));
1092 buffer[ch - orig] = 0;
1093 sprintf(buffer + (ch - orig),
"%s%s", repl, ch + strlen(search));
1095 strcpy(orig, buffer);
1102 const int met_tropo,
1122#pragma omp parallel for default(shared) private(ci,cw)
1123 for (
int ix = 0; ix < nx; ix++)
1124 for (
int iy = 0; iy < ny; iy++) {
1126 &pt[iy * nx + ix], ci, cw, 1);
1128 &ps[iy * nx + ix], ci, cw, 0);
1130 &zs[iy * nx + ix], ci, cw, 0);
1132 lats[iy], &zt[iy * nx + ix], ci, cw, 1);
1134 lats[iy], &tt[iy * nx + ix], ci, cw, 0);
1136 lats[iy], &qt[iy * nx + ix], ci, cw, 0);
1138 lats[iy], &o3t[iy * nx + ix], ci, cw, 0);
1155 *lon2 =
FMOD(lon, 360.);
1156 if (*lon2 < lons[0])
1158 else if (*lon2 > lons[nlon - 1])
1163 if (lats[0] < lats[nlat - 1])
1164 *lat2 =
MIN(
MAX(*lat2, lats[0]), lats[nlat - 1]);
1166 *lat2 =
MIN(
MAX(*lat2, lats[nlat - 1]), lats[0]);
1173 float heights0[
EX][
EY][
EP],
1174 float array0[
EX][
EY][
EP],
1176 float heights1[
EX][
EY][
EP],
1177 float array1[
EX][
EY][
EP],
1179 const double height,
1205 int k_max = ind[0][0];
1206 for (
int i = 0; i < 2; i++)
1207 for (
int j = 0; j < 4; j++) {
1208 if (ci[2] > ind[i][j])
1210 if (k_max < ind[i][j])
1216 cw[0] = (lon2 - met0->
lon[ci[0]]) /
1217 (met0->
lon[ci[0] + 1] - met0->
lon[ci[0]]);
1218 cw[1] = (lat2 - met0->
lat[ci[1]]) /
1219 (met0->
lat[ci[1] + 1] - met0->
lat[ci[1]]);
1222 double height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2]]
1223 - heights0[ci[0]][ci[1]][ci[2]])
1224 + heights0[ci[0]][ci[1]][ci[2]];
1225 double height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2]]
1226 - heights0[ci[0]][ci[1] + 1][ci[2]])
1227 + heights0[ci[0]][ci[1] + 1][ci[2]];
1228 double height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2]]
1229 - heights0[ci[0] + 1][ci[1]][ci[2]])
1230 + heights0[ci[0] + 1][ci[1]][ci[2]];
1231 double height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2]]
1232 - heights0[ci[0] + 1][ci[1] + 1][ci[2]])
1233 + heights0[ci[0] + 1][ci[1] + 1][ci[2]];
1236 double height0 = cw[1] * (height01 - height00) + height00;
1237 double height1 = cw[1] * (height11 - height10) + height10;
1240 double height_bot = cw[0] * (height1 - height0) + height0;
1243 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
1244 - heights0[ci[0]][ci[1]][ci[2] + 1])
1245 + heights0[ci[0]][ci[1]][ci[2] + 1];
1246 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
1247 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
1248 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
1249 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
1250 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
1251 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
1252 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1253 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1254 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1257 height0 = cw[1] * (height01 - height00) + height00;
1258 height1 = cw[1] * (height11 - height10) + height10;
1261 double height_top = cw[0] * (height1 - height0) + height0;
1264 while (((heights0[0][0][0] > heights0[0][0][1]) &&
1265 ((height_bot <= height) || (height_top > height))
1266 && (height_bot >= height) && (ci[2] < k_max))
1268 ((heights0[0][0][0] < heights0[0][0][1]) &&
1269 ((height_bot >= height) || (height_top < height))
1270 && (height_bot <= height) && (ci[2] < k_max))
1274 height_bot = height_top;
1277 height00 = cw[3] * (heights1[ci[0]][ci[1]][ci[2] + 1]
1278 - heights0[ci[0]][ci[1]][ci[2] + 1])
1279 + heights0[ci[0]][ci[1]][ci[2] + 1];
1280 height01 = cw[3] * (heights1[ci[0]][ci[1] + 1][ci[2] + 1]
1281 - heights0[ci[0]][ci[1] + 1][ci[2] + 1])
1282 + heights0[ci[0]][ci[1] + 1][ci[2] + 1];
1283 height10 = cw[3] * (heights1[ci[0] + 1][ci[1]][ci[2] + 1]
1284 - heights0[ci[0] + 1][ci[1]][ci[2] + 1])
1285 + heights0[ci[0] + 1][ci[1]][ci[2] + 1];
1286 height11 = cw[3] * (heights1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1287 - heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1288 + heights0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1291 height0 = cw[1] * (height01 - height00) + height00;
1292 height1 = cw[1] * (height11 - height10) + height10;
1295 height_top = cw[0] * (height1 - height0) + height0;
1299 cw[2] = (height - height_bot)
1300 / (height_top - height_bot);
1304 double array000 = cw[3] * (array1[ci[0]][ci[1]][ci[2]]
1305 - array0[ci[0]][ci[1]][ci[2]])
1306 + array0[ci[0]][ci[1]][ci[2]];
1307 double array100 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2]]
1308 - array0[ci[0] + 1][ci[1]][ci[2]])
1309 + array0[ci[0] + 1][ci[1]][ci[2]];
1310 double array010 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2]]
1311 - array0[ci[0]][ci[1] + 1][ci[2]])
1312 + array0[ci[0]][ci[1] + 1][ci[2]];
1313 double array110 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2]]
1314 - array0[ci[0] + 1][ci[1] + 1][ci[2]])
1315 + array0[ci[0] + 1][ci[1] + 1][ci[2]];
1316 double array001 = cw[3] * (array1[ci[0]][ci[1]][ci[2] + 1]
1317 - array0[ci[0]][ci[1]][ci[2] + 1])
1318 + array0[ci[0]][ci[1]][ci[2] + 1];
1319 double array101 = cw[3] * (array1[ci[0] + 1][ci[1]][ci[2] + 1]
1320 - array0[ci[0] + 1][ci[1]][ci[2] + 1])
1321 + array0[ci[0] + 1][ci[1]][ci[2] + 1];
1322 double array011 = cw[3] * (array1[ci[0]][ci[1] + 1][ci[2] + 1]
1323 - array0[ci[0]][ci[1] + 1][ci[2] + 1])
1324 + array0[ci[0]][ci[1] + 1][ci[2] + 1];
1325 double array111 = cw[3] * (array1[ci[0] + 1][ci[1] + 1][ci[2] + 1]
1326 - array0[ci[0] + 1][ci[1] + 1][ci[2] + 1])
1327 + array0[ci[0] + 1][ci[1] + 1][ci[2] + 1];
1329 double array00 = cw[0] * (array100 - array000) + array000;
1330 double array10 = cw[0] * (array110 - array010) + array010;
1331 double array01 = cw[0] * (array101 - array001) + array001;
1332 double array11 = cw[0] * (array111 - array011) + array011;
1334 double aux0 = cw[1] * (array10 - array00) + array00;
1335 double aux1 = cw[1] * (array11 - array01) + array01;
1338 *var = cw[2] * (aux1 - aux0) + aux0;
1368 cw[0] = (met->
p[ci[0] + 1] - p)
1369 / (met->
p[ci[0] + 1] - met->
p[ci[0]]);
1370 cw[1] = (met->
lon[ci[1] + 1] - lon2)
1371 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
1372 cw[2] = (met->
lat[ci[2] + 1] - lat2)
1373 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
1378 cw[0] * (array[ci[1]][ci[2]][ci[0]] - array[ci[1]][ci[2]][ci[0] + 1])
1379 + array[ci[1]][ci[2]][ci[0] + 1];
1381 cw[0] * (array[ci[1]][ci[2] + 1][ci[0]] -
1382 array[ci[1]][ci[2] + 1][ci[0] + 1])
1383 + array[ci[1]][ci[2] + 1][ci[0] + 1];
1385 cw[0] * (array[ci[1] + 1][ci[2]][ci[0]] -
1386 array[ci[1] + 1][ci[2]][ci[0] + 1])
1387 + array[ci[1] + 1][ci[2]][ci[0] + 1];
1389 cw[0] * (array[ci[1] + 1][ci[2] + 1][ci[0]] -
1390 array[ci[1] + 1][ci[2] + 1][ci[0] + 1])
1391 + array[ci[1] + 1][ci[2] + 1][ci[0] + 1];
1394 aux00 = cw[2] * (aux00 - aux01) + aux01;
1395 aux11 = cw[2] * (aux10 - aux11) + aux11;
1396 *var = cw[1] * (aux00 - aux11) + aux11;
1422 if (z >= zs[ix][iy][iz + 1])
1423 aux00 = array[ix][iy][iz + 1];
1424 else if (z <= zs[ix][iy][iz])
1425 aux00 = array[ix][iy][iz];
1427 aux00 =
LIN(zs[ix][iy][iz], array[ix][iy][iz],
1428 zs[ix][iy][iz + 1], array[ix][iy][iz + 1], z);
1432 if (z >= zs[ix][iy + 1][iz + 1])
1433 aux01 = array[ix][iy + 1][iz + 1];
1434 else if (z <= zs[ix][iy + 1][iz])
1435 aux01 = array[ix][iy + 1][iz];
1437 aux01 =
LIN(zs[ix][iy + 1][iz], array[ix][iy + 1][iz],
1438 zs[ix][iy + 1][iz + 1], array[ix][iy + 1][iz + 1], z);
1442 if (z >= zs[ix + 1][iy][iz + 1])
1443 aux10 = array[ix + 1][iy][iz + 1];
1444 else if (z <= zs[ix + 1][iy][iz])
1445 aux10 = array[ix + 1][iy][iz];
1447 aux10 =
LIN(zs[ix + 1][iy][iz], array[ix + 1][iy][iz],
1448 zs[ix + 1][iy][iz + 1], array[ix + 1][iy][iz + 1], z);
1452 if (z >= zs[ix + 1][iy + 1][iz + 1])
1453 aux11 = array[ix + 1][iy + 1][iz + 1];
1454 else if (z <= zs[ix + 1][iy + 1][iz])
1455 aux11 = array[ix + 1][iy + 1][iz];
1457 aux11 =
LIN(zs[ix + 1][iy + 1][iz], array[ix + 1][iy + 1][iz],
1458 zs[ix + 1][iy + 1][iz + 1], array[ix + 1][iy + 1][iz + 1], z);
1461 double aux0 =
LIN(met->
lat[iy], aux00, met->
lat[iy + 1], aux01, lat2);
1462 double aux1 =
LIN(met->
lat[iy], aux10, met->
lat[iy + 1], aux11, lat2);
1463 *var =
LIN(met->
lon[ix], aux0, met->
lon[ix + 1], aux1, lon2);
1470 float array[
EX][
EY],
1491 cw[1] = (met->
lon[ci[1] + 1] - lon2)
1492 / (met->
lon[ci[1] + 1] - met->
lon[ci[1]]);
1493 cw[2] = (met->
lat[ci[2] + 1] - lat2)
1494 / (met->
lat[ci[2] + 1] - met->
lat[ci[2]]);
1498 double aux00 = array[ci[1]][ci[2]];
1499 double aux01 = array[ci[1]][ci[2] + 1];
1500 double aux10 = array[ci[1] + 1][ci[2]];
1501 double aux11 = array[ci[1] + 1][ci[2] + 1];
1504 if (isfinite(aux00) && isfinite(aux01)
1505 && isfinite(aux10) && isfinite(aux11)) {
1506 aux00 = cw[2] * (aux00 - aux01) + aux01;
1507 aux11 = cw[2] * (aux10 - aux11) + aux11;
1508 *var = cw[1] * (aux00 - aux11) + aux11;
1528 float array0[
EX][
EY][
EP],
1530 float array1[
EX][
EY][
EP],
1547 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
1550 *var = wt * (var0 - var1) + var1;
1558 float array0[
EX][
EY][
EP],
1561 float array1[
EX][
EY][
EP],
1575 *var =
LIN(met0->
time, var0, met1->
time, var1, ts);
1582 float array0[
EX][
EY],
1584 float array1[
EX][
EY],
1600 const double wt = (met1->
time - ts) / (met1->
time - met0->
time);
1603 if (isfinite(var0) && isfinite(var1))
1604 *var = wt * (var0 - var1) + var1;
1615 float array0[
EX][
EY],
1617 float array1[
EX][
EY],
1618 const double lons[
EX],
1619 const double lats[
EY],
1629 double aux0, aux1, aux00, aux01, aux10, aux11, mean = 0;
1638 const int ix =
locate_reg(lons, (
int) nlon, lon2);
1639 const int iy =
locate_irr(lats, (
int) nlat, lat2);
1643 for (
int dx = 0; dx < 2; dx++)
1644 for (
int dy = 0; dy < 2; dy++) {
1645 if (isfinite(array0[ix + dx][iy + dy])) {
1646 mean += array0[ix + dx][iy + dy];
1647 *sigma +=
SQR(array0[ix + dx][iy + dy]);
1650 if (isfinite(array1[ix + dx][iy + dy])) {
1651 mean += array1[ix + dx][iy + dy];
1652 *sigma +=
SQR(array1[ix + dx][iy + dy]);
1657 *sigma = sqrt(
MAX(*sigma / n -
SQR(mean / n), 0.0));
1660 if (method == 1 && isfinite(array0[ix][iy])
1661 && isfinite(array0[ix][iy + 1])
1662 && isfinite(array0[ix + 1][iy])
1663 && isfinite(array0[ix + 1][iy + 1])
1664 && isfinite(array1[ix][iy])
1665 && isfinite(array1[ix][iy + 1])
1666 && isfinite(array1[ix + 1][iy])
1667 && isfinite(array1[ix + 1][iy + 1])) {
1669 aux00 =
LIN(lons[ix], array0[ix][iy],
1670 lons[ix + 1], array0[ix + 1][iy], lon2);
1671 aux01 =
LIN(lons[ix], array0[ix][iy + 1],
1672 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
1673 aux0 =
LIN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
1675 aux10 =
LIN(lons[ix], array1[ix][iy],
1676 lons[ix + 1], array1[ix + 1][iy], lon2);
1677 aux11 =
LIN(lons[ix], array1[ix][iy + 1],
1678 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
1679 aux1 =
LIN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
1681 *var =
LIN(time0, aux0, time1, aux1, time);
1686 aux00 =
NN(lons[ix], array0[ix][iy],
1687 lons[ix + 1], array0[ix + 1][iy], lon2);
1688 aux01 =
NN(lons[ix], array0[ix][iy + 1],
1689 lons[ix + 1], array0[ix + 1][iy + 1], lon2);
1690 aux0 =
NN(lats[iy], aux00, lats[iy + 1], aux01, lat2);
1692 aux10 =
NN(lons[ix], array1[ix][iy],
1693 lons[ix + 1], array1[ix + 1][iy], lon2);
1694 aux11 =
NN(lons[ix], array1[ix][iy + 1],
1695 lons[ix + 1], array1[ix + 1][iy + 1], lon2);
1696 aux1 =
NN(lats[iy], aux10, lats[iy + 1], aux11, lat2);
1698 *var =
NN(time0, aux0, time1, aux1, time);
1723 const time_t jsec0 = (time_t) jsec + timegm(&t0);
1724 t1 = gmtime(&jsec0);
1726 *year = t1->tm_year + 1900;
1727 *mon = t1->tm_mon + 1;
1729 *hour = t1->tm_hour;
1732 *remain = jsec - floor(jsec);
1738 const double kz[
EP],
1739 const double kw[
EP],
1748 const double z =
Z(p);
1753 else if (z > kz[nk - 1])
1757 return LIN(kz[idx], kw[idx], kz[idx + 1], kw[idx + 1], z);
1774 const double a =
RA *
SQR(t), r =
SH(h2o) / (1. -
SH(h2o));
1788 const double press[138] = {
1789 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
1790 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
1791 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
1792 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
1793 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
1794 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
1795 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
1796 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
1797 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
1798 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
1799 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
1800 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
1801 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
1802 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
1803 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
1804 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
1805 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
1806 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
1807 1010.8487, 1013.2500, 1044.45
1810 for (
int ip = 0; ip < ctl->
met_np; ip++)
1817 const double press[92] = {
1818 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
1819 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
1820 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
1821 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
1822 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
1824 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
1825 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
1826 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
1827 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
1828 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
1829 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
1830 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
1831 1007.4431, 1010.8487, 1013.2500, 1044.45
1834 for (
int ip = 0; ip < ctl->
met_np; ip++)
1841 const double press[60] = {
1842 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
1843 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
1844 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
1845 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
1846 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
1847 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
1848 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
1849 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1044.45
1852 for (
int ip = 0; ip < ctl->
met_np; ip++)
1859 const double press[147] = {
1860 0.0200, 0.0310, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861, 0.2499,
1861 0.3299, 0.4288, 0.5496, 0.6952, 0.8690, 1.0742, 1.3143, 1.5928, 1.9134,
1862 2.2797, 2.6954, 3.1642, 3.6898, 4.2759, 4.9262, 5.6441, 6.4334, 7.2974,
1863 8.2397, 9.2634, 10.3720, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945,
1864 18.9752, 20.7610, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
1865 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.1990, 54.5299, 57.9834,
1866 61.5607, 65.2695, 69.1187, 73.1187, 77.2810, 81.6182, 86.1450, 90.8774,
1867 95.8280, 101.0047, 106.4153, 112.0681, 117.9714, 124.1337, 130.5637,
1868 137.2703, 144.2624, 151.5493, 159.1403, 167.0450, 175.2731, 183.8344,
1869 192.7389, 201.9969, 211.6186, 221.6146, 231.9954, 242.7719, 253.9549,
1870 265.5556, 277.5852, 290.0548, 302.9762, 316.3607, 330.2202, 344.5663,
1871 359.4111, 374.7666, 390.6450, 407.0583, 424.0190, 441.5395, 459.6321,
1872 478.3096, 497.5845, 517.4198, 537.7195, 558.3430, 579.1926, 600.1668,
1873 621.1624, 642.0764, 662.8084, 683.2620, 703.3467, 722.9795, 742.0855,
1874 760.5996, 778.4661, 795.6396, 812.0847, 827.7756, 842.6959, 856.8376,
1875 870.2004, 882.7910, 894.6222, 905.7116, 916.0815, 925.7571, 934.7666,
1876 943.1399, 950.9082, 958.1037, 964.7584, 970.9046, 976.5737, 981.7968,
1877 986.6036, 991.0230, 995.0824, 998.8081, 1002.2250, 1005.3562, 1008.2239,
1878 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73, 1028.85,
1880 1035.09, 1038.21, 1041.33, 1044.45
1883 for (
int ip = 0; ip < ctl->
met_np; ip++)
1890 const double press[101] = {
1891 0.0200, 0.0398, 0.0739, 0.1291, 0.2141, 0.3395, 0.5175, 0.7617,
1892 1.0872, 1.5099, 2.0464, 2.7136, 3.5282, 4.5069, 5.6652, 7.0181,
1893 8.5795, 10.3617, 12.3759, 14.6316, 17.1371, 19.8987, 22.9216, 26.2090,
1894 29.7630, 33.5843, 37.6720, 42.0242, 46.6378, 51.5086, 56.6316, 61.9984,
1895 67.5973, 73.4150, 79.4434, 85.7016, 92.2162, 99.0182, 106.1445,
1897 121.5502, 129.9403, 138.8558, 148.3260, 158.3816, 169.0545, 180.3786,
1898 192.3889, 205.1222, 218.6172, 232.9140, 248.0547, 264.0833, 281.0456,
1899 298.9895, 317.9651, 338.0245, 359.2221, 381.6144, 405.2606, 430.2069,
1900 456.4813, 483.8505, 512.0662, 540.8577, 569.9401, 599.0310, 627.9668,
1901 656.6129, 684.8491, 712.5573, 739.5739, 765.7697, 791.0376, 815.2774,
1902 838.3507, 860.1516, 880.6080, 899.6602, 917.2205, 933.2247, 947.6584,
1903 960.5245, 971.8169, 981.5301, 989.7322, 996.8732, 1002.8013,
1904 1007.4431, 1010.8487, 1013.25, 1016.37, 1019.49, 1022.61, 1025.73,
1906 1035.09, 1038.21, 1041.33, 1044.45
1909 for (
int ip = 0; ip < ctl->
met_np; ip++)
1916 const double press[62] = {
1917 0.01, 0.1361, 0.2499, 0.4288, 0.6952, 1.0742,
1918 2.2797, 3.1642, 4.2759, 7.2974, 9.2634, 11.5685, 14.2377, 20.761,
1919 24.6577, 33.8174, 39.1149, 51.199, 57.9834, 73.1187, 81.6182,
1920 90.8774, 101.005, 112.068, 124.134, 137.27, 151.549, 167.045, 183.834,
1921 201.997, 221.615, 242.772, 265.556, 290.055, 316.361, 344.566, 374.767,
1922 407.058, 441.539, 478.31, 517.42, 558.343, 600.167, 683.262, 722.979,
1923 760.6, 795.64, 827.776, 856.838, 882.791, 905.712, 925.757, 943.14,
1924 958.104, 972.495, 986.886, 1001.28, 1015.67, 1030.06, 1034.86, 1039.65,
1928 for (
int ip = 0; ip < ctl->
met_np; ip++)
1935 const double press[137] = {
1936 0.01, 0.02, 0.031, 0.0467, 0.0683, 0.0975, 0.1361, 0.1861,
1937 0.2499, 0.3299, 0.4288, 0.5496, 0.6952, 0.869, 1.0742,
1938 1.3143, 1.5928, 1.9134, 2.2797, 2.6954, 3.1642, 3.6898,
1939 4.2759, 4.9262, 5.6441, 6.4334, 7.2974, 8.2397, 9.2634,
1940 10.372, 11.5685, 12.8561, 14.2377, 15.7162, 17.2945, 18.9752,
1941 20.761, 22.6543, 24.6577, 26.7735, 29.0039, 31.3512, 33.8174,
1942 36.4047, 39.1149, 41.9493, 44.9082, 47.9915, 51.199, 54.5299,
1943 57.9834, 61.5607, 65.2695, 69.1187, 73.1187, 77.281, 81.6182,
1944 86.145, 90.8774, 95.828, 101.005, 106.415, 112.068, 117.971,
1945 124.134, 130.564, 137.27, 144.262, 151.549, 159.14, 167.045,
1946 175.273, 183.834, 192.739, 201.997, 211.619, 221.615, 231.995,
1947 242.772, 253.955, 265.556, 277.585, 290.055, 302.976, 316.361,
1948 330.22, 344.566, 359.411, 374.767, 390.645, 407.058, 424.019,
1949 441.539, 459.632, 478.31, 497.584, 517.42, 537.72, 558.343,
1950 579.193, 600.167, 621.162, 642.076, 662.808, 683.262, 703.347,
1951 722.979, 742.086, 760.6, 778.466, 795.64, 812.085, 827.776,
1952 842.696, 856.838, 870.2, 882.791, 894.622, 905.712, 916.081,
1953 925.757, 934.767, 943.14, 950.908, 958.104, 965.299, 972.495,
1954 979.69, 986.886, 994.081, 1001.28, 1008.47, 1015.67, 1022.86,
1955 1030.06, 1037.25, 1044.45
1958 for (
int ip = 0; ip < ctl->
met_np; ip++)
1965 const double press[59] = {
1966 0.1, 0.2, 0.3843, 0.6365, 0.9564, 1.3448, 1.8058, 2.3478,
1967 2.985, 3.7397, 4.6462, 5.7565, 7.1322, 8.8366, 10.9483,
1968 13.5647, 16.8064, 20.8227, 25.7989, 31.9642, 39.6029, 49.0671,
1969 60.1802, 73.0663, 87.7274, 104.229, 122.614, 142.902, 165.089,
1970 189.147, 215.025, 242.652, 272.059, 303.217, 336.044, 370.407,
1971 406.133, 443.009, 480.791, 519.209, 557.973, 596.777, 635.306,
1972 673.24, 710.263, 746.063, 780.346, 812.83, 843.263, 871.42,
1973 897.112, 920.189, 940.551, 958.148, 975.744, 993.341, 1010.94,
1977 for (
int ip = 0; ip < ctl->
met_np; ip++)
1981 ERRMSG(
"Use 0 for l137, 1 for l91, 2 for l60 or values between 3 and 7.");
1985 ERRMSG(
"Recompile with larger EP to use this pressure level definition.");
1998 int i = (ihi + ilo) >> 1;
2000 if (xx[i] < xx[i + 1])
2001 while (ihi > ilo + 1) {
2002 i = (ihi + ilo) >> 1;
2008 while (ihi > ilo + 1) {
2009 i = (ihi + ilo) >> 1;
2029 int i = (ihi + ilo) >> 1;
2031 if (x >= xx[ig] && x < xx[ig + 1])
2034 if (xx[i] < xx[i + 1])
2035 while (ihi > ilo + 1) {
2036 i = (ihi + ilo) >> 1;
2042 while (ihi > ilo + 1) {
2043 i = (ihi + ilo) >> 1;
2061 const int i = (int) ((x - xx[0]) / (xx[1] - xx[0]));
2075 float profiles[
EX][
EY][
EP],
2077 const int lon_ap_ind,
2078 const int lat_ap_ind,
2079 const double height_ap,
2085 np, height_ap, ind[0]);
2087 np, height_ap, ind[1]);
2089 np, height_ap, ind[2]);
2108 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2112 double dts, u[4], um = 0, v[4], vm = 0, w[4], wm = 0,
2116 for (
int i = 0; i < ctl->
advect; i++) {
2121 x[0] = atm->
lon[ip];
2122 x[1] = atm->
lat[ip];
2125 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
2126 x[0] = atm->
lon[ip] +
DX2DEG(dts * u[i - 1] / 1000., atm->
lat[ip]);
2127 x[1] = atm->
lat[ip] +
DY2DEG(dts * v[i - 1] / 1000.);
2128 x[2] = atm->
p[ip] + dts * w[i - 1];
2130 const double tm = atm->
time[ip] + dts;
2135 tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2137 tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2139 tm, x[2], x[0], x[1], &w[i], ci, cw, 0);
2145 met1, met1->
pl, met1->
ul,
2146 tm, x[2], x[0], x[1], &u[i]);
2148 met1, met1->
pl, met1->
vl,
2149 tm, x[2], x[0], x[1], &v[i]);
2151 met1, met1->
pl, met1->
wl,
2152 tm, x[2], x[0], x[1], &w[i]);
2158 k = (i == 0 ? 0.0 : 1.0);
2159 else if (ctl->
advect == 4)
2160 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2167 atm->
time[ip] += cache->
dt[ip];
2168 atm->
lon[ip] +=
DX2DEG(cache->
dt[ip] * um / 1000.,
2169 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
2170 atm->
lat[ip] +=
DY2DEG(cache->
dt[ip] * vm / 1000.);
2171 atm->
p[ip] += cache->
dt[ip] * wm;
2179 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2185 atm->
lon[ip], atm->
lat[ip],
2189 double dts, u[4], um = 0, v[4], vm = 0, zeta_dot[4],
2190 zeta_dotm = 0, x[3] = { 0, 0, 0 };
2193 for (
int i = 0; i < ctl->
advect; i++) {
2198 x[0] = atm->
lon[ip];
2199 x[1] = atm->
lat[ip];
2202 dts = (i == 3 ? 1.0 : 0.5) * cache->
dt[ip];
2203 x[0] = atm->
lon[ip] +
DX2DEG(dts * u[i - 1] / 1000., atm->
lat[ip]);
2204 x[1] = atm->
lat[ip] +
DY2DEG(dts * v[i - 1] / 1000.);
2205 x[2] = atm->
q[ctl->
qnt_zeta][ip] + dts * zeta_dot[i - 1];
2207 const double tm = atm->
time[ip] + dts;
2211 met1->
ul, tm, x[2], x[0], x[1], &u[i], ci, cw, 1);
2213 met1->
vl, tm, x[2], x[0], x[1], &v[i], ci, cw, 0);
2216 x[1], &zeta_dot[i], ci, cw, 0);
2221 k = (i == 0 ? 0.0 : 1.0);
2222 else if (ctl->
advect == 4)
2223 k = (i == 0 || i == 3 ? 1.0 / 6.0 : 2.0 / 6.0);
2226 zeta_dotm += k * zeta_dot[i];
2230 atm->
time[ip] += cache->
dt[ip];
2231 atm->
lon[ip] +=
DX2DEG(cache->
dt[ip] * um / 1000.,
2232 (ctl->
advect == 2 ? x[1] : atm->
lat[ip]));
2233 atm->
lat[ip] +=
DY2DEG(cache->
dt[ip] * vm / 1000.);
2234 atm->
q[ctl->
qnt_zeta][ip] += cache->
dt[ip] * zeta_dotm;
2240 atm->
lat[ip], &atm->
p[ip], ci, cw, 1);
2259 SELECT_TIMER(
"MODULE_ADVECT_INIT",
"PHYSICS", NVTX_GPU);
2268 atm->
lon[ip], atm->
lat[ip], &atm->
p[ip], ci, cw, 1);
2283 SELECT_TIMER(
"MODULE_BOUND_COND",
"PHYSICS", NVTX_GPU);
2293 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2329 if (atm->
p[ip] < pbl)
2381 ERRMSG(
"Molar mass is not defined!");
2387 const int ensemble_mode = (ctl->
nens > 0);
2388 const int np = atm->
np;
2392 const int ngrid = nx * ny * nz;
2393 const int nens = ensemble_mode ? ctl->
nens : 1;
2395 double *restrict
const z = (
double *) malloc((
size_t) nz *
sizeof(double));
2396 double *restrict
const press =
2397 (
double *) malloc((
size_t) nz *
sizeof(double));
2398 double *restrict
const mass =
2399 (
double *) calloc((
size_t) ngrid * (size_t) nens,
sizeof(
double));
2400 double *restrict
const area =
2401 (
double *) malloc((
size_t) ny *
sizeof(double));
2402 double *restrict
const lon =
2403 (
double *) malloc((
size_t) nx *
sizeof(double));
2404 double *restrict
const lat =
2405 (
double *) malloc((
size_t) ny *
sizeof(double));
2407 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
2408 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
2409 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
2418#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np],z[0:nz],press[0:nz],mass[0:ngrid*nens],area[0:ny],lon[0:nx],lat[0:ny])
2419#pragma acc data present(ctl,met0,met1,atm,ixs,iys,izs,z,press,mass,area,lon,lat)
2420#pragma acc parallel loop independent gang vector
2422#pragma omp parallel for default(shared)
2424 for (
int iz = 0; iz < nz; iz++) {
2426 press[iz] =
P(z[iz]);
2430 const double t0 = tt - 0.5 * ctl->
dt_mod;
2431 const double t1 = tt + 0.5 * ctl->
dt_mod;
2435#pragma acc parallel loop independent gang vector
2437#pragma omp parallel for default(shared)
2439 for (
int ip = 0; ip < np; ip++) {
2443 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
2444 || ixs[ip] < 0 || ixs[ip] >= nx
2445 || iys[ip] < 0 || iys[ip] >= ny || izs[ip] < 0 || izs[ip] >= nz)
2451#pragma acc parallel loop independent gang vector
2453#pragma omp parallel for default(shared)
2455 for (
int ix = 0; ix < nx; ix++)
2459#pragma acc parallel loop independent gang vector
2461#pragma omp parallel for default(shared)
2463 for (
int iy = 0; iy < ny; iy++) {
2465 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
2470#pragma acc parallel loop independent gang vector
2472 for (
int ip = 0; ip < np; ip++) {
2474 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
2475 if (ensemble_mode) {
2476 const int ens = (int) atm->
q[ctl->
qnt_ens][ip];
2477 mass_idx += ens * ngrid;
2480#pragma acc atomic update
2482 mass[mass_idx] += atm->
q[ctl->
qnt_m][ip];
2488#pragma acc parallel loop independent gang vector
2490#pragma omp parallel for default(shared)
2492 for (
int ip = 0; ip < np; ip++)
2500 lon[ixs[ip]], lat[iys[ip]], &temp, ci, cw, 1);
2503 int mass_idx =
ARRAY_3D(ixs[ip], iys[ip], ny, izs[ip], nz);
2504 if (ensemble_mode) {
2505 int ens = (int) atm->
q[ctl->
qnt_ens][ip];
2506 mass_idx += ens * ngrid;
2510 const double m = mass[mass_idx];
2512 / (
RHO(press[izs[ip]], temp) * area[iys[ip]] * dz * 1e9);
2517#pragma acc exit data delete(ixs,iys,izs,z,press,mass,area,lon,lat)
2545 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2562 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
2564 atm->
lat[ip], atm->
p[ip]));
2566 atm->
lat[ip], atm->
p[ip]));
2568 atm->
lat[ip], atm->
p[ip]));
2582 SELECT_TIMER(
"MODULE_CONVECTION",
"PHYSICS", NVTX_GPU);
2588 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2596 double pbot = ps, ptop = ps;
2613 double cape, cin, pel;
2619 if (isfinite(cape) && cape >= ctl->
conv_cape
2621 ptop = GSL_MIN(ptop, pel);
2625 if (ptop != pbot && atm->
p[ip] >= ptop) {
2630 pbot, atm->
lon[ip], atm->
lat[ip], &tbot, ci, cw, 1);
2632 atm->
lon[ip], atm->
lat[ip], &ttop, ci, cw, 1);
2633 const double rhobot = pbot / tbot;
2634 const double rhotop = ptop / ttop;
2637 const double rho = rhobot + (rhotop - rhobot) * cache->
rs[ip];
2640 atm->
p[ip] =
LIN(rhobot, pbot, rhotop, ptop, rho);
2658 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
2661 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,clim,atm)") {
2670 const double aux = exp(-cache->
dt[ip] / tdec);
2671 if (ctl->
qnt_m >= 0) {
2674 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
2675 atm->
q[ctl->
qnt_m][ip] *= aux;
2700 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2708 float umean = 0, usig = 0, vmean = 0, vsig = 0, wmean = 0, wsig = 0;
2709 for (
int i = 0; i < 2; i++)
2710 for (
int j = 0; j < 2; j++)
2711 for (
int k = 0; k < 2; k++) {
2712 umean += met0->
u[ix + i][iy + j][iz + k];
2713 usig +=
SQR(met0->
u[ix + i][iy + j][iz + k]);
2714 vmean += met0->
v[ix + i][iy + j][iz + k];
2715 vsig +=
SQR(met0->
v[ix + i][iy + j][iz + k]);
2716 wmean += met0->
w[ix + i][iy + j][iz + k];
2717 wsig +=
SQR(met0->
w[ix + i][iy + j][iz + k]);
2719 umean += met1->
u[ix + i][iy + j][iz + k];
2720 usig +=
SQR(met1->
u[ix + i][iy + j][iz + k]);
2721 vmean += met1->
v[ix + i][iy + j][iz + k];
2722 vsig +=
SQR(met1->
v[ix + i][iy + j][iz + k]);
2723 wmean += met1->
w[ix + i][iy + j][iz + k];
2724 wsig +=
SQR(met1->
w[ix + i][iy + j][iz + k]);
2726 usig = usig / 16.f -
SQR(umean / 16.f);
2727 usig = (usig > 0 ? sqrtf(usig) : 0);
2728 vsig = vsig / 16.f -
SQR(vmean / 16.f);
2729 vsig = (vsig > 0 ? sqrtf(vsig) : 0);
2730 wsig = wsig / 16.f -
SQR(wmean / 16.f);
2731 wsig = (wsig > 0 ? sqrtf(wsig) : 0);
2734 const double r = 1 - 2 * fabs(cache->
dt[ip]) / ctl->
dt_met;
2735 const double r2 = sqrt(1 - r * r);
2739 cache->
uvwp[ip][0] =
2740 (float) (r * cache->
uvwp[ip][0] +
2745 cache->
uvwp[ip][1] =
2746 (float) (r * cache->
uvwp[ip][1] +
2753 cache->
uvwp[ip][2] =
2754 (float) (r * cache->
uvwp[ip][2] +
2756 atm->
p[ip] += cache->
uvwp[ip][2] * cache->
dt[ip];
2777 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2779 double dsigw_dz = 0.0, sig_u = 0.25, sig_w = 0.1,
2780 tau_u = 300., tau_w = 100.;
2789 if (atm->
p[ip] >= pbl) {
2792 const double p =
MIN(atm->
p[ip], ps);
2793 const double zs =
Z(ps);
2794 const double z = 1e3 * (
Z(p) - zs);
2795 const double zi = 1e3 * (
Z(pbl) - zs);
2796 const double zratio = z / zi;
2799 double ess, nss, h2o, t;
2804 const double rho =
RHO(p,
TVIRT(t, h2o));
2805 const double tau = sqrt(
SQR(ess) +
SQR(nss));
2806 const double ustar = sqrt(tau / rho);
2816 sig_u = 1e-2 + 2.0 * ustar * (1.0 - zratio);
2817 sig_w = 1e-2 + 1.3 * ustar * (1.0 - zratio);
2820 dsigw_dz = -1.3 * ustar / zi;
2823 tau_u = 0.07 * zi / sig_u * sqrt(zratio);
2824 tau_w = 0.1 * zi / sig_w * pow(zratio, 0.8);
2831 const double wstar =
2832 pow(
G0 /
THETAVIRT(p, t, h2o) * shf / (rho *
CPD) * zi, 1. / 3.);
2836 + sqrt(0.4 *
SQR(wstar) + (5.0 - 4.0 * zratio) *
SQR(ustar));
2837 sig_w = 1e-2 + sqrt(1.2 *
SQR(wstar) * (1.0 - 0.9 * zratio)
2838 * pow(zratio, 2.0 / 3.0)
2839 + (1.8 - 1.4 * zratio) *
SQR(ustar));
2842 dsigw_dz = 0.5 / sig_w / zi * (-1.4 *
SQR(ustar) +
SQR(wstar)
2844 pow(
MAX(zratio, 1e-3), -1.0 / 3.0)
2845 - 1.8 * pow(zratio, 2.0 / 3.0)));
2848 const double C0 = 3.0;
2850 (1.5 - 1.2 * pow(zratio, 1.0 / 3.0)) *
SQR(wstar) * wstar / zi
2851 +
SQR(ustar) * ustar * (1.0 - 0.8 * zratio) / (
KARMAN * z);
2852 tau_u = 2 *
SQR(sig_u) / (C0 * eps);
2853 tau_w = 2 *
SQR(sig_w) / (C0 * eps);
2858 sig_u =
MAX(sig_u, 0.25);
2859 sig_w =
MAX(sig_w, 0.1);
2860 tau_u =
MAX(tau_u, 300.);
2861 tau_w =
MAX(tau_w, 100.);
2864 const double ru = exp(-fabs(cache->
dt[ip]) / tau_u);
2865 const double ru2 = sqrt(1.0 -
SQR(ru));
2867 = (float) (cache->
uvwp[ip][0] * ru + ru2 * cache->
rs[3 * ip]);
2869 = (float) (cache->
uvwp[ip][1] * ru + ru2 * cache->
rs[3 * ip + 1]);
2871 const double rw = exp(-fabs(cache->
dt[ip]) / tau_w);
2872 const double rw2 = sqrt(1.0 -
SQR(rw));
2874 = (float) (cache->
uvwp[ip][2] * rw + rw2 * cache->
rs[3 * ip + 2]
2875 + sig_w * dsigw_dz * cache->
dt[ip]);
2882 DZ2DP(cache->
uvwp[ip][2] * cache->
dt[ip] / 1000., atm->
p[ip]);
2904 "acc data present(ctl,cache,clim,met0,met1,atm)") {
2913 const double wpbl =
pbl_weight(ctl, atm, ip, pbl, ps);
2914 const double wtrop =
tropo_weight(clim, atm, ip) * (1.0 - wpbl);
2915 const double wstrat = 1.0 - wpbl - wtrop;
2925 const double sigma = sqrt(2.0 * dx * fabs(cache->
dt[ip])) / 1000.;
2927 atm->
lat[ip] +=
DY2DEG(cache->
rs[3 * ip + 1] * sigma);
2932 const double sigma = sqrt(2.0 * dz * fabs(cache->
dt[ip])) / 1000.;
2933 atm->
p[ip] +=
DZ2DP(cache->
rs[3 * ip + 2] * sigma, atm->
p[ip]);
2952 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
2955 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
2967 const double dz = 1000. * (
Z(ps - ctl->
dry_depo_dp) -
Z(ps));
2987 const double aux = exp(-cache->
dt[ip] * v_dep / dz);
2988 if (ctl->
qnt_m >= 0) {
2991 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
2992 atm->
q[ctl->
qnt_m][ip] *= aux;
3016 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3019 const double a = 3.12541941e-06;
3020 const double b = -5.72532259e-01;
3021 const double low = pow(1. / a, 1. / b);
3024 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3031 if (!(lwc > 0 || rwc > 0))
3042 const double k = 9.1e7 * exp(-29700. /
RI * (1. / t - 1. / 298.15));
3045 const double H_SO2 =
3046 1.3e-2 * exp(2900. * (1. / t - 1. / 298.15)) *
RI * t;
3047 const double K_1S = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
3050 const double H_h2o2 =
3051 8.3e2 * exp(7600. * (1. / t - 1. / 298.15)) *
RI * t;
3057 cor = atm->
q[ctl->
qnt_Cx][ip] >
3058 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
3060 const double h2o2 = H_h2o2
3062 * M * cor * 1000. /
AVO;
3065 const double rho_air = atm->
p[ip] / (
RI * t) *
MA / 10.;
3066 const double CWC = (lwc + rwc) * rho_air / 1e3;
3069 const double rate_coef = k * K_1S * h2o2 * H_SO2 * CWC;
3070 const double aux = exp(-cache->
dt[ip] * rate_coef);
3071 if (ctl->
qnt_m >= 0) {
3074 atm->
q[ctl->
qnt_m][ip] *= aux;
3095 SELECT_TIMER(
"MODULE_ISOSURF_INIT",
"PHYSICS", NVTX_GPU);
3106 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
3109 cache->
iso_var[ip] = atm->
p[ip] / t;
3115 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(cache,met0,met1,atm)") {
3126 LOG(1,
"Read balloon pressure data: %s", ctl->
balloon);
3130 if (!(in = fopen(ctl->
balloon,
"r")))
3131 ERRMSG(
"Cannot open file!");
3135 while (fgets(line,
LEN, in))
3136 if (sscanf(line,
"%lg %lg", &(cache->
iso_ts[cache->
iso_n]),
3139 ERRMSG(
"Too many data points!");
3142 if (cache->
iso_n < 1)
3143 ERRMSG(
"Could not read any data!");
3166 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,met1,atm)") {
3179 atm->
p[ip] = cache->
iso_var[ip] * t;
3185 atm->
p[ip] = 1000. * pow(cache->
iso_var[ip] / t, -1. / 0.286);
3191 atm->
p[ip] = cache->
iso_ps[0];
3218 const int nvar = NVAR, nfix = NFIX, nreact = NREACT;
3219 double rtol[1] = { 1.0e-3 };
3220 double atol[1] = { 1.0 };
3224#pragma acc data copy(rtol,atol,nvar,nfix,nreact)
3227 "acc data present(ctl,cache,clim,met0,met1,atm) ") {
3230 double var[nvar], fix[nfix], rconst[nreact];
3231 for (
int i = 0; i < nvar; i++)
3233 for (
int i = 0; i < nfix; i++)
3235 for (
int i = 0; i < nreact; i++)
3237 kpp_chem_initialize(ctl, clim, met0, met1, atm, var, fix, rconst, ip);
3242 for (
int i = 0; i < 20; i++) {
3249 Rosenbrock(var, fix, rconst, 0, ctl->
dt_kpp,
3250 atol, rtol, &FunTemplate, &JacTemplate, rpar, ipar);
3253 kpp_chem_output2atm(atm, ctl, met0, met1, var, ip);
3274 ERRMSG(
"Need T_ice and T_NAT to calculate T_STS!");
3278 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3280 double ps, ts, zs, us, vs, ess, nss, shf, lsm, sst, pbl, pt, pct, pcb,
3281 cl, plcl, plfc, pel, cape, cin, o3c, pv, t, tt, u, v, w, h2o, h2ot,
3282 o3, lwc, rwc, iwc, swc, cc, z, zt;
3330 atm->
lon[ip], atm->
lat[ip], atm->
p[ip]));
3332 atm->
lat[ip], atm->
p[ip]));
3334 atm->
lat[ip], atm->
p[ip]));
3336 atm->
lat[ip], atm->
p[ip]));
3337 SET_ATM(qnt_vh, sqrt(u * u + v * v));
3357 atm->
lat[ip], atm->
p[ip])));
3375 const int np = atm->
np;
3376 int *restrict
const ixs = (
int *) malloc((
size_t) np *
sizeof(int));
3377 int *restrict
const iys = (
int *) malloc((
size_t) np *
sizeof(int));
3378 int *restrict
const izs = (
int *) malloc((
size_t) np *
sizeof(int));
3386 const double t0 = t - 0.5 * ctl->
dt_mod;
3387 const double t1 = t + 0.5 * ctl->
dt_mod;
3391#pragma acc enter data create(ixs[0:np],iys[0:np],izs[0:np])
3392#pragma acc data present(ctl,clim,atm,ixs,iys,izs)
3393#pragma acc parallel loop independent gang vector
3395#pragma omp parallel for default(shared)
3397 for (
int ip = 0; ip < np; ip++) {
3400 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
mixing_z0) / dz);
3401 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
3402 || ixs[ip] < 0 || ixs[ip] >= ctl->
mixing_nx
3403 || iys[ip] < 0 || iys[ip] >= ctl->
mixing_ny
3404 || izs[ip] < 0 || izs[ip] >= ctl->
mixing_nz)
3409 const int use_ensemble = (ctl->
nens > 0);
3411 const int quantities[] = {
3418 const int n_qnt =
sizeof(quantities) /
sizeof(quantities[0]);
3420 for (
int i = 0; i < n_qnt; i++)
3421 if (quantities[i] >= 0)
3427#pragma acc exit data delete(ixs,iys,izs)
3444 const int use_ensemble) {
3446 const int np = atm->
np;
3448 const int nens = use_ensemble ? ctl->
nens : 1;
3449 const int total_grid = ngrid * nens;
3451 double *restrict
const cmean =
3452 (
double *) malloc((
size_t) total_grid *
sizeof(double));
3453 int *restrict
const count =
3454 (
int *) malloc((
size_t) total_grid *
sizeof(int));
3458#pragma acc enter data create(cmean[0:total_grid],count[0:total_grid])
3459#pragma acc data present(ctl,clim,atm,ixs,iys,izs,cmean,count)
3460#pragma acc parallel loop independent gang vector
3465#pragma omp parallel for
3467 for (
int i = 0; i < total_grid; i++) {
3474#pragma acc parallel loop independent gang vector
3476 for (
int ip = 0; ip < np; ip++)
3478 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
3483#pragma acc atomic update
3485 cmean[idx] += atm->
q[qnt_idx][ip];
3487#pragma acc atomic update
3494#pragma acc parallel loop independent gang vector
3499#pragma omp parallel for
3501 for (
int i = 0; i < total_grid; i++)
3503 cmean[i] /= count[i];
3507#pragma acc parallel loop independent gang vector
3509#pragma omp parallel for
3511 for (
int ip = 0; ip < np; ip++) {
3513 const int ens = use_ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
3515 double mixparam = 1.0;
3524 atm->
q[qnt_idx][ip] += (cmean[idx] - atm->
q[qnt_idx][ip]) * mixparam;
3530#pragma acc exit data delete(cmean,count)
3551 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
3554 const double a = 4.71572206e-08;
3555 const double b = -8.28782867e-01;
3556 const double low = pow(1. / a, 1. / b);
3560 "acc data present(ctl,cache,clim,met0,met1,atm)") {
3586 0 ? pow(298. / t, ctl->
oh_chem[1]) : 1.);
3589 0 ? pow(298. / t, ctl->
oh_chem[3]) : 1.);
3590 const double c = log10(k0 * M / ki);
3591 k = k0 * M / (1. + k0 * M / ki) * pow(0.6, 1. / (1. + c * c));
3600 low ? a * pow(atm->
q[ctl->
qnt_Cx][ip], b) : 1;
3603 const double rate_coef =
3605 atm->
lat[ip], atm->
p[ip]) * M * cor;
3606 const double aux = exp(-cache->
dt[ip] * rate_coef);
3607 if (ctl->
qnt_m >= 0) {
3610 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
3611 atm->
q[ctl->
qnt_m][ip] *= aux;
3632 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(cache,met0,met1,atm)") {
3643 while (atm->
lat[ip] < -90 || atm->
lat[ip] > 90) {
3644 if (atm->
lat[ip] > 90) {
3645 atm->
lat[ip] = 180 - atm->
lat[ip];
3646 atm->
lon[ip] += 180;
3648 if (atm->
lat[ip] < -90) {
3649 atm->
lat[ip] = -180 - atm->
lat[ip];
3650 atm->
lon[ip] += 180;
3655 while (atm->
lon[ip] < -180)
3656 atm->
lon[ip] += 360;
3657 while (atm->
lon[ip] >= 180)
3658 atm->
lon[ip] -= 360;
3661 if (atm->
p[ip] < met0->
p[met0->
np - 1]) {
3662 atm->
p[ip] = met0->
p[met0->
np - 1];
3663 }
else if (atm->
p[ip] > 300.) {
3665 if (atm->
p[ip] > ps)
3677 gsl_rng_env_setup();
3678 if (omp_get_max_threads() >
NTHREADS)
3679 ERRMSG(
"Too many threads!");
3680 for (
int i = 0; i <
NTHREADS; i++) {
3681 rng[i] = gsl_rng_alloc(gsl_rng_default);
3682 gsl_rng_set(rng[i], gsl_rng_default_seed
3683 + (
long unsigned) (ntask *
NTHREADS + i));
3688 if (curandCreateGenerator(&rng_curand, CURAND_RNG_PSEUDO_DEFAULT) !=
3689 CURAND_STATUS_SUCCESS)
3690 ERRMSG(
"Cannot create random number generator!");
3691 if (curandSetPseudoRandomGeneratorSeed(rng_curand, ntask) !=
3692 CURAND_STATUS_SUCCESS)
3693 ERRMSG(
"Cannot set seed for random number generator!");
3696 (cudaStream_t) acc_get_cuda_stream(acc_async_sync)) !=
3697 CURAND_STATUS_SUCCESS)
3698 ERRMSG(
"Cannot set stream for random number generator!");
3715#pragma omp parallel for default(shared)
3716 for (
size_t i = 0; i < n; ++i)
3717 rs[i] = gsl_rng_uniform(rng[omp_get_thread_num()]);
3721 else if (method == 1) {
3722#pragma omp parallel for default(shared)
3723 for (
size_t i = 0; i < n; ++i)
3724 rs[i] = gsl_ran_gaussian_ziggurat(rng[omp_get_thread_num()], 1.0);
3730#pragma acc update device(rs[:n])
3738 const uint64_t key = 0xc8e4fd154ce32f6d;
3742#pragma acc data present(rs)
3743#pragma acc parallel loop independent gang vector
3745#pragma omp parallel for default(shared)
3747 for (
size_t i = 0; i < n + 1; ++i) {
3748 uint64_t r, t, x, y, z;
3749 y = x = (rng_ctr + i) * key;
3752 x = (x >> 32) | (x << 32);
3754 x = (x >> 32) | (x << 32);
3756 x = (x >> 32) | (x << 32);
3758 x = (x >> 32) | (x << 32);
3759 r = t ^ ((x * x + y) >> 32);
3760 rs[i] = (double) r / (
double) UINT64_MAX;
3767#pragma acc parallel loop independent gang vector
3769#pragma omp parallel for default(shared)
3771 for (
size_t i = 0; i < n; i += 2) {
3772 const double r = sqrt(-2.0 * log(rs[i]));
3773 const double phi = 2.0 * M_PI * rs[i + 1];
3774 rs[i] = r * cosf((
float) phi);
3775 rs[i + 1] = r * sinf((
float) phi);
3783#pragma acc host_data use_device(rs)
3788 if (curandGenerateUniformDouble(rng_curand, rs, (n < 4 ? 4 : n)) !=
3789 CURAND_STATUS_SUCCESS)
3790 ERRMSG(
"Cannot create random numbers!");
3794 else if (method == 1) {
3795 if (curandGenerateNormalDouble
3796 (rng_curand, rs, (n < 4 ? 4 : n), 0.0,
3797 1.0) != CURAND_STATUS_SUCCESS)
3798 ERRMSG(
"Cannot create random numbers!");
3802 ERRMSG(
"MPTRAC was compiled without cuRAND!");
3820 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
3828 const double v_s =
sedi(atm->
p[ip], t, atm->
q[ctl->
qnt_rp][ip],
3832 atm->
p[ip] +=
DZ2DP(v_s * cache->
dt[ip] / 1000., atm->
p[ip]);
3847 const int np = atm->
np;
3848 double *restrict
const a = (
double *) malloc((
size_t) np *
sizeof(double));
3849 int *restrict
const p = (
int *) malloc((
size_t) np *
sizeof(int));
3852#pragma acc enter data create(a[0:np],p[0:np])
3853#pragma acc data present(ctl,met0,atm,a,p)
3858#pragma acc parallel loop independent gang vector
3860#pragma omp parallel for default(shared)
3862 for (
int ip = 0; ip < np; ip++) {
3872#pragma acc host_data use_device(a,p)
3877 ERRMSG(
"MPTRAC was compiled without Thrust library!");
3885 for (
int iq = 0; iq < ctl->
nq; iq++)
3890#pragma acc exit data delete(a,p)
3904 double *restrict
const help =
3905 (
double *) malloc((
size_t) np *
sizeof(double));
3909#pragma acc enter data create(help[0:np])
3910#pragma acc data present(a,p,help)
3911#pragma acc parallel loop independent gang vector
3913#pragma omp parallel for default(shared)
3915 for (
int ip = 0; ip < np; ip++)
3916 help[ip] = a[p[ip]];
3918#pragma acc parallel loop independent gang vector
3920#pragma omp parallel for default(shared)
3922 for (
int ip = 0; ip < np; ip++)
3927#pragma acc exit data delete(help)
3944 const double latmin = gsl_stats_min(met0->
lat, 1, (
size_t) met0->
ny),
3945 latmax = gsl_stats_max(met0->
lat, 1, (
size_t) met0->
ny);
3948 (fabs(met0->
lon[met0->
nx - 1] - met0->
lon[0] - 360.0) >= 0.01);
3951 PARTICLE_LOOP(0, atm->
np, 0,
"acc data present(ctl,cache,met0,atm)") {
3957 cache->
dt[ip] = t - atm->
time[ip];
3959 cache->
dt[ip] = 0.0;
3963 if (local && (atm->
lon[ip] <= met0->
lon[0]
3964 || atm->
lon[ip] >= met0->
lon[met0->
nx - 1]
3965 || atm->
lat[ip] <= latmin || atm->
lat[ip] >= latmax))
3966 cache->
dt[ip] = 0.0;
3981 SELECT_TIMER(
"MODULE_TIMESTEPS_INIT",
"PHYSICS", NVTX_GPU);
3985 ctl->
t_start = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
3987 ctl->
t_stop = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
3989 ctl->
t_start = gsl_stats_max(atm->
time, 1, (
size_t) atm->
np);
3991 ctl->
t_stop = gsl_stats_min(atm->
time, 1, (
size_t) atm->
np);
3996 ERRMSG(
"Nothing to do! Check T_STOP and DIRECTION!");
4016 SELECT_TIMER(
"MODULE_TRACER_CHEM",
"PHYSICS", NVTX_GPU);
4020 "acc data present(ctl,cache,clim,met0,met1,atm)") {
4043 const double K_o1d =
ARRHENIUS(3.30e-10, 0, t) * o1d * M;
4045 atm->
p[ip], sza, o3c);
4046 atm->
q[ctl->
qnt_Cccl4][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4051 const double K_o1d =
ARRHENIUS(2.30e-10, 0, t) * o1d * M;
4053 atm->
p[ip], sza, o3c);
4054 atm->
q[ctl->
qnt_Cccl3f][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4059 const double K_o1d =
ARRHENIUS(1.40e-10, -25, t) * o1d * M;
4061 atm->
p[ip], sza, o3c);
4062 atm->
q[ctl->
qnt_Cccl2f2][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4067 const double K_o1d =
ARRHENIUS(1.19e-10, -20, t) * o1d * M;
4069 atm->
p[ip], sza, o3c);
4070 atm->
q[ctl->
qnt_Cn2o][ip] *= exp(-cache->
dt[ip] * (K_hv + K_o1d));
4089 ERRMSG(
"Module needs quantity mass or volume mixing ratio!");
4092 PARTICLE_LOOP(0, atm->
np, 1,
"acc data present(ctl,cache,met0,met1,atm)") {
4098 if (!isfinite(pct) || atm->
p[ip] <= pct)
4114 double lwc, rwc, iwc, swc;
4119 const int inside = (lwc > 0 || rwc > 0 || iwc > 0 || swc > 0);
4133 else if (t <= 238.15)
4153 const double K_1 = 1.23e-2 * exp(2.01e3 * (1. / t - 1. / 298.15));
4154 const double K_2 = 6e-8 * exp(1.12e3 * (1. / t - 1. / 298.15));
4155 h *= (1. + K_1 / H_ion + K_1 * K_2 /
SQR(H_ion));
4159 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
4162 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
4188 const double dz = 1e3 * (
Z(pct) -
Z(pcb));
4191 lambda = h *
RI * t * Is / 3.6e6 / dz * eta;
4196 const double aux = exp(-cache->
dt[ip] * lambda);
4197 if (ctl->
qnt_m >= 0) {
4200 += atm->
q[ctl->
qnt_m][ip] * (1 - aux);
4201 atm->
q[ctl->
qnt_m][ip] *= aux;
4225 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
4227 if (acc_get_num_devices(acc_device_nvidia) <= 0)
4228 ERRMSG(
"Not running on a GPU device!");
4229 acc_set_device_num(rank % acc_get_num_devices(acc_device_nvidia),
4231 acc_device_t device_type = acc_get_device_type();
4232 acc_init(device_type);
4246 SELECT_TIMER(
"CREATE_DATA_REGION",
"MEMORY", NVTX_GPU);
4247 ctl_t *ctlup = *ctl;
4250 met_t *met0up = *met0;
4251 met_t *met1up = *met1;
4252 atm_t *atmup = *atm;
4253#pragma acc enter data create(ctlup[:1],cacheup[:1],climup[:1],met0up[:1],met1up[:1],atmup[:1])
4280 SELECT_TIMER(
"DELETE_DATA_REGION",
"MEMORY", NVTX_GPU);
4281#pragma acc exit data delete (ctl,cache,clim,met0,met1,atm)
4295 MPI_Type_free(&mpi_info->MPI_Particle);
4312 char cachefile[
LEN], cmd[2 *
LEN], filename[
LEN];
4318 if (t == ctl->
t_start || !init) {
4325 ERRMSG(
"Cannot open file!");
4330 ERRMSG(
"Cannot open file!");
4340 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
4341 LOG(1,
"Caching: %s", cachefile);
4342 if (system(cmd) != 0)
4343 WARN(
"Caching command failed!");
4348 if (t > (*met1)->time) {
4358 ERRMSG(
"Cannot open file!");
4368 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
4369 LOG(1,
"Caching: %s", cachefile);
4370 if (system(cmd) != 0)
4371 WARN(
"Caching command failed!");
4376 if (t < (*met0)->time) {
4386 ERRMSG(
"Cannot open file!");
4396 sprintf(cmd,
"cat %s > /dev/null &", cachefile);
4397 LOG(1,
"Caching: %s", cachefile);
4398 if (system(cmd) != 0)
4399 WARN(
"Caching command failed!");
4404 if ((*met0)->nx != 0 && (*met1)->nx != 0) {
4405 if ((*met0)->nx != (*met1)->nx
4406 || (*met0)->ny != (*met1)->ny || (*met0)->np != (*met1)->np)
4407 ERRMSG(
"Meteo grid dimensions do not match!");
4408 for (
int ix = 0; ix < (*met0)->nx; ix++)
4409 if (fabs((*met0)->lon[ix] - (*met1)->lon[ix]) > 0.001)
4410 ERRMSG(
"Meteo grid longitudes do not match!");
4411 for (
int iy = 0; iy < (*met0)->ny; iy++)
4412 if (fabs((*met0)->lat[iy] - (*met1)->lat[iy]) > 0.001)
4413 ERRMSG(
"Meteo grid latitudes do not match!");
4414 for (
int ip = 0; ip < (*met0)->np; ip++)
4415 if (fabs((*met0)->p[ip] - (*met1)->p[ip]) > 0.001)
4416 ERRMSG(
"Meteo grid pressure levels do not match!");
4442 const char *filename,
4455 LOG(1,
"Read atmospheric data: %s", filename);
4475 ERRMSG(
"Atmospheric data type not supported!");
4483 ERRMSG(
"Can not read any data!");
4487 LOG(2,
"Number of particles: %d", atm->
np);
4488 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
4489 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
4490 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
4491 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
4492 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
4493 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
4494 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
4495 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
4496 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
4497 for (
int iq = 0; iq < ctl->
nq; iq++) {
4499 sprintf(msg,
"Quantity %s range: %s ... %s %s",
4502 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
4503 LOG(2, msg, mini, maxi);
4573 const char *filename,
4582 LOG(1,
"\nMassive-Parallel Trajectory Calculations (MPTRAC)\n"
4583 "(executable: %s | version: %s | compiled: %s, %s)\n",
4584 argv[0], VERSION, __DATE__, __TIME__);
4686 ctl->
nq = (int)
scan_ctl(filename, argc, argv,
"NQ", -1,
"0", NULL);
4688 ERRMSG(
"Too many quantities!");
4689 for (
int iq = 0; iq < ctl->
nq; iq++) {
4695 scan_ctl(filename, argc, argv,
"QNT_FORMAT", iq,
"%g",
4697 if (strcasecmp(ctl->
qnt_name[iq],
"aoa") == 0)
4701 SET_QNT(qnt_idx,
"idx",
"particle index",
"-")
4702 SET_QNT(qnt_ens,
"ens",
"ensemble index",
"-")
4703 SET_QNT(qnt_stat,
"stat",
"station flag",
"-")
4704 SET_QNT(qnt_m,
"m",
"mass",
"kg")
4705 SET_QNT(qnt_vmr,
"vmr",
"volume mixing ratio",
"ppv")
4706 SET_QNT(qnt_rp,
"rp",
"particle radius",
"microns")
4707 SET_QNT(qnt_rhop,
"rhop",
"particle density",
"kg/m^3")
4708 SET_QNT(qnt_ps,
"ps",
"surface pressure",
"hPa")
4709 SET_QNT(qnt_ts,
"ts",
"surface temperature",
"K")
4710 SET_QNT(qnt_zs,
"zs",
"surface height",
"km")
4711 SET_QNT(qnt_us,
"us",
"surface zonal wind",
"m/s")
4712 SET_QNT(qnt_vs,
"vs",
"surface meridional wind",
"m/s")
4713 SET_QNT(qnt_ess,
"ess",
"eastward turbulent surface stress",
"N/m^2")
4714 SET_QNT(qnt_nss,
"nss",
"northward turbulent surface stress",
"N/m^2")
4715 SET_QNT(qnt_shf,
"shf",
"surface sensible heat flux",
"W/m^2")
4716 SET_QNT(qnt_lsm,
"lsm",
"land-sea mask",
"1")
4717 SET_QNT(qnt_sst,
"sst",
"sea surface temperature",
"K")
4718 SET_QNT(qnt_pbl,
"pbl",
"planetary boundary layer",
"hPa")
4719 SET_QNT(qnt_pt,
"pt",
"tropopause pressure",
"hPa")
4720 SET_QNT(qnt_tt,
"tt",
"tropopause temperature",
"K")
4721 SET_QNT(qnt_zt,
"zt",
"tropopause geopotential height",
"km")
4722 SET_QNT(qnt_h2ot,
"h2ot",
"tropopause water vapor",
"ppv")
4723 SET_QNT(qnt_zg,
"zg",
"geopotential height",
"km")
4724 SET_QNT(qnt_p,
"p",
"pressure",
"hPa")
4725 SET_QNT(qnt_t,
"t",
"temperature",
"K")
4726 SET_QNT(qnt_rho,
"rho",
"air density",
"kg/m^3")
4727 SET_QNT(qnt_u,
"u",
"zonal wind",
"m/s")
4728 SET_QNT(qnt_v,
"v",
"meridional wind",
"m/s")
4729 SET_QNT(qnt_w,
"w",
"vertical velocity",
"hPa/s")
4730 SET_QNT(qnt_h2o,
"h2o",
"water vapor",
"ppv")
4731 SET_QNT(qnt_o3,
"o3",
"ozone",
"ppv")
4732 SET_QNT(qnt_lwc,
"lwc",
"cloud liquid water content",
"kg/kg")
4733 SET_QNT(qnt_rwc,
"rwc",
"cloud rain water content",
"kg/kg")
4734 SET_QNT(qnt_iwc,
"iwc",
"cloud ice water content",
"kg/kg")
4735 SET_QNT(qnt_swc,
"swc",
"cloud snow water content",
"kg/kg")
4736 SET_QNT(qnt_cc,
"cc",
"cloud cover",
"1")
4737 SET_QNT(qnt_pct,
"pct",
"cloud top pressure",
"hPa")
4738 SET_QNT(qnt_pcb,
"pcb",
"cloud bottom pressure",
"hPa")
4739 SET_QNT(qnt_cl,
"cl",
"total column cloud water",
"kg/m^2")
4740 SET_QNT(qnt_plcl,
"plcl",
"lifted condensation level",
"hPa")
4741 SET_QNT(qnt_plfc,
"plfc",
"level of free convection",
"hPa")
4742 SET_QNT(qnt_pel,
"pel",
"equilibrium level",
"hPa")
4743 SET_QNT(qnt_cape,
"cape",
"convective available potential energy",
4745 SET_QNT(qnt_cin,
"cin",
"convective inhibition",
"J/kg")
4746 SET_QNT(qnt_o3c,
"o3c",
"total column ozone",
"DU")
4747 SET_QNT(qnt_hno3,
"hno3",
"nitric acid",
"ppv")
4748 SET_QNT(qnt_oh,
"oh",
"hydroxyl radical",
"ppv")
4749 SET_QNT(qnt_h2o2,
"h2o2",
"hydrogen peroxide",
"ppv")
4750 SET_QNT(qnt_ho2,
"ho2",
"hydroperoxyl radical",
"ppv")
4751 SET_QNT(qnt_o1d,
"o1d",
"atomic oxygen",
"ppv")
4752 SET_QNT(qnt_mloss_oh,
"mloss_oh",
"mass loss due to OH chemistry",
"kg")
4753 SET_QNT(qnt_mloss_h2o2,
"mloss_h2o2",
4754 "mass loss due to H2O2 chemistry",
"kg")
4755 SET_QNT(qnt_mloss_kpp,
"mloss_kpp",
"mass loss due to kpp chemistry",
4757 SET_QNT(qnt_mloss_wet,
"mloss_wet",
"mass loss due to wet deposition",
4759 SET_QNT(qnt_mloss_dry,
"mloss_dry",
"mass loss due to dry deposition",
4761 SET_QNT(qnt_mloss_decay,
"mloss_decay",
4762 "mass loss due to exponential decay",
"kg")
4763 SET_QNT(qnt_loss_rate,
"loss_rate",
"total loss rate",
"s^-1")
4764 SET_QNT(qnt_psat,
"psat",
"saturation pressure over water",
"hPa")
4765 SET_QNT(qnt_psice,
"psice",
"saturation pressure over ice",
"hPa")
4766 SET_QNT(qnt_pw,
"pw",
"partial water vapor pressure",
"hPa")
4767 SET_QNT(qnt_sh,
"sh",
"specific humidity",
"kg/kg")
4768 SET_QNT(qnt_rh,
"rh",
"relative humidity",
"%%")
4769 SET_QNT(qnt_rhice,
"rhice",
"relative humidity over ice",
"%%")
4770 SET_QNT(qnt_theta,
"theta",
"potential temperature",
"K")
4771 SET_QNT(qnt_zeta,
"zeta",
"zeta coordinate",
"K")
4772 SET_QNT(qnt_zeta_d,
"zeta_d",
"diagnosed zeta coordinate",
"K")
4773 SET_QNT(qnt_zeta_dot,
"zeta_dot",
"velocity of zeta coordinate",
4775 SET_QNT(qnt_tvirt,
"tvirt",
"virtual temperature",
"K")
4776 SET_QNT(qnt_lapse,
"lapse",
"temperature lapse rate",
"K/km")
4777 SET_QNT(qnt_vh,
"vh",
"horizontal velocity",
"m/s")
4778 SET_QNT(qnt_vz,
"vz",
"vertical velocity",
"m/s")
4779 SET_QNT(qnt_pv,
"pv",
"potential vorticity",
"PVU")
4780 SET_QNT(qnt_tdew,
"tdew",
"dew point temperature",
"K")
4781 SET_QNT(qnt_tice,
"tice",
"frost point temperature",
"K")
4782 SET_QNT(qnt_tsts,
"tsts",
"STS existence temperature",
"K")
4783 SET_QNT(qnt_tnat,
"tnat",
"NAT existence temperature",
"K")
4784 SET_QNT(qnt_Cx,
"Cx",
"Trace species x volume mixing ratio",
"ppv")
4785 SET_QNT(qnt_Ch2o,
"Ch2o",
"H2O volume mixing ratio",
"ppv")
4786 SET_QNT(qnt_Co3,
"Co3",
"O3 volume mixing ratio",
"ppv")
4787 SET_QNT(qnt_Cco,
"Cco",
"CO volume mixing ratio",
"ppv")
4788 SET_QNT(qnt_Coh,
"Coh",
"HO volume mixing ratio",
"ppv")
4789 SET_QNT(qnt_Ch,
"Ch",
"H radical volume mixing ratio",
"ppv")
4790 SET_QNT(qnt_Cho2,
"Cho2",
"HO2 volume mixing ratio",
"ppv")
4791 SET_QNT(qnt_Ch2o2,
"Ch2o2",
"H2O2 volume mixing ratio",
"ppv")
4792 SET_QNT(qnt_Co1d,
"Co1d",
"O(1D) volume mixing ratio",
"ppv")
4793 SET_QNT(qnt_Co3p,
"Co3p",
"O(3P) radical volume mixing ratio",
"ppv")
4794 SET_QNT(qnt_Cccl4,
"Cccl4",
"CCl4 (CFC-10) volume mixing ratio",
"ppv")
4795 SET_QNT(qnt_Cccl3f,
"Cccl3f",
"CCl3F (CFC-11) volume mixing ratio",
4797 SET_QNT(qnt_Cccl2f2,
"Cccl2f2",
"CCl2F2 (CFC-12) volume mixing ratio",
4799 SET_QNT(qnt_Cn2o,
"Cn2o",
"N2O volume mixing ratio",
"ppv")
4800 SET_QNT(qnt_Csf6,
"Csf6",
"SF6 volume mixing ratio",
"ppv")
4801 SET_QNT(qnt_aoa,
"aoa",
"age of air",
"s")
4803 SET_QNT(qnt_destination,
"destination",
4804 "subdomain index of destination",
"-")
4805 SET_QNT(qnt_subdomain,
"subdomain",
"current subdomain index",
"-")
4812 (int)
scan_ctl(filename, argc, argv,
"ADVECT_VERT_COORD", -1,
"0", NULL);
4814 ERRMSG(
"Set ADVECT_VERT_COORD to 0, 1, or 2!");
4816 (int)
scan_ctl(filename, argc, argv,
"MET_VERT_COORD", -1,
"0", NULL);
4818 ERRMSG(
"Set MET_VERT_COORD to 0, 1, 2, 3, or 4!");
4820 ERRMSG(
"Please add zeta to your quantities for diabatic calculations!");
4823 (
"Using ADVECT_VERT_COORD = 2 requires meteo data on model levels!");
4827 (int)
scan_ctl(filename, argc, argv,
"DIRECTION", -1,
"1", NULL);
4829 ERRMSG(
"Set DIRECTION to -1 or 1!");
4830 ctl->
t_stop =
scan_ctl(filename, argc, argv,
"T_STOP", -1,
"1e100", NULL);
4831 ctl->
dt_mod =
scan_ctl(filename, argc, argv,
"DT_MOD", -1,
"180", NULL);
4835 ctl->
dt_met =
scan_ctl(filename, argc, argv,
"DT_MET", -1,
"3600", NULL);
4837 (int)
scan_ctl(filename, argc, argv,
"MET_CONVENTION", -1,
"0", NULL);
4839 (int)
scan_ctl(filename, argc, argv,
"MET_TYPE", -1,
"0", NULL);
4842 (
"Please use meteo files in netcdf format for diabatic calculations.");
4844 (int)
scan_ctl(filename, argc, argv,
"MET_CLAMS", -1,
"0", NULL);
4846 (int)
scan_ctl(filename, argc, argv,
"MET_NC_SCALE", -1,
"1", NULL);
4848 (int)
scan_ctl(filename, argc, argv,
"MET_NC_LEVEL", -1,
"0", NULL);
4850 (int)
scan_ctl(filename, argc, argv,
"MET_NC_QUANT", -1,
"0", NULL);
4852 (int)
scan_ctl(filename, argc, argv,
"MET_ZSTD_LEVEL", -1,
"0", NULL);
4853 for (
int i = 0; i <
METVAR; i++) {
4854 char defprec[
LEN] =
"0", deftol[
LEN] =
"0.0";
4856 sprintf(deftol,
"0.5");
4858 sprintf(deftol,
"5.0");
4860 sprintf(defprec,
"8");
4862 (int)
scan_ctl(filename, argc, argv,
"MET_ZFP_PREC", i, defprec, NULL);
4864 scan_ctl(filename, argc, argv,
"MET_ZFP_TOL", i, deftol, NULL);
4867 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_BATCH", -1,
"-1", NULL);
4869 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_ZSTD", -1,
"1", NULL);
4871 (int)
scan_ctl(filename, argc, argv,
"MET_CMS_HEUR", -1,
"1", NULL);
4873 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_Z", -1,
"1.0", NULL);
4875 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_T", -1,
"0.05", NULL);
4877 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_U", -1,
"0.05", NULL);
4879 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_V", -1,
"0.05", NULL);
4881 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_W", -1,
"1.0", NULL);
4883 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_PV", -1,
"1.0", NULL);
4885 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_H2O", -1,
"1.0", NULL);
4887 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_O3", -1,
"1.0", NULL);
4889 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_LWC", -1,
"1.0", NULL);
4891 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_RWC", -1,
"1.0", NULL);
4893 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_IWC", -1,
"1.0", NULL);
4895 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_SWC", -1,
"1.0", NULL);
4897 scan_ctl(filename, argc, argv,
"MET_CMS_EPS_CC", -1,
"1.0", NULL);
4898 ctl->
met_dx = (int)
scan_ctl(filename, argc, argv,
"MET_DX", -1,
"1", NULL);
4899 ctl->
met_dy = (int)
scan_ctl(filename, argc, argv,
"MET_DY", -1,
"1", NULL);
4900 ctl->
met_dp = (int)
scan_ctl(filename, argc, argv,
"MET_DP", -1,
"1", NULL);
4902 ERRMSG(
"MET_DX, MET_DY, and MET_DP need to be greater than zero!");
4903 ctl->
met_sx = (int)
scan_ctl(filename, argc, argv,
"MET_SX", -1,
"1", NULL);
4904 ctl->
met_sy = (int)
scan_ctl(filename, argc, argv,
"MET_SY", -1,
"1", NULL);
4905 ctl->
met_sp = (int)
scan_ctl(filename, argc, argv,
"MET_SP", -1,
"1", NULL);
4907 ERRMSG(
"MET_SX, MET_SY, and MET_SP need to be greater than zero!");
4909 scan_ctl(filename, argc, argv,
"MET_DETREND", -1,
"-999", NULL);
4910 ctl->
met_np = (int)
scan_ctl(filename, argc, argv,
"MET_NP", -1,
"0", NULL);
4912 ERRMSG(
"Too many pressure levels!");
4914 (int)
scan_ctl(filename, argc, argv,
"MET_PRESS_LEVEL_DEF", -1,
"-1",
4920 for (
int ip = 0; ip < ctl->
met_np; ip++)
4922 scan_ctl(filename, argc, argv,
"MET_P", ip,
"", NULL);
4926 (int)
scan_ctl(filename, argc, argv,
"MET_NLEV", -1,
"0", NULL);
4928 ERRMSG(
"Too many model levels!");
4929 for (
int ip = 0; ip < ctl->
met_nlev; ip++) {
4931 scan_ctl(filename, argc, argv,
"MET_LEV_HYAM", ip,
"", NULL);
4933 scan_ctl(filename, argc, argv,
"MET_LEV_HYBM", ip,
"", NULL);
4936 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SX", -1,
"-1", NULL);
4938 (int)
scan_ctl(filename, argc, argv,
"MET_GEOPOT_SY", -1,
"-1", NULL);
4940 (int)
scan_ctl(filename, argc, argv,
"MET_RELHUM", -1,
"0", NULL);
4942 (int)
scan_ctl(filename, argc, argv,
"MET_CAPE", -1,
"1", NULL);
4944 ERRMSG(
"Set MET_CAPE to 0 or 1!");
4946 (int)
scan_ctl(filename, argc, argv,
"MET_PBL", -1,
"3", NULL);
4948 ERRMSG(
"Set MET_PBL to 0 ... 3!");
4950 scan_ctl(filename, argc, argv,
"MET_PBL_MIN", -1,
"0.1", NULL);
4952 scan_ctl(filename, argc, argv,
"MET_PBL_MAX", -1,
"5.0", NULL);
4954 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO", -1,
"3", NULL);
4956 ERRMSG(
"Set MET_TROPO to 0 ... 5!");
4958 scan_ctl(filename, argc, argv,
"MET_TROPO_PV", -1,
"3.5", NULL);
4960 scan_ctl(filename, argc, argv,
"MET_TROPO_THETA", -1,
"380", NULL);
4962 (int)
scan_ctl(filename, argc, argv,
"MET_TROPO_SPLINE", -1,
"1", NULL);
4964 scan_ctl(filename, argc, argv,
"MET_DT_OUT", -1,
"0.1", NULL);
4966 (int)
scan_ctl(filename, argc, argv,
"MET_CACHE", -1,
"0", NULL);
4968 (int)
scan_ctl(filename, argc, argv,
"MET_MPI_SHARE", -1,
"0", NULL);
4971 ctl->
sort_dt =
scan_ctl(filename, argc, argv,
"SORT_DT", -1,
"-999", NULL);
4975 (int)
scan_ctl(filename, argc, argv,
"ISOSURF", -1,
"0", NULL);
4980 (int)
scan_ctl(filename, argc, argv,
"RNG_TYPE", -1,
"1", NULL);
4982 ERRMSG(
"Set RNG_TYPE to 0, 1, or 2!");
4985 ctl->
advect = (int)
scan_ctl(filename, argc, argv,
"ADVECT", -1,
"2", NULL);
4989 ERRMSG(
"Set ADVECT to 0, 1, 2, or 4!");
4993 = (int)
scan_ctl(filename, argc, argv,
"DIFFUSION", -1,
"0", NULL);
4995 ERRMSG(
"Set DIFFUSION to 0, 1 or 2!");
4997 scan_ctl(filename, argc, argv,
"TURB_DX_PBL", -1,
"50", NULL);
4999 scan_ctl(filename, argc, argv,
"TURB_DX_TROP", -1,
"50", NULL);
5001 scan_ctl(filename, argc, argv,
"TURB_DX_STRAT", -1,
"0", NULL);
5003 scan_ctl(filename, argc, argv,
"TURB_DZ_PBL", -1,
"0", NULL);
5005 scan_ctl(filename, argc, argv,
"TURB_DZ_TROP", -1,
"0", NULL);
5007 scan_ctl(filename, argc, argv,
"TURB_DZ_STRAT", -1,
"0.1", NULL);
5009 scan_ctl(filename, argc, argv,
"TURB_MESOX", -1,
"0.16", NULL);
5011 scan_ctl(filename, argc, argv,
"TURB_MESOZ", -1,
"0.16", NULL);
5015 = (int)
scan_ctl(filename, argc, argv,
"CONV_MIX_PBL", -1,
"0", NULL);
5017 =
scan_ctl(filename, argc, argv,
"CONV_PBL_TRANS", -1,
"0", NULL);
5019 =
scan_ctl(filename, argc, argv,
"CONV_CAPE", -1,
"-999", NULL);
5021 =
scan_ctl(filename, argc, argv,
"CONV_CIN", -1,
"-999", NULL);
5022 ctl->
conv_dt =
scan_ctl(filename, argc, argv,
"CONV_DT", -1,
"-999", NULL);
5026 scan_ctl(filename, argc, argv,
"BOUND_MASS", -1,
"-999", NULL);
5028 scan_ctl(filename, argc, argv,
"BOUND_MASS_TREND", -1,
"0", NULL);
5030 scan_ctl(filename, argc, argv,
"BOUND_VMR", -1,
"-999", NULL);
5032 scan_ctl(filename, argc, argv,
"BOUND_VMR_TREND", -1,
"0", NULL);
5034 scan_ctl(filename, argc, argv,
"BOUND_LAT0", -1,
"-999", NULL);
5036 scan_ctl(filename, argc, argv,
"BOUND_LAT1", -1,
"-999", NULL);
5038 scan_ctl(filename, argc, argv,
"BOUND_P0", -1,
"-999", NULL);
5040 scan_ctl(filename, argc, argv,
"BOUND_P1", -1,
"-999", NULL);
5042 scan_ctl(filename, argc, argv,
"BOUND_DPS", -1,
"-999", NULL);
5044 scan_ctl(filename, argc, argv,
"BOUND_DZS", -1,
"-999", NULL);
5046 scan_ctl(filename, argc, argv,
"BOUND_ZETAS", -1,
"-999", NULL);
5048 (int)
scan_ctl(filename, argc, argv,
"BOUND_PBL", -1,
"0", NULL);
5052 if (strcasecmp(ctl->
species,
"CF2Cl2") == 0) {
5056 }
else if (strcasecmp(ctl->
species,
"CFCl3") == 0) {
5060 }
else if (strcasecmp(ctl->
species,
"CH4") == 0) {
5067 }
else if (strcasecmp(ctl->
species,
"CO") == 0) {
5076 }
else if (strcasecmp(ctl->
species,
"CO2") == 0) {
5080 }
else if (strcasecmp(ctl->
species,
"H2O") == 0) {
5082 }
else if (strcasecmp(ctl->
species,
"N2O") == 0) {
5086 }
else if (strcasecmp(ctl->
species,
"NH3") == 0) {
5093 }
else if (strcasecmp(ctl->
species,
"HNO3") == 0) {
5097 }
else if (strcasecmp(ctl->
species,
"NO") == 0) {
5106 }
else if (strcasecmp(ctl->
species,
"NO2") == 0) {
5115 }
else if (strcasecmp(ctl->
species,
"O3") == 0) {
5122 }
else if (strcasecmp(ctl->
species,
"SF6") == 0) {
5126 }
else if (strcasecmp(ctl->
species,
"SO2") == 0) {
5139 sprintf(defstr,
"%g", ctl->
molmass);
5140 ctl->
molmass =
scan_ctl(filename, argc, argv,
"MOLMASS", -1, defstr, NULL);
5145 (int)
scan_ctl(filename, argc, argv,
"OH_CHEM_REACTION", -1, defstr,
5147 for (
int ip = 0; ip < 4; ip++) {
5148 sprintf(defstr,
"%g", ctl->
oh_chem[ip]);
5150 scan_ctl(filename, argc, argv,
"OH_CHEM", ip, defstr, NULL);
5153 scan_ctl(filename, argc, argv,
"OH_CHEM_BETA", -1,
"0", NULL);
5157 (int)
scan_ctl(filename, argc, argv,
"H2O2_CHEM_REACTION", -1,
"0", NULL);
5161 (int)
scan_ctl(filename, argc, argv,
"KPP_CHEM", -1,
"0", NULL);
5162 ctl->
dt_kpp =
scan_ctl(filename, argc, argv,
"DT_KPP", -1,
"1800", NULL);
5166 (int)
scan_ctl(filename, argc, argv,
"TRACER_CHEM", -1,
"0", NULL);
5169 for (
int ip = 0; ip < 2; ip++) {
5172 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_H", ip, defstr, NULL);
5174 for (
int ip = 0; ip < 1; ip++) {
5177 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_H", ip, defstr, NULL);
5180 scan_ctl(filename, argc, argv,
"WET_DEPO_SO2_PH", -1,
"0", NULL);
5182 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_A", -1,
"0", NULL);
5184 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_B", -1,
"0", NULL);
5186 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_A", -1,
"0", NULL);
5188 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_B", -1,
"0", NULL);
5190 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 0,
"0.5", NULL);
5192 scan_ctl(filename, argc, argv,
"WET_DEPO_PRE", 1,
"0.36", NULL);
5194 scan_ctl(filename, argc, argv,
"WET_DEPO_IC_RET_RATIO", -1,
"1", NULL);
5196 scan_ctl(filename, argc, argv,
"WET_DEPO_BC_RET_RATIO", -1,
"1", NULL);
5200 scan_ctl(filename, argc, argv,
"DRY_DEPO_VDEP", -1,
"0", NULL);
5202 scan_ctl(filename, argc, argv,
"DRY_DEPO_DP", -1,
"30", NULL);
5205 scan_ctl(filename, argc, argv,
"CLIM_PHOTO", -1,
5206 "../../data/clams_photolysis_rates.nc", ctl->
clim_photo);
5207 scan_ctl(filename, argc, argv,
"CLIM_HNO3_FILENAME", -1,
5209 scan_ctl(filename, argc, argv,
"CLIM_OH_FILENAME", -1,
5211 scan_ctl(filename, argc, argv,
"CLIM_H2O2_FILENAME", -1,
5213 scan_ctl(filename, argc, argv,
"CLIM_HO2_FILENAME", -1,
5215 scan_ctl(filename, argc, argv,
"CLIM_O1D_FILENAME", -1,
5217 scan_ctl(filename, argc, argv,
"CLIM_CCL4_TIMESERIES", -1,
5219 scan_ctl(filename, argc, argv,
"CLIM_CCL3F_TIMESERIES", -1,
5221 scan_ctl(filename, argc, argv,
"CLIM_CCL2F2_TIMESERIES", -1,
5223 scan_ctl(filename, argc, argv,
"CLIM_N2O_TIMESERIES", -1,
5225 scan_ctl(filename, argc, argv,
"CLIM_SF6_TIMESERIES", -1,
5230 scan_ctl(filename, argc, argv,
"MIXING_DT", -1,
"3600.", NULL);
5232 scan_ctl(filename, argc, argv,
"MIXING_TROP", -1,
"-999", NULL);
5234 scan_ctl(filename, argc, argv,
"MIXING_STRAT", -1,
"-999", NULL);
5236 scan_ctl(filename, argc, argv,
"MIXING_Z0", -1,
"-5", NULL);
5238 scan_ctl(filename, argc, argv,
"MIXING_Z1", -1,
"85", NULL);
5240 (int)
scan_ctl(filename, argc, argv,
"MIXING_NZ", -1,
"90", NULL);
5242 scan_ctl(filename, argc, argv,
"MIXING_LON0", -1,
"-180", NULL);
5244 scan_ctl(filename, argc, argv,
"MIXING_LON1", -1,
"180", NULL);
5246 (int)
scan_ctl(filename, argc, argv,
"MIXING_NX", -1,
"360", NULL);
5248 scan_ctl(filename, argc, argv,
"MIXING_LAT0", -1,
"-90", NULL);
5250 scan_ctl(filename, argc, argv,
"MIXING_LAT1", -1,
"90", NULL);
5252 (int)
scan_ctl(filename, argc, argv,
"MIXING_NY", -1,
"180", NULL);
5256 scan_ctl(filename, argc, argv,
"CHEMGRID_Z0", -1,
"-5", NULL);
5258 scan_ctl(filename, argc, argv,
"CHEMGRID_Z1", -1,
"85", NULL);
5260 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NZ", -1,
"90", NULL);
5262 scan_ctl(filename, argc, argv,
"CHEMGRID_LON0", -1,
"-180", NULL);
5264 scan_ctl(filename, argc, argv,
"CHEMGRID_LON1", -1,
"180", NULL);
5266 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NX", -1,
"360", NULL);
5268 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT0", -1,
"-90", NULL);
5270 scan_ctl(filename, argc, argv,
"CHEMGRID_LAT1", -1,
"90", NULL);
5272 (int)
scan_ctl(filename, argc, argv,
"CHEMGRID_NY", -1,
"180", NULL);
5277 scan_ctl(filename, argc, argv,
"TDEC_STRAT", -1,
"0", NULL);
5280 ctl->
psc_h2o =
scan_ctl(filename, argc, argv,
"PSC_H2O", -1,
"4e-6", NULL);
5282 scan_ctl(filename, argc, argv,
"PSC_HNO3", -1,
"9e-9", NULL);
5288 scan_ctl(filename, argc, argv,
"ATM_DT_OUT", -1,
"86400", NULL);
5290 (int)
scan_ctl(filename, argc, argv,
"ATM_FILTER", -1,
"0", NULL);
5292 (int)
scan_ctl(filename, argc, argv,
"ATM_STRIDE", -1,
"1", NULL);
5294 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE", -1,
"0", NULL);
5296 (int)
scan_ctl(filename, argc, argv,
"ATM_TYPE_OUT", -1,
"-1", NULL);
5300 (int)
scan_ctl(filename, argc, argv,
"ATM_NC_LEVEL", -1,
"0", NULL);
5301 for (
int iq = 0; iq < ctl->
nq; iq++)
5303 (
int)
scan_ctl(filename, argc, argv,
"ATM_NC_QUANT", iq,
"0", NULL);
5305 (int)
scan_ctl(filename, argc, argv,
"OBS_TYPE", -1,
"0", NULL);
5311 scan_ctl(filename, argc, argv,
"CSI_DT_OUT", -1,
"86400", NULL);
5314 scan_ctl(filename, argc, argv,
"CSI_OBSMIN", -1,
"0", NULL);
5316 scan_ctl(filename, argc, argv,
"CSI_MODMIN", -1,
"0", NULL);
5317 ctl->
csi_z0 =
scan_ctl(filename, argc, argv,
"CSI_Z0", -1,
"-5", NULL);
5318 ctl->
csi_z1 =
scan_ctl(filename, argc, argv,
"CSI_Z1", -1,
"85", NULL);
5319 ctl->
csi_nz = (int)
scan_ctl(filename, argc, argv,
"CSI_NZ", -1,
"1", NULL);
5321 scan_ctl(filename, argc, argv,
"CSI_LON0", -1,
"-180", NULL);
5322 ctl->
csi_lon1 =
scan_ctl(filename, argc, argv,
"CSI_LON1", -1,
"180", NULL);
5324 (int)
scan_ctl(filename, argc, argv,
"CSI_NX", -1,
"360", NULL);
5325 ctl->
csi_lat0 =
scan_ctl(filename, argc, argv,
"CSI_LAT0", -1,
"-90", NULL);
5326 ctl->
csi_lat1 =
scan_ctl(filename, argc, argv,
"CSI_LAT1", -1,
"90", NULL);
5328 (int)
scan_ctl(filename, argc, argv,
"CSI_NY", -1,
"180", NULL);
5331 ctl->
nens = (int)
scan_ctl(filename, argc, argv,
"NENS", -1,
"0", NULL);
5334 scan_ctl(filename, argc, argv,
"ENS_DT_OUT", -1,
"86400", NULL);
5337 scan_ctl(filename, argc, argv,
"GRID_BASENAME", -1,
"-",
5342 scan_ctl(filename, argc, argv,
"GRID_DT_OUT", -1,
"86400", NULL);
5344 (int)
scan_ctl(filename, argc, argv,
"GRID_SPARSE", -1,
"0", NULL);
5346 (int)
scan_ctl(filename, argc, argv,
"GRID_NC_LEVEL", -1,
"0", NULL);
5347 for (
int iq = 0; iq < ctl->
nq; iq++)
5349 (
int)
scan_ctl(filename, argc, argv,
"GRID_NC_QUANT", iq,
"0", NULL);
5351 (int)
scan_ctl(filename, argc, argv,
"GRID_STDDEV", -1,
"0", NULL);
5352 ctl->
grid_z0 =
scan_ctl(filename, argc, argv,
"GRID_Z0", -1,
"-5", NULL);
5353 ctl->
grid_z1 =
scan_ctl(filename, argc, argv,
"GRID_Z1", -1,
"85", NULL);
5355 (int)
scan_ctl(filename, argc, argv,
"GRID_NZ", -1,
"1", NULL);
5357 scan_ctl(filename, argc, argv,
"GRID_LON0", -1,
"-180", NULL);
5359 scan_ctl(filename, argc, argv,
"GRID_LON1", -1,
"180", NULL);
5361 (int)
scan_ctl(filename, argc, argv,
"GRID_NX", -1,
"360", NULL);
5363 scan_ctl(filename, argc, argv,
"GRID_LAT0", -1,
"-90", NULL);
5365 scan_ctl(filename, argc, argv,
"GRID_LAT1", -1,
"90", NULL);
5367 (int)
scan_ctl(filename, argc, argv,
"GRID_NY", -1,
"180", NULL);
5369 (int)
scan_ctl(filename, argc, argv,
"GRID_TYPE", -1,
"0", NULL);
5372 scan_ctl(filename, argc, argv,
"PROF_BASENAME", -1,
"-",
5375 ctl->
prof_z0 =
scan_ctl(filename, argc, argv,
"PROF_Z0", -1,
"0", NULL);
5376 ctl->
prof_z1 =
scan_ctl(filename, argc, argv,
"PROF_Z1", -1,
"60", NULL);
5378 (int)
scan_ctl(filename, argc, argv,
"PROF_NZ", -1,
"60", NULL);
5380 scan_ctl(filename, argc, argv,
"PROF_LON0", -1,
"-180", NULL);
5382 scan_ctl(filename, argc, argv,
"PROF_LON1", -1,
"180", NULL);
5384 (int)
scan_ctl(filename, argc, argv,
"PROF_NX", -1,
"360", NULL);
5386 scan_ctl(filename, argc, argv,
"PROF_LAT0", -1,
"-90", NULL);
5388 scan_ctl(filename, argc, argv,
"PROF_LAT1", -1,
"90", NULL);
5390 (int)
scan_ctl(filename, argc, argv,
"PROF_NY", -1,
"180", NULL);
5393 scan_ctl(filename, argc, argv,
"SAMPLE_BASENAME", -1,
"-",
5395 scan_ctl(filename, argc, argv,
"SAMPLE_KERNEL", -1,
"-",
5397 scan_ctl(filename, argc, argv,
"SAMPLE_OBSFILE", -1,
"-",
5400 scan_ctl(filename, argc, argv,
"SAMPLE_DX", -1,
"50", NULL);
5402 scan_ctl(filename, argc, argv,
"SAMPLE_DZ", -1,
"-999", NULL);
5405 scan_ctl(filename, argc, argv,
"STAT_BASENAME", -1,
"-",
5409 ctl->
stat_r =
scan_ctl(filename, argc, argv,
"STAT_R", -1,
"50", NULL);
5411 scan_ctl(filename, argc, argv,
"STAT_T0", -1,
"-1e100", NULL);
5412 ctl->
stat_t1 =
scan_ctl(filename, argc, argv,
"STAT_T1", -1,
"1e100", NULL);
5417 scan_ctl(filename, argc, argv,
"VTK_DT_OUT", -1,
"86400", NULL);
5419 (int)
scan_ctl(filename, argc, argv,
"VTK_STRIDE", -1,
"1", NULL);
5421 scan_ctl(filename, argc, argv,
"VTK_SCALE", -1,
"1.0", NULL);
5423 scan_ctl(filename, argc, argv,
"VTK_OFFSET", -1,
"0.0", NULL);
5425 (int)
scan_ctl(filename, argc, argv,
"VTK_SPHERE", -1,
"0", NULL);
5430 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_MERIDIONAL", -1,
"1",
5433 (int)
scan_ctl(filename, argc, argv,
"DD_SUBDOMAINS_ZONAL", -1,
"1",
5436 (int)
scan_ctl(filename, argc, argv,
"DD_NBR_NEIGHBOURS", -1,
"8", NULL);
5438 (int)
scan_ctl(filename, argc, argv,
"DD_HALOS_SIZE", -1,
"1", NULL);
5446 const char *filename,
5452 LOG(1,
"Read meteo data: %s", filename);
5458 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
5493 ERRMSG(
"MET_TYPE not implemented!");
5547 LOG(2,
"Broadcast data on rank %d...", rank);
5687 module_dd(ctl, atm, cache, mpi_info, met0);
5695 ERRMSG(
"Code was compiled without KPP!");
5728#pragma acc update device(ctl[:1])
5732 if (cache != NULL) {
5735#pragma acc update device(cache[:1])
5742#pragma acc update device(clim[:1])
5749 met_t *met0up = *met0;
5750#pragma acc update device(met0up[:1])
5757 met_t *met1up = *met1;
5758#pragma acc update device(met1up[:1])
5765#pragma acc update device(atm[:1])
5784#pragma acc update host(ctl[:1])
5788 if (cache != NULL) {
5791#pragma acc update host(cache[:1])
5798#pragma acc update host(clim[:1])
5805 met_t *met0up = *met0;
5806#pragma acc update host(met0up[:1])
5813 met_t *met1up = *met1;
5814#pragma acc update host(met1up[:1])
5821#pragma acc update host(atm[:1])
5829 const char *filename,
5838 LOG(1,
"Write atmospheric data: %s", filename);
5862 ERRMSG(
"Atmospheric data type not supported!");
5866 LOG(2,
"Number of particles: %d", atm->
np);
5867 gsl_stats_minmax(&mini, &maxi, atm->
time, 1, (
size_t) atm->
np);
5868 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
5869 gsl_stats_minmax(&mini, &maxi, atm->
p, 1, (
size_t) atm->
np);
5870 LOG(2,
"Altitude range: %g ... %g km",
Z(maxi),
Z(mini));
5871 LOG(2,
"Pressure range: %g ... %g hPa", maxi, mini);
5872 gsl_stats_minmax(&mini, &maxi, atm->
lon, 1, (
size_t) atm->
np);
5873 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
5874 gsl_stats_minmax(&mini, &maxi, atm->
lat, 1, (
size_t) atm->
np);
5875 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
5876 for (
int iq = 0; iq < ctl->
nq; iq++) {
5878 sprintf(msg,
"Quantity %s range: %s ... %s %s",
5881 gsl_stats_minmax(&mini, &maxi, atm->
q[iq], 1, (
size_t) atm->
np);
5882 LOG(2, msg, mini, maxi);
5889 const char *filename,
5897 LOG(1,
"Write meteo data: %s", filename);
5902 ERRMSG(
"MPTRAC was compiled without zfp compression!");
5906 ERRMSG(
"MPTRAC was compiled without zstd compression!");
5910 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
5923 ERRMSG(
"MET_TYPE not implemented!");
5929 const char *dirname,
5936 char ext[10], filename[2 *
LEN];
5940 int year, mon, day, hour, min, sec;
5943 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
5958 sprintf(ext,
"tab");
5960 sprintf(ext,
"bin");
5963 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
5964 dirname, ctl->
atm_basename, year, mon, day, hour, min, ext);
5970 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.%s",
5973 write_grid(filename, ctl, met0, met1, atm, t);
5978 sprintf(filename,
"%s/%s.tab", dirname, ctl->
csi_basename);
5984 sprintf(filename,
"%s/%s_%04d_%02d_%02d_%02d_%02d.tab",
5985 dirname, ctl->
ens_basename, year, mon, day, hour, min);
5991 sprintf(filename,
"%s/%s.tab", dirname, ctl->
prof_basename);
5992 write_prof(filename, ctl, met0, met1, atm, t);
6003 sprintf(filename,
"%s/%s.tab", dirname, ctl->
stat_basename);
6012 sprintf(filename,
"%s/%s_%05d.vtk", dirname, ctl->
vtk_basename, ++nvtk);
6022 const double hno3) {
6025 const double h2o_help =
MAX(h2o, 0.1e-6);
6028 const double p_hno3 = hno3 * p / 1.333224;
6029 const double p_h2o = h2o_help * p / 1.333224;
6030 const double a = 0.009179 - 0.00088 * log10(p_h2o);
6031 const double b = (38.9855 - log10(p_hno3) - 2.7836 * log10(p_h2o)) / a;
6032 const double c = -11397.0 / a;
6033 double tnat = (-b + sqrt(b * b - 4. * c)) / 2.;
6034 double x2 = (-b - sqrt(b * b - 4. * c)) / 2.;
6052 const double p0 = pbl;
6055 if (atm->
p[ip] > p0)
6057 else if (atm->
p[ip] < p1)
6060 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
6066 const char *filename,
6072 if (!(in = fopen(filename,
"r"))) {
6073 WARN(
"Cannot open file!");
6079 while (fgets(line,
LEN, in)) {
6083 TOK(line, tok,
"%lg", atm->
time[atm->
np]);
6084 TOK(NULL, tok,
"%lg", atm->
p[atm->
np]);
6085 TOK(NULL, tok,
"%lg", atm->
lon[atm->
np]);
6086 TOK(NULL, tok,
"%lg", atm->
lat[atm->
np]);
6087 for (
int iq = 0; iq < ctl->
nq; iq++)
6088 TOK(NULL, tok,
"%lg", atm->
q[iq][atm->
np]);
6091 atm->
p[atm->
np] =
P(atm->
p[atm->
np]);
6094 if ((++atm->
np) >
NP)
6095 ERRMSG(
"Too many data points!");
6108 const char *filename,
6114 if (!(in = fopen(filename,
"r")))
6119 FREAD(&version,
int,
6123 ERRMSG(
"Wrong version of binary data!");
6141 for (
int iq = 0; iq < ctl->
nq; iq++)
6142 FREAD(atm->
q[iq],
double,
6152 ERRMSG(
"Error while reading binary data!");
6164 const char *filename,
6171 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
6178 if (nc_inq_varid(ncid,
"TIME_INIT", &varid) == NC_NOERR) {
6179 NC(nc_get_var_double(ncid, varid, atm->
time));
6181 WARN(
"TIME_INIT not found use time instead!");
6184 for (
int ip = 0; ip < atm->
np; ip++) {
6185 atm->
time[ip] = time_init;
6197 if (nc_inq_varid(ncid,
"PRESS_INIT", &varid) == NC_NOERR) {
6198 NC(nc_get_var_double(ncid, varid, atm->
p));
6200 WARN(
"PRESS_INIT not found use PRESS instead!");
6201 nc_inq_varid(ncid,
"PRESS", &varid);
6202 NC(nc_get_var_double(ncid, varid, atm->
p));
6207 for (
int iq = 0; iq < ctl->
nq; iq++)
6224 const char *filename,
6231 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
6244 for (
int iq = 0; iq < ctl->
nq; iq++)
6257 const char *filename,
6263 LOG(1,
"Read photolysis rates: %s", filename);
6266 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
6267 WARN(
"Photolysis rate data are missing!");
6274 if (photo->
p[0] < photo->
p[1])
6275 ERRMSG(
"Pressure data are not descending!");
6280 if (photo->
o3c[0] > photo->
o3c[1])
6281 ERRMSG(
"Total column ozone data are not ascending!");
6286 if (photo->
sza[0] > photo->
sza[1])
6287 ERRMSG(
"Solar zenith angle data are not ascending!");
6304 LOG(2,
"Number of pressure levels: %d", photo->
np);
6305 LOG(2,
"Altitude levels: %g, %g ... %g km",
6306 Z(photo->
p[0]),
Z(photo->
p[1]),
Z(photo->
p[photo->
np - 1]));
6307 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
6308 photo->
p[0], photo->
p[1], photo->
p[photo->
np - 1]);
6309 LOG(2,
"Number of solar zenith angles: %d", photo->
nsza);
6310 LOG(2,
"Solar zenith angles: %g, %g ... %g deg",
6313 LOG(2,
"Number of total column ozone values: %d", photo->
no3c);
6314 LOG(2,
"Total column ozone: %g, %g ... %g DU",
6316 LOG(2,
"N2O photolysis rate: %g, %g ... %g s**-1",
6317 photo->
n2o[0][0][0], photo->
n2o[1][0][0],
6318 photo->
n2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
6319 LOG(2,
"CCl4 photolysis rate: %g, %g ... %g s**-1",
6320 photo->
ccl4[0][0][0], photo->
ccl4[1][0][0],
6322 LOG(2,
"CFC-11 photolysis rate: %g, %g ... %g s**-1",
6323 photo->
ccl3f[0][0][0], photo->
ccl3f[1][0][0],
6325 LOG(2,
"CFC-12 photolysis rate: %g, %g ... %g s**-1",
6328 LOG(2,
"O2 photolysis rate: %g, %g ... %g s**-1",
6329 photo->
o2[0][0][0], photo->
o2[1][0][0],
6330 photo->
o2[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
6331 LOG(2,
"O3 -> O(1D) photolysis rate: %g, %g ... %g s**-1",
6332 photo->
o3_1[0][0][0], photo->
o3_1[1][0][0],
6334 LOG(2,
"O3 -> O(3P) photolysis rate: %g, %g ... %g s**-1",
6335 photo->
o3_2[0][0][0], photo->
o3_2[1][0][0],
6337 LOG(2,
"H2O2 photolysis rate: %g, %g ... %g s**-1",
6338 photo->
h2o2[0][0][0], photo->
h2o2[1][0][0],
6340 LOG(2,
"H2O photolysis rate: %g, %g ... %g s**-1",
6341 photo->
h2o[0][0][0], photo->
h2o[1][0][0],
6342 photo->
h2o[photo->
np - 1][photo->
nsza - 1][photo->
no3c - 1]);
6349 const char *varname,
6363 for (
int ip = 0; ip < photo->
np; ip++)
6364 for (
int is = 0; is < photo->
nsza; is++)
6365 for (
int io = 0; io < photo->
no3c; io++)
6376 const char *filename,
6380 LOG(1,
"Read climatological time series: %s", filename);
6384 if (!(in = fopen(filename,
"r"))) {
6385 WARN(
"Cannot open file!");
6392 while (fgets(line,
LEN, in))
6393 if (sscanf(line,
"%lg %lg", &ts->
time[nh], &ts->
vmr[nh]) == 2) {
6396 ts->
time[nh] = (ts->
time[nh] - 2000.0) * 365.25 * 86400.;
6399 if (nh > 0 && ts->
time[nh] <= ts->
time[nh - 1])
6400 ERRMSG(
"Time series must be ascending!");
6404 ERRMSG(
"Too many data points!");
6413 ERRMSG(
"Not enough data points!");
6416 LOG(2,
"Number of time steps: %d", ts->
ntime);
6417 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s", ts->
time[0], ts->
time[1],
6419 LOG(2,
"Volume mixing ratio range: %g ... %g ppv",
6420 gsl_stats_min(ts->
vmr, 1, (
size_t) nh), gsl_stats_max(ts->
vmr, 1,
6430 const char *filename,
6431 const char *varname,
6434 int ncid, varid, it, iy, iz, iz2, nt;
6436 double *help, varmin = 1e99, varmax = -1e99;
6439 LOG(1,
"Read %s data: %s", varname, filename);
6442 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
6443 WARN(
"%s climatology data are missing!", varname);
6450 if (zm->
p[0] < zm->
p[1])
6451 ERRMSG(
"Pressure data are not descending!");
6456 if (zm->
lat[0] > zm->
lat[1])
6457 ERRMSG(
"Latitude data are not ascending!");
6461 zm->
time[0] = 1209600.00;
6462 zm->
time[1] = 3888000.00;
6463 zm->
time[2] = 6393600.00;
6464 zm->
time[3] = 9072000.00;
6465 zm->
time[4] = 11664000.00;
6466 zm->
time[5] = 14342400.00;
6467 zm->
time[6] = 16934400.00;
6468 zm->
time[7] = 19612800.00;
6469 zm->
time[8] = 22291200.00;
6470 zm->
time[9] = 24883200.00;
6471 zm->
time[10] = 27561600.00;
6472 zm->
time[11] = 30153600.00;
6481 for (it = 0; it < zm->
ntime; it++)
6482 for (iz = 0; iz < zm->
np; iz++)
6483 for (iy = 0; iy < zm->
nlat; iy++)
6488 for (it = 0; it < zm->
ntime; it++)
6489 for (iy = 0; iy < zm->
nlat; iy++)
6490 for (iz = 0; iz < zm->
np; iz++) {
6491 if (zm->
vmr[it][iz][iy] < 0) {
6492 for (iz2 = 0; iz2 < zm->
np; iz2++)
6493 if (zm->
vmr[it][iz2][iy] >= 0) {
6494 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
6497 for (iz2 = zm->
np - 1; iz2 >= 0; iz2--)
6498 if (zm->
vmr[it][iz2][iy] >= 0) {
6499 zm->
vmr[it][iz][iy] = zm->
vmr[it][iz2][iy];
6503 varmin =
MIN(varmin, zm->
vmr[it][iz][iy]);
6504 varmax =
MAX(varmax, zm->
vmr[it][iz][iy]);
6511 LOG(2,
"Number of time steps: %d", zm->
ntime);
6512 LOG(2,
"Time steps: %.2f, %.2f ... %.2f s",
6514 LOG(2,
"Number of pressure levels: %d", zm->
np);
6515 LOG(2,
"Altitude levels: %g, %g ... %g km",
6516 Z(zm->
p[0]),
Z(zm->
p[1]),
Z(zm->
p[zm->
np - 1]));
6517 LOG(2,
"Pressure levels: %g, %g ... %g hPa", zm->
p[0],
6518 zm->
p[1], zm->
p[zm->
np - 1]);
6519 LOG(2,
"Number of latitudes: %d", zm->
nlat);
6520 LOG(2,
"Latitudes: %g, %g ... %g deg",
6522 LOG(2,
"%s volume mixing ratio range: %g ... %g ppv", varname, varmin,
6529 const char *filename,
6535 LOG(1,
"Read kernel function: %s", filename);
6539 if (!(in = fopen(filename,
"r")))
6540 ERRMSG(
"Cannot open file!");
6545 while (fgets(line,
LEN, in))
6546 if (sscanf(line,
"%lg %lg", &kz[n], &kw[n]) == 2) {
6547 if (n > 0 && kz[n] < kz[n - 1])
6548 ERRMSG(
"Height levels must be ascending!");
6550 ERRMSG(
"Too many height levels!");
6559 ERRMSG(
"Not enough height levels!");
6562 const double kmax = gsl_stats_max(kw, 1, (
size_t) n);
6563 for (
int iz = 0; iz < n; iz++)
6570 const char *filename,
6578 int year, mon, day, hour, min, sec;
6584 if (!(in = fopen(filename,
"r"))) {
6585 WARN(
"Cannot open file!");
6591 FREAD(&met_type,
int,
6595 ERRMSG(
"Wrong MET_TYPE of binary data!");
6599 FREAD(&version,
int,
6603 ERRMSG(
"Wrong version of binary data!");
6609 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
6610 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
6611 met->
time, year, mon, day, hour, min);
6612 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
6613 || day < 1 || day > 31 || hour < 0 || hour > 23)
6614 ERRMSG(
"Error while reading time!");
6620 LOG(2,
"Number of longitudes: %d", met->
nx);
6621 if (met->
nx < 2 || met->
nx >
EX)
6622 ERRMSG(
"Number of longitudes out of range!");
6627 LOG(2,
"Number of latitudes: %d", met->
ny);
6628 if (met->
ny < 2 || met->
ny >
EY)
6629 ERRMSG(
"Number of latitudes out of range!");
6634 LOG(2,
"Number of levels: %d", met->
np);
6635 if (met->
np < 2 || met->
np >
EP)
6636 ERRMSG(
"Number of levels out of range!");
6642 LOG(2,
"Longitudes: %g, %g ... %g deg",
6648 LOG(2,
"Latitudes: %g, %g ... %g deg",
6654 LOG(2,
"Altitude levels: %g, %g ... %g km",
6655 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
6656 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
6657 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
6706 ERRMSG(
"Error while reading binary data!");
6721 const char *varname) {
6730 LOG(2,
"Read 2-D variable: %s (uncompressed)", varname);
6732 (
size_t) (met->
nx * met->
ny),
6736 for (
int ix = 0; ix < met->
nx; ix++)
6737 for (
int iy = 0; iy < met->
ny; iy++)
6738 var[ix][iy] = help[
ARRAY_2D(ix, iy, met->
ny)];
6751 const char *varname,
6752 const float bound_min,
6753 const float bound_max) {
6763 LOG(2,
"Read 3-D variable: %s (uncompressed)", varname);
6765 (
size_t) (met->
nx * met->
ny * met->
np),
6772 (
size_t) met->
np, 1, in);
6778 FREAD(&precision,
int,
6783 FREAD(&tolerance,
double,
6790 ERRMSG(
"MPTRAC was compiled without zfp compression!");
6800 ERRMSG(
"MPTRAC was compiled without zstd compression!");
6808 (
size_t) met->
np, 1, in);
6810 ERRMSG(
"MPTRAC was compiled without cmultiscale compression!");
6815#pragma omp parallel for default(shared) collapse(2)
6816 for (
int ix = 0; ix < met->
nx; ix++)
6817 for (
int iy = 0; iy < met->
ny; iy++)
6818 for (
int ip = 0; ip < met->
np; ip++) {
6819 var[ix][iy][ip] = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
6820 if (var[ix][iy][ip] < bound_min)
6821 var[ix][iy][ip] = bound_min;
6822 else if (var[ix][iy][ip] > bound_max)
6823 var[ix][iy][ip] = bound_max;
6843 LOG(2,
"Calculate CAPE...");
6846 const double pfac = 1.01439, dz0 =
RI /
MA /
G0 * log(pfac);
6849#pragma omp parallel for default(shared) collapse(2)
6850 for (
int ix = 0; ix < met->
nx; ix++)
6851 for (
int iy = 0; iy < met->
ny; iy++) {
6855 double h2o = 0, t, theta = 0;
6856 double pbot =
MIN(met->
ps[ix][iy], met->
p[0]);
6857 double ptop = pbot - 50.;
6858 for (
int ip = 0; ip < met->
np; ip++) {
6859 if (met->
p[ip] <= pbot) {
6860 theta +=
THETA(met->
p[ip], met->
t[ix][iy][ip]);
6861 h2o += met->
h2o[ix][iy][ip];
6864 if (met->
p[ip] < ptop && n > 0)
6871 met->
plcl[ix][iy] = NAN;
6872 met->
plfc[ix][iy] = NAN;
6873 met->
pel[ix][iy] = NAN;
6874 met->
cape[ix][iy] = NAN;
6875 met->
cin[ix][iy] = NAN;
6881 pbot = met->
ps[ix][iy];
6883 met->
plcl[ix][iy] = (float) (0.5 * (pbot + ptop));
6884 t = theta / pow(1000. / met->
plcl[ix][iy], 0.286);
6885 if (
RH(met->
plcl[ix][iy], t, h2o) > 100.)
6886 ptop = met->
plcl[ix][iy];
6888 pbot = met->
plcl[ix][iy];
6889 }
while (pbot - ptop > 0.1);
6893 double dcape, dz, h2o_env, t_env;
6894 double p = met->
ps[ix][iy];
6895 met->
cape[ix][iy] = met->
cin[ix][iy] = 0;
6897 dz = dz0 *
TVIRT(t, h2o);
6899 t = theta / pow(1000. / p, 0.286);
6903 &h2o_env, ci, cw, 0);
6904 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
6905 TVIRT(t_env, h2o_env) * dz;
6907 met->
cin[ix][iy] += fabsf((
float) dcape);
6908 }
while (p > met->
plcl[ix][iy]);
6913 p = met->
plcl[ix][iy];
6914 t = theta / pow(1000. / p, 0.286);
6917 dz = dz0 *
TVIRT(t, h2o);
6920 double psat =
PSAT(t);
6921 h2o = psat / (p - (1. -
EPS) * psat);
6925 &h2o_env, ci, cw, 0);
6926 double dcape_old = dcape;
6927 dcape = 1e3 *
G0 * (
TVIRT(t, h2o) -
TVIRT(t_env, h2o_env)) /
6928 TVIRT(t_env, h2o_env) * dz;
6930 met->
cape[ix][iy] += (float) dcape;
6931 if (!isfinite(met->
plfc[ix][iy]))
6932 met->
plfc[ix][iy] = (
float) p;
6933 }
else if (dcape_old > 0)
6934 met->
pel[ix][iy] = (float) p;
6935 if (dcape < 0 && !isfinite(met->
plfc[ix][iy]))
6936 met->
cin[ix][iy] += fabsf((
float) dcape);
6940 if (!isfinite(met->
plfc[ix][iy]))
6941 met->
cin[ix][iy] = NAN;
6952 LOG(2,
"Calculate cloud data...");
6955 const double ccmin = 0.01, cwmin = 1e-6;
6958#pragma omp parallel for default(shared) collapse(2)
6959 for (
int ix = 0; ix < met->
nx; ix++)
6960 for (
int iy = 0; iy < met->
ny; iy++) {
6963 met->
pct[ix][iy] = NAN;
6964 met->
pcb[ix][iy] = NAN;
6965 met->
cl[ix][iy] = 0;
6968 for (
int ip = 0; ip < met->
np - 1; ip++) {
6971 if (met->
p[ip] > met->
ps[ix][iy] || met->
p[ip] <
P(20.))
6975 if (met->
cc[ix][iy][ip] > ccmin
6976 && (met->
lwc[ix][iy][ip] > cwmin
6977 || met->
rwc[ix][iy][ip] > cwmin
6978 || met->
iwc[ix][iy][ip] > cwmin
6979 || met->
swc[ix][iy][ip] > cwmin)) {
6983 = (float) (0.5 * (met->
p[ip] + (
float) met->
p[ip + 1]));
6986 if (!isfinite(met->
pcb[ix][iy]))
6988 = (
float) (0.5 * (met->
p[ip] + met->
p[
MAX(ip - 1, 0)]));
6992 met->
cl[ix][iy] += (float)
6993 (0.5 * (met->
lwc[ix][iy][ip] + met->
lwc[ix][iy][ip + 1]
6994 + met->
rwc[ix][iy][ip] + met->
rwc[ix][iy][ip + 1]
6995 + met->
iwc[ix][iy][ip] + met->
iwc[ix][iy][ip + 1]
6996 + met->
swc[ix][iy][ip] + met->
swc[ix][iy][ip + 1])
6997 * 100. * (met->
p[ip] - met->
p[ip + 1]) /
G0);
7015 SELECT_TIMER(
"READ_MET_DETREND",
"METPROC", NVTX_READ);
7016 LOG(2,
"Detrend meteo data...");
7023 const double tssq = 2. *
SQR(sigma);
7026 int sy = (int) (3. *
DY2DEG(sigma) / fabs(met->
lat[1] - met->
lat[0]));
7030#pragma omp parallel for default(shared) collapse(2)
7031 for (
int ix = 0; ix < met->
nx; ix++) {
7032 for (
int iy = 0; iy < met->
ny; iy++) {
7040 (int) (3. *
DX2DEG(sigma, met->
lat[iy]) /
7041 fabs(met->
lon[1] - met->
lon[0]));
7046 for (
int ip = 0; ip < met->
np; ip++) {
7047 help->
t[ix][iy][ip] = 0;
7048 help->
u[ix][iy][ip] = 0;
7049 help->
v[ix][iy][ip] = 0;
7050 help->
w[ix][iy][ip] = 0;
7054 for (
int ix2 = ix - sx; ix2 <= ix + sx; ix2++) {
7058 else if (ix3 >= met->
nx)
7060 for (
int iy2 =
MAX(iy - sy, 0);
7061 iy2 <=
MIN(iy + sy, met->
ny - 1); iy2++) {
7068 const float w = (float) exp(-
DIST2(x0, x1) / tssq);
7072 for (
int ip = 0; ip < met->
np; ip++) {
7073 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip];
7074 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip];
7075 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip];
7076 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip];
7082 for (
int ip = 0; ip < met->
np; ip++) {
7083 help->
t[ix][iy][ip] /= wsum;
7084 help->
u[ix][iy][ip] /= wsum;
7085 help->
v[ix][iy][ip] /= wsum;
7086 help->
w[ix][iy][ip] /= wsum;
7092#pragma omp parallel for default(shared) collapse(3)
7093 for (
int ix = 0; ix < met->
nx; ix++)
7094 for (
int iy = 0; iy < met->
ny; iy++)
7095 for (
int ip = 0; ip < met->
np; ip++) {
7096 met->
t[ix][iy][ip] -= help->
t[ix][iy][ip];
7097 met->
u[ix][iy][ip] -= help->
u[ix][iy][ip];
7098 met->
v[ix][iy][ip] -= help->
v[ix][iy][ip];
7099 met->
w[ix][iy][ip] -= help->
w[ix][iy][ip];
7112 SELECT_TIMER(
"READ_MET_EXTRAPOLATE",
"METPROC", NVTX_READ);
7113 LOG(2,
"Extrapolate meteo data...");
7116#pragma omp parallel for default(shared) collapse(2)
7117 for (
int ix = 0; ix < met->
nx; ix++)
7118 for (
int iy = 0; iy < met->
ny; iy++) {
7122 for (ip0 = met->
np - 1; ip0 >= 0; ip0--)
7123 if (!isfinite(met->
t[ix][iy][ip0])
7124 || !isfinite(met->
u[ix][iy][ip0])
7125 || !isfinite(met->
v[ix][iy][ip0])
7126 || !isfinite(met->
w[ix][iy][ip0]))
7130 for (
int ip = ip0; ip >= 0; ip--) {
7131 met->
t[ix][iy][ip] = met->
t[ix][iy][ip + 1];
7132 met->
u[ix][iy][ip] = met->
u[ix][iy][ip + 1];
7133 met->
v[ix][iy][ip] = met->
v[ix][iy][ip + 1];
7134 met->
w[ix][iy][ip] = met->
w[ix][iy][ip + 1];
7135 met->
h2o[ix][iy][ip] = met->
h2o[ix][iy][ip + 1];
7136 met->
o3[ix][iy][ip] = met->
o3[ix][iy][ip + 1];
7137 met->
lwc[ix][iy][ip] = met->
lwc[ix][iy][ip + 1];
7138 met->
rwc[ix][iy][ip] = met->
rwc[ix][iy][ip + 1];
7139 met->
iwc[ix][iy][ip] = met->
iwc[ix][iy][ip + 1];
7140 met->
swc[ix][iy][ip] = met->
swc[ix][iy][ip + 1];
7141 met->
cc[ix][iy][ip] = met->
cc[ix][iy][ip + 1];
7160 LOG(2,
"Calculate geopotential heights...");
7167#pragma omp parallel for default(shared)
7168 for (
int ip = 0; ip < met->
np; ip++)
7169 logp[ip] = log(met->
p[ip]);
7172#pragma omp parallel for default(shared) collapse(2)
7173 for (
int ix = 0; ix < met->
nx; ix++)
7174 for (
int iy = 0; iy < met->
ny; iy++) {
7177 const double zs = met->
zs[ix][iy];
7178 const double lnps = log(met->
ps[ix][iy]);
7182 const double ts =
LIN(met->
p[ip0], met->
t[ix][iy][ip0], met->
p[ip0 + 1],
7183 met->
t[ix][iy][ip0 + 1], met->
ps[ix][iy]);
7185 LIN(met->
p[ip0], met->
h2o[ix][iy][ip0], met->
p[ip0 + 1],
7186 met->
h2o[ix][iy][ip0 + 1], met->
ps[ix][iy]);
7189 met->
z[ix][iy][ip0 + 1]
7191 ZDIFF(lnps, ts, h2os, logp[ip0 + 1],
7192 met->
t[ix][iy][ip0 + 1], met->
h2o[ix][iy][ip0 + 1]));
7193 for (
int ip = ip0 + 2; ip < met->
np; ip++)
7195 = (
float) (met->
z[ix][iy][ip - 1] +
7196 ZDIFF(logp[ip - 1], met->
t[ix][iy][ip - 1],
7197 met->
h2o[ix][iy][ip - 1], logp[ip],
7198 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
7203 ZDIFF(lnps, ts, h2os, logp[ip0],
7204 met->
t[ix][iy][ip0], met->
h2o[ix][iy][ip0]));
7205 for (
int ip = ip0 - 1; ip >= 0; ip--)
7207 = (
float) (met->
z[ix][iy][ip + 1] +
7208 ZDIFF(logp[ip + 1], met->
t[ix][iy][ip + 1],
7209 met->
h2o[ix][iy][ip + 1], logp[ip],
7210 met->
t[ix][iy][ip], met->
h2o[ix][iy][ip]));
7214 if (dx == 0 || dy == 0)
7218 if (dx < 0 || dy < 0) {
7219 if (fabs(met->
lon[1] - met->
lon[0]) < 0.5) {
7229 float ws[dx + 1][dy + 1];
7230#pragma omp parallel for default(shared) collapse(2)
7231 for (
int ix = 0; ix <= dx; ix++)
7232 for (
int iy = 0; iy < dy; iy++)
7233 ws[ix][iy] = (1.0f - (
float) ix / (float) dx)
7234 * (1.0f - (float) iy / (
float) dy);
7237#pragma omp parallel for default(shared) collapse(3)
7238 for (
int ix = 0; ix < met->
nx; ix++)
7239 for (
int iy = 0; iy < met->
ny; iy++)
7240 for (
int ip = 0; ip < met->
np; ip++)
7241 help[
ARRAY_3D(ip, ix, met->
nx, iy, met->
ny)] = met->
z[ix][iy][ip];
7244#pragma omp parallel for default(shared) collapse(3)
7245 for (
int ip = 0; ip < met->
np; ip++)
7246 for (
int ix = 0; ix < met->
nx; ix++)
7247 for (
int iy = 0; iy < met->
ny; iy++) {
7248 float res = 0, wsum = 0;
7249 int iy0 =
MAX(iy - dy + 1, 0);
7250 int iy1 =
MIN(iy + dy - 1, met->
ny - 1);
7251 for (
int ix2 = ix - dx + 1; ix2 <= ix + dx - 1; ++ix2) {
7255 else if (ix3 >= met->
nx)
7257 for (
int iy2 = iy0; iy2 <= iy1; ++iy2)
7258 if (isfinite(help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)])) {
7259 float w = ws[abs(ix - ix2)][abs(iy - iy2)];
7260 res += w * help[
ARRAY_3D(ip, ix3, met->
nx, iy2, met->
ny)];
7265 met->
z[ix][iy][ip] = res / wsum;
7267 met->
z[ix][iy][ip] = NAN;
7277 const char *filename,
7282 char levname[
LEN], tstr[10];
7284 double rtime = 0, r, r2;
7286 int varid, year2, mon2, day2, hour2, min2, sec2,
7287 year, mon, day, hour, min, sec;
7292 SELECT_TIMER(
"READ_MET_NC_GRID_DD",
"INPUT", NVTX_READ);
7293 LOG(2,
"Read meteo grid information...");
7302 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
7303 if (nc_inq_varid(ncid,
"time", &varid) == NC_NOERR) {
7304 NC(nc_get_var_double(ncid, varid, &rtime));
7305 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
7306 WARN(
"Time information in meteo file does not match filename!");
7308 WARN(
"Time information in meteo file is missing!");
7319 sprintf(tstr,
"19%.2s", &filename[strlen(filename) - 11]);
7321 sprintf(tstr,
"20%.2s", &filename[strlen(filename) - 11]);
7323 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 9]);
7325 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 7]);
7327 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 5]);
7333 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
7334 || day < 1 || day > 31 || hour < 0 || hour > 23)
7335 ERRMSG(
"Cannot read time from filename!");
7336 jsec2time(met->
time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
7337 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
7338 met->
time, year2, mon2, day2, hour2, min2);
7342 LOG(2,
"Number of longitudes: %d", met->
nx_glob);
7346 LOG(2,
"Number of latitudes: %d", met->
ny_glob);
7351 sprintf(levname,
"lev");
7352 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR)
7353 sprintf(levname,
"plev");
7354 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR)
7355 sprintf(levname,
"hybrid");
7359 sprintf(levname,
"lev_2");
7360 if (nc_inq_dimid(ncid, levname, &dimid2) != NC_NOERR) {
7361 sprintf(levname,
"plev");
7362 NC(nc_inq_dimid(ncid, levname, &dimid2));
7364 NC(nc_inq_dimlen(ncid, dimid2, &np));
7369 LOG(2,
"Number of levels: %d", met->
np);
7371 ERRMSG(
"Number of levels out of range!");
7375 LOG(2,
"Longitudes: %g, %g ... %g deg",
7378 LOG(2,
"Latitudes: %g, %g ... %g deg",
7382 for (
int ix = 2; ix < met->
nx; ix++)
7384 (fabs(met->
lon[ix] - met->
lon[ix - 1]) -
7385 fabs(met->
lon[1] - met->
lon[0])) > 0.001)
7386 ERRMSG(
"No regular grid spacing in longitudes!");
7387 for (
int iy = 2; iy < met->
ny; iy++)
7389 (fabs(met->
lat[iy] - met->
lat[iy - 1]) -
7390 fabs(met->
lat[1] - met->
lat[0])) > 0.001) {
7391 WARN(
"No regular grid spacing in latitudes!");
7397 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
7398 MPI_Comm_size(MPI_COMM_WORLD, &size);
7420 met->
nx = met->
nx + gap;
7421 WARN(
"Extended subdomains at the right to fit to full domain.");
7427 met->
ny = met->
ny + gap;
7428 WARN(
"Extended subdomains at the bottom to fit to full domain.");
7439 if (!left && !right) {
7456 if (!top && !bottom) {
7474 double lon_shift = 0;
7475 if (left || right) {
7493 lon_shift = (left ? -360 : 360);
7498 double lon_range = met->
lon[met->
nx_glob - 1] - met->
lon[0];
7499 double lat_range = met->
lat[met->
ny_glob - 1] - met->
lat[0];
7504 met->
lat[iy] = met->
lat[iy_];
7508 double help_lon[
EX];
7524 for (
int ix = 0; ix < (int) met->
nx; ix++) {
7525 met->
lon[ix] = help_lon[ix];
7538 LOG(2,
" %d Subdomain longitudes: %g, %g ... %g deg", rank,
7540 LOG(2,
" %d Subdomain latitudes: %g, %g ... %g deg", rank,
7543 LOG(2,
"Define subdomain properties.");
7544 LOG(2,
"MPI information: Rank %d, Size %d", rank, size);
7545 LOG(2,
"Edge position: l=%d,r=%d,t=%d, b=%d", (
int) left, (
int) right,
7546 (
int) top, (
int) bottom);
7547 LOG(2,
"Sizes for limits: EX %d EY %d EP %d",
EX,
EY,
EP);
7548 LOG(2,
"Total size for subdomain meteo data: nx %d ny %d np %d", met->
nx,
7550 LOG(2,
"Hyperslab sizes for boundary halos: nx %d ny %d np %d",
7553 LOG(2,
"Hyperslab sizes for subdomain and inner halos: nx %d ny %d np %d",
7566 for (
int ip = 0; ip < met->
np; ip++)
7568 LOG(2,
"Altitude levels: %g, %g ... %g km",
7569 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
7570 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
7571 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
7575 if (strcasecmp(levname,
"hybrid") == 0)
7590 LOG(2,
"Read surface data...");
7594 (ncid,
"lnsp",
"LNSP", NULL, NULL, NULL, NULL, ctl, met, met->
ps, 1.0f,
7596 for (
int ix = 0; ix < met->
nx; ix++)
7597 for (
int iy = 0; iy < met->
ny; iy++)
7598 met->
ps[ix][iy] = (
float) (exp(met->
ps[ix][iy]) / 100.);
7601 (ncid,
"ps",
"PS",
"sp",
"SP", NULL, NULL, ctl, met, met->
ps, 0.01f,
7603 WARN(
"Cannot not read surface pressure data (use lowest level)!");
7604 for (
int ix = 0; ix < met->
nx; ix++)
7605 for (
int iy = 0; iy < met->
ny; iy++)
7607 = (ctl->
met_np > 0 ? (
float) ctl->
met_p[0] : (
float) met->
p[0]);
7615 (ncid,
"z",
"Z", NULL, NULL, NULL, NULL, ctl, met, met->
zs,
7616 (
float) (1. / (1000. *
G0)), 1))
7618 (ncid,
"zm",
"ZM", NULL, NULL, NULL, NULL, ctl, met, met->
zs,
7619 (
float) (1. / 1000.), 1))
7620 WARN(
"Cannot read surface geopotential height!");
7631 memcpy(help, met->
pl,
sizeof(met->
pl));
7633 (ncid,
"gph",
"GPH", NULL, NULL, ctl, met, met->
pl,
7634 (
float) (1e-3 /
G0)))
7635 ERRMSG(
"Cannot read geopotential height!");
7636 for (
int ix = 0; ix < met->
nx; ix++)
7637 for (
int iy = 0; iy < met->
ny; iy++)
7638 met->
zs[ix][iy] = met->
pl[ix][iy][0];
7639 memcpy(met->
pl, help,
sizeof(met->
pl));
7645 (ncid,
"t2m",
"T2M",
"2t",
"2T",
"t2",
"T2", ctl, met, met->
ts, 1.0, 1))
7646 WARN(
"Cannot read surface temperature!");
7650 (ncid,
"u10m",
"U10M",
"10u",
"10U",
"u10",
"U10", ctl, met, met->
us,
7652 WARN(
"Cannot read surface zonal wind!");
7656 (ncid,
"v10m",
"V10M",
"10v",
"10V",
"v10",
"V10", ctl, met, met->
vs,
7658 WARN(
"Cannot read surface meridional wind!");
7662 (ncid,
"iews",
"IEWS", NULL, NULL, NULL, NULL, ctl, met, met->
ess, 1.0,
7664 WARN(
"Cannot read eastward turbulent surface stress!");
7668 (ncid,
"inss",
"INSS", NULL, NULL, NULL, NULL, ctl, met, met->
nss, 1.0,
7670 WARN(
"Cannot read nothward turbulent surface stress!");
7674 (ncid,
"ishf",
"ISHF", NULL, NULL, NULL, NULL, ctl, met, met->
shf, 1.0,
7676 WARN(
"Cannot read surface sensible heat flux!");
7680 (ncid,
"lsm",
"LSM", NULL, NULL, NULL, NULL, ctl, met, met->
lsm, 1.0,
7682 WARN(
"Cannot read land-sea mask!");
7686 (ncid,
"sstk",
"SSTK",
"sst",
"SST", NULL, NULL, ctl, met, met->
sst,
7688 WARN(
"Cannot read sea surface temperature!");
7693 (ncid,
"blp",
"BLP", NULL, NULL, NULL, NULL, ctl, met, met->
pbl,
7695 WARN(
"Cannot read planetary boundary layer pressure!");
7698 (ncid,
"blh",
"BLH", NULL, NULL, NULL, NULL, ctl, met, met->
pbl,
7700 WARN(
"Cannot read planetary boundary layer height!");
7705 (ncid,
"cape",
"CAPE", NULL, NULL, NULL, NULL, ctl, met, met->
cape,
7707 WARN(
"Cannot read CAPE!");
7712 (ncid,
"cin",
"CIN", NULL, NULL, NULL, NULL, ctl, met, met->
cin,
7714 WARN(
"Cannot read convective inhibition!");
7727 SELECT_TIMER(
"READ_MET_NC_LEVELS_DD",
"INPUT", NVTX_READ);
7728 LOG(2,
"Read level data...");
7732 (ncid,
"t",
"T",
"temp",
"TEMP", ctl, met, met->
t, 1.0))
7733 ERRMSG(
"Cannot read temperature!");
7737 ERRMSG(
"Cannot read zonal wind!");
7739 ERRMSG(
"Cannot read meridional wind!");
7741 (ncid,
"w",
"W",
"omega",
"OMEGA", ctl, met, met->
w, 0.01f))
7742 WARN(
"Cannot read vertical velocity!");
7747 (ncid,
"q",
"Q",
"sh",
"SH", ctl, met, met->
h2o, (
float) (
MA /
MH2O)))
7748 WARN(
"Cannot read specific humidity!");
7751 (ncid,
"rh",
"RH", NULL, NULL, ctl, met, met->
h2o, 0.01f))
7752 WARN(
"Cannot read relative humidity!");
7753#pragma omp parallel for default(shared) collapse(2)
7754 for (
int ix = 0; ix < met->
nx; ix++)
7755 for (
int iy = 0; iy < met->
ny; iy++)
7756 for (
int ip = 0; ip < met->
np; ip++) {
7757 double pw = met->
h2o[ix][iy][ip] *
PSAT(met->
t[ix][iy][ip]);
7758 met->
h2o[ix][iy][ip] =
7759 (float) (pw / (met->
p[ip] - (1.0 -
EPS) * pw));
7765 (ncid,
"o3",
"O3", NULL, NULL, ctl, met, met->
o3, (
float) (
MA /
MO3)))
7766 WARN(
"Cannot read ozone data!");
7770 (ncid,
"clwc",
"CLWC", NULL, NULL, ctl, met, met->
lwc, 1.0))
7771 WARN(
"Cannot read cloud liquid water content!");
7773 (ncid,
"crwc",
"CRWC", NULL, NULL, ctl, met, met->
rwc, 1.0))
7774 WARN(
"Cannot read cloud rain water content!");
7776 (ncid,
"ciwc",
"CIWC", NULL, NULL, ctl, met, met->
iwc, 1.0))
7777 WARN(
"Cannot read cloud ice water content!");
7779 (ncid,
"cswc",
"CSWC", NULL, NULL, ctl, met, met->
swc, 1.0))
7780 WARN(
"Cannot read cloud snow water content!");
7782 (ncid,
"cc",
"CC", NULL, NULL, ctl, met, met->
cc, 1.0))
7783 WARN(
"Cannot read cloud cover!");
7787 (ncid,
"ZETA",
"zeta", NULL, NULL, ctl, met, met->
zetal, 1.0))
7788 WARN(
"Cannot read ZETA!");
7790 (ncid,
"ZETA_DOT_TOT",
"ZETA_DOT_clr",
"zeta_dot_clr",
7791 NULL, ctl, met, met->
zeta_dotl, 0.00001157407f))
7792 WARN(
"Cannot read ZETA_DOT!");
7796#pragma omp parallel for default(shared)
7797 for (
int ix = 0; ix < met->
nx; ix++)
7798 for (
int iy = 0; iy < met->
ny; iy++)
7799 for (
int ip = 0; ip < met->
np; ip++) {
7800 met->
ul[ix][iy][ip] = met->
u[ix][iy][ip];
7801 met->
vl[ix][iy][ip] = met->
v[ix][iy][ip];
7802 met->
wl[ix][iy][ip] = met->
w[ix][iy][ip];
7815 (ncid,
"pl",
"PL",
"pressure",
"PRESSURE", ctl, met, met->
pl,
7818 (ncid,
"press",
"PRESS", NULL, NULL, ctl, met, met->
pl, 1.0))
7819 ERRMSG(
"Cannot read pressure on model levels!");
7827 double hyam[
EP], hybm[
EP];
7841 ERRMSG(
"Mismatch in number of model levels!");
7844 for (
int ip = 0; ip < met->
np; ip++) {
7851 for (
int ix = 0; ix < met->
nx; ix++)
7852 for (
int iy = 0; iy < met->
ny; iy++)
7853 for (
int ip = 0; ip < met->
np; ip++)
7854 met->
pl[ix][iy][ip] =
7855 (
float) (hyam[ip] / 100. + hybm[ip] * met->
ps[ix][iy]);
7863 double hyam[
EP], hybm[
EP];
7866 for (
int ip = 0; ip < met->
np + 1; ip++) {
7873 ERRMSG(
"Mismatch in number of model levels!");
7876#pragma omp parallel for default(shared) collapse(2)
7877 for (
int ix = 0; ix < met->
nx; ix++)
7878 for (
int iy = 0; iy < met->
ny; iy++)
7879 for (
int ip = 0; ip < met->
np; ip++) {
7880 double p0 = hyam[ip] / 100. + hybm[ip] * met->
ps[ix][iy];
7881 double p1 = hyam[ip + 1] / 100. + hybm[ip + 1] * met->
ps[ix][iy];
7882 met->
pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
7887 for (
int ix = 0; ix < met->
nx; ix++)
7888 for (
int iy = 0; iy < met->
ny; iy++)
7889 for (
int ip = 1; ip < met->
np; ip++)
7890 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
7891 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
7892 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
7893 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip]))
7894 ERRMSG(
"Pressure profiles are not monotonic!");
7915 for (
int ip = 0; ip < met->
np; ip++) {
7916 met->
p[ip] = ctl->
met_p[ip];
7921 for (
int ip = 1; ip < met->
np; ip++)
7922 if (met->
p[ip - 1] < met->
p[ip])
7923 ERRMSG(
"Pressure levels must be descending!");
7932 const char *filename,
7939 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
7940 WARN(
"Cannot open file!");
7967 const char *varname,
7968 const char *varname2,
7969 const char *varname3,
7970 const char *varname4,
7971 const char *varname5,
7972 const char *varname6,
7984 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
7985 sprintf(varsel,
"%s", varname);
7986 else if (varname2 != NULL
7987 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
7988 sprintf(varsel,
"%s", varname2);
7989 else if (varname3 != NULL
7990 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
7991 sprintf(varsel,
"%s", varname3);
7992 else if (varname4 != NULL
7993 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
7994 sprintf(varsel,
"%s", varname4);
7995 else if (varname5 != NULL
7996 && nc_inq_varid(ncid, varname5, &varid) == NC_NOERR)
7997 sprintf(varsel,
"%s", varname5);
7998 else if (varname6 != NULL
7999 && nc_inq_varid(ncid, varname6, &varid) == NC_NOERR)
8000 sprintf(varsel,
"%s", varname6);
8007 float fillval, missval;
8008 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8010 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8014 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
8015 varsel, fillval, missval);
8019 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
8020 MPI_Comm_size(MPI_COMM_WORLD, &size);
8024 size_t help_subdomain_start[3];
8025 size_t help_subdomain_count[3];
8027 help_subdomain_start[0] = 0;
8031 help_subdomain_count[0] = 1;
8040 NC(nc_get_vara_float
8041 (ncid, varid, help_subdomain_start, help_subdomain_count, help));
8044 size_t help_halo_bnd_start[3];
8045 size_t help_halo_bnd_count[3];
8047 help_halo_bnd_start[0] = 0;
8051 help_halo_bnd_count[0] = 1;
8056 ALLOC(help_halo,
float,
8057 help_halo_bnd_count[1] * help_halo_bnd_count[2]);
8058 NC(nc_get_vara_float
8059 (ncid, varid, help_halo_bnd_start, help_halo_bnd_count, help_halo));
8065#pragma omp parallel for default(shared) num_threads(12)
8066 for (
int ix = 0; ix < (int) help_subdomain_count[2]; ix++)
8067 for (
int iy = 0; iy < (int) help_subdomain_count[1]; iy++) {
8070 float aux = help[
ARRAY_2D(iy, ix, (
int) help_subdomain_count[2])];
8071 if ((fillval == 0 || aux != fillval)
8072 && (missval == 0 || aux != missval)
8073 && fabsf(aux) < 1e14f) {
8080#pragma omp parallel for default(shared) num_threads(12)
8081 for (
int ix = 0; ix < (int) help_halo_bnd_count[2]; ix++)
8082 for (
int iy = 0; iy < (int) help_halo_bnd_count[1]; iy++) {
8085 float aux = help_halo[
ARRAY_2D(iy, ix, (
int) help_halo_bnd_count[2])];
8086 if ((fillval == 0 || aux != fillval)
8087 && (missval == 0 || aux != missval)
8088 && fabsf(aux) < 1e14f)
8098#pragma omp parallel for default(shared) num_threads(12)
8099 for (
int iy = 0; iy < met->
ny; iy++)
8100 for (
int ix = 0; ix < met->
nx; ix++) {
8104 if ((fillval == 0 || aux != fillval)
8105 && (missval == 0 || aux != missval)
8106 && fabsf(aux) < 1e14f)
8107 dest[ix][iy] += scl * aux;
8129 const char *varname,
8130 const char *varname2,
8131 const char *varname3,
8132 const char *varname4,
8143 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
8144 sprintf(varsel,
"%s", varname);
8145 else if (varname2 != NULL
8146 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
8147 sprintf(varsel,
"%s", varname2);
8148 else if (varname3 != NULL
8149 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
8150 sprintf(varsel,
"%s", varname3);
8151 else if (varname4 != NULL
8152 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
8153 sprintf(varsel,
"%s", varname4);
8158 float fillval, missval;
8159 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8161 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8165 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
8166 varsel, fillval, missval);
8170 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
8171 MPI_Comm_size(MPI_COMM_WORLD, &size);
8180 NC(nc_get_vara_float
8185 ALLOC(help_halo,
float,
8188 nc_get_vara_float(ncid,
8190 met->halo_bnd_start,
8191 met->halo_bnd_count,
8195 if (ctl->met_convention == 0) {
8197#pragma omp parallel for default(shared) num_threads(12)
8200 for (
int ip = 0; ip < met->
np; ip++) {
8203 if ((fillval == 0 || aux != fillval)
8204 && (missval == 0 || aux != missval)
8205 && fabsf(aux) < 1e14f)
8211#pragma omp parallel for default(shared) num_threads(12)
8214 for (
int ip = 0; ip < met->
np; ip++) {
8218 if ((fillval == 0 || aux != fillval)
8219 && (missval == 0 || aux != missval)
8220 && fabsf(aux) < 1e14f)
8229#pragma omp parallel for default(shared) num_threads(12)
8230 for (
int ip = 0; ip < met->
np; ip++)
8233 float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
8234 if ((fillval == 0 || aux != fillval)
8235 && (missval == 0 || aux != missval)
8236 && fabsf(aux) < 1e14f)
8242#pragma omp parallel for default(shared) num_threads(12)
8243 for (
int ip = 0; ip < met->
np; ip++)
8246 float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
8247 if ((fillval == 0 || aux != fillval)
8248 && (missval == 0 || aux != missval)
8249 && fabsf(aux) < 1e14f)
8270 const char *filename,
8275 size_t filename_len = strlen(filename) + 1;
8276 char sf_filename[filename_len];
8277 char ml_filename[filename_len];
8278 strcpy(sf_filename, filename);
8279 strcpy(ml_filename, filename);
8284 FILE *ml_file = fopen(ml_filename,
"rb");
8285 FILE *sf_file = fopen(sf_filename,
"rb");
8286 if (ml_file == NULL || sf_file == NULL) {
8287 if (ml_file != NULL) {
8289 WARN(
"Cannot open file: %s", sf_filename);
8291 if (sf_file != NULL) {
8293 WARN(
"Cannot open file: %s", ml_filename);
8299 int ml_num_messages = 0, err = 0;
8300 ECC(codes_count_in_file(0, ml_file, &ml_num_messages));
8301 codes_handle **ml_handles =
8302 (codes_handle **) malloc(
sizeof(codes_handle *) *
8303 (size_t) ml_num_messages);
8304 for (
int i = 0; i < ml_num_messages; i++) {
8305 codes_handle *h = NULL;
8306 if ((h = codes_grib_handle_new_from_file(0, ml_file, &err)) != NULL)
8311 int sf_num_messages = 0;
8312 ECC(codes_count_in_file(0, sf_file, &sf_num_messages));
8313 codes_handle **sf_handles =
8314 (codes_handle **) malloc(
sizeof(codes_handle *) *
8315 (size_t) sf_num_messages);
8316 for (
int i = 0; i < sf_num_messages; i++) {
8317 codes_handle *h = NULL;
8318 if ((h = codes_grib_handle_new_from_file(0, sf_file, &err)) != NULL)
8327 read_met_grib_grid(ml_handles, ml_num_messages, met);
8330 read_met_grib_surface(sf_handles, sf_num_messages, ctl, met);
8331 for (
int i = 0; i < sf_num_messages; i++)
8332 codes_handle_delete(sf_handles[i]);
8337 ECC(codes_get_size(ml_handles[0],
"pv", &value_count));
8338 double *values = (
double *) malloc(value_count *
sizeof(
double));
8339 ECC(codes_get_double_array(ml_handles[0],
"pv", values, &value_count));
8340 double a_vals[138], b_vals[138];
8341 for (
int i = 0; i <= 137; i++) {
8342 a_vals[i] = values[i];
8343 b_vals[i] = values[i + 137];
8345 for (
int nx = 0; nx < met->
nx; nx++)
8346 for (
int ny = 0; ny < met->
ny; ny++)
8347 for (
int level = 0; level <= met->
npl; level++) {
8349 (float) ((a_vals[level] * 0.01f + met->
ps[nx][ny] * b_vals[level]));
8351 (float) ((a_vals[level + 1] * 0.01f +
8352 met->
ps[nx][ny] * b_vals[level + 1]));
8353 met->
pl[nx][ny][level] = (p1 + p2) * 0.5f;
8357 read_met_grib_levels(ml_handles, ml_num_messages, ctl, met);
8358 for (
int i = 0; i < ml_num_messages; i++)
8359 codes_handle_delete(ml_handles[i]);
8370void read_met_grib_grid(
8371 codes_handle **handles,
8376 SELECT_TIMER(
"READ_MET_GRIB_GRID",
"INPUT", NVTX_READ);
8377 LOG(2,
"Read meteo grid information...");
8382 char year[20], month[20], day[20], hour[20];
8383 size_t s =
sizeof(datestr);
8385 ECC(codes_get_string(handles[0],
"dataDate", datestr, &s));
8386 ECC(codes_get_string(handles[0],
"dataTime", timestr, &s));
8387 strncpy(year, datestr, 4);
8389 strncpy(month, datestr + 4, 2);
8391 strncpy(day, datestr + 6, 2);
8393 strncpy(hour, timestr, 2);
8395 time2jsec(atoi(year), atoi(month), atoi(day), atoi(hour), 0, 0, 0,
8399 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
8400 met->
time, atoi(year), atoi(month), atoi(day), atoi(hour), 0);
8403 long count_lat = 0, count_lon = 0;
8404 ECC(codes_get_long(handles[0],
"Nj", &count_lat));
8405 ECC(codes_get_long(handles[0],
"Ni", &count_lon));
8406 met->
ny = (int) count_lat;
8407 met->
nx = (int) count_lon;
8410 LOG(2,
"Number of longitudes: %d", met->
nx);
8411 if (met->
nx < 2 || met->
nx >
EX)
8412 ERRMSG(
"Number of longitudes out of range!");
8413 LOG(2,
"Number of latitudes: %d", met->
ny);
8414 if (met->
ny < 2 || met->
ny >
EY)
8415 ERRMSG(
"Number of latitudes out of range!");
8417 double first_lon, last_lon, first_lat, last_lat, inc_lon, inc_lat;
8418 ECC(codes_get_double
8419 (handles[0],
"longitudeOfFirstGridPointInDegrees", &first_lon));
8420 ECC(codes_get_double
8421 (handles[0],
"latitudeOfFirstGridPointInDegrees", &first_lat));
8422 ECC(codes_get_double
8423 (handles[0],
"longitudeOfLastGridPointInDegrees", &last_lon));
8424 ECC(codes_get_double
8425 (handles[0],
"latitudeOfLastGridPointInDegrees", &last_lat));
8426 ECC(codes_get_double(handles[0],
"iDirectionIncrementInDegrees", &inc_lon));
8427 ECC(codes_get_double(handles[0],
"jDirectionIncrementInDegrees", &inc_lat));
8429 long jscanpos, iscanneg;
8430 ECC(codes_get_long(handles[0],
"iScansNegatively", &iscanneg));
8431 ECC(codes_get_long(handles[0],
"jScansPositively", &jscanpos));
8436 for (
double i = first_lon; i <= last_lon + 1e-6; i += inc_lon) {
8437 met->
lon[counter] = i;
8440 for (
double i = first_lon; i > last_lon - 1e-6; i -= inc_lon) {
8441 met->
lon[counter] = i;
8447 for (
double i = first_lat; i > last_lat - 1e-6; i -= inc_lat) {
8448 met->
lat[counter] = i;
8451 for (
double i = first_lat; i <= last_lat + 1e-6; i += inc_lat) {
8452 met->
lat[counter] = i;
8457 LOG(2,
"Longitudes: %g, %g ... %g deg",
8459 LOG(2,
"Latitudes: %g, %g ... %g deg",
8464 for (
int i = 0; i < count_handles; i++) {
8466 ECC(codes_get_long(handles[i],
"level", &level));
8467 if (level > max_level)
8468 max_level = (int) level;
8470 met->
npl = max_level;
8473 LOG(2,
"Number of levels: %d", met->
npl);
8475 ERRMSG(
"Number of levels out of range!");
8482void read_met_grib_levels(
8483 codes_handle **handles,
8484 const int num_messages,
8489 SELECT_TIMER(
"READ_MET_GRIB_LEVELS",
"INPUT", NVTX_READ);
8490 LOG(2,
"Read level data...");
8493 int t_flag = 0, u_flag = 0, v_flag = 0, w_flag = 0, o3_flag = 0, h2o_flag =
8494 0, lwc_flag = 0, rwc_flag = 0, iwc_flag = 0, swc_flag = 0, cc_flag = 0;
8497 for (
int i = 0; i < num_messages; i++) {
8499 size_t max_size = 50;
8500 char short_name[max_size];
8506 ECC(codes_get_long(handles[i],
"level", ¤t_level));
8510 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
8511 ECC(codes_get_size(handles[i],
"values", &value_count));
8512 ALLOC(values,
double,
8514 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
8522 ECC_READ_3D(
"w", current_level, met->
w, 0.01f, w_flag);
8540 if (t_flag != met->
npl)
8541 ERRMSG(
"Cannot read temperature!");
8542 if (u_flag != met->
npl)
8543 ERRMSG(
"Cannot read zonal wind!");
8544 if (v_flag != met->
npl)
8545 ERRMSG(
"Cannot read meridional wind!");
8546 if (w_flag != met->
npl)
8547 WARN(
"Cannot read vertical velocity!");
8548 if (h2o_flag != met->
npl)
8549 WARN(
"Cannot read specific humidity!");
8550 if (o3_flag != met->
npl)
8551 WARN(
"Cannot read ozone data!");
8552 if (lwc_flag != met->
npl)
8553 WARN(
"Cannot read cloud liquid water content!");
8554 if (rwc_flag != met->
npl)
8555 WARN(
"Cannot read cloud rain water content!");
8556 if (iwc_flag != met->
npl)
8557 WARN(
"Cannot read cloud ice water content!");
8558 if (swc_flag != met->
npl)
8559 WARN(
"Cannot read cloud snow water content!");
8560 if (cc_flag != met->
npl)
8561 WARN(
"Cannot read cloud cover!");
8564 for (
int ix = 0; ix < met->
nx; ix++)
8565 for (
int iy = 0; iy < met->
ny; iy++)
8566 for (
int ip = 1; ip < met->
np; ip++)
8567 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
8568 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
8569 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
8570 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip])) {
8571 LOG(1,
"%f %f %f %f", met->
pl[ix][iy][0], met->
pl[ix][iy][1],
8572 met->
pl[ix][iy][ip - 1], met->
pl[ix][iy][ip]);
8573 ERRMSG(
"Pressure profiles are not monotonic!");
8594 for (
int ip = 0; ip < met->
np; ip++)
8595 met->
p[ip] = ctl->
met_p[ip];
8599 for (
int ip = 1; ip < met->
np; ip++)
8600 if (met->
p[ip - 1] < met->
p[ip])
8601 ERRMSG(
"Pressure levels must be descending!");
8608void read_met_grib_surface(
8609 codes_handle **handles,
8610 const int num_messages,
8615 SELECT_TIMER(
"READ_MET_GRIB_SURFACE",
"INPUT", NVTX_READ);
8616 LOG(2,
"Read surface data...");
8619 int sp_flag = 0, z_flag = 0, t_flag = 0, u_flag = 0, v_flag = 0, lsm_flag =
8620 0, sst_flag = 0, cape_flag = 0, cin_flag = 0, pbl_flag = 0;
8623 for (
int i = 0; i < num_messages; i++) {
8625 size_t max_size = 50;
8626 char short_name[max_size];
8630 ECC(codes_get_string(handles[i],
"shortName", short_name, &max_size));
8631 ECC(codes_get_size(handles[i],
"values", &value_count));
8632 double *values = (
double *) malloc(value_count *
sizeof(
double));
8633 ECC(codes_get_double_array(handles[i],
"values", values, &value_count));
8674 WARN(
"Cannot read surface pressure data!");
8676 WARN(
"Cannot read surface geopotential height!");
8678 WARN(
"Cannot read surface temperature!");
8680 WARN(
"Cannot read surface zonal wind!");
8682 WARN(
"Cannot read surface meridional wind!");
8684 WARN(
"Cannot read land-sea mask!");
8686 WARN(
"Cannot read sea surface temperature!");
8689 WARN(
"Cannot read CAPE!");
8691 WARN(
"Cannot read convective inhibition!");
8693 if (ctl->
met_pbl == 0 && pbl_flag == 0)
8694 WARN(
"Cannot read planetary boundary layer!");
8704 const char *varname) {
8706 double aux[
EP], p[
EP];
8710 LOG(2,
"Interpolate meteo data to pressure levels: %s", varname);
8713#pragma omp parallel for default(shared) private(aux,p) collapse(2)
8714 for (
int ix = 0; ix < met->
nx; ix++)
8715 for (
int iy = 0; iy < met->
ny; iy++) {
8718 for (
int ip = 0; ip < met->
np; ip++)
8719 p[ip] = met->
pl[ix][iy][ip];
8722 for (
int ip = 0; ip < ctl->
met_np; ip++) {
8723 double pt = ctl->
met_p[ip];
8724 if ((pt > p[0] && p[0] > p[1]) || (pt < p[0] && p[0] < p[1]))
8726 else if ((pt > p[met->
np - 1] && p[1] > p[0])
8727 || (pt < p[met->
np - 1] && p[1] < p[0]))
8728 pt = p[met->
np - 1];
8730 aux[ip] =
LIN(p[ip2], var[ix][iy][ip2],
8731 p[ip2 + 1], var[ix][iy][ip2 + 1], pt);
8735 for (
int ip = 0; ip < ctl->
met_np; ip++)
8736 var[ix][iy][ip] = (
float) aux[ip];
8751 SELECT_TIMER(
"READ_MET_MONOTONIZE",
"METPROC", NVTX_READ);
8752 LOG(2,
"Make zeta profiles monotone...");
8755#pragma omp parallel for default(shared) collapse(2)
8756 for (
int i = 0; i < met->
nx; i++)
8757 for (
int j = 0; j < met->
ny; j++) {
8760 while (k < met->npl) {
8761 if ((met->
zetal[i][j][k - 1] >= met->
zetal[i][j][k])) {
8767 while ((met->
zetal[i][j][k - 1] >=
8768 met->
zetal[i][j][k + l]) & (k + l < met->npl));
8773 (float) (met->
zetal[i][j][k + l] - met->
zetal[i][j][k - 1])
8776 for (
int m = k; m < k + l; m++) {
8777 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
8778 met->
zetal[i][j][m] = s * d + met->
zetal[i][j][k - 1];
8790#pragma omp parallel for default(shared) collapse(2)
8791 for (
int i = 0; i < met->
nx; i++)
8792 for (
int j = 0; j < met->
ny; j++) {
8795 while (k < met->npl) {
8796 if ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k])) {
8803 while ((met->
pl[i][j][k - 1] <= met->
pl[i][j][k + l]) & (k + l <
8808 float s = (float) (met->
pl[i][j][k + l] - met->
pl[i][j][k - 1])
8811 for (
int m = k; m < k + l; m++) {
8812 float d = (float) (met->
hybrid[m] - met->
hybrid[k - 1]);
8813 met->
pl[i][j][m] = s * d + met->
pl[i][j][k - 1];
8828 const char *filename,
8835 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR) {
8836 WARN(
"Cannot open file!");
8860 const char *varname,
8861 const char *varname2,
8862 const char *varname3,
8863 const char *varname4,
8864 const char *varname5,
8865 const char *varname6,
8874 float offset, scalfac;
8879 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
8880 sprintf(varsel,
"%s", varname);
8881 else if (varname2 != NULL
8882 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
8883 sprintf(varsel,
"%s", varname2);
8884 else if (varname3 != NULL
8885 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
8886 sprintf(varsel,
"%s", varname3);
8887 else if (varname4 != NULL
8888 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
8889 sprintf(varsel,
"%s", varname4);
8890 else if (varname5 != NULL
8891 && nc_inq_varid(ncid, varname5, &varid) == NC_NOERR)
8892 sprintf(varsel,
"%s", varname5);
8893 else if (varname6 != NULL
8894 && nc_inq_varid(ncid, varname6, &varid) == NC_NOERR)
8895 sprintf(varsel,
"%s", varname6);
8901 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
8902 && nc_get_att_float(ncid, varid,
"scale_factor",
8903 &scalfac) == NC_NOERR) {
8911 short fillval, missval;
8912 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8914 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8918 LOG(2,
"Read 2-D variable: %s"
8919 " (FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
8920 varsel, fillval, missval, scalfac, offset);
8923 NC(nc_get_var_short(ncid, varid, help));
8927 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
8931#pragma omp parallel for default(shared)
8932 for (
int ix = 0; ix < met->
nx; ix++)
8933 for (
int iy = 0; iy < met->
ny; iy++) {
8936 const short aux = help[
ARRAY_2D(iy, ix, met->
nx)];
8937 if ((fillval == 0 || aux != fillval)
8938 && (missval == 0 || aux != missval)
8939 && fabsf(aux * scalfac + offset) < 1e14f)
8940 dest[ix][iy] += scl * (aux * scalfac + offset);
8959 float fillval, missval;
8960 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
8962 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
8966 LOG(2,
"Read 2-D variable: %s (FILL = %g, MISS = %g)",
8967 varsel, fillval, missval);
8970 NC(nc_get_var_float(ncid, varid, help));
8977#pragma omp parallel for default(shared)
8978 for (
int ix = 0; ix < met->
nx; ix++)
8979 for (
int iy = 0; iy < met->
ny; iy++) {
8982 const float aux = help[
ARRAY_2D(iy, ix, met->
nx)];
8983 if ((fillval == 0 || aux != fillval)
8984 && (missval == 0 || aux != missval)
8985 && fabsf(aux) < 1e14f)
8986 dest[ix][iy] += scl * aux;
8996#pragma omp parallel for default(shared)
8997 for (
int iy = 0; iy < met->
ny; iy++)
8998 for (
int ix = 0; ix < met->
nx; ix++) {
9001 const float aux = help[
ARRAY_2D(ix, iy, met->
ny)];
9002 if ((fillval == 0 || aux != fillval)
9003 && (missval == 0 || aux != missval)
9004 && fabsf(aux) < 1e14f)
9005 dest[ix][iy] += scl * aux;
9024 const char *varname,
9025 const char *varname2,
9026 const char *varname3,
9027 const char *varname4,
9035 float offset, scalfac;
9040 if (nc_inq_varid(ncid, varname, &varid) == NC_NOERR)
9041 sprintf(varsel,
"%s", varname);
9042 else if (varname2 != NULL
9043 && nc_inq_varid(ncid, varname2, &varid) == NC_NOERR)
9044 sprintf(varsel,
"%s", varname2);
9045 else if (varname3 != NULL
9046 && nc_inq_varid(ncid, varname3, &varid) == NC_NOERR)
9047 sprintf(varsel,
"%s", varname3);
9048 else if (varname4 != NULL
9049 && nc_inq_varid(ncid, varname4, &varid) == NC_NOERR)
9050 sprintf(varsel,
"%s", varname4);
9056 && nc_get_att_float(ncid, varid,
"add_offset", &offset) == NC_NOERR
9057 && nc_get_att_float(ncid, varid,
"scale_factor",
9058 &scalfac) == NC_NOERR) {
9066 short fillval, missval;
9067 if (nc_get_att_short(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9069 if (nc_get_att_short(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9073 LOG(2,
"Read 3-D variable: %s "
9074 "(FILL = %d, MISS = %d, SCALE = %g, OFFSET = %g)",
9075 varsel, fillval, missval, scalfac, offset);
9078 NC(nc_get_var_short(ncid, varid, help));
9082 ERRMSG(
"Meteo data layout not implemented for packed netCDF files!");
9086#pragma omp parallel for default(shared)
9087 for (
int ix = 0; ix < met->
nx; ix++)
9088 for (
int iy = 0; iy < met->
ny; iy++)
9089 for (
int ip = 0; ip < met->
np; ip++) {
9090 const short aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
9091 if ((fillval == 0 || aux != fillval)
9092 && (missval == 0 || aux != missval)
9093 && fabsf(aux * scalfac + offset) < 1e14f)
9094 dest[ix][iy][ip] = scl * (aux * scalfac + offset);
9096 dest[ix][iy][ip] = NAN;
9113 float fillval, missval;
9114 if (nc_get_att_float(ncid, varid,
"_FillValue", &fillval) != NC_NOERR)
9116 if (nc_get_att_float(ncid, varid,
"missing_value", &missval) != NC_NOERR)
9120 LOG(2,
"Read 3-D variable: %s (FILL = %g, MISS = %g)",
9121 varsel, fillval, missval);
9124 NC(nc_get_var_float(ncid, varid, help));
9131#pragma omp parallel for default(shared)
9132 for (
int ix = 0; ix < met->
nx; ix++)
9133 for (
int iy = 0; iy < met->
ny; iy++)
9134 for (
int ip = 0; ip < met->
np; ip++) {
9135 const float aux = help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)];
9136 if ((fillval == 0 || aux != fillval)
9137 && (missval == 0 || aux != missval)
9138 && fabsf(aux) < 1e14f)
9139 dest[ix][iy][ip] = scl * aux;
9141 dest[ix][iy][ip] = NAN;
9149#pragma omp parallel for default(shared)
9150 for (
int ip = 0; ip < met->
np; ip++)
9151 for (
int iy = 0; iy < met->
ny; iy++)
9152 for (
int ix = 0; ix < met->
nx; ix++) {
9153 const float aux = help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)];
9154 if ((fillval == 0 || aux != fillval)
9155 && (missval == 0 || aux != missval)
9156 && fabsf(aux) < 1e14f)
9157 dest[ix][iy][ip] = scl * aux;
9159 dest[ix][iy][ip] = NAN;
9175 const char *filename,
9180 char levname[
LEN], tstr[10];
9182 double rtime = 0, r, r2;
9184 int varid, ndims, dimids[NC_MAX_DIMS], year2, mon2, day2, hour2, min2, sec2,
9185 year, mon, day, hour, min, sec;
9191 LOG(2,
"Read meteo grid information...");
9200 jsec2time(met->
time, &year, &mon, &day, &hour, &min, &sec, &r);
9201 if (nc_inq_varid(ncid,
"time", &varid) == NC_NOERR) {
9202 NC(nc_get_var_double(ncid, varid, &rtime));
9203 if (fabs(year * 10000. + mon * 100. + day + hour / 24. - rtime) > 1.0)
9204 WARN(
"Time information in meteo file does not match filename!");
9206 WARN(
"Time information in meteo file is missing!");
9217 sprintf(tstr,
"19%.2s", &filename[strlen(filename) - 11]);
9219 sprintf(tstr,
"20%.2s", &filename[strlen(filename) - 11]);
9221 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 9]);
9223 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 7]);
9225 sprintf(tstr,
"%.2s", &filename[strlen(filename) - 5]);
9231 if (year < 1900 || year > 2100 || mon < 1 || mon > 12
9232 || day < 1 || day > 31 || hour < 0 || hour > 23)
9233 ERRMSG(
"Cannot read time from filename!");
9234 jsec2time(met->
time, &year2, &mon2, &day2, &hour2, &min2, &sec2, &r2);
9235 LOG(2,
"Time: %.2f (%d-%02d-%02d, %02d:%02d UTC)",
9236 met->
time, year2, mon2, day2, hour2, min2);
9240 LOG(2,
"Number of longitudes: %d", met->
nx);
9243 LOG(2,
"Number of latitudes: %d", met->
ny);
9247 LOG(2,
"Longitudes: %g, %g ... %g deg",
9250 LOG(2,
"Latitudes: %g, %g ... %g deg",
9254 for (
int ix = 2; ix < met->
nx; ix++)
9256 (fabs(met->
lon[ix] - met->
lon[ix - 1]) -
9257 fabs(met->
lon[1] - met->
lon[0])) > 0.001)
9258 ERRMSG(
"No regular grid spacing in longitudes!");
9259 for (
int iy = 2; iy < met->
ny; iy++)
9261 (fabs(met->
lat[iy] - met->
lat[iy - 1]) -
9262 fabs(met->
lat[1] - met->
lat[0])) > 0.001) {
9263 WARN(
"No regular grid spacing in latitudes!");
9268 if (nc_inq_varid(ncid,
"u", &varid) != NC_NOERR)
9269 if (nc_inq_varid(ncid,
"U", &varid) != NC_NOERR)
9271 (
"Variable 'u' or 'U' not found, cannot determine vertical dimension!");
9273 NC(nc_inq_varndims(ncid, varid, &ndims));
9274 NC(nc_inq_vardimid(ncid, varid, dimids));
9278 (ncid, dimids[ctl->
met_convention == 0 ? 1 : 3], levname, &dimlen));
9279 }
else if (ndims == 3) {
9281 (ncid, dimids[ctl->
met_convention == 0 ? 0 : 2], levname, &dimlen));
9283 ERRMSG(
"Cannot determine vertical dimension!")
9284 met->
np = (int) dimlen;
9286 LOG(2,
"Number of levels: %d", met->
np);
9287 if (met->
np < 2 || met->
np >
EP)
9288 ERRMSG(
"Number of levels out of range!");
9293 for (
int ip = 0; ip < met->
np; ip++)
9295 LOG(2,
"Altitude levels: %g, %g ... %g km",
9296 Z(met->
p[0]),
Z(met->
p[1]),
Z(met->
p[met->
np - 1]));
9297 LOG(2,
"Pressure levels: %g, %g ... %g hPa",
9298 met->
p[0], met->
p[1], met->
p[met->
np - 1]);
9302 if (strcasecmp(levname,
"hybrid") == 0)
9314 SELECT_TIMER(
"READ_MET_NC_LEVELS",
"INPUT", NVTX_READ);
9315 LOG(2,
"Read level data...");
9318 if (!
read_met_nc_3d(ncid,
"t",
"T",
"temp",
"TEMP", ctl, met, met->
t, 1.0))
9319 ERRMSG(
"Cannot read temperature!");
9322 if (!
read_met_nc_3d(ncid,
"u",
"U", NULL, NULL, ctl, met, met->
u, 1.0))
9323 ERRMSG(
"Cannot read zonal wind!");
9324 if (!
read_met_nc_3d(ncid,
"v",
"V", NULL, NULL, ctl, met, met->
v, 1.0))
9325 ERRMSG(
"Cannot read meridional wind!");
9327 (ncid,
"w",
"W",
"omega",
"OMEGA", ctl, met, met->
w, 0.01f))
9328 WARN(
"Cannot read vertical velocity!");
9333 (ncid,
"q",
"Q",
"sh",
"SH", ctl, met, met->
h2o, (
float) (
MA /
MH2O)))
9334 WARN(
"Cannot read specific humidity!");
9337 (ncid,
"rh",
"RH", NULL, NULL, ctl, met, met->
h2o, 0.01f))
9338 WARN(
"Cannot read relative humidity!");
9339#pragma omp parallel for default(shared) collapse(2)
9340 for (
int ix = 0; ix < met->
nx; ix++)
9341 for (
int iy = 0; iy < met->
ny; iy++)
9342 for (
int ip = 0; ip < met->
np; ip++) {
9343 double pw = met->
h2o[ix][iy][ip] *
PSAT(met->
t[ix][iy][ip]);
9344 met->
h2o[ix][iy][ip] =
9345 (float) (pw / (met->
p[ip] - (1.0 -
EPS) * pw));
9351 (ncid,
"o3",
"O3", NULL, NULL, ctl, met, met->
o3, (
float) (
MA /
MO3)))
9352 WARN(
"Cannot read ozone data!");
9356 (ncid,
"clwc",
"CLWC", NULL, NULL, ctl, met, met->
lwc, 1.0))
9357 WARN(
"Cannot read cloud liquid water content!");
9359 (ncid,
"crwc",
"CRWC", NULL, NULL, ctl, met, met->
rwc, 1.0))
9360 WARN(
"Cannot read cloud rain water content!");
9362 (ncid,
"ciwc",
"CIWC", NULL, NULL, ctl, met, met->
iwc, 1.0))
9363 WARN(
"Cannot read cloud ice water content!");
9365 (ncid,
"cswc",
"CSWC", NULL, NULL, ctl, met, met->
swc, 1.0))
9366 WARN(
"Cannot read cloud snow water content!");
9368 WARN(
"Cannot read cloud cover!");
9372 (ncid,
"ZETA",
"zeta", NULL, NULL, ctl, met, met->
zetal, 1.0))
9373 WARN(
"Cannot read ZETA!");
9375 (ncid,
"ZETA_DOT_TOT",
"ZETA_DOT_clr",
"zeta_dot_clr",
9376 NULL, ctl, met, met->
zeta_dotl, 0.00001157407f))
9377 WARN(
"Cannot read ZETA_DOT!");
9381 for (
int ix = 0; ix < met->
nx; ix++)
9382 for (
int iy = 0; iy < met->
ny; iy++)
9383 for (
int ip = 0; ip < met->
np; ip++) {
9384 met->
ul[ix][iy][ip] = met->
u[ix][iy][ip];
9385 met->
vl[ix][iy][ip] = met->
v[ix][iy][ip];
9386 met->
wl[ix][iy][ip] = met->
w[ix][iy][ip];
9399 (ncid,
"pl",
"PL",
"pressure",
"PRESSURE", ctl, met, met->
pl,
9402 (ncid,
"press",
"PRESS", NULL, NULL, ctl, met, met->
pl, 1.0))
9403 ERRMSG(
"Cannot read pressure on model levels!");
9410 double hyam[
EP], hybm[
EP];
9415 if (nc_inq_varid(ncid,
"hyam", &varid) == NC_NOERR
9416 && nc_inq_varid(ncid,
"hybm", &varid) == NC_NOERR) {
9419 }
else if (nc_inq_varid(ncid,
"a_hybrid_level", &varid) == NC_NOERR
9420 && nc_inq_varid(ncid,
"b_hybrid_level",
9421 &varid) == NC_NOERR) {
9425 ERRMSG(
"Cannot read a and b level coefficients from netCDF file!");
9433 ERRMSG(
"Mismatch in number of model levels!");
9436 for (
int ip = 0; ip < met->
np; ip++) {
9443 for (
int ix = 0; ix < met->
nx; ix++)
9444 for (
int iy = 0; iy < met->
ny; iy++)
9445 for (
int ip = 0; ip < met->
np; ip++)
9446 met->
pl[ix][iy][ip] =
9447 (
float) (hyam[ip] / 100. + hybm[ip] * met->
ps[ix][iy]);
9454 double hyam[
EP], hybm[
EP];
9457 for (
int ip = 0; ip < met->
np + 1; ip++) {
9464 ERRMSG(
"Mismatch in number of model levels!");
9467#pragma omp parallel for default(shared) collapse(2)
9468 for (
int ix = 0; ix < met->
nx; ix++)
9469 for (
int iy = 0; iy < met->
ny; iy++)
9470 for (
int ip = 0; ip < met->
np; ip++) {
9471 double p0 = hyam[ip] / 100. + hybm[ip] * met->
ps[ix][iy];
9472 double p1 = hyam[ip + 1] / 100. + hybm[ip + 1] * met->
ps[ix][iy];
9473 met->
pl[ix][iy][ip] = (float) ((p1 - p0) / log(p1 / p0));
9478 for (
int ix = 0; ix < met->
nx; ix++)
9479 for (
int iy = 0; iy < met->
ny; iy++)
9480 for (
int ip = 1; ip < met->
np; ip++)
9481 if ((met->
pl[ix][iy][0] > met->
pl[ix][iy][1]
9482 && met->
pl[ix][iy][ip - 1] <= met->
pl[ix][iy][ip])
9483 || (met->
pl[ix][iy][0] < met->
pl[ix][iy][1]
9484 && met->
pl[ix][iy][ip - 1] >= met->
pl[ix][iy][ip]))
9485 ERRMSG(
"Pressure profiles are not monotonic!");
9492 if (met->
pl[0][0][0] <= 0)
9493 ERRMSG(
"Pressure on model levels is missing, check MET_VERT_COORD!");
9510 for (
int ip = 0; ip < met->
np; ip++)
9511 met->
p[ip] = ctl->
met_p[ip];
9515 for (
int ip = 1; ip < met->
np; ip++)
9516 if (met->
p[ip - 1] < met->
p[ip])
9517 ERRMSG(
"Pressure levels must be descending!");
9528 SELECT_TIMER(
"READ_MET_NC_SURFACE",
"INPUT", NVTX_READ);
9529 LOG(2,
"Read surface data...");
9533 (ncid,
"lnsp",
"LNSP", NULL, NULL, NULL, NULL, ctl, met, met->
ps,
9535 for (
int ix = 0; ix < met->
nx; ix++)
9536 for (
int iy = 0; iy < met->
ny; iy++)
9537 met->
ps[ix][iy] = (
float) (exp(met->
ps[ix][iy]) / 100.);
9540 (ncid,
"ps",
"PS",
"sp",
"SP", NULL, NULL, ctl, met, met->
ps, 0.01f,
9542 WARN(
"Cannot not read surface pressure data (use lowest level)!");
9543 for (
int ix = 0; ix < met->
nx; ix++)
9544 for (
int iy = 0; iy < met->
ny; iy++)
9546 = (ctl->
met_np > 0 ? (
float) ctl->
met_p[0] : (
float) met->
p[0]);
9554 (ncid,
"z",
"Z", NULL, NULL, NULL, NULL, ctl, met, met->
zs,
9555 (
float) (1. / (1000. *
G0)), 1))
9557 (ncid,
"zm",
"ZM", NULL, NULL, NULL, NULL, ctl, met, met->
zs,
9558 (
float) (1. / 1000.), 1))
9559 WARN(
"Cannot read surface geopotential height!");
9570 memcpy(help, met->
pl,
sizeof(met->
pl));
9572 (ncid,
"gph",
"GPH", NULL, NULL, ctl, met, met->
pl,
9573 (
float) (1e-3 /
G0)))
9574 ERRMSG(
"Cannot read geopotential height!");
9575 for (
int ix = 0; ix < met->
nx; ix++)
9576 for (
int iy = 0; iy < met->
ny; iy++)
9577 met->
zs[ix][iy] = met->
pl[ix][iy][0];
9578 memcpy(met->
pl, help,
sizeof(met->
pl));
9584 (ncid,
"t2m",
"T2M",
"2t",
"2T",
"t2",
"T2", ctl, met, met->
ts, 1.0, 1))
9585 WARN(
"Cannot read surface temperature!");
9589 (ncid,
"u10m",
"U10M",
"10u",
"10U",
"u10",
"U10", ctl, met, met->
us,
9591 WARN(
"Cannot read surface zonal wind!");
9595 (ncid,
"v10m",
"V10M",
"10v",
"10V",
"v10",
"V10", ctl, met, met->
vs,
9597 WARN(
"Cannot read surface meridional wind!");
9601 (ncid,
"iews",
"IEWS", NULL, NULL, NULL, NULL, ctl, met, met->
ess,
9603 WARN(
"Cannot read eastward turbulent surface stress!");
9607 (ncid,
"inss",
"INSS", NULL, NULL, NULL, NULL, ctl, met, met->
nss,
9609 WARN(
"Cannot read nothward turbulent surface stress!");
9613 (ncid,
"ishf",
"ISHF", NULL, NULL, NULL, NULL, ctl, met, met->
shf,
9615 WARN(
"Cannot read surface sensible heat flux!");
9619 (ncid,
"lsm",
"LSM", NULL, NULL, NULL, NULL, ctl, met, met->
lsm, 1.0,
9621 WARN(
"Cannot read land-sea mask!");
9625 (ncid,
"sstk",
"SSTK",
"sst",
"SST", NULL, NULL, ctl, met, met->
sst,
9627 WARN(
"Cannot read sea surface temperature!");
9632 (ncid,
"blp",
"BLP", NULL, NULL, NULL, NULL, ctl, met, met->
pbl,
9634 WARN(
"Cannot read planetary boundary layer pressure!");
9637 (ncid,
"blh",
"BLH", NULL, NULL, NULL, NULL, ctl, met, met->
pbl,
9639 WARN(
"Cannot read planetary boundary layer height!");
9644 (ncid,
"cape",
"CAPE", NULL, NULL, NULL, NULL, ctl, met, met->
cape,
9646 WARN(
"Cannot read CAPE!");
9651 (ncid,
"cin",
"CIN", NULL, NULL, NULL, NULL, ctl, met, met->
cin,
9653 WARN(
"Cannot read convective inhibition!");
9664 LOG(2,
"Calculate planetary boundary layer...");
9670#pragma omp parallel for default(shared) collapse(2)
9671 for (
int ix = 0; ix < met->
nx; ix++)
9672 for (
int iy = 0; iy < met->
ny; iy++) {
9675 const float z = met->
zs[ix][iy] + met->
pbl[ix][iy];
9678 (float) (
LIN(met->
z[ix][iy][ip], met->
p[ip],
9679 met->
z[ix][iy][ip + 1], met->
p[ip + 1], z));
9688 const double rib_crit = 0.25, dz = 0.05, umin = 5.0;
9691#pragma omp parallel for default(shared) collapse(2)
9692 for (
int ix = 0; ix < met->
nx; ix++)
9693 for (
int iy = 0; iy < met->
ny; iy++) {
9696 const double pbl_bot = met->
ps[ix][iy] * exp(-dz /
H0);
9700 for (ip = 1; ip < met->
np; ip++)
9701 if (met->
p[ip] < pbl_bot)
9705 const double h2os =
LIN(met->
p[ip - 1], met->
h2o[ix][iy][ip - 1],
9706 met->
p[ip], met->
h2o[ix][iy][ip], pbl_bot);
9707 const double tvs =
THETAVIRT(pbl_bot, met->
ts[ix][iy], h2os);
9713 for (; ip < met->
np; ip++) {
9716 double vh2 =
SQR(met->
u[ix][iy][ip] - met->
us[ix][iy])
9717 +
SQR(met->
v[ix][iy][ip] - met->
vs[ix][iy]);
9718 vh2 =
MAX(vh2,
SQR(umin));
9722 G0 * 1e3 * (met->
z[ix][iy][ip] - met->
zs[ix][iy]) / tvs
9724 met->
h2o[ix][iy][ip]) - tvs) / vh2;
9727 if (rib >= rib_crit) {
9728 met->
pbl[ix][iy] = (float) (
LIN(rib_old, met->
p[ip - 1],
9729 rib, met->
p[ip], rib_crit));
9730 if (met->
pbl[ix][iy] > pbl_bot)
9731 met->
pbl[ix][iy] = (float) pbl_bot;
9746 const double dtheta = 2.0, zmin = 0.1;
9749#pragma omp parallel for default(shared) collapse(2)
9750 for (
int ix = 0; ix < met->
nx; ix++)
9751 for (
int iy = 0; iy < met->
ny; iy++) {
9754 const double theta0 =
THETA(met->
ps[ix][iy], met->
ts[ix][iy]);
9758 for (ip = met->
np - 2; ip > 0; ip--)
9759 if (met->
p[ip] >= 300.)
9760 if (met->
p[ip] > met->
ps[ix][iy]
9761 ||
THETA(met->
p[ip], met->
t[ix][iy][ip]) <= theta0 + dtheta)
9766 = (float) (
LIN(
THETA(met->
p[ip + 1], met->
t[ix][iy][ip + 1]),
9768 THETA(met->
p[ip], met->
t[ix][iy][ip]),
9769 met->
p[ip], theta0 + dtheta));
9772 double pbl_min = met->
ps[ix][iy] * exp(-zmin /
H0);
9773 if (met->
pbl[ix][iy] > pbl_min || met->
p[ip] > met->
ps[ix][iy])
9774 met->
pbl[ix][iy] = (float) pbl_min;
9779#pragma omp parallel for default(shared) collapse(2)
9780 for (
int ix = 0; ix < met->
nx; ix++)
9781 for (
int iy = 0; iy < met->
ny; iy++) {
9785 met->
pbl[ix][iy] =
MIN(met->
pbl[ix][iy], (
float) pbl_min);
9789 met->
pbl[ix][iy] =
MAX(met->
pbl[ix][iy], (
float) pbl_max);
9799 SELECT_TIMER(
"READ_MET_PERIODIC",
"METPROC", NVTX_READ);
9800 LOG(2,
"Apply periodic boundary conditions...");
9803 if (!(fabs(met->
lon[met->
nx - 1] - met->
lon[0]
9804 + met->
lon[1] - met->
lon[0] - 360) < 0.01))
9808 if ((++met->
nx) >=
EX)
9809 ERRMSG(
"Cannot create periodic boundary conditions!");
9815#pragma omp parallel for default(shared)
9816 for (
int iy = 0; iy < met->
ny; iy++) {
9817 met->
ps[met->
nx - 1][iy] = met->
ps[0][iy];
9818 met->
zs[met->
nx - 1][iy] = met->
zs[0][iy];
9819 met->
ts[met->
nx - 1][iy] = met->
ts[0][iy];
9820 met->
us[met->
nx - 1][iy] = met->
us[0][iy];
9821 met->
vs[met->
nx - 1][iy] = met->
vs[0][iy];
9822 met->
ess[met->
nx - 1][iy] = met->
ess[0][iy];
9823 met->
nss[met->
nx - 1][iy] = met->
nss[0][iy];
9824 met->
shf[met->
nx - 1][iy] = met->
shf[0][iy];
9825 met->
lsm[met->
nx - 1][iy] = met->
lsm[0][iy];
9826 met->
sst[met->
nx - 1][iy] = met->
sst[0][iy];
9827 met->
pbl[met->
nx - 1][iy] = met->
pbl[0][iy];
9828 met->
cape[met->
nx - 1][iy] = met->
cape[0][iy];
9829 met->
cin[met->
nx - 1][iy] = met->
cin[0][iy];
9830 for (
int ip = 0; ip < met->
np; ip++) {
9831 met->
t[met->
nx - 1][iy][ip] = met->
t[0][iy][ip];
9832 met->
u[met->
nx - 1][iy][ip] = met->
u[0][iy][ip];
9833 met->
v[met->
nx - 1][iy][ip] = met->
v[0][iy][ip];
9834 met->
w[met->
nx - 1][iy][ip] = met->
w[0][iy][ip];
9835 met->
h2o[met->
nx - 1][iy][ip] = met->
h2o[0][iy][ip];
9836 met->
o3[met->
nx - 1][iy][ip] = met->
o3[0][iy][ip];
9837 met->
lwc[met->
nx - 1][iy][ip] = met->
lwc[0][iy][ip];
9838 met->
rwc[met->
nx - 1][iy][ip] = met->
rwc[0][iy][ip];
9839 met->
iwc[met->
nx - 1][iy][ip] = met->
iwc[0][iy][ip];
9840 met->
swc[met->
nx - 1][iy][ip] = met->
swc[0][iy][ip];
9841 met->
cc[met->
nx - 1][iy][ip] = met->
cc[0][iy][ip];
9843 for (
int ip = 0; ip < met->
npl; ip++) {
9844 met->
ul[met->
nx - 1][iy][ip] = met->
ul[0][iy][ip];
9845 met->
vl[met->
nx - 1][iy][ip] = met->
vl[0][iy][ip];
9846 met->
wl[met->
nx - 1][iy][ip] = met->
wl[0][iy][ip];
9847 met->
pl[met->
nx - 1][iy][ip] = met->
pl[0][iy][ip];
9848 met->
zetal[met->
nx - 1][iy][ip] = met->
zetal[0][iy][ip];
9860 SELECT_TIMER(
"READ_MET_POLAR_WINDS",
"METPROC", NVTX_READ);
9861 LOG(2,
"Apply fix for polar winds...");
9864 if (fabs(met->
lat[0]) < 89.999 || fabs(met->
lat[met->
ny - 1]) < 89.999)
9868 for (
int ihem = 0; ihem < 2; ihem++) {
9871 int i89 = 1, i90 = 0, sign = 1;
9876 if (met->
lat[i90] < 0)
9880 double clon[
EX], slon[
EX];
9881#pragma omp parallel for default(shared)
9882 for (
int ix = 0; ix < met->
nx; ix++) {
9883 clon[ix] = cos(sign *
DEG2RAD(met->
lon[ix]));
9884 slon[ix] = sin(sign *
DEG2RAD(met->
lon[ix]));
9888#pragma omp parallel for default(shared)
9889 for (
int ip = 0; ip < met->
np; ip++) {
9892 double vel89x = 0, vel89y = 0;
9893 for (
int ix = 0; ix < met->
nx; ix++) {
9895 (met->
u[ix][i89][ip] * clon[ix] -
9896 met->
v[ix][i89][ip] * slon[ix]) / met->
nx;
9898 (met->
u[ix][i89][ip] * slon[ix] +
9899 met->
v[ix][i89][ip] * clon[ix]) / met->
nx;
9903 for (
int ix = 0; ix < met->
nx; ix++) {
9905 = (float) (vel89x * clon[ix] + vel89y * slon[ix]);
9907 = (float) (-vel89x * slon[ix] + vel89y * clon[ix]);
9922 LOG(2,
"Calculate potential vorticity...");
9925#pragma omp parallel for default(shared)
9926 for (
int ip = 0; ip < met->
np; ip++)
9927 pows[ip] = pow(1000. / met->
p[ip], 0.286);
9930#pragma omp parallel for default(shared)
9931 for (
int ix = 0; ix < met->
nx; ix++) {
9934 const int ix0 =
MAX(ix - 1, 0);
9935 const int ix1 =
MIN(ix + 1, met->
nx - 1);
9938 for (
int iy = 0; iy < met->
ny; iy++) {
9941 const int iy0 =
MAX(iy - 1, 0);
9942 const int iy1 =
MIN(iy + 1, met->
ny - 1);
9945 const double latr = 0.5 * (met->
lat[iy1] + met->
lat[iy0]);
9946 const double dx = 1000. *
DEG2DX(met->
lon[ix1] - met->
lon[ix0], latr);
9947 const double dy = 1000. *
DEG2DY(met->
lat[iy1] - met->
lat[iy0]);
9948 const double c0 = cos(
DEG2RAD(met->
lat[iy0]));
9949 const double c1 = cos(
DEG2RAD(met->
lat[iy1]));
9950 const double cr = cos(
DEG2RAD(latr));
9951 const double vort = 2 * 7.2921e-5 * sin(
DEG2RAD(latr));
9954 for (
int ip = 0; ip < met->
np; ip++) {
9958 = (met->
t[ix1][iy][ip] - met->
t[ix0][iy][ip]) * pows[ip] / dx;
9959 const double dvdx = (met->
v[ix1][iy][ip] - met->
v[ix0][iy][ip]) / dx;
9963 = (met->
t[ix][iy1][ip] - met->
t[ix][iy0][ip]) * pows[ip] / dy;
9965 = (met->
u[ix][iy1][ip] * c1 - met->
u[ix][iy0][ip] * c0) / dy;
9968 const int ip0 =
MAX(ip - 1, 0);
9969 const int ip1 =
MIN(ip + 1, met->
np - 1);
9972 double dtdp, dudp, dvdp;
9973 const double dp0 = 100. * (met->
p[ip] - met->
p[ip0]);
9974 const double dp1 = 100. * (met->
p[ip1] - met->
p[ip]);
9975 if (ip != ip0 && ip != ip1) {
9976 double denom = dp0 * dp1 * (dp0 + dp1);
9977 dtdp = (dp0 * dp0 * met->
t[ix][iy][ip1] * pows[ip1]
9978 - dp1 * dp1 * met->
t[ix][iy][ip0] * pows[ip0]
9979 + (dp1 * dp1 - dp0 * dp0) * met->
t[ix][iy][ip] * pows[ip])
9981 dudp = (dp0 * dp0 * met->
u[ix][iy][ip1]
9982 - dp1 * dp1 * met->
u[ix][iy][ip0]
9983 + (dp1 * dp1 - dp0 * dp0) * met->
u[ix][iy][ip])
9985 dvdp = (dp0 * dp0 * met->
v[ix][iy][ip1]
9986 - dp1 * dp1 * met->
v[ix][iy][ip0]
9987 + (dp1 * dp1 - dp0 * dp0) * met->
v[ix][iy][ip])
9990 const double denom = dp0 + dp1;
9992 (met->
t[ix][iy][ip1] * pows[ip1] -
9993 met->
t[ix][iy][ip0] * pows[ip0]) / denom;
9994 dudp = (met->
u[ix][iy][ip1] - met->
u[ix][iy][ip0]) / denom;
9995 dvdp = (met->
v[ix][iy][ip1] - met->
v[ix][iy][ip0]) / denom;
9999 met->
pv[ix][iy][ip] = (float)
10001 (-dtdp * (dvdx - dudy / cr + vort) + dvdp * dtdx - dudp * dtdy));
10007#pragma omp parallel for default(shared)
10008 for (
int ix = 0; ix < met->
nx; ix++)
10009 for (
int ip = 0; ip < met->
np; ip++) {
10011 = met->
pv[ix][1][ip]
10012 = met->
pv[ix][2][ip];
10013 met->
pv[ix][met->
ny - 1][ip]
10014 = met->
pv[ix][met->
ny - 2][ip]
10015 = met->
pv[ix][met->
ny - 3][ip];
10026 LOG(2,
"Calculate total column ozone...");
10029#pragma omp parallel for default(shared) collapse(2)
10030 for (
int ix = 0; ix < met->
nx; ix++)
10031 for (
int iy = 0; iy < met->
ny; iy++) {
10035 for (
int ip = 1; ip < met->
np; ip++)
10036 if (met->
p[ip - 1] <= met->
ps[ix][iy]) {
10038 0.5 * (met->
o3[ix][iy][ip - 1] + met->
o3[ix][iy][ip]);
10039 const double dp = met->
p[ip - 1] - met->
p[ip];
10040 cd += vmr *
MO3 /
MA * dp * 1e2 /
G0;
10044 met->
o3c[ix][iy] = (float) (cd / 2.1415e-5);
10062 SELECT_TIMER(
"READ_MET_SAMPLE",
"METPROC", NVTX_READ);
10063 LOG(2,
"Downsampling of meteo data...");
10069 help->
nx = met->
nx;
10070 help->
ny = met->
ny;
10071 help->
np = met->
np;
10072 memcpy(help->
lon, met->
lon,
sizeof(met->
lon));
10073 memcpy(help->
lat, met->
lat,
sizeof(met->
lat));
10074 memcpy(help->
p, met->
p,
sizeof(met->
p));
10077 for (
int ix = 0; ix < met->
nx; ix += ctl->
met_dx) {
10078 for (
int iy = 0; iy < met->
ny; iy += ctl->
met_dy) {
10079 for (
int ip = 0; ip < met->
np; ip += ctl->
met_dp) {
10080 help->
ps[ix][iy] = 0;
10081 help->
zs[ix][iy] = 0;
10082 help->
ts[ix][iy] = 0;
10083 help->
us[ix][iy] = 0;
10084 help->
vs[ix][iy] = 0;
10085 help->
ess[ix][iy] = 0;
10086 help->
nss[ix][iy] = 0;
10087 help->
shf[ix][iy] = 0;
10088 help->
lsm[ix][iy] = 0;
10089 help->
sst[ix][iy] = 0;
10090 help->
pbl[ix][iy] = 0;
10091 help->
cape[ix][iy] = 0;
10092 help->
cin[ix][iy] = 0;
10093 help->
t[ix][iy][ip] = 0;
10094 help->
u[ix][iy][ip] = 0;
10095 help->
v[ix][iy][ip] = 0;
10096 help->
w[ix][iy][ip] = 0;
10097 help->
h2o[ix][iy][ip] = 0;
10098 help->
o3[ix][iy][ip] = 0;
10099 help->
lwc[ix][iy][ip] = 0;
10100 help->
rwc[ix][iy][ip] = 0;
10101 help->
iwc[ix][iy][ip] = 0;
10102 help->
swc[ix][iy][ip] = 0;
10103 help->
cc[ix][iy][ip] = 0;
10105 for (
int ix2 = ix - ctl->
met_sx + 1; ix2 <= ix + ctl->met_sx - 1;
10110 else if (ix3 >= met->
nx)
10113 for (
int iy2 =
MAX(iy - ctl->
met_sy + 1, 0);
10114 iy2 <=
MIN(iy + ctl->
met_sy - 1, met->
ny - 1); iy2++)
10115 for (
int ip2 =
MAX(ip - ctl->
met_sp + 1, 0);
10116 ip2 <=
MIN(ip + ctl->
met_sp - 1, met->
np - 1); ip2++) {
10117 float w = (1.0f - (float) abs(ix - ix2) / (float) ctl->
met_sx)
10118 * (1.0f - (float) abs(iy - iy2) / (float) ctl->
met_sy)
10119 * (1.0f - (float) abs(ip - ip2) / (float) ctl->
met_sp);
10120 help->
ps[ix][iy] += w * met->
ps[ix3][iy2];
10121 help->
zs[ix][iy] += w * met->
zs[ix3][iy2];
10122 help->
ts[ix][iy] += w * met->
ts[ix3][iy2];
10123 help->
us[ix][iy] += w * met->
us[ix3][iy2];
10124 help->
vs[ix][iy] += w * met->
vs[ix3][iy2];
10125 help->
ess[ix][iy] += w * met->
ess[ix3][iy2];
10126 help->
nss[ix][iy] += w * met->
nss[ix3][iy2];
10127 help->
shf[ix][iy] += w * met->
shf[ix3][iy2];
10128 help->
lsm[ix][iy] += w * met->
lsm[ix3][iy2];
10129 help->
sst[ix][iy] += w * met->
sst[ix3][iy2];
10130 help->
pbl[ix][iy] += w * met->
pbl[ix3][iy2];
10131 help->
cape[ix][iy] += w * met->
cape[ix3][iy2];
10132 help->
cin[ix][iy] += w * met->
cin[ix3][iy2];
10133 help->
t[ix][iy][ip] += w * met->
t[ix3][iy2][ip2];
10134 help->
u[ix][iy][ip] += w * met->
u[ix3][iy2][ip2];
10135 help->
v[ix][iy][ip] += w * met->
v[ix3][iy2][ip2];
10136 help->
w[ix][iy][ip] += w * met->
w[ix3][iy2][ip2];
10137 help->
h2o[ix][iy][ip] += w * met->
h2o[ix3][iy2][ip2];
10138 help->
o3[ix][iy][ip] += w * met->
o3[ix3][iy2][ip2];
10139 help->
lwc[ix][iy][ip] += w * met->
lwc[ix3][iy2][ip2];
10140 help->
rwc[ix][iy][ip] += w * met->
rwc[ix3][iy2][ip2];
10141 help->
iwc[ix][iy][ip] += w * met->
iwc[ix3][iy2][ip2];
10142 help->
swc[ix][iy][ip] += w * met->
swc[ix3][iy2][ip2];
10143 help->
cc[ix][iy][ip] += w * met->
cc[ix3][iy2][ip2];
10147 help->
ps[ix][iy] /= wsum;
10148 help->
zs[ix][iy] /= wsum;
10149 help->
ts[ix][iy] /= wsum;
10150 help->
us[ix][iy] /= wsum;
10151 help->
vs[ix][iy] /= wsum;
10152 help->
ess[ix][iy] /= wsum;
10153 help->
nss[ix][iy] /= wsum;
10154 help->
shf[ix][iy] /= wsum;
10155 help->
lsm[ix][iy] /= wsum;
10156 help->
sst[ix][iy] /= wsum;
10157 help->
pbl[ix][iy] /= wsum;
10158 help->
cape[ix][iy] /= wsum;
10159 help->
cin[ix][iy] /= wsum;
10160 help->
t[ix][iy][ip] /= wsum;
10161 help->
u[ix][iy][ip] /= wsum;
10162 help->
v[ix][iy][ip] /= wsum;
10163 help->
w[ix][iy][ip] /= wsum;
10164 help->
h2o[ix][iy][ip] /= wsum;
10165 help->
o3[ix][iy][ip] /= wsum;
10166 help->
lwc[ix][iy][ip] /= wsum;
10167 help->
rwc[ix][iy][ip] /= wsum;
10168 help->
iwc[ix][iy][ip] /= wsum;
10169 help->
swc[ix][iy][ip] /= wsum;
10170 help->
cc[ix][iy][ip] /= wsum;
10177 for (
int ix = 0; ix < help->
nx; ix += ctl->
met_dx) {
10178 met->
lon[met->
nx] = help->
lon[ix];
10180 for (
int iy = 0; iy < help->
ny; iy += ctl->
met_dy) {
10181 met->
lat[met->
ny] = help->
lat[iy];
10182 met->
ps[met->
nx][met->
ny] = help->
ps[ix][iy];
10183 met->
zs[met->
nx][met->
ny] = help->
zs[ix][iy];
10184 met->
ts[met->
nx][met->
ny] = help->
ts[ix][iy];
10185 met->
us[met->
nx][met->
ny] = help->
us[ix][iy];
10186 met->
vs[met->
nx][met->
ny] = help->
vs[ix][iy];
10187 met->
ess[met->
nx][met->
ny] = help->
ess[ix][iy];
10188 met->
nss[met->
nx][met->
ny] = help->
nss[ix][iy];
10189 met->
shf[met->
nx][met->
ny] = help->
shf[ix][iy];
10190 met->
lsm[met->
nx][met->
ny] = help->
lsm[ix][iy];
10191 met->
sst[met->
nx][met->
ny] = help->
sst[ix][iy];
10192 met->
pbl[met->
nx][met->
ny] = help->
pbl[ix][iy];
10194 met->
cin[met->
nx][met->
ny] = help->
cin[ix][iy];
10196 for (
int ip = 0; ip < help->
np; ip += ctl->
met_dp) {
10197 met->
p[met->
np] = help->
p[ip];
10198 met->
t[met->
nx][met->
ny][met->
np] = help->
t[ix][iy][ip];
10199 met->
u[met->
nx][met->
ny][met->
np] = help->
u[ix][iy][ip];
10200 met->
v[met->
nx][met->
ny][met->
np] = help->
v[ix][iy][ip];
10201 met->
w[met->
nx][met->
ny][met->
np] = help->
w[ix][iy][ip];
10202 met->
h2o[met->
nx][met->
ny][met->
np] = help->
h2o[ix][iy][ip];
10203 met->
o3[met->
nx][met->
ny][met->
np] = help->
o3[ix][iy][ip];
10204 met->
lwc[met->
nx][met->
ny][met->
np] = help->
lwc[ix][iy][ip];
10205 met->
rwc[met->
nx][met->
ny][met->
np] = help->
rwc[ix][iy][ip];
10206 met->
iwc[met->
nx][met->
ny][met->
np] = help->
iwc[ix][iy][ip];
10207 met->
swc[met->
nx][met->
ny][met->
np] = help->
swc[ix][iy][ip];
10208 met->
cc[met->
nx][met->
ny][met->
np] = help->
cc[ix][iy][ip];
10227 double p2[200], pv[
EP], pv2[200], t[
EP], t2[200], th[
EP],
10228 th2[200], z[
EP], z2[200];
10232 LOG(2,
"Calculate tropopause...");
10235#pragma omp parallel for default(shared)
10236 for (
int iz = 0; iz < met->
np; iz++)
10237 z[iz] =
Z(met->
p[iz]);
10238#pragma omp parallel for default(shared)
10239 for (
int iz = 0; iz <= 190; iz++) {
10240 z2[iz] = 4.5 + 0.1 * iz;
10241 p2[iz] =
P(z2[iz]);
10246#pragma omp parallel for default(shared) collapse(2)
10247 for (
int ix = 0; ix < met->
nx; ix++)
10248 for (
int iy = 0; iy < met->
ny; iy++)
10249 met->
pt[ix][iy] = NAN;
10253#pragma omp parallel for default(shared) collapse(2)
10254 for (
int ix = 0; ix < met->
nx; ix++)
10255 for (
int iy = 0; iy < met->
ny; iy++)
10263#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10264 for (
int ix = 0; ix < met->
nx; ix++)
10265 for (
int iy = 0; iy < met->
ny; iy++) {
10268 for (
int iz = 0; iz < met->
np; iz++)
10269 t[iz] = met->
t[ix][iy][iz];
10273 int iz = (int) gsl_stats_min_index(t2, 1, 171);
10274 if (iz > 0 && iz < 170)
10275 met->
pt[ix][iy] = (float) p2[iz];
10277 met->
pt[ix][iy] = NAN;
10285#pragma omp parallel for default(shared) private(t,t2) collapse(2)
10286 for (
int ix = 0; ix < met->
nx; ix++)
10287 for (
int iy = 0; iy < met->
ny; iy++) {
10291 for (iz = 0; iz < met->
np; iz++)
10292 t[iz] = met->
t[ix][iy][iz];
10296 met->
pt[ix][iy] = NAN;
10297 for (iz = 0; iz <= 170; iz++) {
10299 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10300 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10305 if (iz > 0 && iz < 170)
10306 met->
pt[ix][iy] = (float) p2[iz];
10313 met->
pt[ix][iy] = NAN;
10314 for (; iz <= 170; iz++) {
10316 for (
int iz2 = iz + 1; iz2 <= iz + 10; iz2++)
10317 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) < 3.0) {
10324 for (; iz <= 170; iz++) {
10326 for (
int iz2 = iz + 1; iz2 <= iz + 20; iz2++)
10327 if (
LAPSE(p2[iz], t2[iz], p2[iz2], t2[iz2]) > 2.0) {
10332 if (iz > 0 && iz < 170)
10333 met->
pt[ix][iy] = (float) p2[iz];
10345#pragma omp parallel for default(shared) private(pv,pv2,th,th2) collapse(2)
10346 for (
int ix = 0; ix < met->
nx; ix++)
10347 for (
int iy = 0; iy < met->
ny; iy++) {
10350 for (
int iz = 0; iz < met->
np; iz++)
10351 pv[iz] = met->
pv[ix][iy][iz];
10355 for (
int iz = 0; iz < met->
np; iz++)
10356 th[iz] =
THETA(met->
p[iz], met->
t[ix][iy][iz]);
10360 met->
pt[ix][iy] = NAN;
10361 for (
int iz = 0; iz <= 170; iz++)
10364 if (iz > 0 && iz < 170)
10365 met->
pt[ix][iy] = (float) p2[iz];
10372 ERRMSG(
"Cannot calculate tropopause!");
10375#pragma omp parallel for default(shared) collapse(2)
10376 for (
int ix = 0; ix < met->
nx; ix++)
10377 for (
int iy = 0; iy < met->
ny; iy++) {
10378 double h2ot, tt, zt;
10381 met->
lat[iy], &tt, ci, cw, 1);
10383 met->
lat[iy], &zt, ci, cw, 0);
10385 met->
lat[iy], &h2ot, ci, cw, 0);
10386 met->
tt[ix][iy] = (float) tt;
10387 met->
zt[ix][iy] = (float) zt;
10388 met->
h2ot[ix][iy] = (float) h2ot;
10395 const char *filename,
10405 LOG(1,
"Read observation data: %s", filename);
10409 read_obs_asc(filename, rt, rz, rlon, rlat, robs, nobs);
10411 read_obs_nc(filename, rt, rz, rlon, rlat, robs, nobs);
10413 ERRMSG(
"Set OBS_TYPE to 0 or 1!");
10416 for (
int i = 1; i < *nobs; i++)
10417 if (rt[i] < rt[i - 1])
10418 ERRMSG(
"Time must be ascending!");
10423 LOG(2,
"Number of observations: %d", *nobs);
10424 gsl_stats_minmax(&mini, &maxi, rt, 1, (
size_t) n);
10425 LOG(2,
"Time range: %.2f ... %.2f s", mini, maxi);
10426 gsl_stats_minmax(&mini, &maxi, rz, 1, (
size_t) n);
10427 LOG(2,
"Altitude range: %g ... %g km", mini, maxi);
10428 gsl_stats_minmax(&mini, &maxi, rlon, 1, (
size_t) n);
10429 LOG(2,
"Longitude range: %g ... %g deg", mini, maxi);
10430 gsl_stats_minmax(&mini, &maxi, rlat, 1, (
size_t) n);
10431 LOG(2,
"Latitude range: %g ... %g deg", mini, maxi);
10432 gsl_stats_minmax(&mini, &maxi, robs, 1, (
size_t) n);
10433 LOG(2,
"Observation range: %g ... %g", mini, maxi);
10439 const char *filename,
10449 if (!(in = fopen(filename,
"r")))
10450 ERRMSG(
"Cannot open file!");
10454 while (fgets(line,
LEN, in))
10455 if (sscanf(line,
"%lg %lg %lg %lg %lg", &rt[*nobs], &rz[*nobs],
10456 &rlon[*nobs], &rlat[*nobs], &robs[*nobs]) == 5)
10457 if ((++(*nobs)) >=
NOBS)
10458 ERRMSG(
"Too many observations!");
10467 const char *filename,
10478 if (nc_open(filename, NC_NOWRITE, &ncid) != NC_NOERR)
10479 ERRMSG(
"Cannot open file!");
10490 NC(nc_close(ncid));
10496 const char *filename,
10499 const char *varname,
10501 const char *defvalue,
10506 char fullname1[
LEN], fullname2[
LEN], rval[
LEN];
10508 int contain = 0, i;
10511 if (filename[strlen(filename) - 1] !=
'-')
10512 if (!(in = fopen(filename,
"r")))
10513 ERRMSG(
"Cannot open file!");
10517 sprintf(fullname1,
"%s[%d]", varname, arridx);
10518 sprintf(fullname2,
"%s[*]", varname);
10520 sprintf(fullname1,
"%s", varname);
10521 sprintf(fullname2,
"%s", varname);
10526 char dummy[
LEN], line[
LEN], rvarname[
LEN];
10527 while (fgets(line,
LEN, in)) {
10528 if (sscanf(line,
"%4999s %4999s %4999s", rvarname, dummy, rval) == 3)
10529 if (strcasecmp(rvarname, fullname1) == 0 ||
10530 strcasecmp(rvarname, fullname2) == 0) {
10536 for (i = 1; i < argc - 1; i++)
10537 if (strcasecmp(argv[i], fullname1) == 0 ||
10538 strcasecmp(argv[i], fullname2) == 0) {
10539 sprintf(rval,
"%s", argv[i + 1]);
10550 if (strlen(defvalue) > 0)
10551 sprintf(rval,
"%s", defvalue);
10553 ERRMSG(
"Missing variable %s!\n", fullname1);
10557 LOG(1,
"%s = %s", fullname1, rval);
10561 sprintf(value,
"%s", rval);
10571 const double rhop) {
10574 const double rp_help = rp * 1e-6;
10577 const double rho =
RHO(p, T);
10580 const double eta = 1.8325e-5 * (416.16 / (T + 120.)) * pow(T / 296.16, 1.5);
10583 const double v = sqrt(8. *
KB * T / (M_PI * 4.8096e-26));
10586 const double lambda = 2. * eta / (rho * v);
10589 const double K = lambda / rp_help;
10592 const double G = 1. + K * (1.249 + 0.42 * exp(-0.87 / K));
10595 return 2. *
SQR(rp_help) * (rhop - rho) *
G0 / (9. * eta) * G;
10607 const int method) {
10613 gsl_interp_accel *acc = gsl_interp_accel_alloc();
10614 gsl_spline *s = gsl_spline_alloc(gsl_interp_cspline, (
size_t) n);
10617 gsl_spline_init(s, x, y, (
size_t) n);
10618 for (
int i = 0; i < n2; i++)
10621 else if (x2[i] >= x[n - 1])
10624 y2[i] = gsl_spline_eval(s, x2[i], acc);
10627 gsl_spline_free(s);
10628 gsl_interp_accel_free(acc);
10633 for (
int i = 0; i < n2; i++)
10636 else if (x2[i] >= x[n - 1])
10640 y2[i] =
LIN(x[idx], y[idx], x[idx + 1], y[idx + 1], x2[i]);
10654 float mean = 0, var = 0;
10656 for (
int i = 0; i < n; ++i) {
10658 var +=
SQR(data[i]);
10661 var = var / (float) n -
SQR(mean / (
float) n);
10663 return (var > 0 ? sqrtf(var) : 0);
10671 const double lat) {
10674 const double D = sec / 86400 - 0.5;
10677 const double g =
DEG2RAD(357.529 + 0.98560028 * D);
10678 const double q = 280.459 + 0.98564736 * D;
10679 const double L =
DEG2RAD(q + 1.915 * sin(g) + 0.020 * sin(2 * g));
10682 const double e =
DEG2RAD(23.439 - 0.00000036 * D);
10685 const double sindec = sin(e) * sin(L);
10688 const double ra = atan2(cos(e) * sin(L), cos(L));
10691 const double GMST = 18.697374558 + 24.06570982441908 * D;
10694 const double LST = GMST + lon / 15;
10697 const double h = LST / 12 * M_PI - ra;
10700 const double lat_help =
DEG2RAD(lat);
10703 return acos(sin(lat_help) * sindec +
10704 cos(lat_help) * sqrt(1 -
SQR(sindec)) * cos(h));
10716 const double remain,
10728 t1.tm_year = year - 1900;
10729 t1.tm_mon = mon - 1;
10735 *jsec = (double) timegm(&t1) - (double) timegm(&t0) + remain;
10743 const int output) {
10750 static int iname = -1, igroup = -1, nname, ngroup, ct_name[
NTIMER];
10753 t1 = omp_get_wtime();
10758 rt_name[iname] += dt;
10759 rt_min[iname] = (ct_name[iname] <= 0 ? dt :
MIN(rt_min[iname], dt));
10760 rt_max[iname] = (ct_name[iname] <= 0 ? dt :
MAX(rt_max[iname], dt));
10764 rt_group[igroup] += t1 - t0;
10768 for (
int i = 0; i < nname; i++)
10769 LOG(1,
"TIMER_%s = %.3f s (min= %g s, mean= %g s,"
10770 " max= %g s, n= %d)", names[i], rt_name[i], rt_min[i],
10771 rt_name[i] / ct_name[i], rt_max[i], ct_name[i]);
10772 for (
int i = 0; i < ngroup; i++)
10773 LOG(1,
"TIMER_GROUP_%s = %.3f s", groups[i], rt_group[i]);
10774 double total = 0.0;
10775 for (
int i = 0; i < nname; i++)
10776 total += rt_name[i];
10777 LOG(1,
"TIMER_TOTAL = %.3f s", total);
10781 for (iname = 0; iname < nname; iname++)
10782 if (strcasecmp(name, names[iname]) == 0)
10784 for (igroup = 0; igroup < ngroup; igroup++)
10785 if (strcasecmp(group, groups[igroup]) == 0)
10789 if (iname >= nname) {
10790 sprintf(names[iname],
"%s", name);
10791 if ((++nname) >=
NTIMER)
10792 ERRMSG(
"Too many timers!");
10796 if (igroup >= ngroup) {
10797 sprintf(groups[igroup],
"%s", group);
10798 if ((++ngroup) >=
NTIMER)
10799 ERRMSG(
"Too many groups!");
10809 const char *filename,
10810 const int offset) {
10817 int len = (int) strlen(filename);
10818 sprintf(tstr,
"%.4s", &filename[len - offset]);
10819 int year = atoi(tstr);
10820 sprintf(tstr,
"%.2s", &filename[len - offset + 5]);
10821 int mon = atoi(tstr);
10822 sprintf(tstr,
"%.2s", &filename[len - offset + 8]);
10823 int day = atoi(tstr);
10824 sprintf(tstr,
"%.2s", &filename[len - offset + 11]);
10825 int hour = atoi(tstr);
10826 sprintf(tstr,
"%.2s", &filename[len - offset + 14]);
10827 int min = atoi(tstr);
10830 if (year < 1900 || year > 2100 || mon < 1 || mon > 12 || day < 1
10831 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59)
10832 ERRMSG(
"Cannot read time from filename!");
10835 time2jsec(year, mon, day, hour, min, 0, 0.0, &t);
10852 const double p1 = pt * 0.866877899;
10853 const double p0 = pt / 0.866877899;
10856 if (atm->
p[ip] > p0)
10858 else if (atm->
p[ip] < p1)
10861 return LIN(p0, 1.0, p1, 0.0, atm->
p[ip]);
10867 const char *filename,
10875 const double t0 = t - 0.5 * ctl->
dt_mod;
10876 const double t1 = t + 0.5 * ctl->
dt_mod;
10882 if (!(out = popen(
"gnuplot",
"w")))
10883 ERRMSG(
"Cannot create pipe to gnuplot!");
10886 fprintf(out,
"set out \"%s.png\"\n", filename);
10890 int year, mon, day, hour, min, sec;
10891 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
10892 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
10893 year, mon, day, hour, min);
10898 ERRMSG(
"Cannot open file!");
10900 while (fgets(line,
LEN, in))
10901 fprintf(out,
"%s", line);
10908 if (!(out = fopen(filename,
"w")))
10909 ERRMSG(
"Cannot create file!");
10914 "# $1 = time [s]\n"
10915 "# $2 = altitude [km]\n"
10916 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
10917 for (
int iq = 0; iq < ctl->
nq; iq++)
10918 fprintf(out,
"# $%i = %s [%s]\n", iq + 5, ctl->
qnt_name[iq],
10920 fprintf(out,
"\n");
10923 for (
int ip = 0; ip < atm->
np; ip += ctl->
atm_stride) {
10930 fprintf(out,
"%.2f %g %g %g", atm->
time[ip],
Z(atm->
p[ip]),
10931 atm->
lon[ip], atm->
lat[ip]);
10932 for (
int iq = 0; iq < ctl->
nq; iq++) {
10937 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
10939 fprintf(out,
"\n");
10949 const char *filename,
10951 const atm_t *atm) {
10956 if (!(out = fopen(filename,
"w")))
10957 ERRMSG(
"Cannot create file!");
10981 for (
int iq = 0; iq < ctl->
nq; iq++)
10999 const char *filename,
11001 const atm_t *atm) {
11003 int tid, pid, ncid, varid;
11004 size_t start[2], count[2];
11007 nc_create(filename, NC_NETCDF4, &ncid);
11010 NC(nc_def_dim(ncid,
"time", 1, &tid));
11011 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11014 int dim_ids[2] = { tid, pid };
11015 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11016 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11017 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
11019 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
11021 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
11024 for (
int iq = 0; iq < ctl->
nq; iq++)
11034 NC(nc_enddef(ncid));
11042 for (
int iq = 0; iq < ctl->
nq; iq++)
11046 NC(nc_close(ncid));
11052 const char *dirname,
11058 static size_t out_cnt = 0;
11060 double r, r_start, r_stop;
11061 int year, mon, day, hour, min, sec;
11062 int year_start, mon_start, day_start, hour_start, min_start, sec_start;
11063 int year_stop, mon_stop, day_stop, hour_stop, min_stop, sec_stop;
11064 char filename_out[2 *
LEN] =
"traj_fix_3d_YYYYMMDDHH_YYYYMMDDHH.nc";
11066 int ncid, varid, tid, pid, cid;
11074 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11076 &min_start, &sec_start, &r_start);
11078 &min_stop, &sec_stop, &r_stop);
11080 sprintf(filename_out,
11081 "%s/traj_fix_3d_%02d%02d%02d%02d_%02d%02d%02d%02d.nc", dirname,
11082 year_start % 100, mon_start, day_start, hour_start,
11083 year_stop % 100, mon_stop, day_stop, hour_stop);
11084 LOG(1,
"Write traj file: %s", filename_out);
11087 start[0] = out_cnt;
11090 count[1] = (size_t) atm->
np;
11093 if (out_cnt == 0) {
11096 nc_create(filename_out, NC_NETCDF4, &ncid);
11099 NC(nc_def_dim(ncid,
"time", NC_UNLIMITED, &tid));
11100 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11101 NC(nc_def_dim(ncid,
"TMDT", 7, &cid));
11106 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11107 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11108 NC_DEF_VAR(
"LAT", NC_DOUBLE, 2, dim_ids,
"Latitude",
"deg",
11110 NC_DEF_VAR(
"LON", NC_DOUBLE, 2, dim_ids,
"Longitude",
"deg",
11112 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 2, dim_ids,
"Pressure",
"hPa",
11114 NC_DEF_VAR(
"ZETA", NC_DOUBLE, 2, dim_ids,
"Zeta",
"K",
11116 for (
int iq = 0; iq < ctl->
nq; iq++)
11126 NC(nc_enddef(ncid));
11127 NC(nc_close(ncid));
11134 NC(nc_open(filename_out, NC_WRITE, &ncid));
11146 for (
int iq = 0; iq < ctl->
nq; iq++)
11150 NC(nc_close(ncid));
11153 if ((year == year_stop) && (mon == mon_stop)
11154 && (day == day_stop) && (hour == hour_stop)) {
11157 char filename_init[2 *
LEN] =
"./init_fix_YYYYMMDDHH.nc";
11158 sprintf(filename_init,
"%s/init_fix_%02d%02d%02d%02d.nc",
11159 dirname, year_stop % 100, mon_stop, day_stop, hour_stop);
11160 LOG(1,
"Write init file: %s", filename_init);
11163 nc_create(filename_init, NC_NETCDF4, &ncid);
11166 NC(nc_def_dim(ncid,
"time", 1, &tid));
11167 NC(nc_def_dim(ncid,
"NPARTS", (
size_t) atm->
np, &pid));
11172 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"Time",
11173 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11174 NC_DEF_VAR(
"LAT", NC_DOUBLE, 1, &pid,
"Latitude",
"deg",
11176 NC_DEF_VAR(
"LON", NC_DOUBLE, 1, &pid,
"Longitude",
"deg",
11178 NC_DEF_VAR(
"PRESS", NC_DOUBLE, 1, &pid,
"Pressure",
"hPa",
11181 for (
int iq = 0; iq < ctl->
nq; iq++)
11191 NC(nc_enddef(ncid));
11199 for (
int iq = 0; iq < ctl->
nq; iq++)
11203 NC(nc_close(ncid));
11210 const char *filename,
11212 const atm_t *atm) {
11214 int ncid, obsid, varid;
11216 size_t start[2], count[2];
11219 NC(nc_create(filename, NC_NETCDF4, &ncid));
11222 NC(nc_def_dim(ncid,
"obs", (
size_t) atm->
np, &obsid));
11225 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &obsid,
"time",
11226 "seconds since 2000-01-01 00:00:00 UTC", ctl->
atm_nc_level, 0);
11227 NC_DEF_VAR(
"press", NC_DOUBLE, 1, &obsid,
"pressure",
"hPa",
11229 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &obsid,
"longitude",
"degrees_east",
11231 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &obsid,
"latitude",
"degrees_north",
11233 for (
int iq = 0; iq < ctl->
nq; iq++)
11242 NC(nc_enddef(ncid));
11249 for (
int iq = 0; iq < ctl->
nq; iq++)
11253 NC(nc_close(ncid));
11259 const char *filename,
11266 static double *modmean, *obsmean, *obsstd, *rt, *rz, *rlon, *rlat, *robs,
11269 static int *obscount, nobs, nk;
11273 const int ensemble = (ctl->
nens > 0);
11279 if (ctl->
qnt_m < 0)
11280 ERRMSG(
"Need quantity mass!");
11283 ERRMSG(
"Missing ensemble IDs!");
11285 ERRMSG(
"Too many ensembles!");
11292 ALLOC(area,
double,
11298 ALLOC(rlon,
double,
11300 ALLOC(rlat,
double,
11302 ALLOC(robs,
double,
11313 LOG(1,
"Write CSI%s data: %s", ensemble ?
" ensemble" :
"", filename);
11314 if (!(out = fopen(filename,
"w")))
11315 ERRMSG(
"Cannot create file!");
11319 "# $1 = time [s]\n"
11320 "# $2 = ensemble ID\n"
11321 "# $3 = number of hits (cx)\n"
11322 "# $4 = number of misses (cy)\n"
11323 "# $5 = number of false alarms (cz)\n"
11324 "# $6 = number of observations (cx + cy)\n"
11325 "# $7 = number of forecasts (cx + cz)\n"
11326 "# $8 = bias (%%)\n"
11327 "# $9 = POD (%%)\n"
11328 "# $10 = FAR (%%)\n"
11329 "# $11 = CSI (%%)\n"
11330 "# $12 = hits by random chance\n"
11331 "# $13 = ETS (%%)\n"
11332 "# $14 = Pearson R\n"
11333 "# $15 = Spearman R\n"
11334 "# $16 = mean error [kg/m²]\n"
11335 "# $17 = RMSE [kg/m²]\n"
11336 "# $18 = MAE [kg/m²]\n"
11337 "# $19 = log-likelihood\n" "# $20 = number of points\n\n");
11345 for (
int iy = 0; iy < ctl->
csi_ny; iy++) {
11346 double lat = ctl->
csi_lat0 + dlat * (iy + 0.5);
11347 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.0) * cos(
DEG2RAD(lat));
11352 double t0 = t - 0.5 * ctl->
dt_mod;
11353 double t1 = t + 0.5 * ctl->
dt_mod;
11357 ALLOC(modmean,
double,
11358 (ensemble ? ctl->
nens : 1) * grid_size);
11359 ALLOC(obsmean,
double,
11361 ALLOC(obscount,
int,
11363 ALLOC(obsstd,
double,
11367 for (
int i = 0; i < (ensemble ? ctl->
nens : 1); i++)
11368 ct[i] = cx[i] = cy[i] = cz[i] = n[i] = 0;
11371 for (
int i = 0; i < nobs; i++) {
11372 if (rt[i] < t0 || rt[i] >= t1 || !isfinite(robs[i]))
11376 int ix = (int) ((rlon[i] - ctl->
csi_lon0) / dlon);
11377 int iy = (int) ((rlat[i] - ctl->
csi_lat0) / dlat);
11378 int iz = (int) ((rz[i] - ctl->
csi_z0) / dz);
11379 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
11385 obsmean[idx] += robs[i];
11386 obsstd[idx] +=
SQR(robs[i]);
11391 for (
int ip = 0; ip < atm->
np; ip++) {
11394 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11398 int ens_id = ensemble ? (int) atm->
q[ctl->
qnt_ens][ip] : 0;
11399 if (ens_id < 0 || ens_id >= (ensemble ? ctl->
nens : 1))
11400 ERRMSG(
"Ensemble ID out of range!");
11403 int ix = (int) ((atm->
lon[ip] - ctl->
csi_lon0) / dlon);
11404 int iy = (int) ((atm->
lat[ip] - ctl->
csi_lat0) / dlat);
11405 int iz = (int) ((
Z(atm->
p[ip]) - ctl->
csi_z0) / dz);
11406 if (ix < 0 || ix >= ctl->
csi_nx || iy < 0 || iy >= ctl->
csi_ny || iz < 0
11418 for (
int ix = 0; ix < ctl->
csi_nx; ix++)
11419 for (
int iy = 0; iy < ctl->
csi_ny; iy++)
11420 for (
int iz = 0; iz < ctl->
csi_nz; iz++) {
11424 if (obscount[idx]) {
11425 obsmean[idx] /= obscount[idx];
11426 obsstd[idx] = sqrt(obsstd[idx] -
SQR(obsmean[idx]));
11430 for (
int e = 0; e < (ensemble ? ctl->
nens : 1); e++) {
11431 int midx = e * grid_size + idx;
11432 if (modmean[midx] > 0)
11433 modmean[midx] /= (1e6 * area[iy]);
11437 if (obscount[idx]) {
11440 for (
int e = 0; e < (ensemble ? ctl->
nens : 1); e++) {
11441 int midx = e * grid_size + idx;
11454 x[n[e]] = modmean[midx];
11455 y[n[e]] = obsmean[idx];
11457 obsstdn[n[e]] = obsstd[idx];
11458 if ((++n[e]) >=
NCSI)
11459 ERRMSG(
"Too many points for statistics!");
11467 for (
int e = 0; e < (ensemble ? ctl->
nens : 1); e++) {
11474 static double work[2 *
NCSI], work2[2 *
NCSI];
11475 int n_obs = cx[e] + cy[e];
11476 int n_for = cx[e] + cz[e];
11477 double cx_rd = (ct[e] > 0) ? (1. * n_obs * n_for) / ct[e] : NAN;
11478 double bias = (n_obs > 0) ? 100. * n_for / n_obs : NAN;
11479 double pod = (n_obs > 0) ? 100. * cx[e] / n_obs : NAN;
11480 double far = (n_for > 0) ? 100. * cz[e] / n_for : NAN;
11482 (cx[e] + cy[e] + cz[e] >
11483 0) ? 100. * cx[e] / (cx[e] + cy[e] + cz[e]) : NAN;
11485 (cx[e] + cy[e] + cz[e] - cx_rd >
11486 0) ? 100. * (cx[e] - cx_rd) / (cx[e] + cy[e] + cz[e] - cx_rd) : NAN;
11487 double rho_p = gsl_stats_correlation(x, 1, y, 1, (
size_t) n[e]);
11488 double rho_s = gsl_stats_spearman(x, 1, y, 1, (
size_t) n[e], work);
11489 for (
int i = 0; i < n[e]; i++) {
11490 work[i] = x[i] - y[i];
11491 work2[i] = (obsstdn[i] != 0) ? work[i] / obsstdn[i] : 0;
11493 double mean = gsl_stats_mean(work, 1, (
size_t) n[e]);
11494 double rmse = gsl_stats_sd_with_fixed_mean(work, 1, (
size_t) n[e], 0.0);
11495 double absdev = gsl_stats_absdev_m(work, 1, (
size_t) n[e], 0.0);
11496 double loglikelihood = gsl_stats_tss(work2, 1, (
size_t) n[e]) * -0.5;
11500 "%.2f %d %d %d %d %d %d %g %g %g %g %g %g %g %g %g %g %g %g %d\n",
11501 t, ensemble ? e : -999, cx[e], cy[e], cz[e], n_obs, n_for, bias,
11502 pod, far, csi, cx_rd, ets, rho_p, rho_s, mean, rmse, absdev,
11503 loglikelihood, n[e]);
11506 ct[e] = cx[e] = cy[e] = cz[e] = n[e] = 0;
11535 const char *filename,
11545 static int n[
NENS];
11552 ERRMSG(
"Missing ensemble IDs!");
11555 const double t0 = t - 0.5 * ctl->
dt_mod;
11556 const double t1 = t + 0.5 * ctl->
dt_mod;
11559 for (
int i = 0; i <
NENS; i++) {
11560 for (
int iq = 0; iq < ctl->
nq; iq++)
11561 qm[iq][i] = qs[iq][i] = 0;
11562 xm[i][0] = xm[i][1] = xm[i][2] = zm[i] = 0;
11567 for (
int ip = 0; ip < atm->
np; ip++) {
11570 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
11575 ERRMSG(
"Ensemble ID is out of range!");
11579 for (
int iq = 0; iq < ctl->
nq; iq++) {
11580 qm[iq][ctl->
qnt_ens] += atm->
q[iq][ip];
11591 LOG(1,
"Write ensemble data: %s", filename);
11592 if (!(out = fopen(filename,
"w")))
11593 ERRMSG(
"Cannot create file!");
11597 "# $1 = time [s]\n"
11598 "# $2 = altitude [km]\n"
11599 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
11600 for (
int iq = 0; iq < ctl->
nq; iq++)
11601 fprintf(out,
"# $%d = %s (mean) [%s]\n", 5 + iq,
11603 for (
int iq = 0; iq < ctl->
nq; iq++)
11604 fprintf(out,
"# $%d = %s (sigma) [%s]\n", 5 + ctl->
nq + iq,
11606 fprintf(out,
"# $%d = number of members\n\n", 5 + 2 * ctl->
nq);
11609 for (
int i = 0; i <
NENS; i++)
11611 cart2geo(xm[i], &dummy, &lon, &lat);
11612 fprintf(out,
"%.2f %g %g %g", t, zm[i] / n[i], lon, lat);
11613 for (
int iq = 0; iq < ctl->
nq; iq++) {
11615 fprintf(out, ctl->
qnt_format[iq], qm[iq][i] / n[i]);
11617 for (
int iq = 0; iq < ctl->
nq; iq++) {
11619 double var = qs[iq][i] / n[i] -
SQR(qm[iq][i] / n[i]);
11620 fprintf(out, ctl->
qnt_format[iq], (var > 0 ? sqrt(var) : 0));
11622 fprintf(out,
" %d\n", n[i]);
11632 const char *filename,
11639 static double kz[
EP], kw[
EP];
11643 double *cd, *mean[
NQ], *sigma[
NQ], *vmr_impl, *z, *lon, *lat, *area, *press;
11645 int *ixs, *iys, *izs, *np;
11651 LOG(1,
"Write grid data: %s", filename);
11664 for (
int iq = 0; iq < ctl->
nq; iq++) {
11665 ALLOC(mean[iq],
double,
11667 ALLOC(sigma[iq],
double,
11670 ALLOC(vmr_impl,
double,
11678 ALLOC(area,
double,
11680 ALLOC(press,
double,
11697#pragma omp parallel
for default(shared)
11698 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
11699 z[iz] = ctl->
grid_z0 + dz * (iz + 0.5);
11700 press[iz] =
P(z[iz]);
11704 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
11705 lon[ix] = ctl->
grid_lon0 + dlon * (ix + 0.5);
11706#pragma omp parallel for default(shared)
11707 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
11708 lat[iy] = ctl->
grid_lat0 + dlat * (iy + 0.5);
11709 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
11713 const double t0 = t - 0.5 * ctl->
dt_mod;
11714 const double t1 = t + 0.5 * ctl->
dt_mod;
11717#pragma omp parallel for default(shared)
11718 for (
int ip = 0; ip < atm->
np; ip++) {
11719 ixs[ip] = (int) ((atm->
lon[ip] - ctl->
grid_lon0) / dlon);
11720 iys[ip] = (int) ((atm->
lat[ip] - ctl->
grid_lat0) / dlat);
11721 izs[ip] = (int) ((
Z(atm->
p[ip]) - ctl->
grid_z0) / dz);
11722 if (atm->
time[ip] < t0 || atm->
time[ip] > t1
11723 || ixs[ip] < 0 || ixs[ip] >= ctl->
grid_nx
11724 || iys[ip] < 0 || iys[ip] >= ctl->
grid_ny
11725 || izs[ip] < 0 || izs[ip] >= ctl->
grid_nz)
11730 for (
int ip = 0; ip < atm->
np; ip++)
11731 if (izs[ip] >= 0) {
11736 for (
int iq = 0; iq < ctl->
nq; iq++) {
11737 mean[iq][idx] += kernel * atm->
q[iq][ip];
11738 sigma[iq][idx] +=
SQR(kernel * atm->
q[iq][ip]);
11743#pragma omp parallel for default(shared)
11744 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
11745 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
11746 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
11753 if (ctl->
qnt_m >= 0)
11754 cd[idx] = mean[ctl->
qnt_m][idx] / (1e6 * area[iy]);
11757 vmr_impl[idx] = NAN;
11758 if (ctl->
qnt_m >= 0 && ctl->
molmass > 0 && met0 != NULL
11761 if (mean[ctl->
qnt_m][idx] > 0) {
11767 lon[ix], lat[iy], &temp, ci, cw, 1);
11771 MA / ctl->
molmass * cd[idx] / (
RHO(press[iz], temp) * dz * 1e3);
11777 for (
int iq = 0; iq < ctl->
nq; iq++) {
11778 mean[iq][idx] /= np[idx];
11779 double var = sigma[iq][idx] / np[idx] -
SQR(mean[iq][idx]);
11780 sigma[iq][idx] = (var > 0 ? sqrt(var) : 0);
11782 for (
int iq = 0; iq < ctl->
nq; iq++) {
11783 mean[iq][idx] = NAN;
11784 sigma[iq][idx] = NAN;
11791 t, z, lon, lat, area, dz, np);
11796 t, z, lon, lat, area, dz, np);
11800 ERRMSG(
"Grid data format GRID_TYPE unknown!");
11804 for (
int iq = 0; iq < ctl->
nq; iq++) {
11823 const char *filename,
11828 const double *vmr_impl,
11833 const double *area,
11843 if (!(out = popen(
"gnuplot",
"w")))
11844 ERRMSG(
"Cannot create pipe to gnuplot!");
11847 fprintf(out,
"set out \"%s.png\"\n", filename);
11851 int year, mon, day, hour, min, sec;
11852 jsec2time(t, &year, &mon, &day, &hour, &min, &sec, &r);
11853 fprintf(out,
"timestr=\"%d-%02d-%02d, %02d:%02d UTC\"\n",
11854 year, mon, day, hour, min);
11860 ERRMSG(
"Cannot open file!");
11861 while (fgets(line,
LEN, in))
11862 fprintf(out,
"%s", line);
11869 if (!(out = fopen(filename,
"w")))
11870 ERRMSG(
"Cannot create file!");
11875 "# $1 = time [s]\n"
11876 "# $2 = altitude [km]\n"
11877 "# $3 = longitude [deg]\n"
11878 "# $4 = latitude [deg]\n"
11879 "# $5 = surface area [km^2]\n"
11880 "# $6 = layer depth [km]\n"
11881 "# $7 = column density (implicit) [kg/m^2]\n"
11882 "# $8 = volume mixing ratio (implicit) [ppv]\n"
11883 "# $9 = number of particles [1]\n");
11884 for (
int iq = 0; iq < ctl->
nq; iq++)
11885 fprintf(out,
"# $%i = %s (mean) [%s]\n", 10 + iq, ctl->
qnt_name[iq],
11888 for (
int iq = 0; iq < ctl->
nq; iq++)
11889 fprintf(out,
"# $%i = %s (stddev) [%s]\n", 10 + ctl->
nq + iq,
11891 fprintf(out,
"\n");
11894 for (
int ix = 0; ix < ctl->
grid_nx; ix++) {
11896 fprintf(out,
"\n");
11897 for (
int iy = 0; iy < ctl->
grid_ny; iy++) {
11899 fprintf(out,
"\n");
11900 for (
int iz = 0; iz < ctl->
grid_nz; iz++) {
11903 fprintf(out,
"%.2f %g %g %g %g %g %g %g %d", t, z[iz], lon[ix],
11904 lat[iy], area[iy], dz, cd[idx], vmr_impl[idx], np[idx]);
11905 for (
int iq = 0; iq < ctl->
nq; iq++) {
11907 fprintf(out, ctl->
qnt_format[iq], mean[iq][idx]);
11910 for (
int iq = 0; iq < ctl->
nq; iq++) {
11912 fprintf(out, ctl->
qnt_format[iq], sigma[iq][idx]);
11914 fprintf(out,
"\n");
11927 const char *filename,
11932 const double *vmr_impl,
11937 const double *area,
11941 char longname[2 *
LEN], varname[2 *
LEN];
11945 int *help2, ncid, dimid[10], varid;
11947 size_t start[2], count[2];
11950 ALLOC(help,
double,
11956 NC(nc_create(filename, NC_NETCDF4, &ncid));
11959 NC(nc_def_dim(ncid,
"time", 1, &dimid[0]));
11960 NC(nc_def_dim(ncid,
"z", (
size_t) ctl->
grid_nz, &dimid[1]));
11961 NC(nc_def_dim(ncid,
"lat", (
size_t) ctl->
grid_ny, &dimid[2]));
11962 NC(nc_def_dim(ncid,
"lon", (
size_t) ctl->
grid_nx, &dimid[3]));
11963 NC(nc_def_dim(ncid,
"dz", 1, &dimid[4]));
11966 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &dimid[0],
"time",
11967 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
11968 NC_DEF_VAR(
"z", NC_DOUBLE, 1, &dimid[1],
"altitude",
"km", 0, 0);
11969 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &dimid[2],
"latitude",
"degrees_north", 0,
11971 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &dimid[3],
"longitude",
"degrees_east", 0,
11973 NC_DEF_VAR(
"dz", NC_DOUBLE, 1, &dimid[1],
"layer depth",
"km", 0, 0);
11974 NC_DEF_VAR(
"area", NC_DOUBLE, 1, &dimid[2],
"surface area",
"km**2", 0, 0);
11976 NC_DEF_VAR(
"cd", NC_FLOAT, 4, dimid,
"column density",
"kg m**-2",
11979 "volume mixing ratio (implicit)",
"ppv", ctl->
grid_nc_level, 0);
11980 NC_DEF_VAR(
"np", NC_INT, 4, dimid,
"number of particles",
"1", 0, 0);
11981 for (
int iq = 0; iq < ctl->
nq; iq++) {
11982 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
11983 sprintf(longname,
"%s (mean)", ctl->
qnt_longname[iq]);
11987 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
11988 sprintf(longname,
"%s (stddev)", ctl->
qnt_longname[iq]);
11994 NC(nc_enddef(ncid));
12004 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12005 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12006 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12011 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12012 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12013 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12018 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12019 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12020 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12025 for (
int iq = 0; iq < ctl->
nq; iq++) {
12026 sprintf(varname,
"%s_mean", ctl->
qnt_name[iq]);
12027 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12028 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12029 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12036 for (
int iq = 0; iq < ctl->
nq; iq++) {
12037 sprintf(varname,
"%s_stddev", ctl->
qnt_name[iq]);
12038 for (
int ix = 0; ix < ctl->
grid_nx; ix++)
12039 for (
int iy = 0; iy < ctl->
grid_ny; iy++)
12040 for (
int iz = 0; iz < ctl->
grid_nz; iz++)
12047 NC(nc_close(ncid));
12057 const char *filename,
12063 if (!(out = fopen(filename,
"w")))
12064 ERRMSG(
"Cannot create file!");
12154 ERRMSG(
"Number of meteo variables doesn't match!");
12172 const char *varname) {
12181 for (
int ix = 0; ix < met->
nx; ix++)
12182 for (
int iy = 0; iy < met->
ny; iy++)
12183 help[
ARRAY_2D(ix, iy, met->
ny)] = var[ix][iy];
12186 LOG(2,
"Write 2-D variable: %s (uncompressed)", varname);
12188 (
size_t) (met->
nx * met->
ny),
12202 const char *varname,
12203 const int precision,
12204 const double tolerance) {
12213#pragma omp parallel for default(shared) collapse(2)
12214 for (
int ix = 0; ix < met->
nx; ix++)
12215 for (
int iy = 0; iy < met->
ny; iy++)
12216 for (
int ip = 0; ip < met->
np; ip++)
12217 help[
ARRAY_3D(ix, iy, met->
ny, ip, met->
np)] = var[ix][iy][ip];
12221 LOG(2,
"Write 3-D variable: %s (uncompressed)", varname);
12223 (
size_t) (met->
nx * met->
ny * met->
np),
12230 (
size_t) met->
np, 0, out);
12238 FWRITE(&tolerance,
double,
12242 tolerance, 0, out);
12257 (
size_t) met->
np, 0, out);
12263 ERRMSG(
"MET_TYPE not supported!");
12264 LOG(3,
"%d %g", precision, tolerance);
12274 const char *filename,
12280 size_t start[4], count[4];
12281 nc_create(filename, NC_NETCDF4, &ncid);
12284 int tid, lonid, latid, levid;
12285 NC(nc_def_dim(ncid,
"time", 1, &tid));
12286 NC(nc_def_dim(ncid,
"lon", (
size_t) met->
nx, &lonid));
12287 NC(nc_def_dim(ncid,
"lat", (
size_t) met->
ny, &latid));
12288 NC(nc_def_dim(ncid,
"lev", (
size_t) met->
np, &levid));
12291 NC_DEF_VAR(
"time", NC_DOUBLE, 1, &tid,
"time",
12292 "seconds since 2000-01-01 00:00:00 UTC", 0, 0);
12293 NC_DEF_VAR(
"lon", NC_DOUBLE, 1, &lonid,
"longitude",
"degrees_east", 0, 0);
12294 NC_DEF_VAR(
"lat", NC_DOUBLE, 1, &latid,
"latitude",
"degrees_north", 0, 0);
12295 NC_DEF_VAR(
"lev", NC_DOUBLE, 1, &levid,
"pressure",
"Pa", 0, 0);
12298 int dimid2[2] = { latid, lonid };
12299 NC_DEF_VAR(
"sp", NC_FLOAT, 2, dimid2,
"Surface pressure",
"Pa",
12301 NC_DEF_VAR(
"z", NC_FLOAT, 2, dimid2,
"Geopotential",
"m**2 s**-2",
12303 NC_DEF_VAR(
"t2m", NC_FLOAT, 2, dimid2,
"2 metre temperature",
"K",
12305 NC_DEF_VAR(
"u10m", NC_FLOAT, 2, dimid2,
"10 metre U wind component",
12307 NC_DEF_VAR(
"v10m", NC_FLOAT, 2, dimid2,
"10 metre V wind component",
12310 "Instantaneous eastward turbulent surface stress",
"N m**-2",
12313 "Instantaneous northward turbulent surface stress",
"N m**-2",
12316 "Instantaneous surface sensible heat flux",
"W m**-1",
12318 NC_DEF_VAR(
"lsm", NC_FLOAT, 2, dimid2,
"Land/sea mask",
"-",
12320 NC_DEF_VAR(
"sstk", NC_FLOAT, 2, dimid2,
"Sea surface temperature",
"K",
12322 NC_DEF_VAR(
"blp", NC_FLOAT, 2, dimid2,
"Boundary layer pressure",
"Pa",
12324 NC_DEF_VAR(
"pt", NC_FLOAT, 2, dimid2,
"Tropopause pressure",
"Pa",
12326 NC_DEF_VAR(
"tt", NC_FLOAT, 2, dimid2,
"Tropopause temperature",
"K",
12328 NC_DEF_VAR(
"zt", NC_FLOAT, 2, dimid2,
"Tropopause height",
"m",
12330 NC_DEF_VAR(
"h2ot", NC_FLOAT, 2, dimid2,
"Tropopause water vapor",
"ppv",
12332 NC_DEF_VAR(
"pct", NC_FLOAT, 2, dimid2,
"Cloud top pressure",
"Pa",
12334 NC_DEF_VAR(
"pcb", NC_FLOAT, 2, dimid2,
"Cloud bottom pressure",
"Pa",
12336 NC_DEF_VAR(
"cl", NC_FLOAT, 2, dimid2,
"Total column cloud water",
12339 "Pressure at lifted condensation level (LCL)",
"Pa",
12342 "Pressure at level of free convection (LFC)",
"Pa",
12345 "Pressure at equilibrium level (EL)",
"Pa", ctl->
met_nc_level,
12348 "Convective available potential energy",
"J kg**-1",
12350 NC_DEF_VAR(
"cin", NC_FLOAT, 2, dimid2,
"Convective inhibition",
12352 NC_DEF_VAR(
"o3c", NC_FLOAT, 2, dimid2,
"Total column ozone",
"DU",
12356 int dimid3[3] = { levid, latid, lonid };
12357 NC_DEF_VAR(
"t", NC_FLOAT, 3, dimid3,
"Temperature",
"K",
12359 NC_DEF_VAR(
"u", NC_FLOAT, 3, dimid3,
"U velocity",
"m s**-1",
12361 NC_DEF_VAR(
"v", NC_FLOAT, 3, dimid3,
"V velocity",
"m s**-1",
12363 NC_DEF_VAR(
"w", NC_FLOAT, 3, dimid3,
"Vertical velocity",
"Pa s**-1",
12365 NC_DEF_VAR(
"q", NC_FLOAT, 3, dimid3,
"Specific humidity",
"kg kg**-1",
12367 NC_DEF_VAR(
"o3", NC_FLOAT, 3, dimid3,
"Ozone mass mixing ratio",
12369 NC_DEF_VAR(
"clwc", NC_FLOAT, 3, dimid3,
"Cloud liquid water content",
12371 NC_DEF_VAR(
"crwc", NC_FLOAT, 3, dimid3,
"Cloud rain water content",
12373 NC_DEF_VAR(
"ciwc", NC_FLOAT, 3, dimid3,
"Cloud ice water content",
12375 NC_DEF_VAR(
"cswc", NC_FLOAT, 3, dimid3,
"Cloud snow water content",
12377 NC_DEF_VAR(
"cc", NC_FLOAT, 3, dimid3,
"Cloud cover",
"-",
12381 NC(nc_enddef(ncid));
12388 for (
int ip = 0; ip < met->
np; ip++)
12389 phelp[ip] = 100. * met->
p[ip];
12432 NC(nc_close(ncid));
12439 const char *varname,
12445 size_t start[4], count[4];
12453 for (
int ix = 0; ix < met->
nx; ix++)
12454 for (
int iy = 0; iy < met->
ny; iy++)
12455 help[
ARRAY_2D(iy, ix, met->
nx)] = scl * var[ix][iy];
12468 const char *varname,
12474 size_t start[4], count[4];
12482 for (
int ix = 0; ix < met->
nx; ix++)
12483 for (
int iy = 0; iy < met->
ny; iy++)
12484 for (
int ip = 0; ip < met->
np; ip++)
12485 help[
ARRAY_3D(ip, iy, met->
ny, ix, met->
nx)] = scl * var[ix][iy][ip];
12497 const char *filename,
12506 static double *mass, *obsmean, *rt, *rz, *rlon, *rlat, *robs, *area,
12507 dz, dlon, dlat, *lon, *lat, *z, *press, temp, vmr, h2o, o3;
12509 static int nobs, *obscount, ip, okay;
12518 if (ctl->
qnt_m < 0)
12519 ERRMSG(
"Need quantity mass!");
12523 ERRMSG(
"Specify molar mass!");
12530 ALLOC(area,
double,
12534 ALLOC(press,
double,
12540 ALLOC(rlon,
double,
12542 ALLOC(rlat,
double,
12544 ALLOC(robs,
double,
12551 LOG(1,
"Write profile data: %s", filename);
12552 if (!(out = fopen(filename,
"w")))
12553 ERRMSG(
"Cannot create file!");
12557 "# $1 = time [s]\n"
12558 "# $2 = altitude [km]\n"
12559 "# $3 = longitude [deg]\n"
12560 "# $4 = latitude [deg]\n"
12561 "# $5 = pressure [hPa]\n"
12562 "# $6 = temperature [K]\n"
12563 "# $7 = volume mixing ratio [ppv]\n"
12564 "# $8 = H2O volume mixing ratio [ppv]\n"
12565 "# $9 = O3 volume mixing ratio [ppv]\n"
12566 "# $10 = observed BT index [K]\n"
12567 "# $11 = number of observations\n");
12575 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
12576 z[iz] = ctl->
prof_z0 + dz * (iz + 0.5);
12577 press[iz] =
P(z[iz]);
12581 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
12582 lon[ix] = ctl->
prof_lon0 + dlon * (ix + 0.5);
12583 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
12584 lat[iy] = ctl->
prof_lat0 + dlat * (iy + 0.5);
12585 area[iy] = dlat * dlon *
SQR(
RE * M_PI / 180.) * cos(
DEG2RAD(lat[iy]));
12590 const double t0 = t - 0.5 * ctl->
dt_mod;
12591 const double t1 = t + 0.5 * ctl->
dt_mod;
12594 ALLOC(mass,
double,
12596 ALLOC(obsmean,
double,
12598 ALLOC(obscount,
int,
12602 for (
int i = 0; i < nobs; i++) {
12607 else if (rt[i] >= t1)
12611 if (!isfinite(robs[i]))
12615 int ix = (int) ((rlon[i] - ctl->
prof_lon0) / dlon);
12616 int iy = (int) ((rlat[i] - ctl->
prof_lat0) / dlat);
12619 if (ix < 0 || ix >= ctl->
prof_nx || iy < 0 || iy >= ctl->
prof_ny)
12624 obsmean[idx] += robs[i];
12629 for (ip = 0; ip < atm->
np; ip++) {
12632 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
12636 int ix = (int) ((atm->
lon[ip] - ctl->
prof_lon0) / dlon);
12637 int iy = (int) ((atm->
lat[ip] - ctl->
prof_lat0) / dlat);
12638 int iz = (int) ((
Z(atm->
p[ip]) - ctl->
prof_z0) / dz);
12641 if (ix < 0 || ix >= ctl->
prof_nx ||
12647 mass[idx] += atm->
q[ctl->
qnt_m][ip];
12651 for (
int ix = 0; ix < ctl->
prof_nx; ix++)
12652 for (
int iy = 0; iy < ctl->
prof_ny; iy++) {
12654 if (obscount[idx2] > 0) {
12658 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
12660 if (mass[idx3] > 0) {
12669 fprintf(out,
"\n");
12672 for (
int iz = 0; iz < ctl->
prof_nz; iz++) {
12677 lon[ix], lat[iy], &temp, ci, cw, 1);
12679 lon[ix], lat[iy], &h2o, ci, cw, 0);
12681 lon[ix], lat[iy], &o3, ci, cw, 0);
12686 / (
RHO(press[iz], temp) * area[iy] * dz * 1e9);
12689 fprintf(out,
"%.2f %g %g %g %g %g %g %g %g %g %d\n",
12690 t, z[iz], lon[ix], lat[iy], press[iz], temp, vmr, h2o, o3,
12691 obsmean[idx2] / obscount[idx2], obscount[idx2]);
12724 const char *filename,
12733 static double area, dlat, rmax2, *rt, *rz, *rlon, *rlat, *robs, kz[
EP],
12736 static int nobs, nk;
12749 ALLOC(rlon,
double,
12751 ALLOC(rlat,
double,
12753 ALLOC(robs,
double,
12764 LOG(1,
"Write sample data: %s", filename);
12765 if (!(out = fopen(filename,
"w")))
12766 ERRMSG(
"Cannot create file!");
12770 "# $1 = time [s]\n"
12771 "# $2 = altitude [km]\n"
12772 "# $3 = longitude [deg]\n"
12773 "# $4 = latitude [deg]\n"
12774 "# $5 = surface area [km^2]\n"
12775 "# $6 = layer depth [km]\n"
12776 "# $7 = number of particles [1]\n"
12777 "# $8 = column density [kg/m^2]\n"
12778 "# $9 = volume mixing ratio [ppv]\n"
12779 "# $10 = observed BT index [K]\n\n");
12784 area = M_PI * rmax2;
12788 const double t0 = t - 0.5 * ctl->
dt_mod;
12789 const double t1 = t + 0.5 * ctl->
dt_mod;
12792 for (
int i = 0; i < nobs; i++) {
12797 else if (rt[i] >= t1)
12802 geo2cart(0, rlon[i], rlat[i], x0);
12805 const double rp =
P(rz[i]);
12806 const double ptop =
P(rz[i] + ctl->
sample_dz);
12807 const double pbot =
P(rz[i] - ctl->
sample_dz);
12815 for (
int ip = 0; ip < atm->
np; ip++) {
12818 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
12822 if (fabs(rlat[i] - atm->
lat[ip]) > dlat)
12828 if (
DIST2(x0, x1) > rmax2)
12833 if (atm->
p[ip] > pbot || atm->
p[ip] < ptop)
12837 if (ctl->
qnt_m >= 0)
12844 const double cd = mass / (1e6 * area);
12855 rlon[i], rlat[i], &temp, ci, cw, 1);
12864 fprintf(out,
"%.2f %g %g %g %g %g %d %g %g %g\n", rt[i], rz[i],
12865 rlon[i], rlat[i], area, ctl->
sample_dz, np, cd, vmr, robs[i]);
12886 const char *filename,
12893 static double rmax2, x0[3], x1[3];
12902 LOG(1,
"Write station data: %s", filename);
12905 if (!(out = fopen(filename,
"w")))
12906 ERRMSG(
"Cannot create file!");
12910 "# $1 = time [s]\n"
12911 "# $2 = altitude [km]\n"
12912 "# $3 = longitude [deg]\n" "# $4 = latitude [deg]\n");
12913 for (
int iq = 0; iq < ctl->
nq; iq++)
12914 fprintf(out,
"# $%i = %s [%s]\n", (iq + 5),
12916 fprintf(out,
"\n");
12924 const double t0 = t - 0.5 * ctl->
dt_mod;
12925 const double t1 = t + 0.5 * ctl->
dt_mod;
12928 for (
int ip = 0; ip < atm->
np; ip++) {
12931 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
12947 if (
DIST2(x0, x1) > rmax2)
12955 fprintf(out,
"%.2f %g %g %g",
12956 atm->
time[ip],
Z(atm->
p[ip]), atm->
lon[ip], atm->
lat[ip]);
12957 for (
int iq = 0; iq < ctl->
nq; iq++) {
12959 fprintf(out, ctl->
qnt_format[iq], atm->
q[iq][ip]);
12961 fprintf(out,
"\n");
12972 const char *filename,
12983 LOG(1,
"Write VTK data: %s", filename);
12986 const double t0 = t - 0.5 * ctl->
dt_mod;
12987 const double t1 = t + 0.5 * ctl->
dt_mod;
12990 if (!(out = fopen(filename,
"w")))
12991 ERRMSG(
"Cannot create file!");
12995 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
12996 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13003 "# vtk DataFile Version 3.0\n"
13004 "vtk output\n" "ASCII\n" "DATASET POLYDATA\n");
13007 fprintf(out,
"POINTS %d float\n", np);
13009 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13010 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13014 const double coslat = cos(
DEG2RAD(atm->
lat[ip]));
13015 const double x = radius * coslat * cos(
DEG2RAD(atm->
lon[ip]));
13016 const double y = radius * coslat * sin(
DEG2RAD(atm->
lon[ip]));
13017 const double z = radius * sin(
DEG2RAD(atm->
lat[ip]));
13018 fprintf(out,
"%g %g %g\n", x, y, z);
13021 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13022 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13024 fprintf(out,
"%g %g %g\n", atm->
lon[ip], atm->
lat[ip],
13029 fprintf(out,
"POINT_DATA %d\n", np);
13030 for (
int iq = 0; iq < ctl->
nq; iq++) {
13031 fprintf(out,
"SCALARS %s float 1\n" "LOOKUP_TABLE default\n",
13033 for (
int ip = 0; ip < atm->
np; ip += ctl->
vtk_stride) {
13034 if (atm->
time[ip] < t0 || atm->
time[ip] > t1)
13036 fprintf(out,
"%g\n", atm->
q[iq][ip]);
13057 int npart = *nparticles;
13058#pragma acc enter data create( nparticles, particles[:DD_NPART])
13059#pragma acc update device( nparticles)
13060#pragma acc parallel loop present( atm, ctl, particles, cache, nparticles)
13061 for (
int ip = atm->
np; ip < atm->np + *nparticles; ip++)
13066 particles[ip - atm->
np].
time = atm->
time[ip];
13067 particles[ip - atm->
np].
lon = atm->
lon[ip];
13068 particles[ip - atm->
np].
lat = atm->
lat[ip];
13069 particles[ip - atm->
np].
p = atm->
p[ip];
13071 for (
int iq = 0; iq < ctl->
nq; iq++)
13072 particles[ip - atm->
np].q[iq] = atm->
q[iq][ip];
13077#pragma acc update host( particles[:npart])
13078#pragma acc exit data delete( nparticles, particles)
13094 int npart = *nparticles;
13095#pragma acc enter data create(nparticles, particles[:DD_NPART])
13096#pragma acc update device(particles[:npart], nparticles)
13097#pragma acc data present(atm, ctl, cache, particles, nparticles)
13098#pragma acc parallel loop
13099 for (
int ip = atm->
np; ip < atm->np + *nparticles; ip++) {
13101 atm->
time[ip] = particles[ip - atm->
np].
time;
13102 atm->
lon[ip] = particles[ip - atm->
np].
lon;
13103 atm->
lat[ip] = particles[ip - atm->
np].
lat;
13104 atm->
p[ip] = particles[ip - atm->
np].
p;
13106 for (
int iq = 0; iq < ctl->
nq; iq++)
13107 atm->
q[iq][ip] = particles[ip - atm->
np].q[iq];
13112#pragma acc exit data delete(nparticles, particles)
13115 atm->
np += *nparticles;
13116#pragma acc update device(atm->np)
13119 ERRMSG(
"Number of particles to high. Increase NP!");
13127void dd_register_MPI_type_particle(
13128 MPI_Datatype *MPI_Particle) {
13129 MPI_Datatype types[5] = { MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE,
13130 MPI_DOUBLE, MPI_DOUBLE
13132 int blocklengths[5] = { 1, 1, 1, 1,
NQ };
13133 MPI_Aint displacements[5] = { offsetof(
particle_t, time),
13139 MPI_Type_create_struct(5, blocklengths, displacements, types, MPI_Particle);
13140 MPI_Type_commit(MPI_Particle);
13147void dd_get_rect_neighbour(
13151 SELECT_TIMER(
"DD_GET_RECT_NEIGHBOUR",
"DD", NVTX_GPU);
13153 if (mpi_info->
rank + 1 == mpi_info->
size) {
13156 mpi_info->neighbours[1] =
DD_SPOLE;
13157 mpi_info->neighbours[2] =
13160 mpi_info->neighbours[3] =
13163 mpi_info->neighbours[4] =
DD_SPOLE;
13164 mpi_info->neighbours[5] =
13167 mpi_info->neighbours[6] = mpi_info->
rank - 1;
13168 mpi_info->neighbours[7] =
DD_SPOLE;
13170 }
else if (mpi_info->
rank ==
13174 mpi_info->neighbours[1] =
13176 mpi_info->neighbours[2] =
DD_NPOLE;
13178 mpi_info->neighbours[3] =
13181 mpi_info->neighbours[4] =
13184 mpi_info->neighbours[5] =
DD_NPOLE;
13186 mpi_info->neighbours[6] =
DD_NPOLE;
13187 mpi_info->neighbours[7] = mpi_info->
rank + 1;
13189 }
else if (mpi_info->
rank == 0) {
13191 mpi_info->neighbours[0] =
13193 mpi_info->neighbours[1] =
13195 mpi_info->neighbours[2] =
DD_NPOLE;
13198 mpi_info->neighbours[4] =
13200 mpi_info->neighbours[5] =
DD_NPOLE;
13202 mpi_info->neighbours[6] =
DD_NPOLE;
13203 mpi_info->neighbours[7] = mpi_info->
rank + 1;
13207 mpi_info->neighbours[0] =
13209 mpi_info->neighbours[1] =
DD_SPOLE;
13210 mpi_info->neighbours[2] =
13214 mpi_info->neighbours[4] =
DD_SPOLE;
13215 mpi_info->neighbours[5] =
13218 mpi_info->neighbours[6] = mpi_info->
rank - 1;
13219 mpi_info->neighbours[7] =
DD_SPOLE;
13224 mpi_info->neighbours[1] =
13226 mpi_info->neighbours[2] =
DD_NPOLE;
13229 mpi_info->neighbours[4] =
13231 mpi_info->neighbours[5] =
DD_NPOLE;
13233 mpi_info->neighbours[6] =
DD_NPOLE;
13234 mpi_info->neighbours[7] = mpi_info->
rank + 1;
13239 mpi_info->neighbours[1] =
DD_SPOLE;
13240 mpi_info->neighbours[2] =
13244 mpi_info->neighbours[4] =
DD_SPOLE;
13245 mpi_info->neighbours[5] =
13248 mpi_info->neighbours[6] = mpi_info->
rank - 1;
13249 mpi_info->neighbours[7] =
DD_SPOLE;
13253 mpi_info->neighbours[0] =
13255 mpi_info->neighbours[1] =
13257 mpi_info->neighbours[2] =
13261 mpi_info->neighbours[4] =
13263 mpi_info->neighbours[5] =
13266 mpi_info->neighbours[6] = mpi_info->
rank - 1;
13267 mpi_info->neighbours[7] = mpi_info->
rank + 1;
13269 }
else if (mpi_info->
rank + 1 >
13273 mpi_info->neighbours[1] =
13275 mpi_info->neighbours[2] =
13278 mpi_info->neighbours[3] =
13281 mpi_info->neighbours[4] =
13284 mpi_info->neighbours[5] =
13287 mpi_info->neighbours[6] = mpi_info->
rank - 1;
13288 mpi_info->neighbours[7] = mpi_info->
rank + 1;
13300 mpi_info->neighbours[6] = mpi_info->
rank - 1;
13301 mpi_info->neighbours[7] = mpi_info->
rank + 1;
13310void dd_communicate_particles(
13313 MPI_Datatype MPI_Particle,
13330 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
13334 MPI_Request requests_snd_nbr[8] =
13335 { MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL,
13336 MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL
13338 MPI_Request requests_rcv_nbr[8] =
13339 { MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL,
13340 MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL
13342 MPI_Request requests_snd_part[8] =
13343 { MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL,
13344 MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL
13346 MPI_Request requests_rcv_part[8] =
13347 { MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL,
13348 MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL, MPI_REQUEST_NULL
13350 MPI_Status states[8];
13353 for (
int idest = 0; idest < nneighbours; idest++) {
13356 if (neighbours[idest] < 0)
13362 for (
int ip = 0; ip < *nparticles; ip++)
13365 nbs[idest] = help_sum;
13369 MPI_Isend(&nbs[idest], 1, MPI_INT,
13370 neighbours[idest], 0, MPI_COMM_WORLD, &requests_snd_nbr[idest]);
13373 if (nbs[idest] == 0)
13382 for (
int ip = 0; ip < *nparticles; ip++) {
13383 if ((
int) particles[ip].q[ctl.
qnt_destination] == neighbours[idest]) {
13384 memcpy(&send_buffers[idest][ibs], &particles[ip],
sizeof(
particle_t));
13388 if (ibs == nbs[idest])
13395 MPI_Isend(send_buffers[idest], nbs[idest], MPI_Particle,
13396 neighbours[idest], 1, MPI_COMM_WORLD,
13397 &requests_snd_part[idest]);
13403 for (
int isourc = 0; isourc < nneighbours; isourc++) {
13406 if (neighbours[isourc] < 0) {
13407 requests_rcv_nbr[isourc] = MPI_REQUEST_NULL;
13412 MPI_Irecv(&nbr[isourc], 1, MPI_INT, neighbours[isourc], 0, MPI_COMM_WORLD,
13413 &requests_rcv_nbr[isourc]);
13418 MPI_Waitall(nneighbours, requests_rcv_nbr, states);
13421 for (
int isourc = 0; isourc < nneighbours; isourc++) {
13424 if ((neighbours[isourc] < 0) || (nbr[isourc] == 0)) {
13425 requests_rcv_part[isourc] = MPI_REQUEST_NULL;
13432 MPI_Irecv(recieve_buffers[isourc], nbr[isourc], MPI_Particle,
13433 neighbours[isourc], 1, MPI_COMM_WORLD,
13434 &requests_rcv_part[isourc]);
13439 MPI_Waitall(nneighbours, requests_rcv_part, states);
13447 for (
int isourc = 0; isourc < nneighbours; isourc++) {
13450 if (neighbours[isourc] < 0)
13454 for (
int ip = 0; ip < nbr[isourc]; ip++) {
13455 memcpy(&particles[ip + api], &recieve_buffers[isourc][ip],
13461 api += nbr[isourc];
13470 MPI_Waitall(nneighbours, requests_snd_part, states);
13471 MPI_Waitall(nneighbours, requests_snd_nbr, states);
13474 for (
int i = 0; i < nneighbours; i++) {
13476 if ((send_buffers[i] != NULL) && (nbs[i] != 0)) {
13477 free(send_buffers[i]);
13478 send_buffers[i] = NULL;
13481 if ((recieve_buffers[i] != NULL) && (nbr[i] != 0)) {
13482 free(recieve_buffers[i]);
13483 recieve_buffers[i] = NULL;
13496void dd_assign_rect_subdomains_atm(
13503 SELECT_TIMER(
"DD_ASSIGN_RECT_SUBDOMAINS",
"DD", NVTX_GPU);
13506#pragma acc enter data create(mpi_info)
13507#pragma acc update device(mpi_info->rank)
13508#pragma acc data present(atm, ctl, mpi_info, met)
13509#pragma acc parallel loop independent gang vector
13510 for (
int ip = 0; ip < atm->
np; ip++) {
13512 double lont = atm->
lon[ip];
13527#pragma acc exit data delete(mpi_info)
13531#pragma acc enter data create(mpi_info)
13532#pragma acc update device(mpi_info->neighbours[:DD_NNMAX], mpi_info->rank, mpi_info->size)
13533#pragma acc data present(atm, met, ctl, mpi_info)
13534#pragma acc parallel loop independent gang vector
13535 for (
int ip = 0; ip < atm->
np; ip++) {
13541 double lont = atm->
lon[ip];
13542 double latt = atm->
lat[ip];
13558 bound = (lont - lon_max > 90) ? 1 : 0;
13560 bound = (lon_min - lont > 90) ? 1 : 0;
13563 if ((lont >= lon_max) && (latt >= lat_max)) {
13566 }
else if ((lont >= lon_max) && (latt <= lat_min)) {
13569 }
else if ((lont <= lon_min) && (latt >= lat_max)) {
13572 }
else if ((lont <= lon_min) && (latt <= lat_min)) {
13575 }
else if (lont >= lon_max) {
13578 }
else if (lont <= lon_min) {
13581 }
else if (latt <= lat_min) {
13584 }
else if (latt >= lat_max) {
13592 if ((lont >= lon_max) && (latt >= lat_max)) {
13595 }
else if ((lont >= lon_max) && (latt <= lat_min)) {
13598 }
else if ((lont <= lon_min) && (latt >= lat_max)) {
13601 }
else if ((lont <= lon_min) && (latt <= lat_min)) {
13604 }
else if (lont >= lon_max) {
13607 }
else if (lont <= lon_min) {
13610 }
else if (latt <= lat_min) {
13613 }
else if (latt >= lat_max) {
13622#pragma acc exit data delete(mpi_info)
13636 int *dd_init_flg) {
13639 if (mpi_info->
size !=
13641 ERRMSG(
"The number of tasks and subdomains is not identical.");
13644 dd_register_MPI_type_particle(&mpi_info->MPI_Particle);
13647 dd_get_rect_neighbour(*ctl, mpi_info);
13650 dd_assign_rect_subdomains_atm(atm, *met, ctl, mpi_info, 1);
13666 int nparticles = 0;
13671 dd_assign_rect_subdomains_atm(atm, *met, ctl, mpi_info, 0);
13674 dd_sort(ctl, *met, atm, &nparticles, &mpi_info->
rank);
13682 dd_communicate_particles(particles, &nparticles, mpi_info->MPI_Particle,
13710 const int np = atm->
np;
13711 double *restrict
const a = (
double *) malloc((
size_t) np *
sizeof(double));
13712 int *restrict
const p = (
int *) malloc((
size_t) np *
sizeof(int));
13713 double amax = (met0->
nx * met0->
ny + met0->
ny) * met0->
np + met0->
np;
13716#pragma acc enter data create(a[0:np],p[0:np],amax, rank)
13717#pragma acc update device(rank, amax)
13718#pragma acc data present(ctl,met0,atm,a,p,amax,rank)
13723#pragma acc parallel loop independent gang vector
13725#pragma omp parallel for default(shared)
13727 for (
int ip = 0; ip < np; ip++) {
13744#pragma acc host_data use_device(a,p)
13749 ERRMSG(
"MPTRAC was compiled without Thrust library!");
13757 for (
int iq = 0; iq < ctl->
nq; iq++)
13763#pragma acc parallel loop reduction(+:npt) present(atm, rank, ctl)
13764 for (
int ip = 0; ip < np; ip++)
13770 int nparticlest = 0;
13771#pragma acc parallel loop reduction(+:nparticlest) present(atm, rank, ctl)
13772 for (
int ip = npt; ip < np; ip++)
13778 *nparticles = nparticlest;
13780#pragma acc update device(atm->np)
13784 (
"Number of particles to send and recieve to small. Increase DD_NPART!");
13788#pragma acc exit data delete(a,p,amax, rank)
void read_met_geopot(const ctl_t *ctl, met_t *met)
Calculates geopotential heights from meteorological data.
void read_met_nc_surface(const int ncid, const ctl_t *ctl, met_t *met)
Reads surface meteorological data from a netCDF file and stores it in the meteorological data structu...
void mptrac_write_atm(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes air parcel data to a file in various formats.
void day2doy(const int year, const int mon, const int day, int *doy)
Get day of year from date.
void read_met_extrapolate(met_t *met)
Extrapolates meteorological data.
void write_atm_clams_traj(const char *dirname, const ctl_t *ctl, const atm_t *atm, const double t)
Writes CLaMS trajectory data to a NetCDF file.
void write_met_nc_2d(const int ncid, const char *varname, met_t *met, float var[EX][EY], const float scl)
Writes a 2D meteorological variable to a NetCDF file.
void mptrac_alloc(ctl_t **ctl, cache_t **cache, clim_t **clim, met_t **met0, met_t **met1, atm_t **atm)
Allocates and initializes memory resources for MPTRAC.
void read_met_sample(const ctl_t *ctl, met_t *met)
Downsamples meteorological data based on specified parameters.
void write_met_bin_3d(FILE *out, const ctl_t *ctl, met_t *met, float var[EX][EY][EP], const char *varname, const int precision, const double tolerance)
Writes a 3-dimensional meteorological variable to a binary file.
void read_obs(const char *filename, const ctl_t *ctl, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from a file and stores it in arrays.
void module_advect(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Advances particle positions using different advection schemes.
void module_timesteps(const ctl_t *ctl, cache_t *cache, met_t *met0, atm_t *atm, const double t)
Calculate time steps for air parcels based on specified conditions.
int mptrac_read_met(const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met)
Reads meteorological data from a file, supporting multiple formats and MPI broadcasting.
void module_meteo(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Update atmospheric properties using meteorological data.
void read_clim_photo(const char *filename, clim_photo_t *photo)
Reads photolysis rates from a NetCDF file and populates the given photolysis structure.
void read_met_cloud(met_t *met)
Calculates cloud-related variables for each grid point.
void module_decay(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, atm_t *atm)
Simulate exponential decay processes for atmospheric particles.
double sedi(const double p, const double T, const double rp, const double rhop)
Calculates the sedimentation velocity of a particle in air.
void intpol_met_space_2d(const met_t *met, float array[EX][EY], const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables in 2D space.
int read_atm_nc(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a generic netCDF file and populates the given atmospheric structure.
void read_met_pbl(const ctl_t *ctl, met_t *met)
Computes the planetary boundary layer (PBL) pressure based on meteorological data.
void read_met_detrend(const ctl_t *ctl, met_t *met)
Detrends meteorological data.
int read_met_nc_2d(const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const char *varname5, const char *varname6, const ctl_t *ctl, const met_t *met, float dest[EX][EY], const float scl, const int init)
Reads a 2-dimensional meteorological variable from a NetCDF file.
void read_met_tropo(const ctl_t *ctl, const clim_t *clim, met_t *met)
Calculates the tropopause and related meteorological variables based on various methods and stores th...
void read_obs_asc(const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from an ASCII file.
void module_chem_init(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Initializes the chemistry modules by setting atmospheric composition.
int locate_reg(const double *xx, const int n, const double x)
Locate the index of the interval containing a given value in a regular grid.
void get_tropo(const int met_tropo, ctl_t *ctl, clim_t *clim, met_t *met, const double *lons, const int nx, const double *lats, const int ny, double *pt, double *zt, double *tt, double *qt, double *o3t, double *ps, double *zs)
Calculate tropopause data.
void mptrac_get_met(ctl_t *ctl, clim_t *clim, const double t, met_t **met0, met_t **met1)
Retrieves meteorological data for the specified time.
void read_met_monotonize(const ctl_t *ctl, met_t *met)
Makes zeta and pressure profiles monotone.
int read_clim_ts(const char *filename, clim_ts_t *ts)
Reads a climatological time series from a file and populates the given time series structure.
void read_met_periodic(met_t *met)
Applies periodic boundary conditions to meteorological data along longitudinal axis.
void module_timesteps_init(ctl_t *ctl, const atm_t *atm)
Initialize start time and time interval for time-stepping.
void write_ens(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes ensemble data to a file.
void module_mixing(const ctl_t *ctl, const clim_t *clim, atm_t *atm, const double t)
Update atmospheric properties through interparcel mixing.
double clim_zm(const clim_zm_t *zm, const double t, const double lat, const double p)
Interpolates monthly mean zonal mean climatological variables.
void module_mixing_help(const ctl_t *ctl, const clim_t *clim, atm_t *atm, const int *ixs, const int *iys, const int *izs, const int qnt_idx, const int use_ensemble)
Perform subgrid-scale interparcel mixing of a given quantity.
void read_clim_photo_help(const int ncid, const char *varname, const clim_photo_t *photo, double var[CP][CSZA][CO3])
Reads a 3D climatological photochemistry variable from a NetCDF file.
void read_met_ml2pl(const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname)
Reads global meteorological information from a grib file.
double clim_tropo(const clim_t *clim, const double t, const double lat)
Calculates the tropopause pressure based on climatological data.
void read_obs_nc(const char *filename, double *rt, double *rz, double *rlon, double *rlat, double *robs, int *nobs)
Reads observation data from a NetCDF file.
void read_met_bin_2d(FILE *in, const met_t *met, float var[EX][EY], const char *varname)
Reads a 2-dimensional meteorological variable from a binary file and stores it in the provided array.
int locate_irr(const double *xx, const int n, const double x)
Locate the index of the interval containing a given value in a sorted array.
void module_isosurf_init(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Initialize the isosurface module based on atmospheric data.
void level_definitions(ctl_t *ctl)
Defines pressure levels for meteorological data.
void intpol_met_4d_coord(const met_t *met0, float heights0[EX][EY][EP], float array0[EX][EY][EP], const met_t *met1, float heights1[EX][EY][EP], float array1[EX][EY][EP], const double ts, const double height, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables to a given position and time.
void write_grid_asc(const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
Writes grid data to an ASCII file.
void mptrac_update_device(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
Updates device memory for specified data structures.
void time2jsec(const int year, const int mon, const int day, const int hour, const int min, const int sec, const double remain, double *jsec)
Converts time components to seconds since January 1, 2000, 12:00:00 UTC.
void mptrac_init(ctl_t *ctl, cache_t *cache, clim_t *clim, atm_t *atm, const int ntask)
Initializes the MPTRAC model and its associated components.
void intpol_met_time_3d(const met_t *met0, float array0[EX][EY][EP], const met_t *met1, float array1[EX][EY][EP], const double ts, const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological data in 3D space and time.
void intpol_met_space_3d_ml(const met_t *met, float zs[EX][EY][EP], float array[EX][EY][EP], const double z, const double lon, const double lat, double *var)
Interpolates meteorological data in 3D space.
void fft_help(double *fcReal, double *fcImag, const int n)
Computes the Fast Fourier Transform (FFT) of a complex sequence.
void module_wet_depo(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Perform wet deposition calculations for air parcels.
void compress_pck(const char *varname, float *array, const size_t nxy, const size_t nz, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats.
double nat_temperature(const double p, const double h2o, const double hno3)
Calculates the nitric acid trihydrate (NAT) temperature.
void spline(const double *x, const double *y, const int n, const double *x2, double *y2, const int n2, const int method)
Performs spline interpolation or linear interpolation.
void module_chem_grid(const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double tt)
Computes gridded chemical tracer concentrations (volume mixing ratio) from individual air parcel mass...
double clim_photo(const double rate[CP][CSZA][CO3], const clim_photo_t *photo, const double p, const double sza, const double o3c)
Calculates the photolysis rate for a given set of atmospheric conditions.
void read_clim_zm(const char *filename, const char *varname, clim_zm_t *zm)
Reads zonally averaged climatological data from a netCDF file and populates the given structure.
void read_met_nc_grid(const char *filename, const int ncid, const ctl_t *ctl, met_t *met)
Reads meteorological grid information from a NetCDF file.
void module_sedi(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate sedimentation of particles in the atmosphere.
void timer(const char *name, const char *group, const int output)
Measures and reports elapsed time for named and grouped timers.
void write_atm_asc(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes air parcel data to an ASCII file or gnuplot.
void intpol_met_space_3d(const met_t *met, float array[EX][EY][EP], const double p, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological variables in 3D space.
void intpol_met_time_3d_ml(const met_t *met0, float zs0[EX][EY][EP], float array0[EX][EY][EP], const met_t *met1, float zs1[EX][EY][EP], float array1[EX][EY][EP], const double ts, const double p, const double lon, const double lat, double *var)
Interpolates meteorological data in both space and time.
void module_convection(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Performs convective mixing of atmospheric particles.
void read_kernel(const char *filename, double kz[EP], double kw[EP], int *nk)
Reads kernel function data from a file and populates the provided arrays.
void module_bound_cond(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Apply boundary conditions to particles based on meteorological and climatological data.
double scan_ctl(const char *filename, int argc, char *argv[], const char *varname, const int arridx, const char *defvalue, char *value)
Scans a control file or command-line arguments for a specified variable.
void module_advect_init(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Initializes the advection module by setting up pressure fields.
void module_sort_help(double *a, const int *p, const int np)
Reorder an array based on a given permutation.
float stddev(const float *data, const int n)
Calculates the standard deviation of a set of data.
void intpol_tropo_3d(const double time0, float array0[EX][EY], const double time1, float array1[EX][EY], const double lons[EX], const double lats[EY], const int nlon, const int nlat, const double time, const double lon, const double lat, const int method, double *var, double *sigma)
Interpolates tropopause data in 3D (latitude, longitude, and time).
int read_met_nc_3d(const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const ctl_t *ctl, const met_t *met, float dest[EX][EY][EP], const float scl)
Reads a 3-dimensional meteorological variable from a NetCDF file.
void read_met_bin_3d(FILE *in, const ctl_t *ctl, const met_t *met, float var[EX][EY][EP], const char *varname, const float bound_min, const float bound_max)
Reads 3D meteorological data from a binary file, potentially using different compression methods.
int locate_irr_float(const float *xx, const int n, const double x, const int ig)
Locate the index of the interval containing a given value in an irregularly spaced array.
double time_from_filename(const char *filename, const int offset)
Extracts and converts a timestamp from a filename to Julian seconds.
void write_prof(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes profile data to a specified file.
void mptrac_read_clim(const ctl_t *ctl, clim_t *clim)
Reads various climatological data and populates the given climatology structure.
double tropo_weight(const clim_t *clim, const atm_t *atm, const int ip)
Computes a weighting factor based on tropopause pressure.
void write_met_nc(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a NetCDF file.
void module_rng_init(const int ntask)
Initialize random number generators for parallel tasks.
int mptrac_read_atm(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a specified file into the given atmospheric structure.
void mptrac_update_host(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t **met0, met_t **met1, const atm_t *atm)
Updates host memory for specified data structures.
void mptrac_write_output(const char *dirname, const ctl_t *ctl, met_t *met0, met_t *met1, atm_t *atm, const double t)
Writes various types of output data to files in a specified directory.
double clim_oh(const ctl_t *ctl, const clim_t *clim, const double t, const double lon, const double lat, const double p)
Calculates the hydroxyl radical (OH) concentration from climatology data, with an optional diurnal co...
void read_met_ozone(met_t *met)
Calculates the total column ozone from meteorological ozone data.
void mptrac_free(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Frees memory resources allocated for MPTRAC.
void clim_tropo_init(clim_t *clim)
Initializes the tropopause data in the climatology structure.
void module_rng(const ctl_t *ctl, double *rs, const size_t n, const int method)
Generate random numbers using various methods and distributions.
void get_met_help(const ctl_t *ctl, const double t, const int direct, const char *metbase, const double dt_met, char *filename)
Generates a formatted filename for meteorological data files based on the input parameters.
void write_station(const char *filename, const ctl_t *ctl, atm_t *atm, const double t)
Writes station data to a specified file.
void cart2geo(const double *x, double *z, double *lon, double *lat)
State variables of cuRAND random number generator.
double sza_calc(const double sec, const double lon, const double lat)
Calculates the solar zenith angle.
void doy2day(const int year, const int doy, int *mon, int *day)
Converts a given day of the year (DOY) to a date (month and day).
void intpol_met_time_2d(const met_t *met0, float array0[EX][EY], const met_t *met1, float array1[EX][EY], const double ts, const double lon, const double lat, double *var, int *ci, double *cw, const int init)
Interpolates meteorological data in 2D space and time.
void module_position(const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Update the positions and pressure levels of atmospheric particles.
void clim_oh_diurnal_correction(const ctl_t *ctl, clim_t *clim)
Applies a diurnal correction to the hydroxyl radical (OH) concentration in climatology data.
void locate_vert(float profiles[EX][EY][EP], const int np, const int lon_ap_ind, const int lat_ap_ind, const double height_ap, int *ind)
Locate the four vertical indizes of a box for a given height value.
void write_met_bin_2d(FILE *out, met_t *met, float var[EX][EY], const char *varname)
Writes a 2-dimensional meteorological variable to a binary file.
void read_met_pv(met_t *met)
Calculates potential vorticity (PV) from meteorological data.
int read_atm_bin(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a binary file and populates the given atmospheric structure.
void get_met_replace(char *orig, char *search, char *repl)
Replaces occurrences of a substring in a string with another substring.
void module_diff_meso(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate mesoscale diffusion for atmospheric particles.
void module_sort(const ctl_t *ctl, met_t *met0, atm_t *atm)
Sort particles according to box index.
int read_met_nc(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a NetCDF file and processes it.
double clim_ts(const clim_ts_t *ts, const double t)
Interpolates a time series of climatological variables.
void jsec2time(const double jsec, int *year, int *mon, int *day, int *hour, int *min, int *sec, double *remain)
Converts Julian seconds to calendar date and time components.
int read_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a binary file.
void mptrac_run_timestep(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t **met0, met_t **met1, atm_t *atm, double t)
Executes a single timestep of the MPTRAC model simulation.
void write_atm_clams(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a NetCDF file in the CLaMS format.
void module_diff_turb(const ctl_t *ctl, cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Applies turbulent diffusion processes to atmospheric particles.
int read_atm_clams(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads atmospheric data from a CLAMS NetCDF file.
void write_vtk(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes VTK (Visualization Toolkit) data to a specified file.
void module_tracer_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Simulate chemical reactions involving long-lived atmospheric tracers.
void mptrac_read_ctl(const char *filename, int argc, char *argv[], ctl_t *ctl)
Reads control parameters from a configuration file and populates the given structure.
void read_met_polar_winds(met_t *met)
Applies a fix for polar winds in meteorological data.
void module_h2o2_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Perform chemical reactions involving H2O2 within cloud particles.
void write_grid_nc(const char *filename, const ctl_t *ctl, const double *cd, double *mean[NQ], double *sigma[NQ], const double *vmr_impl, const double t, const double *z, const double *lon, const double *lat, const double *area, const double dz, const int *np)
Writes grid data to a NetCDF file.
double pbl_weight(const ctl_t *ctl, const atm_t *atm, const int ip, const double pbl, const double ps)
Computes a weighting factor based on planetary boundary layer pressure.
void module_diff_pbl(const ctl_t *ctl, cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Computes particle diffusion within the planetary boundary layer (PBL).
void write_met_nc_3d(const int ncid, const char *varname, met_t *met, float var[EX][EY][EP], const float scl)
Writes a 3D meteorological variable to a NetCDF file.
void module_isosurf(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Apply the isosurface module to adjust atmospheric properties.
void module_oh_chem(const ctl_t *ctl, const cache_t *cache, const clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
Perform hydroxyl chemistry calculations for atmospheric particles.
void geo2cart(const double z, const double lon, const double lat, double *x)
Converts geographic coordinates (longitude, latitude, altitude) to Cartesian coordinates.
double kernel_weight(const double kz[EP], const double kw[EP], const int nk, const double p)
Calculates the kernel weight based on altitude and given kernel data.
void read_met_nc_levels(const int ncid, const ctl_t *ctl, met_t *met)
Reads meteorological variables at different vertical levels from a NetCDF file.
int read_atm_asc(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from an ASCII file and populates the given atmospheric structure.
void intpol_check_lon_lat(const double *lons, const int nlon, const double *lats, const int nlat, const double lon, const double lat, double *lon2, double *lat2)
Adjusts longitude and latitude to ensure they fall within valid bounds.
void write_sample(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes sample data to a specified file.
void write_grid(const char *filename, const ctl_t *ctl, met_t *met0, met_t *met1, const atm_t *atm, const double t)
Writes grid data to a file in ASCII or netCDF format.
void module_dry_depo(const ctl_t *ctl, const cache_t *cache, met_t *met0, met_t *met1, atm_t *atm)
Simulate dry deposition of atmospheric particles.
void write_met_bin(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data in binary format to a specified file.
void write_atm_bin(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a binary file.
void read_met_cape(const ctl_t *ctl, const clim_t *clim, met_t *met)
Calculates Convective Available Potential Energy (CAPE) for each grid point.
void mptrac_write_met(const char *filename, const ctl_t *ctl, met_t *met)
Writes meteorological data to a file, supporting multiple formats and compression options.
double lapse_rate(const double t, const double h2o)
Calculates the moist adiabatic lapse rate in Kelvin per kilometer.
void write_csi(const char *filename, const ctl_t *ctl, const atm_t *atm, const double t)
Writes Critical Success Index (CSI) data to a file.
void write_atm_nc(const char *filename, const ctl_t *ctl, const atm_t *atm)
Writes air parcel data to a NetCDF file.
MPTRAC library declarations.
#define NN(x0, y0, x1, y1, x)
Perform nearest-neighbor interpolation.
void compress_zstd(const char *varname, float *array, const size_t n, const int decompress, const int level, FILE *inout)
Compresses or decompresses a float array using Zstandard (ZSTD).
#define LEN
Maximum length of ASCII data lines.
#define RE
Mean radius of Earth [km].
#define TVIRT(t, h2o)
Compute virtual temperature.
#define DD_NPOLE
Constants indicating the North pole [-].
#define ARRAY_3D(ix, iy, ny, iz, nz)
Compute the linear index of a 3D array element.
#define PARTICLE_LOOP(ip0, ip1, check_dt,...)
Loop over particle indices with OpenACC acceleration.
#define MA
Molar mass of dry air [g/mol].
#define AVO
Avogadro constant [1/mol].
#define KB
Boltzmann constant [kg m^2/(K s^2)].
#define MH2O
Molar mass of water vapor [g/mol].
#define METVAR
Number of 3-D meteorological variables.
#define NENS
Maximum number of data points for ensemble analysis.
#define FWRITE(ptr, type, size, out)
Write data from memory to a file stream.
#define PW(p, h2o)
Calculate partial water vapor pressure.
#define H0
Scale height [km].
#define NC_PUT_ATT_GLOBAL(attname, text)
Add a global text attribute to a NetCDF file.
int read_met_nc_dd(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a NetCDF file and processes it.
#define MOLEC_DENS(p, t)
Calculate the density of a gas molecule.
int read_met_nc_3d_dd(const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const ctl_t *ctl, const met_t *met, float dest[EX][EY][EP], const float scl)
Reads a 3-dimensional meteorological variable from a NetCDF file.
#define DD_SPOLE
Constants indicating the South pole [-].
#define LAPSE(p1, t1, p2, t2)
Calculate lapse rate.
#define NC(cmd)
Execute a NetCDF command and check for errors.
#define ECC_READ_3D(variable, level, target, scaling_factor, found_flag)
Writes 3D data from a grib message into the met struct.
#define RA
Specific gas constant of dry air [J/(kg K)].
#define EP_GLOB
Maximum number of pressure levels for meteo data.
#define KARMAN
Karman's constant.
#define INTPOL_INIT
Initialize arrays for interpolation.
#define MIN(a, b)
Macro to determine the minimum of two values.
#define ERRMSG(...)
Print an error message with contextual information and terminate the program.
#define NC_PUT_INT(varname, ptr, hyperslab)
Write integer data to a NetCDF variable.
void compress_cms(const ctl_t *ctl, const char *varname, float *array, const size_t nx, const size_t ny, const size_t np, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using a custom multiscale compression algorithm.
void compress_zfp(const char *varname, float *array, const int nx, const int ny, const int nz, const int precision, const double tolerance, const int decompress, FILE *inout)
Compresses or decompresses a 3D array of floats using the ZFP library.
#define EY
Maximum number of latitudes for meteo data.
void dd_particles2atm(atm_t *atm, particle_t *particles, ctl_t *ctl, int *nparticles, cache_t *cache)
Converts particle data to atmospheric data.
#define SH(h2o)
Compute specific humidity from water vapor volume mixing ratio.
#define INTPOL_3D(var, init)
Perform 3D interpolation for a meteorological variable.
#define NOBS
Maximum number of observation data points.
#define NTHREADS
Maximum number of OpenMP threads.
#define ARRAY_2D(ix, iy, ny)
Macro for computing the linear index of a 2D array element.
#define Z(p)
Convert pressure to altitude.
#define P(z)
Compute pressure at given altitude.
#define LV
Latent heat of vaporization of water [J/kg].
#define EY_GLOB
Maximum number of global latitudes for meteo data.
#define G0
Standard gravity [m/s^2].
#define CP
Maximum number of pressure levels for climatological data.
#define NQ
Maximum number of quantities per data point.
#define FREAD(ptr, type, size, in)
Read data from a file stream and store it in memory.
#define DX2DEG(dx, lat)
Convert a distance in kilometers to degrees longitude at a given latitude.
#define DEG2DY(dlat)
Convert a latitude difference to a distance in the y-direction (north-south).
#define EX
Maximum number of longitudes for meteo data.
#define EPS
Ratio of the specific gas constant of dry air and water vapor [1].
#define PSICE(t)
Compute saturation pressure over ice (WMO, 2018).
#define THETA(p, t)
Compute potential temperature.
#define RI
Ideal gas constant [J/(mol K)].
#define NORM(a)
Compute the norm (magnitude) of a vector.
int read_met_grib(const char *filename, const ctl_t *ctl, met_t *met)
Reads meteorological data from a grib file and processes it.
#define SET_QNT(qnt, name, longname, unit)
Set atmospheric quantity index.
#define TICE(p, h2o)
Calculate frost point temperature (WMO, 2018).
#define TOK(line, tok, format, var)
Get string tokens.
#define ZDIFF(lnp0, t0, h2o0, lnp1, t1, h2o1)
Calculate geopotential height difference.
#define THETAVIRT(p, t, h2o)
Compute virtual potential temperature.
#define DZ2DP(dz, p)
Convert a change in altitude to a change in pressure.
void dd_atm2particles(atm_t *atm, particle_t *particles, ctl_t *ctl, int *nparticles, cache_t *cache, int rank)
Converts atmospheric data to particle data.
#define WARN(...)
Print a warning message with contextual information.
#define ZETA(ps, p, t)
Computes the value of the zeta vertical coordinate.
void read_met_nc_grid_dd(const char *filename, const int ncid, const ctl_t *ctl, met_t *met)
Reads meteorological grid data from NetCDF files with domain decomposition.
#define RHICE(p, t, h2o)
Compute relative humidity over ice.
#define INTPOL_TIME_ALL(time, p, lon, lat)
Interpolate multiple meteorological variables in time.
#define ALLOC(ptr, type, n)
Allocate memory for a pointer with error handling.
#define SET_ATM(qnt, val)
Set atmospheric quantity value.
#define CTS
Maximum number of data points of climatological time series.
void read_met_nc_surface_dd(const int ncid, const ctl_t *ctl, met_t *met)
Reads and processes surface meteorological data from NetCDF files with domain decomposition.
#define ECC_READ_2D(variable, target, scaling_factor, found_flag)
Writes 2-D data from a grib message into the met struct.
#define DEG2RAD(deg)
Converts degrees to radians.
void broadcast_large_data(void *data, size_t N)
Broadcasts large data across all processes in an MPI communicator.
#define MO3
Molar mass of ozone [g/mol].
#define SQR(x)
Compute the square of a value.
#define RAD2DEG(rad)
Converts radians to degrees.
#define NC_INQ_DIM(dimname, ptr, min, max)
Inquire the length of a dimension in a NetCDF file.
#define NP
Maximum number of atmospheric data points.
#define NTIMER
Maximum number of timers.
#define SELECT_TIMER(id, group, color)
Select and start a timer with specific attributes.
#define INTPOL_2D(var, init)
Perform 2D interpolation for a meteorological variable.
#define RH(p, t, h2o)
Compute relative humidity over water.
#define NC_PUT_FLOAT(varname, ptr, hyperslab)
Write a float array to a NetCDF file.
#define CY
Maximum number of latitudes for climatological data.
#define LOG(level,...)
Print a log message with a specified logging level.
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.
int read_met_nc_2d_dd(const int ncid, const char *varname, const char *varname2, const char *varname3, const char *varname4, const char *varname5, const char *varname6, const ctl_t *ctl, const met_t *met, float dest[EX][EY], const float scl, const int init)
Reads a 2-dimensional meteorological variable from a NetCDF file.
void read_met_nc_levels_dd(const int ncid, const ctl_t *ctl, met_t *met)
Reads and processes meteorological level data from NetCDF files with domain decomposition.
#define ARRHENIUS(a, b, t)
Calculate the Arrhenius rate constant.
#define EX_GLOB
Maximum number of global longitudes for meteo data.
#define NCSI
Maximum number of data points for CSI calculation.
#define NC_GET_DOUBLE(varname, ptr, force)
Retrieve a double-precision variable from a NetCDF file.
#define EP
Maximum number of pressure levels for meteo data.
#define PSAT(t)
Compute saturation pressure over water.
#define DD_NPART
Maximum number of particles to send and recieve.
#define RHO(p, t)
Compute density of air.
void module_kpp_chem(ctl_t *ctl, cache_t *cache, clim_t *clim, met_t *met0, met_t *met1, atm_t *atm)
KPP chemistry module.
#define CO3
Maximum number of total column ozone data for climatological data.
#define NC_PUT_DOUBLE(varname, ptr, hyperslab)
Write double precision data to a NetCDF variable.
#define ECC(cmd)
Execute a ECCODES command and check for errors.
#define LIN(x0, y0, x1, y1, x)
Linear interpolation.
#define DIST2(a, b)
Calculate the squared Euclidean distance between two points in Cartesian coordinates.
#define DEG2DX(dlon, lat)
Convert a longitude difference to a distance in the x-direction (east-west) at a specific latitude.
#define CPD
Specific heat of dry air at constant pressure [J/(kg K)].
#define CSZA
Maximum number of solar zenith angles for climatological data.
#define DY2DEG(dy)
Convert a distance in kilometers to degrees latitude.
#define MAX(a, b)
Macro to determine the maximum of two values.
#define DD_NNMAX
Maximum number of neighbours to communicate with.
#define FMOD(x, y)
Calculate the floating-point remainder of dividing x by y.
double lat[NP]
Latitude [deg].
double lon[NP]
Longitude [deg].
int np
Number of air parcels.
double q[NQ][NP]
Quantity data (for various, user-defined attributes).
double p[NP]
Pressure [hPa].
double dt[NP]
Timesteps [s].
double iso_ts[NP]
Isosurface balloon time [s].
int iso_n
Isosurface balloon number of data points.
double iso_ps[NP]
Isosurface balloon pressure [hPa].
double rs[3 *NP+1]
Random numbers.
float uvwp[NP][3]
Wind perturbations [m/s].
double iso_var[NP]
Isosurface variables.
Climatological data in the form of photolysis rates.
int nsza
Number of solar zenith angles.
double sza[CSZA]
Solar zenith angle [rad].
double o3_1[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O1d + O2) [1/s].
double p[CP]
Pressure [hPa].
double ccl2f2[CP][CSZA][CO3]
CCl2F2 photolysis rate [1/s].
double o2[CP][CSZA][CO3]
O2 photolysis rate [1/s].
double ccl3f[CP][CSZA][CO3]
CCl3F photolysis rate [1/s].
double n2o[CP][CSZA][CO3]
N2O photolysis rate [1/s].
double h2o2[CP][CSZA][CO3]
H2O2 photolysis rate [1/s].
double h2o[CP][CSZA][CO3]
H2O photolysis rate [1/s].
double ccl4[CP][CSZA][CO3]
CCl4 photolysis rate [1/s].
double o3_2[CP][CSZA][CO3]
O3 photolysis rate (O3 + hv = O3p + O2) [1/s].
double o3c[CO3]
Total column ozone [DU].
int np
Number of pressure levels.
int no3c
Number of total ozone columns.
clim_ts_t ccl2f2
CFC-12 time series.
clim_photo_t photo
Photolysis rates.
clim_zm_t ho2
HO2 zonal means.
clim_zm_t hno3
HNO3 zonal means.
int tropo_ntime
Number of tropopause timesteps.
clim_ts_t sf6
SF6 time series.
clim_ts_t ccl4
CFC-10 time series.
clim_ts_t ccl3f
CFC-11 time series.
clim_zm_t o1d
O(1D) zonal means.
double tropo_lat[73]
Tropopause latitudes [deg].
clim_zm_t h2o2
H2O2 zonal means.
int tropo_nlat
Number of tropopause latitudes.
clim_zm_t oh
OH zonal means.
double tropo[12][73]
Tropopause pressure values [hPa].
double tropo_time[12]
Tropopause time steps [s].
clim_ts_t n2o
N2O time series.
Climatological data in the form of time series.
double vmr[CTS]
Volume mixing ratio [ppv].
double time[CTS]
Time [s].
int ntime
Number of timesteps.
Climatological data in the form of zonal means.
int np
Number of pressure levels.
double p[CP]
Pressure [hPa].
double vmr[CT][CP][CY]
Volume mixing ratio [ppv].
int ntime
Number of timesteps.
int nlat
Number of latitudes.
double lat[CY]
Latitude [deg].
double grid_z0
Lower altitude of gridded data [km].
int qnt_o3
Quantity array index for ozone volume mixing ratio.
double csi_lat1
Upper latitude of gridded CSI data [deg].
char csi_obsfile[LEN]
Observation data file for CSI analysis.
int qnt_Coh
Quantity array index for OH volume mixing ratio (chemistry code).
double wet_depo_ic_a
Coefficient A for wet deposition in cloud (exponential form).
int met_nc_scale
Check netCDF scaling factors (0=no, 1=yes).
int qnt_pel
Quantity array index for pressure at equilibrium level (EL).
int csi_nz
Number of altitudes of gridded CSI data.
double molmass
Molar mass [g/mol].
int qnt_p
Quantity array index for pressure.
int qnt_Cccl2f2
Quantity array index for CFC-12 volume mixing ratio (chemistry code).
int dd_halos_size
Size of halos given in grid-points.
char atm_gpfile[LEN]
Gnuplot file for atmospheric data.
int mixing_nx
Number of longitudes of mixing grid.
double chemgrid_z1
Upper altitude of chemistry grid [km].
char qnt_format[NQ][LEN]
Quantity output format.
int qnt_m
Quantity array index for mass.
int qnt_aoa
Quantity array index for age of air.
int qnt_rhop
Quantity array index for particle density.
int qnt_swc
Quantity array index for cloud snow water content.
double csi_obsmin
Minimum observation index to trigger detection.
int qnt_pcb
Quantity array index for cloud bottom pressure.
char clim_n2o_timeseries[LEN]
Filename of N2O time series.
double bound_dzs
Boundary conditions surface layer depth [km].
double csi_lon1
Upper longitude of gridded CSI data [deg].
int qnt_u
Quantity array index for zonal wind.
double stat_lon
Longitude of station [deg].
double mixing_trop
Interparcel exchange parameter for mixing in the troposphere.
double sort_dt
Time step for sorting of particle data [s].
double mixing_z1
Upper altitude of mixing grid [km].
double stat_r
Search radius around station [km].
double wet_depo_bc_a
Coefficient A for wet deposition below cloud (exponential form).
int met_zstd_level
ZSTD compression level (from -5 to 22).
int csi_ny
Number of latitudes of gridded CSI data.
int vtk_sphere
Spherical projection for VTK data (0=no, 1=yes).
double chemgrid_z0
Lower altitude of chemistry grid [km].
double met_pbl_min
Minimum depth of planetary boundary layer [km].
int qnt_iwc
Quantity array index for cloud ice water content.
double chemgrid_lat0
Lower latitude of chemistry grid [deg].
double conv_cape
CAPE threshold for convection module [J/kg].
int qnt_Co1d
Quantity array index for O(1D) volume mixing ratio (chemistry code).
double met_cms_eps_pv
cmultiscale compression epsilon for potential vorticity.
int qnt_pw
Quantity array index for partial water vapor pressure.
char prof_basename[LEN]
Basename for profile output file.
double grid_z1
Upper altitude of gridded data [km].
int direction
Direction flag (1=forward calculation, -1=backward calculation).
char balloon[LEN]
Balloon position filename.
int qnt_Cccl4
Quantity array index for CFC-10 volume mixing ratio (chemistry code).
int met_dp
Stride for pressure levels.
double met_dt_out
Time step for sampling of meteo data along trajectories [s].
int qnt_h2o2
Quantity array index for H2O2 volume mixing ratio (climatology).
int qnt_vh
Quantity array index for horizontal wind.
char species[LEN]
Species.
int csi_nx
Number of longitudes of gridded CSI data.
double csi_lat0
Lower latitude of gridded CSI data [deg].
double turb_dz_trop
Vertical turbulent diffusion coefficient (troposphere) [m^2/s].
int met_pbl
Planetary boundary layer data (0=file, 1=z2p, 2=Richardson, 3=theta).
int qnt_lwc
Quantity array index for cloud liquid water content.
double turb_mesoz
Vertical scaling factor for mesoscale wind fluctuations.
int grid_nc_level
zlib compression level of netCDF grid data files (0=off).
int grid_nx
Number of longitudes of gridded data.
int atm_type
Type of atmospheric data files (0=ASCII, 1=binary, 2=netCDF, 3=CLaMS_traj, 4=CLaMS_pos).
double bound_mass
Boundary conditions mass per particle [kg].
double grid_lat0
Lower latitude of gridded data [deg].
int qnt_ts
Quantity array index for surface temperature.
int qnt_loss_rate
Quantity array index for total loss rate.
double met_cms_eps_h2o
cmultiscale compression epsilon for water vapor.
int qnt_plfc
Quantity array index for pressure at level of free convection (LCF).
double grid_lon0
Lower longitude of gridded data [deg].
int qnt_o1d
Quantity array index for O(1D) volume mixing ratio (climatology).
int met_tropo_spline
Tropopause interpolation method (0=linear, 1=spline).
char sample_kernel[LEN]
Kernel data file for sample output.
int qnt_tvirt
Quantity array index for virtual temperature.
double dt_met
Time step of meteo data [s].
char clim_ho2_filename[LEN]
Filename of HO2 climatology.
double chemgrid_lat1
Upper latitude of chemistry grid [deg].
int met_geopot_sy
Latitudinal smoothing of geopotential heights.
char grid_gpfile[LEN]
Gnuplot file for gridded data.
double met_cms_eps_u
cmultiscale compression epsilon for zonal wind.
double turb_dx_strat
Horizontal turbulent diffusion coefficient (stratosphere) [m^2/s].
int qnt_vmr
Quantity array index for volume mixing ratio.
int qnt_lsm
Quantity array index for land-sea mask.
int qnt_theta
Quantity array index for potential temperature.
double bound_lat1
Boundary conditions maximum longitude [deg].
double stat_t1
Stop time for station output [s].
char csi_kernel[LEN]
Kernel data file for CSI output.
double turb_dx_trop
Horizontal turbulent diffusion coefficient (troposphere) [m^2/s].
int grid_type
Type of grid data files (0=ASCII, 1=netCDF).
double csi_lon0
Lower longitude of gridded CSI data [deg].
int qnt_pbl
Quantity array index for boundary layer pressure.
double oh_chem[4]
Coefficients for OH reaction rate (A, E/R or k0, n, kinf, m).
int grid_stddev
Include standard deviations in grid output (0=no, 1=yes).
int qnt_psice
Quantity array index for saturation pressure over ice.
double chemgrid_lon0
Lower longitude of chemistry grid [deg].
int bound_pbl
Boundary conditions planetary boundary layer (0=no, 1=yes).
int qnt_mloss_wet
Quantity array index for total mass loss due to wet deposition.
int met_geopot_sx
Longitudinal smoothing of geopotential heights.
int met_sy
Smoothing for latitudes.
int qnt_ps
Quantity array index for surface pressure.
int rng_type
Random number generator (0=GSL, 1=Squares, 2=cuRAND).
char prof_obsfile[LEN]
Observation data file for profile output.
int isosurf
Isosurface parameter (0=none, 1=pressure, 2=density, 3=theta, 4=balloon).
double bound_p1
Boundary conditions top pressure [hPa].
int qnt_zs
Quantity array index for surface geopotential height.
int prof_nz
Number of altitudes of gridded profile data.
double csi_dt_out
Time step for CSI output [s].
int met_cape
Convective available potential energy data (0=file, 1=calculate).
double csi_modmin
Minimum column density to trigger detection [kg/m^2].
int met_sx
Smoothing for longitudes.
double chemgrid_lon1
Upper longitude of chemistry grid [deg].
double turb_mesox
Horizontal scaling factor for mesoscale wind fluctuations.
double met_cms_eps_iwc
cmultiscale compression epsilon for cloud ice water content.
double met_cms_eps_swc
cmultiscale compression epsilon for cloud snow water content.
char grid_kernel[LEN]
Kernel data file for grid output.
double met_cms_eps_v
cmultiscale compression epsilon for meridional wind.
double prof_z0
Lower altitude of gridded profile data [km].
int qnt_w
Quantity array index for vertical velocity.
double bound_vmr
Boundary conditions volume mixing ratio [ppv].
double met_tropo_pv
Dynamical tropopause potential vorticity threshold [PVU].
int prof_nx
Number of longitudes of gridded profile data.
int qnt_stat
Quantity array index for station flag.
int met_tropo
Tropopause definition (0=none, 1=clim, 2=cold point, 3=WMO_1st, 4=WMO_2nd, 5=dynamical).
int qnt_rp
Quantity array index for particle radius.
int met_mpi_share
Use MPI to share meteo (0=no, 1=yes).
double mixing_strat
Interparcel exchange parameter for mixing in the stratosphere.
int qnt_vz
Quantity array index for vertical velocity.
int qnt_ho2
Quantity array index for HO2 volume mixing ratio (climatology).
double csi_z1
Upper altitude of gridded CSI data [km].
double stat_t0
Start time for station output [s].
double oh_chem_beta
Beta parameter for diurnal variablity of OH.
char clim_o1d_filename[LEN]
Filename of O(1D) climatology.
char clim_photo[LEN]
Filename of photolysis rates climatology.
double wet_depo_so2_ph
pH value used to calculate effective Henry constant of SO2.
double mixing_z0
Lower altitude of mixing grid [km].
int qnt_mloss_decay
Quantity array index for total mass loss due to exponential decay.
int atm_type_out
Type of atmospheric data files for output (-1=same as ATM_TYPE, 0=ASCII, 1=binary,...
int met_nlev
Number of meteo data model levels.
double dt_kpp
Time step for KPP chemistry [s].
char csi_basename[LEN]
Basename of CSI data files.
double dry_depo_dp
Dry deposition surface layer [hPa].
int qnt_shf
Quantity array index for surface sensible heat flux.
int qnt_vs
Quantity array index for surface meridional wind.
int qnt_Cco
Quantity array index for CO volume mixing ratio (chemistry code).
double vtk_dt_out
Time step for VTK data output [s].
double t_stop
Stop time of simulation [s].
double conv_dt
Time interval for convection module [s].
char sample_obsfile[LEN]
Observation data file for sample output.
int qnt_hno3
Quantity array index for HNO3 volume mixing ratio (climatology).
char grid_basename[LEN]
Basename of grid data files.
int met_clams
Read MPTRAC or CLaMS meteo data (0=MPTRAC, 1=CLaMS).
int qnt_h2ot
Quantity array index for tropopause water vapor volume mixing ratio.
int qnt_rh
Quantity array index for relative humidity over water.
double met_cms_eps_cc
cmultiscale compression epsilon for cloud cover.
double bound_lat0
Boundary conditions minimum longitude [deg].
double met_pbl_max
Maximum depth of planetary boundary layer [km].
int met_dx
Stride for longitudes.
int qnt_destination
Quantity array index for destination subdomain in domain decomposition.
int mixing_ny
Number of latitudes of mixing grid.
int met_convention
Meteo data layout (0=[lev, lat, lon], 1=[lon, lat, lev]).
int qnt_zeta_d
Quantity array index for diagnosed zeta vertical coordinate.
char clim_h2o2_filename[LEN]
Filename of H2O2 climatology.
int tracer_chem
Switch for first order tracer chemistry module (0=off, 1=on).
double dt_mod
Time step of simulation [s].
int diffusion
Diffusion scheme (0=off, 1=fixed-K, 2=PBL).
int qnt_tnat
Quantity array index for T_NAT.
int qnt_tice
Quantity array index for T_ice.
int qnt_zg
Quantity array index for geopotential height.
double vtk_offset
Vertical offset for VTK data [km].
int qnt_v
Quantity array index for meridional wind.
int qnt_mloss_dry
Quantity array index for total mass loss due to dry deposition.
double bound_vmr_trend
Boundary conditions volume mixing ratio trend [ppv/s].
double met_zfp_tol[METVAR]
ZFP compression tolerance.
int met_cache
Preload meteo data into disk cache (0=no, 1=yes).
int qnt_oh
Quantity array index for OH volume mixing ratio (climatology).
char qnt_unit[NQ][LEN]
Quantity units.
int qnt_Ch
Quantity array index for H volume mixing ratio (chemistry code).
int met_press_level_def
Use predefined pressure levels or not.
int oh_chem_reaction
Reaction type for OH chemistry (0=none, 2=bimolecular, 3=termolecular).
int qnt_h2o
Quantity array index for water vapor volume mixing ratio.
int prof_ny
Number of latitudes of gridded profile data.
int qnt_rhice
Quantity array index for relative humidity over ice.
int qnt_rho
Quantity array index for density of air.
double sample_dz
Layer depth for sample output [km].
double tdec_strat
Life time of particles in the stratosphere [s].
int obs_type
Type of observation data files (0=ASCII, 1=netCDF).
int grid_nc_quant[NQ]
Number of digits for quantization of netCDF grid data files (0=off).
double met_cms_eps_lwc
cmultiscale compression epsilon for cloud liquid water content.
int qnt_us
Quantity array index for surface zonal wind.
double met_cms_eps_z
cmultiscale compression epsilon for geopotential height.
double grid_lon1
Upper longitude of gridded data [deg].
int qnt_Cn2o
Quantity array index for N2O volume mixing ratio (chemistry code).
int qnt_Cccl3f
Quantity array index for CFC-11 volume mixing ratio (chemistry code).
char qnt_name[NQ][LEN]
Quantity names.
char atm_basename[LEN]
Basename of atmospheric data files.
double mixing_lat0
Lower latitude of mixing grid [deg].
int nens
Number of ensembles.
int qnt_pt
Quantity array index for tropopause pressure.
int qnt_cl
Quantity array index for total column cloud water.
int advect
Advection scheme (0=off, 1=Euler, 2=midpoint, 4=Runge-Kutta).
double prof_z1
Upper altitude of gridded profile data [km].
double met_lev_hyam[EP]
Meteo data model level a coefficients.
int qnt_t
Quantity array index for temperature.
int atm_filter
Time filter for atmospheric data output (0=none, 1=missval, 2=remove).
int kpp_chem
Switch for KPP chemistry module (0=off, 1=on).
int qnt_zeta
Quantity array index for zeta vertical coordinate.
double conv_pbl_trans
Depth of PBL transition layer (fraction of PBL depth).
char ens_basename[LEN]
Basename of ensemble data file.
double wet_depo_pre[2]
Coefficients for precipitation calculation.
int met_vert_coord
Vertical coordinate of input meteo data (0=plev, 1=mlev_p_file, 2=mlev_ab_file, 3=mlev_ab_full,...
double csi_z0
Lower altitude of gridded CSI data [km].
int qnt_lapse
Quantity array index for lapse rate.
double stat_lat
Latitude of station [deg].
int qnt_Cho2
Quantity array index for HO2 volume mixing ratio (chemistry code).
double wet_depo_bc_h[2]
Coefficients for wet deposition below cloud (Henry's law: Hb, Cb).
int grid_ny
Number of latitudes of gridded data.
int qnt_Csf6
Quantity array index for SF6 volume mixing ratio (chemistry code).
int qnt_Ch2o
Quantity array index for H2O volume mixing ratio (chemistry code).
double met_detrend
FWHM of horizontal Gaussian used for detrending [km].
int conv_mix_pbl
Vertical mixing in the PBL (0=off, 1=on).
char metbase[LEN]
Basename for meteo data.
double bound_dps
Boundary conditions surface layer depth [hPa].
int dd_nbr_neighbours
Number of neighbours to communicate with.
double met_cms_eps_t
cmultiscale compression epsilon for temperature.
int chemgrid_nz
Number of altitudes of chemistry grid.
int qnt_cape
Quantity array index for convective available potential energy (CAPE).
int qnt_zeta_dot
Quantity array index forvelocity of zeta vertical coordinate.
double bound_mass_trend
Boundary conditions mass per particle trend [kg/s].
int mixing_nz
Number of altitudes of mixing grid.
int qnt_o3c
Quantity array index for total column ozone.
double bound_p0
Boundary conditions bottom pressure [hPa].
double mixing_lon0
Lower longitude of mixing grid [deg].
char clim_ccl4_timeseries[LEN]
Filename of CFC-10 time series.
int qnt_Co3
Quantity array index for O3 volume mixing ratio (chemistry code).
int qnt_tsts
Quantity array index for T_STS.
int grid_nz
Number of altitudes of gridded data.
char clim_oh_filename[LEN]
Filename of OH climatology.
int qnt_nss
Quantity array index for northward turbulent surface stress.
double ens_dt_out
Time step for ensemble output [s].
char sample_basename[LEN]
Basename of sample data file.
int atm_stride
Particle index stride for atmospheric data files.
int met_relhum
Try to read relative humidity (0=no, 1=yes).
double mixing_lat1
Upper latitude of mixing grid [deg].
double atm_dt_out
Time step for atmospheric data output [s].
char clim_sf6_timeseries[LEN]
Filename of SF6 time series.
double prof_lat1
Upper latitude of gridded profile data [deg].
int met_cms_batch
cmultiscale batch size.
double psc_h2o
H2O volume mixing ratio for PSC analysis.
int met_sp
Smoothing for pressure levels.
double prof_lon0
Lower longitude of gridded profile data [deg].
int chemgrid_nx
Number of longitudes of chemistry grid.
int qnt_pct
Quantity array index for cloud top pressure.
int qnt_mloss_kpp
Quantity array index for total mass loss due to KPP chemistry.
int qnt_psat
Quantity array index for saturation pressure over water.
int qnt_subdomain
Quantity array index for current subdomain in domain decomposition.
double met_lev_hybm[EP]
Meteo data model level b coefficients.
double prof_lat0
Lower latitude of gridded profile data [deg].
int qnt_cin
Quantity array index for convective inhibition (CIN).
double psc_hno3
HNO3 volume mixing ratio for PSC analysis.
double prof_lon1
Upper longitude of gridded profile data [deg].
double met_cms_eps_rwc
cmultiscale compression epsilon for cloud rain water content.
int met_nc_quant
Number of digits for quantization of netCDF meteo files (0=off).
int h2o2_chem_reaction
Reaction type for H2O2 chemistry (0=none, 1=SO2).
int qnt_Co3p
Quantity array index for O(3P) volume mixing ratio (chemistry code).
int atm_nc_quant[NQ]
Number of digits for quantization of netCDF atmospheric data files (0=off).
double wet_depo_bc_ret_ratio
Coefficients for wet deposition below cloud: retention ratio.
int chemgrid_ny
Number of latitudes of chemistry grid.
char clim_ccl3f_timeseries[LEN]
Filename of CFC-11 time series.
double met_cms_eps_o3
cmultiscale compression epsilon for ozone.
int met_cms_zstd
cmultiscale zstd compression (0=off, 1=on).
int grid_sparse
Sparse output in grid data files (0=no, 1=yes).
char vtk_basename[LEN]
Basename of VTK data files.
double dry_depo_vdep
Dry deposition velocity [m/s].
int qnt_tt
Quantity array index for tropopause temperature.
int met_np
Number of target pressure levels.
int qnt_ens
Quantity array index for ensemble IDs.
int met_nc_level
zlib compression level of netCDF meteo files (0=off).
double mixing_dt
Time interval for mixing [s].
int qnt_mloss_h2o2
Quantity array index for total mass loss due to H2O2 chemistry.
double vtk_scale
Vertical scaling factor for VTK data.
char clim_ccl2f2_timeseries[LEN]
Filename of CFC-12 time series.
double met_cms_eps_w
cmultiscale compression epsilon for vertical velocity.
double wet_depo_ic_h[2]
Coefficients for wet deposition in cloud (Henry's law: Hb, Cb).
double turb_dx_pbl
Horizontal turbulent diffusion coefficient (PBL) [m^2/s].
double conv_cin
CIN threshold for convection module [J/kg].
int qnt_pv
Quantity array index for potential vorticity.
int advect_vert_coord
Vertical velocity of air parcels (0=omega_on_plev, 1=zetadot_on_mlev, 2=omega_on_mlev).
int qnt_mloss_oh
Quantity array index for total mass loss due to OH chemistry.
int qnt_Ch2o2
Quantity array index for H2O2 volume mixing ratio (chemistry code).
int qnt_sst
Quantity array index for sea surface temperature.
double mixing_lon1
Upper longitude of mixing grid [deg].
int atm_nc_level
zlib compression level of netCDF atmospheric data files (0=off).
char clim_hno3_filename[LEN]
Filename of HNO3 climatology.
int met_cms_heur
cmultiscale coarsening heuristics (0=default, 1=mean diff, 2=median diff, 3=max diff).
double wet_depo_ic_ret_ratio
Coefficients for wet deposition in cloud: retention ratio.
int qnt_sh
Quantity array index for specific humidity.
int qnt_ess
Quantity array index for eastward turbulent surface stress.
double wet_depo_ic_b
Coefficient B for wet deposition in cloud (exponential form).
double wet_depo_bc_b
Coefficient B for wet deposition below cloud (exponential form).
int met_dy
Stride for latitudes.
int qnt_Cx
Quantity array index for trace species x volume mixing ratio (chemistry code).
double turb_dz_strat
Vertical turbulent diffusion coefficient (stratosphere) [m^2/s].
double bound_zetas
Boundary conditions surface layer zeta [K].
int dd_subdomains_zonal
Zonal subdomain number.
int qnt_idx
Quantity array index for air parcel IDs.
double met_tropo_theta
Dynamical tropopause potential temperature threshold [K].
int qnt_rwc
Quantity array index for cloud rain water content.
double t_start
Start time of simulation [s].
char qnt_longname[NQ][LEN]
Quantity long names.
double met_p[EP]
Target pressure levels [hPa].
int nq
Number of quantities.
double tdec_trop
Life time of particles in the troposphere [s].
int met_zfp_prec[METVAR]
ZFP compression precision.
double sample_dx
Horizontal radius for sample output [km].
int vtk_stride
Particle index stride for VTK data.
char stat_basename[LEN]
Basename of station data file.
double turb_dz_pbl
Vertical turbulent diffusion coefficient (PBL) [m^2/s].
double grid_lat1
Upper latitude of gridded data [deg].
int dd_subdomains_meridional
Meridional subdomain number.
int qnt_zt
Quantity array index for tropopause geopotential height.
int met_type
Type of meteo data files (0=netCDF, 1=binary, 2=pck, 3=zfp, 4=zstd, 5=cms, 6=grib).
int qnt_cc
Quantity array index for cloud cover.
int qnt_plcl
Quantity array index for pressure at lifted condensation level (LCL).
double grid_dt_out
Time step for gridded data output [s].
int qnt_tdew
Quantity array index for dew point temperature.
float zt[EX][EY]
Tropopause geopotential height [km].
float sst[EX][EY]
Sea surface temperature [K].
float rwc[EX][EY][EP]
Cloud rain water content [kg/kg].
float o3c[EX][EY]
Total column ozone [DU].
float zeta_dotl[EX][EY][EP]
Vertical velocity on model levels [K/s].
float h2o[EX][EY][EP]
Water vapor volume mixing ratio [1].
double subdomain_lon_max
Rectangular grid limit of subdomain.
float cape[EX][EY]
Convective available potential energy [J/kg].
float w[EX][EY][EP]
Vertical velocity [hPa/s].
double subdomain_lat_min
Rectangular grid limit of subdomain.
float pct[EX][EY]
Cloud top pressure [hPa].
double hybrid[EP]
Model hybrid levels.
int nx
Number of longitudes.
double subdomain_lon_min
Rectangular grid limit of subdomain.
int ny_glob
Global sizes of meteo data.
int ny
Number of latitudes.
float shf[EX][EY]
Surface sensible heat flux [W/m^2].
float ps[EX][EY]
Surface pressure [hPa].
float lwc[EX][EY][EP]
Cloud liquid water content [kg/kg].
float us[EX][EY]
Surface zonal wind [m/s].
float wl[EX][EY][EP]
Vertical velocity on model levels [hPa/s].
size_t subdomain_start[4]
Hyperslab start and count for subdomain.
float vl[EX][EY][EP]
Meridional wind on model levels [m/s].
float zs[EX][EY]
Surface geopotential height [km].
float o3[EX][EY][EP]
Ozone volume mixing ratio [1].
float cc[EX][EY][EP]
Cloud cover [1].
int np
Number of pressure levels.
float t[EX][EY][EP]
Temperature [K].
float ts[EX][EY]
Surface temperature [K].
float u[EX][EY][EP]
Zonal wind [m/s].
float ess[EX][EY]
Eastward turbulent surface stress [N/m^2].
float ul[EX][EY][EP]
Zonal wind on model levels [m/s].
float pcb[EX][EY]
Cloud bottom pressure [hPa].
float pel[EX][EY]
Pressure at equilibrium level (EL) [hPa].
int nx_glob
Global sizes of meteo data.
float cin[EX][EY]
Convective inhibition [J/kg].
float plcl[EX][EY]
Pressure at lifted condensation level (LCL) [hPa].
double lon[EX]
Longitudes [deg].
float pt[EX][EY]
Tropopause pressure [hPa].
float tt[EX][EY]
Tropopause temperature [K].
float pbl[EX][EY]
Boundary layer pressure [hPa].
size_t subdomain_count[4]
Hyperslab start and count for subdomain.
float vs[EX][EY]
Surface meridional wind [m/s].
float z[EX][EY][EP]
Geopotential height [km].
float v[EX][EY][EP]
Meridional wind [m/s].
int npl
Number of model levels.
float lsm[EX][EY]
Land-sea mask [1].
float iwc[EX][EY][EP]
Cloud ice water content [kg/kg].
float h2ot[EX][EY]
Tropopause water vapor volume mixing ratio [ppv].
float pv[EX][EY][EP]
Potential vorticity [PVU].
double subdomain_lat_max
Rectangular grid limit of subdomain.
float cl[EX][EY]
Total column cloud water [kg/m^2].
float nss[EX][EY]
Northward turbulent surface stress [N/m^2].
int np_glob
Global sizes of meteo data.
float pl[EX][EY][EP]
Pressure on model levels [hPa].
float plfc[EX][EY]
Pressure at level of free convection (LFC) [hPa].
double lat[EY]
Latitudes [deg].
float swc[EX][EY][EP]
Cloud snow water content [kg/kg].
float zetal[EX][EY][EP]
Zeta on model levels [K].
double p[EP]
Pressure levels [hPa].
double lat
Latitude [deg].
double lon
Longitude [deg].
double q[NQ]
Quantity data (for various, user-defined attributes).