WSL/SLF GitLab Repository

Commit 4265c012 authored by Mathias Bavay's avatar Mathias Bavay
Browse files

A buf in some unsworth implementation in Atmosphere has been fixed (check with...

A buf in some unsworth implementation in Atmosphere has been fixed (check with nodata). The order of the meteodata fields has been changed because this directly impacts the order of the processing of the fields (the goal being that fields that are often checked with a combination of other fields get processed in the end).

The unsworth_dilley ILWR data generator has been implemented with the usage of the last cloudiness during the night as well as the usage of a generic snow albedo (or grass albedo) to convert RSWR to ISWR (if necessary) coupled with a threshold on the snow height.
parent 82b555ad
......@@ -32,6 +32,8 @@ GeneratorAlgorithm* GeneratorAlgorithmFactory::getAlgorithm(const std::string& i
return new ConstGenerator(vecArgs, i_algoname);
} else if (algoname == "STD_PRESS"){
return new StandardPressureGenerator(vecArgs, i_algoname);
} else if (algoname == "UNSWORTH"){
return new UnsworthGenerator(vecArgs, i_algoname);
} else {
throw IOException("The generator algorithm '"+algoname+"' is not implemented" , AT);
}
......@@ -53,7 +55,7 @@ void ConstGenerator::parse_args(const std::vector<std::string>& vecArgs)
}
}
bool ConstGenerator::generate(const size_t& param, MeteoData& md) const
bool ConstGenerator::generate(const size_t& param, MeteoData& md)
{
double &value = md(param);
if(value == IOUtils::nodata)
......@@ -62,7 +64,7 @@ bool ConstGenerator::generate(const size_t& param, MeteoData& md) const
return true; //all missing values could be filled
}
bool ConstGenerator::generate(const size_t& param, std::vector<MeteoData>& vecMeteo) const
bool ConstGenerator::generate(const size_t& param, std::vector<MeteoData>& vecMeteo)
{
if(vecMeteo.empty()) return true;
......@@ -81,7 +83,7 @@ void StandardPressureGenerator::parse_args(const std::vector<std::string>& vecAr
}
}
bool StandardPressureGenerator::generate(const size_t& param, MeteoData& md) const
bool StandardPressureGenerator::generate(const size_t& param, MeteoData& md)
{
if(param!=MeteoData::P) {
stringstream ss;
......@@ -99,7 +101,7 @@ bool StandardPressureGenerator::generate(const size_t& param, MeteoData& md) con
return true; //all missing values could be filled
}
bool StandardPressureGenerator::generate(const size_t& param, std::vector<MeteoData>& vecMeteo) const
bool StandardPressureGenerator::generate(const size_t& param, std::vector<MeteoData>& vecMeteo)
{
if(param!=MeteoData::P) {
stringstream ss;
......@@ -109,7 +111,7 @@ bool StandardPressureGenerator::generate(const size_t& param, std::vector<MeteoD
if(vecMeteo.empty()) return true;
const double altitude = vecMeteo[0].meta.position.getAltitude(); //if the stations move, this has to be in the loop
const double altitude = vecMeteo.front().meta.position.getAltitude(); //if the stations move, this has to be in the loop
if(altitude==IOUtils::nodata) return false;
for(size_t ii=0; ii<vecMeteo.size(); ii++) {
......@@ -121,5 +123,109 @@ bool StandardPressureGenerator::generate(const size_t& param, std::vector<MeteoD
return true; //all missing values could be filled
}
const double UnsworthGenerator::soil_albedo = .23; //grass
const double UnsworthGenerator::snow_albedo = .56; //white surface
const double UnsworthGenerator::snow_thresh = .1; //if snow height greater than this threshold -> snow albedo
void UnsworthGenerator::parse_args(const std::vector<std::string>& vecArgs)
{
//Get the optional arguments for the algorithm: constant value to use
if(!vecArgs.empty()) { //incorrect arguments, throw an exception
throw InvalidArgumentException("Wrong number of arguments supplied for the "+algo+" generator", AT);
}
}
bool UnsworthGenerator::generate(const size_t& param, MeteoData& md)
{
if(param!=MeteoData::ILWR) {
stringstream ss;
ss << "Can not use " << algo << " generator on " << MeteoData::getParameterName(param);
throw InvalidArgumentException(ss.str(), AT);
}
const double lat = md.meta.position.getLat();
const double lon = md.meta.position.getLon();
const double alt = md.meta.position.getAltitude();
double &value = md(param);
const double TA=md(MeteoData::TA), RH=md(MeteoData::RH), HS=md(MeteoData::HS), RSWR=md(MeteoData::RSWR);
double ISWR=md(MeteoData::ISWR);
if(TA==IOUtils::nodata || RH==IOUtils::nodata) return false;
if(ISWR==IOUtils::nodata && (RSWR!=IOUtils::nodata && HS!=IOUtils::nodata)) {
if(HS<snow_thresh) ISWR = RSWR * soil_albedo;
else ISWR = RSWR * snow_albedo;
}
const double julian = md.date.getJulian(true);
const double ilwr_dilley = Atmosphere::Dilley_ilwr(RH, TA);
const double ilwr_no_iswr = ((julian - last_cloudiness_julian) < 1.)? ilwr_dilley*last_cloudiness_ratio : ilwr_dilley;
if(ISWR==IOUtils::nodata || ISWR<5.) {
value = ilwr_no_iswr;
} else {
const double ilwr_uns = Atmosphere::Unsworth_ilwr(lat, lon, alt, julian, 0., RH, TA, ISWR);
if(ilwr_uns==IOUtils::nodata || ilwr_uns<=0) {
value = ilwr_no_iswr;
return true;
}
last_cloudiness_ratio = ilwr_uns / ilwr_dilley;
last_cloudiness_julian = julian;
value = ilwr_uns;
}
return true; //all missing values could be filled
}
bool UnsworthGenerator::generate(const size_t& param, std::vector<MeteoData>& vecMeteo)
{
if(param!=MeteoData::ILWR) {
stringstream ss;
ss << "Can not use " << algo << " generator on " << MeteoData::getParameterName(param);
throw InvalidArgumentException(ss.str(), AT);
}
if(vecMeteo.empty()) return true;
const double lat = vecMeteo.front().meta.position.getLat();
const double lon = vecMeteo.front().meta.position.getLon();
const double alt = vecMeteo.front().meta.position.getAltitude();
bool all_filled = true;
for(size_t ii=0; ii<vecMeteo.size(); ii++) {
double &value = vecMeteo[ii](param);
const double TA=vecMeteo[ii](MeteoData::TA), RH=vecMeteo[ii](MeteoData::RH), HS=vecMeteo[ii](MeteoData::HS), RSWR=vecMeteo[ii](MeteoData::RSWR);
double ISWR=vecMeteo[ii](MeteoData::ISWR);
if(TA==IOUtils::nodata || RH==IOUtils::nodata) {
all_filled = false;
continue;
}
if(ISWR==IOUtils::nodata && (RSWR!=IOUtils::nodata && HS!=IOUtils::nodata)) {
if(HS<snow_thresh) ISWR = RSWR * soil_albedo;
else ISWR = RSWR * snow_albedo;
}
const double julian = vecMeteo[ii].date.getJulian(true);
const double ilwr_dilley = Atmosphere::Dilley_ilwr(RH, TA);
const double ilwr_no_iswr = ((julian - last_cloudiness_julian) < 1.)? ilwr_dilley*last_cloudiness_ratio : ilwr_dilley;
if(ISWR==IOUtils::nodata || ISWR<5.) {
value = ilwr_no_iswr;
} else {
const double ilwr_uns = Atmosphere::Unsworth_ilwr(lat, lon, alt, julian, 0., RH, TA, ISWR);
if(ilwr_uns==IOUtils::nodata || ilwr_uns<=0) {
value = ilwr_no_iswr;
continue;
}
last_cloudiness_ratio = ilwr_uns / ilwr_dilley;
last_cloudiness_julian = julian;
value = ilwr_uns;
}
}
return all_filled;
}
} //namespace
......@@ -52,6 +52,7 @@ namespace mio {
* 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)
* - UNSWORTH: use a Dilley clear sky model coupled with an Unsworth cloud sky model to generate ILWR from TA, RH, ISWR (see UnsworthGenerator)
*
* @author Mathias Bavay
* @date 2013-03-20
......@@ -75,9 +76,9 @@ class GeneratorAlgorithm {
GeneratorAlgorithm(const std::vector<std::string>& /*vecArgs*/, const std::string& i_algo) : algo(i_algo) {};
virtual ~GeneratorAlgorithm() {}
//fill one MeteoData, for one station
virtual bool generate(const size_t& param, MeteoData& md) const = 0;
virtual bool generate(const size_t& param, MeteoData& md) = 0;
//fill one time series of MeteoData for one station
virtual bool generate(const size_t& param, std::vector<MeteoData>& vecMeteo) const = 0;
virtual bool generate(const size_t& param, std::vector<MeteoData>& vecMeteo) = 0;
std::string getAlgo() const;
protected:
virtual void parse_args(const std::vector<std::string>& /*i_vecArgs*/) = 0;
......@@ -102,8 +103,8 @@ 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); }
bool generate(const size_t& param, MeteoData& md) const;
bool generate(const size_t& param, std::vector<MeteoData>& vecMeteo) const;
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 constant;
......@@ -117,12 +118,40 @@ class ConstGenerator : public GeneratorAlgorithm {
class StandardPressureGenerator : public GeneratorAlgorithm {
public:
StandardPressureGenerator(const std::vector<std::string>& vecArgs, const std::string& i_algo)
: GeneratorAlgorithm(vecArgs, i_algo), constant(IOUtils::nodata) { parse_args(vecArgs); }
bool generate(const size_t& param, MeteoData& md) const;
bool generate(const size_t& param, std::vector<MeteoData>& vecMeteo) const;
: 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);
private:
void parse_args(const std::vector<std::string>& vecArgs);
double constant;
};
/**
* @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.
* In case of snow, a snow albedo of 0.56 is used while in the abscence of snow, a grass albedo of 0.23 is used
* in order to compute ISWR from RSWR.
*/
class UnsworthGenerator : public GeneratorAlgorithm {
public:
UnsworthGenerator(const std::vector<std::string>& vecArgs, const std::string& i_algo)
: GeneratorAlgorithm(vecArgs, i_algo), last_cloudiness_ratio(1.), last_cloudiness_julian(0.) { 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 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
};
} //end namespace mio
......
......@@ -80,33 +80,33 @@ const bool MeteoData::__init = MeteoData::initStaticData();
bool MeteoData::initStaticData()
{
//Associate unsigned int value and a string representation of a meteo parameter
static_meteoparamname[P] = "P";
static_meteoparamname[TA] = "TA";
static_meteoparamname[ISWR] = "ISWR";
static_meteoparamname[VW] = "VW";
static_meteoparamname[DW] = "DW";
static_meteoparamname[VW_MAX] = "VW_MAX";
static_meteoparamname[RH] = "RH";
static_meteoparamname[ILWR] = "ILWR";
static_meteoparamname[HNW] = "HNW";
static_meteoparamname[TSG] = "TSG";
static_meteoparamname[TSS] = "TSS";
static_meteoparamname[HS] = "HS";
static_meteoparamname[VW] = "VW";
static_meteoparamname[DW] = "DW";
static_meteoparamname[VW_MAX] = "VW_MAX";
static_meteoparamname[RSWR] = "RSWR";
static_meteoparamname[P] = "P";
static_meteoparamname[ISWR] = "ISWR";
static_meteoparamname[ILWR] = "ILWR";
static_meteoparamname[HNW] = "HNW";
s_default_paramname.push_back("P");
s_default_paramname.push_back("TA");
s_default_paramname.push_back("RH");
s_default_paramname.push_back("TSG");
s_default_paramname.push_back("TSS");
s_default_paramname.push_back("HS");
s_default_paramname.push_back("VW");
s_default_paramname.push_back("DW");
s_default_paramname.push_back("VW_MAX");
s_default_paramname.push_back("ISWR");
s_default_paramname.push_back("RSWR");
s_default_paramname.push_back("ISWR");
s_default_paramname.push_back("ILWR");
s_default_paramname.push_back("HS");
s_default_paramname.push_back("HNW");
s_default_paramname.push_back("TSG");
s_default_paramname.push_back("TSS");
s_default_paramname.push_back("P");
return true;
}
......
......@@ -100,20 +100,20 @@ class MeteoData {
public:
/// \anchor meteoparam this enum provides indexed access to meteorological fields
enum Parameters {firstparam=0,
TA=firstparam, ///< Air temperature
P=firstparam, ///< Air pressure
TA, ///< Air temperature
RH, ///< Relative humidity
TSG, ///< Temperature of the ground surface
TSS, ///< Temperature of the snow surface
HS, ///< Height of snow
VW, ///< Wind velocity
DW, ///< Wind direction
VW_MAX, ///< Maximum wind velocity
ISWR, ///< Incoming short wave radiation
RSWR, ///< Reflected short wave radiation
ISWR, ///< Incoming short wave radiation
ILWR, ///< Incoming long wave radiation (downwelling)
HS, ///< Height of snow
HNW, ///< Water equivalent (water depth) of precipitations, either solid or liquid
TSG, ///< Temperature of the ground surface
TSS, ///< Temperature of the snow surface
P, ///< Air pressure
lastparam=P};
lastparam=HNW};
static const std::string& getParameterName(const size_t& parindex);
......
......@@ -475,7 +475,7 @@ double Atmosphere::Crawford_ilwr(const double& lat, const double& lon, const dou
double Atmosphere::Unsworth_ilwr(const double& RH, const double& TA, const double& iswr_meas, const double& iswr_clear_sky, const double& cloudiness)
{
double c;
if(cloudiness==IOUtils::nodata) {
if(cloudiness!=IOUtils::nodata) {
if(cloudiness<0. || cloudiness>1.)
return IOUtils::nodata;
c = cloudiness;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment