⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 snow_melt.c

📁 降雪及积雪计算的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * 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 + -