Exemplo n.º 1
0
        protected override void RunActualProcess([NotNull] ScenarioSliceParameters slice)
        {
            var dbSrcHouses = Services.SqlConnectionPreparer.GetDatabaseConnection(Stage.Houses, slice.PreviousSliceNotNull);
            var dbDstHouses = Services.SqlConnectionPreparer.GetDatabaseConnection(Stage.Houses, slice);

            dbDstHouses.RecreateTable <DHWHeaterEntry>();
            var srcdhwsystems = dbSrcHouses.Fetch <DHWHeaterEntry>();

            dbDstHouses.BeginTransaction();
            WeightedRandomAllocator <DHWHeaterEntry> dhwAllocator = new WeightedRandomAllocator <DHWHeaterEntry>(Services.Rnd, Services.Logger);
            int numberOfObjects = (int)slice.DHWSystemConversionNumber;
            var electricBoilers = srcdhwsystems.Where(x => x.DhwHeatingSystemType == DhwHeatingSystem.Electricity).ToList();

            if (electricBoilers.Count == 0 && numberOfObjects > 0)
            {
                throw new FlaException("No electric boilers left when trying to allocate " + numberOfObjects);
            }

            bool failOnOversubscribe = slice.DstYear != 2050;
            var  systemsToChange     = dhwAllocator.PickNumberOfObjects(srcdhwsystems, x => x.EffectiveEnergyDemand, numberOfObjects, failOnOversubscribe);

            foreach (var entry in systemsToChange)
            {
                entry.DhwHeatingSystemType  = DhwHeatingSystem.Heatpump;
                entry.EffectiveEnergyDemand = entry.EffectiveEnergyDemand / 3;
            }

            foreach (var dhw in srcdhwsystems)
            {
                dhw.ID = 0;
                dbDstHouses.Save(dhw);
            }

            dbDstHouses.CompleteTransaction();
        }
        protected override void RunActualProcess([NotNull] ScenarioSliceParameters slice)
        {
            var dbSrcHouses = Services.SqlConnectionPreparer.GetDatabaseConnection(Stage.Houses, slice.PreviousSliceNotNull);
            var dbDstHouses = Services.SqlConnectionPreparer.GetDatabaseConnection(Stage.Houses, slice);

            dbDstHouses.RecreateTable <AirConditioningEntry>();
            var srcAirconditioningEntries = dbSrcHouses.Fetch <AirConditioningEntry>();
            var srcHouses       = dbSrcHouses.Fetch <House>();
            var airConGuids     = srcAirconditioningEntries.Select(x => x.HouseGuid).ToList();
            var hausanschlusess = dbSrcHouses.Fetch <Hausanschluss>();
            var businesses      = dbDstHouses.Fetch <BusinessEntry>();
            var housesWithoutAirconditioning1 = srcHouses.Where(x => !airConGuids.Contains(x.Guid)).ToList();

            if (housesWithoutAirconditioning1.Count == 0)
            {
                throw new FlaException("no houses left without airconditioning");
            }

            foreach (var conditioningEntry in srcAirconditioningEntries)
            {
                conditioningEntry.HausAnschlussGuid.Should().NotBeNullOrWhiteSpace();
                var ha = hausanschlusess.First(x => x.Guid == conditioningEntry.HausAnschlussGuid);
                if (ha.ObjectID.ToLower().Contains("kleinanschluss"))
                {
                    throw new FlaException("No ac at kleinanschluss");
                }
            }

            // ReSharper disable once ArrangeLocalFunctionBody
            double CalculateYearlyAirConditioningEnergyConsumption(House h) =>
            h.EnergieBezugsFläche * slice.AirConditioningEnergyIntensityInKWhPerSquareMeter;

            double totalEbf = srcHouses.Sum(x => x.EnergieBezugsFläche);
            double totalTargetAirConditioning =
                totalEbf * slice.PercentageOfAreaWithAirConditioning * slice.AirConditioningEnergyIntensityInKWhPerSquareMeter;
            double currentAirConditioning = srcAirconditioningEntries.Sum(x => x.EffectiveEnergyDemand);
            double newlyInstealledEnergyForAirconditioning = totalTargetAirConditioning - currentAirConditioning;

            if (newlyInstealledEnergyForAirconditioning < 0)
            {
                throw new FlaException("Negative air conditioning target. Currently installed in " + slice + " are " +
                                       currentAirConditioning / (totalEbf * slice.AirConditioningEnergyIntensityInKWhPerSquareMeter));
            }

            bool failOnOver = slice.DstYear != 2050;
            WeightedRandomAllocator <House> allocator = new WeightedRandomAllocator <House>(Services.Rnd, Services.Logger);
            var housesForAirConditioning = allocator.PickObjectUntilLimit(housesWithoutAirconditioning1,
                                                                          x => x.EnergieBezugsFläche,
                                                                          CalculateYearlyAirConditioningEnergyConsumption,
                                                                          newlyInstealledEnergyForAirconditioning,
                                                                          failOnOver);
            var dstAirConditioningEntries = new List <AirConditioningEntry>();

            foreach (var house in housesForAirConditioning)
            {
                var businessesInHouse   = businesses.Where(x => x.HouseGuid == house.Guid).ToList();
                AirConditioningType act = AirConditioningType.Commercial;
                if (businessesInHouse.Count == 0)
                {
                    act = AirConditioningType.Residential;
                }

                foreach (var entry in businessesInHouse)
                {
                    if (entry.BusinessType == BusinessType.Industrie)
                    {
                        act = AirConditioningType.Industrial;
                    }
                }

                Hausanschluss ha = house.GetHausanschlussByIsn(new List <int>(), null, hausanschlusess, MyLogger, false);
                if (ha != null && ha.ObjectID.ToLower().Contains("kleinanschluss"))
                {
                    ha = null;
                }

                if (ha != null)
                {
                    var ace = new AirConditioningEntry(house.Guid,
                                                       Guid.NewGuid().ToString(),
                                                       CalculateYearlyAirConditioningEnergyConsumption(house),
                                                       1,
                                                       act,
                                                       ha.Guid,
                                                       house.ComplexName + " - Air Conditioning",
                                                       "");
                    dstAirConditioningEntries.Add(ace);
                }
            }

            foreach (var airconditioningEntry in srcAirconditioningEntries)
            {
                airconditioningEntry.ID = 0;
                dstAirConditioningEntries.Add(airconditioningEntry);
            }

            //final checks
            foreach (var dstAirConditioningEntry in dstAirConditioningEntries)
            {
                dstAirConditioningEntry.HausAnschlussGuid.Should().NotBeNullOrWhiteSpace();
                var ha = hausanschlusess.First(x => x.Guid == dstAirConditioningEntry.HausAnschlussGuid);
                if (ha.ObjectID.ToLower().Contains("kleinanschluss"))
                {
                    throw new FlaException("No ac at kleinanschluss");
                }
            }

            dbDstHouses.BeginTransaction();
            foreach (var airConditioningEntry in dstAirConditioningEntries)
            {
                dbDstHouses.Save(airConditioningEntry);
            }

            dbDstHouses.CompleteTransaction();
        }
Exemplo n.º 3
0
        protected override void RunActualProcess([NotNull] ScenarioSliceParameters parameters)
        {
            Services.SqlConnection.RecreateTable <HeatingSystemEntry>(Stage.Houses, parameters);
            var dbSrcHouses       = Services.SqlConnection.GetDatabaseConnection(Stage.Houses, parameters.PreviousScenarioNotNull).Database;
            var dbDstHouses       = Services.SqlConnection.GetDatabaseConnection(Stage.Houses, parameters).Database;
            var srcHeatingSystems = dbSrcHouses.Fetch <HeatingSystemEntry>();

            if (srcHeatingSystems.Count == 0)
            {
                throw new FlaException("No heating systems were found");
            }

            int elapsedTime = parameters.DstYear - parameters.PreviousScenarioNotNull.DstYear;

            foreach (var heatingSystemEntry in srcHeatingSystems)
            {
                heatingSystemEntry.Age += elapsedTime;
            }

            int yearsToAge = parameters.DstYear - parameters.PreviousScenarioNotNull.DstYear;
            var potentialSystemsToChange = srcHeatingSystems.Where(x => x.SynthesizedHeatingSystemType == HeatingSystemType.Öl || x.SynthesizedHeatingSystemType == HeatingSystemType.Gas).ToList();

            WeightedRandomAllocator <HeatingSystemEntry> wra = new WeightedRandomAllocator <HeatingSystemEntry>(Services.Rnd);

            double WeighingFunction(HeatingSystemEntry heatingSystemEntry)
            {
                double ageWeight    = heatingSystemEntry.Age / 30.0;
                double energyWeight = 1 - heatingSystemEntry.AverageHeatingEnergyDemandDensity / 200;

                if (energyWeight <= 0)
                {
                    energyWeight = 0.000001;
                }

                double combinedWeight = 1 / (ageWeight * energyWeight);

                if (double.IsInfinity(combinedWeight))
                {
                    throw new Exception("Invalid weight");
                }

                return(combinedWeight);
            }

/*
 *          double SumFunction(HeatingSystemEntry heatingSystemEntry)
 *          {
 *              return heatingSystemEntry.YearlyEnergyDemand;
 *          }
 */
            var pickedHeatingSystems = wra.PickObjects(potentialSystemsToChange, WeighingFunction, (int)parameters.ConversionToHeatPumpNumber);

            if (potentialSystemsToChange.Count < parameters.ConversionToHeatPumpNumber)
            {
                throw new Exception("not enough other heating systems left for heat pump conversion demand");
            }

            foreach (var pickedHeatingSystem in pickedHeatingSystems)
            {
                pickedHeatingSystem.Age = 0;
                pickedHeatingSystem.SynthesizedHeatingSystemType = HeatingSystemType.Heatpump;
            }

            dbDstHouses.BeginTransaction();
            foreach (HeatingSystemEntry heatingSystemEntry in srcHeatingSystems)
            {
                heatingSystemEntry.Age            += yearsToAge;
                heatingSystemEntry.HeatingSystemID = 0;
                dbDstHouses.Save(heatingSystemEntry);
            }

            dbDstHouses.CompleteTransaction();
        }
Exemplo n.º 4
0
        private void ApplyDeathsIncludingPersistence([NotNull] ScenarioSliceParameters slice,
                                                     [NotNull][ItemNotNull]
                                                     List <Household> srcHouseholds,
                                                     [NotNull][ItemNotNull]
                                                     IReadOnlyCollection <Occupant> allOccupants)
        {
            WeightedRandomAllocator <Occupant> wra = new WeightedRandomAllocator <Occupant>(Services.Rnd, Services.Logger);
            var dbDstHousePersistence = Services.SqlConnectionPreparer.GetDatabaseConnection(Stage.Houses, slice, DatabaseCode.Persistence);

            dbDstHousePersistence.CreateTableIfNotExists <PersistenceDeathEntry>();
            int numberOfDeathsLeft = (int)slice.NumberOfDeaths;
            var deathEntries       = dbDstHousePersistence.Fetch <PersistenceDeathEntry>();
            var peopleToRemove     = new List <Occupant>();

            Info("Number of planned deaths: " + numberOfDeathsLeft);
            dbDstHousePersistence.BeginTransaction();
            foreach (var de in deathEntries)
            {
                var hh = srcHouseholds.FirstOrDefault(x => x.HouseholdKey == de.HouseholdKey);
                if (hh == null)
                {
                    dbDstHousePersistence.Delete(de);
                    continue;
                }

                var srcocc = allOccupants.FirstOrDefault(x => x.HouseholdGuid == hh.Guid && x.Age == de.Age && x.Gender == de.Gender);
                if (srcocc == null)
                {
                    dbDstHousePersistence.Delete(de);
                    continue;
                }

                numberOfDeathsLeft--;
                peopleToRemove.Add(srcocc);
                if (numberOfDeathsLeft == 0)
                {
                    break;
                }
            }

            Info("Deaths after applying persistent deaths from db: " + numberOfDeathsLeft);
            List <Occupant> randomRemovedPeople = new List <Occupant>();

            if (numberOfDeathsLeft > 0)
            {
                randomRemovedPeople = wra.PickNumberOfObjects(allOccupants, (x => x.Age * x.Age), numberOfDeathsLeft, true);
                Info("Randomly picked additional people: " + randomRemovedPeople.Count);
            }

            peopleToRemove.AddRange(randomRemovedPeople);
            Info("People dying: " + peopleToRemove.Count);
            foreach (var deadocc in peopleToRemove)
            {
                Household             hh = srcHouseholds.First(x => x.Guid == deadocc.HouseholdGuid);
                PersistenceDeathEntry de = new PersistenceDeathEntry(hh.HouseholdKey, deadocc.Age, deadocc.Gender);
                dbDstHousePersistence.Save(de);
                hh.Occupants.Remove(deadocc);
            }

            dbDstHousePersistence.CompleteTransaction();
        }
Exemplo n.º 5
0
        protected override void RunActualProcess([NotNull] ScenarioSliceParameters slice)
        {
            var dbSrcHouses = Services.SqlConnectionPreparer.GetDatabaseConnection(Stage.Houses, slice.PreviousSliceNotNull);
            var dbDstHouses = Services.SqlConnectionPreparer.GetDatabaseConnection(Stage.Houses, slice);
            var households  = dbDstHouses.FetchAsRepo <Household>();

            dbDstHouses.RecreateTable <Car>();
            var srcCars = dbSrcHouses.FetchAsRepo <Car>();

            CheckCarsPerHousehold(srcCars);
            //filter cars for eliminated households
            var householdGuids = households.ToGuidHashset();

            if (srcCars.Count == 0)
            {
                throw new Exception("No cars were found in the scenario " + slice.DstScenario + " - " + slice.DstYear);
            }

            var yearsToAge = slice.DstYear - slice.PreviousSlice?.DstYear ?? throw new FlaException("Previous scenario was not set");

            dbDstHouses.BeginTransaction();
            WeightedRandomAllocator <Car> allocator = new WeightedRandomAllocator <Car>(Services.Rnd, Services.Logger);
            var  carsToPickFrom              = srcCars.Where(x => x.CarType == CarType.Gasoline).ToList();
            bool failOnOversubscribe         = slice.DstYear == 2050 ? false : true;
            int  numberOfTargetElectricCars  = (int)(slice.TotalPercentageOfElectricCars * srcCars.Count);
            int  numberOfCurrentElectricCars = srcCars.Count - carsToPickFrom.Count;
            int  numberOfNewElectricCars     = numberOfTargetElectricCars - numberOfCurrentElectricCars;

            if (numberOfNewElectricCars < 0)
            {
                throw new FlaException("Negative target electric cars in slice " + slice);
            }

            var        carsToChange = allocator.PickNumberOfObjects(carsToPickFrom, x => x.Age, numberOfNewElectricCars, failOnOversubscribe);
            int        carsSaved    = 0;
            List <Car> carsToDelete = new List <Car>();

            foreach (var car in srcCars)
            {
                if (!householdGuids.Contains(car.HouseholdGuid))
                {
                    var otherhouseholds = households.GetByReferenceGuidWithEmptyReturns(car.HouseGuid, "houseguid", x => x.HouseGuid);
                    if (otherhouseholds.Count == 0)
                    {
                        carsToDelete.Add(car);
                        continue;
                    }

                    var otherCars             = srcCars.GetByReferenceGuidWithEmptyReturns(car.HouseGuid, "houseguid", x => x.HouseGuid);
                    var hhswithCarGuids       = otherCars.Select(x => x.HouseholdGuid).ToList();
                    var householdsWithoutCars = otherhouseholds.Where(x => !hhswithCarGuids.Contains(x.Guid)).ToList();
                    if (householdsWithoutCars.Count > 0)
                    {
                        car.HouseholdGuid = householdsWithoutCars[Services.Rnd.Next(householdsWithoutCars.Count)].Guid;
                    }
                    else
                    {
                        car.HouseholdGuid = otherhouseholds[Services.Rnd.Next(householdsWithoutCars.Count)].Guid;
                    }
                }
            }

            var carsToSave = srcCars.GetValueList();

            foreach (var car in carsToDelete)
            {
                carsToSave.Remove(car);
            }

            CheckCarsPerHousehold(carsToSave);
            int targetCarCount = (int)(households.SelectMany(x => x.Occupants).Count() * slice.CarOwnershipPercentage);

            if (carsToSave.Count > targetCarCount)
            {
                //clear excess cars
                int excessCars = carsToSave.Count - targetCarCount;
                var carsToSell = allocator.PickNumberOfObjects(carsToSave, x => x.Age, excessCars, false);
                foreach (var sellcar in carsToSell)
                {
                    carsToSave.Remove(sellcar);
                }
            }
            else
            {
                int carsToCreate = targetCarCount - carsToSave.Count;
                while (carsToCreate > 0)
                {
                    var dict          = CheckCarsPerHousehold(carsToSave);
                    var householdGuid = dict.First().Key;
                    if (dict.First().Value > 2)
                    {
                        throw new FlaException("more than 2 cars per household");
                    }

                    string  houseguid     = households.GetByGuid(householdGuid).HouseGuid;
                    CarType targetCarType = CarType.Gasoline;
                    if (carsToSave.Count(x => x.CarType == CarType.Electric) < (slice.TotalPercentageOfElectricCars * carsToSave.Count))
                    {
                        targetCarType = CarType.Electric;
                    }

                    Car newcar = new Car(householdGuid, Guid.NewGuid().ToString(), 0, targetCarType, houseguid);
                    carsToCreate--;
                    carsToSave.Add(newcar);
                }
            }

            CheckCarsPerHousehold(carsToSave);
            foreach (var car in carsToSave)
            {
                car.ID   = 0;
                car.Age += yearsToAge;
                if (carsToChange.Contains(car))
                {
                    car.CarType = CarType.Electric;
                    car.Age     = 0;
                }

                carsSaved++;
                dbDstHouses.Save(car);
            }

            //make new Cars
            Info("Converted " + carsToChange.Count + " cars, out of a total of " + carsSaved);
            //convert cars to electric
            dbDstHouses.CompleteTransaction();
        }
        protected override void RunActualProcess([NotNull] ScenarioSliceParameters slice)
        {
            var dbSrcHouses = Services.SqlConnectionPreparer.GetDatabaseConnection(Stage.Houses, slice.PreviousSliceNotNull);
            var dbDstHouses = Services.SqlConnectionPreparer.GetDatabaseConnection(Stage.Houses, slice);

            dbDstHouses.RecreateTable <HeatingSystemEntry>();
            var srcHeatingSystems = dbSrcHouses.Fetch <HeatingSystemEntry>();
            var srcHouses         = dbSrcHouses.Fetch <House>();
            var dstHouses         = dbDstHouses.FetchAsRepo <House>();

            if (srcHeatingSystems.Count == 0)
            {
                throw new FlaException("No heating systems were found");
            }

            double totalHeatingDemand = srcHeatingSystems.Sum(x => x.HeatDemand);
            double totalEbf           = srcHouses.Sum(x => x.EnergieBezugsFläche);
            double averageEnergyIntensityForNewAppartments = totalHeatingDemand / totalEbf * 0.5;

            //add heating demand from new appartments
            foreach (var hse in srcHeatingSystems)
            {
                var house = dstHouses.GetByGuid(hse.HouseGuid);
                foreach (var expansion in house.Appartments)
                {
                    var hseExpansion = hse.HeatDemands.FirstOrDefault(x => x.HouseExpansionGuid == expansion.Guid);
                    if (hseExpansion == null)
                    {
                        AppartmentHeatingDemand hsex = new AppartmentHeatingDemand(expansion.Guid,
                                                                                   expansion.EnergieBezugsFläche,
                                                                                   averageEnergyIntensityForNewAppartments * expansion.EnergieBezugsFläche,
                                                                                   slice.DstYear);
                        hse.HeatDemands.Add(hsex);
                    }
                }
            }

            var dstHousesByGuid = dstHouses.ToDictionary(x => x.Guid, x => x);

            DumpHeatingSystemsToXlsx(slice, srcHeatingSystems, dstHousesByGuid);

            //building renovations
            WeightedRandomAllocator <HeatingSystemEntry> wra = new WeightedRandomAllocator <HeatingSystemEntry>(Services.Rnd, MyLogger);

            var potentialRenovationHeatingSystems = srcHeatingSystems
                                                    .Where(x => x.Age > 10 && x.HeatDemand > 0 && Math.Abs(x.HeatDemand - x.OriginalHeatDemand2017) < 0.1).ToList();

            if (potentialRenovationHeatingSystems.Count == 0)
            {
                throw new FlaException("Not a single heating system found");
            }

            double averageRenovationFactor = slice.AverageHouseRenovationFactor;

            if (Math.Abs(averageRenovationFactor) < 0.000001)
            {
                throw new FlaException("Renovation factor was 0 for scenario " + slice);
            }

            int numberOfBuildingRenovations = (int)(slice.RenovationRatePercentage * srcHouses.Count);

            Info("renovating houses, target number " + numberOfBuildingRenovations + " GWh, renovation factor " + averageRenovationFactor);
            bool failOnOversubscribe = slice.DstYear != 2050;
            var  systemsToRenovate   = wra.PickNumberOfObjects(potentialRenovationHeatingSystems,
                                                               WeighingFunctionForRenovation,
                                                               numberOfBuildingRenovations,
                                                               failOnOversubscribe);

            Info("Renovating " + systemsToRenovate.Count + " houses with a total heat demand of " + systemsToRenovate.Sum(x => x.HeatDemand));
            foreach (var entry in systemsToRenovate)
            {
                entry.RenovateAllHeatDemand(averageRenovationFactor);
            }


            //change heating systems
            var changeableHeatingSystems = srcHeatingSystems.ToList();
            int elapsedTime = slice.DstYear - slice.PreviousSliceNotNull.DstYear;

            foreach (var heatingSystemEntry in srcHeatingSystems)
            {
                heatingSystemEntry.Age += elapsedTime;
            }


            int           yearsToAge             = slice.DstYear - slice.PreviousSliceNotNull.DstYear;
            RowCollection rc                     = new RowCollection("Changes", "Changes");
            double        totalOilHeatDemand2017 = changeableHeatingSystems.Where(x => x.HeatingSystemType2017 == HeatingSystemType.Öl)
                                                   .Sum(x => x.OriginalHeatDemand2017);
            double oilenergyAmountToChange = totalOilHeatDemand2017 * slice.Energy2017PercentageFromOilToHeatpump;

            ChangeHeatingSystemsForOneType(slice, changeableHeatingSystems, HeatingSystemType.Öl, oilenergyAmountToChange, rc, dstHousesByGuid);
            double totalGasHeatDemand2017 = changeableHeatingSystems.Where(x => x.HeatingSystemType2017 == HeatingSystemType.Gas)
                                            .Sum(x => x.OriginalHeatDemand2017);
            double gasEnergyAmountToChange = totalGasHeatDemand2017 * slice.Energy2017PercentageFromGasToHeatpump;

            ChangeHeatingSystemsForOneType(slice, changeableHeatingSystems, HeatingSystemType.Gas, gasEnergyAmountToChange, rc, dstHousesByGuid);
            double totalOtherHeatDemand = changeableHeatingSystems.Where(x => x.HeatingSystemType2017 == HeatingSystemType.Other)
                                          .Sum(x => x.OriginalHeatDemand2017);
            double otherDemandToChange = slice.Energy2017PercentageFromOtherToHeatpump * totalOtherHeatDemand;

            ChangeHeatingSystemsForOneType(slice, changeableHeatingSystems, HeatingSystemType.Other, otherDemandToChange, rc, dstHousesByGuid);
            var fn = MakeAndRegisterFullFilename("HeatingChangeLog.xlsx", slice);

            if (rc.Rows.Count > 0)
            {
                XlsxDumper.WriteToXlsx(fn, rc);
            }

            dbDstHouses.BeginTransaction();
            foreach (HeatingSystemEntry heatingSystemEntry in srcHeatingSystems)
            {
                heatingSystemEntry.Age += yearsToAge;
                heatingSystemEntry.ID   = 0;

                dbDstHouses.Save(heatingSystemEntry);
            }

            dbDstHouses.CompleteTransaction();
            var srcHouseGuids = srcHouses.Select(x => x.Guid).ToHashSet();
            var dstHouseGuids = dstHouses.Select(x => x.Guid).ToHashSet();

            foreach (var heatingSystem in srcHeatingSystems)
            {
                srcHouseGuids.Should().Contain(heatingSystem.HouseGuid);
                dstHouseGuids.Should().Contain(heatingSystem.HouseGuid);
            }
        }
        private void ChangeHeatingSystemsForOneType([NotNull] ScenarioSliceParameters slice,
                                                    [NotNull][ItemNotNull] List <HeatingSystemEntry> allPotentialSystemsToChange,
                                                    HeatingSystemType heatingSystemType,
                                                    double sumToSwitch,
                                                    [NotNull] RowCollection rc,
                                                    [NotNull] Dictionary <string, House> housesByGuid)
        {
            if (Math.Abs(sumToSwitch) < 0.1)
            {
                return;
            }

            var rb = RowBuilder.Start("Type to Change", heatingSystemType.ToString());

            rc.Add(rb);
            var matchingPotentialSystemsToChange =
                allPotentialSystemsToChange.Where(x => x.SynthesizedHeatingSystemType == heatingSystemType).ToList();

            rb.Add("Planned Sum", sumToSwitch);
            rb.Add("Energy Demand before across all systems", matchingPotentialSystemsToChange.Select(x => x.OriginalHeatDemand2017).Sum());
            WeightedRandomAllocator <HeatingSystemEntry> wra = new WeightedRandomAllocator <HeatingSystemEntry>(Services.Rnd, MyLogger);

            var pickedHeatingSystems = wra.PickObjectUntilLimit(matchingPotentialSystemsToChange,
                                                                WeighingFunctionForSwitchingToHeatpump,
                                                                x => x.OriginalHeatDemand2017,
                                                                sumToSwitch,
                                                                false);
            double changedEnergy = 0;

            foreach (var pickedHeatingSystem in pickedHeatingSystems)
            {
                pickedHeatingSystem.Age = 0;
                pickedHeatingSystem.SynthesizedHeatingSystemType = HeatingSystemType.Heatpump;
                pickedHeatingSystem.ProvideProfile = true;
                changedEnergy += pickedHeatingSystem.OriginalHeatDemand2017;
                House house = housesByGuid[pickedHeatingSystem.HouseGuid];
                var   rb1   = RowBuilder.Start("House", house.ComplexName);
                rb1.Add("Changed Energy", pickedHeatingSystem.EffectiveEnergyDemand);
                rb1.Add("Heating System", heatingSystemType);
                rc.Add(rb1);
            }

            rb.Add("Changed Sum", changedEnergy);
            Info("Changed " + pickedHeatingSystems.Count + " from " + heatingSystemType + " to heatpump for a total of " + changedEnergy / 1_000_000 +
                 " gwh");
            double overSubscribed = sumToSwitch - changedEnergy;

            rb.Add("Oversubscribed", overSubscribed);
            if (slice.DstYear != 2050)
            {
                if (overSubscribed > 0)
                {
                    throw new FlaException("Problem: tried to allocate " + sumToSwitch / Constants.GWhFactor +
                                           "gwh to heat pumps, but could only switch " + changedEnergy / Constants.GWhFactor + " gwh in the year " +
                                           slice.DstYear + " and scenario " + slice.DstScenario + " from type " + heatingSystemType);
                }

                //im letzten jahr ist oversubscribe ok.
                //overSubscribed.Should().BeLessOrEqualTo(0);
            }

            var leftoveroldSystems = matchingPotentialSystemsToChange.Where(x => x.SynthesizedHeatingSystemType == heatingSystemType).ToList();

            rb.Add("Energy Demand after across all systems", leftoveroldSystems.Select(x => x.EffectiveEnergyDemand).Sum());
        }