Commit fe668ada authored by Topi Rasku's avatar Topi Rasku
Browse files

Issue #55: Added a new 'param_eff' set for 'ts_effUnit' and 'ts_effGroupUnit',...

Issue #55: Added a new 'param_eff' set for 'ts_effUnit' and 'ts_effGroupUnit', used 'param_unit' for 'ts_unit' for the time being. Created 'unit_timeseries' set to simplify writing conditionals for units with time series data. "inputsLoop" should now work for 'ts_unit', but the nature of 'ts_effUnit' and 'ts_effGroupUnit' should be further discussed before their inclusion into "inputsLoop".
parent f8a09480
......@@ -313,6 +313,13 @@ param_unit "Set of possible data parameters for units" /
lastStepNotAggregated "Last time step when the unit is not yet aggregated - calculated in inputsLoop.gms for units that have aggregation"
/
param_eff "Parameters used for unit efficiency approximations" /
lb "Minimum load of the unit"
op "Maximum load of the unit, or the operating point of the SOS2 variable in the piecewise linear heat rate approximation (lambda)"
section "Operational heat rate of the unit, or the SOS2 variable in the piecewise linear heat rate approximation (lambda)"
slope "Heat rate parameter representing no-load fuel consumption"
/
param_fuel "Parameters for fuels" /
main "Main fuel of the unit - unless input fuels defined as grids"
startup "Startup fuel of the unit, if exists. Can be the same as main fuel - consumption using startupFuelCons"
......
......@@ -48,6 +48,7 @@ Sets
unittype "Unit technology types"
unit_investLP(unit) "Units with continuous investments allowed"
unit_investMIP(unit) "Units with integer investments allowed"
unit_timeseries(unit) "Units with time series enabled"
* --- Nodes -------------------------------------------------------------------
node_spill(node) "Nodes that can spill; used to remove v_spill variables where not relevant"
......
......@@ -60,8 +60,8 @@ Parameters
p_fuelEmission(fuel, emission) "Fuel emission content"
p_uFuel(unit, param_fuel, fuel, param_unitFuel) "Parameters interacting between units and fuels"
p_unitFuelEmissionCost(unit, fuel, emission) "Emission costs for each unit, calculated from input data"
p_effUnit(effSelector, unit, effSelector, *) "Data for piece-wise linear efficiency blocks"
p_effGroupUnit(effSelector, unit, *) "Unit data specific to a efficiency group (e.g. left border of the unit)"
p_effUnit(effSelector, unit, effSelector, param_eff) "Data for piece-wise linear efficiency blocks"
p_effGroupUnit(effSelector, unit, param_eff) "Unit data specific to a efficiency group (e.g. left border of the unit)"
p_uNonoperational(unit, starttype, min_max) "Non-operational time after being shut down before start up"
p_uStartup(unit, starttype, cost_consumption) "Startup cost and fuel consumption"
p_u_maxOutputInLastRunUpInterval(unit) "Maximum output in the last interval for the run-up to min. load (p.u.)"
......@@ -76,11 +76,13 @@ Parameters
p_uCounter_shutdownMin(unit, counter) "Minimum output for the time steps where the unit is being shut down from the minimum load (minimum output in the first interval) (p.u.)"
p_uCounter_shutdownMax(unit, counter) "Maximum output for the time steps where the unit is being shut down from the minimum load (minimum output in the first interval) (p.u.)"
// Time dependent unit & fuel parameters
ts_unit(unit, *, f, t) "Time dependent unit data, where energy type doesn't matter"
ts_effUnit(effSelector, unit, effSelector, *, f, t) "Time dependent data for piece-wise linear efficiency blocks"
ts_effGroupUnit(effSelector, unit, *, f, t) "Time dependent efficiency group unit data"
ts_unit(unit, param_unit, f, t) "Time dependent unit data, where energy type doesn't matter"
ts_effUnit(effSelector, unit, effSelector, param_eff, f, t) "Time dependent data for piece-wise linear efficiency blocks"
ts_effGroupUnit(effSelector, unit, param_eff, f, t) "Time dependent efficiency group unit data"
// Alias used for interval aggregation
ts_unit_(unit, *, f, t)
ts_unit_(unit, param_unit, f, t)
* ts_effUnit_(effSelector, unit, effSelector, param_eff, f, t)
* ts_effGroupUnit_(effSelector, unit, param_eff, f, t)
;
* --- Probability -------------------------------------------------------------
......@@ -153,9 +155,9 @@ Parameters
ts_fuelPrice_(fuel, t) "Mean fuel price time during time step (EUR/MWh)"
// Aliases used for updating data in inputsLoop.gms
ts_unit_update(unit, *, f, t)
ts_effUnit_update(effSelector, unit, effSelector, *, f, t)
ts_effGroupUnit_update(effSelector, unit, *, f, t)
ts_unit_update(unit, param_unit, f, t)
ts_effUnit_update(effSelector, unit, effSelector, param_eff, f, t)
ts_effGroupUnit_update(effSelector, unit, param_eff, f, t)
ts_influx_update(grid, node, f, t)
ts_cf_update(flow, node, f, t)
ts_reserveDemand_update(restype, up_down, node, f, t)
......
......@@ -176,6 +176,9 @@ unitStarttype(unit, starttypeConstrained)${ p_unit(unit, 'startWarmAfterXhours')
}
= yes;
// Units with time series data enabled
unit_timeseries(unit)${ p_unit(unit, 'useTimeseries') }
= yes;
* --- Unit Related Parameters -------------------------------------------------
......
......@@ -284,7 +284,7 @@ loop(effGroupSelectorUnit(effSelector, unit, effSelector_),
// Parameters for direct conversion units without online variables
if(effDirectOff(effSelector),
p_effUnit(effSelector, unit, effSelector, 'lb') = 0; // No min load for the DirectOff approximation
p_effUnit(effSelector, unit, effSelector, 'op') = smax(op, p_unit(unit, op));
p_effUnit(effSelector, unit, effSelector, 'op') = smax(op, p_unit(unit, op)); // Maximum operating point
p_effUnit(effSelector, unit, effSelector, 'slope') = 1 / smax(eff${p_unit(unit, eff)}, p_unit(unit, eff)); // Uses maximum found (nonzero) efficiency.
p_effUnit(effSelector, unit, effSelector, 'section') = 0; // No section for the DirectOff approximation
); // END if(effDirectOff)
......
......@@ -114,6 +114,9 @@ $iftheni.debug NOT '%debug%' == 'yes'
* --- Temporary Time Series ---------------------------------------------------
// Initialize temporary time series
Option clear = ts_unit_;
* Option clear = ts_effUnit_;
* Option clear = ts_effGroupUnit_;
Option clear = ts_influx_;
Option clear = ts_cf_;
Option clear = ts_unit_;
......@@ -523,29 +526,6 @@ uft_onlineLP(uft(unit, f, t))${ suft('directOnLP', unit, f, t) }
= yes;
uft_onlineMIP(uft_online(unit, f, t)) = uft_online(unit, f, t) - uft_onlineLP(unit, f, t);
// Calculate time series form parameters for units using direct input output conversion without online variable
// Always constant 'lb', 'rb', and 'section', so need only to define 'slope'.
loop(effGroupSelectorUnit(effDirectOff, unit, effDirectOff_)${ p_unit(unit, 'useTimeseries') },
ts_effUnit(effDirectOff, unit, effDirectOff_, 'slope', ft(f, t))${ sum(eff, ts_unit(unit, eff, f, t)) } // NOTE!!! Averages the slope over all available data.
= sum(eff${ts_unit(unit, eff, f, t)}, 1 / ts_unit(unit, eff, f, t))
/ sum(eff${ts_unit(unit, eff, f, t)}, 1);
); // END loop(effGroupSelectorUnit)
// NOTE! Using the same methodology for the directOn and lambda approximations in time series form might require looping over ft(f,t) to find the min and max 'eff' and 'rb'
// Alternatively, one might require that the 'rb' is defined in a similar structure, so that the max 'rb' is located in the same index for all ft(f,t)
// Calculate unit wide parameters for each efficiency group
loop(effLevelGroupUnit(effLevel, effGroup, unit)${ mSettingsEff(mSolve, effLevel)
and p_unit(unit, 'useTimeseries')
},
ts_effGroupUnit(effGroup, unit, 'rb', ft(f, t))${ sum(effSelector, ts_effUnit(effGroup, unit, effSelector, 'rb', f, t))}
= smax(effSelector$effGroupSelectorUnit(effGroup, unit, effSelector), ts_effUnit(effGroup, unit, effSelector, 'rb', f, t));
ts_effGroupUnit(effGroup, unit, 'lb', ft(f, t))${ sum(effSelector, ts_effUnit(effGroup, unit, effSelector, 'lb', f, t))}
= smin(effSelector${effGroupSelectorUnit(effGroup, unit, effSelector)}, ts_effUnit(effGroup, unit, effSelector, 'lb', f, t));
ts_effGroupUnit(effGroup, unit, 'slope', ft(f, t))${sum(effSelector, ts_effUnit(effGroup, unit, effSelector, 'slope', f, t))}
= smin(effSelector$effGroupSelectorUnit(effGroup, unit, effSelector), ts_effUnit(effGroup, unit, effSelector, 'slope', f, t)); // Uses maximum efficiency for the group
); // END loop(effLevelGroupUnit)
// Units with start-up and shutdown trajectories
Option clear = uft_startupTrajectory;
Option clear = uft_shutdownTrajectory;
......
......@@ -36,42 +36,43 @@ tt_forecast(t_current(t))
= yes;
if (ord(tSolve) >= tForecastNext(mSolve),
$ontext
* These don't work due to the wild cards in the parameter definitions!
// Update ts_unit
if (mTimeseries_loop_read(mSolve, 'ts_unit'),
put_utility 'gdxin' / '%input_dir%/ts_unit/' tSolve.tl:0 '.gdx';
execute_load ts_unit_update=ts_unit;
ts_unit(unit, *, f_solve(f), tt_forecast(t))
ts_unit(unit_timeseries(unit), param_unit, f_solve(f), tt_forecast(t)) // Only update if time series enabled for the unit
${ not mf_realization(mSolve, f) // Realization not updated
* ts_unit_update(unit, *, f, t) // Update only existing values (zeroes need to be EPS)
* and ts_unit_update(unit, param_unit, f, t) // Update only existing values (zeroes need to be EPS)
}
= ts_unit_update(unit, *, f, t);
= ts_unit_update(unit, param_unit, f, t);
); // END if('ts_unit')
$ontext
* !!! NOTE !!!
* These probably shouldn't be read at all, as p_effUnit and p_effGroupUnit are
* not input data, but calculated based on p_unit
// Update ts_effUnit
if (mTimeseries_loop_read(mSolve, 'ts_effUnit'),
put_utility 'gdxin' / '%input_dir%/ts_effUnit/' tSolve.tl:0 '.gdx';
execute_load ts_effUnit_update=ts_effUnit;
ts_effUnit(effGroupSelectorUnit(effSelector, unit, effSelector), *, f_solve(f), tt_forecast(t))
ts_effUnit(effGroupSelectorUnit(effSelector, unit_timeseries(unit), effSelector), param_eff, f_solve(f), tt_forecast(t)) // Only update if time series enabled for the unit
${ not mf_realization(mSolve, f) // Realization not updated
* ts_effUnit_update(effSelector, unit, effSelector, *, f, t) // Update only existing values (zeroes need to be EPS)
* and ts_effUnit_update(effSelector, unit, effSelector, param_eff, f, t) // Update only existing values (zeroes need to be EPS)
}
= ts_effUnit_update(effSelector, unit, effSelector, *, f, t);
= ts_effUnit_update(effSelector, unit, effSelector, param_eff, f, t);
); // END if('ts_effUnit')
// Update ts_effGroupUnit
if (mTimeseries_loop_read(mSolve, 'ts_effGroupUnit'),
put_utility 'gdxin' / '%input_dir%/ts_effGroupUnit/' tSolve.tl:0 '.gdx';
execute_load ts_effGroupUnit_update=ts_effGroupUnit;
ts_effGroupUnit(effSelector, unit, *, f_solve(f), tt_forecast(t))
ts_effGroupUnit(effSelector, unit_timeseries(unit), param_eff, f_solve(f), tt_forecast(t)) // Only update if time series enabled for the unit
${ not mf_realization(mSolve, f) // Realization not updated
* ts_effGroupUnit_update(effSelector, unit, *, f, t) // Update only existing values (zeroes need to be EPS)
* and ts_effGroupUnit_update(effSelector, unit, param_eff, f, t) // Update only existing values (zeroes need to be EPS)
}
= ts_effGroupUnit_update(effSelector, unit, *, f, t);
= ts_effGroupUnit_update(effSelector, unit, param_eff, f, t);
); // END if('ts_effGroupUnit')
$offtext
// Update ts_influx
if (mTimeseries_loop_read(mSolve, 'ts_influx'),
put_utility 'gdxin' / '%input_dir%/ts_influx/' tSolve.tl:0 '.gdx';
......@@ -172,17 +173,17 @@ if(mSettings(mSolve, 't_improveForecast'),
* --- Calculate the other forecasts relative to the central one ---------------
loop(f_solve(f)${ not mf_realization(mSolve, f) and not mf_central(mSolve, f) },
$ontext
* These don't work due to the wild cards in the parameter definitions!
// ts_unit
ts_unit(unit, *, f, tt(t))
= ts_unit(unit, *, f, t) - ts_unit(unit, *, f+ddf(f), t);
ts_unit(unit_timeseries(unit), param_unit, f, tt(t))// Only update for units with time series enabled
= ts_unit(unit, param_unit, f, t) - ts_unit(unit, param_unit, f+ddf(f), t);
$ontext
* Should these be handled here at all? See above note
// ts_effUnit
ts_effUnit(effGroupSelectorUnit(effSelector, unit, effSelector), *, f, tt(t))
= ts_effUnit(effSelector, unit, effSelector, *, f, t) - ts_effUnit(effSelector, unit, effSelector, *, f+ddf(f), t);
ts_effUnit(effGroupSelectorUnit(effSelector, unit_timeseries(unit), effSelector), param_eff, f, tt(t)) // Only update for units with time series enabled
= ts_effUnit(effSelector, unit, effSelector, param_eff, f, t) - ts_effUnit(effSelector, unit, effSelector, param_eff, f+ddf(f), t);
// ts_effGroupUnit
ts_effGroupUnit(effSelector, unit, *, f, tt(t))
= ts_effGroupUnit(effSelector, unit, *, f, t) - ts_effGroupUnit(effSelector, unit, *, f+ddf(f), t);
ts_effGroupUnit(effSelector, unit_timeseries(unit), param_eff, f, tt(t)) // Only update for units with time series enabled
= ts_effGroupUnit(effSelector, unit, param_eff, f, t) - ts_effGroupUnit(effSelector, unit, param_eff, f+ddf(f), t);
$offtext
// ts_influx
ts_influx(gn(grid, node), f, tt(t))
......@@ -201,28 +202,28 @@ $offtext
* --- Linear improvement of the central forecast ------------------------------
loop(mf_central(mSolve, f),
$ontext
* These don't work due to the wild cards in the parameter definitions!
// ts_unit
ts_unit(unit, *, f, tt(t))
ts_unit(unit_timeseries(unit), param_unit, f, tt(t)) // Only update for units with time series enabled
= [ + (ord(t) - tSolveFirst)
* ts_unit(unit, *, f, t)
* ts_unit(unit, param_unit, f, t)
+ (tSolveFirst - ord(t) + mSettings(mSolve, 't_improveForecast'))
* ts_unit(unit, *, f+ddf_(f), t)
* ts_unit(unit, param_unit, f+ddf_(f), t)
] / mSettings(mSolve, 't_improveForecast');
$ontext
* Should these be handled here at all? See above note
// ts_effUnit
ts_effUnit(effGroupSelectorUnit(effSelector, unit, effSelector), *, f, tt(t))
ts_effUnit(effGroupSelectorUnit(effSelector, unit_timeseries(unit), effSelector), param_eff, f, tt(t)) // Only update for units with time series enabled
= [ + (ord(t) - tSolveFirst)
* ts_effUnit(effSelector, unit, effSelector, *, f, t)
* ts_effUnit(effSelector, unit, effSelector, param_eff, f, t)
+ (tSolveFirst - ord(t) + mSettings(mSolve, 't_improveForecast'))
* ts_effUnit(effSelector, unit, effSelector, *, f+ddf_(f), t)
* ts_effUnit(effSelector, unit, effSelector, param_eff, f+ddf_(f), t)
] / mSettings(mSolve, 't_improveForecast');
// ts_effGroupUnit
ts_effGroupUnit(effSelector, unit, *, f, tt(t))
ts_effGroupUnit(effSelector, unit_timeseries(unit), param_eff, f, tt(t)) // Only update for units with time series enabled
= [ + (ord(t) - tSolveFirst)
* ts_effGroupUnit(effSelector, unit, *, f, t)
* ts_effGroupUnit(effSelector, unit, param_eff, f, t)
+ (tSolveFirst - ord(t) + mSettings(mSolve, 't_improveForecast'))
* ts_effGroupUnit(effSelector, unit, *, f+ddf_(f), t)
* ts_effGroupUnit(effSelector, unit, param_eff, f+ddf_(f), t)
] / mSettings(mSolve, 't_improveForecast');
$offtext
// ts_influx
......@@ -258,17 +259,17 @@ $offtext
* --- Recalculate the other forecasts based on the improved central forecast --
loop(f_solve(f)${ not mf_realization(mSolve, f) and not mf_central(mSolve, f) },
$ontext
* These don't work due to the wild cards in the parameter definitions!
// ts_unit
ts_unit(unit, *, f, tt(t))
= ts_unit(unit, *, f, t) + ts_unit(unit, *, f+ddf(f), t);
ts_unit(unit_timeseries(unit), param_unit, f, tt(t)) // Only update for units with time series enabled
= ts_unit(unit, param_unit, f, t) + ts_unit(unit, param_unit, f+ddf(f), t);
$ontext
* Should these be handled here at all? See above note
// ts_effUnit
ts_effUnit(effGroupSelectorUnit(effSelector, unit, effSelector), *, f, tt(t))
= ts_effUnit(effSelector, unit, effSelector, *, f, t) + ts_effUnit(effSelector, unit, effSelector, *, f+ddf(f), t);
ts_effUnit(effGroupSelectorUnit(effSelector, unit_timeseries(unit), effSelector), param_eff, f, tt(t)) // Only update for units with time series enabled
= ts_effUnit(effSelector, unit, effSelector, param_eff, f, t) + ts_effUnit(effSelector, unit, effSelector, param_eff, f+ddf(f), t);
// ts_effGroupUnit
ts_effGroupUnit(effSelector, unit, *, f, tt(t))
= ts_effGroupUnit(effSelector, unit, *, f, t) + ts_effGroupUnit(effSelector, unit, *, f+ddf(f), t);
ts_effGroupUnit(effSelector, unit_timeseries(unit), param_eff, f, tt(t)) // Only update for units with time series enabled
= ts_effGroupUnit(effSelector, unit, param_eff, f, t) + ts_effGroupUnit(effSelector, unit, param_eff, f+ddf(f), t);
$offtext
// ts_influx
ts_influx(gn(grid, node), f, tt(t))
......@@ -303,13 +304,19 @@ loop(cc(counter),
* --- Select time series data matching the intervals, for stepsPerInterval = 1, this is trivial.
loop(ft(f_solve, tt_interval(t)),
ts_unit_(unit_timeseries(unit), param_unit, f_solve, t) // Only if time series enabled for the unit
= ts_unit(unit, param_unit, f_solve, t+dt_circular(t));
$ontext
* Should these be handled here at all? See above comment
ts_effUnit_(effGroupSelectorUnit(effSelector, unit_timeseries(unit), effSelector), param_eff, f_solve, t)
= ts_effUnit(effSelector, unit, effSelector, param_eff, f_solve, t+dt_circular(t));
ts_effGroupUnit_(effSelector, unit_timeseries(unit), param_eff, f_solve, t)
= ts_effGroupUnit(effSelector, unit, param_eff, f_solve, t+dt_circular(t));
$offtext
ts_cf_(flowNode(flow, node), f_solve, t, s)$msf(mSolve, s, f_solve)
= ts_cf(flow, node, f_solve, t + (dt_sampleOffset(flow, node, 'ts_cf', s) + dt_circular(t)));
ts_influx_(gn(grid, node), f_solve, t, s)$msf(mSolve, s, f_solve)
= ts_influx(grid, node, f_solve, t + (dt_sampleOffset(grid, node, 'ts_influx', s) + dt_circular(t)));
ts_unit_(unit, param_unit, f_solve, t)
${p_unit(unit, 'useTimeseries')} // Only include units that have timeseries attributed to them
= ts_unit(unit, param_unit, f_solve, t+dt_circular(t));
// Reserve demand relevant only up until reserve_length
ts_reserveDemand_(restypeDirectionNode(restype, up_down, node), f_solve, t)
${ord(t) <= tSolveFirst + p_nReserves(node, restype, 'reserve_length')}
......@@ -338,16 +345,24 @@ loop(cc(counter),
and ord(t_) < ord(t) + mInterval(mSolve, 'stepsPerInterval', counter)
}
= yes;
ts_unit_(unit_timeseries(unit), param_unit, f_solve, t)
= sum(tt(t_), ts_unit(unit, param_unit, f_solve, t_+dt_circular(t_)))
/ mInterval(mSolve, 'stepsPerInterval', counter);
$ontext
* Should these be handled here at all? See above comment
ts_effUnit_(effGroupSelectorUnit(effSelector, unit_timeseries(unit), effSelector), param_eff, f_solve, t)
= sum(tt(t_), ts_effUnit(effSelector, unit, effSelector, param_eff, f_solve, t_+dt_circular(t_))))
/ mInterval(mSolve, 'stepsPerInterval', counter);
ts_effGroupUnit_(effSelector, unit_timeseries(unit), param_eff, f_solve, t)
= sum(tt(t_), ts_effGroupUnit(effSelector, unit, param_eff, f_solve, t_+dt_circular(t_))))
/ mInterval(mSolve, 'stepsPerInterval', counter);
$offtext
ts_influx_(gn(grid, node), f_solve, t, s)$msf(mSolve, s, f_solve)
= sum(tt(t_), ts_influx(grid, node, f_solve, t_ + (dt_sampleOffset(grid, node, 'ts_influx', s) + dt_circular(t_))))
/ mInterval(mSolve, 'stepsPerInterval', counter);
ts_cf_(flowNode(flow, node), f_solve, t, s)$msf(mSolve, s, f_solve)
= sum(tt(t_), ts_cf(flow, node, f_solve, t_ + (dt_sampleOffset(flow, node, 'ts_cf', s) + dt_circular(t_))))
/ mInterval(mSolve, 'stepsPerInterval', counter);
ts_unit_(unit, param_unit, f_solve, t)
${ p_unit(unit, 'useTimeseries')} // Only include units with timeseries attributed to them
= sum(tt(t_), ts_unit(unit, param_unit, f_solve, t_+dt_circular(t_)))
/ mInterval(mSolve, 'stepsPerInterval', counter);
// Reserves relevant only until reserve_length
ts_reserveDemand_(restypeDirectionNode(restype, up_down, node), f_solve, t)
${ord(t) <= tSolveFirst + p_nReserves(node, restype, 'reserve_length') }
......@@ -374,6 +389,30 @@ loop(cc(counter),
); // END if(stepsPerInterval)
); // END loop(counter)
* --- Process unit time series data -------------------------------------------
// Calculate time series form parameters for units using direct input output conversion without online variable
// Always constant 'lb', 'rb', and 'section', so need only to define 'slope'.
loop(effGroupSelectorUnit(effDirectOff, unit_timeseries(unit), effDirectOff_),
ts_effUnit(effDirectOff, unit, effDirectOff_, 'slope', ft(f, t))
${ sum(eff, ts_unit(unit, eff, f, t)) } // NOTE!!! Averages the slope over all available data.
= sum(eff${ts_unit(unit, eff, f, t)}, 1 / ts_unit(unit, eff, f, t))
/ sum(eff${ts_unit(unit, eff, f, t)}, 1);
); // END loop(effGroupSelectorUnit)
// NOTE! Using the same methodology for the directOn and lambda approximations in time series form might require looping over ft(f,t) to find the min and max 'eff' and 'rb'
// Alternatively, one might require that the 'rb' is defined in a similar structure, so that the max 'rb' is located in the same index for all ft(f,t)
// Calculate unit wide parameters for each efficiency group
loop(effLevelGroupUnit(effLevel, effGroup, unit)${ mSettingsEff(mSolve, effLevel)
and p_unit(unit, 'useTimeseries')
},
ts_effGroupUnit(effGroup, unit, 'lb', ft(f, t))${ sum(effSelector, ts_effUnit(effGroup, unit, effSelector, 'lb', f, t))}
= smin(effSelector${effGroupSelectorUnit(effGroup, unit, effSelector)}, ts_effUnit(effGroup, unit, effSelector, 'lb', f, t));
ts_effGroupUnit(effGroup, unit, 'slope', ft(f, t))${sum(effSelector, ts_effUnit(effGroup, unit, effSelector, 'slope', f, t))}
= smin(effSelector$effGroupSelectorUnit(effGroup, unit, effSelector), ts_effUnit(effGroup, unit, effSelector, 'slope', f, t)); // Uses maximum efficiency for the group
); // END loop(effLevelGroupUnit)
* =============================================================================
* --- Input data processing ---------------------------------------------------
* =============================================================================
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment