EMlab-generation Documentation  1.0
Documentation of the EMLab-Generation model.
SubmitOffersToElectricitySpotMarketRole.java
1 /*******************************************************************************
2  * Copyright 2012 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  ******************************************************************************/
16 package emlab.gen.role.market;
17 
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Set;
23 
24 import org.springframework.beans.factory.annotation.Autowired;
25 import org.springframework.transaction.annotation.Transactional;
26 
27 import agentspring.role.Role;
28 import agentspring.role.RoleComponent;
41 import emlab.gen.role.AbstractEnergyProducerRole;
42 
49 @RoleComponent
50 public class SubmitOffersToElectricitySpotMarketRole extends AbstractEnergyProducerRole<EnergyProducer> implements
51 Role<EnergyProducer> {
52 
53  @Autowired
54  Reps reps;
55 
56  @Override
57  public void act(EnergyProducer producer) {
58 
59  createOffersForElectricitySpotMarket(producer, getCurrentTick(), false, null);
60  }
61 
62  @Transactional
63  public List<PowerPlantDispatchPlan> createOffersForElectricitySpotMarket(EnergyProducer producer, long tick,
64  boolean forecast, Map<Substance, Double> forecastedFuelPrices) {
65  List<PowerPlantDispatchPlan> ppdpList = new ArrayList<PowerPlantDispatchPlan>();
66 
67  if (forecastedFuelPrices == null && !forecast) {
68  DecarbonizationModel model = reps.genericRepository.findFirst(DecarbonizationModel.class);
69  forecastedFuelPrices = new HashMap<Substance, Double>();
70  for (Substance substance : reps.substanceRepository.findAllSubstancesTradedOnCommodityMarkets()) {
71  forecastedFuelPrices.put(substance, findLastKnownPriceForSubstance(substance, getCurrentTick()));
72  }
73  }
74 
75 
76  long numberOfSegments = reps.segmentRepository.count();
77  ElectricitySpotMarket market = null;
78  if (producer != null)
79  market = producer.getInvestorMarket();
80 
81  Iterable<PowerPlant> powerPlants;
82  if (producer != null) {
83  powerPlants = forecast ? reps.powerPlantRepository
84  .findExpectedOperationalPowerPlantsInMarketByOwner(market, tick, producer) : reps.powerPlantRepository
85  .findOperationalPowerPlantsByOwner(producer, tick);
86  } else {
87  powerPlants = forecast ? reps.powerPlantRepository.findExpectedOperationalPowerPlants(tick)
88  : reps.powerPlantRepository.findOperationalPowerPlants(tick);
89  }
90 
91  boolean producerIsNull = (producer == null) ? true : false;
92  // find all my operating power plants
93  for (PowerPlant plant : powerPlants) {
94 
95  if (producerIsNull) {
96  market = reps.marketRepository.findElectricitySpotMarketForZone(plant.getLocation().getZone());
97  producer = plant.getOwner();
98  }
99 
100  double mc;
101  double price;
102  if (!forecast) {
103  mc = calculateMarginalCostExclCO2MarketCost(plant, tick);
104  price = mc * producer.getPriceMarkUp();
105  } else {
106  mc = calculateExpectedMarginalCostExclCO2MarketCost(plant, forecastedFuelPrices, tick);
107  price = mc * producer.getPriceMarkUp();
108  }
109 
110  logger.info("Submitting offers for {} with technology {}", plant.getName(), plant.getTechnology().getName());
111 
112  for (SegmentLoad segmentload : market.getLoadDurationCurve()) {
113  Segment segment = segmentload.getSegment();
114  double capacity;
115  if (tick == getCurrentTick()) {
116  capacity = plant.getAvailableCapacity(tick, segment, numberOfSegments);
117  } else {
118  capacity = plant.getExpectedAvailableCapacity(tick, segment, numberOfSegments);
119  }
120 
121  logger.info("I bid capacity: {} and price: {}", capacity, mc);
122 
123  PowerPlantDispatchPlan plan = reps.powerPlantDispatchPlanRepository
124  .findOnePowerPlantDispatchPlanForPowerPlantForSegmentForTime(plant, segment, tick, forecast);
125  // TODO: handle exception
126 
127  // plan =
128  // reps.powerPlantDispatchPlanRepository.findOnePowerPlantDispatchPlanForPowerPlantForSegmentForTime(plant,
129  // segment,
130  // getCurrentTick());
131  // Iterable<PowerPlantDispatchPlan> plans =
132  // reps.powerPlantDispatchPlanRepository
133  // .findAllPowerPlantDispatchPlanForPowerPlantForSegmentForTime(plant,
134  // segment, getCurrentTick());
135 
136  if (plan == null) {
137  plan = new PowerPlantDispatchPlan().persist();
138  // plan.specifyNotPersist(plant, producer, market, segment,
139  // time, price, bidWithoutCO2, spotMarketCapacity,
140  // longTermContractCapacity, status);
141  plan.specifyNotPersist(plant, producer, market, segment, tick, price, price, capacity, 0,
142  Bid.SUBMITTED, forecast);
143  } else {
144  // plan = plans.iterator().next();
145  plan.setBidder(producer);
146  plan.setBiddingMarket(market);
147  plan.setPrice(mc);
148  plan.setBidWithoutCO2(mc);
149  plan.setAmount(capacity);
150  plan.setAcceptedAmount(0d);
151  plan.setCapacityLongTermContract(0d);
152  plan.setStatus(Bid.SUBMITTED);
153  plan.setForecast(forecast);
154  }
155  ppdpList.add(plan);
156 
157  }
158 
159  }
160 
161  return ppdpList;
162  }
163 
164  @Transactional
165  void updateMarginalCostInclCO2AfterFuelMixChange(double co2Price,
166  Map<ElectricitySpotMarket, Double> nationalMinCo2Prices, long clearingTick, boolean forecast,
167  Map<Substance, Double> fuelPriceMap) {
168 
169  int i = 0;
170  int j = 0;
171 
172  Government government = reps.template.findAll(Government.class).iterator().next();
173  for (PowerPlantDispatchPlan plan : reps.powerPlantDispatchPlanRepository
174  .findAllPowerPlantDispatchPlansForTime(
175  clearingTick, forecast)) {
176  j++;
177 
178  double effectiveCO2Price;
179 
180  double capacity = plan.getAmount();
181  if (nationalMinCo2Prices.get(plan.getBiddingMarket()) > co2Price)
182  effectiveCO2Price = nationalMinCo2Prices.get(plan.getBiddingMarket());
183  else
184  effectiveCO2Price = co2Price;
185 
186  if (plan.getPowerPlant().getFuelMix().size() > 1) {
187 
188  double oldmc = plan.getBidWithoutCO2();
189 
190  // Fuels
191  Set<Substance> possibleFuels = plan.getPowerPlant().getTechnology().getFuels();
192  Map<Substance, Double> substancePriceMap = new HashMap<Substance, Double>();
193 
194  for (Substance substance : possibleFuels) {
195  substancePriceMap.put(substance, fuelPriceMap.get(substance));
196  }
197  Set<SubstanceShareInFuelMix> fuelMix = calculateFuelMix(plan.getPowerPlant(), substancePriceMap,
198  government.getCO2Tax(clearingTick) + effectiveCO2Price);
199  plan.getPowerPlant().setFuelMix(fuelMix);
200  double mc = calculateMarginalCostExclCO2MarketCost(plan.getPowerPlant(), clearingTick);
201  if (mc != oldmc) {
202  plan.setBidWithoutCO2(mc);
203  i++;
204  }
205 
206  }
207 
208  plan.setPrice(plan.getBidWithoutCO2()
209  + (effectiveCO2Price * plan.getPowerPlant().calculateEmissionIntensity()));
210 
211  plan.setStatus(Bid.SUBMITTED);
212  plan.setAmount(capacity);
213  plan.setAcceptedAmount(0d);
214  plan.setCapacityLongTermContract(0d);
215 
216  }
217 
218  //logger.warn("Marginal cost of {} of {} plans changed", i, j);
219 
220  }
221 
222 }
Iterable< PowerPlant > findOperationalPowerPlants(@Param("tick") long tick)
Iterable< PowerPlant > findOperationalPowerPlantsByOwner(@Param("owner") EnergyProducer owner,@Param("tick") long tick)