Source code for pfnet.parsers.parser_mat

import os
import pfnet
import numpy as np

[docs]class PyParserMAT(object): """ Class for parsing Matpower .m files. """ BUS_TYPE_PQ = 1 BUS_TYPE_PV = 2 BUS_TYPE_SL = 3 BUS_TYPE_IS = 4 def __init__(self): """ Parser for parsing Matpower .m files. """ self.case = None def set(self, key, value): """ Sets parser parameter. Parameters ---------- key : string value : float """ pass def parse(self, filename, num_periods=None): """ Parses Matpower .m file. Parameters ---------- filename : string num_periods : int Returns ------- net : |Network| """ import grg_mpdata as mp if os.path.splitext(filename)[-1][1:] != 'm': raise pfnet.ParserError('invalid file extension') case = mp.io.parse_mp_case_file(filename) self.case = case if num_periods is None: num_periods = 1 net = pfnet.Network(num_periods=num_periods) # Base power net.base_power = case.baseMVA # Numbers num_buses = 0 num_loads = 0 num_shunts = 0 for mat_bus in case.bus: if mat_bus.bus_type != self.BUS_TYPE_IS: num_buses += 1 if mat_bus.pd != 0. or mat_bus.qd != 0.: num_loads += 1 if mat_bus.gs != 0. or mat_bus.bs != 0.: num_shunts += 1 # Buses bus_index = 0 net.set_bus_array(num_buses) for mat_bus in reversed(case.bus): if mat_bus.bus_type != self.BUS_TYPE_IS: bus = net.get_bus(bus_index) bus.number = mat_bus.bus_i bus.area = mat_bus.area bus.zone = mat_bus.zone bus.name = "BUS %d" %bus.number bus.v_mag = mat_bus.vm bus.v_ang = mat_bus.va*np.pi/180. bus.v_base = mat_bus.base_kv bus.v_max_norm = mat_bus.vmax bus.v_min_norm = mat_bus.vmin if mat_bus.bus_type == self.BUS_TYPE_SL: bus.set_slack_flag(True) bus_index += 1 # Hashes net.update_hash_tables() # Load and shunts load_index = 0 shunt_index = 0 net.set_load_array(num_loads) net.set_shunt_array(num_shunts) for mat_bus in reversed(case.bus): if mat_bus.bus_type != self.BUS_TYPE_IS: # Load if mat_bus.pd != 0. or mat_bus.qd != 0.: bus = net.get_bus_from_number(mat_bus.bus_i) load = net.get_load(load_index) bus.add_load(load) assert(bus.is_equal(load.bus)) load.P = mat_bus.pd/net.base_power load.Q = mat_bus.qd/net.base_power load.P_max = load.P load.P_min = load.P load.Q_max = load.Q load.Q_min = load.Q load.comp_cp = load.P load.comp_cq = load.Q load_index += 1 # Shunt if mat_bus.gs != 0. or mat_bus.bs != 0.: bus = net.get_bus_from_number(mat_bus.bus_i) shunt = net.get_shunt(shunt_index) bus.add_shunt(shunt) assert(bus.is_equal(shunt.bus)) shunt.g = mat_bus.gs/net.base_power shunt.b = mat_bus.bs/net.base_power shunt.b_max = shunt.b[0] shunt.b_min = shunt.b[0] shunt_index += 1 # Gens gen_map = {} # mat index -> pfnet index gen_index = 0 net.set_gen_array(len([g for g in case.gen if g.gen_status > 0])) for mat_gen in reversed(case.gen): if mat_gen.gen_status > 0: bus = net.get_bus_from_number(mat_gen.gen_bus) gen = net.get_generator(gen_index) gen_map[mat_gen.index] = gen_index bus.add_generator(gen) assert(bus.is_equal(gen.bus)) gen.name = "%d" %gen.index gen.P = mat_gen.pg/net.base_power gen.P_max = mat_gen.pmax/net.base_power gen.P_min = mat_gen.pmin/net.base_power gen.Q = mat_gen.qg/net.base_power gen.Q_max = mat_gen.qmax/net.base_power gen.Q_min = mat_gen.qmin/net.base_power if bus.is_slack() or gen.Q_max > gen.Q_min: gen.reg_bus = bus assert(gen.index in [g.index for g in bus.reg_generators]) bus.v_set = mat_gen.vg gen_index += 1 # Branches net.set_branch_array(len([br for br in case.branch if br.br_status > 0])) br_index = 0 for mat_br in reversed(case.branch): if mat_br.br_status > 0: bus_k = net.get_bus_from_number(mat_br.f_bus) bus_m = net.get_bus_from_number(mat_br.t_bus) branch = net.get_branch(br_index) den = mat_br.br_r**2.+mat_br.br_x**2. g = mat_br.br_r/den b = -mat_br.br_x/den if mat_br.tap > 0: t = mat_br.tap else: t = 1. z = mat_br.shift*np.pi/180. if t == 1. and z == 0.: branch.set_as_line() else: branch.set_as_fixed_tran() branch.bus_k = bus_k branch.bus_m = bus_m assert(branch.index in [br.index for br in bus_k.branches_k]) assert(branch.index in [br.index for br in bus_m.branches_m]) branch.name = "%d" %branch.index branch.ratio = 1./t branch.ratio_max = branch.ratio[0] branch.ratio_min = branch.ratio[0] branch.phase = z branch.phase_max = z branch.phase_min = z branch.g = g branch.b = b branch.b_k = mat_br.br_b/2. branch.b_m = mat_br.br_b/2. branch.ratingA = mat_br.rate_a/net.base_power branch.ratingB = mat_br.rate_b/net.base_power branch.ratingC = mat_br.rate_c/net.base_power br_index += 1 # Gen costs for mat_cost in case.gencost: if mat_cost.index not in gen_map: continue gen = net.get_generator(gen_map[mat_cost.index]) if mat_cost.model != 2: print("gen cost model %d not supported" %mat_cost.model) continue gen.cost_coeff_Q2 = 0. gen.cost_coeff_Q1 = 0. gen.cost_coeff_Q0 = 0. for n, c in zip(range(mat_cost.ncost-1, -1, -1), mat_cost.cost): if n == 2: gen.cost_coeff_Q2 = c*(net.base_power**2.) if n == 1: gen.cost_coeff_Q1 = c*net.base_power if n == 0: gen.cost_coeff_Q0 # Update props net.update_properties() # Return return net def show(self): if self.case is not None: print(self.case) def write(self, net, filename): """ Writes network to Matpower .m file. Parameters ---------- net : |Network| filename : string """ import grg_mpdata as mp case_name = os.path.splitext(os.path.split(filename)[-1])[0] case_version = '\'2\'' case_baseMVA = net.base_power case_bus = [] case_gen = [] case_branch = [] case_gencost = [] case_dcline = [] case_dclinecost = [] case_busname = [] # Buses for bus in reversed(net.buses): bus_i = bus.number if bus.is_slack(): bus_type = self.BUS_TYPE_SL elif bus.is_regulated_by_gen(): bus_type = self.BUS_TYPE_PV else: bus_type = self.BUS_TYPE_PQ pd, qd = 0., 0. for load in bus.loads: pd += load.P[0]*net.base_power qd += load.Q[0]*net.base_power gs, bs = 0., 0. for shunt in bus.shunts: gs += shunt.g*net.base_power bs += shunt.b[0]*net.base_power area = bus.area vm = bus.v_mag[0] va = bus.v_ang[0]*180./np.pi base_kv = bus.v_base zone = bus.zone vmax = bus.v_max_norm vmin = bus.v_min_norm case_bus.append(mp.struct.Bus(bus_i, bus_type, pd, qd, gs, bs, area, vm, va, base_kv, zone, vmax, vmin)) # Generators for gen in reversed(net.generators): index = gen.index gen_bus = gen.bus.number pg = gen.P[0]*net.base_power qg = gen.Q[0]*net.base_power qmax = gen.Q_max*net.base_power qmin = gen.Q_min*net.base_power vg = gen.bus.v_set[0] mbase = net.base_power gen_status = int(gen.in_service) pmax = gen.P_max*net.base_power pmin = gen.P_min*net.base_power case_gen.append(mp.struct.Generator(index, gen_bus, pg, qg, qmax, qmin, vg, mbase, gen_status, pmax, pmin)) # Branches for branch in reversed(net.branches): index = branch.index f_bus = branch.bus_k.number t_bus = branch.bus_m.number br_r = branch.g/(branch.g**2.+branch.b**2.) br_x = -branch.b/(branch.g**2.+branch.b**2.) br_b = branch.b_k+branch.b_m tap = 1./branch.ratio[0] shift = branch.phase[0]*180./np.pi rate_a = branch.ratingA*net.base_power rate_b = branch.ratingB*net.base_power rate_c = branch.ratingC*net.base_power br_status = int(branch.in_service) case_branch.append(mp.struct.Branch(index, f_bus, t_bus, br_r, br_x, br_b, rate_a, rate_b, rate_c, tap, shift, br_status)) # Generator costs for gen in reversed(net.generators): index = gen.index model = 2 startup = 0 shutdown = 0 ncost = 3 cost = [gen.cost_coeff_Q2/(net.base_power**2.), gen.cost_coeff_Q1/net.base_power, gen.cost_coeff_Q0] case_gencost.append(mp.struct.GeneratorCost(index, model, startup, shutdown, ncost, cost)) case = mp.struct.Case(name=case_name, version=case_version, baseMVA=case_baseMVA, bus=case_bus, gen=case_gen, branch=case_branch, gencost=case_gencost) f = open(filename, 'w') f.write(case.to_matpower()) f.close()