Program Listing for File Richard_albedo.cpp#
↰ Return to documentation for file (src/modules/Richard_albedo.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 "Richard_albedo.hpp"
REGISTER_MODULE_CPP(Richard_albedo);
Richard_albedo::Richard_albedo(config_file cfg)
: module_base("Richard_albedo", parallel::data, cfg)
{
depends("swe");
depends("T_s_0"); // snow temp
depends("p_snow");
provides("snow_albedo");
provides("melting_albedo");
}
Richard_albedo::~Richard_albedo()
{
}
void Richard_albedo::checkpoint(mesh& domain, netcdf& chkpt)
{
chkpt.create_variable1D("Richard_albedo:albedo", domain->size_local_faces());
for (size_t i = 0; i < domain->size_local_faces(); i++)
{
auto face = domain->face(i);
chkpt.put_var1D("Richard_albedo:albedo",i,face->get_module_data<Richard_albedo::data>(ID).albedo);
}
}
void Richard_albedo::load_checkpoint(mesh& domain, netcdf& chkpt)
{
for (size_t i = 0; i < domain->size_local_faces(); i++)
{
auto face = domain->face(i);
face->get_module_data<Richard_albedo::data>(ID).albedo = chkpt.get_var1D("Richard_albedo:albedo",i);
}
}
void Richard_albedo::run(mesh_elem &face)
{
if(is_water(face))
{
set_all_nan_on_skip(face);
return;
}
double albedo = face->get_module_data<Richard_albedo::data>(ID).albedo;
double swe = (*face)["swe"_s];
double dt = global_param->dt();
if(global_param->first_time_step)
{
if(swe > 1.0)
{
albedo = albedo_snow;
}
else
{
albedo = albedo_bare;
}
}
if ( swe > 0.)
{
if ((*face)["T_s_0"_s] >= 273.) //melting snow, T_s_0???
{
albedo = (albedo - amin) * exp(-dt/a2) + amin;
(*face)["melting_albedo"_s]=1;
}
else
{
albedo = albedo - dt/a1; // cold snow decay
(*face)["melting_albedo"_s]=0;
}
double psnow = (*face)["p_snow"_s];
albedo = albedo + (amax - albedo) * (psnow )/min_swe_refresh; //* dt
albedo = std::max(albedo,amin);
albedo = std::min(albedo,amax);
}
else
{
(*face)["melting_albedo"_s]=0;
albedo = albedo_bare;
}
(*face)["snow_albedo"_s]=albedo;
face->get_module_data<Richard_albedo::data>(ID).albedo = albedo;
}
void Richard_albedo::init(mesh& domain)
{
//these
amin = cfg.get("albedo_min",0.5);
amax = cfg.get("albedo_max",0.84);
a1 = cfg.get("a1",1.08e7); //cold snow decay const
a2 = cfg.get("a2",7.2e5); //melting snow decay const
min_swe_refresh = cfg.get("min_swe_refresh",1.); //min swe to refresh albedo
albedo_snow = cfg.get("init_albedo_snow",0.85); // intial snow albedo
albedo_bare = cfg.get("init_albedo_bare",0.17); //initial bare ground albedo
#pragma omp parallel for
for (size_t i=0; i < domain->size_local_faces(); ++i)
{
auto face = domain->face(i);
auto& d = face->make_module_data<data>(ID);
d.albedo = albedo_bare;
}
}