def create_problem(self,net): import pfnet # Parameters params = self._parameters # Clear flags net.clear_flags() # Voltages angles (not slack) net.set_flags('bus', 'variable', 'not slack', 'voltage angle') # Gen active powers (slack) net.set_flags('generator', 'variable', 'slack', 'active power') # Check try: num_buses = len([b for b in net.buses if b.in_service]) assert(net.num_vars == num_buses-1+net.get_num_slack_gens()) except AssertionError: raise PFmethodError_BadProblem() # Set up problem problem = pfnet.Problem(net) problem.add_constraint(pfnet.Constraint('DC power balance',net)) problem.add_constraint(pfnet.Constraint('generator active power participation',net)) problem.analyze() # Return return problem
def NRsolve(net): net.clear_flags() # bus voltage angles net.set_flags('bus', 'variable', 'not slack', 'voltage angle') # bus voltage magnitudes net.set_flags('bus', 'variable', 'not regulated by generator', 'voltage magnitude') # slack gens active powers net.set_flags('generator', 'variable', 'slack', 'active power') # regulator gens reactive powers net.set_flags('generator', 'variable', 'regulator', 'reactive power') p = pfnet.Problem(net) p.add_constraint(pfnet.Constraint('AC power balance', net)) p.add_constraint( pfnet.Constraint('generator active power participation', net)) p.add_constraint( pfnet.Constraint('generator reactive power participation', net)) p.analyze() x = p.get_init_point() p.eval(x) residual = lambda x: hstack((p.A * x - p.b, p.f)) while norm(residual(x)) > 1e-4: x = x + spsolve(bmat([[p.A], [p.J]], format='csr'), -residual(x)) p.eval(x) net.set_var_values(x) net.update_properties()
parameters={'tol': 1e-4}, fast_evaluator=True) print("OPTMOD", func.get_value()) print(info) print('time construction', time_construction) t = time.time() # PFNET and OPTALG net.set_flags('bus', 'variable', 'not slack', 'voltage angle') net.set_flags('bus', ['variable', 'bounded'], 'any', 'voltage magnitude') net.set_flags('generator', ['variable', 'bounded'], 'any', ['active power', 'reactive power']) p = pfnet.Problem(net) p.add_function(pfnet.Function('generation redispatch penalty', 1., net)) p.add_constraint(pfnet.Constraint('AC power balance', net)) p.add_constraint(pfnet.Constraint('variable bounds', net)) time_construction = time.time() - t t = time.time() p.analyze() p.show() time_transformation = time.time() - t t = time.time() solver = optalg.opt_solver.OptSolverIpopt() solver.set_parameters({'tol': 1e-4})
def create_problem(self,net): import pfnet # Parameters params = self._parameters wcost = params['weight_cost'] wvmag = params['weight_vmag'] wvang = params['weight_vang'] wpq = params['weight_pq'] wt = params['weight_t'] wb = params['weight_b'] th = params['thermal_limits'] # Clear flags net.clear_flags() # Voltage magnitudes net.set_flags('bus', ['variable','bounded'], 'any', 'voltage magnitude') # Voltage angles net.set_flags('bus', 'variable', 'not slack', 'voltage angle') # Generator powers net.set_flags('generator', ['variable','bounded'], 'any', ['active power','reactive power']) try: assert(net.num_vars == (2*net.get_num_buses(True)-net.get_num_slack_buses(True) + 2*net.get_num_generators(True))*net.num_periods) assert(net.num_bounded == (2*net.get_num_generators(True) + net.get_num_buses(True))*net.num_periods) except AssertionError: raise PFmethodError_BadProblem() # Problem problem = pfnet.Problem(net) # Constraints problem.add_constraint(pfnet.Constraint('AC power balance',net)) problem.add_constraint(pfnet.Constraint('variable bounds',net)) if th == 'nonlinear': problem.add_constraint(pfnet.Constraint("AC branch flow limits",net)) elif th == 'linear': problem.add_constraint(pfnet.Constraint("linearized AC branch flow limits",net)) elif th == 'none': pass else: raise PFmethodError_BadParamValue('thermal_limits') # Functions problem.add_function(pfnet.Function('generation cost', wcost/max([net.get_num_generators(True),1.]),net)) if wvmag: problem.add_function(pfnet.Function('voltage magnitude regularization', wvmag/max([net.get_num_buses(True),1.]),net)) if wvang: problem.add_function(pfnet.Function('voltage angle regularization', wvang/max([net.get_num_buses(True),1.]),net)) if wpq: problem.add_function(pfnet.Function('generator powers regularization', wpq/max([net.get_num_generators(True),1.]),net)) if wt: problem.add_function(pfnet.Function('tap ratio regularization', wt/max([net.get_num_tap_changers(True),1.]),net)) if wb: problem.add_function(pfnet.Function('susceptance regularization', wb/max([net.get_num_switched_shunts(True),1.]),net)) problem.analyze() # Return return problem
def test_dc_flow_lim(self): for case in test_cases.CASES: net = pf.Parser(case).parse(case) self.assertEqual(net.num_periods,1) for branch in net.branches: if branch.ratingA == 0.: branch.ratingA = 100. # variables net.set_flags('bus', 'variable', 'not slack', 'voltage angle') net.set_flags('branch', 'variable', 'phase shifter', 'phase shift') self.assertEqual(net.num_vars, (net.num_buses-net.get_num_slack_buses() + net.get_num_phase_shifters())) # pre contingency constr = pf.Constraint('DC branch flow limits',net) constr.analyze() constr.eval(net.get_var_values()) G = constr.G.copy() l = constr.l.copy() u = constr.u.copy() x = net.get_var_values() # gen outages counter = 0 for gen in net.generators: cont = pf.Contingency() cont.add_generator_outage(gen) cont.apply(net) constr.del_matvec() constr.analyze() constr.eval(x) self.assertEqual((G-constr.G).nnz,0) self.assertEqual(np.linalg.norm(l-constr.l),0.) self.assertEqual(np.linalg.norm(u-constr.u),0.) cont.clear(net) counter += 1 if counter > TEST_GENS: break # branch outages counter = 0 for br in net.branches: if br.bus_k.degree == 1 or br.bus_m.degree == 1: continue cont = pf.Contingency() cont.add_branch_outage(br) cont.apply(net) constr.del_matvec() constr.analyze() constr.eval(net.get_var_values()) lnew = constr.l.copy() unew = constr.u.copy() Gnew = constr.G.copy() self.assertTupleEqual(lnew.shape,(l.size-1,)) self.assertTupleEqual(unew.shape,(u.size-1,)) self.assertTupleEqual(Gnew.shape,(G.shape[0]-1,G.shape[1])) self.assertLess(np.linalg.norm(lnew-np.hstack((l[:br.index],l[br.index+1:])),np.inf),1e-8) self.assertLess(np.linalg.norm(unew-np.hstack((u[:br.index],u[br.index+1:])),np.inf),1e-8) indices = G.row != br.index row = G.row[indices] row = row - 1*(row>br.index) col = G.col[indices] data = G.data[indices] Gcut = coo_matrix((data,(row,col)),shape=(net.num_branches-1,net.num_vars)) self.assertEqual((Gnew-Gcut).nnz,0) cont.clear(net) counter += 1 if counter > TEST_BRANCHES: break
def test_dcpf(self): for case in test_cases.CASES: net = pf.Parser(case).parse(case) self.assertEqual(net.num_periods,1) # variables net.set_flags('generator', 'variable', 'any', 'active power') net.set_flags('bus', 'variable', 'not slack', 'voltage angle') net.set_flags('branch', 'variable', 'phase shifter', 'phase shift') self.assertEqual(net.num_vars, (net.num_generators + net.num_buses-net.get_num_slack_buses() + net.get_num_phase_shifters())) # pre contingency constr = pf.Constraint('DC power balance',net) constr.analyze() constr.eval(net.get_var_values()) A = constr.A.copy() b = constr.b.copy() x = net.get_var_values() # gen outages counter = 0 for gen in net.generators: bus = gen.bus cont = pf.Contingency() cont.add_generator_outage(gen) cont.apply(net) self.assertTrue(gen.has_flags('variable', 'active power')) self.assertTrue(gen.is_on_outage()) constr.del_matvec() constr.analyze() constr.eval(x) self.assertFalse(np.all(A.col != gen.index_P)) self.assertTrue(np.all(constr.A.col != gen.index_P)) self.assertLess(np.abs((A*x-b)[bus.index]- (constr.A*x-constr.b)[bus.index]-gen.P),1e-8) counter1 = 0 for bus1 in net.buses: if bus != bus1: self.assertLess(np.abs((A*x-b)[bus1.index]- (constr.A*x-constr.b)[bus1.index]),1e-8) counter1 += 1 if counter1 > TEST_BUSES: break cont.clear(net) counter += 1 if counter > TEST_GENS: break # branch outages counter = 0 for br in net.branches: bus_k = br.bus_k bus_m = br.bus_m if br.bus_k.degree == 1 or br.bus_m.degree == 1: continue Pkm = br.P_km_DC cont = pf.Contingency() cont.add_branch_outage(br) cont.apply(net) constr.del_matvec() constr.analyze() constr.eval(net.get_var_values()) self.assertLess(np.abs((A*x-b)[bus_k.index]- ((constr.A*x-constr.b)[bus_k.index]-Pkm)),1e-8) self.assertLess(np.abs((A*x-b)[bus_m.index]- ((constr.A*x-constr.b)[bus_m.index]+Pkm)),1e-8) cont.clear(net) counter += 1 if counter > TEST_BRANCHES: break
def test_acpf(self): for case in test_cases.CASES: net = pf.Parser(case).parse(case) self.assertEqual(net.num_periods,1) # variables net.set_flags('generator', 'variable', 'any', 'active power') net.set_flags('generator', 'variable', 'regulator', 'reactive power') net.set_flags('bus', 'variable', 'any', ['voltage magnitude','voltage angle']) net.set_flags('branch', 'variable', 'tap changer', 'tap ratio') net.set_flags('shunt', 'variable', 'switching - v', 'susceptance') self.assertEqual(net.num_vars, (net.num_generators + net.get_num_reg_gens() + 2*net.num_buses + net.get_num_tap_changers() + net.get_num_switched_shunts())) # pre contingency net.update_properties() mismatches = np.zeros(2*net.num_buses) for bus in net.buses: mismatches[bus.index_P] = bus.P_mismatch mismatches[bus.index_Q] = bus.Q_mismatch constr = pf.Constraint('AC power balance',net) constr.analyze() constr.eval(net.get_var_values()) f = constr.f.copy() self.assertLess(np.linalg.norm(f-mismatches),1e-8) # gen outages counter = 0 for gen in net.generators: bus = gen.bus cont = pf.Contingency() cont.add_generator_outage(gen) cont.apply(net) constr.del_matvec() constr.analyze() constr.eval(net.get_var_values()) net.update_properties() self.assertLess(np.abs(constr.f[bus.index_P]-bus.P_mismatch),1e-8) self.assertLess(np.abs(constr.f[bus.index_Q]-bus.Q_mismatch),1e-8) self.assertLess(np.abs(f[bus.index_P]-constr.f[bus.index_P]-gen.P),1e-8) self.assertLess(np.abs(f[bus.index_Q]-constr.f[bus.index_Q]-gen.Q),1e-8) self.assertLess(np.abs(mismatches[bus.index_P]-bus.P_mismatch-gen.P),1e-8) self.assertLess(np.abs(mismatches[bus.index_Q]-bus.Q_mismatch-gen.Q),1e-8) counter1 = 0 for bus1 in net.buses: if bus != bus1: self.assertLess(np.abs(constr.f[bus1.index_P]-f[bus1.index_P]),1e-8) self.assertLess(np.abs(constr.f[bus1.index_Q]-f[bus1.index_Q]),1e-8) self.assertLess(np.abs(bus1.P_mismatch-mismatches[bus1.index_P]),1e-8) self.assertLess(np.abs(bus1.Q_mismatch-mismatches[bus1.index_Q]),1e-8) counter1 += 1 if counter1 > TEST_BUSES: break cont.clear(net) counter += 1 if counter > TEST_GENS: break # branch outages counter = 0 for br in net.branches: if br.bus_k.degree == 1 or br.bus_m.degree == 1: continue cont = pf.Contingency() cont.add_branch_outage(br) cont.apply(net) constr.del_matvec() constr.analyze() constr.eval(net.get_var_values()) net.update_properties() Pkm = br.get_P_km() Qkm = br.get_Q_km() Pmk = br.get_P_mk() Qmk = br.get_Q_mk() self.assertLess(np.abs(constr.f[br.bus_k.index_P]-br.bus_k.P_mismatch),1e-8) self.assertLess(np.abs(constr.f[br.bus_k.index_Q]-br.bus_k.Q_mismatch),1e-8) self.assertLess(np.abs(f[br.bus_k.index_P]-constr.f[br.bus_k.index_P]+Pkm),1e-8) self.assertLess(np.abs(f[br.bus_k.index_Q]-constr.f[br.bus_k.index_Q]+Qkm),1e-8) self.assertLess(np.abs(mismatches[br.bus_k.index_P]-br.bus_k.P_mismatch+Pkm),1e-8) self.assertLess(np.abs(mismatches[br.bus_k.index_Q]-br.bus_k.Q_mismatch+Qkm),1e-8) self.assertLess(np.abs(constr.f[br.bus_m.index_P]-br.bus_m.P_mismatch),1e-8) self.assertLess(np.abs(constr.f[br.bus_m.index_Q]-br.bus_m.Q_mismatch),1e-8) self.assertLess(np.abs(f[br.bus_m.index_P]-constr.f[br.bus_m.index_P]+Pmk),1e-8) self.assertLess(np.abs(f[br.bus_m.index_Q]-constr.f[br.bus_m.index_Q]+Qmk),1e-8) self.assertLess(np.abs(mismatches[br.bus_m.index_P]-br.bus_m.P_mismatch+Pmk),1e-8) self.assertLess(np.abs(mismatches[br.bus_m.index_Q]-br.bus_m.Q_mismatch+Qmk),1e-8) counter1 = 0 for bus1 in net.buses: if br.bus_k != bus1 and br.bus_m != bus1: self.assertLess(np.abs(constr.f[bus1.index_P]-f[bus1.index_P]),1e-8) self.assertLess(np.abs(constr.f[bus1.index_Q]-f[bus1.index_Q]),1e-8) self.assertLess(np.abs(bus1.P_mismatch-mismatches[bus1.index_P]),1e-8) self.assertLess(np.abs(bus1.Q_mismatch-mismatches[bus1.index_Q]),1e-8) counter1 += 1 if counter1 > TEST_BUSES: break cont.clear(net) counter += 1 if counter > TEST_BRANCHES: break
def test_PVPQ_switching(self): T = 2 for case in test_cases.CASES: net = pf.Parser(case).parse(case, T) self.assertEqual(net.num_periods, T) for gen in net.generators: if gen.is_regulator(): gen.Q[:] = gen.Q_max + 1. # Variables net.set_flags('bus', 'variable', 'not slack', ['voltage magnitude', 'voltage angle']) net.set_flags('generator', 'variable', 'slack', 'active power') net.set_flags('generator', 'variable', 'regulator', 'reactive power') net.set_flags('branch', 'variable', 'tap changer - v', 'tap ratio') net.set_flags('branch', 'variable', 'phase shifter', 'phase shift') net.set_flags('shunt', 'variable', 'switching - v', 'susceptance') self.assertEqual( net.num_vars, (2 * (net.num_buses - net.get_num_slack_buses()) + net.get_num_slack_gens() + net.get_num_reg_gens() + net.get_num_tap_changers_v() + net.get_num_phase_shifters() + net.get_num_switched_v_shunts()) * T) # Fixed net.set_flags('branch', 'fixed', 'tap changer - v', 'tap ratio') net.set_flags('branch', 'fixed', 'phase shifter', 'phase shift') net.set_flags('shunt', 'fixed', 'switching - v', 'susceptance') self.assertEqual( net.num_fixed, (net.get_num_tap_changers_v() + net.get_num_phase_shifters() + net.get_num_switched_v_shunts()) * T) self.assertRaises(pf.HeuristicError, pf.Heuristic, 'foo', net) heur = pf.Heuristic('PVPQ switching', net) self.assertEqual(heur.name, 'PVPQ switching') self.assertTrue(heur.network.has_same_ptr(net)) x = net.get_var_values() acpf = pf.Constraint('AC power balance', net) pvpq = pf.Constraint('PVPQ switching', net) fix = pf.Constraint('variable fixing', net) self.assertRaises(pf.HeuristicError, heur.apply, [], x) self.assertRaises(pf.HeuristicError, heur.apply, [fix], x) self.assertRaises(pf.HeuristicError, heur.apply, [fix, acpf], x) self.assertRaises(pf.HeuristicError, heur.apply, [fix, pvpq], x) self.assertRaises(pf.HeuristicError, heur.apply, [acpf, pvpq], x) self.assertRaises(pf.HeuristicError, heur.apply, [acpf, fix, pvpq], x) for c in [acpf, pvpq, fix]: c.analyze() A = pvpq.A.copy() self.assertRaises(pf.HeuristicError, heur.apply, [], x) self.assertRaises(pf.HeuristicError, heur.apply, [fix], x) self.assertRaises(pf.HeuristicError, heur.apply, [fix, acpf], x) self.assertRaises(pf.HeuristicError, heur.apply, [fix, pvpq], x) heur.apply([acpf, pvpq], x) self.assertEqual(acpf.f.size, 2 * net.num_buses * T) self.assertEqual(pvpq.A.shape[1], net.num_vars) heur.apply([acpf, fix, pvpq], x) self.assertEqual(acpf.f.size, 2 * net.num_buses * T) self.assertEqual(pvpq.A.shape[1], net.num_vars) self.assertFalse(np.all(A.data == pvpq.A.data)) for gen in net.generators: gen.in_service = False for c in [acpf, pvpq, fix]: c.analyze() A = pvpq.A.copy() heur.apply([acpf, fix, pvpq], x) self.assertEqual(acpf.f.size, 2 * net.num_buses * T) self.assertEqual(pvpq.A.shape[1], net.num_vars) self.assertTrue(np.all(A.data == pvpq.A.data)) net.make_all_in_service() for bus in net.buses: bus.in_service = False for c in [acpf, pvpq, fix]: c.analyze() A = pvpq.A.copy() heur.apply([acpf, fix, pvpq], x) self.assertTrue(np.all(A.data == pvpq.A.data))
def create_problem(self, net): import pfnet # Parameters params = self._parameters wm = params['weight_vang'] wa = params['weight_vmag'] wp = params['weight_pq'] wt = params['weight_t'] wb = params['weight_b'] limit_gens = params['limit_gens'] lock_taps = params['lock_taps'] lock_shunts = params['lock_shunts'] solver_name = params['solver'] # Clear flags net.clear_flags() # OPT-based ########### if solver_name != 'nr': # Set up variables net.set_flags('bus', 'variable', 'not slack', ['voltage angle', 'voltage magnitude']) if not limit_gens: net.set_flags('bus', 'fixed', 'regulated by generator', 'voltage magnitude') net.set_flags('generator', 'variable', 'slack', 'active power') net.set_flags('generator', 'variable', 'regulator', 'reactive power') # Tap ratios if not lock_taps: net.set_flags('branch', 'variable', 'tap changer - v', 'tap ratio') # Shunt voltage control if not lock_shunts: net.set_flags('shunt', 'variable', 'switching - v', 'susceptance') try: num_vars = (2 * (net.num_buses - net.get_num_slack_buses()) + net.get_num_slack_gens() + net.get_num_reg_gens()) * net.num_periods if not lock_taps: num_vars += net.get_num_tap_changers_v() * net.num_periods if not lock_shunts: num_vars += net.get_num_switched_shunts() * net.num_periods assert (net.num_vars == num_vars) if limit_gens: assert (net.num_fixed == 0) else: assert (net.num_fixed == net.get_num_buses_reg_by_gen() * net.num_periods) except AssertionError: raise PFmethodError_BadProblem() # Set up problem problem = pfnet.Problem(net) problem.add_constraint(pfnet.Constraint('AC power balance', net)) problem.add_constraint( pfnet.Constraint('generator active power participation', net)) problem.add_constraint( pfnet.Constraint('generator reactive power participation', net)) problem.add_function( pfnet.Function('voltage magnitude regularization', wm / max([net.num_buses, 1.]), net)) problem.add_function( pfnet.Function('voltage angle regularization', wa / max([net.num_buses, 1.]), net)) problem.add_function( pfnet.Function('generator powers regularization', wp / max([net.num_generators, 1.]), net)) if limit_gens: problem.add_constraint( pfnet.Constraint('voltage regulation by generators', net)) else: problem.add_constraint(pfnet.Constraint( 'variable fixing', net)) if not lock_taps: problem.add_constraint( pfnet.Constraint('voltage regulation by transformers', net)) problem.add_function( pfnet.Function( 'tap ratio regularization', wt / max([net.get_num_tap_changers_v(), 1.]), net)) if not lock_shunts: problem.add_constraint( pfnet.Constraint('voltage regulation by shunts', net)) problem.add_function( pfnet.Function( 'susceptance regularization', wb / max([net.get_num_switched_shunts(), 1.]), net)) problem.analyze() # Return return problem # NR-based ########## elif solver_name == 'nr': # Voltages net.set_flags('bus', 'variable', 'not slack', ['voltage magnitude', 'voltage angle']) net.set_flags('bus', 'fixed', 'regulated by generator', 'voltage magnitude') # Gen active powers net.set_flags('generator', 'variable', 'slack', 'active power') # Gen reactive powers net.set_flags('generator', 'variable', 'regulator', 'reactive power') # Tap ratios net.set_flags('branch', ['variable', 'fixed'], 'tap changer - v', 'tap ratio') # Shunt susceptances net.set_flags('shunt', ['variable', 'fixed'], 'switching - v', 'susceptance') try: assert (net.num_vars == (2 * (net.num_buses - net.get_num_slack_buses()) + net.get_num_slack_gens() + net.get_num_reg_gens() + net.get_num_tap_changers_v() + net.get_num_switched_shunts()) * net.num_periods) assert (net.num_fixed == (net.get_num_buses_reg_by_gen() + net.get_num_tap_changers_v() + net.get_num_switched_shunts()) * net.num_periods) except AssertionError: raise PFmethodError_BadProblem() # Set up problem problem = pfnet.Problem(net) problem.add_constraint(pfnet.Constraint('AC power balance', net)) problem.add_constraint( pfnet.Constraint('generator active power participation', net)) problem.add_constraint( pfnet.Constraint('generator reactive power participation', net)) problem.add_constraint(pfnet.Constraint('variable fixing', net)) if limit_gens: problem.add_heuristic(pfnet.HEUR_TYPE_PVPQ) problem.analyze() # Return return problem # Invalid ######### else: raise PFmethodError_BadOptSolver()
#***************************************************# # Optimization Problems - Constraints import sys sys.path.append('.') import pfnet net = pfnet.Parser(sys.argv[1]).parse(sys.argv[1]) net.set_flags('bus', 'variable', 'any', ['voltage magnitude', 'voltage angle']) print(net.num_vars == 2 * net.num_buses) constr = pfnet.Constraint('AC power balance', net) print(constr.name == 'AC power balance') x = net.get_var_values() constr.analyze() print(constr.num_extra_vars) constr.eval(x + 0.01) constr.eval(x) import numpy as np f = constr.f
def create_problem_opt(self, net): import pfnet # Parameters params = self._parameters wm = params['weight_vmag'] wa = params['weight_vang'] wp = params['weight_powers'] wc = params['weight_controls'] wv = params['weight_var'] wr = params['weight_redispatch'] v_limits = params['v_limits'] Q_mode = params['Q_mode'] Q_limits = params['Q_limits'] shunt_mode = params['shunt_mode'] shunt_limits = params['shunt_limits'] tap_mode = params['tap_mode'] tap_limits = params['tap_limits'] lock_vsc_P_dc = params['lock_vsc_P_dc'] lock_csc_P_dc = params['lock_csc_P_dc'] lock_csc_i_dc = params['lock_csc_i_dc'] vdep_loads = params['vdep_loads'] v_mag_warm_ref = params['v_mag_warm_ref'] gens_redispatch = params['gens_redispatch'] curtail_load_q = params['load_q_curtail'] # Check shunt options if shunt_mode not in [self.CONTROL_MODE_LOCKED, self.CONTROL_MODE_FREE, self.CONTROL_MODE_REG]: raise ValueError('invalid shunts mode') if shunt_mode == self.CONTROL_MODE_REG and not shunt_limits: raise ValueError('unsupported shunts configuration') # Check tap options if tap_mode not in [self.CONTROL_MODE_LOCKED, self.CONTROL_MODE_FREE, self.CONTROL_MODE_REG]: raise ValueError('invalid taps mode') if tap_mode == self.CONTROL_MODE_REG and not tap_limits: raise ValueError('unsupported taps configuration') # Check Q options if Q_mode not in [self.CONTROL_MODE_REG, self.CONTROL_MODE_FREE]: raise ValueError('invalid reactive power mode') # Clear flags net.clear_flags() # Buses net.set_flags('bus', 'variable', 'not slack', 'voltage angle') net.set_flags('bus', 'variable', 'any', 'voltage magnitude') if Q_mode == self.CONTROL_MODE_REG and not Q_limits: net.set_flags('bus', 'fixed', 'v set regulated', 'voltage magnitude') if v_limits: net.set_flags('bus', 'bounded', 'any', 'voltage magnitude') # Genertors if gens_redispatch: # Assume slack gens (excep renewables) are redispatchable net.set_flags('generator', ['variable', 'bounded'], 'redispatchable', 'active power') else: net.set_flags('generator', 'variable', 'slack', 'active power') net.set_flags('generator', 'variable', 'regulator', 'reactive power') if Q_mode == self.CONTROL_MODE_FREE and Q_limits: net.set_flags('generator', 'bounded', 'regulator', 'reactive power') # Loads if vdep_loads: for load in net.loads: if load.is_voltage_dependent() and load.is_in_service(): net.set_flags_of_component(load, 'variable', ['active power', 'reactive power']) if curtail_load_q: for load in net.loads: load.Q_min = np.minimum(load.Q, 0) load.Q_max = np.maximum(load.Q, 0) net.set_flags_of_component(load, ['variable','bounded'], 'reactive power') # VSC HVDC net.set_flags('vsc converter', 'variable', 'any', ['dc power', 'active power', 'reactive power']) if Q_mode == self.CONTROL_MODE_FREE and Q_limits: net.set_flags('vsc converter', 'bounded', 'any', 'reactive power') # CSC HVDC net.set_flags('csc converter', 'variable', 'any', ['dc power', 'active power', 'reactive power']) # DC buses net.set_flags('dc bus', 'variable', 'any', 'voltage') # FACTS net.set_flags('facts', 'variable', 'any', 'all') if Q_mode == self.CONTROL_MODE_FREE and Q_limits: net.set_flags('facts', 'bounded', 'any', 'reactive power') # Tap changers if tap_mode != self.CONTROL_MODE_LOCKED: net.set_flags('branch', 'variable', 'tap changer - v', 'tap ratio') if tap_mode == self.CONTROL_MODE_FREE and tap_limits: net.set_flags('branch', 'bounded', 'tap changer - v', 'tap ratio') # Swtiched shunts if shunt_mode != self.CONTROL_MODE_LOCKED: net.set_flags('shunt', 'variable', 'switching - v', 'susceptance') if shunt_mode == self.CONTROL_MODE_FREE and shunt_limits: net.set_flags('shunt', 'bounded', 'switching - v', 'susceptance') # Set up problem problem = pfnet.Problem(net) problem.add_constraint(pfnet.Constraint('AC power balance', net)) problem.add_constraint(pfnet.Constraint('HVDC power balance', net)) problem.add_constraint(pfnet.Constraint('generator active power participation', net)) problem.add_constraint(pfnet.Constraint('VSC converter equations', net)) problem.add_constraint(pfnet.Constraint('CSC converter equations', net)) problem.add_constraint(pfnet.Constraint('FACTS equations', net)) problem.add_constraint(pfnet.Constraint('VSC DC voltage control', net)) problem.add_constraint(pfnet.Constraint('CSC DC voltage control', net)) problem.add_constraint(pfnet.Constraint('power factor regulation', net)) if lock_vsc_P_dc: problem.add_constraint(pfnet.Constraint('VSC DC power control', net)) if lock_csc_P_dc: problem.add_constraint(pfnet.Constraint('CSC DC power control', net)) if lock_csc_i_dc: problem.add_constraint(pfnet.Constraint('CSC DC current control', net)) func = pfnet.Function('voltage magnitude regularization', wm/(net.get_num_buses(True)+1.), net) func.set_parameter('v_set_reference', not v_mag_warm_ref) problem.add_function(func) problem.add_function(pfnet.Function('variable regularization', wv/(net.num_vars+1.), net)) problem.add_function(pfnet.Function('voltage angle regularization', wa/(net.get_num_buses(True)+1.), net)) problem.add_function(pfnet.Function('generator powers regularization', wp/(net.get_num_generators(True)+1.), net)) problem.add_function(pfnet.Function('VSC DC power control', wc/(net.get_num_vsc_converters(True)+1.), net)) problem.add_function(pfnet.Function('CSC DC power control', wc/(net.get_num_csc_converters(True)+1.), net)) problem.add_function(pfnet.Function('CSC DC current control', wc/(net.get_num_csc_converters(True)+1.), net)) problem.add_function(pfnet.Function('FACTS active power control', wc/(net.get_num_facts(True)+1.), net)) problem.add_function(pfnet.Function('FACTS reactive power control', wc/(net.get_num_facts(True)+1.), net)) if gens_redispatch: problem.add_function(pfnet.Function('generation redispatch penalty', wr/(net.get_num_generators(True)+1.), net)) if Q_mode == self.CONTROL_MODE_REG and Q_limits: problem.add_constraint(pfnet.Constraint('voltage set point regulation', net)) if net.num_fixed > 0: problem.add_constraint(pfnet.Constraint('variable fixing', net)) if tap_mode != self.CONTROL_MODE_LOCKED: problem.add_function(pfnet.Function('tap ratio regularization', wc/(net.get_num_tap_changers_v(True)+1.), net)) if tap_mode == self.CONTROL_MODE_REG and tap_limits: problem.add_constraint(pfnet.Constraint('voltage regulation by transformers', net)) if shunt_mode != self.CONTROL_MODE_LOCKED: problem.add_function(pfnet.Function('susceptance regularization', wc/(net.get_num_switched_v_shunts(True)+1.), net)) if shunt_mode == self.CONTROL_MODE_REG and shunt_limits: problem.add_constraint(pfnet.Constraint('voltage regulation by shunts', net)) if vdep_loads: problem.add_constraint(pfnet.Constraint('load voltage dependence', net)) if net.num_bounded > 0: problem.add_constraint(pfnet.Constraint('variable bounds', net)) # Analyze problem.analyze() # Return return problem
def create_problem_nr(self, net): import pfnet # Parameters params = self._parameters Q_mode = params['Q_mode'] Q_limits = params['Q_limits'] shunt_mode = params['shunt_mode'] shunt_limits = params['shunt_limits'] tap_mode = params['tap_mode'] tap_limits = params['tap_limits'] lock_vsc_P_dc = params['lock_vsc_P_dc'] lock_csc_P_dc = params['lock_csc_P_dc'] lock_csc_i_dc = params['lock_csc_i_dc'] vdep_loads = params['vdep_loads'] gens_redispatch = params['gens_redispatch'] # Check shunt options if shunt_mode not in [self.CONTROL_MODE_LOCKED, self.CONTROL_MODE_REG]: raise ValueError('invalid shunts mode') if shunt_mode == self.CONTROL_MODE_REG and not shunt_limits: raise ValueError('unsupported shunts configuration') # Check tap options if tap_mode not in [self.CONTROL_MODE_LOCKED, self.CONTROL_MODE_REG]: raise ValueError('invalid taps mode') if tap_mode == self.CONTROL_MODE_REG and not tap_limits: raise ValueError('unsupported taps configuration') # Check Q options if Q_mode != self.CONTROL_MODE_REG: raise ValueError('invalid reactive power mode') # Check other options if gens_redispatch: raise ValueError('generation redispatch not supported') if not lock_vsc_P_dc: raise ValueError('VSC P DC must be locked') if not lock_csc_P_dc: raise ValueError('CSC P DC must be locked') if not lock_csc_i_dc: raise ValueError('CSC i DC must be locked') # Clear flags net.clear_flags() # Buses net.set_flags('bus', 'variable', 'not slack', 'voltage angle') net.set_flags('bus', 'variable', 'any', 'voltage magnitude') # Generators net.set_flags('generator', 'variable', 'slack', 'active power') net.set_flags('generator', 'variable', 'regulator', 'reactive power') # VSC HVDC net.set_flags('vsc converter', 'variable', 'any', ['dc power', 'active power', 'reactive power']) # CSC HVDC net.set_flags('csc converter', 'variable', 'any', ['dc power', 'active power', 'reactive power']) # DC buses net.set_flags('dc bus', 'variable', 'any', 'voltage') # FACTS net.set_flags('facts', 'variable', 'any', 'all') # Loads if vdep_loads: for load in net.loads: if load.is_voltage_dependent() and load.is_in_service(): net.set_flags_of_component(load, 'variable', ['active power', 'reactive power']) # Tap changers if tap_mode != self.CONTROL_MODE_LOCKED: net.set_flags('branch', ['variable', 'fixed'], 'tap changer - v', 'tap ratio') # Switched shunts if shunt_mode != self.CONTROL_MODE_LOCKED: net.set_flags('shunt', ['variable', 'fixed'], 'switching - v', 'susceptance') # Set up problem problem = pfnet.Problem(net) problem.add_constraint(pfnet.Constraint('AC power balance', net)) problem.add_constraint(pfnet.Constraint('HVDC power balance', net)) problem.add_constraint(pfnet.Constraint('generator active power participation', net)) problem.add_constraint(pfnet.Constraint('variable fixing', net)) problem.add_constraint(pfnet.Constraint('VSC converter equations', net)) problem.add_constraint(pfnet.Constraint('CSC converter equations', net)) problem.add_constraint(pfnet.Constraint('FACTS equations', net)) problem.add_constraint(pfnet.Constraint('VSC DC voltage control', net)) problem.add_constraint(pfnet.Constraint('CSC DC voltage control', net)) problem.add_constraint(pfnet.Constraint('VSC DC power control', net)) problem.add_constraint(pfnet.Constraint('CSC DC power control', net)) problem.add_constraint(pfnet.Constraint('CSC DC current control', net)) problem.add_constraint(pfnet.Constraint('PVPQ switching', net)) problem.add_constraint(pfnet.Constraint('switching power factor regulation', net)) problem.add_constraint(pfnet.Constraint('switching FACTS active power control', net)) problem.add_constraint(pfnet.Constraint('switching FACTS reactive power control', net)) if vdep_loads: problem.add_constraint(pfnet.Constraint('load voltage dependence', net)) if Q_limits: problem.add_heuristic(pfnet.Heuristic('PVPQ switching', net)) problem.add_heuristic(pfnet.Heuristic('switching power factor regulation', net)) problem.analyze() # Check if (problem.J.shape[0] + problem.A.shape[0] != problem.get_num_primal_variables()): raise PFmethodError_BadProblem() # Return return problem
net = pf.ParserRAW().parse(case) # Voltages net.set_flags('bus', 'variable', 'not slack', ['voltage magnitude', 'voltage angle']) # Gen active powers net.set_flags('generator', 'variable', 'slack', 'active power') # Gen reactive powers net.set_flags('generator', 'variable', 'slack', 'reactive power') # Set up problem problem = pf.Problem(net) problem.add_constraint(pf.Constraint('AC power balance', net)) problem.add_constraint( pf.Constraint('generator active power participation', net)) problem.add_constraint(pf.Constraint('PVPQ switching', net)) problem.analyze() problem.eval(problem.get_init_point()) # NR matrix - no HVDC M = bmat([[problem.A], [problem.J]]) M = M.todense() self.assertEqual(np.linalg.matrix_rank(M), M.shape[0]) # DC buses net.set_flags('dc bus', 'variable', 'any', 'voltage') problem.add_constraint(pf.Constraint('HVDC power balance', net))