Package pypower :: Module uopf
[hide private]
[frames] | no frames]

Source Code for Module pypower.uopf

  1  # Copyright (C) 1996-2011 Power System Engineering Research Center (PSERC) 
  2  # Copyright (C) 2011 Richard Lincoln 
  3  # 
  4  # PYPOWER is free software: you can redistribute it and/or modify 
  5  # it under the terms of the GNU General Public License as published 
  6  # by the Free Software Foundation, either version 3 of the License, 
  7  # or (at your option) any later version. 
  8  # 
  9  # PYPOWER is distributed in the hope that it will be useful, 
 10  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 11  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 12  # GNU General Public License for more details. 
 13  # 
 14  # You should have received a copy of the GNU General Public License 
 15  # along with PYPOWER. If not, see <http://www.gnu.org/licenses/>. 
 16   
 17  """Solves combined unit decommitment / optimal power flow. 
 18  """ 
 19   
 20  from time import time 
 21   
 22  from copy import deepcopy 
 23   
 24  from numpy import flatnonzero as find 
 25   
 26  from opf_args import opf_args2 
 27  from ppoption import ppoption 
 28  from isload import isload 
 29  from totcost import totcost 
 30  from fairmax import fairmax 
 31  from opf import opf 
 32   
 33  from idx_bus import PD 
 34  from idx_gen import GEN_STATUS, PG, QG, PMIN, MU_PMIN 
 35   
 36   
37 -def uopf(*args):
38 """Solves combined unit decommitment / optimal power flow. 39 40 Solves a combined unit decommitment and optimal power flow for a single 41 time period. Uses an algorithm similar to dynamic programming. It proceeds 42 through a sequence of stages, where stage C{N} has C{N} generators shut 43 down, starting with C{N=0}. In each stage, it forms a list of candidates 44 (gens at their C{Pmin} limits) and computes the cost with each one of them 45 shut down. It selects the least cost case as the starting point for the 46 next stage, continuing until there are no more candidates to be shut down 47 or no more improvement can be gained by shutting something down. 48 If C{verbose} in ppopt (see L{ppoption} is C{true}, it prints progress 49 info, if it is > 1 it prints the output of each individual opf. 50 51 @see: L{opf}, L{runuopf} 52 53 @author: Ray Zimmerman (PSERC Cornell) 54 @author: Richard Lincoln 55 """ 56 ##----- initialization ----- 57 t0 = time() ## start timer 58 59 ## process input arguments 60 ppc, ppopt = opf_args2(*args) 61 62 ## options 63 verbose = ppopt["VERBOSE"] 64 if verbose: ## turn down verbosity one level for calls to opf 65 ppopt = ppoption(ppopt, VERBOSE=verbose - 1) 66 67 ##----- do combined unit commitment/optimal power flow ----- 68 69 ## check for sum(Pmin) > total load, decommit as necessary 70 on = find( (ppc["gen"][:, GEN_STATUS] > 0) & ~isload(ppc["gen"]) ) ## gens in service 71 onld = find( (ppc["gen"][:, GEN_STATUS] > 0) & isload(ppc["gen"]) ) ## disp loads in serv 72 load_capacity = sum(ppc["bus"][:, PD]) - sum(ppc["gen"][onld, PMIN]) ## total load capacity 73 Pmin = ppc["gen"][on, PMIN] 74 while sum(Pmin) > load_capacity: 75 ## shut down most expensive unit 76 avgPmincost = totcost(ppc["gencost"][on, :], Pmin) / Pmin 77 _, i = fairmax(avgPmincost) ## pick one with max avg cost at Pmin 78 i = on[i] ## convert to generator index 79 80 if verbose: 81 print 'Shutting down generator %d so all Pmin limits can be satisfied.\n' % i 82 83 ## set generation to zero 84 ppc["gen"][i, [PG, QG, GEN_STATUS]] = 0 85 86 ## update minimum gen capacity 87 on = find( (ppc["gen"][:, GEN_STATUS] > 0) & ~isload(ppc["gen"]) ) ## gens in service 88 Pmin = ppc["gen"][on, PMIN] 89 90 ## run initial opf 91 results = opf(ppc, ppopt) 92 93 ## best case so far 94 results1 = deepcopy(results) 95 96 ## best case for this stage (ie. with n gens shut down, n=0,1,2 ...) 97 results0 = deepcopy(results1) 98 ppc["bus"] = results0["bus"].copy() ## use these V as starting point for OPF 99 100 while True: 101 ## get candidates for shutdown 102 candidates = find((results0["gen"][:, MU_PMIN] > 0) & (results0["gen"][:, PMIN] > 0)) 103 if len(candidates) == 0: 104 break 105 106 ## do not check for further decommitment unless we 107 ## see something better during this stage 108 done = True 109 110 for k in candidates: 111 ## start with best for this stage 112 ppc["gen"] = results0["gen"].copy() 113 114 ## shut down gen k 115 ppc["gen"][k, [PG, QG, GEN_STATUS]] = 0 116 117 ## run opf 118 results = opf(ppc, ppopt) 119 120 ## something better? 121 if results['success'] and (results["f"] < results1["f"]): 122 results1 = deepcopy(results) 123 k1 = k 124 done = False ## make sure we check for further decommitment 125 126 if done: 127 ## decommits at this stage did not help, so let's quit 128 break 129 else: 130 ## shutting something else down helps, so let's keep going 131 if verbose: 132 print 'Shutting down generator %d.\n' % k1 133 134 results0 = deepcopy(results1) 135 ppc["bus"] = results0["bus"].copy() ## use these V as starting point for OPF 136 137 ## compute elapsed time 138 et = time() - t0 139 140 ## finish preparing output 141 results0['et'] = et 142 143 return results0
144