예제 #1
0
        private static List <PowerPlantModel> CalculateCostAndMaxPower(PlanCommand request)
        {
            var powerPlantWithCosts = request.PowerPlants.Select(x => new PowerPlantModel
            {
                Name       = x.Name,
                Type       = x.Type,
                Efficiency = x.Efficiency,
                PMax       = x.PMax,
                PMin       = x.PMin,
                Power      = GetMaxPower(x, request.Fuels), // the max power that a powerplant can generate
                Cost       = GetCost(x, request.Fuels)      // total cost
            }).ToList();

            return(powerPlantWithCosts);
        }
예제 #2
0
        public async Task <List <UnitCommitmentModel> > Handle(PlanCommand request, CancellationToken cancellationToken)
        {
            return(await Task.Run(() =>
            {
                var uc = new List <UnitCommitmentModel>();
                var expectedLoad = request.Load;
                var producedLoad = 0M;

                var powerPlantWithCosts = CalculateCostAndMaxPower(request);

                if (powerPlantWithCosts.Sum(x => x.Power) < request.Load)
                {
                    throw new PlanCommandException("The expected load cannot be fulfilled");
                }
                // merit-order
                var powerPlantsThatCanProducePower = powerPlantWithCosts.Where(x => x.Power > 0)
                                                     .OrderBy(x => x.Cost) // privilege the cheapest and the more efficient (Efficiency is taken in account)
                                                     .ThenByDescending(x => x.Power)
                                                     .ThenBy(x => x.PMin);

                var powerPlantsThatCannotProducePower = powerPlantWithCosts.Where(x => x.Power <= 0); // Wind-turbine when % of wind = 0


                foreach (var p in powerPlantsThatCanProducePower)
                {
                    if (producedLoad < expectedLoad)
                    {
                        // calculate the power to generate
                        var powerToGenerate = p.Power + producedLoad > expectedLoad
                            ? (expectedLoad - producedLoad < p.PMin ? p.PMin : expectedLoad - producedLoad)
                            : p.Power;

                        // if we are note above the load
                        if (producedLoad + powerToGenerate <= expectedLoad)
                        {
                            uc.Add(new UnitCommitmentModel()
                            {
                                Name = p.Name,
                                Power = powerToGenerate
                            });
                            producedLoad += powerToGenerate;
                        }
                        else
                        {
                            //The load is not yet reached and if we take the max power of the next powerplants in the list
                            // we will exceed the expected load.
                            // so the rest of load (to achieve the expected load) need to be balanced between the 2 lats poweplants
                            var last = uc.Last();
                            uc.Remove(last);
                            // adjust the amount of the power that powerplant should produce
                            // taking in account the Pmin of the next powerplant that should be switched on
                            var actualPower = uc.Sum(x => x.Power) + p.PMin;
                            uc.Add(new UnitCommitmentModel()
                            {
                                Name = last.Name,
                                Power = expectedLoad - actualPower
                            });

                            uc.Add(new UnitCommitmentModel()
                            {
                                Name = p.Name,
                                Power = p.PMin // take the minimum of the capacity when switched on (more expensive)
                            });
                        }
                    }
                    else
                    {
                        // Should be switched off
                        uc.Add(new UnitCommitmentModel()
                        {
                            Name = p.Name,
                            Power = 0
                        });
                    }
                }

                // the powerplants that should not be switched on
                foreach (var p in powerPlantsThatCannotProducePower)
                {
                    uc.Add(new UnitCommitmentModel()
                    {
                        Name = p.Name,
                        Power = 0
                    });
                }

                // TODO handle this case
                if (uc.Sum(x => x.Power) > request.Load)
                {
                    // TODO
                }

                return uc;
            }, cancellationToken));
        }