Example #1
0
/******************************************************************************
 * @brief    Calculate sublimation from blowing snow
 *****************************************************************************/
double
CalcBlowingSnow(double   Dt,
                double   Tair,
                unsigned LastSnow,
                double   SurfaceLiquidWater,
                double   Wind,
                double   Ls,
                double   AirDens,
                double   EactAir,
                double   ZO,
                double   Zrh,
                double   snowdepth,
                double   lag_one,
                double   sigma_slope,
                double   Tsnow,
                int      iveg,
                int      Nveg,
                double   fe,
                double   displacement,
                double   roughness,
                double  *TotalTransport)
{
    extern parameters_struct param;
    extern option_struct     options;

    /* Local variables: */
    double                   Age;
    double                   U10, Uo, prob_occurence;
    double                   es, Ros, F;
    double                   SubFlux;
    double                   Diffusivity;
    double                   ushear;
    double                   Tk;
    double                   utshear;
    int                      p;
    double                   upper, lower, Total;
    double                   area;
    double                   sigma_w;
    double                   Zo_salt;
    double                   ratio, wind10;
    double                   Uveg, hv, Nd;
    double                   Transport;

    /*******************************************************************/
    /* Calculate some general variables, that don't depend on wind speed. */

    /* Age in hours */
    Age = LastSnow * Dt / SEC_PER_HOUR;

    /* Saturation density of water vapor, Liston A-8 */
    es = svp(Tair);

    Tk = Tair + CONST_TKFRZ;

    Ros = CONST_EPS * es / (CONST_RDAIR * Tk);

    /* Diffusivity in m2/s, Liston eq. A-7 */
    Diffusivity = (2.06e-5) * pow(Tk / 273., 1.75);

    // Essery et al. 1999, eq. 6 (m*s/kg)
    F = (Ls / (param.BLOWING_KA * Tk)) * (Ls * Tk / CONST_RDAIR - 1.);
    F += 1. / (Diffusivity * Ros);

    /* grid cell 10 m wind speed = 50th percentile wind */
    /* Wind speed at 2 m above snow was passed to this function. */

    wind10 = Wind * log(10. / ZO) / log((2 + ZO) / ZO);

    /* Check for bare soil case. */
    if (iveg == Nveg) {
        fe = 1500;
        sigma_slope = .0002;
    }
    // sigma_w/uo:
    ratio = (2.44 - (0.43) * lag_one) * sigma_slope;

    sigma_w = wind10 * ratio;
    Uo = wind10;

    /*********** Parameters for roughness above snow. *****************/
    hv = (3. / 2.) * displacement;
    Nd = (4. / 3.) * (roughness / displacement);

    /*******************************************************************/
    /** Begin loop through wind probability function.                  */

    Total = 0.0;
    *TotalTransport = 0.0;
    area = 1. / (double) param.BLOWING_NUMINCS;

    if (snowdepth > 0.0) {
        if (options.BLOWING_SPATIAL_WIND && sigma_w != 0.) {
            for (p = 0; p < param.BLOWING_NUMINCS; p++) {
                SubFlux = lower = upper = 0.0;
                /* Find the limits of integration. */
                if (p == 0) {
                    lower = -9999;
                    upper = Uo + sigma_w * log(2. * (p + 1) * area);
                }
                else if (p > 0 && p < param.BLOWING_NUMINCS / 2) {
                    lower = Uo + sigma_w * log(2. * (p) * area);
                    upper = Uo + sigma_w * log(2. * (p + 1) * area);
                }
                else if (p < (param.BLOWING_NUMINCS - 1) && p >=
                         (double) param.BLOWING_NUMINCS / 2) {
                    lower = Uo - sigma_w * log(2. - 2. * (p * area));
                    upper = Uo - sigma_w * log(2. - 2. * ((p + 1.) * area));
                }
                else if (p == param.BLOWING_NUMINCS - 1) {
                    lower = Uo - sigma_w * log(2. - 2. * (p * area));
                    upper = 9999;
                }

                if (lower > upper) { /* Could happen if lower > Uo*2 */
                    lower = upper;
                    log_err("Error with probability boundaries");
                }


                /* Find expected value of wind speed for the interval. */
                U10 = Uo;
                if (lower >= Uo) {
                    U10 = -0.5 *
                          ((upper +
                            sigma_w) * exp((-1. / sigma_w) * (upper - Uo)) -
                           (lower +
                            sigma_w) *
                           exp((-1. / sigma_w) * (lower - Uo))) / area;
                }
                else if (upper <= Uo) {
                    U10 = 0.5 *
                          ((upper -
                            sigma_w) * exp((1. / sigma_w) * (upper - Uo)) -
                           (lower -
                            sigma_w) *
                           exp((1. / sigma_w) * (lower - Uo))) / area;
                }
                else {
                    log_err("Problem with probability ranges: Increment = %d, "
                            "integration limits = %f - %f", p, upper, lower);
                }

                if (U10 < 0.4) {
                    U10 = .4;
                }

                if (U10 > 25.) {
                    U10 = 25.;
                }
                /*******************************************************************/
                /* Calculate parameters for probability of blowing snow occurence. */
                /* ( Li and Pomeroy 1997) */

                if (snowdepth < hv) {
                    Uveg = U10 / sqrt(1. + 170 * Nd * (hv - snowdepth));
                }
                else {
                    Uveg = U10;
                }


                prob_occurence = get_prob(Tair, Age, SurfaceLiquidWater, Uveg);

                /*******************************************************************/
                /* Calculate threshold shear stress. Send 0 for constant or  */
                /* 1 for variable threshold after Li and Pomeroy (1997)      */

                utshear =
                    get_thresh(Tair, SurfaceLiquidWater, ZO);

                /* Iterate to find actual shear stress during saltation. */

                shear_stress(U10, ZO, &ushear, &Zo_salt, utshear);

                if (ushear > utshear) {
                    SubFlux = CalcSubFlux(EactAir, es, Zrh, AirDens, utshear,
                                          ushear, fe, Tsnow,
                                          Tair, U10, Zo_salt, F, &Transport);
                }
                else {
                    SubFlux = 0.0;
                    Transport = 0.0;
                }

                Total += (1. / (double) param.BLOWING_NUMINCS) * SubFlux *
                         prob_occurence;
                *TotalTransport += (1. / (double) param.BLOWING_NUMINCS) *
                                   Transport * prob_occurence;
            }
        }
        else {
            U10 = Uo;
            /*******************************************************************/
            /* Calculate parameters for probability of blowing snow occurence. */
            /* ( Li and Pomeroy 1997) */

            if (snowdepth < hv) {
                Uveg = U10 / sqrt(1. + 170 * Nd * (hv - snowdepth));
            }
            else {
                Uveg = U10;
            }

            prob_occurence = get_prob(Tair, Age, SurfaceLiquidWater, Uveg);

            /*******************************************************************/
            /* Calculate threshold shear stress. Send 0 for constant or  */
            /* 1 for variable threshold after Li and Pomeroy (1997)      */

            utshear = get_thresh(Tair, SurfaceLiquidWater, ZO);

            /* Iterate to find actual shear stress during saltation. */

            shear_stress(Uo, ZO, &ushear, &Zo_salt, utshear);

            if (ushear > utshear) {
                SubFlux = CalcSubFlux(EactAir, es, Zrh, AirDens, utshear,
                                      ushear, fe, Tsnow,
                                      Tair, Uo, Zo_salt, F, &Transport);
            }
            else {
                SubFlux = 0.0;
                Transport = 0.0;
            }
            Total = SubFlux * prob_occurence;
            *TotalTransport = Transport * prob_occurence;
        }
    }

    if (Total < -.00005) {
        Total = -.00005;
    }

    return Total;
}
Example #2
0
/*****************************************************************************
  Function name: CalcBlowingSnow()

  Purpose      : Calculate sublimation from blowing snow

  Required     :  double Dt;                     Model time step (hours) 
  double Tair;                    Air temperature (C) 
  int LastSnow;                   Time steps since last snowfall. 
  double SurfaceLiquidWater;      Liquid water in the surface layer (m) 
  double Wind;                    Wind speed (m/s), 2 m above snow 
  double Ls;                      Latent heat of sublimation (J/kg) 
  double AirDens;                 Density of air (kg/m3) 
  double Lv;                      Latent heat of vaporization (J/kg3) 
  double Press;                   Air pressure (Pa) 
  double EactAir;                 Actual vapor pressure of air (Pa) 
  double ZO;                      Snow roughness height (m)
  Returns      : BlowingMassFlux

  Modifies     : 

  Comments     : Called from SnowPackEnergyBalance
    Reference:  

*****************************************************************************/
double CalcBlowingSnow( double Dt, 
			double Tair,
			int LastSnow,
			double SurfaceLiquidWater,
			double Wind,
			double Ls,
			double AirDens,
			double Press,
			double EactAir,
			double ZO,
			double Zrh,
			double snowdepth,
			float lag_one,
			float sigma_slope,
			double Tsnow, 
			int iveg, 
			int Nveg, 
			float fe,
			double displacement,
			double roughness,
			double *TotalTransport)

{
  /* Local variables: */

  double Age;
  double U10, Uo, prob_occurence;
  double es, Ros, F;
  double SubFlux;
  double Diffusivity;
  double ushear, Qsalt, hsalt, phi_s, psi_s;
  double Tk;
  double Lv;
  double T, ztop;
  double ut10, utshear;
  int p;
  double upper, lower, Total;
  double area;
  double sigma_w;
  double undersat_2;
  double b, temp2; /* SBSM scaling parameter. */
  double temp, temp3;
  double Zo_salt;
  double ratio, wind10;
  double Uveg, hv, Nd;
  double Transport;
  int count=0;

  Lv = (2.501e6 - 0.002361e6 * Tsnow);
  /*******************************************************************/
  /* Calculate some general variables, that don't depend on wind speed. */

  /* Age in hours */
  Age = LastSnow*(Dt);
      
  /* Saturation density of water vapor, Liston A-8 */
  es = svp(Tair);

  Tk = Tair  + KELVIN;
    
  Ros = 0.622*es/(287*Tk);
  
  /* Diffusivity in m2/s, Liston eq. A-7 */
  Diffusivity = (2.06e-5) * pow(Tk/273.,1.75);

  // Essery et al. 1999, eq. 6 (m*s/kg)
  F = (Ls/(Ka*Tk))*(Ls*MW/(R*Tk) - 1.);
  F += 1./(Diffusivity*Ros);

  /* grid cell 10 m wind speed = 50th percentile wind */
  /* Wind speed at 2 m above snow was passed to this function. */

  wind10 = Wind*log(10./ZO)/log((2+ZO)/ZO);
  //  fprintf(stderr,"wind=%f, Uo=%f\n",Wind, Uo);

  /* Check for bare soil case. */
  if(iveg == Nveg) {
    fe = 1500;
    sigma_slope = .0002;
  }
  // sigma_w/uo:
  ratio = (2.44 - (0.43)*lag_one)*sigma_slope;
  //  sigma_w = wind10/(.69+(1/ratio));
  //  Uo = sigma_w/ratio;
  
  sigma_w = wind10*ratio;
  Uo = wind10;
  
  /*********** Parameters for roughness above snow. *****************/
    hv = (3./2.)*displacement;
    Nd = (4./3.)*(roughness/displacement);

  /*******************************************************************/
  /** Begin loop through wind probability function.                  */

  Total = 0.0;
  *TotalTransport = 0.0;
  area = 1./NUMINCS;
  
  if(snowdepth > 0.0) {
    if(SPATIAL_WIND && sigma_w != 0.) {
      for(p= 0; p< NUMINCS; p++) {
      
	SubFlux = lower = upper = 0.0;
      /* Find the limits of integration. */
      if(p==0) {
	lower = -9999;
	upper = Uo + sigma_w*log(2.*(p+1)*area);
      }
      else if(p > 0 && p < NUMINCS/2) {
	lower = Uo + sigma_w*log(2.*(p)*area);
	upper = Uo + sigma_w*log(2.*(p+1)*area);
      }
      else if(p < (NUMINCS-1) && p >= NUMINCS/2) {
	lower = Uo - sigma_w*log(2.-2.*(p*area));
	upper = Uo - sigma_w*log(2.-2.*((p+1.)*area));
      }
      else if(p == NUMINCS-1) {
	lower =  Uo - sigma_w*log(2.-2.*(p*area));
	upper = 9999;
      }

      if(lower > upper)  {/* Could happen if lower > Uo*2 */
	lower = upper;
	fprintf(stderr,"Warning: Error with probability boundaries in CalcBlowingSnow()\n");
      }


      /* Find expected value of wind speed for the interval. */
      U10 = Uo;
      if(lower >= Uo ) 
	U10 = -0.5*((upper+sigma_w)*exp((-1./sigma_w)*(upper - Uo))
		    - (lower+sigma_w)*exp((-1./sigma_w)*(lower - Uo)))/area;
      else if(upper <= Uo )
	U10 = 0.5*((upper-sigma_w)*exp((1./sigma_w)*(upper - Uo))
		   - (lower-sigma_w)*exp((1./sigma_w)*(lower - Uo)))/area;
      else {
	fprintf(stderr,"ERROR in CalcBlowingSnow.c: Problem with probability ranges\n");
	fprintf(stderr,"  Increment = %d, integration limits = %f - %f\n",p,upper, lower);
        return ( ERROR );
      }
   
      if(U10 < 0.4)
	U10 = .4;

      if(U10 > 25.) U10 = 25.;
      /*******************************************************************/
      /* Calculate parameters for probability of blowing snow occurence. */
      /* ( Li and Pomeroy 1997) */

      if(snowdepth < hv) {
		Uveg = U10/sqrt(1.+ 170*Nd*(hv - snowdepth));
      }
      else
	Uveg = U10;
  
      //  fprintf(stderr, "Uveg = %f, U10 = %f\n",Uveg, U10);

      prob_occurence = get_prob(Tair, Age, SurfaceLiquidWater, Uveg);

      //   printf("prob=%f\n",prob_occurence);
     
      /*******************************************************************/
      /* Calculate threshold shear stress. Send 0 for constant or  */
      /* 1 for variable threshold after Li and Pomeroy (1997)      */

      utshear = get_thresh(Tair, SurfaceLiquidWater, ZO, VAR_THRESHOLD);
   
      /* Iterate to find actual shear stress during saltation. */

      shear_stress(U10, ZO, &ushear, &Zo_salt, utshear);
      
      if(ushear > utshear) {
	
	SubFlux = CalcSubFlux(EactAir, es, Zrh, AirDens, utshear,ushear, fe, Tsnow, 
			      Tair, U10, Zo_salt, F, &Transport);
      }
      else {
	SubFlux=0.0;
	Transport = 0.0;
      }
 
      Total += (1./NUMINCS)*SubFlux*prob_occurence;
      *TotalTransport += (1./NUMINCS)*Transport*prob_occurence;

      }
   
    }
    else {
      U10=Uo;
       /*******************************************************************/
      /* Calculate parameters for probability of blowing snow occurence. */
      /* ( Li and Pomeroy 1997) */
  
      if(snowdepth < hv)
	Uveg = U10/sqrt(1.+ 170*Nd*(hv - snowdepth));
      else
	Uveg = U10;

      prob_occurence = get_prob(Tair, Age, SurfaceLiquidWater, Uveg);
    
      /*******************************************************************/
      /* Calculate threshold shear stress. Send 0 for constant or  */
      /* 1 for variable threshold after Li and Pomeroy (1997)      */

      utshear = get_thresh(Tair, SurfaceLiquidWater, ZO, VAR_THRESHOLD);

      /* Iterate to find actual shear stress during saltation. */
      
      shear_stress(Uo, ZO, &ushear, &Zo_salt, utshear);

      if(ushear > utshear) {
	SubFlux = CalcSubFlux(EactAir, es, Zrh, AirDens, utshear,ushear, fe, Tsnow, 
			      Tair, Uo, Zo_salt, F, &Transport);
      }
      else {
	SubFlux=0.0;
	Transport = 0.0;
      }
      Total = SubFlux*prob_occurence;
      *TotalTransport = Transport*prob_occurence;
    }
  }

  if(Total < -.00005)
    Total = -.00005;
 
  return Total;
  
}