// 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(); };
// 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!"; }; }