<commit_before>/*
  The prediction of feed intake uses a simplified GrazeIn algorithm.

  GrazeMore, "Improving sustainability of milk production systems in the European Union through increasing reliance on
  grazed pasture" was an EU research project that ran from 2000-2004. It involved the development of a grazing decision
  support system to assist farmers in improving the use of grazed grass for milk production. In order to build the DSS,
  a European herbage growth prediction model and a European herbage intake prediction model were produced. Therefore
  GrazeIn is the only currently available intake prediction for grazing cows that is based on European data.

  The feed intake prediction in GrazeIn is based on the French INRA fill unit system and adapted to grazing dairy cows.
  The authors argue that because European cows don´t graze all year long and are often supplemented, a general model of
  intake is needed rather than one specialized on indoor feeding or grazing.

  Because GrazeIn in based on the INRA fill value system, in some cases equations from Agabriel (2010) are used.

  The general functional principal of the INRA fill value system is as follows: The sum of all fill values of the feeds
  equals the intake capacity of the cow. While the intake capacity of the cow is almost exclusively based on animal-
  related parameters, the fill values of the feeds are almost exclusively based on feed-related parameters. Exceptions
  are the appearance of "potential milk production modified by protein intake" in the calculation of the intake
  capacity, and the appearance of milk yield and energy requirements in the calculation of the fill values of
  concentrates.

  REFERENCES

  <NAME>., <NAME>., <NAME>. & <NAME>. (2011).
  GrazeIn: a model of herbage intake and milk production for grazing dairy
  cows. 1. Prediction of intake capacity, voluntary intake and milk
  production during lactation. Grass and Forage Science 66(1): 29-44.

  <NAME>, <NAME>, <NAME>, Peyraud JL. (2011a). 
  GrazeIn: A model of herbage intake and milk production for grazing dairy cows. 
  2. Prediction of intake under rotational and continuously stocked grazing management. 
  Grass and Forage Science 66: 45–60.

  <NAME>. (2010). Alimentation des bovins, ovins et caprins. Besoins des animaux - Valeurs
  des aliments. Tables INRA 2010. Editions Quae, France.

  Fill values (FV) are expressed in the unit LFU, lactating fill unit (UEL, unite encombrement lait)

  LICENSE

  Copyright 2014 <NAME>   <<EMAIL>>
  Copyright 2014 <NAME> <<EMAIL>>

  Distributed under the MIT License. See accompanying file LICENSE or copy at http://opensource.org/licenses/MIT

  Any publication for which this file or a derived work is used must include an a reference to the article:

  <NAME>., <NAME>., <NAME>., <NAME>. (2014) SOLID-DSS - Eine online-Anwendung zur verbesserten 
  Abstimmung von Grundfutterangebot und -bedarf auf biologisch wirtschaftenden Low Input Milchviehbetrieben.
  In: <NAME>., <NAME>., <NAME>. (eds), Angewandte Forschung und Beratung für den ökologischen Landbau in 
  Bayern: Öko-Landbau-Tag 2014 am 9. April 2014 in Triesdorf; Tagungsband. LfL, Freising-Weihenstephan, pp. 19-22.

  TODO

  - PLPOT in IC and GSR: is it zero for dry cows or still PLPOT?
*/
 
var dairy = dairy || {};

dairy.intake = (function () {

var exp = Math.exp
  , log = Math.log
  , pow = Math.pow
  , Σ = function (a) {
      var sum = 0;
      for (var i = 0, is = a[0].length; i < is; i++)
        sum += a[0][i] * a[1][i];
      return sum;
    }
  ;

function is_null_or_undefined (x) {
  return x === null || x === undefined;
}


/*
  TODO: Funktion rätselhaft, da DMI = Fs + Cs + HI_g

  DMI   [kg]  dry matter intake
  Fs    [kg]  array of feeds
  FVs_f [LFU] array of forage fill values
  Cs    [kg]  array of concentrates
  Cs_f  [LFU] array of concentrate fill values
  FV_h  [LFU] herbage fill value 
  HI_r  [-]   relative herbage intake (0-1)
  HI_g  [kg]  herbage intake at grazing
*/

var DMI = function (Fs, FVs_f, Cs, FVs_c, FV_h, HI_r, HI_g) {

  var DMI = 0
    , DMI_f = Σ([Fs, FVs_f])
    , DMI_c = Σ([Cs, FVs_c])
    ;

  DMI = DMI_f + DMI_c + (FV_h/HI_r * HI_g);

  return DMI;

};

/*
  Agabriel (2010), eq. 2.3

  Equation to calculate the intake capacity.
  
  The intake capacity of the cow is not calculated acc. to Faverdin et al. (2011), because the appearance of MPprot
  (potential milk production modified by protein intake) is problematic since protein intake is unkown at the time of
  feed intake prediction. Instead, the previous Agabriel (2010) version is used:

  In GrazeIn, Pl_pot represents the potential milk yield of a cow, not the actual milk yield. This is done in order
  to avoid milk yield driving feed intake (pull-situation). In SOLID-DSS, values for milk yield are taken from the
  lactation curves modelled within the herd model. These lactation curves are based on input by the user, and thereby
  represent average milk yields instead of actual ones, so they can be interpreted as a potential under the given
  circumstances.

  TODO
    - is PLPOT in ECM?

  IC    [LFU]       intake capacity ~ DMI @ FV = 1
  BW    [kg]        body weight
  PLPOT [kg day-1]  milk yield, potential
  BCS   [-]         body condition score (1-5)
  WL    [week]      week of lactation
  WG    [week]      week of gestation (0-40)
  AGE   [month]     age in month
  p     [#]         parity
*/

var IC = function (BW, PLPOT, BCS, WL, WG, AGE, p) {

  var IC = 0;

  IC = (13.9 + (BW - 600) * 0.015 + PLPOT * 0.15 + (3 - BCS) * 1.5) * IL(p, WL) * IG(WG) * IM(AGE);

  return IC;

}; 

/*
  Agabriel (2010) eq. 2.3f

  The equation for the index of lactation. .

  IL  [-]     index lactation (0-1)
  p   [#]     parity
  WL  [week]  week of lactation
*/

var IL = function IL(p, WL) {

  /* if cow is dry IL = 1 */
  var IL = 1;

  if (p === 1 && WL > 0)
    IL = 0.6 + (1 - 0.6) * (1 - exp(-0.16 * WL));
  else if (p > 1 && WL > 0)
    IL = 0.7 + (1 - 0.7) * (1 - exp(-0.16 * WL));

  return IL;

};

/*
  Agabriel (2010) eq. 2.3f

  The equation for the index of gestation.
  
  IG  [-]     index gestation (0-1)
  WG  [week]  week of gestation (0-40)
*/

var IG = function (WG) {

  return 0.8 + 0.2 * (1 - exp(-0.25 * (40 - WG)));  

};

/*
  Agabriel (2010) eq. 2.3f

  The equation for the index of maturity.
  
  IM  [-]     index maturity (0-1)
  AGE [month] month
*/

var IM = function (AGE) {

  return -0.1 + 1.1 * (1 - exp(-0.08 * AGE));

};

/*
  Agabriel (2010), Table 8.1.

  The general equation for calculating forage fill values.

  The QIL-values are calculated in feed.evaluation, details see there.
  
  FV_f  [LFU kg-1 (DM)] forage fill value (unite encombrement lait)
  QIL   [g kg-1]        ingestibility in g per kg metabolic live weight                
*/

var FV_f = function (QIL) {

  return 140 / QIL;

};

/*
  Faverdin et al. (2011) eq. 11
  
  Equation for calculating concentrate fill value.

  One of the factors influencing the concentrate fill value is the fill value of the forage base.
  Because the total diet is unknown prior to the allocation of feeds, the weighted mean of the FV of all available
  forages for the group of cows and the time period in question is used for FV_fr.

  FV_c  [LFU kg-1 (DM)] concentrate fill value (lactating fill unit, unite encombrement lait)
  FV_fs [LFU]           weighted FV of forages in ration
  GSR   [-]             global substitution rate (0-1)
*/

var FV_c = function (FV_fs, GSR) {

  return FV_fs * GSR;

};

/*
  Baldinger et. al. (xxxx) eq. x

  Equation to estimate the fill value of forages in a diet from the cow's requirements prior to ration optimization.
  This is based on the fact that on average a feed's fill value will descrease with increasing energy content. The 
  estimated FV_fs is used to calculate a concentrate fill value (see FV_cs). We need it if we what to keep the diet LP linear.
  The regression was calculated from all forages available in Agabriel 2010 (r^2 = 0.564, n = 643).

  FV_fs_diet  [LFU kg-1 (DM)] Estimated fill value of forages in diet
  E_fs        [UFL]           Total energy content of forages in diet
  FV_fs       [LFU]           Total fill values of forages in diet
*/

var FV_fs_diet = function (E_fs, FV_fs) {

  return - 0.489 * E_fs / FV_fs + 1.433;

};

/*
  Baldinger et. al. (xxxx) eq. x

  Estimate an average concentrate fill value. We assume that requirements are met i.e. cows with BWC >= 0 have a zero
  energy balance. 

  TODO: 
    - simplify to an equation?
    - use this as a better estimate of DMI instead of DMI = IC (FV ~ 1)?

  FV_cs_diet  [LFU kg-1 (DM)] estimated fill value of concentrates in diet
  E_req       [UFL]           Energy requirements of a cow (in UFL!)
  IC          [LFU]           Intake capacity of a cow
  c_mx        [kg kg-1]       Maximum fraction (DM) of concentrates in diet (optional, defaults to 0.5 which is the 
                              range the INRA system is applicable)
  PLPOT       [kg day-1]      milk yield, potential
  parity      [#]             parity
  BWC         [kg]            body weight change       
*/

var FV_cs_diet = function (E_req, IC, c_mx, PLPOT, parity, BWC) {

  var FV_cs_diet = 0;

  if (is_null_or_undefined(c_mx) || c_mx > 0.5)
    c_mx = 0.5;
      
  var c = 0       /* fraction of conc. in diet [kg (DM) kg-1 (DM)] */
    , c_kg = 0    /* kg conc. in diet */
    , E_f = E_req /* energy requirements covered by forage */
    , IC_f = IC   /* IC covered by forage */
    , c_fvs = []  /* store conc. fill values */
    , c_fv = 0    /* estimated conc. fill value */
    , f_fv = 0    /* estimated forage fill value */
    , s = 0       /* substitution rate */
    ;

  /* fixed to a max. UFL / UEL value observed in feeds */
  if (E_f / IC_f > 1.15)
    E_f = E_req = IC_f * 1.15;  

  while (true) {

    /* staring from a diet with zero kg conc. we add conc. till we reach c_mx */
    s = GSR(c_kg, DEF(E_f, IC_f), PLPOT, parity, BWC);
    f_fv = FV_fs_diet(E_f, IC_f);
    c_fv = f_fv * s;
    c = c_kg / (IC_f / f_fv + c_kg);

    if (c >= c_mx)
      break;

    c_fvs.push(c_fv);

    /* add concentrate to the diet */
    c_kg += 0.5;
    /* we assume the concentrate's UFL content is 1.05. In fact the result is not very sensitive to UFL of conc. */
    E_f = E_req - c_kg * 1.05;
    IC_f = IC - c_kg * c_fv;

  }

  /* average */
  FV_cs_diet = c_fvs.reduce(function (a, b, i, array) { return a + b / array.length; }, 0);

  return FV_cs_diet;

};

/*
  Agabriel (2010) eq. 2.25

  DEF is the average energy density of the forages in the diet, which is calculated as the weighted mean of all
  available forages for the group of cows and the time period in question.

  DEF       [UFL LFU-1]      average energy density of the forages in the diet (can be slightly higher than 1)
  UFL_fs    [UFL kg-1 (DM)]  sum of the energy contents of all available forages
  LFU_fs    [LFU kg-1 (DM)]  sum of the fill values of all available forages
*/

var DEF = function (UFL_fs, LFU_fs) {

  return UFL_fs / LFU_fs;

};

/*
  Agabriel (2010) eq 2.26.

  Both in Agabriel (2010) and in GrazeIn, concentrate fill values not only vary with the fill value of the forage base,
  but also with the amount of concentrates, the milk yield of the cow and the energy balance of the cow, which are
  all incorporated into the calculation of the global substitution rate (GSR). Consequently, concentrate fill values
  and feed intake are calcalated iteratively until the system converges.
  In SOLID-DSS, no iterative calculation is possible because all fill values must stay constant when the linear
  programming starts to allocate feeds. Therefore the simplified version of calculating GSR that can be found in
  Agabriel (2010) was chosen. According to this version, there is one calculation fo GSR when cows are not mobilizing,
  and a different calculation when cows are mobilizing.

  For QI_c, the maximum of concentrates the user is willing to feed is used, because we assume that those cows that are
  mobilizing will receive the maximum concentrate supplementation.

  GSR           [-]         global substitution rate (0-1)
  QI_c          [kg (DM)]   total amount of concentrates that are fed
  DEF           [UFL LFU-1] average energy density of the forages in the diet (can be slightly higher than 1)
  PLPOT         [kg day-1]  milk yield, potential
  parity        [#]         parity
  BWC           [kg]        body weight change
*/

var GSR = function (QI_c, DEF, PLPOT, parity, BWC) {

  var GSR = 0
    , GSR_zero = 0.55
    , d = (parity > 1 ? 1.10 : 0.96)
    ;

  /* should be larger 0 (dry cows have a pot. milk yield as well) */
  if (PLPOT <= 0)
    PLPOT = 0.1;

  GSR_zero = d * pow(PLPOT, -0.62) * exp(1.32 * DEF);

  if (BWC < 0) /* cow is mobilizing */
    GSR = -0.43 + 1.82 * GSR_zero + 0.035 * QI_c - 0.00053 * PLPOT * QI_c;
  else
    GSR = GSR_zero;

  return GSR;

};

/*
  Delagarde et al. (2011) eq. 13
  Equation for relative herbage intake limited by allowance when grazing is rotational.

  When cows are not grazing, all necessary calculations are hereby completed and the feed intake restriction is:
  DMI = sum of fill values of forages and concentrates multiplied with their amount (or share in the diet)
  When cows are grazing, their herbage intake can be restricted by sward availability or by time at grazing.
  For calculating the restriction caused by sward availability, there are two different calculations, one for rotational
  and one for continuous grazing.

  HI_r_ha [-] relative herbage intake limited by herbage allowance when grazing is rotational (0-1)
  HA_r    [-] relative herbage allowance
*/
 
var HI_r_ha = function (HA_r) {

  return 1.08 * (1 - exp(-1.519 * HA_r));

};

/*
  Delagarde et al. (2011) eq. 15
<commit_msg>Add comment<commit_after>/*
  The prediction of feed intake uses a simplified GrazeIn algorithm.

  GrazeMore, "Improving sustainability of milk production systems in the European Union through increasing reliance on
  grazed pasture" was an EU research project that ran from 2000-2004. It involved the development of a grazing decision
  support system to assist farmers in improving the use of grazed grass for milk production. In order to build the DSS,
  a European herbage growth prediction model and a European herbage intake prediction model were produced. Therefore
  GrazeIn is the only currently available intake prediction for grazing cows that is based on European data.

  The feed intake prediction in GrazeIn is based on the French INRA fill unit system and adapted to grazing dairy cows.
  The authors argue that because European cows don´t graze all year long and are often supplemented, a general model of
  intake is needed rather than one specialized on indoor feeding or grazing.

  Because GrazeIn in based on the INRA fill value system, in some cases equations from Agabriel (2010) are used.

  The general functional principal of the INRA fill value system is as follows: The sum of all fill values of the feeds
  equals the intake capacity of the cow. While the intake capacity of the cow is almost exclusively based on animal-
  related parameters, the fill values of the feeds are almost exclusively based on feed-related parameters. Exceptions
  are the appearance of "potential milk production modified by protein intake" in the calculation of the intake
  capacity, and the appearance of milk yield and energy requirements in the calculation of the fill values of
  concentrates.

  REFERENCES

  <NAME>., <NAME>., <NAME>. & <NAME>. (2011).
  GrazeIn: a model of herbage intake and milk production for grazing dairy
  cows. 1. Prediction of intake capacity, voluntary intake and milk
  production during lactation. Grass and Forage Science 66(1): 29-44.

  <NAME>, <NAME>, <NAME>, P<NAME>L. (2011a). 
  GrazeIn: A model of herbage intake and milk production for grazing dairy cows. 
  2. Prediction of intake under rotational and continuously stocked grazing management. 
  Grass and Forage Science 66: 45–60.

  <NAME>. (2010). Alimentation des bovins, ovins et caprins. Besoins des animaux - Valeurs
  des aliments. Tables INRA 2010. Editions Quae, France.

  Fill values (FV) are expressed in the unit LFU, lactating fill unit (UEL, unite encombrement lait)

  LICENSE

  Copyright 2014 <NAME>   <<EMAIL>>
  Copyright 2014 <NAME> <<EMAIL>>

  Distributed under the MIT License. See accompanying file LICENSE or copy at http://opensource.org/licenses/MIT

  Any publication for which this file or a derived work is used must include an a reference to the article:

  <NAME>., <NAME>., <NAME>., <NAME>. (2014) SOLID-DSS - Eine online-Anwendung zur verbesserten 
  Abstimmung von Grundfutterangebot und -bedarf auf biologisch wirtschaftenden Low Input Milchviehbetrieben.
  In: <NAME>., <NAME>., <NAME>. (eds), Angewandte Forschung und Beratung für den ökologischen Landbau in 
  Bayern: Öko-Landbau-Tag 2014 am 9. April 2014 in Triesdorf; Tagungsband. LfL, Freising-Weihenstephan, pp. 19-22.

  TODO

  - PLPOT in IC and GSR: is it zero for dry cows or still PLPOT?
*/
 
var dairy = dairy || {};

dairy.intake = (function () {

var exp = Math.exp
  , log = Math.log
  , pow = Math.pow
  , Σ = function (a) {
      var sum = 0;
      for (var i = 0, is = a[0].length; i < is; i++)
        sum += a[0][i] * a[1][i];
      return sum;
    }
  ;

function is_null_or_undefined (x) {
  return x === null || x === undefined;
}


/*
  TODO: Funktion rätselhaft, da DMI = Fs + Cs + HI_g

  DMI   [kg]  dry matter intake
  Fs    [kg]  array of feeds
  FVs_f [LFU] array of forage fill values
  Cs    [kg]  array of concentrates
  Cs_f  [LFU] array of concentrate fill values
  FV_h  [LFU] herbage fill value 
  HI_r  [-]   relative herbage intake (0-1)
  HI_g  [kg]  herbage intake at grazing
*/

var DMI = function (Fs, FVs_f, Cs, FVs_c, FV_h, HI_r, HI_g) {

  var DMI = 0
    , DMI_f = Σ([Fs, FVs_f])
    , DMI_c = Σ([Cs, FVs_c])
    ;

  DMI = DMI_f + DMI_c + (FV_h/HI_r * HI_g);

  return DMI;

};

/*
  Agabriel (2010), eq. 2.3

  Equation to calculate the intake capacity.
  
  The intake capacity of the cow is not calculated acc. to Faverdin et al. (2011), because the appearance of MPprot
  (potential milk production modified by protein intake) is problematic since protein intake is unkown at the time of
  feed intake prediction. Instead, the previous Agabriel (2010) version is used:

  In GrazeIn, Pl_pot represents the potential milk yield of a cow, not the actual milk yield. This is done in order
  to avoid milk yield driving feed intake (pull-situation). In SOLID-DSS, values for milk yield are taken from the
  lactation curves modelled within the herd model. These lactation curves are based on input by the user, and thereby
  represent average milk yields instead of actual ones, so they can be interpreted as a potential under the given
  circumstances.

  TODO
    - is PLPOT in ECM?

  IC    [LFU]       intake capacity ~ DMI @ FV = 1
  BW    [kg]        body weight
  PLPOT [kg day-1]  milk yield, potential
  BCS   [-]         body condition score (1-5)
  WL    [week]      week of lactation
  WG    [week]      week of gestation (0-40)
  AGE   [month]     age in month
  p     [#]         parity
*/

var IC = function (BW, PLPOT, BCS, WL, WG, AGE, p) {

  var IC = 0;

  IC = (13.9 + (BW - 600) * 0.015 + PLPOT * 0.15 + (3 - BCS) * 1.5) * IL(p, WL) * IG(WG) * IM(AGE);

  return IC;

}; 

/*
  Agabriel (2010) eq. 2.3f

  The equation for the index of lactation. .

  IL  [-]     index lactation (0-1)
  p   [#]     parity
  WL  [week]  week of lactation
*/

var IL = function IL(p, WL) {

  /* if cow is dry IL = 1 */
  var IL = 1;

  if (p === 1 && WL > 0)
    IL = 0.6 + (1 - 0.6) * (1 - exp(-0.16 * WL));
  else if (p > 1 && WL > 0)
    IL = 0.7 + (1 - 0.7) * (1 - exp(-0.16 * WL));

  return IL;

};

/*
  Agabriel (2010) eq. 2.3f

  The equation for the index of gestation.
  
  IG  [-]     index gestation (0-1)
  WG  [week]  week of gestation (0-40)
*/

var IG = function (WG) {

  return 0.8 + 0.2 * (1 - exp(-0.25 * (40 - WG)));  

};

/*
  Agabriel (2010) eq. 2.3f

  The equation for the index of maturity.
  
  IM  [-]     index maturity (0-1)
  AGE [month] month
*/

var IM = function (AGE) {

  return -0.1 + 1.1 * (1 - exp(-0.08 * AGE));

};

/*
  Agabriel (2010), Table 8.1.

  The general equation for calculating forage fill values.

  The QIL-values are calculated in feed.evaluation, details see there.
  
  FV_f  [LFU kg-1 (DM)] forage fill value (unite encombrement lait)
  QIL   [g kg-1]        ingestibility in g per kg metabolic live weight                
*/

var FV_f = function (QIL) {

  return 140 / QIL;

};

/*
  Faverdin et al. (2011) eq. 11
  
  Equation for calculating concentrate fill value.

  One of the factors influencing the concentrate fill value is the fill value of the forage base.
  Because the total diet is unknown prior to the allocation of feeds, the weighted mean of the FV of all available
  forages for the group of cows and the time period in question is used for FV_fr.

  FV_c  [LFU kg-1 (DM)] concentrate fill value (lactating fill unit, unite encombrement lait)
  FV_fs [LFU]           weighted FV of forages in ration
  GSR   [-]             global substitution rate (0-1)
*/

var FV_c = function (FV_fs, GSR) {

  return FV_fs * GSR;

};

/*
  Baldinger et. al. (xxxx) eq. x

  Equation to estimate the fill value of forages in a diet from the cow's requirements prior to ration optimization.
  This is based on the fact that on average a feed's fill value will descrease with increasing energy content. The 
  estimated FV_fs is used to calculate a concentrate fill value (see FV_cs). We need it if we what to keep the diet LP linear.
  The regression was calculated from all forages available in Agabriel 2010 (r^2 = 0.564, n = 643).

  FV_fs_diet  [LFU kg-1 (DM)] Estimated fill value of forages in diet
  E_fs        [UFL]           Total energy content of forages in diet
  FV_fs       [LFU]           Total fill values of forages in diet
*/

var FV_fs_diet = function (E_fs, FV_fs) {

  return - 0.489 * E_fs / FV_fs + 1.433;

};

/*
  Baldinger et. al. (xxxx) eq. x

  Estimate an average concentrate fill value. We assume that requirements are met i.e. cows with BWC >= 0 have a zero
  energy balance. 

  TODO: 
    - simplify to an equation?
    - use this as a better estimate of DMI instead of DMI = IC (FV ~ 1)?

  FV_cs_diet  [LFU kg-1 (DM)] estimated fill value of concentrates in diet
  E_req       [UFL]           Energy requirements of a cow (in UFL!)
  IC          [LFU]           Intake capacity of a cow
  c_mx        [kg kg-1]       Maximum fraction (DM) of concentrates in diet (optional, defaults to 0.5 which is the 
                              range the INRA system is applicable)
  PLPOT       [kg day-1]      milk yield, potential
  parity      [#]             parity
  BWC         [kg]            body weight change       
*/

var FV_cs_diet = function (E_req, IC, c_mx, PLPOT, parity, BWC) {

  var FV_cs_diet = 0;

  if (is_null_or_undefined(c_mx) || c_mx > 0.5)
    c_mx = 0.5;
      
  var c = 0       /* fraction of conc. in diet [kg (DM) kg-1 (DM)] */
    , c_kg = 0    /* kg conc. in diet */
    , E_f = E_req /* energy requirements covered by forage */
    , IC_f = IC   /* IC covered by forage */
    , c_fvs = []  /* store conc. fill values */
    , c_fv = 0    /* estimated conc. fill value */
    , f_fv = 0    /* estimated forage fill value */
    , s = 0       /* substitution rate */
    ;

  /* fixed to a max. UFL / UEL value observed in feeds */
  if (E_f / IC_f > 1.15)
    E_f = E_req = IC_f * 1.15;  

  while (true) {

    /* staring from a diet with zero kg conc. we add conc. till we reach c_mx */
    s = GSR(c_kg, DEF(E_f, IC_f), PLPOT, parity, BWC);
    f_fv = FV_fs_diet(E_f, IC_f);
    c_fv = f_fv * s;
    c = c_kg / (IC_f / f_fv + c_kg);

    if (c >= c_mx)
      break;

    c_fvs.push(c_fv);

    /* add concentrate to the diet */
    c_kg += 0.5;
    /* we assume the concentrate's UFL content is 1.05. In fact the result is not very sensitive to UFL of conc. */
    E_f = E_req - c_kg * 1.05;
    IC_f = IC - c_kg * c_fv;

  }

  /* average */
  FV_cs_diet = c_fvs.reduce(function (a, b, i, array) { return a + b / array.length; }, 0);

  return FV_cs_diet;

};

/*
  Agabriel (2010) eq. 2.25

  DEF is the average energy density of the forages in the diet, which is calculated as the weighted mean of all
  available forages for the group of cows and the time period in question.

  DEF       [UFL LFU-1]      average energy density of the forages in the diet (can be slightly higher than 1)
  UFL_fs    [UFL kg-1 (DM)]  sum of the energy contents of all available forages
  LFU_fs    [LFU kg-1 (DM)]  sum of the fill values of all available forages
*/

var DEF = function (UFL_fs, LFU_fs) {

  return UFL_fs / LFU_fs;

};

/*
  Agabriel (2010) eq 2.26.

  Both in Agabriel (2010) and in GrazeIn, concentrate fill values not only vary with the fill value of the forage base,
  but also with the amount of concentrates, the milk yield of the cow and the energy balance of the cow, which are
  all incorporated into the calculation of the global substitution rate (GSR). Consequently, concentrate fill values
  and feed intake are calcalated iteratively until the system converges.
  In SOLID-DSS, no iterative calculation is possible because all fill values must stay constant when the linear
  programming starts to allocate feeds. Therefore the simplified version of calculating GSR that can be found in
  Agabriel (2010) was chosen. According to this version, there is one calculation fo GSR when cows are not mobilizing,
  and a different calculation when cows are mobilizing.

  For QI_c, the maximum of concentrates the user is willing to feed is used, because we assume that those cows that are
  mobilizing will receive the maximum concentrate supplementation.

  GSR           [-]         global substitution rate (0-1)
  QI_c          [kg (DM)]   total amount of concentrates that are fed
  DEF           [UFL LFU-1] average energy density of the forages in the diet (can be slightly higher than 1)
  PLPOT         [kg day-1]  milk yield, potential
  parity        [#]         parity
  BWC           [kg]        body weight change
*/

var GSR = function (QI_c, DEF, PLPOT, parity, BWC) {

  var GSR = 0
    , GSR_zero = 0.55
    , d = (parity > 1 ? 1.10 : 0.96)
    ;

  /* should be larger 0 (dry cows have a pot. milk yield as well) */
  if (PLPOT <= 0)
    PLPOT = 0.1;

  GSR_zero = d * pow(PLPOT, -0.62) * exp(1.32 * DEF);

  if (BWC < 0) /* energy balance of the cow is negative, irrespective of the reason */
    GSR = -0.43 + 1.82 * GSR_zero + 0.035 * QI_c - 0.00053 * PLPOT * QI_c;
  else
    GSR = GSR_zero;

  return GSR;

};

/*
  Delagarde et al. (2011) eq. 13
  Equation for relative herbage intake limited by allowance when grazing is rotational.

  When cows are not grazing, all necessary calculations are hereby completed and the feed intake restriction is:
  DMI = sum of fill values of forages and concentrates multiplied with their amount (or share in the diet)
  When cows are grazing, their herbage intake can be restricted by sward availability or by time at grazing.
  For calculating the restriction caused by sward availability, there are two different calculations, one for rotational
  and one for continuous grazing.

  HI_r_ha [-] relative herbage intake limited by herbage allowance when grazing is rotational (0-1)
  HA_r    [-] relative herbage allowance
*/
 
var HI_r_ha = function (HA_r) {

  return 1.08 * (1 - exp(-1.519 * HA_r));

};

/*
  Delagarde et al. (2011) eq. 15

{'fraction_non_alphanumeric': 0.08377170858254666, 'fraction_numerical': 0.025077466311162356, 'mean_word_length': 2.7080828323313293, 'pattern_counts': {'":': 0, '<': 52, '<?xml version=': 0, '>': 62, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4697209', 'n_tokens_mistral': 9899, 'n_tokens_neox': 8857, 'n_words': 3960}