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 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
 
double rainfall_intensity ()
 
void CalcIrrigation (unsigned int)
 apportion daily irrigation to subdaily irrigation More...
 
lerr_t CalcIceContent ()
 Call of ice-content related processes.
 
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 CalcSurfaceWaterEvaporation ()
 
void CalcSurfaceFlux ()
 
void WatercycleDNDC_preferential_flow ()
 
void CalcSoilEvapoPercolation ()
 
void SoilWaterEvaporation (size_t)
 
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.

2315 {
2316  double balance = get_leaf_water() + wc_.surface_ice + wc_.surface_water + m_wc.plant_waterdeficit_compensation;
2317  for ( size_t sl = 0; sl < m_soillayers->soil_layer_cnt(); ++sl)
2318  {
2319  balance += (wc_.wc_sl[sl] + wc_.ice_sl[sl]) * sc_.h_sl[sl];
2320  }
2321  balance += ( - m_wc.accumulated_irrigation_event_executed
2322  - wc_.accumulated_irrigation_automatic
2323  - wc_.accumulated_irrigation_ggcmi
2324  - wc_.accumulated_irrigation_reservoir_withdrawal
2325  - wc_.accumulated_precipitation
2326  - wc_.accumulated_groundwater_access
2327  + wc_.accumulated_percolation
2328  + wc_.accumulated_runoff
2329  + wc_.accumulated_transpiration_sl.sum()
2330  + wc_.accumulated_interceptionevaporation
2331  + wc_.accumulated_soilevaporation
2332  + wc_.accumulated_surfacewaterevaporation);
2333 
2334  if ( _balance)
2335  {
2336  double const balance_delta( std::abs( *_balance - balance));
2337  if ( balance_delta > cbm::DIFFMAX)
2338  {
2339  KLOGWARN( "Water leakage: difference is ", balance - *_balance);
2340  }
2341  }
2342 
2343  for ( size_t sl = 0; sl < m_soillayers->soil_layer_cnt(); ++sl)
2344  {
2345  if ( cbm::flt_less( wc_.wc_sl[sl], 0.0))
2346  {
2347  KLOGWARN( "Negative water content of: ", wc_.wc_sl[sl], " in layer: ", sl, ". Water content set to zero.");
2348  wc_.wc_sl[sl] = 0.0;
2349  }
2350  if ( cbm::flt_less( wc_.ice_sl[sl], 0.0))
2351  {
2352  KLOGWARN( "Negative ice content of: ", wc_.ice_sl[sl], " in layer: ", sl, ". Ice content set to zero.");
2353  wc_.ice_sl[sl] = 0.0;
2354  }
2355  }
2356 
2357  return balance;
2358 }
double get_leaf_water()
Collects leaf water from all canopy layers.
Definition: watercycle-dndc.cpp:1089

◆ 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

604 {
605  //reset irrigation
606  m_wc.irrigation = 0.0;
607 
611  if ( cbm::flt_in_range_lu(0.0, m_cfg.automaticirrigation, 1.0))
612  {
613  for ( size_t l = 0; l < m_soillayers->soil_layer_cnt(); ++l)
614  {
615  // trigger irrigation events as soon as drought stress appears
616  double const wc_target( sc_.wcmin_sl[l] + m_cfg.automaticirrigation * (sc_.wcmax_sl[l] - sc_.wcmin_sl[l]));
617  if ( cbm::flt_less( wc_.wc_sl[l], wc_target))
618  {
619  // irrigation assumed until target water content
620  double const irrigate_layer( (wc_target - wc_.wc_sl[l]) * sc_.h_sl[l]);
621  m_wc.irrigation += irrigate_layer;
622  wc_.accumulated_irrigation_automatic += irrigate_layer;
623  }
624  }
625  }
626 
627  if ( cbm::flt_in_range_lu( 0.0, m_eventflood.get_saturation_level(), 1.0) &&
628  cbm::is_valid( m_eventflood.get_irrigation_height()) &&
629  cbm::is_valid( m_eventflood.get_soil_depth()))
630  {
631  double wc_sum( 0.0);
632  double wcmax_sum( 0.0);
633  double wcmin_sum( 0.0);
634  for ( size_t l = 0; l < m_soillayers->soil_layer_cnt(); ++l)
635  {
636  wc_sum += wc_.wc_sl[l] * sc_.h_sl[l];
637  wcmax_sum += sc_.wcmax_sl[l] * sc_.h_sl[l];
638  wcmin_sum += sc_.wcmin_sl[l] * sc_.h_sl[l];
639 
640  if ( cbm::flt_greater_equal( sc_.depth_sl[l], m_eventflood.get_soil_depth()))
641  {
642  break;
643  }
644  }
645 
646  // trigger irrigation events as soon as drought stress appears
647  double const wc_target( wcmin_sum + m_eventflood.get_saturation_level() * (wcmax_sum - wcmin_sum));
648  if ( cbm::flt_less( wc_sum, wc_target))
649  {
650  m_wc.irrigation += m_eventflood.get_irrigation_height();
651  wc_.accumulated_irrigation_automatic += m_eventflood.get_irrigation_height();
652  }
653  }
654 
662  if ( m_cfg.ggcmi_irrigation)
663  {
664  if( (lclock()->subday() == 1) && (_i == 0))
665  {
666  if( m_veg->size() > 0 ) //check crop is present
667  {
668  double water_supply( 0.0);
669  for ( size_t l = 0; l < m_soillayers->soil_layer_cnt(); ++l)
670  {
671  if ( cbm::flt_greater_zero( m_veg->mfrt_sl( l))) //only irrigate soil layers that contain roots
672  {
673  if( cbm::flt_less( wc_.wc_sl[l], sc_.wcmax_sl[l]) &&
674  cbm::flt_equal_zero( wc_.ice_sl[l])) //only add water if no ice is present
675  {
676  water_supply += (sc_.wcmax_sl[l] - wc_.wc_sl[l]) * sc_.h_sl[l]; //amount of water added (m)
677  wc_.wc_sl[l] = sc_.wcmax_sl[l];
678  }
679  }
680  }
681  wc_.accumulated_irrigation_ggcmi += water_supply;
682  }
683  }
684  }
685 
689  if ( cbm::is_valid( m_eventflood.get_water_table()))
690  {
691  /* Dynamic flooding */
692  if ( cbm::is_valid( m_eventflood.get_irrigation_height()))
693  {
694  bool irrigate( false);
695 
696  /* Irrigate after surface water table drop */
697  if ( cbm::flt_greater_equal_zero( m_eventflood.get_water_table()))
698  {
699  if ( cbm::flt_greater( m_eventflood.get_water_table(), wc_.surface_water))
700  {
701  irrigate = true;
702  }
703  }
704  else
705  {
706  if ( !cbm::flt_greater_zero( wc_.surface_water))
707  {
708  for ( size_t sl = 0; sl < m_soillayers->soil_layer_cnt(); ++sl)
709  {
710  if ( cbm::flt_greater_equal( sc_.depth_sl[sl], -m_eventflood.get_water_table()))
711  {
712  //check if water content below AWD_DEPTH is saturated
713  if ( cbm::flt_less( wc_.wc_sl[sl], 0.9 * sc_.poro_sl[sl]))
714  {
715  irrigate = true;
716  }
717  break;
718  }
719  }
720  }
721  }
722  // trigger AWD irrigation event
723  if ( irrigate)
724  {
725  double water_supply( cbm::bound_min( 0.0, m_eventflood.get_irrigation_height() - wc_.surface_water));
726  for ( size_t sl = 0; sl < m_soillayers->soil_layer_cnt(); ++sl)
727  {
728  // set soil fully water saturated
729  if ( cbm::flt_greater( sc_.poro_sl[sl], wc_.wc_sl[sl]))
730  {
731  water_supply += ((sc_.poro_sl[sl] - wc_.wc_sl[sl]) * sc_.h_sl[sl]);
732  }
733  }
734 
735  //remove rainfall (less irrigation water is supplied if it if raining)
736  water_supply = cbm::bound_min( 0.0, water_supply - m_mc.rainfall);
737 
738  if ( m_eventflood.have_unlimited_water())
739  {
740  wc_.accumulated_irrigation_automatic += water_supply;
741  }
742  else
743  {
744  if ( cbm::flt_greater( wc_.irrigation_reservoir, water_supply))
745  {
746  wc_.irrigation_reservoir -= water_supply;
747  }
748  else
749  {
750  water_supply = wc_.irrigation_reservoir;
751  wc_.irrigation_reservoir = 0.0;
752  }
753  wc_.accumulated_irrigation_reservoir_withdrawal += water_supply;
754  }
755  m_wc.irrigation += water_supply;
756  }
757  }
758  /* Static flooding */
759  else
760  {
761  if ( !cbm::flt_greater_zero( m_eventflood.get_water_table()))
762  {
763  double water_supply( 0.0);
764  for ( size_t sl = 0; sl < m_soillayers->soil_layer_cnt(); ++sl)
765  {
766  if ( cbm::flt_greater( sc_.depth_sl[sl], -m_eventflood.get_water_table()) &&
767  cbm::flt_greater( sc_.poro_sl[sl], wc_.wc_sl[sl]))
768  {
769  water_supply += (sc_.poro_sl[sl] - wc_.wc_sl[sl]) * sc_.h_sl[sl];
770  }
771  }
772 
773  //remove rainfall (less irrigation water is supplied if it if raining)
774  water_supply = cbm::bound_min( 0.0, water_supply - m_mc.rainfall);
775 
776  /* Surface water will be actively drained */
777  if ( cbm::flt_greater( wc_.surface_water, water_supply))
778  {
779  wc_.accumulated_runoff += wc_.surface_water - water_supply;
780  wc_.surface_water = water_supply;
781  }
782 
783  if ( m_eventflood.have_unlimited_water())
784  {
785  wc_.accumulated_irrigation_automatic += water_supply;
786  }
787  else
788  {
789  if ( cbm::flt_greater( wc_.irrigation_reservoir, water_supply))
790  {
791  wc_.irrigation_reservoir -= water_supply;
792  }
793  else
794  {
795  water_supply = wc_.irrigation_reservoir;
796  wc_.irrigation_reservoir = 0.0;
797  }
798  wc_.accumulated_irrigation_reservoir_withdrawal += water_supply;
799  }
800  m_wc.irrigation += water_supply;
801  }
805  else if ( cbm::flt_greater( m_eventflood.get_water_table(), wc_.surface_water))
806  {
807  //adjust surface and soil water in case of flooding event
808  //water required to fill up surface water
809  double water_supply( m_eventflood.get_water_table() - wc_.surface_water);
810 
811  //add water required to fill top x layers up to saturation
812  unsigned long no_layers(3);
813  if( no_layers > m_soillayers->soil_layer_cnt())
814  {
815  no_layers = m_soillayers->soil_layer_cnt();
816  }
817 
818  for ( size_t sl = 0; sl < no_layers; ++sl)
819  {
820  water_supply += ((sc_.poro_sl[sl] - wc_.wc_sl[sl]) * sc_.h_sl[sl]);
821  }
822 
823  //remove rainfall (less irrigation water is supplied if it if raining)
824  water_supply = cbm::bound_min( 0.0, water_supply - m_mc.rainfall);
825 
826  if ( m_eventflood.have_unlimited_water())
827  {
828  wc_.accumulated_irrigation_automatic += water_supply;
829  }
830  else
831  {
832  if ( cbm::flt_greater( wc_.irrigation_reservoir, water_supply))
833  {
834  wc_.irrigation_reservoir -= water_supply;
835  }
836  else
837  {
838  water_supply = wc_.irrigation_reservoir;
839  wc_.irrigation_reservoir = 0.0;
840  }
841  wc_.accumulated_irrigation_reservoir_withdrawal += water_supply;
842  }
843  m_wc.irrigation += water_supply;
844  }
845  }
846  }
847 
851  double const irrigation_scheduled( cbm::bound_min( 0.0, wc_.accumulated_irrigation - m_wc.accumulated_irrigation_event_executed));
852 
853  if ( cbm::flt_greater( irrigation_scheduled, 24.0 * rainfall_intensity()))
854  {
855  m_wc.irrigation += irrigation_scheduled / 24.0;
856  m_wc.accumulated_irrigation_event_executed += irrigation_scheduled / 24.0;
857  }
858  else if ( cbm::flt_greater( irrigation_scheduled, (double)hours_per_time_step() * rainfall_intensity()))
859  {
860  m_wc.irrigation += (double)hours_per_time_step() * rainfall_intensity();
861  m_wc.accumulated_irrigation_event_executed += (double)hours_per_time_step() * rainfall_intensity();
862  }
863  else
864  {
865  m_wc.irrigation += irrigation_scheduled;
866  m_wc.accumulated_irrigation_event_executed += irrigation_scheduled;
867  }
868 }
double rainfall_intensity()
Definition: watercycle-dndc.cpp:113

◆ 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().

1004 {
1005  if ( m_cfg.evapotranspiration_method == "thornthwaite")
1006  {
1007  if ( lclock()->is_position( TMODE_PRE_YEARLY))
1008  {
1010  lclock()->days_in_year(),
1011  m_climate->annual_temperature_average(),
1012  m_climate->annual_temperature_amplitude());
1013  }
1014 
1015  double const daylength( ldndc::meteo::daylength( m_setup->latitude(),
1016  lclock()->yearday()));
1017 
1018  hr_pot_evapotrans = m_param->WCDNDC_INCREASE_POT_EVAPOTRANS() * nhr / 24.0
1020  mc_.nd_airtemperature,
1021  daylength,
1023  }
1024  else if ( (m_cfg.evapotranspiration_method == "penman") ||
1025  (m_cfg.evapotranspiration_method == "priestleytaylor"))
1026  {
1027  /* clock */
1028  cbm::sclock_t const & clk( this->lclock_ref());
1029 
1030  /* leaf area index */
1031  double lai( 0.0);
1032  for( PlantIterator vt = m_veg->begin(); vt != m_veg->end(); ++vt)
1033  {
1034  lai += (*vt)->lai();
1035  }
1036 
1037  /* vapour pressure [10^3:Pa] */
1038  double vps( 0.0);
1039  ldndc::meteo::vps( mc_.nd_airtemperature, &vps);
1040  double vp( vps - m_climate->vpd_day( clk));
1041 
1042  if( m_cfg.evapotranspiration_method == "priestleytaylor")
1043  {
1044  hr_pot_evapotrans = m_param->WCDNDC_INCREASE_POT_EVAPOTRANS() * nhr / 24.0
1045  * ldndc::priestleytaylor( clk.yearday(),
1046  clk.days_in_year(),
1047  mc_.albedo,
1048  m_setup->latitude(),
1049  mc_.nd_airtemperature,
1050  mc_.nd_shortwaveradiation_in,
1051  vp,
1052  m_param->PT_ALPHA());
1053  }
1054  else if( m_cfg.evapotranspiration_method == "penman")
1055  {
1056  ldndc::surface_type surface( cbm::flt_greater_zero( lai) ? short_grass : bare_soil);
1057 
1058  hr_pot_evapotrans = m_param->WCDNDC_INCREASE_POT_EVAPOTRANS() * nhr / 24.0
1059  * ldndc::penman( surface,
1060  clk.yearday(),
1061  clk.days_in_year(),
1062  mc_.albedo,
1063  m_setup->latitude(),
1064  mc_.nd_shortwaveradiation_in * cbm::SEC_IN_DAY,
1065  mc_.nd_airtemperature,
1066  mc_.nd_windspeed,
1067  vp);
1068  }
1069  }
1070  else
1071  {
1072  KLOGERROR("[BUG] huh :o how did you get here? ",
1073  "tell the maintainers refering to this error message");
1074  return LDNDC_ERR_FAIL;
1075  }
1076 
1077 
1078  wc_.accumulated_potentialevapotranspiration += hr_pot_evapotrans;
1079 
1080  return LDNDC_ERR_OK;
1081 }
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:134
Here is the call graph for this function:

◆ CalcSnowEvaporation()

void ldndc::WatercycleDNDC::CalcSnowEvaporation ( )
private
Parameters
[in]None
[out]None
Returns
None
1690 {
1691  //Average limit of snowEvaporation is 0.00013m day-1 (Granger and Male 1978)
1692  double hr_potESnow( cbm::bound(0.0, hr_pot_evapotrans, 0.00013 * nhr/24.0));
1693 
1694  if ( cbm::flt_greater_zero( wc_.surface_ice) &&
1695  cbm::flt_greater_zero( hr_potESnow))
1696  {
1697  //If there is a snowpack and there is a potential to evaporate
1698  if ( wc_.surface_ice > hr_potESnow)
1699  {
1700  //Partial evaporation from the snow
1701  hr_pot_evapotrans = cbm::bound_min( 0.0, hr_pot_evapotrans - hr_potESnow);
1702  wc_.accumulated_surfacewaterevaporation += hr_potESnow;
1703  wc_.surface_ice -= hr_potESnow;
1704  }
1705  else
1706  {
1707  //Total evaporation of the snowpack
1708  hr_pot_evapotrans = cbm::bound_min( 0.0, hr_pot_evapotrans - wc_.surface_ice);;
1709  wc_.accumulated_surfacewaterevaporation += wc_.surface_ice;
1710  wc_.surface_ice = 0.0;
1711  }
1712  }
1713 }

◆ CalcSoilEvapoPercolation()

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

◆ CalcSurfaceFlux()

void ldndc::WatercycleDNDC::CalcSurfaceFlux ( )
private
Parameters
[in]None
[out]None
Returns
None
2229 {
2230  if ( cbm::flt_greater_zero( m_eventflood.get_bund_height()))
2231  {
2232  if ( cbm::flt_greater( wc_.surface_water, m_eventflood.get_bund_height()))
2233  {
2234  wc_.accumulated_runoff += wc_.surface_water - m_eventflood.get_bund_height();
2235  wc_.surface_water = m_eventflood.get_bund_height();
2236  }
2237  }
2238  else
2239  {
2240  /* runoff fraction per time step equals RO fraction per hour * length of a time step */
2241  double const runoff_fraction( m_param->FRUNOFF() * get_time_step_duration());
2242 
2243  // if frunoff_ts < 1
2244  if ( cbm::flt_less( runoff_fraction, 1.0))
2245  {
2246  double const runoff( runoff_fraction * wc_.surface_water);
2247  wc_.surface_water -= runoff;
2248  wc_.accumulated_runoff += runoff;
2249  }
2250  else
2251  {
2252  wc_.accumulated_runoff += wc_.surface_water;
2253  wc_.surface_water = 0.0;
2254  }
2255  }
2256 }
double get_time_step_duration()
Time fraction with regard to daily rates.
Definition: watercycle-dndc.cpp:2303

◆ CalcSurfaceWaterEvaporation()

void ldndc::WatercycleDNDC::CalcSurfaceWaterEvaporation ( )
private
Parameters
[in]None
[out]None
Returns
None
1659 {
1660  if ( cbm::flt_greater_zero( wc_.surface_water) &&
1661  cbm::flt_greater_zero( hr_pot_evapotrans))
1662  {
1663  if ( hr_pot_evapotrans > wc_.surface_water)
1664  {
1665  wc_.accumulated_surfacewaterevaporation += wc_.surface_water;
1666  hr_pot_evapotrans -= wc_.surface_water;
1667  wc_.surface_water = 0.0;
1668  }
1669  else
1670  {
1671  wc_.surface_water -= hr_pot_evapotrans;
1672  wc_.accumulated_surfacewaterevaporation += hr_pot_evapotrans;
1673  hr_pot_evapotrans = 0.0;
1674  }
1675  }
1676 }

◆ 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
1518 {
1519  // hourly potential transpiration
1520  double const hr_potTrans( hr_potTransinm * cbm::CM_IN_M);
1521  // hourly transpiration
1522  double hr_trans( 0.0);
1523 
1524  // Calculate the root water uptake and hence the transpiration for every plant individually
1525  for( PlantIterator vt = m_veg->begin(); vt != m_veg->end(); ++vt)
1526  {
1527  // split up the potential transpiration equally to the various plants
1528  // frt mass of the current species
1529  double const mfrt_species( (*vt)->mFrt);
1530  // total frt mass
1531  double const mfrt_sum( m_veg->dw_frt());
1532  double const hr_potTransspecies = hr_potTrans * mfrt_species/mfrt_sum; // in cm
1533 
1534  // If some soil layers are frozen and contain only ice, no fluid water is present and the water potential diverges.
1535  // The uptake from these layers is prevented by considering only roots in layers with more water than ice.
1536  // In this case the root distribution needs to be rescaled (otherwise the non-contributing layers would effectively contribute a potential = 0).
1537  double fFrt_unfrozen( 1.0);
1538 
1539  /* TODO: include icetowatercrit as proper parameter */
1540  double icetowatercrit( 0.1);
1541  double effsoilwatpot( 0.0);
1542  for( size_t sl = 0; sl < m_soillayers->soil_layer_cnt(); ++sl)
1543  {
1544  // fine root conditions to prevent transpiration without uptake organs, wateruptake from frozen ground
1545  if( cbm::flt_greater_zero( (*vt)->fFrt_sl[sl] * mfrt_species))
1546  {
1547  if(cbm::flt_less( wc_.ice_sl[sl]/wc_.wc_sl[sl], icetowatercrit))
1548  {
1549  // overall water potential in this layer
1550  double const watpotl( Soillayerwaterhead( sl)); // negative
1551  effsoilwatpot += watpotl * (*vt)->fFrt_sl[sl]; // negative
1552  }
1553  else
1554  {
1555  fFrt_unfrozen -= (*vt)->fFrt_sl[sl];
1556  }
1557  }
1558  else
1559  {
1560  // roots are not wireless ;-)
1561  break;
1562  }
1563  }
1564  // normalize the root distribution in the potential, if some soil is frozen
1565  effsoilwatpot = effsoilwatpot / fFrt_unfrozen;
1566 
1567  // hydraulic conductivities of plant system
1568  double const Krs(vt->KRSINIT() * mfrt_species / vt->FRTMASSINIT() * nhr); // cm(water)/cm(from pressure)/timestep
1569  double const Kcomp(vt->KCOMPINIT() * mfrt_species / vt->FRTMASSINIT() * nhr); // cm(water)/cm(from pressure)/timestep
1570 
1571  // water potential in the leafs, depending on the potential transpiration
1572  double const leafwatpot( cbm::bound_min(vt->HLEAFCRIT(), effsoilwatpot - (hr_potTransspecies / Krs))); // cm
1573 
1574  if( cbm::flt_greater_zero( leafwatpot))
1575  {
1576  KLOGERROR( "leafwatpot is positive");
1577  return LDNDC_ERR_FAIL;
1578  }
1579  if( !cbm::flt_greater_zero( effsoilwatpot - leafwatpot))
1580  {
1581  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.");
1582  return LDNDC_ERR_FAIL;
1583  }
1584 
1585  double const effuptake( Krs * (effsoilwatpot - leafwatpot)); // cm/timestep
1586  double uptake_tot( 0.0);
1587  double uptakecomp_tot( 0.0);
1588 // double uptakecompabs_tot( 0.0);
1589 
1590  for( size_t sl = 0; sl < m_soillayers->soil_layer_cnt(); ++sl)
1591  {
1592  // fine root condition to prevent transpiration without uptake organs
1593  if( cbm::flt_greater_zero( (*vt)->fFrt_sl[sl] * mfrt_species))
1594  {
1595  if(cbm::flt_less( wc_.ice_sl[sl]/wc_.wc_sl[sl], icetowatercrit))
1596  {
1597  double const watpotl( Soillayerwaterhead( sl));
1598  double const compuptake( Kcomp * (watpotl - effsoilwatpot));
1599  double uptake_layer( (effuptake + compuptake) * (*vt)->fFrt_sl[sl]); // absolute value in cm
1600 
1601  wc_.accumulated_transpiration_sl[sl] += uptake_layer * cbm::M_IN_CM;
1602  uptake_tot += uptake_layer; // absolute value in cm
1603  uptakecomp_tot += compuptake * (*vt)->fFrt_sl[sl]; // absolute value in cm
1604 // uptakecompabs_tot += fabs(compuptake * (*vt)->fFrt_sl[sl]); // absolute value in cm
1605 
1606  wc_.wc_sl[sl] -= uptake_layer * cbm::M_IN_CM /sc_.h_sl[sl]; // fraction of water in this layer, in m
1607 
1608  if( !cbm::flt_greater_zero( wc_.wc_sl[sl]))
1609  {
1610  KLOGERROR( "In soil layer ", sl, " the water content is negative: ", wc_.wc_sl[sl]);
1611  return LDNDC_ERR_FAIL;
1612  }
1613  }
1614  }
1615  else
1616  {
1617  // roots are not wireless ;-)
1618  break;
1619  }
1620  }
1621  hr_trans += uptake_tot * cbm::M_IN_CM; // absolute value in m for all species
1622 
1623 
1624  if( cbm::flt_greater_zero( fabs(uptakecomp_tot))){
1625  KLOGWARN( "Compensatory water uptake ", uptakecomp_tot, " > 0.");
1626  }
1627  if( cbm::flt_greater( uptake_tot, hr_potTransspecies, 0.0000000001))
1628  {
1629  KLOGERROR( "Total water uptake ", uptake_tot, " larger than potential transpiration ", hr_potTransspecies);
1630  }
1631  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))
1632  {
1633  KLOGERROR( "T ", uptake_tot, "cm < Tpot ", hr_potTransspecies, "cm even though leafwatpot ", leafwatpot, " > HLEAFCRIT", vt->HLEAFCRIT());
1634  }
1635  }
1636  hr_pot_evapotrans -= hr_trans;
1637 
1638  return LDNDC_ERR_OK;
1639 }

◆ event_flood()

lerr_t ldndc::WatercycleDNDC::event_flood ( )
private

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

  • surface water table
  • bund height
574 {
575  lerr_t rc = m_eventflood.solve();
576  if ( rc != LDNDC_ERR_OK)
577  {
578  KLOGERROR("Irrigation event not successful!");
579  return rc;
580  }
581 
582  /* max_percolation is gradually decreased after end of flooding event to inital value */
583  double const maximum_percolation = m_eventflood.get_maximum_percolation();
584  if ( cbm::is_valid( maximum_percolation))
585  {
586  if ( cbm::flt_greater_zero( maximum_percolation))
587  {
588  max_percolation = maximum_percolation * nhr / 24.0;
589  }
590  }
591  else
592  {
593  /* time rate for gradual recovery of max_percolation */
594  double const time_rate( get_time_step_duration() * 0.1);
595  max_percolation -= (max_percolation - WaterFlowSaturated( m_soillayers->soil_layer_cnt()-1, 1.0)) * time_rate;
596  }
597 
598  return LDNDC_ERR_OK;
599 }
double WaterFlowSaturated(size_t, double const &)
Definition: watercycle-dndc.cpp:2103
double get_time_step_duration()
Time fraction with regard to daily rates.
Definition: watercycle-dndc.cpp:2303

◆ 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
1234 {
1235  // layer specific water availability
1236  // organic fraction [%]
1237  double const orgf( sc_.fcorg_sl[_sl] / cbm::CCORG);
1238  // clay factor "1" [-]
1239  double const clay_f1( pow(10.0, (-sc_.clay_sl[_sl] - m_param->RCLAY())));
1240  // clay factor "2" [-]
1241  double const clay_f2( std::max(0.0, 1.0 + std::min(1.0 - orgf, sc_.clay_sl[_sl])));
1242 
1243  // fraction of max uptake that can be used according to soil conditions [%]
1244  return cbm::bound(0.0, clay_f1 + pow( _water_avail / _water_ref, clay_f2), 1.0);
1245 }

◆ 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
1090 {
1091  if ( m_veg->size() > 0u)
1092  {
1093  return wc_.wc_fl.sum();
1094  }
1095  return 0.0;
1096 }

◆ rainfall_intensity()

double ldndc::WatercycleDNDC::rainfall_intensity ( )
private

fixed amount of maximum rainfall/irrigation triggered per time step

References ldndc::climate::climate_info_t::rainfall_intensity, and ldndc::thornthwaite_heat_index().

114 {
115  if ( m_iokcomm->get_input_class< input_class_climate_t >())
116  {
117  return m_iokcomm->get_input_class< climate::input_class_climate_t >()->station_info()->rainfall_intensity * cbm::M_IN_MM;
118  }
119  else
120  {
121  return ldndc::climate::climate_info_defaults.rainfall_intensity * cbm::M_IN_MM;
122  }
123 }
double rainfall_intensity
Definition: climatetypes.h:40
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
1757 {
1758  //percolation and direct evaporation from the (upper) soil
1759  //if there is snow cover, evaporation from soil will be set to 0, and only sublimation is allowed.
1760  double const orgf( sc_.fcorg_sl[_sl] / cbm::CCORG);
1761  double const clay_fact( 1.0 + m_param->SLOPE_CLAYF() * std::min(1.0 - orgf, sc_.clay_sl[_sl]));
1762  double const wc_min_evaporation( m_param->WCDNDC_EVALIM_FRAC_WCMIN() * sc_.wcmin_sl[_sl]);
1763 
1764  if ( ((sc_.depth_sl[_sl] - sc_.h_sl[_sl]) < m_param->EVALIM()) &&
1765  (wc_.wc_sl[_sl] > wc_min_evaporation) &&
1766  cbm::flt_greater_zero( hr_pot_evapotrans))
1767  {
1768  //limiting factor for soil water infiltration
1769  double limit_wi( cbm::bound_min( 0.0,
1770  (wc_.wc_sl[_sl] - wc_min_evaporation) / sc_.wcmax_sl[_sl]));
1771  limit_wi = cbm::bound_max( pow(limit_wi, clay_fact), 1.0);
1772 
1773  double const hrest( std::min( sc_.h_sl[_sl], m_param->EVALIM() - ( sc_.depth_sl[_sl] - sc_.h_sl[_sl])));
1774 
1775  //soil water evaporation from the upper soil layers due to physical evaporation (not transpiration)
1776  //linear decrease, consistent with variable soil thickness
1777  double const layer_Evapo = cbm::bound(0.0,
1778  hr_pot_evapotrans * hrest / m_param->EVALIM()
1779  * std::max(0.0,
1780  1.0 - std::min((double)m_param->EVALIM(),
1781  sc_.depth_sl[_sl] - ( 0.5 * sc_.h_sl[_sl]))
1782  / m_param->EVALIM())
1783  * limit_wi,
1784  limit_wi * wc_.wc_sl[_sl]*sc_.h_sl[_sl]);
1785 
1786  //update of the current soil layer water content
1787  wc_.wc_sl[_sl] -= (layer_Evapo / sc_.h_sl[_sl]);
1788  wc_.accumulated_soilevaporation += layer_Evapo;
1789  hr_pot_evapotrans = cbm::bound_min( 0.0, hr_pot_evapotrans - layer_Evapo);
1790  }
1791 }

◆ WatercycleDNDC_preferential_flow()

void ldndc::WatercycleDNDC::WatercycleDNDC_preferential_flow ( )
private
Parameters
[in]None
[out]None
Returns
None
2118 {
2119  //BY_PASSF is defined as the fraction of surface water that passes per hour (0.0 by default)
2120  if ( cbm::flt_greater_zero( m_param->BY_PASSF()) &&
2121  cbm::flt_greater_zero( wc_.surface_water))
2122  {
2123 
2124  double water_def_total( 0.0);
2125  for ( size_t sl = 0; sl < m_soillayers->soil_layer_cnt(); ++sl)
2126  {
2127  //water flux that flow through macro pores can maximally store
2128  water_def_total += cbm::bound_min( 0.0, (sc_.wcmax_sl[sl] - wc_.wc_sl[sl] - wc_.ice_sl[sl]) * sc_.h_sl[sl]);
2129  }
2130 
2131  //duration of timestep (hr-1)
2132  double const fhr( get_time_step_duration());
2133 
2134 
2135  //fraction of surface water that is put into bypass flow (m timestep-1)
2136  double const bypass_fraction( cbm::bound_max( m_param->BY_PASSF() * fhr, 0.99));
2137  double const bypass_water( wc_.surface_water * bypass_fraction);
2138  wc_.surface_water -= bypass_water;
2139  wc_.accumulated_infiltration += bypass_water;
2140 
2141  if ( cbm::flt_greater_equal( water_def_total, bypass_water))
2142  {
2143 
2144  for ( size_t sl = 0; sl < m_soillayers->soil_layer_cnt(); ++sl)
2145  {
2146  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]));
2147  double const water_add( water_def / water_def_total * bypass_water);
2148 
2149  wc_.wc_sl[sl] += water_add / sc_.h_sl[sl];
2150  }
2151  }
2152  else
2153  {
2154  for ( size_t sl = 0; sl < m_soillayers->soil_layer_cnt(); ++sl)
2155  {
2156  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]));
2157  wc_.wc_sl[sl] += water_def / sc_.h_sl[sl];
2158  }
2159  /* add surplus to percolation out of last soil layer */
2160  wc_.accumulated_percolation += bypass_water - water_def_total;
2161  wc_.accumulated_waterflux_sl[m_soillayers->soil_layer_cnt()-1] += bypass_water - water_def_total;
2162  }
2163  }
2164 }
double get_time_step_duration()
Time fraction with regard to daily rates.
Definition: watercycle-dndc.cpp:2303

◆ 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

2027 {
2028  double const sks( WaterFlowSaturated( _sl, _fact_impedance));
2029  double const fsl( get_fsl( _sl));
2030  double const fhr( get_time_step_duration());
2031 
2033  double slope(( _sl < m_soillayers->soil_layers_in_litter_cnt()) ? m_param->SLOPE_FF() : m_param->SLOPE_MS());
2034 
2035  //max 0.005 means that no sks values up to 9.88 cm min-1 are allowed !!
2036  double const travelTime( std::max( 0.005, 1.0 - log10( sc_.sks_sl[_sl] * cbm::M_IN_CM * cbm::MIN_IN_DAY * fhr)));
2037  return( cbm::bound_max( cbm::sqr(1.0 - (sc_.wcmax_sl[_sl] / ((wc_.wc_sl[_sl] + wc_.ice_sl[_sl]) * slope)))
2038  * 0.5 * wc_.wc_sl[_sl] * sc_.h_sl[_sl] * fsl * (1.0 - exp(-1.0 / travelTime)) * _fact_impedance,
2039  sks));
2040 }
double WaterFlowSaturated(size_t, double const &)
Definition: watercycle-dndc.cpp:2103
double get_time_step_duration()
Time fraction with regard to daily rates.
Definition: watercycle-dndc.cpp:2303
double get_fsl(size_t)
Returns factor accounting for soil layer depth. Originally, a constant soil layer depth of 0...
Definition: watercycle-dndc.cpp:2200

◆ WaterFlowSaturated()

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

Returns saturated water flow per time step accounting for impedance

2105 {
2106  double const sks( sc_.sks_sl[_sl] * cbm::M_IN_CM * cbm::MIN_IN_DAY * get_time_step_duration() * _fact_impedance);
2107  return sks;
2108 }
double get_time_step_duration()
Time fraction with regard to daily rates.
Definition: watercycle-dndc.cpp:2303

Member Data Documentation

◆ IMAX_W

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

number of iteration steps within a day