WSL/SLF GitLab Repository

Commit 87556084 authored by Mathias Bavay's avatar Mathias Bavay
Browse files

The default ilwr model in Atmosphere as been changed to Unsworth. The fixed...

The default ilwr model in Atmosphere as been changed to Unsworth. The fixed snow albedo has been set to 0.85 for all filters/generators using it. 

The Config class can now import an ini file from another ini file, this could greatly simplify the management of operational deployments (a station that has a special configuration now can simply import a standard config file and redefine what it needs). This is either done with IMPORT_BEFORE or IMPORT_AFTER in order to choose who has precedence. Multiple (ie recursive) inclusions are supported with some enforced limitations to prevent circular dependencies.
parent c7476e31
......@@ -16,6 +16,7 @@
along with MeteoIO. If not, see <http://www.gnu.org/licenses/>.
*/
#include <meteoio/Config.h>
#include <algorithm>
using namespace std;
......@@ -24,12 +25,12 @@ namespace mio {
const std::string Config::defaultSection = "GENERAL";
//Constructors
Config::Config() : properties(), sourcename()
Config::Config() : properties(), imported(), sourcename()
{
//nothing is even put in the property map, the user will have to fill it by himself
}
Config::Config(const std::string& i_filename) : properties(), sourcename(i_filename)
Config::Config(const std::string& i_filename) : properties(), imported(), sourcename(i_filename)
{
addFile(i_filename);
}
......@@ -168,12 +169,15 @@ void Config::parseFile(const std::string& filename)
std::string section=defaultSection;
const char eoln = IOUtils::getEoln(fin); //get the end of line character for the file
unsigned int linenr = 0;
std::vector<std::string> import_after; //files to import after the current one
bool accept_import_before = true;
imported.push_back(filename);
try {
do {
std::string line;
getline(fin, line, eoln); //read complete line
parseLine(linenr++, line, section);
parseLine(linenr++, import_after, accept_import_before, line, section);
} while(!fin.eof());
fin.close();
} catch(const std::exception&){
......@@ -182,9 +186,16 @@ void Config::parseFile(const std::string& filename)
}
throw;
}
std::reverse(import_after.begin(), import_after.end());
while(!import_after.empty()) {
const string filename = import_after.back();
addFile(filename);
import_after.pop_back();
}
}
void Config::parseLine(const unsigned int& linenr, std::string& line, std::string& section)
void Config::parseLine(const unsigned int& linenr, std::vector<std::string> &import_after, bool &accept_import_before, std::string &line, std::string &section)
{
//First thing cut away any possible comments (may start with "#" or ";")
IOUtils::stripComments(line);
......@@ -192,7 +203,9 @@ void Config::parseLine(const unsigned int& linenr, std::string& line, std::strin
if (line.empty()) //ignore empty lines
return;
if (line[0] == '['){
//if this is a section header, read it
if(line[0] == '[') {
accept_import_before = false; //this is not an import, so no further imports allowed
const size_t endpos = line.find_last_of(']');
if ((endpos == string::npos) || (endpos < 2) || (endpos != (line.length()-1))) {
stringstream tmp;
......@@ -205,12 +218,32 @@ void Config::parseLine(const unsigned int& linenr, std::string& line, std::strin
}
}
//At this point line can only be a key value pair
if (!IOUtils::readKeyValuePair(line, "=", properties, section+"::", true)) {
//this can only be a key value pair...
string key, value;
if(IOUtils::readKeyValuePair(line, "=", key, value, true)) {
if(key=="IMPORT_BEFORE") {
if(!accept_import_before)
throw IOException("Error in \""+sourcename+"\": IMPORT_BEFORE key MUST occur before any other key!", AT);
if(std::find(imported.begin(), imported.end(), value)!=imported.end())
throw IOException("Can not import again \"" + value + "\": it has already been imported!", AT);
parseFile(value);
return;
}
if(key=="IMPORT_AFTER") {
if(std::find(imported.begin(), imported.end(), value)!=imported.end())
throw IOException("Can not import again \"" + value + "\": it has already been imported!", AT);
import_after.push_back(value);
return;
}
properties[section+"::"+key] = value; //save the key/value pair
accept_import_before = false; //this is not an import, so no further import_before allowed
} else {
stringstream tmp;
tmp << linenr;
throw InvalidFormatException("Error reading key value pair in \"" + sourcename + "\" at line " + tmp.str(), AT);
}
}
//Return key/value filename
......
......@@ -42,8 +42,16 @@ namespace mio {
* - empty lines are ignored
* - if there is no section name given in a file, the default section called "GENERAL" is assumed
* - a VALUE for a KEY can consist of multiple whitespace separated values (e.g. MYNUMBERS = 17.77 -18.55 8888 99.99)
* @anchor config_import
* - it is possible to import another ini file, by specifying as many of the keys listed below as necessary.
* Please not that in order to prevent circular dependencies, it is not possible to import the same file several times.
* - IMPORT_BEFORE = {file and path to import}. This must take place before any non-import
* key or section header. This imports the specified file before processing the current file, allowing
* to overwrite the imported parameters in the current configuration file.
* - IMPORT_AFTER = {file and path to import}. This can occur anywhere and imports the specified file
* after processing the current file, allowing to overwrite the local parameters by the imported parameters.
*
* @author Thomas Egger
* @author Thomas Egger & Mathias Bavay
* @date 2008-11-30
*/
......@@ -269,10 +277,11 @@ class Config {
private:
void parseCmdLine(const std::string& cmd_line);
void parseFile(const std::string& filename);
void parseLine(const unsigned int& linenr, std::string& line, std::string& section);
void parseLine(const unsigned int& linenr, std::vector<std::string> &import_after, bool &accept_import_before, std::string &line, std::string &section);
std::string extract_section(std::string key) const;
std::map<std::string, std::string> properties; //Save key value pairs
std::vector<std::string> imported; //list of files already imported (to avoid circular references)
std::string sourcename; //description of the data source for the key/value pair
}; //end class definition Config
......
......@@ -167,7 +167,7 @@ bool StandardPressureGenerator::generate(const size_t& param, std::vector<MeteoD
}
const double UnsworthGenerator::soil_albedo = .23; //grass
const double UnsworthGenerator::snow_albedo = .56; //white surface
const double UnsworthGenerator::snow_albedo = .85; //snow
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)
......@@ -200,6 +200,8 @@ bool UnsworthGenerator::generate(const size_t& param, MeteoData& md)
}
} else {
albedo = RSWR / ISWR;
if(albedo>=1.) albedo=0.99;
if(albedo<=0.) albedo=0.01;
}
const double julian = md.date.getJulian(true);
......@@ -260,6 +262,8 @@ bool UnsworthGenerator::generate(const size_t& param, std::vector<MeteoData>& ve
}
} else {
albedo = RSWR / ISWR;
if(albedo>=1.) albedo=0.99;
if(albedo<=0.) albedo=0.01;
}
const double julian = vecMeteo[ii].date.getJulian(true);
......@@ -290,7 +294,7 @@ bool UnsworthGenerator::generate(const size_t& param, std::vector<MeteoData>& ve
}
const double PotRadGenerator::soil_albedo = .23; //grass
const double PotRadGenerator::snow_albedo = .56; //white surface
const double PotRadGenerator::snow_albedo = .85; //snow
const double PotRadGenerator::snow_thresh = .1; //if snow height greater than this threshold -> snow albedo
void PotRadGenerator::parse_args(const std::vector<std::string>& vecArgs)
{
......@@ -318,6 +322,8 @@ bool PotRadGenerator::generate(const size_t& param, MeteoData& md)
albedo = (HS>=snow_thresh)? snow_albedo : soil_albedo;
} else { //this could happen if the user calls this generator for a copy parameter, etc
albedo = RSWR / ISWR;
if(albedo>=1.) albedo=0.99;
if(albedo<=0.) albedo=0.01;
}
if(TA==IOUtils::nodata || RH==IOUtils::nodata) {
......@@ -371,6 +377,8 @@ bool PotRadGenerator::generate(const size_t& param, std::vector<MeteoData>& vecM
albedo = (HS>=snow_thresh)? snow_albedo : soil_albedo;
} else { //this could happen if the user calls this generator for a copy parameter, etc
albedo = RSWR / ISWR;
if(albedo>=1.) albedo=0.99;
if(albedo<=0.) albedo=0.01;
}
if(TA==IOUtils::nodata || RH==IOUtils::nodata) {
......
......@@ -212,20 +212,13 @@ bool isNumeric(std::string str, const unsigned int& nBase)
return ( iss.rdbuf()->in_avail() == 0 ); //true if nothing was left after conversion
}
bool readKeyValuePair(const std::string& in_line, const std::string& delimiter,
std::map<std::string,std::string>& out_map, const std::string& keyprefix, const bool& setToUpperCase)
bool readKeyValuePair(const std::string& in_line, const std::string& delimiter, std::string &key, std::string &value, const bool& setToUpperCase)
{
size_t pos;
if ((delimiter==" ") || (delimiter=="\t")) {
pos = in_line.find_first_of(" \t", 0);
} else {
pos = in_line.find(delimiter); //first occurence of '='
}
const size_t pos = ((delimiter==" ") || (delimiter=="\t"))? in_line.find_first_of(" \t", 0) : in_line.find(delimiter); //first occurence of delimiter
if(pos != std::string::npos) { //ignore in_lines that are empty or without '='
std::string key = in_line.substr(0, pos);
std::string value = in_line.substr(pos + 1);
key = in_line.substr(0, pos);
value = in_line.substr(pos + 1);
trim(key);
trim(value);
......@@ -236,10 +229,9 @@ bool readKeyValuePair(const std::string& in_line, const std::string& delimiter,
if (setToUpperCase)
toUpper(key);
out_map[keyprefix + key] = value;
} else {
key="";
value="";
return false;
}
......@@ -357,10 +349,12 @@ void readKeyValueHeader(std::map<std::string,std::string>& headermap,
for (size_t ii=0; ii< linecount; ii++){
if (std::getline(fin, line, eol)) {
std::string key, value;
linenr++;
const bool result = readKeyValuePair(line, delimiter, headermap);
if (!result) { // means if ((key == "") || (value==""))
const bool result = readKeyValuePair(line, delimiter, key, value);
if(result) {
headermap[key] = value;
} else { // means if ((key == "") || (value==""))
std::stringstream out;
out << "Invalid key value pair in line: " << linenr << " of header";
throw IOException(out.str(), AT);
......
......@@ -178,15 +178,13 @@ namespace IOUtils {
* @brief read a string line, parse it and save it into a map object, that is passed by reference
* @param in_line (const string&) string to parse
* @param delimiter (const string&) delimiter to use for the parsing
* @param out_map (map\<string,string\>&) map after parsing
* @param keyprefix this string is prefixed before the key, defaults to no prefix: ""
* @param setToUpperCase If set to true the key will be put into upper case (for case insensitivity)
* @param key retrieved key
* @param value retrieved value
* @return (bool) true when line is empty
*/
bool readKeyValuePair(const std::string& in_line,
const std::string& delimiter,
std::map<std::string,std::string>& out_map,
const std::string& keyprefix="", const bool& setToUpperCase=false);
bool readKeyValuePair(const std::string& in_line, const std::string& delimiter,
std::string &key, std::string &value, const bool& setToUpperCase=false);
void toUpper(std::string& str);
std::string strToUpper(const std::string &str);
......
......@@ -154,6 +154,8 @@ namespace mio {
*
* @endcode
*
* It is also possible (for advanced use) to import another configuration file, see in the \ref config_import "Config class" documentation.
*
* @subsection Finding_docs Where to find the proper documentation
* As can be seen from the previous example, each plugin, each filter or each interpolation algorithm might have its own parameters. Therefore, this is the documentation of each specific plugin/filter/algorithm that has to be used in order to figure out what can be configured when it (see the next sections in the welcome page).
*/
......
......@@ -24,7 +24,7 @@ namespace mio {
const double ProcUnventilatedT::dflt_albedo = .23;
const double ProcUnventilatedT::soil_albedo = .23; //grass
const double ProcUnventilatedT::snow_albedo = .56; //white surface
const double ProcUnventilatedT::snow_albedo = .85; //snow
const double ProcUnventilatedT::snow_thresh = .1; //if snow height greater than this threshold -> snow albedo
const double ProcUnventilatedT::vw_thresh = 0.1; //wind speed threshold
......
......@@ -559,7 +559,7 @@ double Atmosphere::ILWR_parametrized(const double& lat, const double& lon, const
return Omstedt_ilwr(RH, TA, cloudiness);
}
if(lat!=ND && lon!=ND && altitude!=ND && julian!=ND && TZ!=ND && RH!=ND && TA!=ND && ISWR!=ND && ISWR>iswr_thresh) {
const double ilwr_p = Crawford_ilwr(lat, lon, altitude, julian, TZ, RH, TA, ISWR);
const double ilwr_p = Unsworth_ilwr(lat, lon, altitude, julian, TZ, RH, TA, ISWR);
if(ilwr_p!=IOUtils::nodata) return ilwr_p; //it might have been that we could not compute (for low solar angles)
}
if(RH!=ND && TA!=ND) {
......
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