51 {
52
54
56
58
60
61 FILE *out;
62
63 static double *timem, ps, *psm, ts, *tsm, zs, *zsm, us, *usm, vs, *vsm,
64 ess, *essm, nss, *nssm, shf, *shfm, lsm, *lsmm, sst, *sstm, pbl, *pblm,
65 pt, *ptm, t, *pm, *tm, u, *um, v, *vm, w, *wm, h2o, *h2om, h2ot, *h2otm,
66 o3, *o3m, *hno3m, *ohm, *h2o2m, *ho2m, *o1dm, *tdewm, *ticem, *tnatm,
67 lwc, *lwcm, rwc, *rwcm, iwc, *iwcm, swc, *swcm, cc, *ccm, z, *zm,
68 pv, *pvm, zt, *ztm, tt, *ttm, pct, *pctm, pcb, *pcbm, cl, *clm,
69 plcl, *plclm, plfc, *plfcm, pel, *pelm, cape, *capem, cin, *cinm,
70 o3c, *o3cm, *rhm, *rhicem, ptop, pbot, t0, lon, lons[
NX], lat, lats[
NY];
71
72 static int *np, *npc, *npt, nx, ny;
73
74
174 ALLOC(rhicem,
double,
182
183
185
186
187 if (argc < 4)
188 ERRMSG(
"Missing or invalid command-line arguments.\n\n"
189 "Usage: met_map <ctl> <map.tab> <met0> [<met1> ...]\n\n"
190 "Use -h for full help.");
191
192
194 double p0 =
P(
scan_ctl(argv[1], argc, argv,
"MAP_Z0", -1,
"10", NULL));
195 double lon0 =
scan_ctl(argv[1], argc, argv,
"MAP_LON0", -1,
"-180", NULL);
196 double lon1 =
scan_ctl(argv[1], argc, argv,
"MAP_LON1", -1,
"180", NULL);
197 double dlon =
scan_ctl(argv[1], argc, argv,
"MAP_DLON", -1,
"-999", NULL);
198 double lat0 =
scan_ctl(argv[1], argc, argv,
"MAP_LAT0", -1,
"-90", NULL);
199 double lat1 =
scan_ctl(argv[1], argc, argv,
"MAP_LAT1", -1,
"90", NULL);
200 double dlat =
scan_ctl(argv[1], argc, argv,
"MAP_DLAT", -1,
"-999", NULL);
201 double theta =
scan_ctl(argv[1], argc, argv,
"MAP_THETA", -1,
"-999", NULL);
202
203
205
206
207 for (int i = 3; i < argc; i++) {
208
209
211 continue;
212
213
214 if (dlon <= 0)
215 dlon = fabs(met->
lon[1] - met->
lon[0]);
216 if (dlat <= 0)
217 dlat = fabs(met->
lat[1] - met->
lat[0]);
218 if (lon0 < -360 && lon1 > 360) {
219 lon0 = gsl_stats_min(met->
lon, 1, (
size_t) met->
nx);
220 lon1 = gsl_stats_max(met->
lon, 1, (
size_t) met->
nx);
221 }
222 nx = ny = 0;
223 for (lon = lon0; lon <= lon1 + 0.001; lon += dlon) {
224 lons[nx] = round(lon * 1e3) / 1e3;
226 ERRMSG(
"Too many longitudes!");
227 }
228 if (lat0 < -90 && lat1 > 90) {
229 lat0 = gsl_stats_min(met->
lat, 1, (
size_t) met->
ny);
230 lat1 = gsl_stats_max(met->
lat, 1, (
size_t) met->
ny);
231 }
232 for (lat = lat0; lat <= lat1 + 0.001; lat += dlat) {
233 lats[ny] = round(lat * 1e3) / 1e3;
235 ERRMSG(
"Too many latitudes!");
236 }
237
238
239 for (int ix = 0; ix < nx; ix++)
240 for (int iy = 0; iy < ny; iy++) {
241
242
244 if (theta > 0) {
245 ptop = met->
p[met->
np - 1];
247 do {
248 p0 = 0.5 * (ptop + pbot);
250 &t0, ci, cw, 1);
251 if (
THETA(p0, t0) > theta)
252 ptop = p0;
253 else
254 pbot = p0;
255 } while (fabs(ptop - pbot) > 1e-5);
256 }
257
258
260
261
262 timem[iy * nx + ix] += met->
time;
263 zm[iy * nx + ix] += z;
264 pm[iy * nx + ix] += p0;
265 tm[iy * nx + ix] += t;
266 um[iy * nx + ix] += u;
267 vm[iy * nx + ix] += v;
268 wm[iy * nx + ix] += w;
269 pvm[iy * nx + ix] += pv;
270 h2om[iy * nx + ix] += h2o;
271 o3m[iy * nx + ix] += o3;
272 lwcm[iy * nx + ix] += lwc;
273 rwcm[iy * nx + ix] += rwc;
274 iwcm[iy * nx + ix] += iwc;
275 swcm[iy * nx + ix] += swc;
276 ccm[iy * nx + ix] += cc;
277 psm[iy * nx + ix] += ps;
278 tsm[iy * nx + ix] += ts;
279 zsm[iy * nx + ix] += zs;
280 usm[iy * nx + ix] += us;
281 vsm[iy * nx + ix] += vs;
282 essm[iy * nx + ix] += ess;
283 nssm[iy * nx + ix] += nss;
284 shfm[iy * nx + ix] += shf;
285 lsmm[iy * nx + ix] += lsm;
286 sstm[iy * nx + ix] += sst;
287 pblm[iy * nx + ix] += pbl;
288 pctm[iy * nx + ix] += pct;
289 pcbm[iy * nx + ix] += pcb;
290 clm[iy * nx + ix] += cl;
291 if (isfinite(plfc) && isfinite(pel) && cape >= ctl.
conv_cape
293 plclm[iy * nx + ix] += plcl;
294 plfcm[iy * nx + ix] += plfc;
295 pelm[iy * nx + ix] += pel;
296 capem[iy * nx + ix] += cape;
297 cinm[iy * nx + ix] += cin;
298 npc[iy * nx + ix]++;
299 }
300 if (isfinite(pt)) {
301 ptm[iy * nx + ix] += pt;
302 ztm[iy * nx + ix] += zt;
303 ttm[iy * nx + ix] += tt;
304 h2otm[iy * nx + ix] += h2ot;
305 npt[iy * nx + ix]++;
306 }
307 o3cm[iy * nx + ix] += o3c;
309 tnatm[iy * nx + ix] +=
312 ohm[iy * nx + ix] +=
313 clim_oh(&ctl, clim, met->
time, lons[ix], lats[iy], p0);
315 ho2m[iy * nx + ix] +=
clim_zm(&clim->
ho2, met->
time, lats[iy], p0);
316 o1dm[iy * nx + ix] +=
clim_zm(&clim->
o1d, met->
time, lats[iy], p0);
317 rhm[iy * nx + ix] +=
RH(p0, t, h2o);
318 rhicem[iy * nx + ix] +=
RHICE(p0, t, h2o);
319 tdewm[iy * nx + ix] +=
TDEW(p0, h2o);
320 ticem[iy * nx + ix] +=
TICE(p0, h2o);
321 np[iy * nx + ix]++;
322 }
323 }
324
325
326 LOG(1,
"Write meteorological data file: %s", argv[2]);
327 if (!(out = fopen(argv[2], "w")))
328 ERRMSG(
"Cannot create file!");
329
330
332
333
334 for (int iy = 0; iy < ny; iy++) {
335 fprintf(out, "\n");
336 for (int ix = 0; ix < nx; ix++)
337 fprintf(out,
338 "%.2f %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g"
339 " %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g"
340 " %g %g %g %g %g %g %g %g %g %g %g %g %g %g %d %d %d\n",
341 timem[iy * nx + ix] / np[iy * nx + ix],
342 Z(pm[iy * nx + ix] / np[iy * nx + ix]), lons[ix], lats[iy],
343 pm[iy * nx + ix] / np[iy * nx + ix],
344 tm[iy * nx + ix] / np[iy * nx + ix],
345 um[iy * nx + ix] / np[iy * nx + ix],
346 vm[iy * nx + ix] / np[iy * nx + ix],
347 wm[iy * nx + ix] / np[iy * nx + ix],
348 h2om[iy * nx + ix] / np[iy * nx + ix],
349 o3m[iy * nx + ix] / np[iy * nx + ix],
350 zm[iy * nx + ix] / np[iy * nx + ix],
351 pvm[iy * nx + ix] / np[iy * nx + ix],
352 psm[iy * nx + ix] / np[iy * nx + ix],
353 tsm[iy * nx + ix] / np[iy * nx + ix],
354 zsm[iy * nx + ix] / np[iy * nx + ix],
355 usm[iy * nx + ix] / np[iy * nx + ix],
356 vsm[iy * nx + ix] / np[iy * nx + ix],
357 essm[iy * nx + ix] / np[iy * nx + ix],
358 nssm[iy * nx + ix] / np[iy * nx + ix],
359 shfm[iy * nx + ix] / np[iy * nx + ix],
360 lsmm[iy * nx + ix] / np[iy * nx + ix],
361 sstm[iy * nx + ix] / np[iy * nx + ix],
362 ptm[iy * nx + ix] / npt[iy * nx + ix],
363 ztm[iy * nx + ix] / npt[iy * nx + ix],
364 ttm[iy * nx + ix] / npt[iy * nx + ix],
365 h2otm[iy * nx + ix] / npt[iy * nx + ix],
366 lwcm[iy * nx + ix] / np[iy * nx + ix],
367 rwcm[iy * nx + ix] / np[iy * nx + ix],
368 iwcm[iy * nx + ix] / np[iy * nx + ix],
369 swcm[iy * nx + ix] / np[iy * nx + ix],
370 ccm[iy * nx + ix] / np[iy * nx + ix],
371 clm[iy * nx + ix] / np[iy * nx + ix],
372 pctm[iy * nx + ix] / np[iy * nx + ix],
373 pcbm[iy * nx + ix] / np[iy * nx + ix],
374 plclm[iy * nx + ix] / npc[iy * nx + ix],
375 plfcm[iy * nx + ix] / npc[iy * nx + ix],
376 pelm[iy * nx + ix] / npc[iy * nx + ix],
377 capem[iy * nx + ix] / npc[iy * nx + ix],
378 cinm[iy * nx + ix] / npc[iy * nx + ix],
379 rhm[iy * nx + ix] / np[iy * nx + ix],
380 rhicem[iy * nx + ix] / np[iy * nx + ix],
381 tdewm[iy * nx + ix] / np[iy * nx + ix],
382 ticem[iy * nx + ix] / np[iy * nx + ix],
383 tnatm[iy * nx + ix] / np[iy * nx + ix],
384 hno3m[iy * nx + ix] / np[iy * nx + ix],
385 ohm[iy * nx + ix] / np[iy * nx + ix],
386 h2o2m[iy * nx + ix] / np[iy * nx + ix],
387 ho2m[iy * nx + ix] / np[iy * nx + ix],
388 o1dm[iy * nx + ix] / np[iy * nx + ix],
389 pblm[iy * nx + ix] / np[iy * nx + ix],
390 o3cm[iy * nx + ix] / np[iy * nx + ix], np[iy * nx + ix],
391 npt[iy * nx + ix], npc[iy * nx + ix]);
392 }
393
394
395 fclose(out);
396
397
398 free(clim);
399 free(met);
400 free(dd);
401 free(timem);
402 free(psm);
403 free(tsm);
404 free(zsm);
405 free(usm);
406 free(vsm);
407 free(essm);
408 free(nssm);
409 free(shfm);
410 free(lsmm);
411 free(sstm);
412 free(pblm);
413 free(ptm);
414 free(pm);
415 free(tm);
416 free(um);
417 free(vm);
418 free(wm);
419 free(h2om);
420 free(h2otm);
421 free(o3m);
422 free(hno3m);
423 free(ohm);
424 free(h2o2m);
425 free(ho2m);
426 free(o1dm);
427 free(tdewm);
428 free(ticem);
429 free(tnatm);
430 free(lwcm);
431 free(rwcm);
432 free(iwcm);
433 free(swcm);
434 free(ccm);
435 free(zm);
436 free(pvm);
437 free(ztm);
438 free(ttm);
439 free(pctm);
440 free(pcbm);
441 free(clm);
442 free(plclm);
443 free(plfcm);
444 free(pelm);
445 free(capem);
446 free(cinm);
447 free(o3cm);
448 free(rhm);
449 free(rhicem);
450 free(np);
451 free(npc);
452 free(npt);
453
454 return EXIT_SUCCESS;
455}
#define NX
Maximum number of longitudes.
#define NY
Maximum number of latitudes.
double clim_zm(const clim_zm_t *zm, const double t, const double lat, const double p)
Interpolates monthly mean zonal mean climatological variables.
double nat_temperature(const double p, const double h2o, const double hno3)
Calculates the nitric acid trihydrate (NAT) temperature.
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.
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 mptrac_read_clim(const ctl_t *ctl, clim_t *clim)
Reads various climatological data and populates the given climatology structure.
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...
int mptrac_read_met(const char *filename, const ctl_t *ctl, const clim_t *clim, met_t *met, dd_t *dd)
Reads meteorological data from a file, supporting multiple formats and MPI broadcasting.
void 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.
#define INTPOL_SPACE_ALL(p, lon, lat)
Interpolate multiple meteorological variables in space.
#define INTPOL_INIT
Initialize arrays for interpolation.
#define ERRMSG(...)
Print an error message with contextual information and terminate the program.
#define USAGE
Print usage information on -h or --help.
#define Z(p)
Convert pressure to altitude.
#define P(z)
Compute pressure at given altitude.
#define THETA(p, t)
Compute potential temperature.
#define MET_HEADER
Write header for meteorological data file.
#define TICE(p, h2o)
Calculate frost point temperature (WMO, 2018).
#define RHICE(p, t, h2o)
Compute relative humidity over ice.
#define ALLOC(ptr, type, n)
Allocate memory for a pointer with error handling.
#define RH(p, t, h2o)
Compute relative humidity over water.
#define LOG(level,...)
Print a log message with a specified logging level.
#define TDEW(p, h2o)
Calculate dew point temperature.
clim_zm_t ho2
HO2 zonal means.
clim_zm_t hno3
HNO3 zonal means.
clim_zm_t o1d
O(1D) zonal means.
clim_zm_t h2o2
H2O2 zonal means.
double conv_cape
CAPE threshold for convection module [J/kg].
double conv_cin
CIN threshold for convection module [J/kg].
Domain decomposition data structure.
int nx
Number of longitudes.
int ny
Number of latitudes.
int np
Number of pressure levels.
float t[EX][EY][EP]
Temperature [K].
double lon[EX]
Longitudes [deg].
double lat[EY]
Latitudes [deg].
double p[EP]
Pressure levels [hPa].