📄 snow_melt.c
字号:
/* * SUMMARY: SnowMelt.c - Calculate snow accumulation and melt * USAGE: * * AUTHOR: Mark Wigmosta and Pascal Storck * ORG: University of Washington, Department of Civil Engineering * E-MAIL: nijssen@u.washington.edu * ORIG-DATE: 8-Oct-1996 at 08:50:06 * LAST-MOD: Tue Mar 7 17:02:40 2000 by Keith Cherkauer <cherkaue@u.washington.edu> * DESCRIPTION: Calculate snow accumulation and melt using an energy balance * approach for a two layer snow model * DESCRIP-END. * FUNCTIONS: SnowMelt() * COMMENTS: */#include <assert.h>#include <stdarg.h>#include <stdio.h>#include <stdlib.h>#include <vicNl.h>static char vcid[] = "$Id: snow_melt.c,v 4.1.2.2 2004/09/22 00:40:33 vicadmin Exp $";/***************************************************************************** Function name: SnowMelt() Purpose : Calculate snow accumulation and melt using an energy balance approach for a two layer snow model Required : double delta_t - Model timestep (hours) double z2 - Reference height (m) double displacement - Displacement height (m) double aero_resist - Aerodynamic resistance (uncorrected for stability) (s/m) double atmos->density - Density of air (kg/m3) double atmos->vp - Actual vapor pressure of air (Pa) double Le - Latent heat of vaporization (J/kg3) double atmos->net_short - Net exchange of shortwave radiation (W/m2) double atmos->longwave - Incoming long wave radiation (W/m2) double atmos->pressure - Air pressure (Pa) double RainFall - Amount of rain (m) double Snowfall - Amount of snow (m) double atmos->air_temp - Air temperature (C) double atmos->vpd - Vapor pressure deficit (Pa) double wind - Wind speed (m/s) double snow->pack_water - Liquid water content of snow pack double snow->surf_water - Liquid water content of surface layer double snow->swq - Snow water equivalent at current pixel (m) double snow->vapor_flux; - Mass flux of water vapor to or from the intercepted snow (m/time step) double snow->pack_temp - Temperature of snow pack (C) double snow->surf_temp - Temperature of snow pack surface layer (C) double snow->melt_energy - Energy used for melting and heating of snow pack (W/m2) Modifies : double atmos->melt - Amount of snowpack outflow (m) double snow->pack_water - Liquid water content of snow pack double snow->surf_water - Liquid water content of surface layer double snow->swq - Snow water equivalent at current pixel (m) double snow->vapor_flux; - Mass flux of water vapor to or from the intercepted snow (m) double snow->pack_temp - Temperature of snow pack (C) double snow->surf_temp - Temperature of snow pack surface layer (C) double snow->melt_energy - Energy used for melting and heating of snow pack (W/m2) Comments : 04-Jun-04 Added descriptive error message to beginning of screen dump in ErrorPrintSnowPackEnergyBalance. TJB 21-Sep-04 Added ErrorString to store error messages from root_brent. TJB*****************************************************************************/void snow_melt(soil_con_struct *soil_con, int rec, int iveg, double z2, double aero_resist, double Le, snow_data_struct *snow, double delta_t, double displacement, double Z0, double surf_atten, double rainfall, double snowfall, double wind, double grnd_surf_temp, double air_temp, double net_short, double longwave, double density, double pressure, double vpd, double vp, double *melt, double *save_advection, double *save_deltaCC, double *save_grnd_flux, double *save_latent, double *save_sensible, double *save_Qnet, double *save_refreeze_energy){ int Twidth; double DeltaPackCC; /* Change in cold content of the pack */ double DeltaPackSwq; /* Change in snow water equivalent of the pack (m) */ double Ice; /* Ice content of snow pack (m)*/ double InitialSwq; /* Initial snow water equivalent (m) */ double MassBalanceError; /* Mass balance error (m) */ double MaxLiquidWater; /* Maximum liquid water content of pack (m) */ double OldTSurf; /* Old snow surface temperature (C) */ double PackCC; /* Cold content of snow pack (J) */ double PackSwq; /* Snow pack snow water equivalent (m) */ double Qnet; /* Net energy exchange at the surface (W/m2) */ double RefreezeEnergy; /* refreeze energy (W/m2) */ double RefrozenWater; /* Amount of refrozen water (m) */ double SnowFallCC; /* Cold content of new snowfall (J) */ double SnowMelt; /* Amount of snow melt during time interval (m water equivalent) */ double SurfaceCC; /* Cold content of snow pack (J) */ double SurfaceSwq; /* Surface layer snow water equivalent (m) */ double SnowFall; double RainFall; double vapor_flux; double advection; double deltaCC; double grnd_flux; /* thermal flux through snowpack from ground */ double latent_heat; /* thermal flux through snowpack from ground */ double sensible_heat; /* thermal flux through snowpack from ground */ double melt_energy = 0.; char ErrorString[MAXSTRING]; SnowFall = snowfall / 1000.; /* convet to m */ RainFall = rainfall / 1000.; /* convet to m */ InitialSwq = snow->swq; OldTSurf = snow->surf_temp; /* Initialize snowpack variables */ Ice = snow->swq - snow->pack_water - snow->surf_water; /* Reconstruct snow pack */ if (Ice > MAX_SURFACE_SWE) SurfaceSwq = MAX_SURFACE_SWE; else SurfaceSwq = Ice; PackSwq = Ice - SurfaceSwq; /* Calculate cold contents */ SurfaceCC = CH_ICE * SurfaceSwq * snow->surf_temp; PackCC = CH_ICE * PackSwq * snow->pack_temp; if (air_temp > 0.0) SnowFallCC = 0.0; else SnowFallCC = CH_ICE * SnowFall * air_temp; /* Distribute fresh snowfall */ if (SnowFall > (MAX_SURFACE_SWE - SurfaceSwq)) { DeltaPackSwq = SurfaceSwq + SnowFall - MAX_SURFACE_SWE; if (DeltaPackSwq > SurfaceSwq) DeltaPackCC = SurfaceCC + (SnowFall - MAX_SURFACE_SWE)/SnowFall * SnowFallCC; else DeltaPackCC = DeltaPackSwq/SurfaceSwq * SurfaceCC; SurfaceSwq = MAX_SURFACE_SWE; SurfaceCC += SnowFallCC - DeltaPackCC; PackSwq += DeltaPackSwq; PackCC += DeltaPackCC; } else { SurfaceSwq += SnowFall; SurfaceCC += SnowFallCC; } if (SurfaceSwq > 0.0) snow->surf_temp = SurfaceCC/(CH_ICE * SurfaceSwq); else snow->surf_temp = 0.0; if (PackSwq > 0.0) snow->pack_temp = PackCC/(CH_ICE * PackSwq); else snow->pack_temp = 0.0; /* Adjust ice and snow->surf_water */ Ice += SnowFall; snow->surf_water += RainFall; /* Calculate the surface energy balance for snow_temp = 0.0 */ vapor_flux = snow->vapor_flux; Qnet = CalcSnowPackEnergyBalance((double)0.0, delta_t, aero_resist, z2, displacement, Z0, wind, net_short, longwave, density, Le, air_temp, pressure * 1000., vpd * 1000., vp * 1000., RainFall, SurfaceSwq, snow->surf_water, OldTSurf, &RefreezeEnergy, &vapor_flux, &advection, &deltaCC, grnd_surf_temp, snow->depth, snow->density, surf_atten, &grnd_flux, &latent_heat, &sensible_heat); snow->vapor_flux = vapor_flux; save_refreeze_energy[0] = RefreezeEnergy; /* If Qnet == 0.0, then set the surface temperature to 0.0 */ if (Qnet == 0.0) { snow->surf_temp = 0.0; if (RefreezeEnergy >= 0.0) { RefrozenWater = RefreezeEnergy/(Lf * RHO_W) * delta_t * SECPHOUR; if (RefrozenWater > snow->surf_water) { RefrozenWater = snow->surf_water; RefreezeEnergy = RefrozenWater * Lf * RHO_W/ (delta_t * SECPHOUR); } melt_energy += RefreezeEnergy; SurfaceSwq += RefrozenWater; Ice += RefrozenWater; snow->surf_water -= RefrozenWater; assert(snow->surf_water >= 0.0); SnowMelt = 0.0; } else { /* Calculate snow melt */ SnowMelt = fabs(RefreezeEnergy)/(Lf * RHO_W) * delta_t * SECPHOUR; melt_energy += RefreezeEnergy; } /* Convert vapor mass flux to a depth per timestep and adjust snow->surf_water */ snow->vapor_flux *= delta_t * SECPHOUR; if (snow->surf_water < -(snow->vapor_flux)) { snow->vapor_flux = -(snow->surf_water); snow->surf_water = 0.0; } else snow->surf_water += snow->vapor_flux; /* If SnowMelt < Ice, there was incomplete melting of the pack */ if (SnowMelt < Ice) { if (SnowMelt <= PackSwq) { snow->surf_water += SnowMelt; PackSwq -= SnowMelt; Ice -= SnowMelt; } else { snow->surf_water += SnowMelt + snow->pack_water; snow->pack_water = 0.0; PackSwq = 0.0; Ice -= SnowMelt; SurfaceSwq = Ice; } } /* Else, SnowMelt > Ice and there was complete melting of the pack */ else { SnowMelt = Ice; snow->surf_water += Ice; SurfaceSwq = 0.0; snow->surf_temp = 0.0; PackSwq = 0.0; snow->pack_temp = 0.0; Ice = 0.0; } } /* Else, SnowPackEnergyBalance(T=0.0) <= 0.0 */ else { /* Calculate surface layer temperature using "Brent method" */ vapor_flux = snow->vapor_flux; snow->surf_temp = root_brent((double)(snow->surf_temp-SNOW_DT), (double)0.0, ErrorString, SnowPackEnergyBalance, delta_t, aero_resist, z2, displacement, Z0, wind, net_short, longwave, density, Le, air_temp, pressure * 1000., vpd * 1000., vp * 1000., RainFall, SurfaceSwq, snow->surf_water, OldTSurf, &RefreezeEnergy, &vapor_flux, &advection, &deltaCC, grnd_surf_temp, snow->depth, snow->density,surf_atten,&grnd_flux, &latent_heat, &sensible_heat); if(snow->surf_temp <= -9998) ErrorSnowPackEnergyBalance(snow->surf_temp, delta_t, aero_resist, z2, displacement, Z0, wind, net_short, longwave, density, Le, air_temp, pressure * 1000., vpd * 1000., vp * 1000., RainFall, SurfaceSwq, snow->surf_water, OldTSurf, &RefreezeEnergy, &vapor_flux, &advection, &deltaCC, grnd_surf_temp, snow->depth, snow->density,surf_atten, &grnd_flux,&latent_heat, &sensible_heat, ErrorString); Qnet = CalcSnowPackEnergyBalance(snow->surf_temp, delta_t, aero_resist, z2, displacement, Z0, wind, net_short, longwave, density, Le, air_temp, pressure * 1000., vpd * 1000., vp * 1000., RainFall, SurfaceSwq, snow->surf_water, OldTSurf, &RefreezeEnergy, &vapor_flux, &advection, &deltaCC, grnd_surf_temp,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -