Program Listing for File Winstral_parameters.cpp#
↰ Return to documentation for file (src/modules/interp_met/Winstral_parameters.cpp)
//
// Canadian Hydrological Model - The Canadian Hydrological Model (CHM) is a novel
// modular unstructured mesh based approach for hydrological modelling
// Copyright (C) 2018 Christopher Marsh
//
// This file is part of Canadian Hydrological Model.
//
// Canadian Hydrological Model is free software: you can redistribute it and/or
// modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Canadian Hydrological Model 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Canadian Hydrological Model. If not, see
// <http://www.gnu.org/licenses/>.
//
#include "Winstral_parameters.hpp"
REGISTER_MODULE_CPP(Winstral_parameters);
Winstral_parameters::Winstral_parameters(config_file cfg)
: module_base("Winstral_parameters", parallel::domain, cfg)
{
depends("vw_dir");
optional("snowdepthavg");
provides("Sx");
//max distance to search
dmax = cfg.get("dmax",300.0);
//size of the step to take
size_of_step = cfg.get("size_of_step",10);
//number of steps along the search vector to check for a higher point
//steps = cfg.get("steps",10);
steps = dmax / size_of_step;
//height parameter to account for instrument height or the impact of small terrain perturbation on Sx
// see Winstral et al. (2013) for more details
height_param = cfg.get("height_param",0.0);
//separation distance to compute drift separators
//sepdist = cfg.get("dmax",60.0);
angular_window = cfg.get("angular_window",30.);
delta_angle = cfg.get("delta_angle",5.);
nangle = angular_window / delta_angle+1;
// Logical to include vegetation in the computation of Sx
incl_veg = cfg.get("incl_veg",false);
// Logical to include snow depth in the computation of Sx
incl_snw = cfg.get("incl_snw",false);
// Option to compute the elevation of the point considered to compute Sx
use_subgridz = cfg.get("use_subgridz",true);
SPDLOG_DEBUG("Successfully instantiated module {}",this->ID);
}
void Winstral_parameters::run(mesh& domain)
{
#pragma omp parallel for
for (size_t i = 0; i < domain->size_local_faces(); i++)
{
auto face = domain->face(i);
// Derive Sx averaged over the angular windows
double sx_mean = Sx(domain,face);
(*face)["Sx"_s]= sx_mean;
}
}
double Winstral_parameters::Sx(const mesh &domain, mesh_elem& face) const
{
// Reference point: center of the triangle
auto face_centre = face->center();
// Reference height: elevation of the center of the triangle
double Z_loc = face_centre.z() + this->height_param;
if (this->incl_veg && face->has_vegetation())
{
Z_loc = Z_loc + face->veg_attribute("CanopyHeight");
}
if (this->incl_snw)
{
Z_loc = Z_loc + (*face)["snowdepthavg"_s];
}
double sx_mean = 0.;
// Extract Wind direction
double wind_dir = (*face)["vw_dir"_s] ;
for (int i = 1; i <= this->nangle; ++i)
{
double sx = -9999.0;
double max_tan_sx = 0.;
//direction it is from,i need upwind fetch
double wdir = wind_dir - this->angular_window / 2.0 + (i - 1) * this->delta_angle;
// search along wdir azimuth in j step increments
for (int j = 1; j <= this->steps; ++j)
{
double distance = j * this->size_of_step;
// Select point along the line
Point_2 pref = math::gis::point_from_bearing(face_centre, wdir, distance);
// Find corresponding triangle
auto f = domain->find_closest_face (pref );
double Z_dist = 0.;
if(this->use_subgridz)
{
Z_dist = f->get_subgrid_z(pref);
}
else
{
Z_dist = face_centre.z();
}
if (this->incl_veg && f->has_vegetation())
{
Z_dist = Z_dist + f->veg_attribute("CanopyHeight");
}
if (this->incl_snw)
{
Z_dist = Z_dist+ (*f)["snowdepthavg"_s];
}
double tan_sx = (Z_dist-Z_loc) / distance;
if(std::abs(tan_sx) > std::abs(max_tan_sx))
{
max_tan_sx = tan_sx;
}
}
sx = atan(max_tan_sx);
sx_mean = sx_mean+sx;
}
// Derive Sx averaged over the angular windows
sx_mean = sx_mean / this->nangle;
return sx_mean*180/M_PI;
}
Winstral_parameters::~Winstral_parameters()
{
}