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-2025 Forschungszentrum Juelich GmbH
18*/
19
25#include "mptrac.h"
26
27int main(
28 int argc,
29 char *argv[]) {
30
31 atm_t *atm, *atm2;
32
33 ctl_t ctl;
34
35 char kernel[LEN];
36
37 double k, kw[EP], kz[EP], mmax = 0, mtot = 0, z, zmin = 0, zmax = 0;
38
39 int ip, nk = 0;
40
41 /* Allocate... */
42 ALLOC(atm, atm_t, 1);
43 ALLOC(atm2, atm_t, 1);
44
45 /* Check arguments... */
46 if (argc < 4)
47 ERRMSG("Give parameters: <ctl> <atm_in> <atm_out>");
48
49 /* Read control parameters... */
50 read_ctl(argv[1], argc, argv, &ctl);
51 const int n = (int) scan_ctl(argv[1], argc, argv, "SPLIT_N", -1, "", NULL);
52 const double m = scan_ctl(argv[1], argc, argv, "SPLIT_M", -1, "-999", NULL);
53 const double um = scan_ctl(argv[1], argc, argv, "SPLIT_UM", -1, "0", NULL);
54 const double dt = scan_ctl(argv[1], argc, argv, "SPLIT_DT", -1, "0", NULL);
55 const double t0 = scan_ctl(argv[1], argc, argv, "SPLIT_T0", -1, "0", NULL);
56 const double t1 = scan_ctl(argv[1], argc, argv, "SPLIT_T1", -1, "0", NULL);
57 const double dz = scan_ctl(argv[1], argc, argv, "SPLIT_DZ", -1, "0", NULL);
58 const double z0 = scan_ctl(argv[1], argc, argv, "SPLIT_Z0", -1, "0", NULL);
59 const double z1 = scan_ctl(argv[1], argc, argv, "SPLIT_Z1", -1, "0", NULL);
60 const double dx = scan_ctl(argv[1], argc, argv, "SPLIT_DX", -1, "0", NULL);
61 const double lon0 =
62 scan_ctl(argv[1], argc, argv, "SPLIT_LON0", -1, "0", NULL);
63 const double lon1 =
64 scan_ctl(argv[1], argc, argv, "SPLIT_LON1", -1, "0", NULL);
65 const double lat0 =
66 scan_ctl(argv[1], argc, argv, "SPLIT_LAT0", -1, "0", NULL);
67 const double lat1 =
68 scan_ctl(argv[1], argc, argv, "SPLIT_LAT1", -1, "0", NULL);
69 scan_ctl(argv[1], argc, argv, "SPLIT_KERNEL", -1, "-", kernel);
70
71 /* Init random number generator... */
72 gsl_rng_env_setup();
73 gsl_rng *rng = gsl_rng_alloc(gsl_rng_default);
74
75 /* Read atmospheric data... */
76 if (!read_atm(argv[2], &ctl, atm))
77 ERRMSG("Cannot open file!");
78
79 /* Read kernel function... */
80 if (kernel[0] != '-') {
81 read_kernel(kernel, kz, kw, &nk);
82 zmax = gsl_stats_max(kz, 1, (size_t) nk);
83 zmin = gsl_stats_min(kz, 1, (size_t) nk);
84 }
85
86 /* Get total and maximum mass... */
87 if (ctl.qnt_m >= 0)
88 for (ip = 0; ip < atm->np; ip++) {
89 mtot += atm->q[ctl.qnt_m][ip];
90 mmax = MAX(mmax, atm->q[ctl.qnt_m][ip]);
91 }
92 if (m >= 0)
93 mtot = m;
94
95 /* Loop over air parcels... */
96 for (int i = 0; i < n; i++) {
97
98 /* Select air parcel... */
99 if (ctl.qnt_m >= 0)
100 do {
101 ip = (int) gsl_rng_uniform_int(rng, (long unsigned int) atm->np);
102 } while (gsl_rng_uniform(rng) > atm->q[ctl.qnt_m][ip] / mmax);
103 else
104 ip = (int) gsl_rng_uniform_int(rng, (long unsigned int) atm->np);
105
106 /* Set time... */
107 if (t1 > t0)
108 atm2->time[atm2->np] = t0 + (t1 - t0) * gsl_rng_uniform_pos(rng);
109 else
110 atm2->time[atm2->np] = atm->time[ip]
111 + gsl_ran_gaussian_ziggurat(rng, dt / 2.3548);
112
113 /* Set vertical position... */
114 do {
115 if (nk > 0) {
116 do {
117 z = zmin + (zmax - zmin) * gsl_rng_uniform_pos(rng);
118 k = kernel_weight(kz, kw, nk, P(z));
119 } while (gsl_rng_uniform(rng) > k);
120 atm2->p[atm2->np] = P(z);
121 } else if (z1 > z0)
122 atm2->p[atm2->np] = P(z0 + (z1 - z0) * gsl_rng_uniform_pos(rng));
123 else
124 atm2->p[atm2->np] = atm->p[ip]
125 + DZ2DP(gsl_ran_gaussian_ziggurat(rng, dz / 2.3548), atm->p[ip]);
126 } while (atm2->p[atm2->np] < P(100.) || atm2->p[atm2->np] > P(-1.));
127
128 /* Set horizontal position... */
129 if (lon1 > lon0 && lat1 > lat0) {
130 atm2->lon[atm2->np] = lon0 + (lon1 - lon0) * gsl_rng_uniform_pos(rng);
131 atm2->lat[atm2->np] = lat0 + (lat1 - lat0) * gsl_rng_uniform_pos(rng);
132 } else {
133 atm2->lon[atm2->np] = atm->lon[ip]
134 + gsl_ran_gaussian_ziggurat(rng, DX2DEG(dx, atm->lat[ip]) / 2.3548);
135 atm2->lat[atm2->np] = atm->lat[ip]
136 + gsl_ran_gaussian_ziggurat(rng, DY2DEG(dx) / 2.3548);
137 }
138
139 /* Copy quantities... */
140 for (int iq = 0; iq < ctl.nq; iq++)
141 atm2->q[iq][atm2->np] = atm->q[iq][ip];
142
143 /* Adjust mass... */
144 if (ctl.qnt_m >= 0)
145 atm2->q[ctl.qnt_m][atm2->np]
146 = (mtot + (um > 0 ? um * (gsl_rng_uniform_pos(rng) - 0.5) : 0.0)) / n;
147
148 /* Adjust air parcel index... */
149 if (ctl.qnt_idx >= 0)
150 atm2->q[ctl.qnt_idx][atm2->np] = atm2->np;
151
152 /* Increment particle counter... */
153 if ((++atm2->np) > NP)
154 ERRMSG("Too many air parcels!");
155 }
156
157 /* Save data and close file... */
158 write_atm(argv[3], &ctl, atm2, 0);
159
160 /* Free... */
161 free(atm);
162 free(atm2);
163
164 return EXIT_SUCCESS;
165}
int main(int argc, char *argv[])
Definition: atm_split.c:27
void 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:8874
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:5976
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:8503
void 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:5156
int 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:4566
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:1864
MPTRAC library declarations.
#define LEN
Maximum length of ASCII data lines.
Definition: mptrac.h:241
#define ERRMSG(...)
Print an error message with contextual information and terminate the program.
Definition: mptrac.h:1916
#define P(z)
Compute pressure at given altitude.
Definition: mptrac.h:1304
#define DX2DEG(dx, lat)
Convert a distance in kilometers to degrees longitude at a given latitude.
Definition: mptrac.h:525
#define DZ2DP(dz, p)
Convert a change in altitude to a change in pressure.
Definition: mptrac.h:562
#define ALLOC(ptr, type, n)
Allocate memory for a pointer with error handling.
Definition: mptrac.h:349
#define NP
Maximum number of atmospheric data points.
Definition: mptrac.h:246
#define EP
Maximum number of pressure levels for meteo data.
Definition: mptrac.h:261
#define DY2DEG(dy)
Convert a distance in kilometers to degrees latitude.
Definition: mptrac.h:543
#define MAX(a, b)
Macro to determine the maximum of two values.
Definition: mptrac.h:886
Air parcel data.
Definition: mptrac.h:3147
double time[NP]
Time [s].
Definition: mptrac.h:3153
double lat[NP]
Latitude [deg].
Definition: mptrac.h:3162
double lon[NP]
Longitude [deg].
Definition: mptrac.h:3159
int np
Number of air parcels.
Definition: mptrac.h:3150
double q[NQ][NP]
Quantity data (for various, user-defined attributes).
Definition: mptrac.h:3165
double p[NP]
Pressure [hPa].
Definition: mptrac.h:3156
Control parameters.
Definition: mptrac.h:2170
int qnt_m
Quantity array index for mass.
Definition: mptrac.h:2201
int qnt_idx
Quantity array index for air parcel IDs.
Definition: mptrac.h:2192
int nq
Number of quantities.
Definition: mptrac.h:2177