Skip to content

Commit

Permalink
Thermal storage also used in MTS, heating plots updated, new fuel typ…
Browse files Browse the repository at this point in the history
…es (ELE - electricity and THE thermal energy) useful for storage technologies
  • Loading branch information
MPavicevic committed May 20, 2021
1 parent f7d5062 commit 5f1a899
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 48 deletions.
40 changes: 22 additions & 18 deletions dispaset/GAMS/UCM_h.gms
Original file line number Diff line number Diff line change
Expand Up @@ -130,17 +130,17 @@ Markup(u,h) [EUR\MW] Markup
OutageFactor(au,h) [%] Outage Factor (100% = full outage)
PartLoadMin(au) [%] Minimum part load
PowerCapacity(au) [MW\u] Installed capacity
PowerInitial(au) [MW\u] Power output before initial period
PowerInitial(u) [MW\u] Power output before initial period
PowerMinStable(au) [MW\u] Minimum power output
PriceTransmission(l,h) [EUR\MWh] Transmission price
StorageChargingCapacity(au) [MW\u] Storage capacity
StorageChargingEfficiency(au) [%] Charging efficiency
StorageSelfDischarge(au) [%\day] Self-discharge of the storage units
RampDownMaximum(u) [MW\h\u] Ramp down limit
RampShutDownMaximum(u) [MW\h\u] Shut-down ramp limit
RampStartUpMaximum(u) [MW\h\u] Start-up ramp limit
RampStartUpMaximumH(u,h) [MW\h\u] Start-up ramp limit - Clustered formulation
RampShutDownMaximumH(u,h) [MW\h\u] Shut-down ramp limit - Clustered formulation
RampShutDownMaximum(au) [MW\h\u] Shut-down ramp limit
RampStartUpMaximum(au) [MW\h\u] Start-up ramp limit
RampStartUpMaximumH(au,h) [MW\h\u] Start-up ramp limit - Clustered formulation
RampShutDownMaximumH(au,h) [MW\h\u] Shut-down ramp limit - Clustered formulation
RampUpMaximum(u) [MW\h\u] Ramp up limit
Reserve(t) [n.a.] Reserve technology {1 0}
StorageCapacity(au) [MWh\u] Storage capacity
Expand All @@ -158,14 +158,14 @@ MaxCapacityPtL(p2h2) [MW] Max capacity of PtL
$If %RetrieveStatus% == 1 CommittedCalc(u,z) [n.a.] Committment status as for the MILP
Nunits(au) [n.a.] Number of units inside the cluster (upper bound value for integer variables)
K_QuickStart(n) [n.a.] Part of the reserve that can be provided by offline quickstart units
QuickStartPower(u,h) [MW\h\u] Available max capacity in tertiary regulation up from fast-starting power plants - TC formulation
QuickStartPower(au,h) [MW\h\u] Available max capacity in tertiary regulation up from fast-starting power plants - TC formulation
;

*Parameters as used within the loop
PARAMETERS
CostLoadShedding(n,h) [EUR\MW] Value of lost load
LoadMaximum(au,h) [%] Maximum load given AF and OF
PowerMustRun(u,h) [MW\u] Minimum power output
PowerMustRun(au,h) [MW\u] Minimum power output
StorageFinalMin(au) [MWh] Minimum storage level at the end of the optimization horizon
MaxFlexDemand(n) [MW] Maximum value of the flexible demand parameter
MaxOverSupply(n,h) [MWh] Maximum flexible demand accumultation
Expand Down Expand Up @@ -402,18 +402,18 @@ DemandModulation(n,h) [MW] Difference between the flexible demand and th

*Initial commitment status
CommittedInitial(au)=0;
CommittedInitial(au)$(PowerInitial(au)>0)=1;
CommittedInitial(u)$(PowerInitial(u)>0)=1;

* Definition of the minimum stable load:
PowerMinStable(au) = PartLoadMin(au)*PowerCapacity(au);

LoadMaximum(au,h)= AvailabilityFactor(au,h)*(1-OutageFactor(au,h));

* parameters for clustered formulation (quickstart is defined as the capability to go to minimum power in 15 min)
QuickStartPower(u,h) = 0;
QuickStartPower(u,h)$(RampStartUpMaximum(u)>=PowerMinStable(u)*4) = PowerCapacity(u)*LoadMaximum(u,h);
RampStartUpMaximumH(u,h) = min(PowerCapacity(u)*LoadMaximum(u,h),max(RampStartUpMaximum(u),PowerMinStable(u),QuickStartPower(u,h)));
RampShutDownMaximumH(u,h) = min(PowerCapacity(u)*LoadMaximum(u,h),max(RampShutDownMaximum(u),PowerMinStable(u)));
QuickStartPower(au,h) = 0;
QuickStartPower(au,h)$(RampStartUpMaximum(au)>=PowerMinStable(au)*4) = PowerCapacity(au)*LoadMaximum(au,h);
RampStartUpMaximumH(au,h) = min(PowerCapacity(au)*LoadMaximum(au,h),max(RampStartUpMaximum(au),PowerMinStable(au),QuickStartPower(au,h)));
RampShutDownMaximumH(au,h) = min(PowerCapacity(au)*LoadMaximum(au,h),max(RampShutDownMaximum(au),PowerMinStable(au)));

PowerMustRun(u,h)=PowerMinStable(u)*LoadMaximum(u,h);
PowerMustRun(u,h)$(sum(tr,Technology(u,tr))>=1 and smin(n,Location(u,n)*(1-Curtailment(n)))=1) = PowerCapacity(u)*LoadMaximum(u,h);
Expand Down Expand Up @@ -748,6 +748,7 @@ EQ_thms_Heat_available(thms,i)..
=L=
PowerCapacity(thms)
*LoadMaximum(thms,i)
*Committed(thms,i)
;

*Storage level must be above a minimum
Expand Down Expand Up @@ -777,7 +778,8 @@ EQ_Storage_input(s,i)..
EQ_Storage_MaxDischarge(s,i)$(StorageCapacity(s)>PowerCapacity(s)*TimeStep)..
Power(s,i)*TimeStep/(max(StorageDischargeEfficiency(s),0.0001))
=L=
StorageInitial(s)$(ord(i) = 1) + StorageLevel(s,i-1)$(ord(i) > 1)
StorageInitial(s)$(ord(i) = 1)
+ StorageLevel(s,i-1)$(ord(i) > 1)
+StorageInflow(s,i)*Nunits(s)*TimeStep
;

Expand Down Expand Up @@ -898,7 +900,7 @@ EQ_P2H(p2h,i)..
EQ_Max_P2H(p2h,i)..
PowerConsumption(p2h,i)
=L=
PowerCapacity(p2h) * Nunits(p2h)
PowerCapacity(p2h) * Committed(p2h,i)
;

*EQ_CHP_demand_satisfaction(th,i)..
Expand Down Expand Up @@ -948,7 +950,7 @@ EQ_Heat_Storage_level(th,i)..
EQ_Heat_Storage_input(thms,i)..
StorageInput(thms,i)
=L=
StorageChargingCapacity(thms)
StorageChargingCapacity(thms)*(Nunits(thms)-Committed(thms,i))
;

* Heat storage discharge is limited by the remaining storage capacity
Expand Down Expand Up @@ -1077,7 +1079,7 @@ if (mod(Config("RollingHorizon Length","day")*24,TimeStep) <> 0, abort "The roll

* Some parameters used for debugging:
failed=0;
parameter CommittedInitial_dbg(au), PowerInitial_dbg(au), StorageInitial_dbg(au);
parameter CommittedInitial_dbg(au), PowerInitial_dbg(u), StorageInitial_dbg(au);

* Fixing the initial guesses:
*PowerH.L(u,i)=PowerInitial(u);
Expand Down Expand Up @@ -1120,13 +1122,14 @@ $label skipdisplay3
status("model",i) = UCM_SIMPLE.Modelstat;
status("solver",i) = UCM_SIMPLE.Solvestat;

if(UCM_SIMPLE.Modelstat <> 1 and UCM_SIMPLE.Modelstat <> 8 and not failed, CommittedInitial_dbg(au) = CommittedInitial(au); PowerInitial_dbg(au) = PowerInitial(au); StorageInitial_dbg(au) = StorageInitial(au);
if(UCM_SIMPLE.Modelstat <> 1 and UCM_SIMPLE.Modelstat <> 8 and not failed, CommittedInitial_dbg(au) = CommittedInitial(au); PowerInitial_dbg(u) = PowerInitial(u); StorageInitial_dbg(au) = StorageInitial(au);
EXECUTE_UNLOAD "debug.gdx" day, status, CommittedInitial_dbg, PowerInitial_dbg, StorageInitial_dbg;
failed=1;);

CommittedInitial(au)=sum(i$(ord(i)=LastKeptHour-FirstHour+1),Committed.L(au,i));
PowerInitial(u) = sum(i$(ord(i)=LastKeptHour-FirstHour+1),Power.L(u,i));
StorageInitial(s) = sum(i$(ord(i)=LastKeptHour-FirstHour+1),StorageLevel.L(s,i));
StorageInitial(thms) = sum(i$(ord(i)=LastKeptHour-FirstHour+1),StorageLevel.L(thms,i));
StorageInitial(chp) = sum(i$(ord(i)=LastKeptHour-FirstHour+1),StorageLevel.L(chp,i));
$If %ActivateFlexibleDemand% == 1 AccumulatedOverSupply_inital(n) = sum(i$(ord(i)=LastKeptHour-FirstHour+1),AccumulatedOverSupply.L(n,i));

Expand Down Expand Up @@ -1192,7 +1195,7 @@ OutputReserve_2D(u,h)
OutputReserve_3U(u,h)
ShadowPrice_RampUp_TC(u,h)
ShadowPrice_RampDown_TC(u,h)
OutputRampRate(u,h)
OutputRampRate(au,h)
OutputStartUp(au,h)
OutputShutDown(au,h)
;
Expand Down Expand Up @@ -1249,6 +1252,7 @@ OutputReserve_3U(u,z) = Reserve_3U.L(u,z);
ShadowPrice_RampUp_TC(u,z) = EQ_RampUp_TC.m(u,z);
ShadowPrice_RampDown_TC(u,z) = EQ_RampDown_TC.m(u,z);
OutputRampRate(u,z) = - Power.L(u,z-1)$(ord(z) > 1) - PowerInitial(u)$(ord(z) = 1) + Power.L(u,z);
OutputRampRate(hu,z) = - Heat.L(hu,z-1)$(ord(z) > 1) + Heat.L(hu,z);
OutputStartUp(au,z) = StartUp.L(au,z);
OutputShutDown(au,z) = ShutDown.L(au,z);

Expand Down
8 changes: 5 additions & 3 deletions dispaset/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@
commons['types_CHP'] = ['extraction', 'back-pressure', 'p2h']
# DispaSET fuels:
commons['Fuels'] = ['AIR', 'BIO', 'GAS', 'HRD', 'LIG', 'NUC', 'OIL', 'PEA', 'SUN', 'WAT', 'WIN', 'WST', 'OTH', 'GEO',
'HYD', 'WHT']
'HYD', 'WHT', 'ELE', 'THE']
# Ordered list of fuels for plotting (the first ones are negative):
commons['MeritOrder'] = ['SCSP', 'BATS', 'BEVS', 'HDAM', 'HPHS', 'P2GS', 'FlowOut', 'GEO', 'NUC', 'LIG',
'HRD', 'BIO', 'GAS', 'OIL', 'PEA', 'WST', 'OTH', 'SUN', 'WIN', 'FlowIn', 'WAT',
'HYD', 'AIR', 'WHT']
commons['MeritOrderHeat'] = ['GEO', 'NUC', 'LIG', 'HRD', 'BIO', 'GAS', 'OIL', 'PEA', 'WST', 'OTH', 'SUN', 'WIN', 'WAT',
'HYD', 'AIR', 'WHT', 'HeatSlack', 'THMS']
'HYD', 'AIR', 'WHT', 'ELE', 'THE', 'HeatSlack', 'THMS']

# Colors associated with each fuel:
# commons['colors'] = {'LIG': '#af4b9180', 'PEA': '#af4b9199', 'HRD': '#af4b91b2', 'OIL': '#af4b91ff',
Expand Down Expand Up @@ -85,14 +85,16 @@
'ShedLoad': '#ffffffff',
'AIR': '#aed6f1ff',
'WHT': '#a93226ff',
'ELE': '#2C75FFff',
'THE': '#c70509ff',
'HeatSlack': '#943126ff'}

commons['colors']['curtailment'] = 'red'
# Hatches associated with each fuel:
commons['hatches'] = {'LIG': '', 'PEA': '', 'HRD': '', 'OIL': '', 'GAS': '', 'NUC': '', 'SUN': '', 'WIN': '', 'WAT': '',
'BIO': '', 'GEO': '', 'Storage': '', 'WST': '', 'OTH': '', 'HYD': '',
'FlowIn': '/', 'FlowOut': '\\', 'HDAM': '/', 'HPHS': '/', 'SCSP': '/', 'THMS': '', 'BATS': '/',
'BEVS': '/', 'P2GS': '/', 'AIR': '', 'WHT': '', 'HeatSlack': '/'
'BEVS': '/', 'P2GS': '/', 'AIR': '', 'WHT': '', 'HeatSlack': '/', 'ELE': '', 'THE': ''
}

commons['logfile'] = str(datetime.datetime.now()).replace(':', '-').replace(' ', '_') + '.dispa.log'
Expand Down

0 comments on commit 5f1a899

Please sign in to comment.