WSL/SLF GitLab Repository

GeneratorAlgorithms.h 17.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/***********************************************************************************/
/*  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__

21
22
#include <meteoio/dataClasses/MeteoData.h>
#include <meteoio/meteoLaws/Sun.h>
23
24
25
26
27

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

28
#ifdef _MSC_VER
29
30
31
	#pragma warning(disable:4512) //we don't need any = operator!
#endif

32
33
34
35
36
37
38
39
40
41
42
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).
 *
43
44
 * Another usage scenario is to create new parameters fully based on parametrizations. In such a case, the "generator" is called
 * a "creator" and behaves the same way as a generator, except that it creates an additional parameter. It is declared as
45
 * {new_parameter}::%create = {data generators}.
46
 *
47
48
49
50
 * @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.
 *
51
52
53
54
 * @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
55
56
 * 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!
57
58
59
60
61
62
 * @code
 * [Generators]
 * RH::generators = CST
 * RH::Cst        = .7
 *
 * P::generators  = STD_PRESS
63
 *
64
 * ILWR::generators = AllSky_LW ClearSky_LW
65
66
67
 *
 * TAU_CLD::create  = CST
 * TA_CLD::Cst      = 0.5
68
69
 * @endcode
 *
70
 * @section generators_keywords Available generators
71
72
 * The keywords defining the algorithms are the following:
 * - STD_PRESS: standard atmospheric pressure as a function of the elevation of each station (see StandardPressureGenerator)
73
 * - RELHUM: relative humidity from other humidity measurements (see RhGenerator)
74
 * - CST: constant value as provided in argument (see ConstGenerator)
75
 * - SIN: sinusoidal variation (see SinGenerator)
76
77
 * - CLEARSKY_LW: use a clear sky model to generate ILWR from TA, RH (see ClearSkyLWGenerator)
 * - ALLSKY_LW: use an all sky model to generate ILWR from TA, RH and cloudiness (see AllSkyLWGenerator)
78
 * - POT_RADIATION: generate the potential incoming short wave radiation, corrected for cloudiness if possible (see PotRadGenerator)
79
 *
80
 * @section generators_biblio Bibliography
81
 * The data generators have been inspired by the following papers:
82
83
84
 * - Brutsaert -- <i>"On a Derivable Formula for Long-Wave Radiation From Clear Skies"</i>, Journal of Water Resources
 * Research, <b>11</b>, No. 5, October 1975, pp 742-744.
 * - Prata -- <i>"A new long-wave formula for estimating downward clear-sky radiation at the surface"</i>, Q. J. R. Meteorolo. Soc., <b>122</b>, 1996, pp 1127-1151.
Mathias Bavay's avatar
Mathias Bavay committed
85
 * - Dilley and O'Brien -- <i>"Estimating downward clear sky long-wave irradiance at the surface from screen temperature and precipitable water"</i>, Q. J. R. Meteorolo. Soc., Vol. 124, 1998, doi:10.1002/qj.49712454903
86
87
 * - Clark & Allen -- <i>"The estimation of atmospheric radiation for clear and cloudy skies"</i>, Proceedings of the second national passive solar conference, <b>2</b>, 1978, p 676.
 * - Tang et al. -- <i>"Estimates of clear night sky emissivity in the Negev Highlands, Israel"</i>, Energy Conversion and Management, <b>45.11</b>, 2004, pp 1831-1843.
88
 * - Idso -- <i>"A set of equations for full spectrum and 8 to 14 um and 10.5 to 12.5 um thermal radiation from cloudless skies"</i>, Water Resources Research, <b>17</b>, 1981, pp 295-304.
89
90
91
92
93
94
95
 * - Kasten and Czeplak -- <i>"Solar and terrestrial radiation dependent on the amount and type of cloud"</i>, 1980, Solar energy, 24.2, pp 177-189
 * - Omstedt -- <i>"A coupled one-dimensional sea ice-ocean model applied to a semi-enclosed basin"</i>, Tellus, <b>42 A</b>, 568-582, 1990, DOI:10.1034/j.1600-0870.1990.t01-3-00007.
 * - Konzelmann et al. -- <i>"Parameterization of global and longwave incoming radiation for the Greenland Ice Sheet."</i> Global and Planetary change <b>9.1</b> (1994): 143-164.
 * - Crawford and Duchon -- <i>"An Improved Parametrization for Estimating Effective Atmospheric Emissivity for Use in Calculating Daytime
 * Downwelling Longwave Radiation"</i>, Journal of Applied Meteorology, <b>38</b>, 1999, pp 474-480
 * - Unsworth and Monteith -- <i>"Long-wave radiation at the ground"</i>, Q. J. R. Meteorolo. Soc., Vol. 101, 1975, pp 13-24
 * - Meeus -- <i>"Astronomical Algorithms"</i>, second edition, 1998, Willmann-Bell, Inc., Richmond, VA, USA
96
97
 *
 *
98
99
100
101
102
103
104
105
106
107
108
109
 * @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).
 *
110
 * @ingroup meteoLaws
111
112
113
114
115
116
117
118
119
 * @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
120
		virtual bool generate(const size_t& param, MeteoData& md) = 0;
121
		//fill one time series of MeteoData for one station
122
		virtual bool generate(const size_t& param, std::vector<MeteoData>& vecMeteo) = 0;
123
124
		std::string getAlgo() const;
 	protected:
125
		virtual void parse_args(const std::vector<std::string>& i_vecArgs);
126
127
128
129
130
131
132
133
134
135
136
		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.
137
 * Generate a constant value for this parameter, as provided in argument (please remember that it must be in SI units).
138
139
140
141
142
143
144
145
146
 * @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); }
147
148
		bool generate(const size_t& param, MeteoData& md);
		bool generate(const size_t& param, std::vector<MeteoData>& vecMeteo);
149
150
151
152
153
	private:
		void parse_args(const std::vector<std::string>& vecArgs);
		double constant;
};

154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/**
 * @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;
};

179
180
181
182
/**
 * @class StandardPressureGenerator
 * @brief Standard atmospheric pressure generator.
 * Generate a standard atmosphere's pressure, depending on the local elevation.
183
 * @code
184
185
 * P::generators = STD_PRESS
 * @endcode
186
187
188
189
 */
class StandardPressureGenerator : public GeneratorAlgorithm {
	public:
		StandardPressureGenerator(const std::vector<std::string>& vecArgs, const std::string& i_algo)
190
191
192
193
194
			: 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);
};

195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
/**
 * @class RhGenerator
 * @brief Relative humidity generator.
 * Generate the relative humidity from either dew point temperature or specific humidity and air temperature.
 * The dew point temperature must be named "TD" and the specific humidity "SH"
 * @code
 * RH::generators = RELHUM
 * @endcode
 */
class RhGenerator : public GeneratorAlgorithm {
	public:
		RhGenerator(const std::vector<std::string>& vecArgs, const std::string& i_algo)
			: 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);
};


213
/**
214
 * @class ClearSkyLWGenerator
215
216
 * @brief ILWR clear sky parametrization
 * Using air temperature (TA) and relative humidity (RH), this offers the choice of several clear sky parametrizations:
217
 *  - BRUTSAERT -- from Brutsaert, <i>"On a Derivable Formula for Long-Wave Radiation From Clear Skies"</i>,
218
 * Journal of Water Resources Research, <b>11</b>, No. 5, October 1975, pp 742-744.
219
 *  - DILLEY -- from Dilley and O'Brien, <i>"Estimating downward clear sky
220
 * long-wave irradiance at the surface from screen temperature and precipitable water"</i>, Q. J. R. Meteorolo. Soc., <b>124</b>, 1998, pp 1391-1401.
221
 *  - PRATA -- from Prata, <i>"A new long-wave formula for estimating downward clear-sky radiation at the surface"</i>, Q. J. R. Meteorolo. Soc., <b>122</b>, 1996, pp 1127-1151.
222
223
224
225
 *  - CLARK -- from Clark & Allen, <i>"The estimation of atmospheric radiation for clear and
 * cloudy skies"</i>, Proceedings of the second national passive solar conference, <b>2</b>, 1978, p 676.
 *  - TANG -- from Tang et al., <i>"Estimates of clear night sky emissivity in the
 * Negev Highlands, Israel"</i>, Energy Conversion and Management, <b>45.11</b>, 2004, pp 1831-1843.
226
227
228
 *  - IDSO -- from Idso, <i>"A set of equations for full spectrum and 8 to 14 um and
 * 10.5 to 12.5 um thermal radiation from cloudless skies"</i>, Water Resources Research, <b>17</b>, 1981, pp 295-304.
 *
229
230
 * Please keep in mind that for energy balance modeling, this significantly underestimate the ILWR input.
 * @code
231
232
 * ILWR::generators = clearsky_LW
 * ILWR::clearsky_lw = Dilley
233
234
235
 * @endcode
 *
 */
236
class ClearSkyLWGenerator : public GeneratorAlgorithm {
237
	public:
238
		ClearSkyLWGenerator(const std::vector<std::string>& vecArgs, const std::string& i_algo)
239
			: GeneratorAlgorithm(vecArgs, i_algo), model(BRUTSAERT) { parse_args(vecArgs); }
240
241
		bool generate(const size_t& param, MeteoData& md);
		bool generate(const size_t& param, std::vector<MeteoData>& vecMeteo);
242
243
244
245
246
	private:
		void parse_args(const std::vector<std::string>& vecArgs);
		typedef enum PARAMETRIZATION {
			BRUTSAERT,
			DILLEY,
247
248
			PRATA,
			CLARK,
249
250
			TANG,
			IDSO
251
252
		} parametrization;
		parametrization model;
253
254
255
};

/**
256
 * @class AllSkyLWGenerator
257
 * @brief ILWR all sky parametrization
258
 * Using air temperature (TA) and relative humidity (RH) and optionnally cloud fraction (TAU_CLD, but please note that this name is not definitive yet),
259
 * this offers the choice of several all-sky parametrizations:
260
 *  - OMSTEDT -- from Omstedt, <i>"A coupled one-dimensional sea ice-ocean model applied to a semi-enclosed basin"</i>,
261
 * Tellus, <b>42 A</b>, 568-582, 1990, DOI:10.1034/j.1600-0870.1990.t01-3-00007.
262
 *  - KONZELMANN -- from Konzelmann et al., <i>"Parameterization of global and longwave incoming radiation
263
 * for the Greenland Ice Sheet."</i> Global and Planetary change <b>9.1</b> (1994): 143-164.
264
265
266
 *  - UNSWORTH -- 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).
 *  - CRAWFORD -- from Crawford and Duchon, <i>"An Improved Parametrization for Estimating Effective Atmospheric Emissivity for Use in Calculating Daytime
267
 * Downwelling Longwave Radiation"</i>, Journal of Applied Meteorology, <b>38</b>, 1999, pp 474-480
268
 *
269
270
271
272
273
274
275
276
277
278
 * If no cloudiness is provided in the data, it is calculated from the solar index (ratio of measured iswr to potential iswr, therefore using
 * the current location (lat, lon, altitude) and ISWR to parametrize the cloud cover). This relies on (Kasten and Czeplak, 1980)
 * except for Crawfor that provides its own parametrization.
 * The last evaluation of cloudiness 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.
 * 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
 * in order to compute ISWR from RSWR.
 * Finally, it is recommended to also use a clear sky generator (declared after this one)
 * for the case of no available short wave measurement (by declaring the ClearSky generator \em after AllSky).
279
 * @code
280
281
 * ILWR::generators = allsky_LW
 * ILWR::allsky_lw = Omstedt
282
283
284
 * @endcode
 *
 */
285
class AllSkyLWGenerator : public GeneratorAlgorithm {
286
	public:
287
		AllSkyLWGenerator(const std::vector<std::string>& vecArgs, const std::string& i_algo)
288
		               : GeneratorAlgorithm(vecArgs, i_algo), model(OMSTEDT), clf_model(KASTEN),
289
		                 last_cloudiness() { parse_args(vecArgs); }
290
291
		bool generate(const size_t& param, MeteoData& md);
		bool generate(const size_t& param, std::vector<MeteoData>& vecMeteo);
292
293
	private:
		void parse_args(const std::vector<std::string>& vecArgs);
294
295
		double getCloudiness(const MeteoData& md, SunObject& sun, bool &is_night);

296
297
298
299
300
301
302
		typedef enum PARAMETRIZATION {
			OMSTEDT,
			KONZELMANN,
			UNSWORTH,
			CRAWFORD
		} parametrization;
		parametrization model;
303
304
305
306
307
308
309

		typedef enum CLF_PARAMETRIZATION {
			KASTEN,
			CLF_CRAWFORD
		} clf_parametrization;
		clf_parametrization clf_model;

310
		std::map< std::string, std::pair<double, double> > last_cloudiness; //as < station_hash, <julian_gmt, cloudiness> >
311
312

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

315
316
317
318
319
/**
 * @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
320
321
 * 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
322
323
 * 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).
324
 * @note This relies on SunObject to perform the heavy duty computation.
325
326
327
 * @code
 * ISWR::generators = POT_RADIATION
 * @endcode
328
329
330
331
332
333
334
335
336
 */
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);
337
		double getSolarIndex(const double& ta, const double& rh, const double& ilwr);
338
339
340
341
342
		SunObject sun;

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

343
344
345
class HSSweGenerator : public GeneratorAlgorithm {
	public:
		HSSweGenerator(const std::vector<std::string>& vecArgs, const std::string& i_algo)
346
			: GeneratorAlgorithm(vecArgs, i_algo) { parse_args(vecArgs); }
347
348
		bool generate(const size_t& param, MeteoData& md);
		bool generate(const size_t& param, std::vector<MeteoData>& vecMeteo);
349

350
351
352
353
354
355
356
	private:
		void parse_args(const std::vector<std::string>& vecArgs);
		double newSnowDensity(const MeteoData& md) const;

		static const bool soft;
};

357
358
359
} //end namespace mio

#endif