MPTRAC
tropo_clim.c
Go to the documentation of this file.
1/*
2 This file is part of MPTRAC.
3
4 MPTRAC is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 MPTRAC is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with MPTRAC. If not, see <http://www.gnu.org/licenses/>.
16
17 Copyright (C) 2013-2026 Forschungszentrum Juelich GmbH
18*/
19
25#include "mptrac.h"
26
27/* ------------------------------------------------------------
28 Dimensions...
29 ------------------------------------------------------------ */
30
32#define NT 744
33
34/* ------------------------------------------------------------
35 Functions...
36 ------------------------------------------------------------ */
37
39void usage(
40 void);
41
42/* ------------------------------------------------------------
43 Main...
44 ------------------------------------------------------------ */
45
46int main(
47 int argc,
48 char *argv[]) {
49
50 ctl_t ctl;
51
52 static FILE *out;
53
54 static char varname[LEN];
55
56 static double lons[EX], lats[EY], *zm, *zs, *pm, *ps, *tm, *ts, *qm, *qs,
57 *o3m, *o3s;
58
59 static float *tropo_z0, *tropo_p0, *tropo_t0, *tropo_q0, *tropo_o30;
60
61 static int ncid, varid, varid_z, varid_p, varid_t, varid_q, varid_o3, h2o,
62 o3, *n, *nt, ntime, nlon, nlat;
63
64 static size_t count[10], start[10];
65
66 /* Allocate... */
67 ALLOC(zm, double,
68 EX * EY);
69 ALLOC(zs, double,
70 EX * EY);
71 ALLOC(pm, double,
72 EX * EY);
73 ALLOC(ps, double,
74 EX * EY);
75 ALLOC(tm, double,
76 EX * EY);
77 ALLOC(ts, double,
78 EX * EY);
79 ALLOC(qm, double,
80 EX * EY);
81 ALLOC(qs, double,
82 EX * EY);
83 ALLOC(o3m, double,
84 EX * EY);
85 ALLOC(o3s, double,
86 EX * EY);
87
88 ALLOC(tropo_z0, float,
89 EX * EY);
90 ALLOC(tropo_p0, float,
91 EX * EY);
92 ALLOC(tropo_t0, float,
93 EX * EY);
94 ALLOC(tropo_q0, float,
95 EX * EY);
96 ALLOC(tropo_o30, float,
97 EX * EY);
98
99 ALLOC(n, int,
100 EX * EY);
101 ALLOC(nt, int,
102 EX * EY);
103
104 /* Print usage information... */
105 USAGE;
106
107 /* Check arguments... */
108 if (argc < 5)
109 ERRMSG("Missing or invalid command-line arguments.\n\n"
110 "Usage: tropo_clim <ctl> <clim.tab> <var> <tropo.nc> [<tropo2.nc> ...] [KEY VALUE ...]\n\n"
111 "Use -h for full help.");
112
113 /* Read control parameters... */
114 mptrac_read_ctl(argv[1], argc, argv, &ctl);
115
116 /* Loop over tropopause files... */
117 for (int iarg = 4; iarg < argc; iarg++) {
118
119 /* Open tropopause file... */
120 LOG(1, "Read tropopause data: %s", argv[iarg]);
121 if (nc_open(argv[iarg], NC_NOWRITE, &ncid) != NC_NOERR)
122 ERRMSG("Cannot open file!");
123
124 /* Get dimensions... */
125 NC_INQ_DIM("time", &ntime, 1, NT, 1);
126 NC_INQ_DIM("lat", &nlat, 1, EY, 1);
127 NC_INQ_DIM("lon", &nlon, 1, EX, 1);
128
129 /* Read coordinates... */
130 NC_GET_DOUBLE("lat", lats, 1);
131 NC_GET_DOUBLE("lon", lons, 1);
132
133 /* Get variable indices... */
134 sprintf(varname, "%s_z", argv[3]);
135 NC(nc_inq_varid(ncid, varname, &varid_z));
136 sprintf(varname, "%s_p", argv[3]);
137 NC(nc_inq_varid(ncid, varname, &varid_p));
138 sprintf(varname, "%s_t", argv[3]);
139 NC(nc_inq_varid(ncid, varname, &varid_t));
140 sprintf(varname, "%s_q", argv[3]);
141 h2o = (nc_inq_varid(ncid, varname, &varid_q) == NC_NOERR);
142 sprintf(varname, "%s_o3", argv[3]);
143 o3 = (nc_inq_varid(ncid, varname, &varid_o3) == NC_NOERR);
144
145 /* Set dimensions... */
146 count[0] = 1;
147 count[1] = (size_t) nlat;
148 count[2] = (size_t) nlon;
149
150 /* Loop over time steps... */
151 for (int it = 0; it < ntime; it++) {
152
153 /* Read data... */
154 start[0] = (size_t) it;
155 NC(nc_get_vara_float(ncid, varid_z, start, count, tropo_z0));
156 NC(nc_get_vara_float(ncid, varid_p, start, count, tropo_p0));
157 NC(nc_get_vara_float(ncid, varid_t, start, count, tropo_t0));
158 if (h2o) {
159 NC(nc_get_vara_float(ncid, varid_q, start, count, tropo_q0));
160 } else
161 for (int i = 0; i < nlon * nlat; i++)
162 tropo_q0[i] = NAN;
163 if (o3) {
164 NC(nc_get_vara_float(ncid, varid_o3, start, count, tropo_o30));
165 } else
166 for (int i = 0; i < nlon * nlat; i++)
167 tropo_o30[i] = NAN;
168
169 /* Averaging... */
170 for (int i = 0; i < nlon * nlat; i++) {
171 nt[i]++;
172 if (isfinite(tropo_z0[i])
173 && isfinite(tropo_p0[i])
174 && isfinite(tropo_t0[i])
175 && (!h2o || isfinite(tropo_q0[i]))
176 && (!o3 || isfinite(tropo_o30[i]))) {
177 zm[i] += tropo_z0[i];
178 zs[i] += SQR(tropo_z0[i]);
179 pm[i] += tropo_p0[i];
180 ps[i] += SQR(tropo_p0[i]);
181 tm[i] += tropo_t0[i];
182 ts[i] += SQR(tropo_t0[i]);
183 qm[i] += tropo_q0[i];
184 qs[i] += SQR(tropo_q0[i]);
185 o3m[i] += tropo_o30[i];
186 o3s[i] += SQR(tropo_o30[i]);
187 n[i]++;
188 }
189 }
190 }
191
192 /* Close files... */
193 NC(nc_close(ncid));
194 }
195
196 /* Normalize... */
197 for (int i = 0; i < nlon * nlat; i++)
198 if (n[i] > 0) {
199 zm[i] /= n[i];
200 pm[i] /= n[i];
201 tm[i] /= n[i];
202 qm[i] /= n[i];
203 o3m[i] /= n[i];
204 double aux = zs[i] / n[i] - SQR(zm[i]);
205 zs[i] = aux > 0 ? sqrt(aux) : 0.0;
206 aux = ps[i] / n[i] - SQR(pm[i]);
207 ps[i] = aux > 0 ? sqrt(aux) : 0.0;
208 aux = ts[i] / n[i] - SQR(tm[i]);
209 ts[i] = aux > 0 ? sqrt(aux) : 0.0;
210 aux = qs[i] / n[i] - SQR(qm[i]);
211 qs[i] = aux > 0 ? sqrt(aux) : 0.0;
212 aux = o3s[i] / n[i] - SQR(o3m[i]);
213 o3s[i] = aux > 0 ? sqrt(aux) : 0.0;
214 }
215
216 /* Create file... */
217 LOG(1, "Write tropopause climatological data: %s", argv[2]);
218 if (!(out = fopen(argv[2], "w")))
219 ERRMSG("Cannot create file!");
220
221 /* Write header... */
222 fprintf(out,
223 "# $1 = longitude [deg]\n"
224 "# $2 = latitude [deg]\n"
225 "# $3 = tropopause height (mean) [km]\n"
226 "# $4 = tropopause pressure (mean) [hPa]\n"
227 "# $5 = tropopause temperature (mean) [K]\n"
228 "# $6 = tropopause water vapor (mean) [ppv]\n"
229 "# $7 = tropopause ozone (mean) [ppv]\n"
230 "# $8 = tropopause height (sigma) [km]\n"
231 "# $9 = tropopause pressure (sigma) [hPa]\n"
232 "# $10 = tropopause temperature (sigma) [K]\n"
233 "# $11 = tropopause water vapor (sigma) [ppv]\n"
234 "# $12 = tropopause ozone (sigma) [ppv]\n"
235 "# $13 = number of data points\n"
236 "# $14 = occurrence frequency [%%]\n");
237
238 /* Write output... */
239 for (int ilat = 0; ilat < nlat; ilat++) {
240 fprintf(out, "\n");
241 for (int ilon = 0; ilon < nlon; ilon++)
242 fprintf(out, "%g %g %g %g %g %g %g %g %g %g %g %g %d %g\n",
243 lons[ilon], lats[ilat], zm[ilat * nlon + ilon],
244 pm[ilat * nlon + ilon], tm[ilat * nlon + ilon],
245 qm[ilat * nlon + ilon], o3m[ilat * nlon + ilon],
246 zs[ilat * nlon + ilon], ps[ilat * nlon + ilon],
247 ts[ilat * nlon + ilon], qs[ilat * nlon + ilon],
248 o3s[ilat * nlon + ilon], n[ilat * nlon + ilon],
249 100. * n[ilat * nlon + ilon] / nt[ilat * nlon + ilon]);
250 }
251
252 /* Close files... */
253 fclose(out);
254
255 /* Free... */
256 free(zm);
257 free(zs);
258 free(pm);
259 free(ps);
260 free(tm);
261 free(ts);
262 free(qm);
263 free(qs);
264 free(o3m);
265 free(o3s);
266
267 free(tropo_z0);
268 free(tropo_p0);
269 free(tropo_t0);
270 free(tropo_q0);
271 free(tropo_o30);
272
273 free(n);
274 free(nt);
275
276 return EXIT_SUCCESS;
277}
278
279/*****************************************************************************/
280
282void usage(
283 void) {
284
285 printf("\nMPTRAC tropo_clim tool.\n\n");
286 printf("Calculate tropopause climatology statistics.\n");
287 printf("\n");
288 printf("Usage:\n");
289 printf
290 (" tropo_clim <ctl> <clim.tab> <var> <tropo.nc> [<tropo2.nc> ...] [KEY VALUE ...]\n");
291 printf("\n");
292 printf("Arguments:\n");
293 printf(" <ctl> Control file.\n");
294 printf(" <clim.tab> Output table.\n");
295 printf
296 (" <var> Tropopause variable prefix, such as clp, dyn, wmo_1st,\n");
297 printf(" or wmo_2nd.\n");
298 printf(" <tropo*> Tropopause netCDF input files.\n");
299 printf(" [KEY VALUE] Optional control parameters.\n");
300 printf("\nFurther information:\n");
301 printf(" Manual: https://slcs-jsc.github.io/mptrac/\n");
302}
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.
Definition: mptrac.c:5502
MPTRAC library declarations.
#define LEN
Maximum length of ASCII data lines.
Definition: mptrac.h:348
#define NC(cmd)
Execute a NetCDF command and check for errors.
Definition: mptrac.h:1217
#define ERRMSG(...)
Print an error message with contextual information and terminate the program.
Definition: mptrac.h:2115
#define EY
Maximum number of latitudes for meteo data.
Definition: mptrac.h:343
#define USAGE
Print usage information on -h or --help.
Definition: mptrac.h:1922
#define EX
Maximum number of longitudes for meteo data.
Definition: mptrac.h:338
#define ALLOC(ptr, type, n)
Allocate memory for a pointer with error handling.
Definition: mptrac.h:466
#define SQR(x)
Compute the square of a value.
Definition: mptrac.h:1746
#define LOG(level,...)
Print a log message with a specified logging level.
Definition: mptrac.h:2045
#define NC_GET_DOUBLE(varname, ptr, force)
Retrieve a double-precision variable from a NetCDF file.
Definition: mptrac.h:1276
#define NC_INQ_DIM(dimname, ptr, min, max, check)
Inquire the length of a dimension in a NetCDF file.
Definition: mptrac.h:1306
Control parameters.
Definition: mptrac.h:2203
int main(int argc, char *argv[])
Definition: tropo_clim.c:46
#define NT
Maximum number of time steps.
Definition: tropo_clim.c:32
void usage(void)
Print command-line help.
Definition: tropo_clim.c:282