WSL/SLF GitLab Repository

Commit 978d5b96 authored by Mathias Bavay's avatar Mathias Bavay
Browse files

New possibilities for the Unventillated_T filter (according to issue 374).

parent 576d0a6c
......@@ -30,7 +30,7 @@ const double ProcUnventilatedT::vw_thresh = 0.1; //wind speed threshold
ProcUnventilatedT::ProcUnventilatedT(const std::vector<std::string>& vec_args, const std::string& name)
: ProcessingBlock(name), usr_albedo(dflt_albedo),
is_soft(true), nakamura(true)
usr_vw_thresh(IOUtils::nodata), nakamura(false)
{
parse_args(vec_args);
properties.stage = ProcessingProperties::first; //for the rest: default values
......@@ -39,48 +39,66 @@ ProcUnventilatedT::ProcUnventilatedT(const std::vector<std::string>& vec_args, c
void ProcUnventilatedT::process(const unsigned int& param, const std::vector<MeteoData>& ivec,
std::vector<MeteoData>& ovec)
{
if(param!=MeteoData::TA) {
if (param!=MeteoData::TA) {
ostringstream ss;
ss << "Can not use " << getName() << " processing on " << MeteoData::getParameterName(param);
throw InvalidArgumentException(ss.str(), AT);
}
ovec = ivec;
for (size_t ii=0; ii<ovec.size(); ii++){
if (usr_vw_thresh!=IOUtils::nodata)
filterTA(param, ovec);
else
correctTA(param, ovec);
}
void ProcUnventilatedT::filterTA(const unsigned int& param, std::vector<MeteoData>& ovec) const
{
for (size_t ii=0; ii<ovec.size(); ii++) {
const double vw = ovec[ii](MeteoData::VW);
if (vw!=IOUtils::nodata && vw<usr_vw_thresh)
ovec[ii](param) = IOUtils::nodata;
}
}
void ProcUnventilatedT::correctTA(const unsigned int& param, std::vector<MeteoData>& ovec) const
{
for (size_t ii=0; ii<ovec.size(); ii++) {
double& tmp = ovec[ii](param);
if(tmp == IOUtils::nodata) continue; //preserve nodata values
if (tmp == IOUtils::nodata) continue; //preserve nodata values
double albedo = usr_albedo;
double iswr = ivec[ii](MeteoData::ISWR);
const double rswr = ivec[ii](MeteoData::RSWR);
const double ta = ivec[ii](MeteoData::TA);
double vw = ivec[ii](MeteoData::VW);
double hs = ivec[ii](MeteoData::HS);
double iswr = ovec[ii](MeteoData::ISWR);
const double rswr = ovec[ii](MeteoData::RSWR);
const double ta = ovec[ii](MeteoData::TA);
double vw = ovec[ii](MeteoData::VW);
double hs = ovec[ii](MeteoData::HS);
if(is_soft && iswr!=IOUtils::nodata && rswr!=IOUtils::nodata && rswr>5. && iswr>5.) {
if (iswr!=IOUtils::nodata && rswr!=IOUtils::nodata && rswr>5. && iswr>5.) {
albedo = iswr / rswr;
hs = IOUtils::nodata; //to make sure we would not try to recompute a pseudo albedo later
}
if(is_soft && hs!=IOUtils::nodata && iswr==IOUtils::nodata && rswr!=IOUtils::nodata) {
if (hs!=IOUtils::nodata && iswr==IOUtils::nodata && rswr!=IOUtils::nodata) {
if(hs>snow_thresh) iswr = snow_albedo*rswr;
else iswr = soil_albedo*rswr;
}
if(iswr==IOUtils::nodata || ta==IOUtils::nodata || vw==IOUtils::nodata)
if (iswr==IOUtils::nodata || ta==IOUtils::nodata || vw==IOUtils::nodata)
continue;
if(is_soft && hs!=IOUtils::nodata) { //try to get snow height in order to adjust the albedo
if (hs!=IOUtils::nodata) { //try to get snow height in order to adjust the albedo
if(hs>snow_thresh) albedo = snow_albedo;
else albedo = soil_albedo;
}
if(vw<vw_thresh) vw = vw_thresh; //this should be around the minimum measurable wind speed on regular instruments
if (vw<vw_thresh) vw = vw_thresh; //this should be around the minimum measurable wind speed on regular instruments
const double rho = 1.2; // in kg/m3
const double Cp = 1004.;
const double X = iswr / (rho*Cp*ta*vw);
if(X<1e-4) continue; //the correction does not work well for small X values
if(nakamura) {
if (X<1e-4) continue; //the correction does not work well for small X values
if (nakamura) {
const double C0 = 0.13;
const double C1 = 373.40 * albedo / dflt_albedo; //in order to introduce the albedo as a scaling factor
const double RE = C0 + C1*X;
......@@ -92,26 +110,47 @@ void ProcUnventilatedT::process(const unsigned int& param, const std::vector<Met
}
}
void ProcUnventilatedT::parse_args(std::vector<std::string> vec_args) {
vector<double> filter_args;
void ProcUnventilatedT::parse_args(std::vector<std::string> vec_args)
{
const size_t nrArgs = vec_args.size();
is_soft = false;
if (!vec_args.empty()){
is_soft = ProcessingBlock::is_soft(vec_args);
}
//no args -> simple correction with default albedo
if (nrArgs==0) return;
convert_args(0, 1, vec_args, filter_args);
const bool arg0_is_num = IOUtils::isNumeric(vec_args[0]);
if (filter_args.size() > 1)
if (nrArgs==1) { //either nakamura or default albedo
if ( arg0_is_num ) {
IOUtils::convertString(usr_albedo, vec_args[0]);
} else {
const string strArg( IOUtils::strToUpper(vec_args[0]) );
if (strArg=="NAKAMURA")
nakamura=true;
else if (strArg=="SUPPR")
throw InvalidArgumentException("Invalid use of the SUPPR option for filter " + getName(), AT);
else
throw InvalidArgumentException("Unknown argument \""+strArg+"\" for filter " + getName(), AT);
}
} else if (nrArgs==2) {
const string strArg = (!arg0_is_num)? IOUtils::strToUpper(vec_args[0]) : IOUtils::strToUpper(vec_args[1]);
double dblArg;
if (arg0_is_num)
IOUtils::convertString(dblArg, vec_args[0]);
else
IOUtils::convertString(dblArg, vec_args[1]);
if (strArg=="NAKAMURA") {
nakamura = true;
usr_albedo = dblArg;
} else if (strArg=="SUPPR") {
usr_vw_thresh = dblArg;
} else
throw InvalidArgumentException("Unknown argument \""+strArg+"\" for filter " + getName(), AT);
} else
throw InvalidArgumentException("Wrong number of arguments for filter " + getName(), AT);
if (filter_args.empty()){
usr_albedo = dflt_albedo;
} else {
usr_albedo = filter_args[0];
}
nakamura = false;
if (usr_albedo<0. || usr_albedo>1.)
throw InvalidArgumentException("Albedo value should be between 0 and 1 for filter " + getName(), AT);
}
} //end namespace
......@@ -28,16 +28,27 @@ namespace mio {
* @class ProcUnventilatedT
* @ingroup processing
* @brief Filters and corrects temperatures from unventilated sensor.
* This implements the correction described in <i>"Air Temperature Measurement Errors in Naturally Ventilated Radiation Shields"</i>, Reina Nakamura, L. Mahrt, J. Atmos. Oceanic Technol., <b>22</b>, 2005, pp 1046–1058
* This either deletes all air temperature values when the wind speed is below a given threshold or corrects the air temperature data according to
* <i>"Air Temperature Measurement Errors in Naturally Ventilated Radiation Shields"</i>, Reina Nakamura, L. Mahrt, J. Atmos. Oceanic Technol., <b>22</b>, 2005, pp 1046–1058
* with an albedo dependency as introduced in <i>"Albedo effect on radiative errors in air temperature measurements"</i>, H. Huwald, C. W. Higgins, M.-O. Boldi, E. Bou-Zeid, M. Lehning, and M. B. Parlange, Water Resour. Res., <b>45</b>, W08431, 2009.
*
* If the "soft" option is given, the albedo has a value different according to snow (or no snow) on the ground. The default albedo (that is also used if snow height is nodata) can be given as a second option.
* When correcting the data, the albedo of the surroundings is required as well as the incoming or reflected short wave radiation. If a snow height is available, a generic
* snow albedo is used when the snow height is above a given threshold, otherwise a soil albedo. This soil albedo can be provided as an option. Moreover, two corrections
* are available: either the (Huwald, 2009)[default] or the (Nakamura, 2005). When simply deleting all suspicious air temperatures, the wind speed threshold must be provided.
*
* @note This filter can ONLY be applied to air temperatures. Moreover, since it <i>might</i> depend on the radiation shield, it is highly recommended to do some tests (ie. comparisons between ventillated and unventillated sensors) before using it on a new sensor type. Hopefully a new paper would come and clarify its usability per sensor types...
*
* @code
* #using (Huwald, 2009) with default soil albedo
* TA::filter2 = unventilated_T
* TA::arg2 = soft 0.23
*
* #using (Nakamura, 2005) with specified soil albedo
* TA::filter2 = unventilated_T
* TA::arg2 = nakamura 0.23
*
* #simply deleting all values when VW<3. m/s
* TA::filter2 = unventilated_T
* TA::arg2 = suppr 3.
* @endcode
*
* @author Mathias Bavay
......@@ -52,12 +63,13 @@ class ProcUnventilatedT : public ProcessingBlock {
std::vector<MeteoData>& ovec);
private:
void filterTA(const unsigned int& param, std::vector<MeteoData>& ovec) const;
void correctTA(const unsigned int& param, std::vector<MeteoData>& ovec) const;
void parse_args(std::vector<std::string> vec_args);
double usr_albedo;
double usr_albedo, usr_vw_thresh;
static const double dflt_albedo, soil_albedo, snow_albedo;
static const double snow_thresh, vw_thresh;
bool is_soft;
bool nakamura; //use Nakamura or Huwald model
};
......
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