/*******************************************************************************
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package emlab.role.investment;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import org.springframework.beans.factory.annotation.Autowired;
import emlab.domain.market.electricity.ElectricitySpotMarket;
import emlab.domain.market.electricity.Segment;
import emlab.domain.market.electricity.SegmentLoad;
import emlab.domain.technology.PowerPlant;
import emlab.domain.technology.Substance;
import emlab.domain.technology.SubstanceShareInFuelMix;
import emlab.repository.Reps;
import emlab.util.MapValueComparator;
public class SingleElectricityMarketInformation {
@Autowired
Reps reps;
Map<Segment, Double> expectedElectricityPricesPerSegment;
double maxExpectedLoad = 0d;
Map<PowerPlant, Double> meritOrder;
double capacitySum;
SingleElectricityMarketInformation(ElectricitySpotMarket market, Map<Substance, Double> fuelPrices, double co2price, long time) {
// determine expected power prices
expectedElectricityPricesPerSegment = new HashMap<Segment, Double>();
Map<PowerPlant, Double> marginalCostMap = new HashMap<PowerPlant, Double>();
capacitySum = 0d;
// get merit order for this market
for (PowerPlant plant : reps.powerPlantRepository.findExpectedOperationalPowerPlantsInMarket(market, time)) {
double plantMarginalCost = determineExpectedMarginalCost(plant, fuelPrices, co2price);
marginalCostMap.put(plant, plantMarginalCost);
capacitySum += plant.getTechnology().getCapacity();
}
MapValueComparator comp = new MapValueComparator(marginalCostMap);
meritOrder = new TreeMap<PowerPlant, Double>(comp);
meritOrder.putAll(marginalCostMap);
long numberOfSegments = reps.segmentRepository.count();
double demandFactor = market.getDemandGrowthTrend().getValue(time);
// find expected prices per segment given merit order
for (SegmentLoad segmentLoad : market.getLoadDurationCurve()) {
double expectedSegmentLoad = segmentLoad.getBaseLoad() * demandFactor;
if (expectedSegmentLoad > maxExpectedLoad) {
maxExpectedLoad = expectedSegmentLoad;
}
double segmentSupply = 0d;
double segmentPrice = 0d;
for (Entry<PowerPlant, Double> plantCost : meritOrder.entrySet()) {
PowerPlant plant = plantCost.getKey();
double plantCapacity = 0d;
// Determine available capacity in the future in this
// segment
plantCapacity = plant.getExpectedAvailableCapacity(time, segmentLoad.getSegment(), numberOfSegments);
// logger.warn("Capacity of plant " + plant.toString() +
// " is " +
// plantCapacity/plant.getTechnology().getCapacity());
if (segmentSupply < expectedSegmentLoad) {
segmentSupply += plantCapacity;
segmentPrice = plantCost.getValue();
}
}
// logger.warn("Segment " +
// segmentLoad.getSegment().getSegmentID() + " supply equals " +
// segmentSupply + " and segment demand equals " +
// expectedSegmentLoad);
if (segmentSupply >= expectedSegmentLoad) {
expectedElectricityPricesPerSegment.put(segmentLoad.getSegment(), segmentPrice);
} else {
expectedElectricityPricesPerSegment.put(segmentLoad.getSegment(), market.getValueOfLostLoad());
}
}
}
public double determineExpectedMarginalCost(PowerPlant plant, Map<Substance, Double> expectedFuelPrices, double expectedCO2Price) {
double mc = determineExpectedMarginalFuelCost(plant, expectedFuelPrices);
double co2Intensity = calculateCO2Intensity(plant);
mc += co2Intensity * expectedCO2Price;
return mc;
}
public double determineExpectedMarginalFuelCost(PowerPlant powerPlant, Map<Substance, Double> expectedFuelPrices) {
double fc = 0d;
for (SubstanceShareInFuelMix mix : powerPlant.getFuelMix()) {
double amount = mix.getShare();
double fuelPrice = expectedFuelPrices.get(mix.getSubstance());
fc += amount * fuelPrice;
}
return fc;
}
public double calculateCO2Intensity(PowerPlant plant) {
return calculateCO2Intensity(plant.getFuelMix()) * (1 - plant.getTechnology().getCo2CaptureEffciency());
}
public double calculateCO2Intensity(Set<SubstanceShareInFuelMix> fuelMix) {
double co2Intensity = 0d;
for (SubstanceShareInFuelMix mix : fuelMix) {
co2Intensity += mix.getShare() * mix.getSubstance().getCo2Density();
}
return co2Intensity;
}
}