/// <summary>
        /// Builds the Throughput
        /// </summary>
        /// <param name="replacementLevel">replacement Level</param>
        /// <param name="rticleaningLevel">rti cleaning Level</param>
        /// <param name="startingSaltSplit">starting Salt Split</param>
        /// <param name="randomGrains">random Grains</param>
        /// <param name="amountOfResin">amount Of Resin</param>
        /// <param name="cleaningEffectivness">cleaning Effectivness</param>
        /// <param name="trainGPM">train GPM</param>
        /// <param name="ageOfResin">age Of Resin</param>
        /// <param name="newResinSaltSplit">new Resin Salt Split</param>
        /// <param name="lifeExpectancy">life Expectancy</param>
        /// <param name="isCleaning">is Cleaning</param>
        /// <param name="isReplacing">is Replacing</param>
        /// <returns>Returns the throughput data</returns>
        public Dictionary<DateTime, Tuple<int, double, string>> ThroughputBuild(double replacementLevel, double rticleaningLevel, double startingSaltSplit, Dictionary<int, double> randomGrains, double amountOfResin, double cleaningEffectivness, double trainGPM, double ageOfResin, double newResinSaltSplit, double lifeExpectancy, bool isCleaning, bool isReplacing, List<double> hoursPerRun)
        {
            try
            {
                replacementLevel = 10.00;
                rticleaningLevel = 17.00;
                Dictionary<DateTime, Tuple<int, double, string>> tpPrediction = new Dictionary<DateTime, Tuple<int, double, string>>();
                TOCBuilder toc = new TOCBuilder();
                PreviousWeek lastWeeks = new PreviousWeek();
                DateTime date = new DateTime();
                date = DateTime.Now.Date;
                double effectiveResinAge = ageOfResin;
                double origionalCleaningLevel = replacementLevel;
                int simulationDuration = 104;
                int weekNumber = 1;
                int lastCleaningWeek = 0; // Keep track of the last week a cleaning was performed
                double cleaningInterval = 52; // Spacing between cleanings

                foreach (var week in randomGrains)
                {
                    if (weekNumber <= simulationDuration) // Ensure simulation does not exceed 130 weeks (2.5 years)
                    {
                        // Calculte data for the very first week in the simulation
                        if (week.Key == randomGrains.FirstOrDefault().Key)
                        {
                            Tuple<int, double, string> weekTpPair = CalculateFirstWeek(toc, isCleaning, startingSaltSplit, amountOfResin, week, trainGPM, ageOfResin, lastWeeks, hoursPerRun);
                            tpPrediction.Add(date, weekTpPair);
                            lastWeeks.Date = date;
                        }
                        else if (isCleaning)
                        {
                            date = lastWeeks.Date.AddDays(7);
                            effectiveResinAge += 1;

                            // NORMAL OPS
                            if (lastWeeks.SaltSplit > rticleaningLevel && (Convert.ToInt32(week.Key) - lastCleaningWeek <= cleaningInterval))
                            {
                                Tuple<int, double, string> weekTpPair = NormalOpsWeek(isCleaning, trainGPM, lifeExpectancy, toc, effectiveResinAge, amountOfResin, week, randomGrains, lastWeeks, newResinSaltSplit, hoursPerRun);
                                tpPrediction.Add(date, weekTpPair);
                                lastWeeks.Date = date;
                            }

                            // CLEANING WEEK
                            else if ((lastWeeks.SaltSplit > replacementLevel) && (lastWeeks.SaltSplit < rticleaningLevel) || lastCleaningWeek == 0)
                            {
                                effectiveResinAge = effectiveResinAge - (effectiveResinAge * cleaningEffectivness * 0.01);
                                Tuple<int, double, string> weekTpPair = CleanOpsWeek(toc, effectiveResinAge, amountOfResin, week, cleaningEffectivness, newResinSaltSplit, lastWeeks, trainGPM, hoursPerRun, lifeExpectancy);
                                //rticleaningLevel = PostCleaningSaltSPlitReduction(rticleaningLevel, replacementLevel, cleaningEffectivness, lastWeeks);
                                tpPrediction.Add(date, weekTpPair);
                                lastWeeks.Date = date;
                                if (lastCleaningWeek != 0)
                                    cleaningInterval = cleaningInterval - cleaningInterval * (rticleaningLevel / 100);
                                lastCleaningWeek = week.Key;
                            }

                            //if (week.Key > 169)
                            //{
                            //    // break
                            //}

                            //// REPLACEMENT WEEK
                            //else
                            //{
                            //    if (isReplacing)
                            //    {
                            //        effectiveResinAge = 1;
                            //        Tuple<int, double, string> weekTpPair = ReplaceOpsWeek(isCleaning, trainGPM, lifeExpectancy, toc, effectiveResinAge, newResinSaltSplit, amountOfResin, week, lastWeeks, hoursPerRun);
                            //        rticleaningLevel = origionalCleaningLevel;   // Restore the cleaning level upon resin replacement
                            //        tpPrediction.Add(date, weekTpPair);
                            //        lastWeeks.Date = date;
                            //    }
                            //    else
                            //    {
                            //        Tuple<int, double, string> weekTpPair = NormalOpsWeek(isCleaning, trainGPM, lifeExpectancy, toc, effectiveResinAge, amountOfResin, week, randomGrains, lastWeeks, newResinSaltSplit, hoursPerRun);
                            //        tpPrediction.Add(date, weekTpPair);
                            //        lastWeeks.Date = date;
                            //    }
                            //}
                        }
                        else  // If not the first week and you are not performing cleanings, calculate data
                        {
                            date = lastWeeks.Date.AddDays(7);
                            effectiveResinAge += 1;

                            // NORMAL OPS
                            if (lastWeeks.SaltSplit > replacementLevel || isReplacing)
                            {
                                Tuple<int, double, string> weekTpPair = NormalOpsWeek(isCleaning, trainGPM, lifeExpectancy, toc, effectiveResinAge, amountOfResin, week, randomGrains, lastWeeks, newResinSaltSplit, hoursPerRun);
                                tpPrediction.Add(date, weekTpPair);
                                lastWeeks.Date = date;
                            }

                            // REPLACEMENT WEEK
                            else
                            {
                                effectiveResinAge = 1;
                                Tuple<int, double, string> weekTpPair = ReplaceOpsWeek(isCleaning, trainGPM, lifeExpectancy, toc, effectiveResinAge, newResinSaltSplit, amountOfResin, week, lastWeeks, hoursPerRun);
                                tpPrediction.Add(date, weekTpPair);
                                lastWeeks.Date = date;
                            }
                        }
                    }
                    weekNumber++;
                }
                return tpPrediction;
            }
            catch
            {
                throw;
            }
        }
        /// <summary>
        /// Replace Ops Week
        /// </summary>
        /// <param name="isCleaning">is Cleaning parameter</param>
        /// <param name="trainGpm">train GPM parameter</param>
        /// <param name="lifeExpectancy">life Expectancy</param>
        /// <param name="toc">toc parameter</param>
        /// <param name="effectiveResinAge">effective Resin Age</param>
        /// <param name="newResinSaltSplit">new Resin Salt Split</param>
        /// <param name="amountOfResin">amount Of Resin</param>
        /// <param name="grains">grains parameter</param>
        /// <param name="lastWeeks">last Weeks</param>
        /// <returns></returns>
        private Tuple<int, double, string> ReplaceOpsWeek(bool isCleaning, double trainGPM, double lifeExpectancy, TOCBuilder toc, double effectiveResinAge, double newResinSaltSplit, double amountOfResin, KeyValuePair<int, double> grains, PreviousWeek lastWeeks, List<double> hoursPerRun)
        {
            try
            {
                //lifeExpectancy = 0;
                //double regenerationTime = toc.RegenTimeCurve(lifeExpectancy) / 60;
                //double saltSplit = newResinSaltSplit;
                //lastWeeks.SaltSplit = saltSplit;

                // Determines the number of trains being analyzed
                int numberOfTrains = hoursPerRun.Count();

                // Get the most recent salt split level
                lastWeeks.SaltSplit = newResinSaltSplit;

                // Calculate the systems grain capacity in one run
                double grainCapacityPerRun = lastWeeks.SaltSplit * 1000 * (amountOfResin / numberOfTrains);

                // Calculate the throughput based on this weeks salt split
                double throughput = grainCapacityPerRun / grains.Value;

                // Calculate the system run time  (hours per run)
                double hoursRunTime = throughput / (trainGPM * 60);

                // Add in the regeneration time in hours
                double hoursTotalTime = hoursRunTime + hoursPerRun.Average();

                // Calculate the number of runs per week
                double numberOfHoursInWeek = 7 * 24;
                double runsPerWeek = numberOfHoursInWeek / hoursTotalTime;

                // Set data
                lastWeeks.HoursPerRun = hoursRunTime;
                lastWeeks.RegPerWeek = runsPerWeek;

                Tuple<int, double, string> weekTpPair = new Tuple<int, double, string>(grains.Key, throughput, "Replace");
                lastWeeks.TpData = weekTpPair;
                double silicaFactor = RandomNumberGenerator.Between(97, 100);

                // Calculate the number of regenerations in this week
                if (throughput == 0)
                {
                    lastWeeks.RegPerWeek = 0;
                    lastWeeks.HoursPerRun = 0.0001 * (silicaFactor * 0.01);
                }

                Tuple<double, double, double, double, double, double> regenData = new Tuple<double, double, double, double, double, double>(grains.Key, lastWeeks.RegPerWeek, lastWeeks.HoursPerRun, hoursPerRun.Average(), throughput, lastWeeks.SaltSplit);
                if (isCleaning)
                {
                    this.AfterSystemConditions.Add(regenData);
                }
                else
                {
                    this.BeforeSystemConditions.Add(regenData);
                }
                return weekTpPair;
            }
            catch
            {
                throw;
            }
        }
        /// <summary>
        /// Clean Ops Week
        /// </summary>
        /// <param name="toc">toc parameter</param>
        /// <param name="effectiveResinAge">effective Resin Age</param>
        /// <param name="amountOfResin">amount Of Resin</param>
        /// <param name="grains">grains parameter</param>
        /// <param name="cleaningEffectivness"></param>
        /// <param name="newResinSaltSplit">new Resin Salt Split</param>
        /// <param name="lastWeeks">last Weeks parameter</param>
        /// <returns>Returns the Clean ops week</returns>
        private Tuple<int, double, string> CleanOpsWeek(TOCBuilder toc, double effectiveResinAge, double amountOfResin, KeyValuePair<int, double> grains, double cleaningEffectivness, double newResinSaltSplit, PreviousWeek lastWeeks, double trainGPM, List<double> hoursPerRun, double lifeExpectancy)
        {
            try
            {

                double saltSplit = fetchSaltSplitLevel(effectiveResinAge, lifeExpectancy, newResinSaltSplit);

                //double saltSplit = lastWeeks.SaltSplit + (lastWeeks.SaltSplit * cleaningEffectivness * 0.01);
                //if (saltSplit > newResinSaltSplit)
                //{
                //    saltSplit = newResinSaltSplit;
                //}
                //double percentIncrease = (saltSplit - lastWeeks.SaltSplit) / lastWeeks.SaltSplit;
                //effectiveResinAge = effectiveResinAge - (effectiveResinAge * percentIncrease);
                //double regenerationTime = toc.RegenTimeCurve(effectiveResinAge) / 60;

                // Determines the number of trains being analyzed
                int numberOfTrains = hoursPerRun.Count();

                // Get the most recent salt split level
                lastWeeks.SaltSplit = saltSplit;

                // Calculate the systems grain capacity in one run
                double grainCapacityPerRun = lastWeeks.SaltSplit * 1000 * (amountOfResin / numberOfTrains);

                // Calculate the throughput based on this weeks salt split
                double throughput = grainCapacityPerRun / grains.Value;

                // Calculate the system run time  (hours per run)
                double hoursRunTime = throughput / (trainGPM * 60);

                // Add in the regeneration time in hours
                double hoursTotalTime = hoursRunTime + hoursPerRun.Average();

                // Calculate the number of runs per week
                double numberOfHoursInWeek = 7 * 24;
                double runsPerWeek = numberOfHoursInWeek / hoursTotalTime;

                // Set data
                lastWeeks.HoursPerRun = hoursRunTime;
                lastWeeks.RegPerWeek = runsPerWeek;

                Tuple<int, double, string> weekTpPair = new Tuple<int, double, string>(grains.Key, throughput, "Clean");
                lastWeeks.TpData = weekTpPair;
                Tuple<double, double, double, double, double, double> regenData = new Tuple<double, double, double, double, double, double>(grains.Key, lastWeeks.RegPerWeek, lastWeeks.HoursPerRun, hoursPerRun.Average(), throughput, lastWeeks.SaltSplit);
                this.AfterSystemConditions.Add(regenData);
                return weekTpPair;
            }
            catch
            {
                throw;
            }
        }
        /// <summary>
        /// Post Cleaning SaltSPlit Reduction
        /// </summary>
        /// <param name="cleaningSaltSplit">cleaning SaltSplit</param>
        /// <param name="replaceSaltSplit">replace SaltSplit</param>
        /// <returns>Returns the salt split reduction</returns>
        private double PostCleaningSaltSPlitReduction(double cleaningSaltSplit, double replaceSaltSplit, double cleaningEffectiveness, PreviousWeek lastWeeks)
        {
            try
            {
                double afterReductionSS = cleaningSaltSplit;

                if(lastWeeks.SaltSplit < afterReductionSS){
                    afterReductionSS = lastWeeks.SaltSplit - (lastWeeks.SaltSplit * (cleaningEffectiveness * 0.01));
                }
                return afterReductionSS;
            }
            catch
            {
                throw;
            }
        }
Пример #5
0
        /// <summary>
        /// Normal Ops Week
        /// </summary>
        /// <param name="isCleaning">is Cleaning</param>
        /// <param name="trainGPM">train GPM parameter</param>
        /// <param name="lifeExpectancy">life Expectancy</param>
        /// <param name="toc">toc parameter</param>
        /// <param name="effectiveResinAge">effective Resin Age</param>
        /// <param name="amountOfResin">amount Of Resin</param>
        /// <param name="grains">grains parameter</param>
        /// <param name="randomGrains">random Grains</param>
        /// <param name="lastWeeks">last Weeks</param>
        /// <param name="newResinSS">new Resin SS</param>
        /// <returns>Returns the normal ops week</returns>
        private Tuple<int, double, string> NormalOpsWeek(bool isCleaning, double trainGPM, double lifeExpectancy, TOCBuilder toc, double effectiveResinAge, double amountOfResin, KeyValuePair<int, double> grains, Dictionary<int, double> randomGrains, PreviousWeek lastWeeks, double newResinSS, double regenTime, bool isAllTrains, int numberTrains)
        {
            try
            {
                // Get the current weeks salt split level
                double saltSplit = fetchSaltSplitLevel(effectiveResinAge,lifeExpectancy,newResinSS);
                lastWeeks.SaltSplit = saltSplit;

                // Determines the number of trains being analyzed
                int numberOfTrains = isAllTrains ? numberTrains : 1;

                // Get the most recent salt split level
                lastWeeks.SaltSplit = saltSplit;

                // Calculate the systems grain capacity in one run
                double grainCapacityPerRun = lastWeeks.SaltSplit * 1000 * (amountOfResin / numberOfTrains);

                // Calculate the throughput based on this weeks salt split
                double throughput = grainCapacityPerRun / grains.Value;

                // Calculate the system run time  (hours per run)
                double hoursRunTime = throughput / (trainGPM * 60);

                // Add in the regeneration time in hours
                double hoursTotalTime = hoursRunTime + regenTime;

                // Calculate the number of runs per week
                double numberOfHoursInWeek = 7 * 24;
                double runsPerWeek = numberOfHoursInWeek / hoursTotalTime;

                // Set data
                lastWeeks.RegPerWeek = runsPerWeek;
                lastWeeks.HoursPerRun = hoursRunTime;

               // if (throughput <= 0 && lastWeeks != null && lastWeeks.TpData != null)
               // {
               //     throughput = lastWeeks.TpData.Item2;
               // }

                Tuple<int, double, string> weekTpPair = new Tuple<int, double, string>(grains.Key, throughput, "Normal");
                lastWeeks.TpData = weekTpPair;

                //double silicaFactor = RandomNumberGenerator.Between(97, 100);
                //if (throughput == 0)
                //{
                //    lastWeeks.HoursPerRun = 0.0001 * (silicaFactor * 0.01);
                //    lastWeeks.RegPerWeek = 0;
                //}

                Tuple<double, double, double, double, double, double> regenData = new Tuple<double, double, double, double, double, double>(grains.Key, lastWeeks.RegPerWeek, lastWeeks.HoursPerRun, regenTime, throughput, lastWeeks.SaltSplit);
                if (isCleaning)
                {
                    this.AfterSystemConditions.Add(regenData);
                }
                else
                {
                    this.BeforeSystemConditions.Add(regenData);
                }
                return weekTpPair;
            }
            catch
            {
                throw;
            }
        }