EMlab-generation Documentation  1.0
Documentation of the EMLab-Generation model.
PowerPlant.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.domain.technology;
17 
18 import java.util.Set;
19 
20 import org.neo4j.graphdb.Direction;
21 import org.springframework.beans.factory.annotation.Autowired;
22 import org.springframework.beans.factory.annotation.Configurable;
23 import org.springframework.data.annotation.Transient;
24 import org.springframework.data.neo4j.annotation.NodeEntity;
25 import org.springframework.data.neo4j.annotation.RelatedTo;
26 import org.springframework.transaction.annotation.Transactional;
27 
35 
44 @Configurable
45 @NodeEntity
46 public class PowerPlant {
47 
48  @Transient
49  @Autowired
50  private PowerPlantDispatchPlanRepository powerPlantDispatchPlanRepository;
51 
52  @Transient
53  @Autowired
54  private IntermittentTechnologyNodeLoadFactorRepository intermittentTechnologyNodeLoadFactorRepository;
55 
56  @RelatedTo(type = "TECHNOLOGY", elementClass = PowerGeneratingTechnology.class, direction = Direction.OUTGOING)
57  private PowerGeneratingTechnology technology;
58 
59  @RelatedTo(type = "FUEL_MIX", elementClass = SubstanceShareInFuelMix.class, direction = Direction.OUTGOING)
60  private Set<SubstanceShareInFuelMix> fuelMix;
61 
62  @RelatedTo(type = "POWERPLANT_OWNER", elementClass = EnergyProducer.class, direction = Direction.OUTGOING)
63  private EnergyProducer owner;
64 
65  @RelatedTo(type = "LOCATION", elementClass = PowerGridNode.class, direction = Direction.OUTGOING)
66  private PowerGridNode location;
67 
68  @RelatedTo(type = "LOAN", elementClass = Loan.class, direction = Direction.OUTGOING)
69  private Loan loan;
70 
71  @RelatedTo(type = "DOWNPAYMENT", elementClass = Loan.class, direction = Direction.OUTGOING)
72  private Loan downpayment;
73 
78  private long dismantleTime;
79  private long constructionStartTime;
80  private long actualLeadtime;
81  private long actualPermittime;
82  private long actualLifetime;
83  private String name;
84  private String label;
85  private double actualInvestedCapital;
86  private double actualFixedOperatingCost;
87  private double actualEfficiency;
88  private double expectedEndOfLife;
89  private double actualNominalCapacity;
90 
91  public boolean isOperational(long currentTick) {
92 
93  double finishedConstruction = getConstructionStartTime()
94  + calculateActualPermittime() + calculateActualLeadtime();
95 
96  if (finishedConstruction <= currentTick) {
97  // finished construction
98 
99  if (getDismantleTime() == 1000) {
100  // No dismantletime set, therefore must be not yet dismantled.
101  return true;
102  } else if (getDismantleTime() > currentTick) {
103  // Dismantle time set, but not yet reached
104  return true;
105  } else if (getDismantleTime() <= currentTick) {
106  // Dismantle time passed so not operational
107  return false;
108  }
109  }
110  // Construction not yet finished.
111  return false;
112  }
113 
114  public boolean isExpectedToBeOperational(long time) {
115 
116  double finishedConstruction = getConstructionStartTime()
117  + calculateActualPermittime() + calculateActualLeadtime();
118 
119  if (finishedConstruction <= time) {
120  // finished construction
121 
122  if (getExpectedEndOfLife() > time) {
123  // Powerplant is not expected to be dismantled
124  return true;
125  }
126  }
127  // Construction not yet finished.
128  return false;
129  }
130 
131  public boolean isInPipeline(long currentTick) {
132 
133  double finishedConstruction = getConstructionStartTime()
134  + calculateActualPermittime() + calculateActualLeadtime();
135 
136  if (finishedConstruction > currentTick) {
137  // finished construction
138 
139  if (getDismantleTime() == 1000) {
140  // No dismantletime set, therefore must be not yet dismantled.
141  return true;
142  } else if (getDismantleTime() > currentTick) {
143  // Dismantle time set, but not yet reached
144  return true;
145  } else if (getDismantleTime() <= currentTick) {
146  // Dismantle time passed so not operational
147  return false;
148  }
149  }
150  // Construction finished
151  return false;
152  }
153 
154  public double getAvailableCapacity(long currentTick, Segment segment,
155  long numberOfSegments) {
156  if (isOperational(currentTick)) {
157  if (this.getTechnology().isIntermittent()) {
158  IntermittentTechnologyNodeLoadFactor intermittentTechnologyNodeLoadFactor = getIntermittentTechnologyNodeLoadFactor();
159  double factor = intermittentTechnologyNodeLoadFactor.getLoadFactorForSegment(segment);
160  return getActualNominalCapacity() * factor;
161  } else {
162  double factor = 1;
163  if (segment != null) {// if no segment supplied, assume we want full
164  // capacity
165  double segmentID = segment.getSegmentID();
166  if ((int) segmentID != 1) {
167 
168  double min = getTechnology()
169  .getPeakSegmentDependentAvailability();
170  double max = getTechnology()
171  .getBaseSegmentDependentAvailability();
172  double segmentPortion = (numberOfSegments - segmentID)
173  / (numberOfSegments - 1); // start
174  // counting
175  // at
176  // 1.
177 
178  double range = max - min;
179 
180  factor = max - segmentPortion * range;
181  int i = 0;
182  } else {
183  factor = getTechnology()
184  .getPeakSegmentDependentAvailability();
185  }
186  }
187  return getActualNominalCapacity() * factor;
188  }
189  } else {
190  return 0;
191  }
192  }
193 
194  public double getExpectedAvailableCapacity(long futureTick,
195  Segment segment, long numberOfSegments) {
196  if (isExpectedToBeOperational(futureTick)) {
197  if (this.getTechnology().isIntermittent()) {
198  double factor = getIntermittentTechnologyNodeLoadFactor().getLoadFactorForSegment(segment);
199  return getActualNominalCapacity() * factor;
200  } else {
201  double factor = 1;
202  if (segment != null) {// if no segment supplied, assume we want full
203  // capacity
204  double segmentID = segment.getSegmentID();
205  double min = getTechnology()
206  .getPeakSegmentDependentAvailability();
207  double max = getTechnology()
208  .getBaseSegmentDependentAvailability();
209  double segmentPortion = (numberOfSegments - segmentID)
210  / (numberOfSegments - 1); // start
211  // counting
212  // at
213  // 1.
214 
215  double range = max - min;
216 
217  factor = max - segmentPortion * range;
218  }
219  return getActualNominalCapacity() * factor;
220  }
221  } else {
222  return 0;
223  }
224  }
225 
226  public double getAvailableCapacity(long currentTick) {
227  if (isOperational(currentTick)) {
228  return getActualNominalCapacity();
229  } else {
230  return 0;
231  }
232  }
233 
234  public long calculateActualLeadtime() {
235  long actual;
236  actual = getActualLeadtime();
237  if (actual <= 0) {
238  actual = getTechnology().getExpectedLeadtime();
239  }
240  return actual;
241  }
242 
243  public long calculateActualPermittime() {
244  long actual;
245  actual = getActualPermittime();
246  if (actual <= 0) {
247  actual = getTechnology().getExpectedPermittime();
248  }
249  return actual;
250  }
251 
252  public long calculateActualLifetime() {
253  long actual;
254  actual = getActualLifetime();
255  if (actual <= 0) {
256  actual = getTechnology().getExpectedLifetime();
257  }
258  return actual;
259  }
260 
269  public boolean isWithinTechnicalLifetime(long currentTick) {
270  long endOfTechnicalLifetime = getConstructionStartTime()
271  + calculateActualPermittime() + calculateActualLeadtime()
272  + calculateActualLifetime();
273  if (endOfTechnicalLifetime <= currentTick) {
274  return false;
275  }
276  return true;
277  }
278 
279  public PowerGridNode getLocation() {
280  return location;
281  }
282 
283  public void setLocation(PowerGridNode location) {
284  this.location = location;
285  }
286 
287  public PowerGeneratingTechnology getTechnology() {
288  return technology;
289  }
290 
291  public void setTechnology(PowerGeneratingTechnology technology) {
292  this.technology = technology;
293  }
294 
295  public long getConstructionStartTime() {
296  return constructionStartTime;
297  }
298 
299  public void setConstructionStartTime(long constructionStartTime) {
300  this.constructionStartTime = constructionStartTime;
301  }
302 
303  public EnergyProducer getOwner() {
304  return owner;
305  }
306 
307  public void setOwner(EnergyProducer owner) {
308  this.owner = owner;
309  }
310 
311  public void setActualLifetime(long actualLifetime) {
312  this.actualLifetime = actualLifetime;
313  }
314 
315  public long getActualLifetime() {
316  return actualLifetime;
317  }
318 
319  public void setActualPermittime(long actualPermittime) {
320  this.actualPermittime = actualPermittime;
321  }
322 
323  public long getActualPermittime() {
324  return actualPermittime;
325  }
326 
327  public void setActualLeadtime(long actualLeadtime) {
328  this.actualLeadtime = actualLeadtime;
329  }
330 
331  public long getActualLeadtime() {
332  return actualLeadtime;
333  }
334 
335  public long getDismantleTime() {
336  return dismantleTime;
337  }
338 
339  public void setDismantleTime(long dismantleTime) {
340  this.dismantleTime = dismantleTime;
341  }
342 
343  public String getName() {
344  return label;
345  }
346 
347  public void setName(String label) {
348  this.name = label;
349  this.label = label;
350  }
351 
352  public String getLabel() {
353  return label;
354  }
355 
356  public void setLabel(String label) {
357  this.label = label;
358  }
359 
360  public double getActualInvestedCapital() {
361  return actualInvestedCapital;
362  }
363 
364  public void setActualInvestedCapital(double actualInvestedCapital) {
365  this.actualInvestedCapital = actualInvestedCapital;
366  }
367 
368  public Set<SubstanceShareInFuelMix> getFuelMix() {
369  return fuelMix;
370  }
371 
372  public void setFuelMix(Set<SubstanceShareInFuelMix> fuelMix) {
373  this.fuelMix = fuelMix;
374  }
375 
376  public Loan getLoan() {
377  return loan;
378  }
379 
380  public void setLoan(Loan loan) {
381  this.loan = loan;
382  }
383 
384  public Loan getDownpayment() {
385  return downpayment;
386  }
387 
388  public void setDownpayment(Loan downpayment) {
389  this.downpayment = downpayment;
390  }
391 
392  public double getActualEfficiency() {
393  return actualEfficiency;
394  }
395 
396  public void setActualEfficiency(double actualEfficiency) {
397  this.actualEfficiency = actualEfficiency;
398  }
399 
400  @Override
401  public String toString() {
402  return this.getName() + " power plant";
403  }
404 
413  long timeOfPermitorBuildingStart) {
414  setActualInvestedCapital(this.getTechnology().getInvestmentCost(
415  timeOfPermitorBuildingStart + getActualLeadtime() + getActualPermittime())
417  }
418 
419  public void calculateAndSetActualFixedOperatingCosts(long timeOfPermitorBuildingStart) {
420  setActualFixedOperatingCost(this.getTechnology().getFixedOperatingCost(
421  timeOfPermitorBuildingStart + getActualLeadtime() + getActualPermittime())
423  }
424 
425  public void calculateAndSetActualEfficiency(long timeOfPermitorBuildingStart) {
426  this.setActualEfficiency(this.getTechnology().getEfficiency(
427  timeOfPermitorBuildingStart + getActualLeadtime() + getActualPermittime()));
428  }
429 
430  public double calculateEmissionIntensity() {
431 
432  double emission = 0d;
433  for (SubstanceShareInFuelMix sub : this.getFuelMix()) {
434  Substance substance = sub.getSubstance();
435  double fuelAmount = sub.getShare();
436  double co2density = substance.getCo2Density()
437  * (1 - this.getTechnology().getCo2CaptureEffciency());
438 
439  // determine the total cost per MWh production of this plant
440  double emissionForThisFuel = fuelAmount * co2density;
441  emission += emissionForThisFuel;
442  }
443 
444  return emission;
445  }
446 
447  public double calculateElectricityOutputAtTime(long time, boolean forecast) {
448  // TODO This is in MWh (so hours of segment included!!)
449  double amount = 0d;
450  for (PowerPlantDispatchPlan plan : powerPlantDispatchPlanRepository
451  .findAllPowerPlantDispatchPlansForPowerPlantForTime(this, time, forecast)) {
452  amount += plan.getSegment().getLengthInHours()
453  * (plan.getCapacityLongTermContract() + plan
454  .getAcceptedAmount());
455  }
456  return amount;
457  }
458 
459  public double calculateCO2EmissionsAtTime(long time, boolean forecast) {
460  return this.calculateEmissionIntensity()
461  * calculateElectricityOutputAtTime(time, forecast);
462  }
463 
464  @Transactional
465  public void dismantlePowerPlant(long time) {
466  this.setDismantleTime(time);
467  }
468 
483  @Transactional
484  public void specifyAndPersist(long time, EnergyProducer energyProducer,
485  PowerGridNode location, PowerGeneratingTechnology technology) {
486  specifyNotPersist(time, energyProducer, location, technology);
487  this.persist();
488  }
489 
490  public void specifyNotPersist(long time, EnergyProducer energyProducer,
491  PowerGridNode location, PowerGeneratingTechnology technology) {
492  String label = energyProducer.getName() + " - " + technology.getName();
493  this.setName(label);
494  this.setTechnology(technology);
495  this.setOwner(energyProducer);
496  this.setLocation(location);
497  this.setConstructionStartTime(time);
498  this.setActualLeadtime(this.technology.getExpectedLeadtime());
499  this.setActualPermittime(this.technology.getExpectedPermittime());
500  this.calculateAndSetActualEfficiency(time);
501  this.setActualNominalCapacity(this.getTechnology().getCapacity() * location.getCapacityMultiplicationFactor());
502  assert this.getActualEfficiency() <= 1 : this.getActualEfficiency();
503  this.setDismantleTime(1000);
504  this.calculateAndSetActualInvestedCapital(time);
505  this.calculateAndSetActualFixedOperatingCosts(time);
506  this.setExpectedEndOfLife(time + getActualPermittime()
507  + getActualLeadtime() + getTechnology().getExpectedLifetime());
508  }
509 
510  @Transactional
511  public void createOrUpdateLoan(Loan loan) {
512  this.setLoan(loan);
513  }
514 
515  @Transactional
516  public void createOrUpdateDownPayment(Loan downpayment) {
517  this.setDownpayment(downpayment);
518  }
519 
520  public double getExpectedEndOfLife() {
521  return expectedEndOfLife;
522  }
523 
524  public void setExpectedEndOfLife(double expectedEndOfLife) {
525  this.expectedEndOfLife = expectedEndOfLife;
526  }
527 
528  @Transactional
529  public void updateFuelMix(Set<SubstanceShareInFuelMix> fuelMix) {
530  this.setFuelMix(fuelMix);
531  }
532 
536  public double getActualNominalCapacity() {
537  return actualNominalCapacity;
538  }
539 
544  public void setActualNominalCapacity(double actualNominalCapacity) {
545  if (actualNominalCapacity < 0)
546  throw new RuntimeException("ERROR: " + this.name + " power plant is being set with a negative capacity!");
547  this.actualNominalCapacity = actualNominalCapacity;
548  }
549 
553  public double getActualFixedOperatingCost() {
554  return actualFixedOperatingCost;
555  }
556 
561  public void setActualFixedOperatingCost(double actualFixedOperatingCost) {
562  this.actualFixedOperatingCost = actualFixedOperatingCost;
563  }
564 
565  IntermittentTechnologyNodeLoadFactor getIntermittentTechnologyNodeLoadFactor(){
566  return intermittentTechnologyNodeLoadFactorRepository
567  .findIntermittentTechnologyNodeLoadFactorForNodeAndTechnology(this.getLocation(),
568  this.getTechnology());
569  }
570 
571 }
boolean isWithinTechnicalLifetime(long currentTick)
void setActualNominalCapacity(double actualNominalCapacity)
void calculateAndSetActualInvestedCapital(long timeOfPermitorBuildingStart)
void setActualFixedOperatingCost(double actualFixedOperatingCost)
void specifyAndPersist(long time, EnergyProducer energyProducer, PowerGridNode location, PowerGeneratingTechnology technology)