Example #1
0
void CSnowInterception::init(int y, int x, int Dt, float F, float LAI,
		      float MaxInt, float MaxSnowIntCap, float MDRatio,
		      float SnowIntEff, float Ra, float AirDens, float EactAir,
		      float Lv, PIXRAD * LocalRad, float Press, float Tair,
		      float Vpd, float Wind, float *RainFall, float *SnowFall,
		      float *IntRain, float *IntSnow, float *TempIntStorage,
		      float *VaporMassFlux, float *Tcanopy, float *MeltEnergy,
		      float *MomentSq, float *Height, unsigned char Understory,
		      float MS_Rainfall, float LD_FallVelocity)
{
  float AdvectedEnergy;		/* Energy advected by the rain (W/m2) */
  float DeltaSnowInt;		/* Change in the physical swe of snow
				   interceped on the branches. (m) */
  float Drip;			/* Amount of drip from intercepted snow as a
				   result of snowmelt (m) */
  float ExcessSnowMelt;		/* Snowmelt in excess of the water holding
				   capacity of the tree (m) */
  float EsSnow;			/* saturated vapor pressure in the snow pack
				   (Pa)  */
  float InitialSnowInt;		/* Initial intercepted snow (m) */
  float InitialWaterInt;	/* Initial intercepted water (snow and rain)
				   (m) */
  float LatentHeat;		/* Latent heat flux (W/m2) */
  float LongOut;		/* Longwave radiation emitted by canopy
				   (W/m2) */
  float Ls;			/* Latent heat of sublimation (J/(kg K) */
  float MassBalanceError;	/* Mass blalnce to make sure no water is
				   being destroyed/created (m) */
  float MaxWaterInt;		/* Water interception capacity (m) */
  float MaxSnowInt;		/* Snow interception capacity (m) -
				   multiplier w/ temp */
  float NetRadiation;
  float PotSnowMelt;		/* Potential snow melt (m) */
  float RainThroughFall;	/* Amount of rain reaching to the ground (m)
				 */
  float RefreezeEnergy;		/* Energy available for refreezing or melt */
  float ReleasedMass;		/* Amount of mass release of intercepted snow
				   (m) */
  float SensibleHeat;		/* Sensible heat flux (W/m2) */
  float SnowThroughFall;	/* Amount of snow reaching to the ground (m)
				 */
  float Tmp;			/* Temporary variable */
  float MaxIntercept;		/* max snow interception - regardless of temp */
  float overload;		/* overload of intercepted snow due to rainfall
				   or condensation */
  float intrainfrac;		/* fraction of intercepted water which is
				   liquid */
  float intsnowfrac;		/*fraction of intercepted water which is solid */
  float OriginalRainfall;

  /* Initialize Drip, H2O balance, and mass release variables. */

  OriginalRainfall = *RainFall;
  InitialWaterInt = *IntSnow + *IntRain;

  *IntSnow /= F;
  *IntRain /= F;

  InitialSnowInt = *IntSnow;

  Drip = 0.0;
  ReleasedMass = 0.0;

  /* Determine the maximum snow interception water equivalent.
     Kobayashi, D., 1986, Snow Accumulation on a Narrow Board,
     Cold Regions Science and Technology, (13), pp. 239-245.
     Figure 4. */

  if (Tair > -5.0)
    MaxSnowInt = 1.0;
  else
    MaxSnowInt = 0.25;

  /* therefore LAI_ratio decreases as temp decreases */

  MaxSnowInt *= MaxSnowIntCap;
  MaxIntercept = MaxSnowIntCap;

  /* Calculate snow interception. */

  DeltaSnowInt = SnowIntEff * *SnowFall;
  if (DeltaSnowInt + *IntSnow > MaxSnowInt)
    DeltaSnowInt = MaxSnowInt - *IntSnow;
  if (DeltaSnowInt < 0.0)
    DeltaSnowInt = 0.0;

  /* now update snowfall and total accumulated intercepted snow amounts */

  /* pixel depth    */
  SnowThroughFall = (*SnowFall - DeltaSnowInt) * F + (*SnowFall) * (1 - F);

  /* physical depth */
  *IntSnow += DeltaSnowInt;

  /* Calculate amount of rain intercepted on branches and stored in
     intercepted snow. */

  /* physical depth */
  MaxWaterInt = LIQUID_WATER_CAPACITY * (*IntSnow) + MaxInt;

  if ((*IntRain + *RainFall) <= MaxWaterInt) {
    /* physical depth */
    *IntRain += *RainFall;
    /* pixel depth */
    RainThroughFall = *RainFall * (1 - F);
  }
  else {
    /* pixel depth */
    RainThroughFall = (*IntRain + *RainFall - MaxWaterInt) * F +
      (*RainFall * (1 - F));
    /* physical depth */
    *IntRain = MaxWaterInt;
  }

  /* Now that total intercepted water has been calculated, allow for structural
     unloading of branches.  I.e. if absolute maximum capacity is reached then
     allow sliding due to branch bending.  Of course, if chunks of snow are
     falling, they can contain both ice and liquid water - Let both of these
     come off in the correct proportions */

  if (*IntRain + *IntSnow > MaxIntercept) {
    overload = (*IntRain + *IntSnow) - MaxIntercept;
    intsnowfrac = *IntSnow / (*IntSnow + *IntRain);
    intrainfrac = *IntRain / (*IntSnow + *IntRain);
    *IntRain = *IntRain - overload * intrainfrac;
    *IntSnow = *IntSnow - overload * intsnowfrac;
    SnowThroughFall = SnowThroughFall + overload * intsnowfrac * F;
    RainThroughFall = RainThroughFall + overload * intrainfrac * F;
  }

  /* The canopy temperature is assumed to be equal to the air temperature if
     the air temperature is below 0C, otherwise the canopy temperature is
     equal to 0C */

  if (Tair > 0.)
    *Tcanopy = 0.;
  else
    *Tcanopy = Tair;

  /* Calculate the net radiation at the canopy surface, using the canopy
     temperature.  The outgoing longwave is subtracted twice, because the
     canopy radiates in two directions */

  Tmp = *Tcanopy + 273.15;
  LongOut = STEFAN * (Tmp * Tmp * Tmp * Tmp);
  NetRadiation = LocalRad->NetShort[0] + LocalRad->LongIn[0] - 2 * F * LongOut;
  NetRadiation /= F;

  /* Calculate the vapor mass flux between the canopy and the surrounding
     air mass - snow covered aerodynamic resistance is assumed to increase by an order
     of magnitude based on Lunderg et al 1998, Journal of Hydrological Processes */

  EsSnow = SatVaporPressure(*Tcanopy);
  *VaporMassFlux = AirDens * (EPS / Press) * (EactAir - EsSnow) / (Ra * 10.0);
  *VaporMassFlux /= WATER_DENSITY;
  if (fequal(Vpd, 0.0) && *VaporMassFlux < 0.0)
    *VaporMassFlux = 0.0;

  /* Calculate the latent heat flux */

  Ls = (677. - 0.07 * *Tcanopy) * JOULESPCAL * GRAMSPKG;
  LatentHeat = Ls * *VaporMassFlux * WATER_DENSITY;

  /* Calculate the sensible heat flux */

  SensibleHeat = AirDens * CP * (Tair - *Tcanopy) / (Ra * 10.0);

  /* Calculate the advected energy */

  AdvectedEnergy = (CH_WATER * Tair * *RainFall) / Dt;

  /* Calculate the amount of energy available for refreezing */

  RefreezeEnergy = SensibleHeat + LatentHeat + NetRadiation + AdvectedEnergy;

  RefreezeEnergy *= Dt;

  /* if RefreezeEnergy is positive it means energy is available to melt the
     intercepted snow in the canopy.  If it is negative, it means that
     intercepted water will be refrozen */

  /* Update maximum water interception storage */

  MaxWaterInt = LIQUID_WATER_CAPACITY * (*IntSnow) + MaxInt;

  /* Convert the vapor mass flux from a flux to a depth per interval */
  *VaporMassFlux *= Dt;

  if (RefreezeEnergy > 0.0) {	/*we've got melt */

    if (-(*VaporMassFlux) > *IntRain) {
      *VaporMassFlux = -(*IntRain);
      *IntRain = 0.;
    }
    else
      *IntRain += *VaporMassFlux;

    PotSnowMelt = MIN((RefreezeEnergy / (LF * WATER_DENSITY)), *IntSnow);

    *MeltEnergy -= (LF * PotSnowMelt * WATER_DENSITY) / Dt;

    if ((*IntRain + PotSnowMelt) <= MaxWaterInt) {
      /* if the intercepted rain and potential snowmelt is less than the
         liquid water holding capacity of the intercepted snowpack, then simply
         add the total potential snowmelt to the liquid water content of the
         intercepted snowpack. */
      *IntSnow -= PotSnowMelt;
      *IntRain += PotSnowMelt;
      PotSnowMelt = 0.0;
    }
    else {
      ExcessSnowMelt = PotSnowMelt + *IntRain - MaxWaterInt;

      *IntSnow -= MaxWaterInt - (*IntRain);
      *IntRain = MaxWaterInt;
      if (*IntSnow < 0.0)
	*IntSnow = 0.0;

      if (SnowThroughFall > 0.0 && InitialSnowInt <= MIN_INTERCEPTION_STORAGE) {
	/* Water in excess of MaxWaterInt has been generated.  If it is
	   snowing and there was little intercepted snow at the beginning of the
	   time step ( <= MIN_INTERCEPTION_STORAGE), then allow the snow to melt
	   as it is intercepted.  Also, enforce that the following holds true:
	   if Intercpeted snow is below minimum thresold then it can only be
	   removed via melting */
	Drip += ExcessSnowMelt;
	*IntSnow -= ExcessSnowMelt;
	if (*IntSnow < 0.0)
	  *IntSnow = 0.0;
	ExcessSnowMelt = 0.0;
      }
      else
	/* Else, SnowThroughFall = 0.0 or SnowThroughFall > 0.0 and there is a
	   substantial amount of intercepted snow at the beginning of the time
	   step ( > MIN_INTERCEPTION_STORAGE).  Snow melt may generate mass
	   release. */

	*TempIntStorage += ExcessSnowMelt;

      MassRelease(IntSnow, TempIntStorage, &ReleasedMass, &Drip, MDRatio);
    }

    /* If intercepted snow has melted, add the water it held to drip */

    MaxWaterInt = LIQUID_WATER_CAPACITY * (*IntSnow) + MaxInt;
    if (*IntRain > MaxWaterInt) {
      Drip += *IntRain - MaxWaterInt;
      *IntRain = MaxWaterInt;
    }
  }

  else {			/* else (RefreezeEnergy <= 0.0) */

    /* Reset *TempIntStorage to 0.0 when energy balance is negative */

    *TempIntStorage = 0.0;

    /* Refreeze as much surface water as you can */

    if (RefreezeEnergy > -(*IntRain) * LF) {
      *IntSnow += fabs(RefreezeEnergy) / LF;
      *IntRain -= fabs(RefreezeEnergy) / LF;

      *MeltEnergy += (fabs(RefreezeEnergy) * WATER_DENSITY) / Dt;

      RefreezeEnergy = 0.0;
    }

    else {

      /* All of the water in the surface layer has been frozen. */

      *IntSnow += *IntRain;

      /* Added on April 8 as a test */
      /*       RefreezeEnergy += *IntRain*LF; */
      /*       *VaporMassFlux = MAX(*VaporMassFlux,  */
      /*                            RefreezeEnergy/(Ls * WATER_DENSITY)); */

      /* Energy released by freezing of intercepted water is added to the
         MeltEnergy */

      *MeltEnergy += (LF * *IntRain * WATER_DENSITY) / Dt;
      *IntRain = 0.0;

    }

    if (-(*VaporMassFlux) > *IntSnow) {
      *VaporMassFlux = -(*IntSnow);
      *IntSnow = 0.0;
    }
    else
      *IntSnow += *VaporMassFlux;
  }

  /* Convert drip, mass, *IntSnow, *IntRain, *MeltEnergy and
   *int_vapor_flux from physical depths to pixel depths.  Update p0 and
   snow_fract. */

  *IntSnow *= F;
  *IntRain *= F;
  *MeltEnergy *= F;
  *VaporMassFlux *= F;
  Drip *= F;
  ReleasedMass *= F;

  /* Calculate intercepted H2O balance. */

  MassBalanceError = (InitialWaterInt - (*IntSnow + *IntRain)) +
    (*SnowFall + *RainFall) -
    (SnowThroughFall + RainThroughFall + Drip + ReleasedMass) + *VaporMassFlux;

  *RainFall = RainThroughFall + Drip;
  *SnowFall = SnowThroughFall + ReleasedMass;

   /* Find momentum squared of rainfall for use by the sediment model. */
  if(Understory)
     /* Since the understory is assumed to cover the entire grid cell, all
       momentum is associated with leaf drip, eq. 2, Wicks and Bathurst (1996) */
    *MomentSq = pow(LD_FallVelocity * WATER_DENSITY, 2) * PI/6 *
      pow(LEAF_DRIP_DIA, 3) * (*RainFall)/Dt;
  else
    /* If no understory, part of the rainfall reaches the ground as direct throughfall. */
     *MomentSq = pow(LD_FallVelocity * WATER_DENSITY, 2) * PI/6 *
      pow(LEAF_DRIP_DIA, 3) * Drip/Dt + (1-F) * MS_Rainfall;
}
/*****************************************************************************
  Function name: SnowInterception()

  Purpose      : Calculate snow interception and release by the canopy

  Required     :
    int Dt                 - Model timestep (hours)
    double F                - Fractional coverage
    double LAI              - Leaf Area Index
    double MaxInt           - Maximum rainfall interception storage (m)
    double Ra               - Aerodynamic resistance (uncorrected for
                             stability) (s/m)
    double *Ra_used         - Aerodynamic resistance after adjustments (s/m)
    double AirDens          - Density of air (kg/m3)
    double EactAir          - Actual vapor pressure of air (Pa) 
    double Lv               - Latent heat of vaporization (J/kg3)
    PIXRAD *LocalRad       - Components of radiation balance for current pixel
                             (W/m2) 
    double Press            - Air pressure (Pa)
    double Tair             - Air temperature (C) 
    double Vpd	           - Vapor pressure deficit (Pa) 
    double Wind             - Wind speed (m/s)
    double *RainFall        - Amount of rain (m)
    double *Snowfall        - Amount of snow (m)
    double *IntRain         - Intercepted rain (m) 
    double *IntSnow         - Snow water equivalent of intercepted snow (m)
    double *TempIntStorage  - Temporary storage for snowmelt and rainfall
                             involved in mass release calculations (m)
    double *VaporMassFlux   - Vapor mass flux to/from intercepted snow
                             (m/timestep)
    double *Tcanopy         - Canopy temperature (C)
    double *MeltEnergy      - Energy used in heating and melting of the snow 
                             (W/m2)

  Returns      : none

  Modifies     :
    double *Ra_used         - Aerodynamic resistance after adjustments (s/m)
    double *RainFall        - Amount of rain (m)
    double *Snowfall        - Amount of snow (m)
    double *IntRain         - Intercepted rain (m) 
    double *IntSnow         - Snow water equivalent of intercepted snow (m)
    double *TempIntStorage  - Temporary storage for snowmelt and rainfall
                             involved in mass release calculations (m)
    double *VaporMassFlux   - Vapor mass flux to/from intercepted snow
                             (m/timestep)  
    double *Tcanopy         - Canopy temperature (C)

  Comments     : Only the top canopy layer is taken into account for snow
                 interception.  Snow interception by lower canopy is
                 disregarded.  Rain water CAN be intercepted by lower canopy
                 layers (similar to InterceptionStorage()).
                 Of course:  NO vegetation -> NO interception

  Modifications:
  06-98 included maximum structural loading to prevent the model
        from loading the canopy with more snow than it can handle
        structurally.                                             PXS
  09-98 aerodynamic resistances in the canopy when snow has been  
        intercepted is increased by a factor of 10:  include REF
        Journal of Hydrology, 1998                            KAC, GO'D
  28-Sep-04 Added Ra_used to store the aerodynamic resistance actually
	    used in flux calculations.				TJB

*****************************************************************************/
void snow_intercept(double Dt, 
		    double F,  
		    double LAI, 
		    double MaxInt, 
		    double Ra, 
		    double *Ra_used, 
		    double AirDens,
		    double EactAir, 
		    double Lv, 
		    double Shortwave,
		    double Longwave, 
		    double Press, 
		    double Tair, 
		    double Vpd, 
		    double Wind,  
		    double *RainFall,
		    double *SnowFall, 
		    double *IntRain, 
		    double *IntSnow,
		    double *TempIntStorage, 
		    double *VaporMassFlux,
		    double *Tcanopy, 
		    double *MeltEnergy, 
		    int month, 
		    int rec,
		    int hour)
{
  double AdvectedEnergy;         /* Energy advected by the rain (W/m2) */
  double BlownSnow;              /* Depth of snow blown of the canopy (m) */
  double DeltaSnowInt;           /* Change in the physical swe of snow
				    interceped on the branches. (m) */
  double Drip;                   /* Amount of drip from intercepted snow as a
				    result of snowmelt (m) */
  double ExcessSnowMelt;         /* Snowmelt in excess of the water holding
				    capacity of the tree (m) */
  double EsSnow;                 /* saturated vapor pressure in the snow pack
                                   (Pa)  */
  double InitialSnowInt;         /* Initial intercepted snow (m) */ 
  double InitialWaterInt;        /* Initial intercepted water (snow and rain)
                                    (m) */ 
  double LatentHeat;             /* Latent heat flux (W/m2) */
  double LongOut;                /* Longwave radiation emitted by canopy 
                                   (W/m2) */
  double Ls;                     /* Latent heat of sublimation (J/(kg K) */
  double MassBalanceError;       /* Mass blalnce to make sure no water is
				    being destroyed/created (m) */
  double MaxWaterInt;            /* Water interception capacity (m) */  
  double MaxSnowInt;             /* Snow interception capacity (m) */
  double NetRadiation;
  double PotSnowMelt;            /* Potential snow melt (m) */
  double RainThroughFall;        /* Amount of rain reaching to the ground (m)
				  */ 
  double RefreezeEnergy;         /* Energy available for refreezing or melt */
  double ReleasedMass;           /* Amount of mass release of intercepted snow
				    (m) */ 
  double SensibleHeat;           /* Sensible heat flux (W/m2) */
  double SnowThroughFall;        /* Amount of snow reaching to the ground (m)
				  */ 
  double Tmp;                    /* Temporary variable */

  double Imax1;                  /* maxium water intecept regardless of temp */
  double IntRainFract;           /* Fraction of intercpeted water which is 
				    liquid */
  double IntSnowFract;           /* Fraction of intercepted water which is 
				    solid */
  double Overload;               /* temp variable to calculated structural 
				    overloading */

  /* Convert Units from VIC (mm -> m) */
  *RainFall /= 1000.;
  *SnowFall /= 1000.;
  *IntRain  /= 1000.;
  MaxInt    /= 1000.;

  /* Initialize Drip, H2O balance, and mass release variables. */
  
  InitialWaterInt = *IntSnow + *IntRain;
  
  *IntSnow /= F;
  *IntRain /= F;
  
  InitialSnowInt = *IntSnow;
  
  Drip = 0.0;
  ReleasedMass = 0.0;
  
  /* Determine the maximum snow interception water equivalent.           
     Kobayashi, D., 1986, Snow Accumulation on a Narrow Board,           
     Cold Regions Science and Technology, (13), pp. 239-245.           
     Figure 4. */  
  
  Imax1 = 4.0* LAI_SNOW_MULTIPLIER * LAI;

  if (Tair < -1.0 && Tair > -3.0)
    MaxSnowInt = (Tair*3.0/2.0) + (11.0/2.0);
  else if (Tair > -1.0) 
    MaxSnowInt = 4.0;  
  else
    MaxSnowInt = 1.0;
  
  /* therefore LAI_ratio decreases as temp decreases */
  
  MaxSnowInt *= LAI_SNOW_MULTIPLIER * LAI;
  
  /* Calculate snow interception. */  
  
  DeltaSnowInt = (1-*IntSnow/MaxSnowInt) * *SnowFall; 
  if (DeltaSnowInt + *IntSnow > MaxSnowInt) 
    DeltaSnowInt = MaxSnowInt - *IntSnow;
  if (DeltaSnowInt < 0.0)  
    DeltaSnowInt = 0.0;
  
  /* Reduce the amount of intercepted snow if windy and cold.         
     Ringyo Shikenjo Tokyo, #54, 1952.                                
     Bulletin of the Govt. Forest Exp. Station,                       
     Govt. Forest Exp. Station, Meguro, Tokyo, Japan.                 
     FORSTX 634.9072 R475r #54.                                       
     Page 146, Figure 10.                                               
     
     Reduce the amount of intercepted snow if snowing, windy, and     
     cold (< -3 to -5 C).                                             
     Schmidt and Troendle 1992 western snow conference paper. */  
  
  if (Tair < -3.0 && DeltaSnowInt > 0.0 && Wind > 1.0) {
    BlownSnow = (0.2 * Wind - 0.2) * DeltaSnowInt;
    if (BlownSnow >= DeltaSnowInt) 
      BlownSnow = DeltaSnowInt;
    DeltaSnowInt -= BlownSnow;
  }
  
  /* now update snowfall and total accumulated intercepted snow amounts */

  if (*IntSnow +  DeltaSnowInt > Imax1) DeltaSnowInt =0.0; 
  
  /* pixel depth    */ 
  SnowThroughFall = (*SnowFall - DeltaSnowInt) * F + (*SnowFall) * (1 - F);
  
  /* physical depth */
  *IntSnow += DeltaSnowInt;
  
  /* Calculate amount of rain intercepted on branches and stored in
     intercepted snow. */  
  
  /* physical depth */
  MaxWaterInt = LIQUID_WATER_CAPACITY * (*IntSnow) + MaxInt;
  
  if ((*IntRain + *RainFall) <= MaxWaterInt) {
    /* physical depth */
    *IntRain += *RainFall;
    /* pixel depth */
    RainThroughFall = *RainFall * (1 - F);      
  }
  else {
    /* pixel depth */
    RainThroughFall = (*IntRain + *RainFall - MaxWaterInt) * F + 
      (*RainFall * (1 - F));
    /* physical depth */
    *IntRain = MaxWaterInt;
  }

  /* at this point we have calculated the amount of snowfall intercepted and
     the amount of rainfall intercepted.  These values have been 
     appropriately subtracted from SnowFall and RainFall to determine 
     SnowThroughfall and RainThroughfall.  However, we can end up with the 
     condition that the total intercepted rain plus intercepted snow is 
     greater than the maximum bearing capacity of the tree regardless of air 
     temp (Imax1).  The following routine will adjust *IntRain and *IntSnow 
     by triggering mass release due to overloading.  Of course since *IntRain
     and *IntSnow are mixed, we need to slough them of as fixed fractions  */

  if (*IntRain + *IntSnow > Imax1) { /*then trigger structural unloading*/
    Overload = (*IntSnow + *IntRain) - Imax1;
    IntRainFract= *IntRain/(*IntRain + *IntSnow);
    IntSnowFract = *IntSnow/(*IntRain + *IntSnow);
    *IntRain = *IntRain - Overload*IntRainFract;
    *IntSnow = *IntSnow - Overload*IntSnowFract;
    RainThroughFall = RainThroughFall + (Overload*IntRainFract)*F;
    SnowThroughFall = SnowThroughFall + (Overload*IntSnowFract)*F;
  }
  
  /* The canopy temperature is assumed to be equal to the air temperature if 
     the air temperature is below 0C, otherwise the canopy temperature is 
     equal to 0C */
  
  if (Tair > 0.)
    *Tcanopy = 0.;
  else
    *Tcanopy = Tair;

  /* Calculate the net radiation at the canopy surface, using the canopy 
     temperature.  The outgoing longwave is subtracted twice, because the 
     canopy radiates in two directions */

  Tmp = *Tcanopy + 273.15;
  LongOut = STEFAN_B * (Tmp * Tmp * Tmp * Tmp);
  NetRadiation = (1.-NEW_SNOW_ALB)*Shortwave + Longwave - 2 * F * LongOut;
  NetRadiation /= F;

  /* Calculate the vapor mass flux between the canopy and the surrounding 
     air mass */
  
  EsSnow = svp(*Tcanopy); 

  *Ra_used = Ra;

  /** Added division by 10 to incorporate change in canopy resistance due
      to smoothing by intercepted snow **/
  *VaporMassFlux = AirDens * (0.622/Press) * (EactAir - EsSnow) / *Ra_used / 10.0;
  *VaporMassFlux /= RHO_W; 

  if (Vpd == 0.0 && *VaporMassFlux < 0.0)
    *VaporMassFlux = 0.0;
  
  /* Calculate the latent heat flux */

  Ls = (677. - 0.07 * *Tcanopy) * 4.1868 * 1000.;
  LatentHeat = Ls * *VaporMassFlux * RHO_W;

  /* Calculate the sensible heat flux */

  SensibleHeat = AirDens * Cp * (Tair - *Tcanopy) / *Ra_used;
  
  /** Multiply Ra by 10 to reflect the value used in calculating VaporMassFlux **/
  *Ra_used *= 10.0;

  /* Calculate the advected energy */

  AdvectedEnergy = (4186.8 * Tair * *RainFall)/(Dt * SECPHOUR);

  /* Calculate the amount of energy available for refreezing */

  RefreezeEnergy = SensibleHeat + LatentHeat + NetRadiation + AdvectedEnergy;

  RefreezeEnergy *= Dt * SECPHOUR;

  /* if RefreezeEnergy is positive it means energy is available to melt the
     intercepted snow in the canopy.  If it is negative, it means that 
     intercepted water will be refrozen */
  
  /* Update maximum water interception storage */
  
  MaxWaterInt = LIQUID_WATER_CAPACITY * (*IntSnow) + MaxInt;

  /* Convert the vapor mass flux from a flux to a depth per interval */
  *VaporMassFlux *= Dt * SECPHOUR;
  
  if (RefreezeEnergy > 0.0) {

    if (-(*VaporMassFlux) > *IntRain) {
      *VaporMassFlux = -(*IntRain);
      *IntRain = 0.;
    }
    else
      *IntRain += *VaporMassFlux;

    PotSnowMelt = min((RefreezeEnergy/Lf/RHO_W), *IntSnow);

    *MeltEnergy -= (Lf * PotSnowMelt * RHO_W) / (Dt *SECPHOUR);
    
    if ((*IntRain + PotSnowMelt) <= MaxWaterInt) {

      *IntSnow -= PotSnowMelt;
      *IntRain += PotSnowMelt;
      PotSnowMelt = 0.0;

    }
    
    else {

      ExcessSnowMelt = PotSnowMelt + *IntRain - MaxWaterInt;
      
      *IntSnow -= MaxWaterInt - (*IntRain);
      *IntRain = MaxWaterInt;
      if (*IntSnow < 0.0) 
        *IntSnow = 0.0;
      
      if (SnowThroughFall > 0.0 && 
	  InitialSnowInt <= MIN_INTERCEPTION_STORAGE) {
        /* Water in excess of MaxWaterInt has been generated.  If it is 
           snowing and there was little intercepted snow at the beginning 
	   of the time step ( <= MIN_INTERCEPTION_STORAGE), then allow the 
	   snow to melt as it is intercepted */
        Drip += ExcessSnowMelt; 
        *IntSnow -= ExcessSnowMelt;
        if (*IntSnow < 0.0) 
          *IntSnow = 0.0;
      }
      else 
      /* Else, SnowThroughFall = 0.0 or SnowThroughFall > 0.0 and there is a 
         substantial amount of intercepted snow at the beginning of the time 
         step ( > MIN_INTERCEPTION_STORAGE).  Snow melt may generate mass 
         release. */
        *TempIntStorage += ExcessSnowMelt;
      
      MassRelease(IntSnow, TempIntStorage, &ReleasedMass, &Drip);
    }
    
    /* If intercepted snow has melted, add the water it held to drip */
    
    MaxWaterInt = LIQUID_WATER_CAPACITY * (*IntSnow) + MaxInt;
    if (*IntRain > MaxWaterInt) {
      Drip += *IntRain - MaxWaterInt;
      *IntRain = MaxWaterInt;
    }
  }  
  
  else /* else (RefreezeEnergy <= 0.0) */ {
    
    /* Reset *TempIntStorage to 0.0 when energy balance is negative */
    
    *TempIntStorage = 0.0;
    
    /* Refreeze as much surface water as you can */
    
    if (RefreezeEnergy > - (*IntRain) * Lf) {
      *IntSnow += fabs(RefreezeEnergy) / Lf;
      *IntRain -= fabs(RefreezeEnergy) / Lf;

      *MeltEnergy += (fabs(RefreezeEnergy) * RHO_W) / (Dt *SECPHOUR);

      RefreezeEnergy = 0.0;
    }

    else {
      
      /* All of the water in the surface layer has been frozen. */
      
      *IntSnow += *IntRain;
     
      /* Added on April 8 as a test */
      /*       RefreezeEnergy += *IntRain*Lf; */
      /*       *VaporMassFlux = MAX(*VaporMassFlux,  */
      /*                            RefreezeEnergy/(Ls * RHO_W)); */
      
      /* Energy released by freezing of intercepted water is added to the 
         MeltEnergy */

      *MeltEnergy += (Lf * *IntRain * RHO_W) / (Dt *SECPHOUR);
      *IntRain = 0.0;
      
    } 
    
    if (-(*VaporMassFlux) > *IntSnow) {
      *VaporMassFlux = -(*IntSnow);
      *IntSnow = 0.0;
    }
    else
      *IntSnow += *VaporMassFlux;
  } 
  
  *IntSnow *= F;
  *IntRain *= F;
  *MeltEnergy *= F;
  *VaporMassFlux *= F;
  Drip           *= F;
  ReleasedMass   *= F;
  
  /* Calculate intercepted H2O balance. */  
  
  MassBalanceError = (InitialWaterInt - (*IntSnow + *IntRain))
                   + (*SnowFall + *RainFall) - (SnowThroughFall
                   + RainThroughFall + Drip + ReleasedMass)
                   + *VaporMassFlux;

  *RainFall = RainThroughFall + Drip;
  *SnowFall = SnowThroughFall + ReleasedMass;

  /* Convert Units to VIC (m -> mm) */
  *VaporMassFlux *= -1.;
  *RainFall *= 1000.;
  *SnowFall *= 1000.;
  *IntRain  *= 1000.;

}
Example #3
0
/******************************************************************************
 * @brief    Calculates mass release of snow from canopy.
 *****************************************************************************/
void
MassRelease(double *InterceptedSnow,
            double *TempInterceptionStorage,
            double *ReleasedMass,
            double *Drip)
{
    extern parameters_struct param;

    double                   TempDrip;
    double                   TempReleasedMass;
    double                   Threshold;
    double                   MaxRelease;

    /* If the amount of snow in the canopy is greater than some minimum
       value, MIN_INTERCEPTION_STORAGE, then calculte mass release and Drip */

    if (*InterceptedSnow > param.VEG_MIN_INTERCEPTION_STORAGE) {
        Threshold = 0.10 * *InterceptedSnow;
        MaxRelease = 0.17 * *InterceptedSnow;

        /* If the amount of snow_melt after interception, snow_melt, is >= the
           theshhold then there is mass release.  If snow_melt is < the treshhold
           then there is no mass release but that water remains in
         * TempInterceptionStorage which will be augmented during the next
           compute period */

        if ((*TempInterceptionStorage) >= Threshold) {
            *Drip += Threshold;
            *InterceptedSnow -= Threshold;
            *TempInterceptionStorage -= Threshold;
            if (*InterceptedSnow < param.VEG_MIN_INTERCEPTION_STORAGE) {
                TempReleasedMass = 0.0;
            }
            else {
                TempReleasedMass =
                    min((*InterceptedSnow - param.VEG_MIN_INTERCEPTION_STORAGE),
                        MaxRelease);
            }
            *ReleasedMass += TempReleasedMass;
            *InterceptedSnow -= TempReleasedMass;
            MassRelease(InterceptedSnow, TempInterceptionStorage, ReleasedMass,
                        Drip);
        }
        else {
            TempDrip = min(*TempInterceptionStorage, *InterceptedSnow);
            *Drip += TempDrip;
            *InterceptedSnow -= TempDrip;
        }
    }

    /* (*InterceptedSnow < MIN_INTERCEPTION_STORAGE) If the amount of snow in
       the canopy is less than some minimum value, MIN_INTERCEPTION_STORAGE,
       then only melt can occur and there is no mass release. */

    else {
        TempDrip = min(*TempInterceptionStorage, *InterceptedSnow);
        *Drip += TempDrip;
        *InterceptedSnow -= TempDrip;
        *TempInterceptionStorage = 0.0;
    }
}
Example #4
0
/*****************************************************************************
  Function name: MassRelease()

  Purpose      : Calculates mass release of snow from canopy

  Required     :
    float *InterceptedSnow
    float *TempInterceptionStorage
    float *ReleasedMass
    float *Drip 

  Returns      : none

  Modifies     : see under required (i.e. all variables are modified)

  Comments     : Modified 02/12/08 to match VIC snow model- Elizabeth Clark
  *              ****No longer calls MDRatio-EC
*****************************************************************************/
void MassRelease(float *InterceptedSnow, float *TempInterceptionStorage,
		 float *ReleasedMass, float *Drip)
{
  float TempDrip;
  float TempReleasedMass;
  float Threshold;
  float MaxRelease;

  /* If the amount of snow in the canopy is greater than some minimum
     value, MIN_INTERCEPTION_STORAGE, then calculte mass release and Drip */

  if (*InterceptedSnow > MIN_INTERCEPTION_STORAGE) {
    Threshold  = 0.10 * *InterceptedSnow;
    MaxRelease = 0.17 * *InterceptedSnow;
    
    /* If the amount of snow_melt after interception, snow_melt, is >= the
       theshhold then there is mass release.  If snow_melt is < the treshhold
       then there is no mass release but that water remains in
       *TempInterceptionStorage which will be augmented during the next
       compute period */
    /*
    if ((*TempInterceptionStorage) >= 0.0) {
      *Drip += *TempInterceptionStorage;
      *InterceptedSnow -= *TempInterceptionStorage;

      if (*InterceptedSnow < MIN_INTERCEPTION_STORAGE)
	TempReleasedMass = 0.0;
      else
	TempReleasedMass = MIN((*InterceptedSnow - MIN_INTERCEPTION_STORAGE),
			       *TempInterceptionStorage * MDRatio);
      *ReleasedMass += TempReleasedMass;
      *InterceptedSnow -= TempReleasedMass;
      *TempInterceptionStorage = 0;

      }

    else {
      TempDrip = MIN(*TempInterceptionStorage, *InterceptedSnow);
      *Drip += TempDrip;
      *InterceptedSnow -= TempDrip;
    }
    }*/
    if ((*TempInterceptionStorage) >= Threshold) {
      
      
      *Drip += Threshold;
      *InterceptedSnow -= Threshold;
      *TempInterceptionStorage -= Threshold;
      if (*InterceptedSnow < MIN_INTERCEPTION_STORAGE)
        TempReleasedMass = 0.0;
      else
        TempReleasedMass = MIN((*InterceptedSnow - MIN_INTERCEPTION_STORAGE),
                               MaxRelease); 
      *ReleasedMass += TempReleasedMass;
      *InterceptedSnow -= TempReleasedMass;
      MassRelease(InterceptedSnow, TempInterceptionStorage, ReleasedMass,
                  Drip); 
    }

    else {
      TempDrip = MIN(*TempInterceptionStorage, *InterceptedSnow);
      *Drip += TempDrip;
      *InterceptedSnow -= TempDrip;
    }
  }


  /* (*InterceptedSnow < MIN_INTERCEPTION_STORAGE) If the amount of snow in
     the canopy is less than some minimum value, MIN_INTERCEPTION_STORAGE,
     then only melt can occur and there is no mass release. */

  else {
    TempDrip = MIN(*TempInterceptionStorage, *InterceptedSnow);
    *Drip += TempDrip;
    *InterceptedSnow -= TempDrip;
    *TempInterceptionStorage = 0.0;
  }
}