|
1980 | 1980 | mdo = mdi; %% initialize output |
1981 | 1981 | mdo.om = om.copy(); %% make copy of opt_model object, so changes to |
1982 | 1982 | %% output obj (mdo) don't modify input obj (mdi) |
1983 | | -[vv, ll] = mdo.om.get_idx(); |
1984 | 1983 | if mpopt.most.solve_model |
1985 | 1984 | %% check consistency of model options (in case mdi was built in previous call) |
1986 | 1985 | if mdi.DCMODEL ~= mo.DCMODEL |
|
2037 | 2036 | fprintf('- Post-processing results.\n'); |
2038 | 2037 | end |
2039 | 2038 | if success |
| 2039 | + om = mdo.om; |
2040 | 2040 | for t = 1:nt |
2041 | 2041 | if UC |
2042 | | - mdo.UC.CommitSched(:, t) = mdo.QP.x(vv.i1.u(t):vv.iN.u(t)); |
| 2042 | + mdo.UC.CommitSched(:, t) = om.get_soln('var', 'u', {t}); |
2043 | 2043 | end |
2044 | 2044 | for j = 1:mdi.idx.nj(t) |
2045 | 2045 | for k = 1:mdi.idx.nc(t,j)+1 |
|
2049 | 2049 | mpc.bus(:, VM) = 1; |
2050 | 2050 | end |
2051 | 2051 | % Injections and shadow prices |
2052 | | - mpc.gen(:, PG) = baseMVA * mdo.QP.x(vv.i1.Pg(t,j,k):vv.iN.Pg(t,j,k)); |
| 2052 | + mpc.gen(:, PG) = baseMVA * om.get_soln('var', 'Pg', {t,j,k}); |
2053 | 2053 | %% need to update Qg for loads consistent w/constant power factor |
2054 | 2054 | Pmin = mpc.gen(:, PMIN); |
2055 | 2055 | Qmin = mpc.gen(:, QMIN); |
|
2059 | 2059 | mpc.gen(ivl, QG) = mpc.gen(ivl, PG) .* Qlim ./ Pmin(ivl); |
2060 | 2060 | if mdo.DCMODEL |
2061 | 2061 | %% bus angles |
2062 | | - mpc.bus(:, VA) = (180/pi) * mdo.QP.x(vv.i1.Va(t,j,k):vv.iN.Va(t,j,k)); |
| 2062 | + Va = om.get_soln('var', 'Va', {t,j,k}); |
| 2063 | + mpc.bus(:, VA) = (180/pi) * Va; |
2063 | 2064 |
|
2064 | 2065 | %% nodal prices |
2065 | | - price = (mdo.QP.lambda.mu_u(ll.i1.Pmis(t,j,k):ll.iN.Pmis(t,j,k))-mdo.QP.lambda.mu_l(ll.i1.Pmis(t,j,k):ll.iN.Pmis(t,j,k))) / baseMVA; |
| 2066 | + price = (om.get_soln('lin', 'mu_u', 'Pmis', {t,j,k})-om.get_soln('lin', 'mu_l', 'Pmis', {t,j,k})) / baseMVA; |
2066 | 2067 | mpc.bus(:, LAM_P) = price; |
2067 | 2068 |
|
2068 | 2069 | %% line flows and line limit shadow prices |
|
2073 | 2074 | mpc.branch(:, MU_SF) = 0; |
2074 | 2075 | mpc.branch(:, MU_ST) = 0; |
2075 | 2076 | ion = find(mpc.branch(:, BR_STATUS)); |
2076 | | - rows = ll.i1.Pf(t,j,k):ll.iN.Pf(t,j,k); |
2077 | | - cols = vv.i1.Va(t,j,k):vv.iN.Va(t,j,k); |
2078 | | - lf = baseMVA * (mdo.QP.A(rows,cols) * mdo.QP.x(cols) + mdo.flow(t,j,k).PLsh); |
| 2077 | + AA = om.params_lin_constraint('Pf', {t,j,k}); |
| 2078 | + lf = baseMVA * (AA * Va + mdo.flow(t,j,k).PLsh); |
2079 | 2079 | mpc.branch(ion, PF) = lf; |
2080 | 2080 | mpc.branch(ion, PT) = -lf; |
2081 | | - mpc.branch(ion, MU_SF) = mdo.QP.lambda.mu_u(rows) / baseMVA; |
2082 | | - mpc.branch(ion, MU_ST) = mdo.QP.lambda.mu_l(rows) / baseMVA; |
| 2081 | + mpc.branch(ion, MU_SF) = om.get_soln('lin', 'mu_u', 'Pf', {t,j,k}) / baseMVA; |
| 2082 | + mpc.branch(ion, MU_ST) = om.get_soln('lin', 'mu_l', 'Pf', {t,j,k}) / baseMVA; |
2083 | 2083 | else |
2084 | 2084 | %% system price |
2085 | | - price = (mdo.QP.lambda.mu_l(ll.i1.Pmis(t,j,k):ll.iN.Pmis(t,j,k))-mdo.QP.lambda.mu_u(ll.i1.Pmis(t,j,k):ll.iN.Pmis(t,j,k))) / baseMVA; |
| 2085 | + price = (om.get_soln('lin', 'mu_l', 'Pmis', {t,j,k})-om.get_soln('lin', 'mu_u', 'Pmis', {t,j,k})) / baseMVA; |
2086 | 2086 | mpc.bus(:, LAM_P) = price; |
2087 | 2087 | end |
2088 | 2088 | if UC |
2089 | 2089 | % igenon does not contain gens ousted because of a contingency or |
2090 | 2090 | % a forced-off UC.CommitKey |
2091 | 2091 | igenon = find(mpc.gen(:, GEN_STATUS)); |
2092 | | - u = mdo.QP.x(vv.i1.u(t):vv.iN.u(t)); |
2093 | | - mpc.gen(igenon, GEN_STATUS) = u(igenon); |
| 2092 | + mpc.gen(igenon, GEN_STATUS) = mdo.UC.CommitSched(igenon, t); |
2094 | 2093 | gs = mpc.gen(igenon, GEN_STATUS) > 0; % gen status |
2095 | 2094 | mpc.gen(:, MU_PMAX) = 0; |
2096 | 2095 | mpc.gen(:, MU_PMIN) = 0; |
2097 | 2096 | mpc.gen(igenon, MU_PMAX) = gs .* ... |
2098 | | - mdo.QP.lambda.mu_u(ll.i1.uPmax(t,j,k):ll.iN.uPmax(t,j,k)) / baseMVA; |
| 2097 | + om.get_soln('lin', 'mu_u', 'uPmax', {t,j,k}) / baseMVA; |
2099 | 2098 | mpc.gen(igenon, MU_PMIN) = gs .* ... |
2100 | | - mdo.QP.lambda.mu_u(ll.i1.uPmin(t,j,k):ll.iN.uPmin(t,j,k)) / baseMVA; |
| 2099 | + om.get_soln('lin', 'mu_u', 'uPmin', {t,j,k}) / baseMVA; |
2101 | 2100 | if mdo.QCoordination |
2102 | 2101 | mpc.gen(:, MU_QMAX) = 0; |
2103 | 2102 | mpc.gen(:, MU_QMIN) = 0; |
2104 | 2103 | mpc.gen(igenon, MU_QMAX) = gs .* ... |
2105 | | - mdo.QP.lambda.mu_u(ll.i1.uQmax(t,j,k):ll.iN.uQmax(t,j,k)) / baseMVA; |
| 2104 | + om.get_soln('lin', 'mu_u', 'uQmax', {t,j,k}) / baseMVA; |
2106 | 2105 | mpc.gen(igenon, MU_QMIN) = gs .* ... |
2107 | | - mdo.QP.lambda.mu_u(ll.i1.uQmin(t,j,k):ll.iN.uQmin(t,j,k)) / baseMVA; |
| 2106 | + om.get_soln('lin', 'mu_u', 'uQmin', {t,j,k}) / baseMVA; |
2108 | 2107 | end |
2109 | 2108 | else |
2110 | 2109 | gs = mpc.gen(:, GEN_STATUS) > 0; % gen status |
2111 | 2110 | mpc.gen(:, MU_PMAX) = gs .* ... |
2112 | | - mdo.QP.lambda.upper(vv.i1.Pg(t,j,k):vv.iN.Pg(t,j,k)) / baseMVA; |
| 2111 | + om.get_soln('var', 'mu_u', 'Pg', {t,j,k}) / baseMVA; |
2113 | 2112 | mpc.gen(:, MU_PMIN) = gs .* ... |
2114 | | - mdo.QP.lambda.lower(vv.i1.Pg(t,j,k):vv.iN.Pg(t,j,k)) / baseMVA; |
| 2113 | + om.get_soln('var', 'mu_l', 'Pg', {t,j,k}) / baseMVA; |
2115 | 2114 | if mdo.QCoordination |
2116 | 2115 | mpc.gen(:, MU_QMAX) = gs .* ... |
2117 | | - mdo.QP.lambda.upper(vv.i1.Qg(t,j,k):vv.iN.Qg(t,j,k)) / baseMVA; |
| 2116 | + om.get_soln('var', 'mu_u', 'Qg', {t,j,k}) / baseMVA; |
2118 | 2117 | mpc.gen(:, MU_QMIN) = gs .* ... |
2119 | | - mdo.QP.lambda.lower(vv.i1.Qg(t,j,k):vv.iN.Qg(t,j,k)) / baseMVA; |
| 2118 | + om.get_soln('var', 'mu_l', 'Qg', {t,j,k}) / baseMVA; |
2120 | 2119 | end |
2121 | 2120 | end |
2122 | 2121 | if mdi.IncludeFixedReserves |
|
2125 | 2124 | r.R = z; |
2126 | 2125 | r.prc = z; |
2127 | 2126 | r.mu = struct('l', z, 'u', z, 'Pmax', z); |
2128 | | - r.totalcost = sum(mdo.om.eval_quad_cost(mdo.QP.x, 'Rcost', {t,j,k})); |
2129 | | - r.R(r.igr) = mdo.QP.x(vv.i1.R(t,j,k):vv.iN.R(t,j,k)) * baseMVA; |
| 2127 | + r.totalcost = sum(om.get_soln('qdc', 'Rcost', {t,j,k})); |
| 2128 | + r.R(r.igr) = om.get_soln('var', 'R', {t,j,k}) * baseMVA; |
| 2129 | + R_mu_l = om.get_soln('lin', 'mu_l', 'Rreq', {t,j,k}); |
2130 | 2130 | for gg = r.igr |
2131 | 2131 | iz = find(r.zones(:, gg)); |
2132 | | - kk = ll.i1.Rreq(t,j,k):ll.iN.Rreq(t,j,k); |
2133 | | - r.prc(gg) = sum(mdo.QP.lambda.mu_l(kk(iz))) / baseMVA; |
| 2132 | + r.prc(gg) = sum(R_mu_l(iz)) / baseMVA; |
2134 | 2133 | end |
2135 | | - r.mu.l(r.igr) = mdo.QP.lambda.lower(vv.i1.R(t,j,k):vv.iN.R(t,j,k)) / baseMVA; |
2136 | | - r.mu.u(r.igr) = mdo.QP.lambda.upper(vv.i1.R(t,j,k):vv.iN.R(t,j,k)) / baseMVA; |
2137 | | - r.mu.Pmax(r.igr) = mdo.QP.lambda.mu_u(ll.i1.Pg_plus_R(t,j,k):ll.iN.Pg_plus_R(t,j,k)) / baseMVA; |
| 2134 | + r.mu.l(r.igr) = om.get_soln('var', 'mu_l', 'R', {t,j,k}) / baseMVA; |
| 2135 | + r.mu.u(r.igr) = om.get_soln('var', 'mu_u', 'R', {t,j,k}) / baseMVA; |
| 2136 | + r.mu.Pmax(r.igr) = om.get_soln('lin', 'mu_u', 'Pg_plus_R', {t,j,k}) / baseMVA; |
2138 | 2137 | mpc.reserves = r; |
2139 | 2138 | end |
2140 | 2139 | mdo.flow(t,j,k).mpc = mpc; %% stash modified mpc in output struct |
2141 | 2140 | end |
2142 | 2141 | end |
2143 | 2142 | % Contract, contingency reserves, energy limits |
2144 | | - mdo.results.Pc(:,t) = baseMVA * mdo.QP.x(vv.i1.Pc(t):vv.iN.Pc(t)); |
2145 | | - mdo.results.Rpp(:,t) = baseMVA * mdo.QP.x(vv.i1.Rpp(t):vv.iN.Rpp(t)); |
2146 | | - mdo.results.Rpm(:,t) = baseMVA * mdo.QP.x(vv.i1.Rpm(t):vv.iN.Rpm(t)); |
| 2143 | + mdo.results.Pc(:,t) = baseMVA * om.get_soln('var', 'Pc', {t}); |
| 2144 | + mdo.results.Rpp(:,t) = baseMVA * om.get_soln('var', 'Rpp', {t}); |
| 2145 | + mdo.results.Rpm(:,t) = baseMVA * om.get_soln('var', 'Rpm', {t}); |
2147 | 2146 | if ns |
2148 | | - mdo.results.Sm(:,t) = baseMVA * mdo.QP.x(vv.i1.Sm(t):vv.iN.Sm(t)); |
2149 | | - mdo.results.Sp(:,t) = baseMVA * mdo.QP.x(vv.i1.Sp(t):vv.iN.Sp(t)); |
| 2147 | + mdo.results.Sm(:,t) = baseMVA * om.get_soln('var', 'Sm', {t}); |
| 2148 | + mdo.results.Sp(:,t) = baseMVA * om.get_soln('var', 'Sp', {t}); |
2150 | 2149 | end |
2151 | 2150 | end |
2152 | 2151 | % Ramping reserves |
2153 | 2152 | for t = 1:mdo.idx.ntramp |
2154 | | - mdo.results.Rrp(:,t) = baseMVA * mdo.QP.x(vv.i1.Rrp(t):vv.iN.Rrp(t)); |
2155 | | - mdo.results.Rrm(:,t) = baseMVA * mdo.QP.x(vv.i1.Rrm(t):vv.iN.Rrm(t)); |
| 2153 | + mdo.results.Rrp(:,t) = baseMVA * om.get_soln('var', 'Rrp', {t}); |
| 2154 | + mdo.results.Rrm(:,t) = baseMVA * om.get_soln('var', 'Rrm', {t}); |
2156 | 2155 | end |
2157 | 2156 | % Expected energy prices for generators, per generator and per period, |
2158 | 2157 | % both absolute and conditional on making it to that period |
|
2172 | 2171 | mdo.results.RppPrices = zeros(ng, nt); |
2173 | 2172 | mdo.results.RpmPrices = zeros(ng, nt); |
2174 | 2173 | for t = 1:nt |
2175 | | - mdo.results.RppPrices(:, t) = mdo.QP.lambda.lower(vv.i1.Rpp(t):vv.iN.Rpp(t)) / baseMVA; |
2176 | | - mdo.results.RpmPrices(:, t) = mdo.QP.lambda.lower(vv.i1.Rpm(t):vv.iN.Rpm(t)) / baseMVA; |
| 2174 | + mdo.results.RppPrices(:, t) = om.get_soln('var', 'mu_l', 'Rpp', {t}) / baseMVA; |
| 2175 | + mdo.results.RpmPrices(:, t) = om.get_soln('var', 'mu_l', 'Rpm', {t}) / baseMVA; |
2177 | 2176 | for j = 1:mdi.idx.nj(t); |
2178 | 2177 | for k = 1:mdi.idx.nc(t,j)+1 |
2179 | 2178 | ii = find(mdi.flow(t,j,k).mpc.gen(:, GEN_STATUS) > 0); |
2180 | | - mdo.results.RppPrices(ii, t) = mdo.results.RppPrices(ii, t) + mdo.QP.lambda.mu_l(ll.i1.dPpRp(t,j,k):ll.iN.dPpRp(t,j,k)) / baseMVA; |
2181 | | - mdo.results.RpmPrices(ii, t) = mdo.results.RpmPrices(ii, t) + mdo.QP.lambda.mu_l(ll.i1.dPmRm(t,j,k):ll.iN.dPmRm(t,j,k)) / baseMVA; |
| 2179 | + mdo.results.RppPrices(ii, t) = mdo.results.RppPrices(ii, t) + om.get_soln('lin', 'mu_l', 'dPpRp', {t,j,k}) / baseMVA; |
| 2180 | + mdo.results.RpmPrices(ii, t) = mdo.results.RpmPrices(ii, t) + om.get_soln('lin', 'mu_l', 'dPmRm', {t,j,k}) / baseMVA; |
2182 | 2181 | end |
2183 | 2182 | end |
2184 | 2183 | end |
|
2190 | 2189 | for j1 = 1:mdo.idx.nj(t) |
2191 | 2190 | for j2 = 1:mdo.idx.nj(t+1) |
2192 | 2191 | if mdi.tstep(t+1).TransMask(j2,j1) |
2193 | | - mdo.results.RrpPrices(:, t) = mdo.results.RrpPrices(:, t) + mdo.QP.lambda.mu_l(ll.i1.Rrp(t,j1,j2):ll.iN.Rrp(t,j1,j2)) / baseMVA; |
2194 | | - mdo.results.RrmPrices(:, t) = mdo.results.RrmPrices(:, t) + mdo.QP.lambda.mu_l(ll.i1.Rrm(t,j1,j2):ll.iN.Rrm(t,j1,j2)) / baseMVA; |
| 2192 | + mdo.results.RrpPrices(:, t) = mdo.results.RrpPrices(:, t) + om.get_soln('lin', 'mu_l', 'Rrp', {t,j1,j2}) / baseMVA; |
| 2193 | + mdo.results.RrmPrices(:, t) = mdo.results.RrmPrices(:, t) + om.get_soln('lin', 'mu_l', 'Rrm', {t,j1,j2}) / baseMVA; |
2195 | 2194 | end |
2196 | 2195 | end |
2197 | 2196 | end |
2198 | 2197 | end |
2199 | 2198 | % then last period only if specified for with terminal state |
2200 | 2199 | if ~mdo.OpenEnded |
2201 | 2200 | for j1 = 1:mdo.idx.nj(nt) |
2202 | | - mdo.results.RrpPrices(:, nt) = mdo.results.RrpPrices(:, nt) + mdo.QP.lambda.mu_l(ll.i1.Rrp(nt,j1,1):ll.iN.Rrp(nt,j1,1)) / baseMVA; |
2203 | | - mdo.results.RrmPrices(:, nt) = mdo.results.RrmPrices(:, nt) + mdo.QP.lambda.mu_l(ll.i1.Rrm(nt,j1,1):ll.iN.Rrm(nt,j1,1)) / baseMVA; |
| 2201 | + mdo.results.RrpPrices(:, nt) = mdo.results.RrpPrices(:, nt) + om.get_soln('lin', 'mu_l', 'Rrp', {nt,j1,1}) / baseMVA; |
| 2202 | + mdo.results.RrmPrices(:, nt) = mdo.results.RrmPrices(:, nt) + om.get_soln('lin', 'mu_l', 'Rrm', {nt,j1,1}) / baseMVA; |
2204 | 2203 | end |
2205 | 2204 | end |
2206 | 2205 | % Expected wear and tear costs per gen and period |
|
2240 | 2239 | end |
2241 | 2240 | % If Cyclic storage, pull InitialStorage value out of x |
2242 | 2241 | if ns && mdo.Storage.ForceCyclicStorage |
2243 | | - mdo.Storage.InitialStorage = baseMVA * mdo.QP.x(vv.i1.S0:vv.iN.S0); |
| 2242 | + mdo.Storage.InitialStorage = baseMVA * om.get_soln('var', 'S0'); |
2244 | 2243 | end |
2245 | 2244 | % Compute expected storage state trajectory |
2246 | 2245 | mdo.Storage.ExpectedStorageState = zeros(ns,nt); |
|
2267 | 2266 | if nzds |
2268 | 2267 | mdo.results.Z = zeros(nzds, ntds); |
2269 | 2268 | for t = 1:ntds |
2270 | | - mdo.results.Z(:,t) = mdo.QP.x(vv.i1.Z(t):vv.iN.Z(t)); |
| 2269 | + mdo.results.Z(:,t) = om.get_soln('var', 'Z', {t}); |
2271 | 2270 | end |
2272 | 2271 | end |
2273 | 2272 | mdo.results.Y = zeros(nyds, ntds); |
2274 | 2273 | if nyds |
2275 | 2274 | for t = 1:ntds |
2276 | | - mdo.results.Y(:, t) = ... |
2277 | | - mdo.QP.A(ll.i1.DSy(t):ll.iN.DSy(t), :) * mdo.QP.x; |
| 2275 | + AA = om.params_lin_constraint('DSy', {t}); |
| 2276 | + mdo.results.Y(:, t) = AA * mdo.QP.x; |
2278 | 2277 | end |
2279 | 2278 | end |
2280 | 2279 | end |
|
0 commit comments