📄 snowpackenergybalance.c
字号:
/* * SUMMARY: SnowPackEnergyBalance.c - Calculate snow pack energy balance * USAGE: Part of DHSVM * * AUTHOR: Bart Nijssen * ORG: University of Washington, Department of Civil Engineering * E-MAIL: nijssen@u.washington.edu * ORIG-DATE: 8-Oct-1996 at 09:09:29 * LAST-MOD: Thu Apr 6 12:43:30 2000 by Keith Cherkauer <cherkaue@u.washington.edu> * $Id: SnowPackEnergyBalance.c,v 4.1.2.1 2004/05/06 00:37:51 tbohn Exp $ * DESCRIPTION: Calculate snow pack energy balance * DESCRIP-END. * FUNCTIONS: SnowPackEnergyBalance() * COMMENTS: */#include <stdarg.h>#include <stdio.h>#include <stdlib.h>#include <vicNl.h>#define GRAMSPKG 1000.#define CH_WATER 4186.8e3#define JOULESPCAL 4.1868 /* Joules per calorie */#define EPS 0.622 /* ratio of molecular weight of water vapor to that for dry air */#define CP 1013.0 /* Specific heat of moist air at constant pressure (J/(kg*C)) *//***************************************************************************** Function name: SnowPackEnergyBalance() Purpose : Calculate the surface energy balance for the snow pack Required : double TSurf - new estimate of effective surface temperature va_list ap - Argument list initialized by va_start(). For elements of list and order, see beginning of routine Returns : double RestTerm - Rest term in the energy balance Modifies : double *RefreezeEnergy - Refreeze energy (W/m2) double *VaporMassFlux - Mass flux of water vapor to or from the intercepted snow (m/s) Comments : Reference: Bras, R. A., Hydrology, an introduction to hydrologic science, Addisson Wesley, Inc., Reading, etc., 1990.*****************************************************************************/double SnowPackEnergyBalance(double TSurf, va_list ap){ extern option_struct options; const char *Routine = "SnowPackEnergyBalance"; /* start of list of arguments in variable argument list */ double Dt; /* Model time step (hours) */ double Ra; /* Aerodynamic resistance (s/m) */ double Z; /* Reference height (m) */ double Displacement; /* Displacement height (m) */ double Z0; /* surface roughness height (m) */ double Wind; /* Wind speed (m/s) */ double ShortRad; /* Net incident shortwave radiation (W/m2) */ double LongRadIn; /* Incoming longwave radiation (W/m2) */ double AirDens; /* Density of air (kg/m3) */ double Lv; /* Latent heat of vaporization (J/kg3) */ double Tair; /* Air temperature (C) */ double Press; /* Air pressure (Pa) */ double Vpd; /* Vapor pressure deficit (Pa) */ double EactAir; /* Actual vapor pressure of air (Pa) */ double Rain; /* Rain fall (m/timestep) */ double SweSurfaceLayer; /* Snow water equivalent in surface layer (m) */ double SurfaceLiquidWater; /* Liquid water in the surface layer (m) */ double OldTSurf; /* Surface temperature during previous time step */ double *GroundFlux; /* Ground Heat Flux (W/m2) */ double *RefreezeEnergy; /* Refreeze energy (W/m2) */ double *VaporMassFlux; /* Mass flux of water vapor to or from the intercepted snow */ double *AdvectedEnergy; /* Energy advected by precipitation (W/m2) */ double *DeltaColdContent; /* Change in cold content (W/m2) */ double TGrnd; double SnowDepth; double SnowDensity; double SurfAttenuation; /* end of list of arguments in variable argument list */ double Density; /* Density of water/ice at TMean (kg/m3) */ double EsSnow; /* saturated vapor pressure in the snow pack (Pa) */ double *LatentHeat; /* Latent heat exchange at surface (W/m2) */ double LongRadOut; /* long wave radiation emitted by surface (W/m2) */ double Ls; /* Latent heat of sublimation (J/kg) */ double NetRad; /* Net radiation exchange at surface (W/m2) */ double RestTerm; /* Rest term in surface energy balance (W/m2) */ double *SensibleHeat; /* Sensible heat exchange at surface (W/m2) */ double TMean; /* Average temperature for time step (C) */ /* Assign the elements of the array to the appropriate variables. The list is traversed as if the elements are doubles, because: In the variable-length part of variable-length argument lists, the old ``default argument promotions'' apply: arguments of type double are always promoted (widened) to type double, and types char and short int are promoted to int. Therefore, it is never correct to invoke va_arg(argp, double); instead you should always use va_arg(argp, double). (quoted from the comp.lang.c FAQ list) */ Dt = (double) va_arg(ap, double); Ra = (double) va_arg(ap, double); Z = (double) va_arg(ap, double); Displacement = (double) va_arg(ap, double); Z0 = (double) va_arg(ap, double); Wind = (double) va_arg(ap, double); ShortRad = (double) va_arg(ap, double); LongRadIn = (double) va_arg(ap, double); AirDens = (double) va_arg(ap, double); Lv = (double) va_arg(ap, double); Tair = (double) va_arg(ap, double); Press = (double) va_arg(ap, double); Vpd = (double) va_arg(ap, double); EactAir = (double) va_arg(ap, double); Rain = (double) va_arg(ap, double); SweSurfaceLayer = (double) va_arg(ap, double); SurfaceLiquidWater = (double) va_arg(ap, double); OldTSurf = (double) va_arg(ap, double); RefreezeEnergy = (double *) va_arg(ap, double *); VaporMassFlux = (double *) va_arg(ap, double *); AdvectedEnergy = (double *) va_arg(ap, double *); DeltaColdContent = (double *) va_arg(ap, double *); TGrnd = (double) va_arg(ap, double); SnowDepth = (double) va_arg(ap, double); SnowDensity = (double) va_arg(ap, double); SurfAttenuation = (double) va_arg(ap, double); GroundFlux = (double *) va_arg(ap, double *); LatentHeat = (double *) va_arg(ap, double *); SensibleHeat = (double *) va_arg(ap, double *); /* Calculate active temp for energy balance as average of old and new */ /* TMean = 0.5 * (OldTSurf + TSurf); */ TMean = TSurf; Density = RHO_W; /* Correct aerodynamic conductance for stable conditions Note: If air temp >> snow temp then aero_cond -> 0 (i.e. very stable) velocity (vel_2m) is expected to be in m/sec */ /* Apply the stability correction to the aerodynamic resistance NOTE: In the old code 2m was passed instead of Z-Displacement. I (bart) think that it is more correct to calculate ALL fluxes at the same reference level */ if (Wind > 0.0) Ra /= StabilityCorrection(Z, 0.f, TMean, Tair, Wind, Z0); /*Ra /= StabilityCorrection(2.f, 0.f, TMean, Tair, Wind, Z0);*/ else Ra = HUGE_RESIST; /* Calculate longwave exchange and net radiation */ LongRadOut = STEFAN * (TMean+273.15) * (TMean+273.15) * (TMean+273.15) * (TMean+273.15); NetRad = SurfAttenuation * ShortRad + LongRadIn - LongRadOut; /* Calculate the sensible heat flux */ *SensibleHeat = AirDens * CP * (Tair - TMean)/Ra; /* Calculate the mass flux of ice to or from the surface layer */ /* Calculate the saturated vapor pressure in the snow pack, (Equation 3.32, Bras 1990) */ EsSnow = svp(TMean) * 1000.;/* EsSnow = 610.78 * exp((double)((17.269 * TMean) / (237.3 + TMean))); *//* if (TMean < 0.0) *//* EsSnow *= 1.0 + .00972 * TMean + .000042 * pow((double)TMean,(double)2.0); */ *VaporMassFlux = AirDens * (EPS/Press) * (EactAir - EsSnow)/Ra; *VaporMassFlux /= Density; if (Vpd == 0.0 && *VaporMassFlux < 0.0) *VaporMassFlux = 0.0; /* Calculate latent heat flux */ if (TMean >= 0.0) { /* Melt conditions: use latent heat of vaporization */ *LatentHeat = Lv * *VaporMassFlux * Density; } else { /* Accumulation: use latent heat of sublimation (Eq. 3.19, Bras 1990 */ Ls = (677. - 0.07 * TMean) * JOULESPCAL * GRAMSPKG; *LatentHeat = Ls * *VaporMassFlux * Density; } /* Calculate advected heat flux from rain WORK IN PROGRESS: Should the following read (Tair - Tsurf) ?? */ *AdvectedEnergy = (CH_WATER * Tair * Rain) / (Dt*SECPHOUR); /* Calculate change in cold content */ *DeltaColdContent = CH_ICE * SweSurfaceLayer * (TSurf - OldTSurf)/ (Dt * SECPHOUR); /* Calculate Ground Heat Flux */ if(SnowDepth>0.) { *GroundFlux = 2.9302e-6 * SnowDensity * SnowDensity * (TGrnd - TMean) / SnowDepth; } else *GroundFlux=0; *DeltaColdContent -= *GroundFlux; /* Calculate net energy exchange at the snow surface */ RestTerm = NetRad + *SensibleHeat + *LatentHeat + *AdvectedEnergy - *DeltaColdContent ; *RefreezeEnergy = (SurfaceLiquidWater * Lf * Density)/(Dt * SECPHOUR); if (TSurf == 0.0 && RestTerm > -(*RefreezeEnergy)) { *RefreezeEnergy = -RestTerm; /* available energy input over cold content used to melt, i.e. Qrf is negative value (energy out of pack)*/ RestTerm = 0.0; } else { RestTerm += *RefreezeEnergy; /* add this positive value to the pack */ } return RestTerm;}#undef GRAMSPKG#undef CH_WATER#undef JOULESPCAL#undef EPS#undef CP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -