Example #1
0
 /// <summary>
 /// Determines whether [is same as] [the specified other supp].
 /// </summary>
 /// <param name="otherSupp">The other supp.</param>
 /// <returns></returns>
 public bool isSameAs(TSupplement otherSupp)
 {
     return (sName == otherSupp.sName)
     && (IsRoughage == otherSupp.IsRoughage)
     && (DM_Propn == otherSupp.DM_Propn)
     && (DM_Digestibility == otherSupp.DM_Digestibility)
     && (ME_2_DM == otherSupp.ME_2_DM)
     && (EtherExtract == otherSupp.EtherExtract)
     && (CrudeProt == otherSupp.CrudeProt)
     && (DgProt == otherSupp.DgProt)
     && (ADIP_2_CP == otherSupp.ADIP_2_CP)
     && (Phosphorus == otherSupp.Phosphorus)
     && (Sulphur == otherSupp.Sulphur)
     && (AshAlkalinity == otherSupp.AshAlkalinity)
     && (MaxPassage == otherSupp.MaxPassage);
 }
Example #2
0
        /// <summary>
        /// Mix two supplements together and store in Self
        /// Will work if Supp1=this or Supp2=this
        /// This method is only exact if the passage rates of the two supplements are equal
        /// </summary>
        /// <param name="Supp1">The supp1.</param>
        /// <param name="Supp2">The supp2.</param>
        /// <param name="propn1">The propn1.</param>
        public void Mix(TSupplement Supp1, TSupplement Supp2, double propn1)
        {
            if (propn1 >= 0.50)
                IsRoughage = Supp1.IsRoughage;
            else
                IsRoughage = Supp2.IsRoughage;
            double propn2 = 1.0 - propn1;                                  // Proportion of suppt 2 on a FW basis
            double DMpropn1 = MathUtilities.Divide(propn1 * Supp1.DM_Propn, // Proportion of suppt 1 on a DM basis
                      propn1 * Supp1.DM_Propn + propn2 * Supp2.DM_Propn, 0.0);
            double DMpropn2 = 1.0 - DMpropn1;                              // Proportion of suppt 2 on a DM basis

            double CPpropn1;                                               // Proportion of suppt 1 on a total CP basis
            if (propn1 * Supp1.DM_Propn * Supp1.CrudeProt + propn2 * Supp2.DM_Propn * Supp2.CrudeProt > 0.0)
                CPpropn1 = propn1 * Supp1.DM_Propn * Supp1.CrudeProt
                   / (propn1 * Supp1.DM_Propn * Supp1.CrudeProt + propn2 * Supp2.DM_Propn * Supp2.CrudeProt);
            else
                CPpropn1 = propn1;
            double CPpropn2 = 1.0 - CPpropn1;                             // Proportion of suppt 1 on a total CP basis

            DM_Propn = propn1 * Supp1.DM_Propn + propn2 * Supp2.DM_Propn;
            DM_Digestibility = DMpropn1 * Supp1.DM_Digestibility + DMpropn2 * Supp2.DM_Digestibility;
            ME_2_DM = DMpropn1 * Supp1.ME_2_DM + DMpropn2 * Supp2.ME_2_DM;
            EtherExtract = DMpropn1 * Supp1.EtherExtract + DMpropn2 * Supp2.EtherExtract;
            CrudeProt = DMpropn1 * Supp1.CrudeProt + DMpropn2 * Supp2.CrudeProt;
            DgProt = CPpropn1 * Supp1.DgProt + CPpropn2 * Supp2.DgProt;
            ADIP_2_CP = CPpropn1 * Supp1.ADIP_2_CP + CPpropn2 * Supp2.ADIP_2_CP;
            Phosphorus = DMpropn1 * Supp1.Phosphorus + DMpropn2 * Supp2.Phosphorus;
            Sulphur = DMpropn1 * Supp1.Sulphur + DMpropn2 * Supp2.Sulphur;
            AshAlkalinity = DMpropn1 * Supp1.AshAlkalinity + DMpropn2 * Supp2.AshAlkalinity;
            MaxPassage = DMpropn1 * Supp1.MaxPassage + DMpropn2 * Supp2.MaxPassage;
        }
Example #3
0
 /// <summary>
 /// copy consructor
 /// </summary>
 /// <param name="src">The source.</param>
 public TSupplement(TSupplement src)
 {
     Assign(src);
 }
Example #4
0
 /// <summary>
 /// Assigns the specified source supp.
 /// </summary>
 /// <param name="srcSupp">The source supp.</param>
 public void Assign(TSupplement srcSupp)
 {
     if (srcSupp != null)
     {
         sName = srcSupp.sName;
         IsRoughage = srcSupp.IsRoughage;
         DM_Propn = srcSupp.DM_Propn;
         DM_Digestibility = srcSupp.DM_Digestibility;
         ME_2_DM = srcSupp.ME_2_DM;
         EtherExtract = srcSupp.EtherExtract;
         CrudeProt = srcSupp.CrudeProt;
         DgProt = srcSupp.DgProt;
         ADIP_2_CP = srcSupp.ADIP_2_CP;
         Phosphorus = srcSupp.Phosphorus;
         Sulphur = srcSupp.Sulphur;
         AshAlkalinity = srcSupp.AshAlkalinity;
         MaxPassage = srcSupp.MaxPassage;
         Array.Resize(ref FTranslations, srcSupp.FTranslations.Length);
         Array.Copy(srcSupp.FTranslations, FTranslations, srcSupp.FTranslations.Length);
     }
 }
Example #5
0
 /// <summary>
 /// Inserts the specified index.
 /// </summary>
 /// <param name="idx">The index.</param>
 /// <param name="supp">The supp.</param>
 /// <param name="amt">The amt.</param>
 /// <param name="cost">The cost.</param>
 public void Insert(int idx, TSupplement supp, double amt = 0.0, double cost = 0.0)
 {
     Array.Resize(ref fSuppts, fSuppts.Length + 1);
     for (int jdx = fSuppts.Length - 1; jdx > idx; jdx--)
         fSuppts[jdx] = fSuppts[jdx - 1];
     fSuppts[idx] = new TSupplementItem(supp, amt, cost);
 }
Example #6
0
        /// <summary>
        /// Scales the attributes of the members of the supplement so that the weighted
        /// average attributes match those of aveSupp. Ensures that fractional values
        /// remain within the range 0-1
        /// * Assumes that all values are non-negative
        /// </summary>
        /// <param name="scaleToSupp">The scale to supp.</param>
        /// <param name="attrs">The attrs.</param>
        public void RescaleRation(TSupplement scaleToSupp, IList<TSupplement.TSuppAttribute> attrs)
        {
            Array attribs = Enum.GetValues(typeof(TSupplement.TSuppAttribute));
            foreach (TSupplement.TSuppAttribute attr in attribs)  // NB this only works becuase of the way the supplement attributes are ordered, i.e. DM proportion first and CP before dg and ADIP:CP                         }
            {                                                     // i.e. DM proportion first and CP before dg and ADIP:CP
                if (attrs.Contains(attr))
                {
                    double newWtMean = scaleToSupp[attr];

                    if (fSuppts.Length == 1)
                        fSuppts[0][attr] = newWtMean;
                    else
                    {
                        double oldWtMean = 0.0;
                        double totalWeight = 0.0;
                        double fWeight = 0.0;
                        for (int idx = 0; idx < fSuppts.Length; idx++)
                        {
                            switch (attr)
                            {
                                case TSupplement.TSuppAttribute.spaDMP:
                                    fWeight = getFWFract(idx);
                                    break;
                                case TSupplement.TSuppAttribute.spaDG:
                                case TSupplement.TSuppAttribute.spaADIP:
                                    fWeight = getFWFract(idx) * fSuppts[idx].DM_Propn * fSuppts[idx].CrudeProt;
                                    break;
                                default:
                                    fWeight = getFWFract(idx) * fSuppts[idx].DM_Propn;
                                    break;
                            }
                            oldWtMean += fWeight * fSuppts[idx][attr];
                            totalWeight += fWeight;
                        }
                        if (totalWeight > 0.0)
                            oldWtMean /= totalWeight;

                        for (int idx = 0; idx < fSuppts.Length; idx++)
                        {
                            if (totalWeight == 0.0)
                                fSuppts[idx][attr] = newWtMean;
                            else if ((newWtMean < oldWtMean) || (!PROPN_ATTRS.Contains(attr)))
                                fSuppts[idx][attr] *= newWtMean / oldWtMean;
                            else
                                fSuppts[idx][attr] += (1.0 - fSuppts[idx][attr]) * (newWtMean - oldWtMean)
                                                        / (1.0 - oldWtMean);
                        }
                    }
                }
            }
        }
Example #7
0
 /// <summary>
 /// Adds the specified supp.
 /// </summary>
 /// <param name="supp">The supp.</param>
 /// <param name="amt">The amt.</param>
 /// <param name="cost">The cost.</param>
 /// <returns></returns>
 public int Add(TSupplement supp, double amt = 0.0, double cost = 0.0)
 {
     int idx = fSuppts.Length;
     Insert(idx, supp, amt, cost);
     return idx;
 }
Example #8
0
        /// <summary>
        /// Blends the specified source store.
        /// </summary>
        /// <param name="srcStore">The source store.</param>
        /// <param name="transferKg">The transfer kg.</param>
        /// <param name="destStore">The dest store.</param>
        /// <exception cref="System.Exception">Supplement \ + srcStore + \ not recognised</exception>
        public void Blend(string srcStore, double transferKg, string destStore)
        {
            int iSrc = IndexOf(srcStore);
            if (iSrc < 0)
                throw new Exception("Supplement \"" + srcStore + "\" not recognised");

            transferKg = System.Math.Min(transferKg, this[iSrc].Amount);
            if (transferKg > 0.0)
            {
                int iDest = IndexOf(destStore);
                if (iDest < 0)
                {
                    TSupplement newSupp = new TSupplement();
                    newSupp.Assign(this[iSrc]);
                    newSupp.sName = destStore;
                    iDest = AddToStore(0.0, newSupp);
                }
                Transfer(this, iSrc, this, iDest, transferKg);
            }
        }
Example #9
0
        /// <summary>
        /// Adds an amount of a supplement to a store.
        /// * If the store name already exists in the FStores array, the method adds
        /// the supplement to that store.  Otherwise a new store is created.
        /// * The DMP, DMD, MEDM, CP, DG, EE and ADIP2CP parameters may be set to zero,
        /// in which case the default values for the supplement name are used.
        /// Defaults are taken from the current store if the name is already defined,
        /// and from grazSUPP.PAS otherwise.  If defaults cannot be found for a name,
        /// wheat is used as the default composition.
        /// </summary>
        /// <param name="suppKg">Amount (kg fresh weight) of the supplement to be included in the store.</param>
        /// <param name="suppName">Name of the supplement.</param>
        /// <param name="roughage">The roughage.</param>
        /// <param name="DMP">Proportion of the fresh weight which is dry matter   kg/kg FW</param>
        /// <param name="DMD">Dry matter digestibility of the supplement           kg/kg DM</param>
        /// <param name="MEDM">Metabolisable energy content of dry matter           MJ/kg DM</param>
        /// <param name="CP">Crude protein content                                kg/kg DM</param>
        /// <param name="DG">Degradability of the crude protein                   kg/kg CP</param>
        /// <param name="EE">Ether-extractable content                            kg/kg DM</param>
        /// <param name="ADIP2CP">Ratio of acid detergent insoluble protein to CP      kg/kg CP</param>
        /// <param name="phos">Phosphorus content                                   kg/kg DM</param>
        /// <param name="sulf">Sulphur content                                      kg/kg DM</param>
        /// <param name="ashAlk">Ash alkalinity                                       mol/kg DM</param>
        /// <param name="maxPass">Maximum passage rate                                 0-1</param>
        /// <returns>
        /// Index of the supplement in the store
        /// </returns>
        public int AddToStore(double suppKg, string suppName, int roughage = DEFAULT, double DMP = 0.0, double DMD = 0.0,
            double MEDM = 0.0, double CP = 0.0, double DG = 0.0, double EE = 0.0, double ADIP2CP = 0.0,
            double phos = 0.0, double sulf = 0.0, double ashAlk = 0.0, double maxPass = 0.0)
        {
            int idx = IndexOf(suppName);

            TSupplement addSupp = new TSupplement(suppName);

            if (idx >= 0)                             // Work out the composition of the supplement being added
                addSupp.Assign(this[idx]);
            else
                addSupp.DefaultFromName();
            addSupp.sName = suppName.ToLower();

            if (roughage == ROUGHAGE)                 // Override the default composition as required
                addSupp.IsRoughage = true;
            else if (roughage != DEFAULT)
                addSupp.IsRoughage = false;

            if (DMP > 0.0)
                addSupp.DM_Propn = DMP;
            if (DMD > 0.0)
                addSupp.DM_Digestibility = DMD;
            if (MEDM > 0.0)
                addSupp.ME_2_DM = MEDM;
            if (CP > 0.0)
                addSupp.CrudeProt = CP;
            if (DG > 0.0)
                addSupp.DgProt = DG;
            if (EE > 0.0)
                addSupp.EtherExtract = EE;
            if (ADIP2CP > 0.0)
                addSupp.ADIP_2_CP = ADIP2CP;
            if (phos > 0.0)
                addSupp.Phosphorus = phos;
            if (sulf > 0.0)
                addSupp.Sulphur = sulf;
            if (ashAlk > 0.0)
                addSupp.AshAlkalinity = ashAlk;
            if (maxPass > 0.0)
                addSupp.MaxPassage = maxPass;

            if (DMD > 0.0 && MEDM == 0.0)
                addSupp.ME_2_DM = addSupp.DefaultME2DM();
            else if (DMD == 0.0 && MEDM > 0.0)
                addSupp.DM_Digestibility = addSupp.DefaultDMD();

            return AddToStore(suppKg, addSupp);
        }
Example #10
0
        /// <summary>
        /// Reads from strings.
        /// </summary>
        /// <param name="locale">The locale.</param>
        /// <param name="strings">The strings.</param>
        /// <exception cref="System.Exception">
        /// Error reading supplement library - must contain a header line
        /// or
        /// Error reading supplement library - header line is invalid
        /// or
        /// Error reading supplement library - line for  + sNameStr +  is invalid
        /// </exception>
        public void ReadFromStrings(string locale, string[] strings)
        {
            if (strings == null || strings.Length == 0)
                throw new Exception("Error reading supplement library - must contain a header line");

            int iAttrPosn = strings[0].IndexOf('|');       // Every line must have a | character in
            // this column
            string sHdrStr = "Name";
            sHdrStr = sHdrStr.PadRight(iAttrPosn, ' ') + "|" + sATTR_HEADER;

            if (strings[0] != sHdrStr)
                throw new Exception("Error reading supplement library - header line is invalid");

            Clear();

            string sNameStr = "";
            try
            {
                for (int idx = 1; idx < strings.Length; idx++)
                {
                    if (strings[idx].Length < iAttrPosn)
                        continue;
                    sNameStr = strings[idx].Substring(0, iAttrPosn - 1).Trim();
                    string sAttrStr = strings[idx].Substring(iAttrPosn + 1);

                    TSupplement newSupp = new TSupplement();
                    newSupp.sName = sNameStr;
                    newSupp.IsRoughage = sAttrStr[0] == 'Y';
                    sAttrStr = sAttrStr.Remove(0, 1);

                    StringUtilities.TokenDouble(ref sAttrStr, ref newSupp._DM_Propn);
                    StringUtilities.TokenDouble(ref sAttrStr, ref newSupp._DM_Digestibility);
                    StringUtilities.TokenDouble(ref sAttrStr, ref newSupp._ME_2_DM);
                    StringUtilities.TokenDouble(ref sAttrStr, ref newSupp._EtherExtract);
                    StringUtilities.TokenDouble(ref sAttrStr, ref newSupp._CrudeProt);
                    StringUtilities.TokenDouble(ref sAttrStr, ref newSupp._DgProt);
                    StringUtilities.TokenDouble(ref sAttrStr, ref newSupp._ADIP_2_CP);
                    StringUtilities.TokenDouble(ref sAttrStr, ref newSupp._Phosphorus);
                    StringUtilities.TokenDouble(ref sAttrStr, ref newSupp._Sulphur);
                    StringUtilities.TokenDouble(ref sAttrStr, ref newSupp._AshAlkalinity);
                    StringUtilities.TokenDouble(ref sAttrStr, ref newSupp._MaxPassage);

                    sAttrStr = sAttrStr.Trim();
                    string sTransStr;
                    string sTransName;
                    string sLocStr;
                    string sLang;
                    int iBlank = sAttrStr.IndexOf(' ');
                    if (iBlank < 0)
                    {
                        sLocStr = sAttrStr;
                        sTransStr = "";
                    }
                    else
                    {
                        sLocStr = sAttrStr.Substring(0, iBlank);
                        sTransStr = sAttrStr.Substring(iBlank + 1).Trim();
                    }

                    while (sTransStr != "")
                    {
                        StringUtilities.TextToken(ref sTransStr, out sLang);
                        if (sTransStr[0] == ':')
                        {
                            sTransStr = sTransStr.Substring(1);
                            StringUtilities.TextToken(ref sTransStr, out sTransName, true);
                            newSupp.AddTranslation(sLang, sTransName);
                        }
                        if (sTransStr.Length > 0 && sTransStr[0] == ';')
                            sTransStr = sTransStr.Substring(1);
                    }

                    if (sLocStr == "" || GrazParam.InLocale(locale, sLocStr))
                        Add(newSupp, 0.0, 0.0);
                }
            }
            catch (Exception)
            {
                throw new Exception("Error reading supplement library - line for " + sNameStr + " is invalid");
            }
        }
Example #11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TSupplementModel"/> class.
 /// </summary>
 public TSupplementModel()
     : base()
 {
     AddToStore(0.0, FODDER, ROUGHAGE);
     fSuppts[0].DM_Propn = 0.85;
     FCurrPaddSupp = new TSupplement();
 }
Example #12
0
        /// <summary>
        /// Transfers the specified source.
        /// </summary>
        /// <param name="src">The source.</param>
        /// <param name="srcIdx">Index of the source.</param>
        /// <param name="dest">The dest.</param>
        /// <param name="destIdx">Index of the dest.</param>
        /// <param name="amount">The amount.</param>
        /// <exception cref="System.Exception">Invalid transfer of feed</exception>
        private void Transfer(TSupplementRation src, int srcIdx, TSupplementRation dest, int destIdx, double amount)
        {
            if (srcIdx < 0 || srcIdx >= src.Count || destIdx < 0 || destIdx > dest.Count)
                throw new Exception("Invalid transfer of feed");

            if (amount > 0.0)
            {
                if (destIdx < dest.Count)
                    SuppIntoRation(dest, destIdx, src[srcIdx], amount);
                else
                {
                    TSupplement copy = new TSupplement();
                    copy.Assign(src[srcIdx]);
                    dest.Add(copy, amount);
                }
                src[srcIdx].Amount -= amount;
            }
        }
Example #13
0
 /// <summary>
 /// Supps the into ration.
 /// </summary>
 /// <param name="ration">The ration.</param>
 /// <param name="idx">The index.</param>
 /// <param name="supp">The supp.</param>
 /// <param name="amount">The amount.</param>
 private void SuppIntoRation(TSupplementRation ration, int idx, TSupplement supp, double amount)
 {
     if (amount > 0.0)
     {
         double propn = amount / (amount + ration[idx].Amount);
         ration[idx].Mix(supp, ration[idx], propn);
         ration[idx].Amount += amount;
     }
 }
Example #14
0
 /// <summary>
 /// Mixes the many.
 /// </summary>
 /// <param name="supps">The supps.</param>
 /// <param name="amounts">The amounts.</param>
 public void MixMany(TSupplement[] supps, double[] amounts)
 {
     double amountSum = 0.0;
     for (int idx = 0; idx < supps.Length; idx++)
     {
         if (idx < amounts.Length && amounts[idx] > 0.0)
         {
             Mix(supps[idx], this, amounts[idx] / (amountSum + amounts[idx]));
             amountSum += amounts[idx];
         }
     }
 }
Example #15
0
 /// <summary>
 /// Computes a weighted average supplement composition
 /// </summary>
 /// <param name="aveSupp">receives the average supplement composition</param>
 public void AverageSuppt(out TSupplement aveSupp)
 {
     aveSupp = new TSupplement();
     if (TotalAmount > 0.0)
         aveSupp.MixMany(fSuppts);
 }
Example #16
0
 /// <summary>
 /// Constructor
 /// Note that it makes a copy of the TSupplement
 /// </summary>
 /// <param name="src">The source.</param>
 /// <param name="amt">The amt.</param>
 /// <param name="cst">The CST.</param>
 public TSupplementItem(TSupplement src, double amt = 0.0, double cst = 0.0)
     : base(src)
 {
     Amount = amt;
     Cost = cst;
 }
Example #17
0
 /// <summary>
 /// Adds to store.
 /// </summary>
 /// <param name="suppKg">The supp kg.</param>
 /// <param name="suppComp">The supp comp.</param>
 /// <returns></returns>
 /// <exception cref="System.Exception">Supplement submodel: cannot combine roughage and concentrate, both named  + suppComp.sName</exception>
 public int AddToStore(double suppKg, TSupplement suppComp)
 {
     int suppIdx = IndexOf(suppComp.sName);
     if (suppIdx < 0)
         suppIdx = Add(suppComp, suppKg);
     else if (suppKg > 0.0)
     {
         if (suppComp.IsRoughage != fSuppts[suppIdx].IsRoughage)
             throw new Exception("Supplement submodel: cannot combine roughage and concentrate, both named " + suppComp.sName);
         SuppIntoRation(this, suppIdx, suppComp, suppKg);
     }
     return suppIdx;
 }