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