Пример #1
0
// soil moisture calculation
void Soil_Env::updateDailySM(){

	// define the soil water module's domain
	Layer * fstsoill = ground->fstsoill;
	Layer * lstsoill = ground->lstsoill;
	Layer * drainl    = ground->drainl;
	double draindepth = ground->draindepth;

	// First, data connection
	double trans[MAX_SOI_LAY], melt, evap, rnth;

	for (int i=0; i<MAX_SOI_LAY; i++) {
		trans[i] = ed->d_v2a.tran*ed->d_soid.fbtran[i];  //mm/day: summed for all Vegetations
	}
    evap  = ed->d_soi2a.evap; //mm/day: summed for soil evaporation
    rnth  = (ed->d_v2g.rthfl +ed->d_v2g.rdrip)   // note: rthfl and rdrip are already fpc adjusted
    		+(1.- cd->m_vegd.fpcsum)*ed->d_a2l.rnfl; //mm/day

    melt  = ed->d_snw2soi.melt; //mm/day

	// 1) calculate the surface runoff and infiltration
    ed->d_soi2l.qover  = 0.;
    ed->d_soi2l.qdrain = 0.;

    ed->d_sois.watertab = getWaterTable(lstsoill);
    if(rnth+melt>0){
       	ed->d_soi2l.qover  = getRunoff(fstsoill, drainl, rnth, melt); //mm/day
    }else{
       	ed->d_soi2l.qover  = 0.;
    }

    double infil = rnth+melt-ed->d_soi2l.qover;
    ed->d_soi2l.qinfl = infil;

    // 2) Then soil water dynamics at daily time step

    double sinday= 86400.;

	for (int i=0; i<MAX_SOI_LAY; i++) {
		trans[i] /=sinday; // mm/day to mm/s
	}
	infil /=sinday; // mm/day to mm/s
	evap /=sinday;  // mm/day to mm/s

 	// water drainage condition
	double baseflow = 1.;    //fraction of bottom drainage (free) into water system: 0 - 1 upon drainage condition
    if(cd->gd->drgtype==1){  //0: well-drained; 1: poorly-drained
 		baseflow = 0.;
  	}

   	richards.update(fstsoill, drainl, draindepth, baseflow, trans, evap, infil, sinday);
   	ed->d_soi2l.qdrain  += richards.qdrain;

   	//
   	ground->checkWaterValidity();
};
Пример #2
0
// soil moisture calculation
void Soil_Env::updateDailySM(double weighted_veg_tran) {
  // define the soil water module's domain
  //Skip moss for all soil moisture calculations
  Layer * fstsoill = ground->fstshlwl;
  Layer * lstsoill = ground->lstsoill;
  Layer * drainl = ground->drainl;
  double draindepth = ground->draindepth;
  int topind = fstsoill->solind;

  // First, data connection
  //trans[MAX_SOI_LAY] = {0};
  double melt, evap, rnth;

  for (int il=0; il<MAX_SOI_LAY; il++) {
    // mm/day
    //CLM3 Equation 7.80
    root_water_up[il] = ed->d_soid.r_e_i[il] * weighted_veg_tran;

    if(root_water_up[il] != root_water_up[il]){
      BOOST_LOG_SEV(glg, err) << "NaN in root_water_up in updateDailySM";
    }
  }

  evap  = ed->d_soi2a.evap; // mm/day: summed for soil evaporation
  //Testing: turn off evap
  //evap = 0.0;

  // mm/day note: rthfl and rdrip are already fpc adjusted
  rnth  = (ed->d_v2g.rthfl + ed->d_v2g.rdrip) +
          (1.0 - cd->m_vegd.fpcsum) * ed->d_a2l.rnfl;

  melt  = ed->d_snw2soi.melt; // mm/day

  //Calculate surface runoff
  ed->d_soi2l.qover  = 0.0;
  ed->d_soi2l.qdrain = 0.0;
  //Update water table for runoff calculation
  ed->d_sois.watertab = getWaterTable(lstsoill);
  if( (rnth + melt) > 0 ) {
    ed->d_soi2l.qover = getRunoff(fstsoill, drainl, rnth, melt); // mm/day
  } else {
    ed->d_soi2l.qover = 0.0;
  }

  //Calculate infiltration (mm/day)
  double infil = rnth + melt - ed->d_soi2l.qover;

  //Get unsaturated space potentially available for liq infiltration (mm)
  double space_for_liq = 0.0;
  Layer *currl = fstsoill;
  if(drainl != NULL && ground->frnttype[0] != 1){//no infil if top of ground frozen
    int drainind = drainl->solind;
    while(currl != NULL && currl->solind <= drainind){
      double thetai = currl->getVolIce();
      double thetal = currl->getVolLiq();
      double avail_poro = fmax(fmin(currl->poro - thetai - thetal, currl->poro), 0.0);
      space_for_liq += avail_poro * DENLIQ * currl->dz;
      currl = currl->nextl;
    }
  }
  //Modify available pore space by the liquid that will be
  // infiltrating on this day.
  space_for_liq -= infil;
  space_for_liq = fmax(space_for_liq, 0.0);

  //Add runoff (up to 10 mm) to surface water storage (magic puddle)
  double space_in_puddle = ponding_max_mm - ed->d_soi2l.magic_puddle;
  double add_to_puddle = fmax(fmin(ed->d_soi2l.qover, space_in_puddle), 0.0);
  ed->d_soi2l.magic_puddle += add_to_puddle;
  //Subtracting surface water storage from runoff
  ed->d_soi2l.qover -= add_to_puddle;

  //If there is space remaining in the soil, and water in
  // the puddle, transfer water from the puddle
  // to the infiltration value.
  if(space_for_liq > 0.0 && ed->d_soi2l.magic_puddle > 0.0){
    //limit puddle contribution by max infiltration rate (CLM 5 eq 7.27)
    //with fmax = 0.25, fover = 0.5 m-1
    double fsat = 0.25 * pow(10.0, (-0.5 * 0.5 * ed->d_sois.watertab));
    double qinmax_layer = 1.e3; //initiate large to take min later
    currl = fstsoill;
    //Following CLM FORTRAN code and CLM 5
    //Use first three layers
    while(currl != NULL && currl->solind < topind + 3){
      double theta_ice = currl->getVolIce();
      double frac_ice = theta_ice / currl->poro;
      double imped_exp = -richards.e_ice * frac_ice;
      qinmax_layer = fmin(pow(10.0, imped_exp) * currl->hksat, qinmax_layer);
      currl = currl->nextl;
    }
    //CLM 5 eq 7.37:
    double qinmax = (1.0 - fsat) * qinmax_layer;
    qinmax *= SEC_IN_DAY; //convert to mm/day
    qinmax = fmax(qinmax, 0.5); //minimum of 0.5 mm/day

    double puddle2grnd = fmax(fmin(space_for_liq, ed->d_soi2l.magic_puddle), 0.0);
    puddle2grnd = fmax(fmin(puddle2grnd, qinmax), 0.0);
    infil += puddle2grnd;
    ed->d_soi2l.magic_puddle -= puddle2grnd;
    if(ed->d_soi2l.magic_puddle < 0.0){
      ed->d_soi2l.magic_puddle = 0.0;
    }
  }

  ed->d_soi2l.qinfl = infil;

  //Soil water dynamics at daily time step

  for (int i=0; i<MAX_SOI_LAY+1; i++) {
    root_water_up[i] /= SEC_IN_DAY; // mm/day to mm/s
  }

  infil /= SEC_IN_DAY; // mm/day to mm/s
  evap /= SEC_IN_DAY;  // mm/day to mm/s

  // water drainage condition
  double baseflow = 1.0; // fraction of bottom drainage (free) into water system:
                         //  0 - 1 upon drainage condition

  if(cd->drainage_type == 1) { // 0: well-drained; 1: poorly-drained
    baseflow = 0.0;
  }

  //This prevents Richards from executing in a talik. In the case of
  // a closed talik, there should be no water exiting other than
  // transpiration, and in the case of an open talik, our equations
  // may need modification. 
  if(ground->fstshlwl->frozen != 1 && ground->fstmossl->frozen != 1){
    richards.update(ground->fstshlwl, drainl, draindepth, baseflow,
                    ed->d_sois.watertab, root_water_up, evap,
                    infil, cd->cell_slope);
    ed->d_soi2l.qdrain += richards.qdrain;

    for(int il=0; il<MAX_SOI_LAY; il++){
      ed->d_soi2l.layer_drain[il] = richards.layer_drain[il];
    }
    checkSoilLiquidWaterValidity(fstsoill, topind);
  }
  else{
    //No percolation. Add any infil back to ponding/qover
    if(infil > 0.0){
      infil *= SEC_IN_DAY;// -->mm/day
      //Add to ponding
      space_in_puddle = ponding_max_mm - ed->d_soi2l.magic_puddle;
      add_to_puddle = fmin(space_in_puddle, infil);
      ed->d_soi2l.magic_puddle += add_to_puddle;
      infil -= add_to_puddle;
      ed->d_soi2l.qover += infil;
      ed->d_soi2l.qinfl = 0;
    }
    if(weighted_veg_tran > 0){
      //Subtract transpiration from each layer
      currl = fstsoill;
      while(currl!=NULL && currl->isSoil){
        if(currl->frozen < 1){
          double uptake = root_water_up[currl->solind-topind] * SEC_IN_DAY;
          currl->liq -= uptake;
        }
        currl = currl->nextl;
      }
      checkSoilLiquidWaterValidity(fstsoill, topind);
    }
  }
  //for moss layers excluded from hydrological process, match
  //water to first shallow layer.
  currl = ground->fstshlwl->prevl;
  while (currl!=NULL && currl->isMoss) {
    double lwc = ground->fstshlwl->getVolLiq();
    currl->liq = currl->dz*(1.0-currl->frozenfrac) * lwc * DENLIQ;
    currl=currl->prevl;
  }
  if(ed->d_soi2l.qdrain < 0){
   BOOST_LOG_SEV(glg, err) << "qdrain is negative!";
  };
}