WSL/SLF GitLab Repository

GeneratorAlgorithms.h 11 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/***********************************************************************************/
/*  Copyright 2013 WSL Institute for Snow and Avalanche Research    SLF-DAVOS      */
/***********************************************************************************/
/* This file is part of MeteoIO.
    MeteoIO is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    MeteoIO is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with MeteoIO.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GENERATORALGORITHMS_H__
#define __GENERATORALGORITHMS_H__

#include <meteoio/MeteoData.h>
22
#include <meteoio/meteolaws/Sun.h>
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

#include <vector>
#include <set>
#include <string>

namespace mio {

/**
 * @page generators Data generators
 * Once the data has been read, filtered and resampled, it can be that some data points are still missing.
 * These are either a few isolated periods (a sensor was not functioning) that are too large for performing
 * a statistical temporal interpolation or that a meteorological parameter was not even measured. In such a case,
 * we generate data, generally relying on some parametrization using other meteorological parameters. In a few
 * cases, even fully arbitrary data might be helpful (replacing missing value by a given constant so a model can
 * run over the data gap).
 *
39
40
41
42
 * @note it is generally not advised to use data generators in combination with spatial interpolations as this would
 * potentially mix measured and generated values in the resulting grid. It is therefore advised to turn the data generators
 * off and let the spatial interpolations algorithms adjust to the amount of measured data.
 *
43
44
45
46
 * @section generators_section Data generators section
 * The data generators are defined per meteorological parameter. They are applied to all stations
 * (if using multiple meteorological stations). If multiple dat generators are specified for each parameter,
 * they would be used in the order of declaration, meaning that only the data points that could not be
47
48
 * generated by the first generator would be tentatively generated by the second generator, etc. Please also keep
 * in mind that at this stage, all data <b>must be in SI</b> units!
49
50
51
52
53
54
55
56
 * @code
 * [Generators]
 * RH::generators = CST
 * RH::Cst        = .7
 *
 * P::generators  = STD_PRESS
 * @endcode
 *
57
 * @section generators_keywords Available generators
58
59
60
 * The keywords defining the algorithms are the following:
 * - STD_PRESS: standard atmospheric pressure as a function of the elevation of each station (see StandardPressureGenerator)
 * - CST: constant value as provided in argument (see ConstGenerator)
61
 * - SIN: sinusoidal variation (see SinGenerator)
62
 * - UNSWORTH: use a Dilley clear sky model coupled with an Unsworth cloud sky model to generate ILWR from TA, RH, ISWR (see UnsworthGenerator)
63
 * - POT_RADIATION: generate the potential incoming short wave radiation, corrected for cloudiness if possible (see PotRadGenerator)
64
 *
65
 * @section generators_biblio Bibliography
66
67
68
69
 * The data generators have been inspired by the following papers:
 * - <i>"Long-wave radiation at the ground"</i>, Unsworth and Monteith, Q. J. R. Meteorolo. Soc., Vol. 101, 1975, pp 13-24
 * - <i>"Estimating downward clear sky long-wave irradiance at the surface from screen temperature and precipitable water"</i>, Dilley and O'Brien, Q. J. R. Meteorolo. Soc., Vol. 124, 1998, doi:10.1002/qj.49712454903
 * - <i>"Solar and terrestrial radiation dependent on the amount and type of cloud"</i>, Kasten and Czeplak, 1980, Solar energy, 24.2, pp 177-189
70
 * - <i>"Astronomical Algorithms"</i>, Meeus, second edition, 1998, Willmann-Bell, Inc., Richmond, VA, USA
71
72
 *
 *
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
 * @author Mathias Bavay
 * @date   2013-03-20
 */

/**
 * @class GeneratorAlgorithm
 * @brief Interface class for the generator models.
 * These models generate data for a specific parameter when all other options failed (the resampling could not help).
 * Therefore, there is nothing more that could be done with the temporal history of the data, we have to use
 * a totally different approach: either generic data (constant value, etc) or generate the data from other
 * meteorological parameters (relying on a parametrization, like clear sky for ILWR).
 *
 * @ingroup meteolaws
 * @author Mathias Bavay
 * @date   2013-03-20
*/
class GeneratorAlgorithm {

	public:
		GeneratorAlgorithm(const std::vector<std::string>& /*vecArgs*/, const std::string& i_algo) : algo(i_algo) {};
		virtual ~GeneratorAlgorithm() {}
		//fill one MeteoData, for one station
95
		virtual bool generate(const size_t& param, MeteoData& md) = 0;
96
		//fill one time series of MeteoData for one station
97
		virtual bool generate(const size_t& param, std::vector<MeteoData>& vecMeteo) = 0;
98
99
100
101
102
103
104
105
106
107
108
109
110
111
		std::string getAlgo() const;
 	protected:
		virtual void parse_args(const std::vector<std::string>& /*i_vecArgs*/) = 0;
		const std::string algo;
};

class GeneratorAlgorithmFactory {
	public:
		static GeneratorAlgorithm* getAlgorithm(const std::string& i_algoname, const std::vector<std::string>& vecArgs);
};

/**
 * @class ConstGenerator
 * @brief Constant value generator.
112
 * Generate a constant value for this parameter, as provided in argument (please remember that it must be in SI units).
113
114
115
116
117
118
119
120
121
 * @code
 * RH::generators = Cst
 * RH::Cst = .7
 * @endcode
 */
class ConstGenerator : public GeneratorAlgorithm {
	public:
		ConstGenerator(const std::vector<std::string>& vecArgs, const std::string& i_algo)
			: GeneratorAlgorithm(vecArgs, i_algo), constant(IOUtils::nodata) { parse_args(vecArgs); }
122
123
		bool generate(const size_t& param, MeteoData& md);
		bool generate(const size_t& param, std::vector<MeteoData>& vecMeteo);
124
125
126
127
128
	private:
		void parse_args(const std::vector<std::string>& vecArgs);
		double constant;
};

129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/**
 * @class SinGenerator
 * @brief Sinusoid generator.
 * Generate a sinusoidal variation for this parameter, as provided in argument (please remember that it must be in SI units).
 * The arguments that must be provided are the following: the sinusoidal period (either "yearly" or "daily"), the minimum value,
 * the maximum value and the offset specifying when the minimum value should be reached, within one period (expressed as fraction of such period).
 * The example below generates a yearly sinusoidal variation for the air temperature, the minimum being 268.26 K and occuring at 1/12
 * of the period (which practically means, at the end of the first month).
 * @code
 * TA::generators = Sin
 * TA::Sin = yearly 268.26 285.56 0.0833
 * @endcode
 */
class SinGenerator : public GeneratorAlgorithm {
	public:
		SinGenerator(const std::vector<std::string>& vecArgs, const std::string& i_algo)
			: GeneratorAlgorithm(vecArgs, i_algo), amplitude(IOUtils::nodata), offset(IOUtils::nodata), phase(IOUtils::nodata), type(' ') { parse_args(vecArgs); }
		bool generate(const size_t& param, MeteoData& md);
		bool generate(const size_t& param, std::vector<MeteoData>& vecMeteo);
	private:
		void parse_args(const std::vector<std::string>& vecArgs);
		double amplitude, offset, phase;
		char type;
};

154
155
156
157
158
159
160
161
/**
 * @class StandardPressureGenerator
 * @brief Standard atmospheric pressure generator.
 * Generate a standard atmosphere's pressure, depending on the local elevation.
 */
class StandardPressureGenerator : public GeneratorAlgorithm {
	public:
		StandardPressureGenerator(const std::vector<std::string>& vecArgs, const std::string& i_algo)
162
163
164
			: GeneratorAlgorithm(vecArgs, i_algo) { parse_args(vecArgs); }
		bool generate(const size_t& param, MeteoData& md);
		bool generate(const size_t& param, std::vector<MeteoData>& vecMeteo);
165
166
	private:
		void parse_args(const std::vector<std::string>& vecArgs);
167
168
169
170
171
172
173
174
175
176
177
178
179
180
};

/**
 * @class UnsworthGenerator
 * @brief ILWR parametrization using TA, RH, ISWR
 * Use a Dilley clear sky model coupled with an Unsworth cloud sky model to generate
 * ILWR from TA, RH, ISWR.
 * This uses the formula from Unsworth and Monteith -- <i>"Long-wave radiation at the ground"</i>,
 * Q. J. R. Meteorolo. Soc., Vol. 101, 1975, pp 13-24 coupled with a clear sky emissivity following Dilley, 1998.
 * A parametrization (according to Kasten and Czeplak (1980)) using the current location (lat, lon, altitude)
 * and ISWR is used to parametrize the cloud cover.
 * The last evaluation of cloudiness (as a ratio of cloudy_ilwr / clear_sky_ilwr) is used all along
 * during the times when no ISWR is available if such ratio is not too old (ie. no more than 1 day old).
 * If only RSWR is measured, the measured snow height is used to determine if there is snow on the ground or not.
181
 * In case of snow, a snow albedo of 0.85 is used while in the abscence of snow, a grass albedo of 0.23 is used
182
183
184
185
186
 * in order to compute ISWR from RSWR.
 */
class UnsworthGenerator : public GeneratorAlgorithm {
	public:
		UnsworthGenerator(const std::vector<std::string>& vecArgs, const std::string& i_algo)
187
			: GeneratorAlgorithm(vecArgs, i_algo), sun(), last_cloudiness_ratio(1.), last_cloudiness_julian(0.) { parse_args(vecArgs); }
188
189
190
191
		bool generate(const size_t& param, MeteoData& md);
		bool generate(const size_t& param, std::vector<MeteoData>& vecMeteo);
	private:
		void parse_args(const std::vector<std::string>& vecArgs);
192
		SunObject sun;
193
194
195
196
		double last_cloudiness_ratio; //last ratio of cloudiness
		double last_cloudiness_julian; //time of such ratio

		static const double soil_albedo, snow_albedo, snow_thresh; //to try using rswr if not iswr is given
197
198
};

199
200
201
202
203
/**
 * @class PotRadGenerator
 * @brief potential ISWR parametrization
 * This computes the potential incoming solar radiation, based on the position of the sun ine the sky
 * (as a function of the location and the date). Please note that although this is the radiation as perceived
204
205
 * at ground level (on the horizontal). If an incoming long wave measurement is available, it corrects the
 * generated iswr for cloudiness (basically doing like UnsworthGenerator in reverse), otherwise this assumes
206
207
208
 * clear sky! If no TA or RH is available, average values will be used
 * (in order to get an average value for the precipitable water vapor).
 * @note This relies on SunObject to perform the heavy duty computation.
209
210
211
212
213
214
215
216
217
 */
class PotRadGenerator : public GeneratorAlgorithm {
	public:
		PotRadGenerator(const std::vector<std::string>& vecArgs, const std::string& i_algo)
			: GeneratorAlgorithm(vecArgs, i_algo), sun() { parse_args(vecArgs); }
		bool generate(const size_t& param, MeteoData& md);
		bool generate(const size_t& param, std::vector<MeteoData>& vecMeteo);
	private:
		void parse_args(const std::vector<std::string>& vecArgs);
218
		double getSolarIndex(const double& ta, const double& rh, const double& ilwr);
219
220
221
222
223
		SunObject sun;

		static const double soil_albedo, snow_albedo, snow_thresh; //to try using rswr if not iswr is given
};

224
225
226
} //end namespace mio

#endif