From 7afca638f0716bda06252b1df75a0d878cdf7ce3 Mon Sep 17 00:00:00 2001 From: Nander Wever Date: Sat, 14 Jan 2023 12:22:55 +0100 Subject: [PATCH 1/3] If NET_LW is prescribed, set air emissivity to 1 to remain consistent. Otherwise, even when NET_LW is set to 0, the heat equation still solves with a negative net longwave. --- Source/snowpack/applications/snowpack/Main.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Source/snowpack/applications/snowpack/Main.cc b/Source/snowpack/applications/snowpack/Main.cc index 3ec322ae..5d10e879 100644 --- a/Source/snowpack/applications/snowpack/Main.cc +++ b/Source/snowpack/applications/snowpack/Main.cc @@ -416,11 +416,13 @@ inline void copyMeteoData(const mio::MeteoData& md, CurrentMeteo& Mdata, Mdata.iswr = md(MeteoData::ISWR); Mdata.rswr = md(MeteoData::RSWR); - Mdata.ea = md("EA"); - if (md.param_exists("NET_LW")) + if (md.param_exists("NET_LW")) { + Mdata.ea = 1.; Mdata.lw_net = md("NET_LW"); - else + } else { + Mdata.ea = md("EA"); Mdata.lw_net = IOUtils::nodata; + } Mdata.tss = md(MeteoData::TSS); if (md.param_exists("TSS_A12H") && (md("TSS_A12H") != mio::IOUtils::nodata)) Mdata.tss_a12h = md("TSS_A12H"); From e8011cc630703d3004316f33c70d26142f8aedf1 Mon Sep 17 00:00:00 2001 From: Nander Wever Date: Tue, 24 Jan 2023 17:45:26 +0100 Subject: [PATCH 2/3] Fixing misplaced brackets. --- Source/snowpack/snowpack/Laws_sn.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/snowpack/snowpack/Laws_sn.cc b/Source/snowpack/snowpack/Laws_sn.cc index 778cf93f..b84e348f 100644 --- a/Source/snowpack/snowpack/Laws_sn.cc +++ b/Source/snowpack/snowpack/Laws_sn.cc @@ -1119,7 +1119,7 @@ double SnLaws::newSnowDensityEvent(const std::string& variant, const SnLaws::Eve const double vw_avg_ref = Meteo::windspeedProfile(Mdata, z_ref_vw, Mdata.vw_avg); if ((vw_avg_ref >= event_wind_lowlim) && (vw_avg_ref <= event_wind_highlim)) { static const double rho_0=361., rho_1=33.; - return (vw_avg_ref == 0.) ? (rho_1) : (std::max(rho_1, rho_0*log10(vw_avg_ref)) + rho_1); + return (vw_avg_ref == 0.) ? (rho_1) : (std::max(rho_1, rho_0*log10(vw_avg_ref) + rho_1)); } else return Constants::undefined; } From ed2ee296d8f6f6e01b25a1857250308d23efc99b Mon Sep 17 00:00:00 2001 From: Nander Wever Date: Tue, 31 Jan 2023 14:43:55 +0100 Subject: [PATCH 3/3] Adding the option REDEPOSIT_KEEP_AGE to keep original deposition date of redeposited snow. --- Source/snowpack/snowpack/DataClasses.cc | 7 +++++-- Source/snowpack/snowpack/DataClasses.h | 1 + Source/snowpack/snowpack/SnowDrift.cc | 8 ++++++++ Source/snowpack/snowpack/SnowpackConfig.cc | 1 + Source/snowpack/snowpack/snowpackCore/Snowpack.cc | 9 ++++++++- Source/snowpack/snowpack/snowpackCore/Snowpack.h | 1 + 6 files changed, 24 insertions(+), 3 deletions(-) diff --git a/Source/snowpack/snowpack/DataClasses.cc b/Source/snowpack/snowpack/DataClasses.cc index 24b3a075..eb2febd7 100644 --- a/Source/snowpack/snowpack/DataClasses.cc +++ b/Source/snowpack/snowpack/DataClasses.cc @@ -1922,7 +1922,7 @@ SnowStation::SnowStation(const bool i_useCanopyModel, const bool i_useSoilLayers meta(), cos_sl(1.), sector(0), Cdata(), Seaice(NULL), pAlbedo(0.), Albedo(0.), SoilAlb(0.), SoilEmissivity(0.), BareSoil_z0(0.), SoilNode(0), Ground(0.), cH(0.), mH(0.), mass_sum(0.), swe(0.), lwc_sum(0.), lwc_sum_soil(0.), swc_sum_soil(0), hn(0.), rho_hn(0.), rime_hn(0.), - hn_redeposit(0.), rho_hn_redeposit(0.), ErosionLevel(0), ErosionMass(0.), ErosionLength(0.), + hn_redeposit(0.), rho_hn_redeposit(0.), ErosionLevel(0), ErosionMass(0.), ErosionLength(0.), ErosionAge(Constants::undefined), S_class1(0), S_class2(0), S_d(0.), z_S_d(0.), S_n(0.), z_S_n(0.), S_s(0.), z_S_s(0.), S_4(0.), z_S_4(0.), S_5(0.), z_S_5(0.), Ndata(), Edata(), Kt(NULL), ColdContent(0.), ColdContentSoil(0.), dIntEnergy(0.), dIntEnergySoil(0.), meltFreezeEnergy(0.), meltFreezeEnergySoil(0.), meltMassTot(0.), refreezeMassTot(0.), @@ -1940,7 +1940,7 @@ SnowStation::SnowStation(const SnowStation& c) : meta(c.meta), cos_sl(c.cos_sl), sector(c.sector), Cdata(c.Cdata), Seaice(c.Seaice), pAlbedo(c.pAlbedo), Albedo(c.Albedo), SoilAlb(c.SoilAlb), SoilEmissivity(c.SoilEmissivity), BareSoil_z0(c.BareSoil_z0), SoilNode(c.SoilNode), Ground(c.Ground), cH(c.cH), mH(c.mH), mass_sum(c.mass_sum), swe(c.swe), lwc_sum(c.lwc_sum), lwc_sum_soil(c.lwc_sum_soil), swc_sum_soil(c.swc_sum_soil), hn(c.hn), rho_hn(c.rho_hn), rime_hn(c.rime_hn), - hn_redeposit(c.hn_redeposit), rho_hn_redeposit(c.rho_hn_redeposit), ErosionLevel(c.ErosionLevel), ErosionMass(c.ErosionMass), ErosionLength(c.ErosionLength), + hn_redeposit(c.hn_redeposit), rho_hn_redeposit(c.rho_hn_redeposit), ErosionLevel(c.ErosionLevel), ErosionMass(c.ErosionMass), ErosionLength(c.ErosionLength), ErosionAge(c.ErosionAge), S_class1(c.S_class1), S_class2(c.S_class2), S_d(c.S_d), z_S_d(c.z_S_d), S_n(c.S_n), z_S_n(c.z_S_n), S_s(c.S_s), z_S_s(c.z_S_s), S_4(c.S_4), z_S_4(c.z_S_4), S_5(c.S_5), z_S_5(c.z_S_5), Ndata(c.Ndata), Edata(c.Edata), Kt(NULL), ColdContent(c.ColdContent), ColdContentSoil(c.ColdContentSoil), dIntEnergy(c.dIntEnergy), dIntEnergySoil(c.dIntEnergySoil), meltFreezeEnergy(c.meltFreezeEnergy), meltFreezeEnergySoil(c.meltFreezeEnergySoil), meltMassTot(c.meltMassTot), refreezeMassTot(c.refreezeMassTot), @@ -1989,6 +1989,7 @@ SnowStation& SnowStation::operator=(const SnowStation& source) { ErosionLevel = source.ErosionLevel; ErosionMass = source.ErosionMass; ErosionLength = source.ErosionLength; + ErosionAge = source.ErosionAge; S_class1 = source.S_class1; S_class2 = source.S_class2; S_d = source.S_d; @@ -2924,6 +2925,7 @@ std::ostream& operator<<(std::ostream& os, const SnowStation& data) os.write(reinterpret_cast(&data.ErosionLevel), sizeof(data.ErosionLevel)); os.write(reinterpret_cast(&data.ErosionMass), sizeof(data.ErosionMass)); os.write(reinterpret_cast(&data.ErosionLength), sizeof(data.ErosionLength)); + os.write(reinterpret_cast(&data.ErosionAge), sizeof(data.ErosionAge)); os.write(reinterpret_cast(&data.S_class1), sizeof(data.S_class1)); os.write(reinterpret_cast(&data.S_class2), sizeof(data.S_class2)); os.write(reinterpret_cast(&data.S_d), sizeof(data.S_d)); @@ -3012,6 +3014,7 @@ std::istream& operator>>(std::istream& is, SnowStation& data) is.read(reinterpret_cast(&data.ErosionLevel), sizeof(data.ErosionLevel)); is.read(reinterpret_cast(&data.ErosionMass), sizeof(data.ErosionMass)); is.read(reinterpret_cast(&data.ErosionLength), sizeof(data.ErosionLength)); + is.read(reinterpret_cast(&data.ErosionAge), sizeof(data.ErosionAge)); is.read(reinterpret_cast(&data.S_class1), sizeof(data.S_class1)); is.read(reinterpret_cast(&data.S_class2), sizeof(data.S_class2)); is.read(reinterpret_cast(&data.S_d), sizeof(data.S_d)); diff --git a/Source/snowpack/snowpack/DataClasses.h b/Source/snowpack/snowpack/DataClasses.h index 75e66c19..0d0088fb 100644 --- a/Source/snowpack/snowpack/DataClasses.h +++ b/Source/snowpack/snowpack/DataClasses.h @@ -665,6 +665,7 @@ class SnowStation { size_t ErosionLevel; ///< Element where snow erosion stopped previously for the drift index double ErosionMass; ///< Eroded mass either real or virtually (storage if less than one element) double ErosionLength; ///< Snow height change dueo to eroded mass (only real erosion) + double ErosionAge; ///< Layer age of eroded snow layers char S_class1; ///< Stability class based on hand hardness, grain class ... char S_class2; ///< Stability class based on hand hardness, grain class ... double S_d; ///< Minimum Direct Action Stability Index ... diff --git a/Source/snowpack/snowpack/SnowDrift.cc b/Source/snowpack/snowpack/SnowDrift.cc index a0707dfc..124947c2 100644 --- a/Source/snowpack/snowpack/SnowDrift.cc +++ b/Source/snowpack/snowpack/SnowDrift.cc @@ -218,6 +218,7 @@ void SnowDrift::compSnowDrift(const CurrentMeteo& Mdata, SnowStation& Xdata, Sur const bool no_wind_data = (Mdata.vw_drift == mio::IOUtils::nodata); Xdata.ErosionMass = 0.; Xdata.ErosionLength = 0.; + Xdata.ErosionAge = 0.; if (no_snow || no_wind_data) { if (no_snow) { Xdata.ErosionLevel = Xdata.SoilNode; @@ -282,6 +283,7 @@ void SnowDrift::compSnowDrift(const CurrentMeteo& Mdata, SnowStation& Xdata, Sur Xdata.ErosionMass += EMS[e].M; Xdata.ErosionLength -= EMS[e].L; Xdata.ErosionLevel = std::min(e, Xdata.ErosionLevel); + Xdata.ErosionAge += EMS[e].depositionDate.getJulian() * EMS[e].L; nErode++; massErode -= EMS[e].M; forced_massErode = -massErode; @@ -304,6 +306,7 @@ void SnowDrift::compSnowDrift(const CurrentMeteo& Mdata, SnowStation& Xdata, Sur assert(EMS[e].M>=0.); //mass must be positive Xdata.ErosionMass += massErode; Xdata.ErosionLength += dL; + Xdata.ErosionAge += EMS[e].depositionDate.getJulian() * -dL; massErode = 0.; forced_massErode = 0.; break; @@ -354,5 +357,10 @@ void SnowDrift::compSnowDrift(const CurrentMeteo& Mdata, SnowStation& Xdata, Sur Xdata.ErosionMass = 0.; } Sdata.mass[SurfaceFluxes::MS_EROSION_DHS] += Xdata.ErosionLength; + if (Xdata.ErosionLength < 0.) { + Xdata.ErosionAge /= -Xdata.ErosionLength; + } else { + Xdata.ErosionAge = Constants::undefined; + } return; } diff --git a/Source/snowpack/snowpack/SnowpackConfig.cc b/Source/snowpack/snowpack/SnowpackConfig.cc index 8469d21c..f3c752e0 100644 --- a/Source/snowpack/snowpack/SnowpackConfig.cc +++ b/Source/snowpack/snowpack/SnowpackConfig.cc @@ -84,6 +84,7 @@ bool SnowpackConfig::initStaticData() advancedConfig["PERP_TO_SLOPE"] = "false"; advancedConfig["PLASTIC"] = "false"; advancedConfig["PREVAILING_WIND_DIR"] = "0."; + advancedConfig["REDEPOSIT_KEEP_AGE"] = "false"; advancedConfig["RESEARCH"] = "true"; advancedConfig["SNOW_ALBEDO"] = "PARAMETERIZED"; advancedConfig["SNOW_EROSION"] = "false"; diff --git a/Source/snowpack/snowpack/snowpackCore/Snowpack.cc b/Source/snowpack/snowpack/snowpackCore/Snowpack.cc index 052b73b8..96518b4c 100644 --- a/Source/snowpack/snowpack/snowpackCore/Snowpack.cc +++ b/Source/snowpack/snowpack/snowpackCore/Snowpack.cc @@ -97,7 +97,7 @@ Snowpack::Snowpack(const SnowpackConfig& i_cfg) allow_adaptive_timestepping(false), research_mode(false), useCanopyModel(false), enforce_measured_snow_heights(false), detect_grass(false), soil_flux(false), useSoilLayers(false), coupled_phase_changes(false), combine_elements(false), reduce_n_elements(0), force_add_snowfall(false), max_simulated_hs(-1.), change_bc(false), meas_tss(false), vw_dendricity(false), - enhanced_wind_slab(false), snow_erosion("NONE"), alpine3d(false), ageAlbedo(true), soot_ppmv(0.), adjust_height_of_meteo_values(true), + enhanced_wind_slab(false), snow_erosion("NONE"), redeposit_keep_age(false), alpine3d(false), ageAlbedo(true), soot_ppmv(0.), adjust_height_of_meteo_values(true), adjust_height_of_wind_value(false), advective_heat(false), heat_begin(0.), heat_end(0.), temp_index_degree_day(0.), temp_index_swr_factor(0.), forestfloor_alb(false), rime_index(false), newsnow_lwc(false), read_dsm(false), soil_evaporation(), soil_thermal_conductivity() { @@ -276,6 +276,7 @@ Snowpack::Snowpack(const SnowpackConfig& i_cfg) cfg.getValue("SNOW_EROSION", "SnowpackAdvanced", snow_erosion); std::transform(snow_erosion.begin(), snow_erosion.end(), snow_erosion.begin(), ::toupper); // Force upper case + cfg.getValue("REDEPOSIT_KEEP_AGE", "SnowpackAdvanced", redeposit_keep_age); cfg.getValue("NEW_SNOW_GRAIN_SIZE", "SnowpackAdvanced", new_snow_grain_size); new_snow_bond_size = 0.25 * new_snow_grain_size; @@ -1953,6 +1954,7 @@ void Snowpack::RedepositSnow(CurrentMeteo Mdata, SnowStation& Xdata, SurfaceFlux const bool tmp_enforce_measured_snow_heights = enforce_measured_snow_heights; const double tmp_Xdata_hn = Xdata.hn; const double tmp_Xdata_rho_hn = Xdata.rho_hn; + const mio::Date tmp_MdataDate = Mdata.date; // Deposition mode settings: double tmp_psum = redeposit_mass; force_add_snowfall = true; @@ -1963,6 +1965,10 @@ void Snowpack::RedepositSnow(CurrentMeteo Mdata, SnowStation& Xdata, SurfaceFlux if (Mdata.vw_avg == mio::IOUtils::nodata) Mdata.vw_avg = Mdata.vw; if (Mdata.rh_avg == mio::IOUtils::nodata) Mdata.rh_avg = Mdata.rh; Xdata.hn = 0.; + if (Xdata.ErosionAge != Constants::undefined && redeposit_keep_age) { + mio::Date EnforcedDepositionDate(Xdata.ErosionAge, Mdata.date.getTimeZone()); + Mdata.date = EnforcedDepositionDate; + } // Add eroded snow: compSnowFall(Mdata, Xdata, tmp_psum, Sdata); // Set back original settings: @@ -1970,6 +1976,7 @@ void Snowpack::RedepositSnow(CurrentMeteo Mdata, SnowStation& Xdata, SurfaceFlux hn_density = tmp_hn_density; variant = tmp_variant; enforce_measured_snow_heights = tmp_enforce_measured_snow_heights; + Mdata.date = tmp_MdataDate; // Calculate new snow density (weighted average) and total snowfall (snowfall + redeposited snow) Xdata.hn_redeposit = Xdata.hn; Xdata.rho_hn_redeposit = Xdata.rho_hn; diff --git a/Source/snowpack/snowpack/snowpackCore/Snowpack.h b/Source/snowpack/snowpack/snowpackCore/Snowpack.h index 5c15a57e..de65da48 100644 --- a/Source/snowpack/snowpack/snowpackCore/Snowpack.h +++ b/Source/snowpack/snowpack/snowpackCore/Snowpack.h @@ -149,6 +149,7 @@ class Snowpack { bool vw_dendricity; bool enhanced_wind_slab; ///< to use an even stronger wind slab densification than implemented by default std::string snow_erosion; + bool redeposit_keep_age; bool alpine3d; ///< triggers various tricks for Alpine3D (including reducing the number of warnings) bool ageAlbedo; ///< use the age of snow in the albedo parametrizations? default: true double soot_ppmv; ///< Impurity content in ppmv for albedo calculatoins