Commit 333c48ca authored by Niina Helistö's avatar Niina Helistö
Browse files

Merge branch 'nhniina_DynamicGenerationPortfolios' into dev

parents 91b43688 397c2c96
......@@ -20,8 +20,7 @@ loop(unit${r_invest(unit)},
* Update capacity values in the child setups
loop(gnu(grid, node, unit)${r_invest(unit)},
tmp = round(r_invest(unit), 0) * p_gnu(grid, node, unit, 'unitSize');
put "p_gnu('", grid.tl, "', '", node.tl, "', '", unit.tl, "', 'capacity') = p_gnu('", grid.tl, "', '", node.tl, "', '", unit.tl, "', 'capacity') + ", tmp, ";"/;
);
put "p_gnu('", grid.tl, "', '", node.tl, "', '", unit.tl, "', 'capacity') = p_gnu('", grid.tl, "', '", node.tl, "', '", unit.tl, "', 'capacity') + ", tmp, ";"/;);
* Do not allow investments in the child setups (commented out at the moment)
*loop(gn2n_directional(grid, node, node_),
......
......@@ -49,13 +49,15 @@ if (mType('building'),
// Define time span of samples
msStart('building', 's000') = 1;
msEnd('building', 's000') = msStart('building', 's000') + mSettings('building', 't_horizon');
msEnd('building', 's000') = msStart('building', 's000') + mSettings('building', 't_end') + mSettings('building', 't_horizon');
// Define the probability (weight) of samples
p_msProbability('building', s) = 0;
p_msProbability('building', 's000') = 1;
p_msWeight('building', s) = 0;
p_msWeight('building', 's000') = 1;
p_msAnnuityWeight('building', s) = 0;
p_msAnnuityWeight('building', 's000') = 1;
* --- Define Time Step Intervals ----------------------------------------------
......
......@@ -65,6 +65,10 @@ if (mType('invest'),
p_msWeight('invest', 's000') = 8760/504;
p_msWeight('invest', 's001') = 8760/504;
p_msWeight('invest', 's002') = 8760/504;
p_msAnnuityWeight('invest', s) = 0;
p_msAnnuityWeight('invest', 's000') = 1/3;
p_msAnnuityWeight('invest', 's001') = 1/3;
p_msAnnuityWeight('invest', 's002') = 1/3;
* --- Define Time Step Intervals ----------------------------------------------
......
......@@ -59,13 +59,15 @@ if (mType('schedule'),
// Define time span of samples
msStart('schedule', 's000') = 1;
msEnd('schedule', 's000') = msStart('schedule', 's000') + mSettings('schedule', 't_horizon');
msEnd('schedule', 's000') = msStart('schedule', 's000') + mSettings('schedule', 't_end') + mSettings('schedule', 't_horizon'); // May not work if using scenarios
// Define the probability (weight) of samples
p_msProbability('schedule', s) = 0;
p_msProbability('schedule', 's000') = 1;
p_msWeight('schedule', s) = 0;
p_msWeight('schedule', 's000') = 1;
p_msAnnuityWeight('schedule', s) = 0;
p_msAnnuityWeight('schedule', 's000') = 1;
// If using long-term samples, uncomment
//ms_central('schedule', 's001') = yes;
......
......@@ -322,6 +322,8 @@ param_unit "Set of possible data parameters for units" /
minUnitCount "Minimum number of units when making integer investments"
// Calculated based on other input data
lastStepNotAggregated "Last time step when the unit is not yet aggregated - calculated in inputsLoop.gms for units that have aggregation"
becomeAvailable "The relative position of the time step when the unit becomes available (calculated from ut(unit, t, start_end))"
becomeUnavailable "The relative position of the time step when the unit becomes unavailable (calculated from ut(unit, t, start_end))"
/
param_eff "Parameters used for unit efficiency approximations" /
......@@ -411,4 +413,6 @@ useConstantOrTimeSeries(param_gnBoundaryProperties) "useTimeSeries and useConsta
// Directional sets that are subsets of others
up_down(param_policy) "Direction set used by some variables, e.g. reserve provisions and generation ramps"
/ up, down /
availabilityLimits(param_unit) "Start and end, e.g. of unit lifetime"
/ becomeAvailable, becomeUnavailable /
; // END parameter set declarations
......@@ -137,7 +137,7 @@ $if defined scenario
gn_forecasts(*, node, timeseries) "Which grid/flow, node and timeseries use short-term forecasts"
gn_scenarios(*, node, timeseries) "Which grid/flow, node and timeseries have data for long-term scenarios"
* --- Sets used for the changing unit aggregation and efficiency approximations
* --- Sets used for the changing unit aggregation and efficiency approximations as well as unit lifetimes
uft(unit, f, t) "Active units on intervals, enables aggregation of units for later intervals"
uft_online(unit, f, t) "Units with any online and startup variables on intervals"
uft_onlineLP(unit, f, t) "Units with LP online and startup variables on intervals"
......@@ -161,12 +161,14 @@ $if defined scenario
unitCounter(unit, counter) "Counter used for restricting excessive looping over the counter set when defining unit startup/shutdown/online time restrictions"
runUpCounter(unit, counter) "Counter used for unit run-up intervals"
shutdownCounter(unit, counter) "Counter used for unit shutdown intervals"
utAvailabilityLimits(unit, t, availabilityLimits) "Time step when the unit becomes available/unavailable, e.g. because of technical lifetime"
* --- Sets used for grouping of units, transfer links, nodes, etc. ------------
uGroup(unit, group) "Units in particular groups"
gnuGroup(grid, node, unit, group) "Combination of grids, nodes and units in particular groups"
gn2nGroup(grid, node, node, group) "Transfer links in particular groups"
gnGroup(grid, node, group) "Combination of grids and nodes in particular groups"
sGroup(s, group) "Samples in particular groups"
* --- Set of timeseries that will be read from files between solves -----------
mTimeseries_loop_read(mType, timeseries) "Those time series that will be read between solves"
......
......@@ -100,6 +100,7 @@ Parameters
* --- Probability -------------------------------------------------------------
Parameters
p_msWeight(mType, s) "Temporal weight of sample: number of similar periods represented by sample s"
p_msAnnuityWeight(mType, s) "Temporal weight of sample: used when calculating annuities"
p_msProbability(mType, s) "Probability to reach sample conditioned on anchestor samples"
p_mfProbability(mType, f) "Probability of forecast"
p_msft_probability(mType, s, f, t) "Probability of forecast"
......@@ -203,4 +204,5 @@ Parameters
p_storageValue(grid, node, t) "Value of stored something at the end of a time step"
p_stepLength(mType, f, t) "Length of an interval in hours"
p_stepLengthNoReset(mType, f, t) "Length of an interval in hours - includes also lengths of previously realized intervals"
p_s_discountFactor(s) "Discount factor for samples when using a multi-year horizon"
;
......@@ -55,6 +55,12 @@ Parameters
r_totalRealizedOperatingCost "Total realized system operating costs over the simulation (MEUR)" / 0 /
r_totalRealizedNetOperatingCost "Total realized system operating costs over the simulation (MEUR)" / 0 /
// Realized System Fixed Costs
r_gnTotalRealizedFixedCost(grid, node) "Total realized system fixed costs in gn over the simulation (MEUR)"
r_gnTotalRealizedFixedCostShare(grid, node) "Total realized system fixed cost gn/g shares over the simulation"
r_gTotalRealizedFixedCost(grid) "Total realized system fixed costs in g over the simulation (MEUR)"
r_totalRealizedFixedCost "Total realized system fixed costs over the simulation (MEUR)" / 0 /
// Realized System Costs
r_gnTotalRealizedCost(grid, node) "Total realized system costs in gn over the simulation (MEUR)"
r_gnTotalRealizedCostShare(grid, node) "Total realized system cost gn/g shares over the simulation"
......
......@@ -62,12 +62,15 @@ $ifthen exist '%input_dir%/inputData.gdx'
$$loaddc ts_priceChange
$$loaddc ts_influx
$$loaddc ts_node
$$loaddc p_s_discountFactor
$$loaddc t_invest
$$loaddc utAvailabilityLimits
$$loaddc p_storageValue
$$loaddc uGroup
$$loaddc gnuGroup
$$loaddc gn2nGroup
$$loaddc gnGroup
$$loaddc sGroup
$$loaddc p_groupPolicy
$$loaddc p_groupPolicy3D
$$loaddc gnss_bound
......@@ -268,6 +271,11 @@ p_unitEmissionCost(unit, node, emission)${nu(node, unit) and p_nEmission(node, e
;
// Unit lifetime
loop(utAvailabilityLimits(unit, t, availabilityLimits),
p_unit(unit, availabilityLimits) = ord(t)
); // END loop(ut)
* =============================================================================
* --- Determine Commodity Price Representation -------------------------------------
* =============================================================================
......@@ -608,6 +616,25 @@ loop( (gnu(grid, node, unit), restypeDirection(restype, up_down)),
); // END if(p_gnuReserves)
); // END loop((gnu,restypeDirection))
* --- Check investment related data -------------------------------------------
// Check that units with LP investment possibility have unitSize
loop( unit_investLP(unit),
if(not sum(gnu(grid, node, unit), abs(p_gnu(grid, node, unit, 'unitSize'))),
put log '!!! Error occurred on unit ', unit.tl:0 /;
put log '!!! Abort: Unit is listed as an investment option but it has no unitSize!' /;
abort "All units with investment possibility should have 'unitSize' in p_gnu!"
); // END if
); // END loop(unit_investLP)
// Check that units with MIP investment possibility have unitSize
loop( unit_investMIP(unit),
if(not sum(gnu(grid, node, unit), abs(p_gnu(grid, node, unit, 'unitSize'))),
put log '!!! Error occurred on unit ', unit.tl:0 /;
put log '!!! Abort: Unit is listed as an investment option but it has no unitSize!' /;
abort "All units with investment possibility should have 'unitSize' in p_gnu!"
); // END if
); // END loop(unit_investMIP)
* =============================================================================
* --- Default values ---------------------------------------------------------
......
......@@ -482,6 +482,18 @@ $ifthen exist '%input_dir%/ts_node3.gdx'
$$gdxin
$endif
$ifthen exist '%input_dir%/p_s_discountFactor2.gdx'
$$gdxin '%input_dir%/p_s_discountFactor2.gdx'
$$loaddcm p_discountFactor
$$gdxin
$endif
$ifthen exist '%input_dir%/p_s_discountFactor3.gdx'
$$gdxin '%input_dir%/p_s_discountFactor3.gdx'
$$loaddcm p_discountFactor
$$gdxin
$endif
$ifthen exist '%input_dir%/t_invest2.gdx'
$$gdxin '%input_dir%/t_invest2.gdx'
$$loaddcm t_invest
......@@ -494,6 +506,18 @@ $ifthen exist '%input_dir%/t_invest3.gdx'
$$gdxin
$endif
$ifthen exist '%input_dir%/utAvailabilityLimits2.gdx'
$$gdxin '%input_dir%/utAvailabilityLimits2.gdx'
$$loaddcm ut
$$gdxin
$endif
$ifthen exist '%input_dir%/utAvailabilityLimits3.gdx'
$$gdxin '%input_dir%/utAvailabilityLimits3.gdx'
$$loaddcm ut
$$gdxin
$endif
$ifthen exist '%input_dir%/p_storageValue2.gdx'
$$gdxin '%input_dir%/p_storageValue2.gdx'
$$loaddcm p_storageValue
......@@ -554,6 +578,18 @@ $ifthen exist '%input_dir%/gnGroup3.gdx'
$$gdxin
$endif
$ifthen exist '%input_dir%/sGroup2.gdx'
$$gdxin '%input_dir%/sGroup2.gdx'
$$loaddcm sGroup
$$gdxin
$endif
$ifthen exist '%input_dir%/sGroup3.gdx'
$$gdxin '%input_dir%/sGroup3.gdx'
$$loaddcm sGroup
$$gdxin
$endif
$ifthen exist '%input_dir%/p_groupPolicy2.gdx'
$$gdxin '%input_dir%/p_groupPolicy2.gdx'
$$loaddcm p_groupPolicy
......
......@@ -21,13 +21,13 @@ Free variables
v_state(grid, node, s, f, t) "State variable for nodes that maintain a state (MWh, unless modified by energyStoredPerUnitOfState and diffCoeff parameters)"
v_genRamp(grid, node, unit, s, f, t) "Change in energy generation or consumption over an interval (MW/h)"
v_transfer(grid, node, node, s, f, t) "Average electricity transmission level from node to node during an interval (MW)"
v_ICramp(grid, node, node, s, f, t) "Change in energy transfer over an interval (MW/h)"
v_ICramp(grid, node, node, s, f, t) "Change in energy transfer over an interval (MW/h)"
;
Integer variables
v_startup_MIP(unit, starttype, s, f, t) "Sub-units started up after/during an interval (p.u.), (MIP variant)"
v_shutdown_MIP(unit, s, f, t) "Sub-units shut down after/during an interval (p.u.) (MIP variant)"
v_online_MIP(unit, s, f, t) "Number of sub-units online for units with unit commitment restrictions"
v_invest_MIP(unit, t) "Number of invested sub-units"
v_invest_MIP(unit) "Number of invested sub-units"
v_investTransfer_MIP(grid, node, node, t) "Number of invested transfer links"
;
Binary variables
......@@ -48,7 +48,7 @@ Positive variables
v_reserve(restype, up_down, grid, node, unit, s, f, t) "Unit capacity reserved for providing reserve of specific type (MW)"
v_investTransfer_LP(grid, node, node, t) "Invested transfer capacity (MW)"
v_online_LP(unit, s, f, t) "Number of sub-units online for 'units' with unit commitment restrictions (LP variant)"
v_invest_LP(unit, t) "Number of invested 'sub-units' (LP variant)"
v_invest_LP(unit) "Number of invested 'sub-units' (LP variant)"
v_gen_inc(grid, node, unit, hr, s, f, t) "Energy generation in hr block in an interval (MW)"
;
......
......@@ -114,7 +114,7 @@ equations
q_instantaneousShareMax(group, s, f, t) "Maximum instantaneous share of generation and controlled import from a group of units and links"
q_constrainedOnlineMultiUnit(group, s, f, t) "Constrained number of online units for a group of units"
q_capacityMargin(grid, node, s, f, t) "There needs to be enough capacity to cover energy demand plus a margin"
q_constrainedCapMultiUnit(group, t) "Constrained unit number ratios and sums for a group of units"
q_constrainedCapMultiUnit(group) "Constrained unit number ratios and sums for a group of units"
q_emissioncap(group, emission) "Limit for emissions"
q_energyShareMax(group) "Maximum energy share of generation and import from a group of units"
q_energyShareMin(group) "Minimum energy share of generation and import from a group of units"
......
......@@ -30,6 +30,7 @@ q_obj ..
+ sum(msft(m, s, f, t),
// Probability (weight coefficient) of (s,f,t)
+ p_msft_probability(m, s, f, t)
* p_s_discountFactor(s) // Discount costs
* [
// Time step length dependent costs
+ p_stepLength(m, f, t)
......@@ -112,7 +113,7 @@ q_obj ..
) // END sum over msft(m, s, f, t)
// Cost of energy storage change
// Cost of energy storage change (note: not discounted)
+ sum(gn_state(grid, node),
+ sum(mft_start(m, f, t)${ p_storageValue(grid, node, t)
and active(m, 'storageValue')
......@@ -135,44 +136,51 @@ q_obj ..
) // END sum(gn_state)
// Investment Costs
+ sum(t_invest(t),
// Unit investment costs (including fixed operation and maintenance costs)
+ sum(gnu(grid, node, unit),
+ v_invest_LP(unit, t)${ unit_investLP(unit) }
* p_gnu(grid, node, unit, 'unitSize')
* [
+ p_gnu(grid, node, unit, 'invCosts') * p_gnu(grid, node, unit, 'annuity')
+ p_gnu(grid, node, unit, 'fomCosts')
]
+ v_invest_MIP(unit, t)${ unit_investMIP(unit) }
* p_gnu(grid, node, unit, 'unitSize')
* [
+ p_gnu(grid, node, unit, 'invCosts') * p_gnu(grid, node, unit, 'annuity')
+ p_gnu(grid, node, unit, 'fomCosts')
]
) // END sum(gnu)
// Transfer link investment costs
+ sum(gn2n_directional(grid, from_node, to_node),
+ v_investTransfer_LP(grid, from_node, to_node, t)${ gn2n_directional_investLP(grid, from_node, to_node) }
* [
+ p_gnn(grid, from_node, to_node, 'invCost')
* p_gnn(grid, from_node, to_node, 'annuity')
+ p_gnn(grid, to_node, from_node, 'invCost')
* p_gnn(grid, to_node, from_node, 'annuity')
] // END * v_investTransfer_LP
+ v_investTransfer_MIP(grid, from_node, to_node, t)${ gn2n_directional_investMIP(grid, from_node, to_node) }
* [
+ p_gnn(grid, from_node, to_node, 'unitSize')
* p_gnn(grid, from_node, to_node, 'invCost')
* p_gnn(grid, from_node, to_node, 'annuity')
+ p_gnn(grid, to_node, from_node, 'unitSize')
* p_gnn(grid, to_node, from_node, 'invCost')
* p_gnn(grid, to_node, from_node, 'annuity')
] // END * v_investTransfer_MIP
) // END sum(gn2n_directional)
) // END sum(t_invest)
+ sum(ms(m, s)${ sum(msft(m, s, f, t), 1) }, // consider ms only if it has active msft
+ p_msAnnuityWeight(m, s) // Sample weighting to calculate annual costs
* p_s_discountFactor(s) // Discount costs
* [
// Unit investment costs (including fixed operation and maintenance costs)
+ sum(gnu(grid, node, unit),
+ v_invest_LP(unit)${ unit_investLP(unit) and sum(msft(m, s, f, t_), uft(unit, f, t_))} // consider unit only if it is active in the sample
* p_gnu(grid, node, unit, 'unitSize')
* [
+ p_gnu(grid, node, unit, 'invCosts') * p_gnu(grid, node, unit, 'annuity')
+ p_gnu(grid, node, unit, 'fomCosts')
]
+ v_invest_MIP(unit)${ unit_investMIP(unit) and sum(msft(m, s, f, t_), uft(unit, f, t_))} // consider unit only if it is active in the sample
* p_gnu(grid, node, unit, 'unitSize')
* [
+ p_gnu(grid, node, unit, 'invCosts') * p_gnu(grid, node, unit, 'annuity')
+ p_gnu(grid, node, unit, 'fomCosts')
]
) // END sum(gnu)
+ sum(t_invest(t)${ord(t) <= msEnd(m, s)},
// Transfer link investment costs
+ sum(gn2n_directional(grid, from_node, to_node),
+ v_investTransfer_LP(grid, from_node, to_node, t)${ gn2n_directional_investLP(grid, from_node, to_node) }
* [
+ p_gnn(grid, from_node, to_node, 'invCost')
* p_gnn(grid, from_node, to_node, 'annuity')
+ p_gnn(grid, to_node, from_node, 'invCost')
* p_gnn(grid, to_node, from_node, 'annuity')
] // END * v_investTransfer_LP
+ v_investTransfer_MIP(grid, from_node, to_node, t)${ gn2n_directional_investMIP(grid, from_node, to_node) }
* [
+ p_gnn(grid, from_node, to_node, 'unitSize')
* p_gnn(grid, from_node, to_node, 'invCost')
* p_gnn(grid, from_node, to_node, 'annuity')
+ p_gnn(grid, to_node, from_node, 'unitSize')
* p_gnn(grid, to_node, from_node, 'invCost')
* p_gnn(grid, to_node, from_node, 'annuity')
] // END * v_investTransfer_MIP
) // END sum(gn2n_directional)
) // END sum(t_invest)
] // END * p_s_discountFactor(s)
) // END sum(ms)
$ifthen.addterms exist '%input_dir%/2c_additional_objective_terms.gms'
$$include '%input_dir%/2c_additional_objective_terms.gms';
......
......@@ -542,12 +542,8 @@ q_maxDownward(gnu(grid, node, unit), msft(m, s, f, t))
+ v_online_MIP(unit, s, f+df_central(f,t), t)${uft_onlineMIP(unit, f, t)}
// Investments to additional non-online capacity
+ sum(t_invest(t_)${ ord(t_)<=ord(t)
and not uft_online(unit, f, t)
},
+ v_invest_LP(unit, t_)${unit_investLP(unit)} // NOTE! v_invest_LP also for consuming units is positive
+ v_invest_MIP(unit, t_)${unit_investMIP(unit)} // NOTE! v_invest_MIP also for consuming units is positive
) // END sum(t_invest)
+ v_invest_LP(unit)${unit_investLP(unit) and not uft_online(unit, f, t)} // NOTE! v_invest_LP also for consuming units is positive
+ v_invest_MIP(unit)${unit_investMIP(unit) and not uft_online(unit, f, t)} // NOTE! v_invest_MIP also for consuming units is positive
] // END * p_gnu(unitSize)
] // END * p_unit(availability)
;
......@@ -595,11 +591,8 @@ q_maxDownwardOfflineReserve(gnu(grid, node, unit), msft(m, s, f, t))
+ p_gnu(grid, node, unit, 'unitSize')
]
* [
+ sum(t_invest(t_)${ ord(t_)<=ord(t)
},
+ v_invest_LP(unit, t_)${unit_investLP(unit)}
+ v_invest_MIP(unit, t_)${unit_investMIP(unit)}
) // END sum(t_invest)
+ v_invest_LP(unit)${unit_investLP(unit)}
+ v_invest_MIP(unit)${unit_investMIP(unit)}
] // END * p_gnu(unitSize)
] // END * p_unit(availability)
......@@ -672,12 +665,8 @@ q_maxUpward(gnu(grid, node, unit), msft(m, s, f, t))
+ v_online_MIP(unit, s, f+df_central(f,t), t)${uft_onlineMIP(unit, f, t)}
// Investments to non-online capacity
+ sum(t_invest(t_)${ ord(t_)<=ord(t)
and not uft_online(unit, f ,t)
},
+ v_invest_LP(unit, t_)${unit_investLP(unit)}
+ v_invest_MIP(unit, t_)${unit_investMIP(unit)}
) // END sum(t_invest)
+ v_invest_LP(unit)${unit_investLP(unit) and not uft_online(unit, f ,t)}
+ v_invest_MIP(unit)${unit_investMIP(unit) and not uft_online(unit, f ,t)}
] // END * p_gnu(unitSize)
] // END * p_unit(availability)
......@@ -751,11 +740,8 @@ q_maxUpwardOfflineReserve(gnu(grid, node, unit), msft(m, s, f, t))
+ p_unit(unit, 'unitCount')
// Investments to new capacity
+ sum(t_invest(t_)${ ord(t_)<=ord(t)
},
+ v_invest_LP(unit, t_)${unit_investLP(unit)}
+ v_invest_MIP(unit, t_)${unit_investMIP(unit)}
) // END sum(t_invest)
+ v_invest_LP(unit)${unit_investLP(unit)}
+ v_invest_MIP(unit)${unit_investMIP(unit)}
] // END * p_gnu(unitSize)
] // END * p_unit(availability)
;
......@@ -777,12 +763,10 @@ q_reserveProvision(gnuRescapable(restypeDirectionGridNode(restype, up_down, grid
+ p_gnuReserves(grid, node, unit, restype, up_down)
* [
+ p_gnu(grid, node, unit, 'capacity')
+ sum(t_invest(t_)${ ord(t_)<=ord(t) },
+ v_invest_LP(unit, t_)${unit_investLP(unit)}
* p_gnu(grid, node, unit, 'unitSize')
+ v_invest_MIP(unit, t_)${unit_investMIP(unit)}
* p_gnu(grid, node, unit, 'unitSize')
) // END sum(t_)
+ v_invest_LP(unit)${unit_investLP(unit)}
* p_gnu(grid, node, unit, 'unitSize')
+ v_invest_MIP(unit)${unit_investMIP(unit)}
* p_gnu(grid, node, unit, 'unitSize')
]
* p_unit(unit, 'availability') // Taking into account availability...
* [
......@@ -948,10 +932,8 @@ q_onlineLimit(ms(m, s), uft_online(unit, f, t))
)${unit_aggregator(unit)} // END sum(unit_)
// Investments into units
+ sum(t_invest(t_)${ord(t_)<=ord(t)},
+ v_invest_LP(unit, t_)${unit_investLP(unit)}
+ v_invest_MIP(unit, t_)${unit_investMIP(unit)}
) // END sum(t_invest)
+ v_invest_LP(unit)${unit_investLP(unit)}
+ v_invest_MIP(unit)${unit_investMIP(unit)}
;
*--- Both q_offlineAfterShutdown and q_onlineOnStartup work when there is only one unit.
......@@ -986,10 +968,8 @@ q_offlineAfterShutdown(s_active(s), uft_online(unit, f, t))
+ p_unit(unit, 'unitCount')
// Investments into units
+ sum(t_invest(t_)${ord(t_)<=ord(t)},
+ v_invest_LP(unit, t_)${unit_investLP(unit)}
+ v_invest_MIP(unit, t_)${unit_investMIP(unit)}
) // END sum(t_invest)
+ v_invest_LP(unit)${unit_investLP(unit)}
+ v_invest_MIP(unit)${unit_investMIP(unit)}
// Units currently online
- v_online_LP(unit, s, f+df_central(f,t), t)${uft_onlineLP(unit, f, t)}
......@@ -1048,7 +1028,6 @@ q_onlineMinUptime(ms(m, s), uft_online(unit, f, t))
q_onlineCyclic(uss_bound(unit, s_, s), m)
${ ms(m, s_)
and ms(m, s)
and tSolveFirst = mSettings(m, 't_start')
}..
// Initial value of the state of the unit at the start of the sample
......@@ -1122,12 +1101,10 @@ q_rampUpLimit(ms(m, s), gnuft_ramp(grid, node, unit, f, t))
// Ramping capability of units without an online variable
+ (
+ p_gnu(grid, node, unit, 'capacity')${not uft_online(unit, f, t)}
+ sum(t_invest(t_)${ ord(t_)<=ord(t) },
+ v_invest_LP(unit, t_)${not uft_online(unit, f, t) and unit_investLP(unit)}
* p_gnu(grid, node, unit, 'unitSize')
+ v_invest_MIP(unit, t_)${not uft_online(unit, f, t) and unit_investMIP(unit)}
* p_gnu(grid, node, unit, 'unitSize')
)
+ v_invest_LP(unit)${(not uft_online(unit, f, t)) and unit_investLP(unit)}
* p_gnu(grid, node, unit, 'unitSize')
+ v_invest_MIP(unit)${(not uft_online(unit, f, t)) and unit_investMIP(unit)}
* p_gnu(grid, node, unit, 'unitSize')
)
* p_gnu(grid, node, unit, 'maxRampUp')
* 60 // Unit conversion from [p.u./min] to [p.u./h]
......@@ -1258,14 +1235,10 @@ q_rampDownLimit(ms(m, s), gnuft_ramp(grid, node, unit, f, t))
// Ramping capability of units without online variable
- (
+ p_gnu(grid, node, unit, 'capacity')${not uft_online(unit, f, t)}
+ sum(t_invest(t_)${ ord(t_)<=ord(t) },
+ v_invest_LP(unit, t_)
${not uft_online(unit, f, t) and unit_investLP(unit)}
* p_gnu(grid, node, unit, 'unitSize')
+ v_invest_MIP(unit, t_)
${not uft_online(unit, f, t) and unit_investMIP(unit)}
* p_gnu(grid, node, unit, 'unitSize')
)
+ v_invest_LP(unit)${(not uft_online(unit, f, t)) and unit_investLP(unit)}
* p_gnu(grid, node, unit, 'unitSize')
+ v_invest_MIP(unit)${(not uft_online(unit, f, t)) and unit_investMIP(unit)}
* p_gnu(grid, node, unit, 'unitSize')
)
* p_gnu(grid, node, unit, 'maxRampDown')
* 60 // Unit conversion from [p.u./min] to [p.u./h]
......@@ -1539,12 +1512,10 @@ q_rampSlack(ms(m, s), gnuft_rampCost(grid, node, unit, slack, f, t))
// Ramping capability of units without an online variable
+ (
+ p_gnu(grid, node, unit, 'capacity')${not uft_online(unit, f, t)}
+ sum(t_invest(t_)${ ord(t_)<=ord(t) },
+ v_invest_LP(unit, t_)${not uft_online(unit, f, t) and unit_investLP(unit)}
* p_gnu(grid, node, unit, 'unitSize')
+ v_invest_MIP(unit, t_)${not uft_online(unit, f, t) and unit_investMIP(unit)}
* p_gnu(grid, node, unit, 'unitSize')
)
+ v_invest_LP(unit)${(not uft_online(unit, f, t)) and unit_investLP(unit)}
* p_gnu(grid, node, unit, 'unitSize')
+ v_invest_MIP(unit)${(not uft_online(unit, f, t)) and unit_investMIP(unit)}
* p_gnu(grid, node, unit, 'unitSize')
)
* p_gnuBoundaryProperties(grid, node, unit, slack, 'rampLimit')
* 60 // Unit conversion from [p.u./min] to [p.u./h]
......@@ -2284,13 +2255,13 @@ q_stateUpwardLimit(gn_state(grid, node), msft(m, s, f, t))
+ ts_node_(grid, node, 'upwardLimit', s, f, t)${ p_gnBoundaryPropertiesForStates(grid, node, 'upwardLimit', 'useTimeseries') }
// Investments
+ sum(gnu(grid, node, unit),
+ sum(gnu(grid, node, unit)${gnuft(grid, node, unit, f, t)},
+ p_gnu(grid, node, unit, 'upperLimitCapacityRatio')
* p_gnu(grid, node, unit, 'unitSize')
* sum(t_invest(t_)${ord(t_)<=ord(t)},
+ v_invest_LP(unit, t_)${unit_investLP(unit)}
+ v_invest_MIP(unit, t_)${unit_investMIP(unit)}
) // END sum(t_invest)
* [
+ v_invest_LP(unit)${unit_investLP(unit)}
+ v_invest_MIP(unit)${unit_investMIP(unit)}
]
) // END sum(gnu)
// Current state of the variable
......@@ -2503,7 +2474,6 @@ q_boundStateMaxDiff(gnn_boundState(grid, node, node_), msft(m, s, f, t)) ..
q_boundCyclic(gnss_bound(gn_state(grid, node), s_, s), m)
${ ms(m, s_)
and ms(m, s)
and tSolveFirst = mSettings(m, 't_start')
}..
// Initial value of the state of the node at the start of the sample s
......@@ -2712,10 +2682,10 @@ q_capacityMargin(gn(grid, node), sft(s, f, t))
// Output capacity investments
+ p_gnu(grid, node, unit, 'unitSize')
* sum(t_invest(t_)${ord(t_)<=ord(t)},
+ v_invest_LP(unit, t_)${unit_investLP(unit)}
+ v_invest_MIP(unit, t_)${unit_investMIP(unit)}
) // END sum(t_invest)
* [
+ v_invest_LP(unit)${unit_investLP(unit)}
+ v_invest_MIP(unit)${unit_investMIP(unit)}
] // END * p_gnu(unitSize)
] // END * p_unit(availability)
) // END sum(gnu_output)
......@@ -2734,10 +2704,10 @@ q_capacityMargin(gn(grid, node), sft(s, f, t))
// Output capacity investments
+ p_gnu(grid, node, unit, 'unitSize')
* sum(t_invest(t_)${ord(t_)<=ord(t)},
+ v_invest_LP(unit, t_)${unit_investLP(unit)}
+ v_invest_MIP(unit, t_)${unit_investMIP(unit)}
) // END sum(t_invest)
* [
+ v_invest_LP(unit)${unit_investLP(unit)}
+ v_invest_MIP(unit)${unit_investMIP(unit)}
] // END * p_gnu(unitSize)
] // END * p_unit(availability)
+ v_gen(grid, node, unit, s, f, t)${not unit_flow(unit)}
) // END sum(gnu_output)
......@@ -2787,7 +2757,7 @@ q_capacityMargin(gn(grid, node), sft(s, f, t))
*--- Constrained Investment Ratios and Sums For Groups of Units -----------
q_constrainedCapMultiUnit(group, t_invest(t))
q_constrainedCapMultiUnit(group)
${ p_groupPolicy(group, 'constrainedCapTotalMax')
or sum(uGroup(unit, group), abs(p_groupPolicy3D(group, 'constrainedCapMultiplier', unit)))
} ..
......@@ -2796,8 +2766,8 @@ q_constrainedCapMultiUnit(group, t_invest(t))
+ sum(uGroup(unit, group),
+ p_groupPolicy3D(group, 'constrainedCapMultiplier', unit)
* [
+ v_invest_LP(unit, t)${unit_investLP(unit)}
+ v_invest_MIP(unit, t)${unit_investMIP(unit)}
+ v_invest_LP(unit)${unit_investLP(unit)}
+ v_invest_MIP(unit)${unit_investMIP(unit)}
] // END * p_groupPolicy3D(group, 'constrainedCapMultiplier', unit)
) // END sum(unit)
......@@ -2816,7 +2786,7 @@ q_emissioncap(group, emission)
${ p_groupPolicy3D(group, 'emissionCap', emission)
} ..
+ sum(msft(m, s, f, t),
+ sum(msft(m, s, f, t)${sGroup(s, group)},
+ p_msft_Probability(m,s,f,t)
* [
// Time step length dependent emissions - calculated from consumption
......@@ -2856,7 +2826,7 @@ q_energyShareMax(group)
${ p_groupPolicy(group, 'energyShareMax')
} ..
+ sum(msft(m, s, f, t),
+ sum(msft(m, s, f, t)${sGroup(s, group)},
+ p_msft_Probability(m,s,f,t)
* p_stepLength(m, f, t)
* [
......@@ -2896,7 +2866,7 @@ q_energyShareMin(group)
${ p_groupPolicy(group, 'energyShareMin')
} ..
+ sum(msft(m, s, f, t),
+ sum(msft(m, s, f, t)${sGroup(s, group)},
+ p_msft_Probability(m,s,f,t)
* p_stepLength(m, f, t)
* [
......
......@@ -725,5 +725,24 @@ loop(m, // Not ideal, but multi-model functionality is not yet implemented
); // END if()
); // END if
* --- Check investment related data -------------------------------------------
loop( unit_investLP(unit),
// Check that the investment decisions are not by accident fixed to zero in 3d_setVariableLimits.gms
if(p_unit(unit, 'becomeAvailable') <= mSettings(m, 't_start'),
put log '!!! Error occurred on unit ', unit.tl:0 /;
put log '!!! Abort: Unit with investment possibility should not become available before t_start!' /;
abort "The 'utAvailabilityLimits(unit, t, 'becomeAvailable')' should correspond to a timestep in the model without the initial timestep!"
); // END if
); // END loop(unit_investLP)