MPTRAC
atm_split.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 Functions...
29 ------------------------------------------------------------ */
30
32void usage(
33 void);
34
35/* ------------------------------------------------------------
36 Main...
37 ------------------------------------------------------------ */
38
39int main(
40 int argc,
41 char *argv[]) {
42
43 atm_t *atm, *atm2;
44
45 ctl_t ctl;
46
47 char kernel[LEN];
48
49 double k, kw[EP], kz[EP], mmax = 0, mtot = 0, z, zmin = 0, zmax = 0;
50
51 int ip, nk = 0;
52
53 /* Allocate... */
54 ALLOC(atm, atm_t, 1);
55 ALLOC(atm2, atm_t, 1);
56
57 /* Print usage information... */
58 USAGE;
59
60 /* Check arguments... */
61 if (argc < 4)
62 ERRMSG("Missing or invalid command-line arguments.\n\n"
63 "Usage: atm_split <ctl> <atm_in> <atm_out> [KEY VALUE ...]\n\n"
64 "Use -h for full help.");
65
66 /* Read control parameters... */
67 mptrac_read_ctl(argv[1], argc, argv, &ctl);
68 const int n = (int) scan_ctl(argv[1], argc, argv, "SPLIT_N", -1, "", NULL);
69 const double m = scan_ctl(argv[1], argc, argv, "SPLIT_M", -1, "-999", NULL);
70 const double um = scan_ctl(argv[1], argc, argv, "SPLIT_UM", -1, "0", NULL);
71 const double dt = scan_ctl(argv[1], argc, argv, "SPLIT_DT", -1, "0", NULL);
72 const double t0 = scan_ctl(argv[1], argc, argv, "SPLIT_T0", -1, "0", NULL);
73 const double t1 = scan_ctl(argv[1], argc, argv, "SPLIT_T1", -1, "0", NULL);
74 const double dz = scan_ctl(argv[1], argc, argv, "SPLIT_DZ", -1, "0", NULL);
75 const double z0 = scan_ctl(argv[1], argc, argv, "SPLIT_Z0", -1, "0", NULL);
76 const double z1 = scan_ctl(argv[1], argc, argv, "SPLIT_Z1", -1, "0", NULL);
77 const double dx = scan_ctl(argv[1], argc, argv, "SPLIT_DX", -1, "0", NULL);
78 const double lon0 =
79 scan_ctl(argv[1], argc, argv, "SPLIT_LON0", -1, "0", NULL);
80 const double lon1 =
81 scan_ctl(argv[1], argc, argv, "SPLIT_LON1", -1, "0", NULL);
82 const double lat0 =
83 scan_ctl(argv[1], argc, argv, "SPLIT_LAT0", -1, "0", NULL);
84 const double lat1 =
85 scan_ctl(argv[1], argc, argv, "SPLIT_LAT1", -1, "0", NULL);
86 scan_ctl(argv[1], argc, argv, "SPLIT_KERNEL", -1, "-", kernel);
87
88 /* Init random number generator... */
89 gsl_rng_env_setup();
90 gsl_rng *rng = gsl_rng_alloc(gsl_rng_default);
91
92 /* Read atmospheric data... */
93 if (!mptrac_read_atm(argv[2], &ctl, atm))
94 ERRMSG("Cannot open file!");
95
96 /* Read kernel function... */
97 if (kernel[0] != '-') {
98 read_kernel(kernel, kz, kw, &nk);
99 zmax = gsl_stats_max(kz, 1, (size_t) nk);
100 zmin = gsl_stats_min(kz, 1, (size_t) nk);
101 }
102
103 /* Get total and maximum mass... */
104 if (ctl.qnt_m >= 0)
105 for (ip = 0; ip < atm->np; ip++) {
106 mtot += atm->q[ctl.qnt_m][ip];
107 mmax = MAX(mmax, atm->q[ctl.qnt_m][ip]);
108 }
109 if (m >= 0)
110 mtot = m;
111
112 /* Loop over air parcels... */
113 for (int i = 0; i < n; i++) {
114
115 /* Select air parcel... */
116 if (ctl.qnt_m >= 0)
117 do {
118 ip = (int) gsl_rng_uniform_int(rng, (long unsigned int) atm->np);
119 } while (gsl_rng_uniform(rng) > atm->q[ctl.qnt_m][ip] / mmax);
120 else
121 ip = (int) gsl_rng_uniform_int(rng, (long unsigned int) atm->np);
122
123 /* Set time... */
124 if (t1 > t0)
125 atm2->time[atm2->np] = t0 + (t1 - t0) * gsl_rng_uniform_pos(rng);
126 else
127 atm2->time[atm2->np] = atm->time[ip]
128 + gsl_ran_gaussian_ziggurat(rng, dt / 2.3548);
129
130 /* Set vertical position... */
131 do {
132 if (nk > 0) {
133 do {
134 z = zmin + (zmax - zmin) * gsl_rng_uniform_pos(rng);
135 k = kernel_weight(kz, kw, nk, P(z));
136 } while (gsl_rng_uniform(rng) > k);
137 atm2->p[atm2->np] = P(z);
138 } else if (z1 > z0)
139 atm2->p[atm2->np] = P(z0 + (z1 - z0) * gsl_rng_uniform_pos(rng));
140 else
141 atm2->p[atm2->np] = atm->p[ip]
142 + DZ2DP(gsl_ran_gaussian_ziggurat(rng, dz / 2.3548), atm->p[ip]);
143 } while (atm2->p[atm2->np] < P(100.) || atm2->p[atm2->np] > P(-1.));
144
145 /* Set horizontal position... */
146 if (lon1 > lon0 && lat1 > lat0) {
147 atm2->lon[atm2->np] = lon0 + (lon1 - lon0) * gsl_rng_uniform_pos(rng);
148 atm2->lat[atm2->np] = lat0 + (lat1 - lat0) * gsl_rng_uniform_pos(rng);
149 } else {
150 atm2->lon[atm2->np] = atm->lon[ip]
151 + gsl_ran_gaussian_ziggurat(rng, DX2DEG(dx, atm->lat[ip]) / 2.3548);
152 atm2->lat[atm2->np] = atm->lat[ip]
153 + gsl_ran_gaussian_ziggurat(rng, DY2DEG(dx) / 2.3548);
154 }
155
156 /* Copy quantities... */
157 for (int iq = 0; iq < ctl.nq; iq++)
158 atm2->q[iq][atm2->np] = atm->q[iq][ip];
159
160 /* Adjust mass... */
161 if (ctl.qnt_m >= 0)
162 atm2->q[ctl.qnt_m][atm2->np]
163 = (mtot + (um > 0 ? um * (gsl_rng_uniform_pos(rng) - 0.5) : 0.0)) / n;
164
165 /* Adjust air parcel index... */
166 if (ctl.qnt_idx >= 0)
167 atm2->q[ctl.qnt_idx][atm2->np] = atm2->np;
168
169 /* Increment particle counter... */
170 if ((++atm2->np) > NP)
171 ERRMSG("Too many air parcels!");
172 }
173
174 /* Save data and close file... */
175 mptrac_write_atm(argv[3], &ctl, atm2, 0);
176
177 /* Free... */
178 free(atm);
179 free(atm2);
180
181 return EXIT_SUCCESS;
182}
183
184/*****************************************************************************/
185
187void usage(
188 void) {
189
190 printf("\nMPTRAC atm_split tool.\n\n");
191 printf("Split air parcels into a larger number of parcels.\n");
192 printf("\n");
193 printf("Usage:\n");
194 printf(" atm_split <ctl> <atm_in> <atm_out> [KEY VALUE ...]\n");
195 printf("\n");
196 printf("Arguments:\n");
197 printf(" <ctl> Control file.\n");
198 printf(" <atm_in> Atmospheric input file.\n");
199 printf(" <atm_out> Atmospheric output file.\n");
200 printf(" [KEY VALUE] Optional control parameters.\n");
201 printf("\nFurther information:\n");
202 printf(" Manual: https://slcs-jsc.github.io/mptrac/\n");
203}
int main(int argc, char *argv[])
Definition: atm_split.c:39
void usage(void)
Print command-line help.
Definition: atm_split.c:187
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.
Definition: mptrac.c:6523
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.
Definition: mptrac.c:7227
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.
Definition: mptrac.c:10645
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.
Definition: mptrac.c:5114
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:5245
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.
Definition: mptrac.c:2327
MPTRAC library declarations.
#define LEN
Maximum length of ASCII data lines.
Definition: mptrac.h:345
#define ERRMSG(...)
Print an error message with contextual information and terminate the program.
Definition: mptrac.h:2102
#define USAGE
Print usage information on -h or --help.
Definition: mptrac.h:1909
#define P(z)
Compute pressure at given altitude.
Definition: mptrac.h:1480
#define DX2DEG(dx, lat)
Convert a distance in kilometers to degrees longitude at a given latitude.
Definition: mptrac.h:651
#define DZ2DP(dz, p)
Convert a change in altitude to a change in pressure.
Definition: mptrac.h:688
#define ALLOC(ptr, type, n)
Allocate memory for a pointer with error handling.
Definition: mptrac.h:453
#define NP
Maximum number of atmospheric data points.
Definition: mptrac.h:355
#define EP
Maximum number of pressure levels for meteo data.
Definition: mptrac.h:330
#define DY2DEG(dy)
Convert a distance in kilometers to degrees latitude.
Definition: mptrac.h:669
#define MAX(a, b)
Macro to determine the maximum of two values.
Definition: mptrac.h:1074
Air parcel data.
Definition: mptrac.h:3241
double time[NP]
Time [s].
Definition: mptrac.h:3247
double lat[NP]
Latitude [deg].
Definition: mptrac.h:3256
double lon[NP]
Longitude [deg].
Definition: mptrac.h:3253
int np
Number of air parcels.
Definition: mptrac.h:3244
double q[NQ][NP]
Quantity data (for various, user-defined attributes).
Definition: mptrac.h:3259
double p[NP]
Pressure [hPa].
Definition: mptrac.h:3250
Control parameters.
Definition: mptrac.h:2190
int qnt_m
Quantity array index for mass.
Definition: mptrac.h:2221
int qnt_idx
Quantity array index for air parcel IDs.
Definition: mptrac.h:2212
int nq
Number of quantities.
Definition: mptrac.h:2197