示例#1
0
 public void TestInitialize()
 {
     _validator = new ProductionPlanValidator();
 }
        /// <summary>
        /// Calculate the output power for each powerplant in order to supply the requested load
        /// </summary>
        public IEnumerable <PowerPlantLoad> CalculateUnitCommitment(ProductionPlan productionPlan)
        {
            if (productionPlan == null)
            {
                _logger.LogError("The production plan should not be null");
                throw new ArgumentNullException(nameof(productionPlan), "The production plan should not be null");
            }

            var validator = new ProductionPlanValidator();

            validator.ValidateAndThrow(productionPlan);

            // Create PowerPlantLoad and order it by merit order and maximum power
            var powerPlantLoadsByMeritOrder = productionPlan.PowerPlants
                                              .OrderBy(p => CalculatePricePerMWh(p, productionPlan.Fuels))
                                              .ThenByDescending(p => p.PMax)
                                              .Select(p => new PowerPlantLoad(p.Name, p.Type, p.PMin, p.PMax, productionPlan.Fuels.WindPercentage, 0))
                                              .ToList();

            // Check if there is at least one powerplant which has a minimum power less than or equal to the requested load
            var smallestPMin = powerPlantLoadsByMeritOrder.Min(p => p.RealPMin);

            if (productionPlan.Load < smallestPMin)
            {
                throw new ImpossibleToSupplyException(
                          productionPlan.Load,
                          $"All powerplants have a PMin greater than the requested load (smallest PMin {smallestPMin})"
                          );
            }

            // Check if the maximum real power of all powerplants is greater than or equal to the requested load
            var totalPMaxPossible = powerPlantLoadsByMeritOrder.Sum(p => p.RealPMax);

            if (productionPlan.Load > totalPMaxPossible)
            {
                throw new ImpossibleToSupplyException(
                          productionPlan.Load,
                          $"The sum of all PMax is lesser than the requested load (total PMax {totalPMaxPossible})"
                          );
            }

            // Find best output power for each powerplant
            var remainingLoadToPlan = productionPlan.Load;

            for (var i = 0; i < powerPlantLoadsByMeritOrder.Count; i++)
            {
                var(power, newRemainingLoadToPlan) = CalculateOutputPowerPlant(
                    powerPlantLoadsByMeritOrder[i],
                    powerPlantLoadsByMeritOrder.Take(i),
                    remainingLoadToPlan
                    );

                remainingLoadToPlan = newRemainingLoadToPlan;
                powerPlantLoadsByMeritOrder[i].ChangePower(power);

                // No more power to find
                if (remainingLoadToPlan == 0)
                {
                    break;
                }
            }

            // If there is some remaining load, it's not possible to find a solution
            if (remainingLoadToPlan > 0)
            {
                throw new ImpossibleToSupplyException(
                          productionPlan.Load,
                          "No combination of powerplants allows to obtain it"
                          );
            }

            return(powerPlantLoadsByMeritOrder);
        }