LandscapeDNDC  1.36.0
ldndc::WatercycleDNDC Class Reference

Watercycle model WatercycleDNDC. More...

Inherits ldndc::MBE_LegacyModel.

Public Member Functions

lerr_t solve ()
 Kicks off computation for one time step.
 

Static Public Attributes

static const unsigned int IMAX_W = 24
 

Private Member Functions

lerr_t CalcIceContent ()
 Call of ice-content related processes.
 
double rainfall_intensity ()
 
lerr_t event_irrigate ()
 considers water input due to irrigation and/or liquid manure evetns
 
lerr_t event_flood ()
 sets hydrologic conditions during flooding events, e.g., More...
 
double balance_check (double *)
 checks each time step for correct water balance More...
 
void CalcRaining (unsigned int)
 apportion daily rainfall to subdaily rainfall
 
void CalcIrrigation (unsigned int)
 apportion daily irrigation to subdaily irrigation More...
 
lerr_t CalcPotEvapoTranspiration ()
 Potential evaporation. More...
 
void CalcInterception ()
 Calculates water quantity that is retained on leaf and stem bark surfaces. More...
 
double get_leaf_water ()
 Collects leaf water from all canopy layers. More...
 
double get_impedance_factor (size_t)
 Reduces water fluxes out of a layer if ice lenses have formed.
 
double get_clay_limitation (size_t, double, double)
 
lerr_t CalcTranspiration ()
 
lerr_t CalcTranspirationCouvreur (double const &hr_potTransinm)
 
void CalcSnowEvaporation ()
 
void CalcSurfaceFlux ()
 
void WatercycleDNDC_preferential_flow ()
 
void CalcSoilEvapoPercolation ()
 
void SoilWaterEvaporation (size_t)
 
void CalcSurfaceWaterEvaporation ()
 
double WaterFlowCapillaryRise (size_t, double const &)
 Similar to WaterFlowBelowFieldCapacity(...) but restricts water flow by water availability from soil layer below.
 
double WaterFlowAboveFieldCapacity (size_t, double const &)
 
double WaterFlowSaturated (size_t, double const &)
 
double get_fsl (size_t)
 Returns factor accounting for soil layer depth. Originally, a constant soil layer depth of 0.02 m has been assumed. Due to flexible layer depth, an additional factor has been introduced that accounts for a higher resistance of larger layers.
 
double get_time_step_duration ()
 Time fraction with regard to daily rates.
 

Private Attributes

double thornthwaite_heat_index
 heat index for potential evaporation using approach after Thornthwaite
 

Detailed Description

Watercycle model WatercycleDNDC.

Member Function Documentation

◆ balance_check()

double ldndc::WatercycleDNDC::balance_check ( double *  _balance)
private

checks each time step for correct water balance

Balance check of water.

2343 {
2344  double balance = get_leaf_water() + wc_.surface_ice + wc_.surface_water + m_wc.plant_waterdeficit_compensation;
2345  for ( size_t sl = 0; sl < m_soillayers->soil_layer_cnt(); ++sl)
2346  {
2347  balance += (wc_.wc_sl[sl] + wc_.ice_sl[sl]) * sc_.h_sl[sl];
2348  }
2349  balance += ( - m_wc.accumulated_irrigation_event_executed
2350  - wc_.accumulated_irrigation_automatic
2351  - wc_.accumulated_irrigation_ggcmi
2352  - wc_.accumulated_irrigation_reservoir_withdrawal
2353  - wc_.accumulated_precipitation
2354  - wc_.accumulated_groundwater_access
2355  + wc_.accumulated_percolation
2356  + wc_.accumulated_runoff
2357  + wc_.accumulated_transpiration_sl.sum()
2358  + wc_.accumulated_interceptionevaporation
2359  + wc_.accumulated_soilevaporation
2360  + wc_.accumulated_surfacewaterevaporation);
2361 
2362  if ( _balance)
2363  {
2364  double const balance_delta( std::abs( *_balance - balance));
2365  if ( balance_delta > cbm::DIFFMAX)
2366  {
2367  KLOGWARN( "Water leakage: difference is ", balance - *_balance);
2368  }
2369  }
2370 
2371  for ( size_t sl = 0; sl < m_soillayers->soil_layer_cnt(); ++sl)
2372  {
2373  if ( cbm::flt_less( wc_.wc_sl[sl], 0.0))
2374  {
2375  KLOGWARN( "Negative water content of: ", wc_.wc_sl[sl], " in layer: ", sl, ". Water content set to zero.");
2376  wc_.wc_sl[sl] = 0.0;
2377  }
2378  if ( cbm::flt_less( wc_.ice_sl[sl], 0.0))
2379  {
2380  KLOGWARN( "Negative ice content of: ", wc_.ice_sl[sl], " in layer: ", sl, ". Ice content set to zero.");
2381  wc_.ice_sl[sl] = 0.0;
2382  }
2383  }
2384 
2385  return balance;
2386 }
double get_leaf_water()
Collects leaf water from all canopy layers.
Definition: watercycle-dndc.cpp:1119

◆ CalcInterception()

void ldndc::WatercycleDNDC::CalcInterception ( )
private

Calculates water quantity that is retained on leaf and stem bark surfaces.

  • Rainfall and interception are assumed to happen at the end of the timestep and evaporation is realised at once at the start of the timestep.
  • The model assumes a homogeneous horizontal distribution of LAI although a non-linear dependency to crown cover (relative foliage clumping) has been reported (e.g. Teklehaimanot et al. 1991).
  • The default water-interception for foliage almost equal to the largest species specific value

◆ CalcIrrigation()

void ldndc::WatercycleDNDC::CalcIrrigation ( unsigned int  _i)
private

apportion daily irrigation to subdaily irrigation

Automatic irrigation to prevent water stress

GGCMI style irrigation

  • fill up the water content of each soil layer to field capacity at the start of each day
  • water supplied just injected into soil layer
  • no interception, no run off, no surface-water
  • only irrigate if a crop is present

Irrigation due to flooding

irrigation triggered by flooding management

Irrigation due to explicit irrigation event

629 {
630  //reset irrigation
631  m_wc.irrigation = 0.0;
632 
636  if ( cbm::flt_in_range_lu(0.0, m_cfg.automaticirrigation, 1.0))
637  {
638  for ( size_t l = 0; l < m_soillayers->soil_layer_cnt(); ++l)
639  {
640  // trigger irrigation events as soon as drought stress appears
641  double const wc_target( sc_.wcmin_sl[l] + m_cfg.automaticirrigation * (sc_.wcmax_sl[l] - sc_.wcmin_sl[l]));
642  if ( cbm::flt_less( wc_.wc_sl[l], wc_target))
643  {
644  // irrigation assumed until target water content
645  double const irrigate_layer( (wc_target - wc_.wc_sl[l]) * sc_.h_sl[l]);
646  m_wc.irrigation += irrigate_layer;
647  wc_.accumulated_irrigation_automatic += irrigate_layer;
648  }
649  }
650  }
651 
652  if ( cbm::flt_in_range_lu( 0.0, saturation_level, 1.0))
653  {
654  double wc_sum( 0.0);
655  double wcmax_sum( 0.0);
656  double wcmin_sum( 0.0);
657  for ( size_t l = 0; l < m_soillayers->soil_layer_cnt(); ++l)
658  {
659  wc_sum += wc_.wc_sl[l] * sc_.h_sl[l];
660  wcmax_sum += sc_.wcmax_sl[l] * sc_.h_sl[l];
661  wcmin_sum += sc_.wcmin_sl[l] * sc_.h_sl[l];
662 
663  if ( cbm::flt_greater_equal( sc_.depth_sl[l], soil_depth_flooding))
664  {
665  break;
666  }
667  }
668 
669  // trigger irrigation events as soon as drought stress appears
670  double const wc_target( wcmin_sum + saturation_level * (wcmax_sum - wcmin_sum));
671  if ( cbm::flt_less( wc_sum, wc_target))
672  {
673  m_wc.irrigation += irrigation_height;
674  wc_.accumulated_irrigation_automatic += irrigation_height;
675  }
676  }
677 
685  if ( m_cfg.ggcmi_irrigation)
686  {
687  if( (lclock()->subday() == 1) && (_i == 0))
688  {
689  if( m_veg->size() > 0 ) //check crop is present
690  {
691  double water_supply( 0.0);
692  for ( size_t l = 0; l < m_soillayers->soil_layer_cnt(); ++l)
693  {
694  if ( cbm::flt_greater_zero( m_veg->mfrt_sl( l))) //only irrigate soil layers that contain roots
695  {
696  if( cbm::flt_less( wc_.wc_sl[l], sc_.wcmax_sl[l]) &&
697  cbm::flt_equal_zero( wc_.ice_sl[l])) //only add water if no ice is present
698  {
699  water_supply += (sc_.wcmax_sl[l] - wc_.wc_sl[l]) * sc_.h_sl[l]; //amount of water added (m)
700  wc_.wc_sl[l] = sc_.wcmax_sl[l];
701  }
702  }
703  }
704  wc_.accumulated_irrigation_ggcmi += water_supply;
705  }
706  }
707  }
708 
712  if ( cbm::is_valid( water_table_flooding))
713  {
714  /* Dynamic flooding */
715  if ( cbm::is_valid( irrigation_height))
716  {
717  bool irrigate( false);
718 
719  /* Irrigate after surface water table drop */
720  if ( cbm::flt_greater_equal_zero( water_table_flooding))
721  {
722  if ( cbm::flt_greater( water_table_flooding, wc_.surface_water))
723  {
724  irrigate = true;
725  }
726  }
727  else
728  {
729  if ( !cbm::flt_greater_zero( wc_.surface_water))
730  {
731  for ( size_t sl = 0; sl < m_soillayers->soil_layer_cnt(); ++sl)
732  {
733  if ( cbm::flt_greater_equal( sc_.depth_sl[sl], -water_table_flooding))
734  {
735  //check if water content below AWD_DEPTH is saturated
736  if ( cbm::flt_less( wc_.wc_sl[sl], 0.9 * sc_.poro_sl[sl]))
737  {
738  irrigate = true;
739  }
740  break;
741  }
742  }
743  }
744  }
745  // trigger AWD irrigation event
746  if ( irrigate)
747  {
748  double water_supply( cbm::bound_min( 0.0, irrigation_height - wc_.surface_water));
749  for ( size_t sl = 0; sl < m_soillayers->soil_layer_cnt(); ++sl)
750  {
751  // set soil fully water saturated
752  if ( cbm::flt_greater( sc_.poro_sl[sl], wc_.wc_sl[sl]))
753  {
754  water_supply += ((sc_.poro_sl[sl] - wc_.wc_sl[sl]) * sc_.h_sl[sl]);
755  }
756  }
757 
758  //remove rainfall (less irrigation water is supplied if it if raining)
759  water_supply = cbm::bound_min( 0.0, water_supply - m_mc.rainfall);
760 
761  if ( !unlimited_water)
762  {
763  if ( cbm::flt_greater( wc_.irrigation_reservoir, water_supply))
764  {
765  wc_.irrigation_reservoir -= water_supply;
766  }
767  else
768  {
769  water_supply = wc_.irrigation_reservoir;
770  wc_.irrigation_reservoir = 0.0;
771  }
772  wc_.accumulated_irrigation_reservoir_withdrawal += water_supply;
773  }
774  else
775  {
776  wc_.accumulated_irrigation_automatic += water_supply;
777  }
778  m_wc.irrigation += water_supply;
779  }
780  }
781  /* Static flooding */
782  else
783  {
784  if ( !cbm::flt_greater_zero( water_table_flooding))
785  {
786  double water_supply( 0.0);
787  for ( size_t sl = 0; sl < m_soillayers->soil_layer_cnt(); ++sl)
788  {
789  if ( cbm::flt_greater( -water_table_flooding, sc_.depth_sl[sl]) &&
790  cbm::flt_greater( sc_.wcmax_sl[sl], wc_.wc_sl[sl]))
791  {
792  water_supply += (sc_.wcmax_sl[sl] - wc_.wc_sl[sl]) * sc_.h_sl[sl];
793  }
794  else
795  {
796  if ( cbm::flt_greater( sc_.poro_sl[sl], wc_.wc_sl[sl]))
797  {
798  water_supply += (sc_.poro_sl[sl] - wc_.wc_sl[sl]) * sc_.h_sl[sl];
799  }
800  }
801  }
802 
803  //remove rainfall (less irrigation water is supplied if it if raining)
804  water_supply = cbm::bound_min( 0.0, water_supply - m_mc.rainfall);
805 
806  /* Surface water will be actively drained */
807  if ( cbm::flt_greater( wc_.surface_water, water_supply))
808  {
809  wc_.accumulated_runoff += wc_.surface_water - water_supply;
810  wc_.surface_water = water_supply;
811  }
812 
813  if ( !unlimited_water)
814  {
815  if ( cbm::flt_greater( wc_.irrigation_reservoir, water_supply))
816  {
817  wc_.irrigation_reservoir -= water_supply;
818  }
819  else
820  {
821  water_supply = wc_.irrigation_reservoir;
822  wc_.irrigation_reservoir = 0.0;
823  }
824  wc_.accumulated_irrigation_reservoir_withdrawal += water_supply;
825  }
826  else
827  {
828  wc_.accumulated_irrigation_automatic += water_supply;
829  }
830  m_wc.irrigation += water_supply;
831  }
835  else if ( cbm::flt_greater( water_table_flooding, wc_.surface_water))
836  {
837  //adjust surface and soil water in case of flooding event
838  //water required to fill up surface water
839  double water_supply( water_table_flooding - wc_.surface_water);
840 
841  //add water required to fill top x layers up to saturation
842  unsigned long no_layers(3);
843  if( no_layers > m_soillayers->soil_layer_cnt())
844  {
845  no_layers = m_soillayers->soil_layer_cnt();
846  }
847 
848  for ( size_t sl = 0; sl < no_layers; ++sl)
849  {
850  water_supply += ((sc_.poro_sl[sl] - wc_.wc_sl[sl]) * sc_.h_sl[sl]);
851  }
852 
853  //remove rainfall (less irrigation water is supplied if it if raining)
854  water_supply = cbm::bound_min( 0.0, water_supply - m_mc.rainfall);
855 
856  if ( !unlimited_water)
857  {
858  if ( cbm::flt_greater( wc_.irrigation_reservoir, water_supply))
859  {
860  wc_.irrigation_reservoir -= water_supply;
861  }
862  else
863  {
864  water_supply = wc_.irrigation_reservoir;
865  wc_.irrigation_reservoir = 0.0;
866  }
867  wc_.accumulated_irrigation_reservoir_withdrawal += water_supply;
868  }
869  else
870  {
871  wc_.accumulated_irrigation_automatic += water_supply;
872  }
873  m_wc.irrigation += water_supply;
874  }
875  }
876  }
877 
881  double const irrigation_scheduled( cbm::bound_min( 0.0, wc_.accumulated_irrigation - m_wc.accumulated_irrigation_event_executed));
882 
883  if ( cbm::flt_greater( irrigation_scheduled, 24.0 * rainfall_intensity()))
884  {
885  m_wc.irrigation += irrigation_scheduled / 24.0;
886  m_wc.accumulated_irrigation_event_executed += irrigation_scheduled / 24.0;
887  }
888  else if ( cbm::flt_greater( irrigation_scheduled, (double)hours_per_time_step() * rainfall_intensity()))
889  {
890  m_wc.irrigation += (double)hours_per_time_step() * rainfall_intensity();
891  m_wc.accumulated_irrigation_event_executed += (double)hours_per_time_step() * rainfall_intensity();
892  }
893  else
894  {
895  m_wc.irrigation += irrigation_scheduled;
896  m_wc.accumulated_irrigation_event_executed += irrigation_scheduled;
897  }
898 }
double rainfall_intensity()
Definition: watercycle-dndc.cpp:128

◆ CalcPotEvapoTranspiration()

lerr_t ldndc::WatercycleDNDC::CalcPotEvapoTranspiration ( )
private

Potential evaporation.


there are two methods of calculating potential evaporation (choose via macro POTENTIAL_EVAPORATION above)

  • [0] Procedure according to Thornthwaite 1948 with modifications by Camargo et al. 1999 and Peireira and Pruitt 2004 (implemented from Pereira and Pruitt 2004) to better account for dry environments and daylength.
    NOTE:
    • monthly temperatures are assumed to be equal to daily average temperature of the middle of the month, calculated from continous equations equal to those used in the weather generator.
    • the model uses always daily average temperature as input even if it is run in sub-daily mode
    • the original PnET-N-DNDC code which contains modification that could not be found in the literature has been outcommented.
  • [1] uses the Priestley Taylor equation (Priestly and Taylor 1972) to calculate daily and hourly potential evapotranspiration (implemented from internet) vps calculation according to Allen et al. 1998, cit. in Cai et al. 2007

References ldndc::thornthwaite(), and ldndc::thornthwaite_heat_index().

1034 {
1035  if ( m_cfg.evapotranspiration_method == "thornthwaite")
1036  {
1037  if ( lclock()->is_position( TMODE_PRE_YEARLY))
1038  {
1040  lclock()->days_in_year(),
1041  m_climate->annual_temperature_average(),
1042  m_climate->annual_temperature_amplitude());
1043  }
1044 
1045  double const daylength( ldndc::meteo::daylength( m_setup->latitude(),
1046  lclock()->yearday()));
1047 
1048  hr_pot_evapotrans = m_param->WCDNDC_INCREASE_POT_EVAPOTRANS() * nhr / 24.0
1050  mc_.nd_airtemperature,
1051  daylength,
1053  }
1054  else if ( (m_cfg.evapotranspiration_method == "penman") ||
1055  (m_cfg.evapotranspiration_method == "priestleytaylor"))
1056  {
1057  /* clock */
1058  cbm::sclock_t const & clk( this->lclock_ref());
1059 
1060  /* leaf area index */
1061  double lai( 0.0);
1062  for( PlantIterator vt = m_veg->begin(); vt != m_veg->end(); ++vt)
1063  {
1064  lai += (*vt)->lai();
1065  }
1066 
1067  /* vapour pressure [10^3:Pa] */
1068  double vps( 0.0);
1069  ldndc::meteo::vps( mc_.nd_airtemperature, &vps);
1070  double vp( vps - m_climate->vpd_day( clk));
1071 
1072  if( m_cfg.evapotranspiration_method == "priestleytaylor")
1073  {
1074  hr_pot_evapotrans = m_param->WCDNDC_INCREASE_POT_EVAPOTRANS() * nhr / 24.0
1075  * ldndc::priestleytaylor( clk.yearday(),
1076  clk.days_in_year(),
1077  mc_.albedo,
1078  m_setup->latitude(),
1079  mc_.nd_airtemperature,
1080  mc_.nd_shortwaveradiation_in,
1081  vp,
1082  m_param->PT_ALPHA());
1083  }
1084  else if( m_cfg.evapotranspiration_method == "penman")
1085  {
1086  ldndc::surface_type surface( cbm::flt_greater_zero( lai) ? short_grass : bare_soil);
1087 
1088  hr_pot_evapotrans = m_param->WCDNDC_INCREASE_POT_EVAPOTRANS() * nhr / 24.0
1089  * ldndc::penman( surface,
1090  clk.yearday(),
1091  clk.days_in_year(),
1092  mc_.albedo,
1093  m_setup->latitude(),
1094  mc_.nd_shortwaveradiation_in * cbm::SEC_IN_DAY,
1095  mc_.nd_airtemperature,
1096  mc_.nd_windspeed,
1097  vp);
1098  }
1099  }
1100  else
1101  {
1102  KLOGERROR("[BUG] huh :o how did you get here? ",
1103  "tell the maintainers refering to this error message");
1104  return LDNDC_ERR_FAIL;
1105  }
1106 
1107 
1108  wc_.accumulated_potentialevapotranspiration += hr_pot_evapotrans;
1109 
1110  return LDNDC_ERR_OK;
1111 }
double LDNDC_API thornthwaite_heat_index(double, size_t, double, double)
Thornthwaite heat index.
Definition: ld_thornthwaite.cpp:98
double LDNDC_API thornthwaite(double, double, double)
Potential evapotranspiration after .
Definition: ld_thornthwaite.cpp:41
double thornthwaite_heat_index
heat index for potential evaporation using approach after Thornthwaite
Definition: watercycle-dndc.h:215
Here is the call graph for this function:

◆ CalcSnowEvaporation()

void ldndc::WatercycleDNDC::CalcSnowEvaporation ( )
private
Parameters
[in]None
[out]None
Returns
None
1718 {
1719  //Average limit of snowEvaporation is 0.00013m day-1 (Granger and Male 1978)
1720  double hr_potESnow( cbm::bound(0.0, hr_pot_evapotrans, 0.00013 * nhr/24.0));
1721 
1722  if ( cbm::flt_greater_zero( wc_.surface_ice) &&
1723  cbm::flt_greater_zero( hr_potESnow))
1724  {
1725  //If there is a snowpack and there is a potential to evaporate
1726  if ( wc_.surface_ice > hr_potESnow)
1727  {
1728  //Partial evaporation from the snow
1729  hr_pot_evapotrans = cbm::bound_min( 0.0, hr_pot_evapotrans - hr_potESnow);
1730  wc_.accumulated_surfacewaterevaporation += hr_potESnow;
1731  wc_.surface_ice -= hr_potESnow;
1732  }
1733  else
1734  {
1735  //Total evaporation of the snowpack
1736  hr_pot_evapotrans = cbm::bound_min( 0.0, hr_pot_evapotrans - wc_.surface_ice);;
1737  wc_.accumulated_surfacewaterevaporation += wc_.surface_ice;
1738  wc_.surface_ice = 0.0;
1739  }
1740  }
1741 }

◆ CalcSoilEvapoPercolation()

void ldndc::WatercycleDNDC::CalcSoilEvapoPercolation ( )
private
Parameters
[in]None
[out]None
Returns
None
1861 {
1862  /* Reset water fluxes */
1863  for ( size_t sl = 0; sl < m_soillayers->soil_layer_cnt(); ++sl)
1864  {
1865  m_wc.percolation_sl[sl] = 0.0;
1866  }
1867 
1868  /* Fill groundwater layer with water */
1869  for ( int sl = m_soillayers->soil_layer_cnt()-1; sl >= 0; --sl)
1870  {
1871  if ( cbm::flt_greater_equal( sc_.depth_sl[sl], ground_water_table))
1872  {
1873  /* ensure that ice volume is less than porosity */
1874  double const ice_vol( wc_.ice_sl[sl] / cbm::DICE);
1875  if ( cbm::flt_greater( sc_.poro_sl[sl], ice_vol))
1876  {
1877  //air filled porosity is filled with groundwater
1878  double const gw_access( cbm::bound_min( 0.0,
1879  (sc_.poro_sl[sl] - ice_vol - wc_.wc_sl[sl]) * sc_.h_sl[sl]));
1880  wc_.wc_sl[sl] += gw_access / sc_.h_sl[sl];
1881  wc_.accumulated_groundwater_access += gw_access;
1882  }
1883  }
1884  else
1885  {
1886  break;
1887  }
1888  }
1889 
1890  for ( size_t sl = 0; sl < m_soillayers->soil_layer_cnt(); ++sl)
1891  {
1892  if ( sl == 0)
1893  {
1894  wc_.accumulated_infiltration += wc_.surface_water;
1895  wc_.wc_sl[0] += wc_.surface_water / sc_.h_sl[0];
1896  wc_.surface_water = 0.0;
1897  }
1898  else
1899  {
1900  wc_.wc_sl[sl] += m_wc.percolation_sl[sl-1] / sc_.h_sl[sl];
1901  }
1902 
1903  if ( cbm::flt_greater( sc_.depth_sl[sl], ground_water_table))
1904  {
1905  //set constant flux for all ground water layers depending on last non-groundwater layer
1906  if ( sl > 0)
1907  {
1908  m_wc.percolation_sl[sl] = m_wc.percolation_sl[sl-1];
1909  }
1910 
1911  //in case of groundwater until soil surface first outflux is estimated by saturated water flow
1912  else
1913  {
1914  m_wc.percolation_sl[sl] = WaterFlowSaturated( sl, get_impedance_factor( sl));
1915  }
1916  }
1917  else if ( sl + 1 == m_soillayers->soil_layer_cnt())
1918  {
1919  m_wc.percolation_sl[sl] = 0.0;
1920  if ( cbm::flt_greater_zero( sc_.sks_sl[sl]))
1921  {
1922  if ( cbm::flt_greater( wc_.wc_sl[sl], sc_.poro_sl[sl]) &&
1923  cbm::flt_greater( wc_.wc_sl[sl], sc_.wcmax_sl[sl])) //security, should be always true if first condition is met
1924  {
1925  //maximum allowed flow until field capacity
1926  double const max_flow( (wc_.wc_sl[sl] - sc_.wcmax_sl[sl]) * sc_.h_sl[sl]);
1927  m_wc.percolation_sl[sl] = cbm::bound_max( WaterFlowSaturated( sl, get_impedance_factor( sl)),
1928  max_flow);
1929  }
1930 
1931  //water flux above field capacity
1932  else if ( cbm::flt_greater_equal( wc_.wc_sl[sl] + wc_.ice_sl[sl], sc_.wcmax_sl[sl]))
1933  {
1934  m_wc.percolation_sl[sl] = WaterFlowAboveFieldCapacity( sl, get_impedance_factor( sl));
1935  }
1936 
1937  //water flux below field capacity and above wilting point
1938  else if ( cbm::flt_greater_zero( m_wc.percolation_sl[sl-1])
1939  && cbm::flt_greater( wc_.wc_sl[sl], sc_.wcmin_sl[sl]))
1940  {
1941  m_wc.percolation_sl[sl] = m_param->FPERCOL() * m_wc.percolation_sl[sl-1];
1942  }
1943 
1944  //bound water flux by defined maximal percolation rate (e.g., during flooding events)
1945  m_wc.percolation_sl[sl] = cbm::bound_max( m_wc.percolation_sl[sl], max_percolation);
1946  }
1947  }
1948 
1949  //infiltrating water in current time step is exceeding available pore space of last time step
1950  //second condition: security, should be always true if first condition is met
1951  else if ( cbm::flt_greater( wc_.wc_sl[sl], sc_.poro_sl[sl]) &&
1952  cbm::flt_greater( wc_.wc_sl[sl], sc_.wcmax_sl[sl]))
1953  {
1954  //maximum allowed flow until field capacity
1955  double const max_flow( (wc_.wc_sl[sl] - sc_.wcmax_sl[sl]) * sc_.h_sl[sl]);
1956  m_wc.percolation_sl[sl] = cbm::bound_max( WaterFlowSaturated( sl, get_impedance_factor( sl)),
1957  max_flow);
1958  }
1959  else if ( cbm::flt_greater_equal( wc_.wc_sl[sl] + wc_.ice_sl[sl], sc_.wcmax_sl[sl]))
1960  {
1961  m_wc.percolation_sl[sl] = WaterFlowAboveFieldCapacity( sl, get_impedance_factor( sl));
1962  }
1963  else if ( cbm::flt_greater( wc_.wc_sl[sl], sc_.wcmin_sl[sl]))
1964  {
1965  m_wc.percolation_sl[sl] = WaterFlowCapillaryRise( sl, get_impedance_factor( sl));
1966  }
1967  else
1968  {
1969  m_wc.percolation_sl[sl] = 0.0;
1970  }
1971 
1972 
1973  // New water content must be greater equal wilting point
1974  if ( cbm::flt_less( (wc_.wc_sl[sl] + wc_.ice_sl[sl]) * sc_.h_sl[sl] - m_wc.percolation_sl[sl],
1975  sc_.wcmin_sl[sl] * sc_.h_sl[sl]) &&
1976  cbm::flt_greater_zero( m_wc.percolation_sl[sl]))
1977  {
1978  m_wc.percolation_sl[sl] = cbm::bound( 0.0,
1979  (wc_.wc_sl[sl] + wc_.ice_sl[sl] - sc_.wcmin_sl[sl]) * sc_.h_sl[sl],
1980  m_wc.percolation_sl[sl]);
1981  }
1982 
1983  // Update of the current soil layer water content
1984  wc_.wc_sl[sl] -= m_wc.percolation_sl[sl] / sc_.h_sl[sl];
1985 
1986  SoilWaterEvaporation( sl);
1987  }
1988 
1989  /* Correct water content and percolation if water content is above porosity
1990  * If the layer below cannot take up all of the water assigned for percolation,
1991  * so if the air filled pore space is not sufficient,
1992  * the water remains in the upper layer.
1993  */
1994  for ( size_t sl = m_soillayers->soil_layer_cnt()-1; sl > 0; sl--)
1995  {
1996  double const ice_vol( wc_.ice_sl[sl] / cbm::DICE);
1997  if ( cbm::flt_greater( wc_.wc_sl[sl] + ice_vol,
1998  sc_.poro_sl[sl]))
1999  {
2000  double delta_wc( wc_.wc_sl[sl] + ice_vol - sc_.poro_sl[sl]);
2001  if ( cbm::flt_greater_equal( ice_vol, sc_.poro_sl[sl]))
2002  {
2003  delta_wc = wc_.wc_sl[sl];
2004  wc_.wc_sl[sl] = 0.0;
2005  }
2006  else
2007  {
2008  wc_.wc_sl[sl] = sc_.poro_sl[sl] - ice_vol;
2009  }
2010  m_wc.percolation_sl[sl-1] -= delta_wc * sc_.h_sl[sl];
2011  wc_.wc_sl[sl-1] += delta_wc * sc_.h_sl[sl] / sc_.h_sl[sl-1];
2012  }
2013  }
2014 
2015  double const ice_vol( wc_.ice_sl[0] / cbm::DICE);
2016  if ( cbm::flt_greater( wc_.wc_sl[0] + ice_vol,
2017  sc_.poro_sl[0]))
2018  {
2019 
2020  double delta_wc( wc_.wc_sl[0] + ice_vol - sc_.poro_sl[0]);
2021  if ( cbm::flt_greater_equal( ice_vol, sc_.poro_sl[0]))
2022  {
2023  delta_wc = wc_.wc_sl[0];
2024  wc_.wc_sl[0] = 0.0;
2025  }
2026  else
2027  {
2028  wc_.wc_sl[0] = sc_.poro_sl[0] - ice_vol;
2029  }
2030  wc_.accumulated_infiltration -= delta_wc * sc_.h_sl[0];
2031  wc_.surface_water += delta_wc * sc_.h_sl[0];
2032  }
2033 
2034 
2035  CalcSurfaceFlux();
2036 
2037  wc_.accumulated_waterflux_sl += m_wc.percolation_sl;
2038  wc_.accumulated_percolation += m_wc.percolation_sl[ m_soillayers->soil_layer_cnt()-1];
2039 }
double WaterFlowSaturated(size_t, double const &)
Definition: watercycle-dndc.cpp:2131
double get_impedance_factor(size_t)
Reduces water fluxes out of a layer if ice lenses have formed.
Definition: watercycle-dndc.cpp:2207
void SoilWaterEvaporation(size_t)
Definition: watercycle-dndc.cpp:1783
double WaterFlowAboveFieldCapacity(size_t, double const &)
Definition: watercycle-dndc.cpp:2052
void CalcSurfaceFlux()
Definition: watercycle-dndc.cpp:2256
double WaterFlowCapillaryRise(size_t, double const &)
Similar to WaterFlowBelowFieldCapacity(...) but restricts water flow by water availability from soil ...
Definition: watercycle-dndc.cpp:2101

◆ CalcSurfaceFlux()

void ldndc::WatercycleDNDC::CalcSurfaceFlux ( )
private
Parameters
[in]None
[out]None
Returns
None
2257 {
2258  if ( cbm::flt_greater_zero( bund_height))
2259  {
2260  if ( cbm::flt_greater( wc_.surface_water, bund_height))
2261  {
2262  wc_.accumulated_runoff += (wc_.surface_water - bund_height);
2263  wc_.surface_water = bund_height;
2264  }
2265  }
2266  else
2267  {
2268  /* runoff fraction per time step equals RO fraction per hour * length of a time step */
2269  double const runoff_fraction( m_param->FRUNOFF() * get_time_step_duration());
2270 
2271  // if frunoff_ts < 1
2272  if ( cbm::flt_less( runoff_fraction, 1.0))
2273  {
2274  double const runoff( runoff_fraction * wc_.surface_water);
2275  wc_.surface_water -= runoff;
2276  wc_.accumulated_runoff += runoff;
2277  }
2278  else
2279  {
2280  wc_.accumulated_runoff += wc_.surface_water;
2281  wc_.surface_water = 0.0;
2282  }
2283  }
2284 }
double get_time_step_duration()
Time fraction with regard to daily rates.
Definition: watercycle-dndc.cpp:2331

◆ CalcSurfaceWaterEvaporation()

void ldndc::WatercycleDNDC::CalcSurfaceWaterEvaporation ( )
private
Parameters
[in]None
[out]None
Returns
None
1687 {
1688  if ( cbm::flt_greater_zero( wc_.surface_water) &&
1689  cbm::flt_greater_zero( hr_pot_evapotrans))
1690  {
1691  if ( hr_pot_evapotrans > wc_.surface_water)
1692  {
1693  wc_.accumulated_surfacewaterevaporation += wc_.surface_water;
1694  hr_pot_evapotrans -= wc_.surface_water;
1695  wc_.surface_water = 0.0;
1696  }
1697  else
1698  {
1699  wc_.surface_water -= hr_pot_evapotrans;
1700  wc_.accumulated_surfacewaterevaporation += hr_pot_evapotrans;
1701  hr_pot_evapotrans = 0.0;
1702  }
1703  }
1704 }

◆ CalcTranspiration()

lerr_t ldndc::WatercycleDNDC::CalcTranspiration ( )
private
Parameters
[in]None
[out]None
Returns
None

◆ CalcTranspirationCouvreur()

lerr_t ldndc::WatercycleDNDC::CalcTranspirationCouvreur ( double const &  hr_potTransinm)
private
Parameters
[in]None
[out]None
Returns
None
1546 {
1547  // hourly potential transpiration
1548  double const hr_potTrans( hr_potTransinm * cbm::CM_IN_M);
1549  // hourly transpiration
1550  double hr_trans( 0.0);
1551 
1552  // Calculate the root water uptake and hence the transpiration for every plant individually
1553  for( PlantIterator vt = m_veg->begin(); vt != m_veg->end(); ++vt)
1554  {
1555  // split up the potential transpiration equally to the various plants
1556  // frt mass of the current species
1557  double const mfrt_species( (*vt)->mFrt);
1558  // total frt mass
1559  double const mfrt_sum( m_veg->dw_frt());
1560  double const hr_potTransspecies = hr_potTrans * mfrt_species/mfrt_sum; // in cm
1561 
1562  // If some soil layers are frozen and contain only ice, no fluid water is present and the water potential diverges.
1563  // The uptake from these layers is prevented by considering only roots in layers with more water than ice.
1564  // In this case the root distribution needs to be rescaled (otherwise the non-contributing layers would effectively contribute a potential = 0).
1565  double fFrt_unfrozen( 1.0);
1566 
1567  /* TODO: include icetowatercrit as proper parameter */
1568  double icetowatercrit( 0.1);
1569  double effsoilwatpot( 0.0);
1570  for( size_t sl = 0; sl < m_soillayers->soil_layer_cnt(); ++sl)
1571  {
1572  // fine root conditions to prevent transpiration without uptake organs, wateruptake from frozen ground
1573  if( cbm::flt_greater_zero( (*vt)->fFrt_sl[sl] * mfrt_species))
1574  {
1575  if(cbm::flt_less( wc_.ice_sl[sl]/wc_.wc_sl[sl], icetowatercrit))
1576  {
1577  // overall water potential in this layer
1578  double const watpotl( Soillayerwaterhead( sl)); // negative
1579  effsoilwatpot += watpotl * (*vt)->fFrt_sl[sl]; // negative
1580  }
1581  else
1582  {
1583  fFrt_unfrozen -= (*vt)->fFrt_sl[sl];
1584  }
1585  }
1586  else
1587  {
1588  // roots are not wireless ;-)
1589  break;
1590  }
1591  }
1592  // normalize the root distribution in the potential, if some soil is frozen
1593  effsoilwatpot = effsoilwatpot / fFrt_unfrozen;
1594 
1595  // hydraulic conductivities of plant system
1596  double const Krs(vt->KRSINIT() * mfrt_species / vt->FRTMASSINIT() * nhr); // cm(water)/cm(from pressure)/timestep
1597  double const Kcomp(vt->KCOMPINIT() * mfrt_species / vt->FRTMASSINIT() * nhr); // cm(water)/cm(from pressure)/timestep
1598 
1599  // water potential in the leafs, depending on the potential transpiration
1600  double const leafwatpot( cbm::bound_min(vt->HLEAFCRIT(), effsoilwatpot - (hr_potTransspecies / Krs))); // cm
1601 
1602  if( cbm::flt_greater_zero( leafwatpot))
1603  {
1604  KLOGERROR( "leafwatpot is positive");
1605  return LDNDC_ERR_FAIL;
1606  }
1607  if( !cbm::flt_greater_zero( effsoilwatpot - leafwatpot))
1608  {
1609  KLOGERROR( "effsoilwatpot - leafwatpot is smaller 0: ", effsoilwatpot - leafwatpot, ", effsoilwatpot = ", effsoilwatpot, ", leafwatpot = ", leafwatpot, "\n-> Hourly transpiration ", hr_trans, " is negative!\nPlant dies :-( Try with a smaller KRSINIT or different KCOMPINIT or different EXP_ROOT_DISTRIBUTION.\nOr wcmin is to close to the residual water content.. increase it.");
1610  return LDNDC_ERR_FAIL;
1611  }
1612 
1613  double const effuptake( Krs * (effsoilwatpot - leafwatpot)); // cm/timestep
1614  double uptake_tot( 0.0);
1615  double uptakecomp_tot( 0.0);
1616 // double uptakecompabs_tot( 0.0);
1617 
1618  for( size_t sl = 0; sl < m_soillayers->soil_layer_cnt(); ++sl)
1619  {
1620  // fine root condition to prevent transpiration without uptake organs
1621  if( cbm::flt_greater_zero( (*vt)->fFrt_sl[sl] * mfrt_species))
1622  {
1623  if(cbm::flt_less( wc_.ice_sl[sl]/wc_.wc_sl[sl], icetowatercrit))
1624  {
1625  double const watpotl( Soillayerwaterhead( sl));
1626  double const compuptake( Kcomp * (watpotl - effsoilwatpot));
1627  double uptake_layer( (effuptake + compuptake) * (*vt)->fFrt_sl[sl]); // absolute value in cm
1628 
1629  wc_.accumulated_transpiration_sl[sl] += uptake_layer * cbm::M_IN_CM;
1630  uptake_tot += uptake_layer; // absolute value in cm
1631  uptakecomp_tot += compuptake * (*vt)->fFrt_sl[sl]; // absolute value in cm
1632 // uptakecompabs_tot += fabs(compuptake * (*vt)->fFrt_sl[sl]); // absolute value in cm
1633 
1634  wc_.wc_sl[sl] -= uptake_layer * cbm::M_IN_CM /sc_.h_sl[sl]; // fraction of water in this layer, in m
1635 
1636  if( !cbm::flt_greater_zero( wc_.wc_sl[sl]))
1637  {
1638  KLOGERROR( "In soil layer ", sl, " the water content is negative: ", wc_.wc_sl[sl]);
1639  return LDNDC_ERR_FAIL;
1640  }
1641  }
1642  }
1643  else
1644  {
1645  // roots are not wireless ;-)
1646  break;
1647  }
1648  }
1649  hr_trans += uptake_tot * cbm::M_IN_CM; // absolute value in m for all species
1650 
1651 
1652  if( cbm::flt_greater_zero( fabs(uptakecomp_tot))){
1653  KLOGWARN( "Compensatory water uptake ", uptakecomp_tot, " > 0.");
1654  }
1655  if( cbm::flt_greater( uptake_tot, hr_potTransspecies, 0.0000000001))
1656  {
1657  KLOGERROR( "Total water uptake ", uptake_tot, " larger than potential transpiration ", hr_potTransspecies);
1658  }
1659  if(cbm::flt_equal_eps(fFrt_unfrozen, 1.0, 0.0000000001) && !cbm::flt_equal_eps( uptake_tot, hr_potTransspecies, 0.0000000001) && !cbm::flt_equal_eps( leafwatpot, vt->HLEAFCRIT(), 0.0000000001))
1660  {
1661  KLOGERROR( "T ", uptake_tot, "cm < Tpot ", hr_potTransspecies, "cm even though leafwatpot ", leafwatpot, " > HLEAFCRIT", vt->HLEAFCRIT());
1662  }
1663  }
1664  hr_pot_evapotrans -= hr_trans;
1665 
1666  return LDNDC_ERR_OK;
1667 }

◆ event_flood()

lerr_t ldndc::WatercycleDNDC::event_flood ( )
private

sets hydrologic conditions during flooding events, e.g.,

  • surface water table
  • bund height
578 {
579  lerr_t rc = m_eventflood.solve();
580  if ( rc != LDNDC_ERR_OK)
581  {
582  KLOGERROR("Irrigation event not successful!");
583  return rc;
584  }
585 
586  water_table_flooding = m_eventflood.get_water_table();
587 
588  bund_height = m_eventflood.get_bund_height();
589  if ( cbm::flt_greater_zero( water_table_flooding))
590  {
591  bund_height = cbm::bound_min( water_table_flooding, bund_height);
592  }
593 
594  irrigation_height = m_eventflood.get_irrigation_height();
595 
596  /* max_percolation is gradually decreased after end of flooding event to inital value */
597  double const maximum_percolation = m_eventflood.get_maximum_percolation();
598  if ( cbm::is_valid( maximum_percolation))
599  {
600  if ( cbm::flt_greater_zero( maximum_percolation))
601  {
602  max_percolation = maximum_percolation * nhr / 24.0;
603  }
604  }
605  else
606  {
607  /* time rate for gradual recovery of max_percolation */
608  double const time_rate( get_time_step_duration() * 0.1);
609  max_percolation -= (max_percolation - WaterFlowSaturated( m_soillayers->soil_layer_cnt()-1, 1.0)) * time_rate;
610  }
611 
612  unlimited_water = m_eventflood.have_unlimited_water();
613 
614  saturation_level = m_eventflood.get_saturation_level();
615  soil_depth_flooding = m_eventflood.get_soil_depth();
616 
617  return LDNDC_ERR_OK;
618 }
double WaterFlowSaturated(size_t, double const &)
Definition: watercycle-dndc.cpp:2131
double get_time_step_duration()
Time fraction with regard to daily rates.
Definition: watercycle-dndc.cpp:2331

◆ get_clay_limitation()

double ldndc::WatercycleDNDC::get_clay_limitation ( size_t  _sl,
double  _water_avail,
double  _water_ref 
)
private
Parameters
[in]_slSoil layer
[in]_water_availAvailable water content
[in]_water_refReference water content
[out]None
Returns
Clay limitation
1264 {
1265  // layer specific water availability
1266  // organic fraction [%]
1267  double const orgf( sc_.fcorg_sl[_sl] / cbm::CCORG);
1268  // clay factor "1" [-]
1269  double const clay_f1( pow(10.0, (-sc_.clay_sl[_sl] - m_param->RCLAY())));
1270  // clay factor "2" [-]
1271  double const clay_f2( std::max(0.0, 1.0 + std::min(1.0 - orgf, sc_.clay_sl[_sl])));
1272 
1273  // fraction of max uptake that can be used according to soil conditions [%]
1274  return cbm::bound(0.0, clay_f1 + pow( _water_avail / _water_ref, clay_f2), 1.0);
1275 }

◆ get_leaf_water()

double ldndc::WatercycleDNDC::get_leaf_water ( )
private

Collects leaf water from all canopy layers.

Parameters
[in]None
[out]None
Returns
Leaf water
1120 {
1121  if ( m_veg->size() > 0u)
1122  {
1123  return wc_.wc_fl.sum();
1124  }
1125  return 0.0;
1126 }

◆ rainfall_intensity()

double ldndc::WatercycleDNDC::rainfall_intensity ( )
private

fixed amount of maximum rainfall/irrigation triggered per time step

References ldndc::thornthwaite_heat_index().

129 {
130  if ( m_iokcomm->get_input_class< input_class_climate_t >())
131  {
132  return m_iokcomm->get_input_class< climate::input_class_climate_t >()->station_info()->rainfall_intensity * cbm::M_IN_MM;
133  }
134  else
135  {
136  return ldndc::climate::climate_info_defaults.rainfall_intensity * cbm::M_IN_MM;
137  }
138 }
Here is the call graph for this function:

◆ SoilWaterEvaporation()

void ldndc::WatercycleDNDC::SoilWaterEvaporation ( size_t  _sl)
private
Parameters
[in]_slSoil layer
[out]None
Returns
None
1785 {
1786  //percolation and direct evaporation from the (upper) soil
1787  //if there is snow cover, evaporation from soil will be set to 0, and only sublimation is allowed.
1788  double const orgf( sc_.fcorg_sl[_sl] / cbm::CCORG);
1789  double const clay_fact( 1.0 + m_param->SLOPE_CLAYF() * std::min(1.0 - orgf, sc_.clay_sl[_sl]));
1790  double const wc_min_evaporation( m_param->WCDNDC_EVALIM_FRAC_WCMIN() * sc_.wcmin_sl[_sl]);
1791 
1792  if ( ((sc_.depth_sl[_sl] - sc_.h_sl[_sl]) < m_param->EVALIM()) &&
1793  (wc_.wc_sl[_sl] > wc_min_evaporation) &&
1794  cbm::flt_greater_zero( hr_pot_evapotrans))
1795  {
1796  //limiting factor for soil water infiltration
1797  double limit_wi( cbm::bound_min( 0.0,
1798  (wc_.wc_sl[_sl] - wc_min_evaporation) / sc_.wcmax_sl[_sl]));
1799  limit_wi = cbm::bound_max( pow(limit_wi, clay_fact), 1.0);
1800 
1801  double const hrest( std::min( sc_.h_sl[_sl], m_param->EVALIM() - ( sc_.depth_sl[_sl] - sc_.h_sl[_sl])));
1802 
1803  //soil water evaporation from the upper soil layers due to physical evaporation (not transpiration)
1804  //linear decrease, consistent with variable soil thickness
1805  double const layer_Evapo = cbm::bound(0.0,
1806  hr_pot_evapotrans * hrest / m_param->EVALIM()
1807  * std::max(0.0,
1808  1.0 - std::min((double)m_param->EVALIM(),
1809  sc_.depth_sl[_sl] - ( 0.5 * sc_.h_sl[_sl]))
1810  / m_param->EVALIM())
1811  * limit_wi,
1812  limit_wi * wc_.wc_sl[_sl]*sc_.h_sl[_sl]);
1813 
1814  //update of the current soil layer water content
1815  wc_.wc_sl[_sl] -= (layer_Evapo / sc_.h_sl[_sl]);
1816  wc_.accumulated_soilevaporation += layer_Evapo;
1817  hr_pot_evapotrans = cbm::bound_min( 0.0, hr_pot_evapotrans - layer_Evapo);
1818  }
1819 }

◆ WatercycleDNDC_preferential_flow()

void ldndc::WatercycleDNDC::WatercycleDNDC_preferential_flow ( )
private
Parameters
[in]None
[out]None
Returns
None
2146 {
2147  //BY_PASSF is defined as the fraction of surface water that passes per hour (0.0 by default)
2148  if ( cbm::flt_greater_zero( m_param->BY_PASSF()) &&
2149  cbm::flt_greater_zero( wc_.surface_water))
2150  {
2151 
2152  double water_def_total( 0.0);
2153  for ( size_t sl = 0; sl < m_soillayers->soil_layer_cnt(); ++sl)
2154  {
2155  //water flux that flow through macro pores can maximally store
2156  water_def_total += cbm::bound_min( 0.0, (sc_.wcmax_sl[sl] - wc_.wc_sl[sl] - wc_.ice_sl[sl]) * sc_.h_sl[sl]);
2157  }
2158 
2159  //duration of timestep (hr-1)
2160  double const fhr( get_time_step_duration());
2161 
2162 
2163  //fraction of surface water that is put into bypass flow (m timestep-1)
2164  double const bypass_fraction( cbm::bound_max( m_param->BY_PASSF() * fhr, 0.99));
2165  double const bypass_water( wc_.surface_water * bypass_fraction);
2166  wc_.surface_water -= bypass_water;
2167  wc_.accumulated_infiltration += bypass_water;
2168 
2169  if ( cbm::flt_greater_equal( water_def_total, bypass_water))
2170  {
2171 
2172  for ( size_t sl = 0; sl < m_soillayers->soil_layer_cnt(); ++sl)
2173  {
2174  double const water_def( cbm::bound_min( 0.0, (sc_.wcmax_sl[sl] - wc_.wc_sl[sl] - wc_.ice_sl[sl]) * sc_.h_sl[sl]));
2175  double const water_add( water_def / water_def_total * bypass_water);
2176 
2177  wc_.wc_sl[sl] += water_add / sc_.h_sl[sl];
2178  }
2179  }
2180  else
2181  {
2182  for ( size_t sl = 0; sl < m_soillayers->soil_layer_cnt(); ++sl)
2183  {
2184  double const water_def( cbm::bound_min( 0.0, (sc_.wcmax_sl[sl] - wc_.wc_sl[sl] - wc_.ice_sl[sl]) * sc_.h_sl[sl]));
2185  wc_.wc_sl[sl] += water_def / sc_.h_sl[sl];
2186  }
2187  /* add surplus to percolation out of last soil layer */
2188  wc_.accumulated_percolation += bypass_water - water_def_total;
2189  wc_.accumulated_waterflux_sl[m_soillayers->soil_layer_cnt()-1] += bypass_water - water_def_total;
2190  }
2191  }
2192 }
double get_time_step_duration()
Time fraction with regard to daily rates.
Definition: watercycle-dndc.cpp:2331

◆ WaterFlowAboveFieldCapacity()

double ldndc::WatercycleDNDC::WaterFlowAboveFieldCapacity ( size_t  _sl,
double const &  _fact_impedance 
)
private

factor accounting for different water travelling characteristics in litter and mineral soil

2055 {
2056  double const sks( WaterFlowSaturated( _sl, _fact_impedance));
2057  double const fsl( get_fsl( _sl));
2058  double const fhr( get_time_step_duration());
2059 
2061  double slope(( _sl < m_soillayers->soil_layers_in_litter_cnt()) ? m_param->SLOPE_FF() : m_param->SLOPE_MS());
2062 
2063  //max 0.005 means that no sks values up to 9.88 cm min-1 are allowed !!
2064  double const travelTime( std::max( 0.005, 1.0 - log10( sc_.sks_sl[_sl] * cbm::M_IN_CM * cbm::MIN_IN_DAY * fhr)));
2065  return( cbm::bound_max( cbm::sqr(1.0 - (sc_.wcmax_sl[_sl] / ((wc_.wc_sl[_sl] + wc_.ice_sl[_sl]) * slope)))
2066  * 0.5 * wc_.wc_sl[_sl] * sc_.h_sl[_sl] * fsl * (1.0 - exp(-1.0 / travelTime)) * _fact_impedance,
2067  sks));
2068 }
double WaterFlowSaturated(size_t, double const &)
Definition: watercycle-dndc.cpp:2131
double get_time_step_duration()
Time fraction with regard to daily rates.
Definition: watercycle-dndc.cpp:2331
double get_fsl(size_t)
Returns factor accounting for soil layer depth. Originally, a constant soil layer depth of 0...
Definition: watercycle-dndc.cpp:2228

◆ WaterFlowSaturated()

double ldndc::WatercycleDNDC::WaterFlowSaturated ( size_t  _sl,
double const &  _fact_impedance 
)
private

Returns saturated water flow per time step accounting for impedance

2133 {
2134  double const sks( sc_.sks_sl[_sl] * cbm::M_IN_CM * cbm::MIN_IN_DAY * get_time_step_duration() * _fact_impedance);
2135  return sks;
2136 }
double get_time_step_duration()
Time fraction with regard to daily rates.
Definition: watercycle-dndc.cpp:2331

Member Data Documentation

◆ IMAX_W

const int unsigned ldndc::WatercycleDNDC::IMAX_W = 24
static

number of iteration steps within a day