41 {
42
44
46
48
50
52
53
55
56
57 if (argc < 3)
58 ERRMSG(
"Missing or invalid command-line arguments.\n\n"
59 "Usage: atm_init <ctl> <atm_out> [KEY VALUE ...]\n\n"
60 "Use -h for full help.");
61
62
68
69
71 const int ens =
72 (int)
scan_ctl(argv[1], argc, argv,
"INIT_ENS", -1,
"0", NULL);
73 const double t0 =
scan_ctl(argv[1], argc, argv,
"INIT_T0", -1,
"0", NULL);
74 const double t1 =
scan_ctl(argv[1], argc, argv,
"INIT_T1", -1,
"0", NULL);
75 const double dt =
scan_ctl(argv[1], argc, argv,
"INIT_DT", -1,
"1", NULL);
76 const double z0 =
scan_ctl(argv[1], argc, argv,
"INIT_Z0", -1,
"0", NULL);
77 const double z1 =
scan_ctl(argv[1], argc, argv,
"INIT_Z1", -1,
"0", NULL);
78 const double dz =
scan_ctl(argv[1], argc, argv,
"INIT_DZ", -1,
"1", NULL);
79 const double lon0 =
80 scan_ctl(argv[1], argc, argv,
"INIT_LON0", -1,
"0", NULL);
81 const double lon1 =
82 scan_ctl(argv[1], argc, argv,
"INIT_LON1", -1,
"0", NULL);
83 const double dlon =
84 scan_ctl(argv[1], argc, argv,
"INIT_DLON", -1,
"1", NULL);
85 const double lat0 =
86 scan_ctl(argv[1], argc, argv,
"INIT_LAT0", -1,
"0", NULL);
87 const double lat1 =
88 scan_ctl(argv[1], argc, argv,
"INIT_LAT1", -1,
"0", NULL);
89 const double dlat =
90 scan_ctl(argv[1], argc, argv,
"INIT_DLAT", -1,
"1", NULL);
91 const double st =
scan_ctl(argv[1], argc, argv,
"INIT_ST", -1,
"0", NULL);
92 const double sz =
scan_ctl(argv[1], argc, argv,
"INIT_SZ", -1,
"0", NULL);
93 const double slon =
94 scan_ctl(argv[1], argc, argv,
"INIT_SLON", -1,
"0", NULL);
95 const double slat =
96 scan_ctl(argv[1], argc, argv,
"INIT_SLAT", -1,
"0", NULL);
97 const double sx =
scan_ctl(argv[1], argc, argv,
"INIT_SX", -1,
"0", NULL);
98 const double ut =
scan_ctl(argv[1], argc, argv,
"INIT_UT", -1,
"0", NULL);
99 const double uz =
scan_ctl(argv[1], argc, argv,
"INIT_UZ", -1,
"0", NULL);
100 const double ulon =
101 scan_ctl(argv[1], argc, argv,
"INIT_ULON", -1,
"0", NULL);
102 const double ulat =
103 scan_ctl(argv[1], argc, argv,
"INIT_ULAT", -1,
"0", NULL);
104 const int even =
105 (int)
scan_ctl(argv[1], argc, argv,
"INIT_EVENLY", -1,
"0", NULL);
106 const int rho =
107 (int)
scan_ctl(argv[1], argc, argv,
"INIT_RHO", -1,
"0", NULL);
108 const int rep =
109 (int)
scan_ctl(argv[1], argc, argv,
"INIT_REP", -1,
"1", NULL);
110 const double m =
scan_ctl(argv[1], argc, argv,
"INIT_MASS", -1,
"0", NULL);
111 const double vmr =
scan_ctl(argv[1], argc, argv,
"INIT_VMR", -1,
"0", NULL);
112 const double bellrad =
113 scan_ctl(argv[1], argc, argv,
"INIT_BELLRAD", -1,
"0", NULL);
114 const int idx_offset =
115 (int)
scan_ctl(argv[1], argc, argv,
"INIT_IDX_OFFSET", -1,
"0", NULL);
116
117
119 ERRMSG(
"INIT_EVENLY is only supported for lat/lon grids");
121 ERRMSG(
"INIT_BELLRAD is only supported for lat/lon grids");
122
123
125
126
127 gsl_rng_env_setup();
128 gsl_rng *rng = gsl_rng_alloc(gsl_rng_default);
129
130
131 double ptop, ztop, rhomax =
RHO(1100., 200.);
132 if (rho) {
134 ptop = gsl_stats_min(met0->
p, 1, (
size_t)met0->
np);
136 }
137
138
139 for (double t = t0; t <= t1; t += dt)
140 for (double z = z0; z <= z1; z += dz)
141 for (double lon = lon0; lon <= lon1; lon += dlon)
142 for (double lat = lat0; lat <= lat1; lat += dlat)
143 for (int irep = 0; irep < rep; irep++) {
144
145
146 double rg = gsl_ran_gaussian_ziggurat(rng, st / 2.3548);
147 double ru = ut * (gsl_rng_uniform(rng) - 0.5);
148 atm->
time[atm->
np] = (t + rg + ru);
149
150
151 rg = gsl_ran_gaussian_ziggurat(rng, sz / 2.3548);
152 ru = uz * (gsl_rng_uniform(rng) - 0.5);
153 atm->
p[atm->
np] =
P(z + rg + ru);
154
155
156 rg = gsl_ran_gaussian_ziggurat(rng, slon / 2.3548);
157 const double sx_coord =
159 double rx = gsl_ran_gaussian_ziggurat(rng, sx_coord / 2.3548);
160 ru = ulon * (gsl_rng_uniform(rng) - 0.5);
161 atm->
lon[atm->
np] = (lon + rg + rx + ru);
162
163
166
167
168 do {
169 rg = gsl_ran_gaussian_ziggurat(rng, slat / 2.3548);
170 const double sy_coord =
172 rx = gsl_ran_gaussian_ziggurat(rng, sy_coord / 2.3548);
173 ru = ulat * (gsl_rng_uniform(rng) - 0.5);
174 atm->
lat[atm->
np] = (lat + rg + rx + ru);
175 } while (even && gsl_rng_uniform(rng) >
177
178
179 if (bellrad > 0) {
180 double x0[3], x1[3];
181 geo2cart(0.0, 0.5 * (lon0 + lon1), 0.5 * (lat0 + lat1), x0);
183 const double rad =
186 if (rad > bellrad)
187 continue;
190 0.5 * (1. + cos(M_PI * rad / bellrad));
193 0.5 * (1. + cos(M_PI * rad / bellrad));
194 }
195
196
197 if (rho) {
199 double ps, ttry;
202 atm->
lat[atm->
np], &ps, ci, cw, 1);
203 const double zs =
Z(ps);
204 do {
205 atm->
p[atm->
np] =
P(zs + (ztop - zs) * gsl_rng_uniform(rng));
209 &ttry, ci, cw, 0);
210 }
while (
RHO(atm->
p[atm->
np], ttry) <= rhomax);
211 }
212
213
214 if ((++atm->
np) >
NP)
215 ERRMSG(
"Too many particles!");
216 }
217
218
220 ERRMSG(
"Did not create any air parcels!");
221
222
223 if (ctl.
qnt_m >= 0 && bellrad <= 0)
224 for (
int ip = 0; ip < atm->
np; ip++)
225 atm->
q[ctl.
qnt_m][ip] = m / atm->
np;
226
227
228 if (ctl.
qnt_vmr >= 0 && bellrad <= 0)
229 for (
int ip = 0; ip < atm->
np; ip++)
231
232
234 for (
int ip = 0; ip < atm->
np; ip++)
235 atm->
q[ctl.
qnt_idx][ip] = idx_offset + ip;
236
237
239 for (
int ip = 0; ip < atm->
np; ip++)
241
242
244
245
246 gsl_rng_free(rng);
247 free(clim);
248 free(atm);
249 free(met0);
250 free(met1);
251 free(dd);
252
253 return EXIT_SUCCESS;
254}
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 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.
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_get_met(ctl_t *ctl, clim_t *clim, const double t, met_t **met0, met_t **met1, dd_t *dd)
Retrieves meteorological data for the specified time.
void mptrac_read_clim(const ctl_t *ctl, clim_t *clim)
Reads various climatological data and populates the given climatology structure.
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 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 geo2cart(const double z, const double lon, const double lat, double *x)
Converts geographic coordinates (longitude, latitude, altitude) to Cartesian coordinates.
#define RE
Mean radius of Earth [km].
#define DOTP(a, b)
Calculate the dot product of two vectors.
#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 DX2DEG(dx, lat)
Convert a distance in kilometers to degrees longitude at a given latitude.
#define ALLOC(ptr, type, n)
Allocate memory for a pointer with error handling.
#define DEG2RAD(deg)
Converts degrees to radians.
#define NP
Maximum number of atmospheric data points.
#define RHO(p, t)
Compute density of air.
#define DY2DEG(dy)
Convert a distance in kilometers to degrees latitude.
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].
int qnt_m
Quantity array index for mass.
int qnt_aoa
Quantity array index for age of air.
int qnt_vmr
Quantity array index for volume mixing ratio.
int qnt_ens
Quantity array index for ensemble IDs.
int met_coord_type
Type of coordinates for meteo data (-1=detect, 0=lat/lon [deg], 1=UTM [m]).
int qnt_idx
Quantity array index for air parcel IDs.
Domain decomposition data structure.
float ps[EX][EY]
Surface pressure [hPa].
int np
Number of pressure levels.
float t[EX][EY][EP]
Temperature [K].
double p[EP]
Pressure levels [hPa].