Open lordleoo opened 4 years ago
I like this! Nice idea.
Pull requests are welcome, but I think I'd prefer to start by adding it to MATPOWER where it'll be easier to test and document.
I'm glad you liked it. I hope this makes up for my other issue earlier today.
For MOST manual, you can refer to the following papers and make the following argument:
This feature is particularly useful with renewable energy sources. According to [1-4], operating a wind turbine at 5% below the available (maximum) power from wind contributes significant cost savings on primary reserve. i know that this margin we're talking about is a fraction of PMAX, and it can be defined in mpc.reserve.req as a fixed number; but for a generic one-time solution that applies to all time steps (t) and all scenarios (j), you can just enter it as pweight(:,iwind) = (1/0.95)-1=0.0526;
[1] Ye Wang ; Herman Bayem ; Maria Giralt-Devant ; Vera Silva ; Xavier Guillaud ; Bruno Francois, " Methods for Assessing Available Wind Primary Power Reserve," IEEE {Trans.} on Sustainable Energy, vol. 6, no. 1, pp. 272-280, January 2015. [2] E. Saiz-Marin, J. Garcia-Gonzalez, J. Barquin, and E. Lobato, “Economic assessment of the participation of wind generation in the secondary regulation market,” IEEE Trans. Power Syst., vol. 27, no. 2, pp. 866–874, May 2012. [3] M. Hedayati-Mehdiabadi, K. W. Hedman, and J. Zhang, “Reserve policy optimization for scheduling wind energy and reserve,” IEEE Trans. Power Syst., vol. 33, no. 1, pp. 19–31, Jan. 2018.
and if i may cite my ownself: [4] B. Mohandes, M. S. E. Moursi, N. Hatziargyriou and S. E. Khatib, "A Review of Power System Flexibility With High Penetration of Renewables," in IEEE Transactions on Power Systems, vol. 34, no. 4, pp. 3140-3155, July 2019. doi: 10.1109/TPWRS.2019.2897727
Hi. I'm back. I've implemented this in MATPOWER. i should've done it earlier, it's just 4 lines of code
in MATPOWER library, toggle_reserves.m
replace the line: om.add_lin_constraint('Rreq', r.zones(:, igr), lreq, [], {'R'}); %the original
replace with:
if ~isfield(r,'pweights')
nrz = size(r.zones,1);
r.pweights = zeros(nrz,ng); % remember to check how & where 'r' was created, and whether its fields are transferred from another structure
end
assert(size(r.pweights,2)==ng,'Number of columns of reserve.pweights must be = n_gen');
om.add_lin_constraint('Rreq', [r.zones(:, igr), -r.pweights], lreq, [], {'R','Pg'});
I'm not good with github, not sure how to submit pull-requests. i'll try. @rdzman Dr. Rayman, can we discuss preparting the documentation for this. what is your preferred style, etc.
Thanks, again. I really do like this idea.
I've opened MATPOWER issue #104 to track the inclusion of this feature in MATPOWER, so we can move the discussion there until it's in MATPOWER, and use this space for subsequent inclusion into MOST.
The fixedReserve feature in MOST and MATPOWER allows setting a fixed reserve requirement in power units (i.e. in MW). The system can be divided into zones, and a fixed requirement can be set for each zone. Of course, the system can be declared as one zone, and one fixed reserve value (in MW) is required.
However, going through the literature, i came across many rules-of-thumb for setting the reserve, such as: 1) reserve must be larger than the output of the largest online unit 2) you want to operate some renewable energy source at 5% below its maximum (available) output 3) reserve must be larger than a percentage of a dispatchable/elastic load.
it took me less than an hour to implement this in
MOST
. but i haven't gone throughMATPOWER
files to do it.in the 'mpc.reserve' structure, i'm just going to define a new field called
pweights
pweights
has as many rows as zonespweights
has as many columns as the number of generators that is:size(mpc.reserves.pweights) = [nrz , ng]
wherenrz = size(mpc.reserves.zones,1);
ng = size(mpc.gen,1);
Each element in 'pweights' has a coefficient to be multiplied by Pg of a unit. for example, if i have one zone, and i want the reserve to be at least 50% of the power output of the third generator, then:
pweights = [0 0 0.5 0]; % assuming i have 4 generators
The required changes in most.m are just 2 lines of code. I'll submit this as a pull-request later. my thesis is due in 3 weeks. the mathematical formula of the old constraint is:
sum_i(igr) { R(i(igr)} >= fixed_reserve_requirement
the fixed reserve requirement is called Rreq in most.m the new mathematical formula allows both, fixed reserve (in MW) and a percentage of a unit's outputsum_i(igr) { R(i(igr)} >= fixed_reserve_requirement + coefficient * Pg
rearrange to have all variables on one sidesum_i(igr) { R(i(igr)} - coefficient * Pg>= fixed_reserve_requirement
usually i'd set the fixed_reserve_requirement in this case to 0. but this way, the constraint is generic. you can apply either type or both.
code changes: at line 1042 of
most.m
{ % original block of code:}
% new block of code
% ================================================ a few notes:
let
ng
be the number of generatorslet
igr
be the indices of generators which are willing to provide reserve. if all units provide reserve, thenigr=1:ng
;to implement the reserve criterion that: total reserve >= max(Pg(:))
ng
zones. that is, create r.zones which hasng
rows. (such thatsize(reserves.zones,1) = ng
)pweights
withng
rows; that is:size(reserves.pweights,1) = ng
' and remember to:now define these:
this code here assumes that the reserve from generator (i) is included in the total reserve to replace it. to exclude a generator from contributing reserve to replace its own self, remove its entry from r.zones. for example, remove generator 1 from the total reserve required to replace generator 1
be aware that in small systems (used for tutorials and simple examples), the number of generators is small. requiring all generators to be able to replace on full generator might make the problem infeasible.
if you want your fixed_reserve to be a percentage of some fixed load, you don't need to use the
pweights
method. just grab the sum of all loads frommpc.bus(:,PD)
and throw it in reserves.qtyif you want your
fixed_reserve
to be a percentage of some dispatchable load, then remember to use negative weight for the load inpweights
, because dispatchable load is negative% ======================================================================== % MOST example 3; see how fixed_resreves work
% ======================================================================== % this is the case file now. notice the definition of reserve.pweights