WSL/SLF GitLab Repository

Commit 63a71f48 authored by Mathias Bavay's avatar Mathias Bavay
Browse files

A little more cleanup (constification, mostly) in GSNIO as well as...

A little more cleanup (constification, mostly) in GSNIO as well as documentation. Updated the example io.ini. And a new data generator: Brutsaert for clear sky ILWR.
parent c1e141c6
......@@ -76,9 +76,9 @@ STATION6 = OTT2
; METEOPREFIX = _meteo
#GSN direct input -> GSN plugin
; ENDPOINT = http://montblanc.slf.ch:22002/services/GSNWebService
; ENDPOINT = http://planetdata.epfl.ch:22001/rest
; METEO = GSN
; ;ENDPOINT = http://gc3:swissex@montblanc.slf.ch:22002/services/GSNWebService
; ;ENDPOINT = http://montblanc.slf.ch:22001/rest
; STATION1 = imis_flu_2
; STATION2 = imis_slf_2
......
......@@ -35,6 +35,8 @@ GeneratorAlgorithm* GeneratorAlgorithmFactory::getAlgorithm(const std::string& i
return new SinGenerator(vecArgs, i_algoname);
} else if (algoname == "STD_PRESS"){
return new StandardPressureGenerator(vecArgs, i_algoname);
} else if (algoname == "BRUTSAERT"){
return new BrutsaertGenerator(vecArgs, i_algoname);
} else if (algoname == "UNSWORTH"){
return new UnsworthGenerator(vecArgs, i_algoname);
} else if (algoname == "POT_RADIATION"){
......@@ -173,6 +175,42 @@ bool StandardPressureGenerator::generate(const size_t& param, std::vector<MeteoD
return true; //all missing values could be filled
}
void BrutsaertGenerator::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 BrutsaertGenerator::generate(const size_t& param, MeteoData& md)
{
double &value = md(param);
if(value==IOUtils::nodata) {
const double TA=md(MeteoData::TA), RH=md(MeteoData::RH);
if(TA==IOUtils::nodata || RH==IOUtils::nodata) return false;
value = Atmosphere::Brutsaert_ilwr(RH, TA);
}
return true; //all missing values could be filled
}
bool BrutsaertGenerator::generate(const size_t& param, std::vector<MeteoData>& vecMeteo)
{
if(vecMeteo.empty()) return true;
bool all_filled = true;
for(size_t ii=0; ii<vecMeteo.size(); ii++) {
const bool status = generate(param, vecMeteo[ii]);
if(status==false) all_filled=false;
}
return all_filled;
}
const double UnsworthGenerator::soil_albedo = .23; //grass
const double UnsworthGenerator::snow_albedo = .85; //snow
const double UnsworthGenerator::snow_thresh = .1; //if snow height greater than this threshold -> snow albedo
......
......@@ -63,6 +63,7 @@ namespace mio {
* - 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)
* - SIN: sinusoidal variation (see SinGenerator)
* - BRUTSAERT: use a Brutsaert clear sky model to generate ILWR from TA, RH (see BrutsaertGenerator)
* - UNSWORTH: use a Dilley clear sky model coupled with an Unsworth cloud sky model to generate ILWR from TA, RH, ISWR (see UnsworthGenerator)
* - POT_RADIATION: generate the potential incoming short wave radiation, corrected for cloudiness if possible (see PotRadGenerator)
*
......@@ -173,6 +174,28 @@ class StandardPressureGenerator : public GeneratorAlgorithm {
void parse_args(const std::vector<std::string>& vecArgs);
};
/**
* @class BrutsaertGenerator
* @brief ILWR clear sky Brutsaert parametrization
* Use a Brutsaert clear sky model to estimate ILWR from RH, TA.
* This uses the formula from 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.
* Please keep in mind that for energy balance modeling, this significantly underestimate the ILWR input.
* @code
* ILWR::generators = BRUTSAERT
* @endcode
*
*/
class BrutsaertGenerator : public GeneratorAlgorithm {
public:
BrutsaertGenerator(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);
private:
void parse_args(const std::vector<std::string>& vecArgs);
};
/**
* @class UnsworthGenerator
* @brief ILWR parametrization using TA, RH, ISWR
......@@ -186,7 +209,7 @@ class StandardPressureGenerator : public GeneratorAlgorithm {
* 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.
* in order to compute ISWR from RSWR. Finally, if no short wave measurement is available, it uses a Dilley clear sky model.
* @code
* ILWR::generators = UNSWORTH
* @endcode
......@@ -214,8 +237,8 @@ class UnsworthGenerator : public GeneratorAlgorithm {
* (as a function of the location and the date). Please note that although this is the radiation as perceived
* 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
* 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).
* 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.
* @code
* ISWR::generators = POT_RADIATION
......
......@@ -79,6 +79,14 @@ namespace mio {
* If no STATION keys are given, the full list of ALL stations available to the user in GSN will be used!
* This may result in a long download.
*
* @code
* METEO = GSN
* GSN_URL = http://montblanc.slf.ch:22001/rest
* GSN_USER = mylogin
* GSN_PASS = mypasswd
* STATION1 = wind_tunnel_meteo
* @endcode
*
*/
const int GSNIO::http_timeout = 60; // seconds until connect time out for libcurl
......@@ -297,7 +305,6 @@ void GSNIO::readMeteoData(const Date& dateStart, const Date& dateEnd,
}
}
//cout << "Trying to fetch data for: " << dateStart.toString(Date::ISO) << " until " << dateEnd.toString(Date::ISO) << endl;
for (size_t ii=indexStart; ii<indexEnd; ii++){ //loop through stations
readData(dateStart, dateEnd, vecMeteo[ii], ii);
}
......@@ -309,11 +316,10 @@ void GSNIO::readData(const Date& dateStart, const Date& dateEnd, std::vector<Met
const string fields_str("# fields:");
const string units_str("# units:");
stringstream ss;
string request = sensors_endpoint + "/" + vecMeta[stationindex].stationID + "?from=" + dateStart.toString(Date::ISO) + ":00"
const string request = sensors_endpoint + "/" + vecMeta[stationindex].stationID + "?from=" + dateStart.toString(Date::ISO) + ":00"
+ "&to=" + dateEnd.toString(Date::ISO) + ":00" + "&username=" + userid + "&password=" + passwd;
//cout << "Requesting: " << request << endl;
stringstream ss;
if (curl_read(request, ss) == CURLE_OK) {
vector<size_t> index;
......@@ -355,8 +361,6 @@ void GSNIO::map_parameters(const std::string& fields, const std::string& units,
size_t timestamp_field = IOUtils::npos;
multiplier.clear();
offset.clear();
//cout << fields << endl;
//cout << units << endl;
IOUtils::readLineToVec(fields, field, ',');
IOUtils::readLineToVec(units, unit, ',');
......@@ -366,9 +370,9 @@ void GSNIO::map_parameters(const std::string& fields, const std::string& units,
}
for (size_t ii=0; ii<field.size(); ii++) {
const string field_name = IOUtils::strToUpper(field[ii]);
const string field_name( IOUtils::strToUpper(field[ii]) );
if (field_name == "RELATIVE_HUMIDITY" || field_name == "RH" || field_name == "AIR_HUMID") {
if (field_name == "RELATIVE_HUMIDITY" || field_name == "RH" || field_name == "AIR_HUMID" || field_name == "REL_HUMIDITY") {
index.push_back(MeteoData::RH);
} else if (field_name == "AIR_TEMPERATURE" || field_name == "TA" || field_name == "AIR_TEMP") {
index.push_back(MeteoData::TA);
......@@ -391,8 +395,10 @@ void GSNIO::map_parameters(const std::string& fields, const std::string& units,
index.push_back(MeteoData::HS);
} else if (field_name == "RAIN_METER" || field_name == "PINT") {
index.push_back(MeteoData::HNW);
} else if (field_name == "SURFACE_TEMP" || field_name == "TSS") {
} else if (field_name == "SURFACE_TEMP" || field_name == "TSS" || field_name == "SNOW_SURFACE_TEMPERATURE") {
index.push_back(MeteoData::TSS);
} else if (field_name == "ATM_PRESSURE" || field_name == "P") {
index.push_back(MeteoData::P);
} else if (field_name == "TIMESTAMP") {
timestamp_field = ii;
index.push_back(IOUtils::npos);
......@@ -400,12 +406,12 @@ void GSNIO::map_parameters(const std::string& fields, const std::string& units,
index.push_back(IOUtils::npos);
} else { //this is an extra parameter
md.addParameter(field_name);
size_t parindex = md.getParameterIndex(field_name);
const size_t parindex = md.getParameterIndex(field_name);
index.push_back(parindex);
//For the parameters unknown to MeteoIO we can store the units qualification °C, %, etc
//and make it possible for the values to be converted to MKSA in the convertUnits procedure
string name = unit[ii];
string name( unit[ii] );
IOUtils::trim(name);
if (name == "%") {
......@@ -423,7 +429,7 @@ void GSNIO::map_parameters(const std::string& fields, const std::string& units,
}
}
void GSNIO::parse_streamElement(const std::string& line, const std::vector<size_t>& index, const bool& olwr_present, std::vector<MeteoData>& vecMeteo, MeteoData& tmpmeteo)
void GSNIO::parse_streamElement(const std::string& line, const std::vector<size_t>& index, const bool& olwr_present, std::vector<MeteoData>& vecMeteo, MeteoData& tmpmeteo) const
{
static vector<string> data;
static double timestamp;
......@@ -486,7 +492,7 @@ void GSNIO::write2DGrid(const Grid2DObject&, const MeteoGrids::Parameters&, cons
throw IOException("Nothing implemented here", AT);
}
void GSNIO::convertUnits(MeteoData& meteo)
void GSNIO::convertUnits(MeteoData& meteo) const
{
//converts C to Kelvin, converts RH to [0,1]
double& ta = meteo(MeteoData::TA);
......@@ -526,7 +532,7 @@ size_t GSNIO::data_write(void* buf, size_t size, size_t nmemb, void* userp)
{
if (userp) {
ostream& os = *static_cast<ostream*>(userp);
streamsize len = size * nmemb;
const streamsize len = size * nmemb;
if (os.write(static_cast<char*>(buf), len)) return len;
}
......
......@@ -68,7 +68,7 @@ class GSNIO : public IOInterface {
virtual void write2DGrid(const Grid2DObject& grid_in, const MeteoGrids::Parameters& parameter, const Date& date);
private:
void convertUnits(MeteoData& meteo);
void convertUnits(MeteoData& meteo) const;
void initGSNConnection();
void readMetaData();
void getAllStations();
......@@ -76,9 +76,9 @@ class GSNIO : public IOInterface {
const double& alt, const double& slope_angle, const double& slope_azi);
void readData(const Date& dateStart, const Date& dateEnd, std::vector<MeteoData>& vecMeteo, const size_t& stationindex);
void map_parameters(const std::string& fields, const std::string& units, MeteoData& md, std::vector<size_t>& index);
double olwr_to_tss(const double& olwr);
static double olwr_to_tss(const double& olwr);
void parse_streamElement(const std::string& line, const std::vector<size_t>& index,
const bool& olwr_present, std::vector<MeteoData>& vecMeteo, MeteoData& tmpmeteo);
const bool& olwr_present, std::vector<MeteoData>& vecMeteo, MeteoData& tmpmeteo) const;
static size_t data_write(void* buf, size_t size, size_t nmemb, void* userp);
CURLcode curl_read(const std::string& url, std::ostream& os);
......
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