Source code for VeraGridEngine.IO.veragrid.json_parser

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
# SPDX-License-Identifier: MPL-2.0
from __future__ import annotations

import json
from typing import List, Any, Dict
from warnings import warn
import numpy as np
from VeraGridEngine.basic_structures import Logger
from VeraGridEngine.Devices.multi_circuit import MultiCircuit
from VeraGridEngine.IO.veragrid.contingency_parser import get_contingencies_dict, parse_contingencies
from VeraGridEngine.IO.veragrid.generic_io_functions import CustomJSONizer
import VeraGridEngine.Devices as dev
from VeraGridEngine.Devices.Profiles import AnyProfile
from VeraGridEngine.Devices.Parents.editable_device import EditableDevice
from VeraGridEngine.Simulations.driver_template import DriverToSave
from VeraGridEngine.enumerations import (DeviceType, HvdcControlType, BuildStatus,
                                         TapModuleControl, TapPhaseControl, SimulationTypes,
                                         GeneratorControlMode)


[docs] def add_to_dict(main_dict: Dict[str, List[Any]], data_to_append: Dict[Any, Any], key: str): """ Append d2 into a list of d at the key :param main_dict: Dictionary to append to :param data_to_append: Secondary dictionary to append :param key: key where to append the dictionary """ lst = main_dict.get(key, None) if lst is None: main_dict[key] = [data_to_append] # create list at the entry else: lst.append(data_to_append) # increase list
[docs] def add_to_dict2(main_dict: Dict[str, Any], data: Dict[Any, Any], key: str): """ Add data to the main dictionary at the given key if it does not exists already :param main_dict:Dictionary to append to :param data: Some dictionary :param key: key to store """ if key not in main_dict.keys(): main_dict[key] = data
[docs] def profile_to_json(profile: AnyProfile) -> Dict[str, Any]: """ Convert a Profile to a json dictionary :param profile: :return: """ if profile.is_sparse: indptr, data = profile.get_sparse_representation() return {'type': 'sparse', 'base': profile.default_value, 'size': profile.size(), 'data': data, 'indptr': indptr} else: arr = profile.tolist() return {'type': 'dense', 'data': arr}
[docs] def json_to_profile(profile: AnyProfile, d: Dict[str, Any]) -> None: """ Assign a json profile to a Profile object :param profile: Profile to modify :param d: json parsed dictionary """ if isinstance(d, dict): if 'type' in d.keys(): if d['type'] == 'sparse': profile.create_sparse(size=d['size'], default_value=d['base']) profile.set_sparse_data_from_data(indptr=d['indptr'], data=d['data']) return None elif d['type'] == 'dense': val = np.array(d['data']) if len(val): profile.default_value = val[0] profile.set(arr=val) else: profile.default_value = 0 return None else: raise Exception('Unknown profile type' + str(d['type'])) else: raise Exception("The passed dictionary is not a profile definition") elif isinstance(d, list): if len(d) > 0: profile.default_value = d[0] profile.set(arr=np.array(d)) return None else: raise Exception("The passed value is not a list or dictionary definition")
[docs] def get_profiles_dict(elm: EditableDevice) -> Dict[str, Any]: """ :return: """ """ Example: {'id': self.idtag, 'active': active_prof, 'rate': rate_prof} """ data = {'id': elm.idtag} for property_name, profile_name in elm.properties_with_profile.items(): data[property_name] = profile_to_json(elm.get_profile(magnitude=property_name)) return data
[docs] def parse_json_data(data) -> MultiCircuit: """ Parse JSON structure into VeraGrid MultiCircuit :param data: JSON structure (list of dictionaries) :return: VeraGrid MultiCircuit """ circuit = MultiCircuit() bus_id = dict() for element in data: if element["phases"] == 'ps': if element["type"] == "circuit": circuit = MultiCircuit() circuit.name = element["name"] circuit.Sbase = element["Sbase"] circuit.comments = element['comments'] elif element["type"] == "bus": # create the bus and add some properties elm = dev.Bus(name=element["name"], Vnom=element["Vnom"], vmin=0.9, vmax=1.1, xpos=element['x'], ypos=element['y'], height=element['h'], width=element['w'], active=True) if element["is_slack"]: elm._bus_type = dev.BusMode.Slack_tpe if element["vmax"] > 0: elm.Vmax = element["vmax"] if element["vmin"] > 0: elm.Vmin = element["vmin"] elm.Zf = complex(element['rf'], element['xf']) circuit.add_bus(elm) # add the bus to the dictionary bus_id[element["id"]] = elm elif element["type"] == "load": # get the matching bus object pointer bus = bus_id[element["bus"]] # create a load in the bus elm = dev.Load(name=element['name'], G=element["G"], B=element["B"], Ir=element["Ir"], Ii=element["Ii"], P=element["P"], Q=element["Q"], active=element['active']) circuit.add_load(bus=bus, api_obj=elm) elif element["type"] == "controlled_gen": # get the matching bus object pointer bus = bus_id[element["bus"]] # create a load in the bus elm = dev.Generator(name=element['name'], P=element["P"], vset=element["vset"], Qmin=element['qmin'], Qmax=element['qmax'], Snom=element['Snom'], active=element['active'], Pmin=0.0, Pmax=element['Snom'], Cost=1.0) circuit.add_generator(bus=bus, api_obj=elm) elif element["type"] == "static_gen": # get the matching bus object pointer bus = bus_id[element["bus"]] # create a load in the bus elm = dev.StaticGenerator(name=element['name'], P=element['P'], Q=element['Q'], active=element['active']) circuit.add_generator(bus=bus, api_obj=elm) elif element["type"] == "battery": # get the matching bus object pointer bus = bus_id[element["bus"]] # create a load in the bus elm = dev.Battery(name=element['name'], P=element["P"], vset=element["vset"], Qmin=element['qmin'], Qmax=element['qmax'], Snom=element['Snom'], Enom=element['Enom'], active=element['active']) circuit.add_battery(bus=bus, api_obj=elm) elif element["type"] == "shunt": # get the matching bus object pointer bus = bus_id[element["bus"]] # create a load in the bus elm = dev.Shunt(name=element['name'], G=element["g"], B=element["b"], active=element['active']) circuit.add_shunt(bus=bus, api_obj=elm) elif element["type"] == "branch": # get the matching bus object pointer bus1 = bus_id[element["from"]] bus2 = bus_id[element["to"]] # create a load in the bus elm = dev.Branch(bus_from=bus1, bus_to=bus2, name=element["name"], r=element["r"], x=element["x"], g=element["g"], b=element["b"], rate=element["rate"], tap=element["tap_module"], shift_angle=element["tap_angle"], active=element["active"], mttf=0, mttr=0, branch_type=element["branch_type"]) circuit.add_branch(elm) else: warn('ID: ' + element["id"] + ' error: VeraGrid only takes positive sequence elements.') return circuit
[docs] def set_object_properties(elm, prop: List[str], entry: Dict[str, Any]): """ Set the properties of an object :param elm: object to be set :param prop: list of properties :param entry: :return: """ for jprop, gcprop in prop: if jprop in entry.keys(): setattr(elm, gcprop, entry[jprop])
[docs] def parse_json_data_v3(data: dict, logger: Logger): """ Json parser for V3 :param data: :param logger: :return: """ devices = data['devices'] profiles = data['profiles'] # parse devices if DeviceType.CircuitDevice.value in devices.keys(): dta = devices[DeviceType.CircuitDevice.value] circuit = MultiCircuit(name=str(dta['name']), Sbase=float(dta['sbase']), fbase=float(dta['fbase']), idtag=str(dta['id'])) jcircuit = devices["Circuit"] circuit.Sbase = jcircuit["sbase"] # parse time series if DeviceType.CircuitDevice.value in profiles.keys(): circuit.set_time_profile(profiles[DeviceType.CircuitDevice.value]['time']) # Countries country_dict = dict() if 'Country' in devices.keys(): elms = devices["Country"] for jentry in elms: elm = dev.Country(idtag=str(jentry['id']), code=str(jentry['code']), name=str(jentry['name'])) circuit.add_country(elm) country_dict[elm.idtag] = elm else: elm = dev.Country(idtag=None, code='Default', name='Default') circuit.add_country(elm) # Areas areas_dict = dict() if 'Area' in devices.keys(): elms = devices["Area"] for jentry in elms: elm = dev.Area(idtag=str(jentry['id']), code=str(jentry['code']), name=str(jentry['name'])) circuit.add_area(elm) areas_dict[elm.idtag] = elm else: elm = dev.Area(idtag=None, code='Default', name='Default') circuit.add_area(elm) # Zones zones_dict = dict() if 'Zone' in devices.keys(): elms = devices["Zone"] for jentry in elms: elm = dev.Zone(idtag=str(jentry['id']), code=str(jentry['code']), name=str(jentry['name'])) circuit.add_zone(elm) zones_dict[elm.idtag] = elm else: elm = dev.Zone(idtag=None, code='Default', name='Default') circuit.add_zone(elm) # Substations substations_dict = dict() if 'Substation' in devices.keys(): elms = devices["Substation"] for jentry in elms: elm = dev.Substation(idtag=str(jentry['id']), code=str(jentry['code']), name=str(jentry['name'])) circuit.add_substation(elm) substations_dict[elm.idtag] = elm else: elm = dev.Substation(idtag=None, code='Default', name='Default') circuit.add_substation(elm) # buses bus_dict = dict() if 'Bus' in devices.keys(): buses = devices["Bus"] if 'Bus' in profiles.keys(): device_profiles_dict = {e['id']: e for e in profiles["Bus"]} has_profiles = True else: device_profiles_dict = dict() has_profiles = False for jentry in buses: area_id = str(jentry['area']) if 'area' in jentry.keys() else '' zone_id = str(jentry['zone']) if 'zone' in jentry.keys() else '' substation_id = str(jentry['Substation']) if 'Substation' in jentry.keys() else '' country_id = str(jentry['country']) if 'country' in jentry.keys() else '' area = areas_dict.get(area_id, None) zone = zones_dict.get(zone_id, None) substation = substations_dict.get(substation_id, None) country = country_dict.get(country_id, None) bus = dev.Bus(name=str(jentry['name']), idtag=str(jentry['id']), code=str(jentry['name_code']), Vnom=float(jentry['vnom']), vmin=float(jentry['vmin']), vmax=float(jentry['vmax']), r_fault=float(jentry['rf']), x_fault=float(jentry['xf']), xpos=float(jentry['x']), ypos=float(jentry['y']), height=float(jentry['h']), width=float(jentry['w']), active=bool(jentry['active']), is_slack=bool(jentry['is_slack']), is_internal=bool(jentry.get('is_internal', False)), is_dc=bool(jentry.get('is_dc', False)), area=area, zone=zone, substation=substation, country=country, longitude=float(jentry['lon']), latitude=float(jentry['lat'])) bus_dict[jentry['id']] = bus if has_profiles: json_to_profile(bus.active_prof, device_profiles_dict[bus.idtag]['active']) circuit.add_bus(bus) if 'Generator' in devices.keys(): generators = devices["Generator"] if 'Generator' in profiles.keys(): device_profiles_dict = {e['id']: e for e in profiles["Generator"]} has_profiles = True else: device_profiles_dict = dict() has_profiles = False for jentry in generators: control_mode = GeneratorControlMode.V if bool(jentry['is_controlled']) else GeneratorControlMode.Q elm = dev.Generator( name=str(jentry['name']), idtag=str(jentry['id']), P=float(jentry['p']), power_factor=float(jentry['pf']), vset=float(jentry['vset']), control_mode=control_mode, Qmin=float(jentry['qmin']), Qmax=float(jentry['qmax']), Snom=float(jentry['snom']), active=bool(jentry['active']), Pmin=float(jentry['pmin']), Pmax=float(jentry['pmax']), Cost=float(jentry['cost'] if "cost" in jentry else 1.0), ) if has_profiles: profile_entry = device_profiles_dict[elm.idtag] json_to_profile(elm.active_prof, profile_entry['active']) json_to_profile(elm.P_prof, profile_entry['p']) json_to_profile(elm.Vset_prof, profile_entry['v']) json_to_profile(elm.Pf_prof, profile_entry['pf']) elm.bus = bus_dict[jentry['bus']] circuit.add_generator(elm.bus, elm) if 'Battery' in devices.keys(): batteries = devices["Battery"] if 'Battery' in profiles.keys(): device_profiles_dict = {e['id']: e for e in profiles["Battery"]} has_profiles = True else: device_profiles_dict = dict() has_profiles = False for jentry in batteries: control_mode = GeneratorControlMode.V if bool(jentry['is_controlled']) else GeneratorControlMode.Q elm = dev.Battery( name=str(jentry['name']), idtag=str(jentry['id']), P=float(jentry['p']), power_factor=float(jentry['pf']), vset=float(jentry['vset']), control_mode=control_mode, Qmin=float(jentry['qmin']), Qmax=float(jentry['qmax']), Snom=float(jentry['snom']), active=bool(jentry['active']), Pmin=float(jentry['pmin']), Pmax=float(jentry['pmax']), Cost=float(jentry['cost']), ) if has_profiles: profile_entry = device_profiles_dict[elm.idtag] json_to_profile(elm.active_prof, profile_entry['active']) json_to_profile(elm.P_prof, profile_entry['p']) json_to_profile(elm.Vset_prof, profile_entry['v']) json_to_profile(elm.Pf_prof, profile_entry['pf']) elm.bus = bus_dict[jentry['bus']] circuit.add_battery(elm.bus, elm) if 'Load' in devices.keys(): loads = devices["Load"] if 'Load' in profiles.keys(): device_profiles_dict = {e['id']: e for e in profiles["Load"]} has_profiles = True else: device_profiles_dict = dict() has_profiles = False for jentry in loads: elm = dev.Load(name=str(jentry['name']), idtag=str(jentry['id']), P=float(jentry['p']), Q=float(jentry['q']), Ir=float(jentry['ir']), Ii=float(jentry['ii']), G=float(jentry['g']), B=float(jentry['b']), active=bool(jentry['active'])) if has_profiles: profile_entry = device_profiles_dict[elm.idtag] json_to_profile(elm.active_prof, profile_entry['active']) json_to_profile(elm.P_prof, profile_entry['p']) json_to_profile(elm.Q_prof, profile_entry['q']) json_to_profile(elm.Ir_prof, profile_entry['ir']) json_to_profile(elm.Ii_prof, profile_entry['ii']) json_to_profile(elm.G_prof, profile_entry['g']) json_to_profile(elm.B_prof, profile_entry['b']) elm.bus = bus_dict[jentry['bus']] circuit.add_load(elm.bus, elm) if "Shunt" in devices.keys(): shunts = devices["Shunt"] if 'Shunt' in profiles.keys(): device_profiles_dict = {e['id']: e for e in profiles["Shunt"]} has_profiles = True else: device_profiles_dict = dict() has_profiles = False for jentry in shunts: if 'b_max' in jentry: Bmax = float(jentry['b_max']) elif 'bmax' in jentry: Bmax = float(jentry['bmax']) else: Bmax = 9999.0 if 'b_min' in jentry: Bmin = float(jentry['b_min']) elif 'bmax' in jentry: Bmin = float(jentry['bmin']) else: Bmin = 9999.0 elm = dev.Shunt(name=str(jentry['name']), idtag=str(jentry['id']), G=float(jentry['g']), B=float(jentry['b']), active=bool(jentry['active']) ) if has_profiles: profile_entry = device_profiles_dict[elm.idtag] json_to_profile(elm.active_prof, profile_entry['active']) json_to_profile(elm.G_prof, profile_entry['g']) json_to_profile(elm.B_prof, profile_entry['b']) elm.bus = bus_dict[jentry['bus']] circuit.add_shunt(elm.bus, elm) if "Line" in devices.keys(): if 'Line' in profiles.keys(): device_profiles_dict = {e['id']: e for e in profiles["Line"]} has_profiles = True else: device_profiles_dict = dict() has_profiles = False for entry in devices["Line"]: build_status = BuildStatus.Commissioned build_status_str = entry.get("build_status", None) if build_status_str is not None: if build_status_str == "candidate": build_status = BuildStatus.Candidate elif build_status_str == "commissioned": build_status = BuildStatus.Commissioned elif build_status_str == "decommissioned": build_status = BuildStatus.Decommissioned elif build_status_str == "planned": build_status = BuildStatus.Planned elif build_status_str == "planned_decommission": build_status = BuildStatus.PlannedDecommission elm = dev.Line(bus_from=bus_dict[entry['bus_from']], bus_to=bus_dict[entry['bus_to']], name=str(entry['name']), idtag=str(entry['id']), code=str(entry['name_code']), r=float(entry['r']), x=float(entry['x']), b=float(entry['b']), rate=float(entry['rate']), active=entry['active'], length=float(entry['length']), temp_base=float(entry['base_temperature']), temp_oper=float(entry['operational_temperature']), alpha=float(entry['alpha']), build_status=build_status, opex=entry.get('opex', 0.0), capex=entry.get('capex', 0.0) ) if build_status == BuildStatus.Candidate: inv_group = dev.InvestmentsGroup(idtag='', name=f'inv{elm.name}', category='single') invst = dev.Investment(idtag='', device=elm, name=f'inv{elm.name}', code=elm.code, CAPEX=elm.capex, group=inv_group) circuit.add_investments_group(inv_group) circuit.add_investment(invst) if has_profiles: profile_entry = device_profiles_dict[elm.idtag] json_to_profile(elm.active_prof, profile_entry['active']) json_to_profile(elm.rate_prof, profile_entry['rate']) circuit.add_line(elm, logger=logger) if "DC line" in devices.keys(): if 'DC line' in profiles.keys(): device_profiles_dict = {e['id']: e for e in profiles["DC line"]} has_profiles = True else: device_profiles_dict = dict() has_profiles = False for entry in devices["DC line"]: elm = dev.DcLine(bus_from=bus_dict[entry['bus_from']], bus_to=bus_dict[entry['bus_to']], name=str(entry['name']), idtag=str(entry['id']), code=str(entry['name_code']), r=float(entry['r']), rate=float(entry['rate']), active=entry['active'], length=float(entry['length']), temp_base=float(entry['base_temperature']), temp_oper=float(entry['operational_temperature']), alpha=float(entry['alpha'])) if has_profiles: profile_entry = device_profiles_dict[elm.idtag] json_to_profile(elm.active_prof, profile_entry['active']) json_to_profile(elm.rate_prof, profile_entry['rate']) circuit.add_dc_line(elm) if "Transformer2w" in devices.keys() or "Transformer" in devices.keys(): if "Transformer2w" in devices.keys(): transformers = devices["Transformer2w"] if 'Transformer2w' in profiles.keys(): device_profiles_dict = {e['id']: e for e in profiles["Transformer2w"]} has_profiles = True else: device_profiles_dict = dict() has_profiles = False else: transformers = devices["Transformer"] if 'Transformer' in profiles.keys(): device_profiles_dict = {e['id']: e for e in profiles["Transformer"]} has_profiles = True else: device_profiles_dict = dict() has_profiles = False for entry in transformers: v1 = float(entry['Vnomf']) v2 = float(entry['Vnomt']) bus_from = bus_dict[entry['bus_from']] bus_to = bus_dict[entry['bus_to']] if v1 == 0.0: v1 = bus_from.Vnom if v2 == 0.0: v2 = bus_to.Vnom if v1 > v2: HV = v1 LV = v2 else: HV = v2 LV = v1 elm = dev.Transformer2W(bus_from=bus_from, bus_to=bus_to, name=str(entry['name']), idtag=str(entry['id']), code=str(entry['name_code']), r=float(entry['r']), x=float(entry['x']), g=float(entry['g']), b=float(entry['b']), rate=float(entry['rate']), HV=HV, LV=LV, active=bool(entry['active']), tap_module=float(entry['tap_module']), tap_phase=float(entry['tap_angle']), vset=float(entry['vset']), temp_base=float(entry['base_temperature']), temp_oper=float(entry['operational_temperature']), alpha=float(entry['alpha']) ) if has_profiles: profile_entry = device_profiles_dict[elm.idtag] json_to_profile(elm.active_prof, profile_entry['active']) json_to_profile(elm.rate_prof, profile_entry['rate']) circuit.add_transformer2w(elm) windings_dict = dict() if "Windings" in devices.keys(): transformers = devices["Windings"] if 'Windings' in profiles.keys(): device_profiles_dict = {e['id']: e for e in profiles["Windings"]} has_profiles = True else: device_profiles_dict = dict() has_profiles = False for entry in transformers: v1 = float(entry['Vnomf']) v2 = float(entry['Vnomt']) bus_from = bus_dict[entry['bus_from']] bus_to = bus_dict[entry['bus_to']] if v1 == 0.0: v1 = bus_from.Vnom if v2 == 0.0: v2 = bus_to.Vnom if v1 > v2: HV = v1 LV = v2 else: HV = v2 LV = v1 elm = dev.Winding(bus_from=bus_from, bus_to=bus_to, name=str(entry['name']), idtag=str(entry['id']), code=str(entry['name_code']), r=float(entry['r']), x=float(entry['x']), g=float(entry['g']), b=float(entry['b']), rate=float(entry['rate']), HV=HV, LV=LV, active=bool(entry['active']), tap_module=float(entry['tap_module']), tap_phase=float(entry['tap_angle']), vset=float(entry['vset']), temp_base=float(entry['base_temperature']), temp_oper=float(entry['operational_temperature']), alpha=float(entry['alpha']) ) if has_profiles: profile_entry = device_profiles_dict[elm.idtag] json_to_profile(elm.active_prof, profile_entry['active']) json_to_profile(elm.rate_prof, profile_entry['rate']) circuit.add_winding(elm) windings_dict[elm.idtag] = elm if "Transformer3w" in devices.keys(): transformers = devices["Transformer3w"] for entry in transformers: elm = dev.Transformer3W(idtag=entry['id'], code=entry['code'], name=entry['name'], bus1=bus_dict[entry['bus_1']], bus2=bus_dict[entry['bus_2']], bus3=bus_dict[entry['bus_3']]) elm.bus0 = bus_dict[entry['bus_0']] elm.winding1 = windings_dict[entry['winding1']] elm.winding2 = windings_dict[entry['winding2']] elm.winding3 = windings_dict[entry['winding3']] circuit.add_transformer3w(elm) if "TransformerNw" in devices.keys(): for tr_entry in devices["TransformerNw"]: for entry in tr_entry['windings']: v1 = float(entry['Vnomf']) v2 = float(entry['Vnomt']) if v1 > v2: HV = v1 LV = v2 else: HV = v2 LV = v1 elm = dev.Transformer2W(bus_from=bus_dict[entry['bus_from']], bus_to=bus_dict[entry['bus_to']], name=str(tr_entry['name']), idtag=str(entry['id']), code=str(entry['name_code']), active=bool(tr_entry['active']), r=float(entry['r']), x=float(entry['x']), g=float(entry['g']), b=float(entry['b']), rate=float(entry['rate']), HV=HV, LV=LV ) circuit.add_transformer2w(elm) if "VSC" in devices.keys(): if 'VSC' in profiles.keys(): device_profiles_dict = {e['id']: e for e in profiles["VSC"]} has_profiles = True else: device_profiles_dict = dict() has_profiles = False # json property -> gc property name prop = [('id', 'idtag'), ('name', 'name'), ('name_code', 'code'), ('active', 'active'), ('rate', 'rate'), ('contingency_factor1', 'contingency_factor'), ('r', 'R1'), ('x', 'X1'), ('G0sw', 'G0sw'), ('m', 'm'), ('m_min', 'm_min'), ('m_max', 'm_max'), ('theta', 'theta'), ('theta_min', 'theta_min'), ('theta_max', 'theta_max'), ('Beq', 'Beq'), ('Beq_min', 'Beq_min'), ('Beq_max', 'Beq_max'), ('alpha1', 'alpha1'), ('alpha2', 'alpha2'), ('alpha3', 'alpha3'), ('k', 'k'), ('kdp', 'kdp'), ('Pfset', 'Pdc_set'), ('Qfset', 'Qac_set'), ('vac_set', 'Vac_set'), ('vdc_set', 'Vdc_set'), ] # modes = {0: ConverterControlType.type_0_free, # 1: ConverterControlType.type_I_1, # 2: ConverterControlType.type_I_2, # 3: ConverterControlType.type_I_3, # 4: ConverterControlType.type_II_4, # 5: ConverterControlType.type_II_5, # 6: ConverterControlType.type_III_6, # 7: ConverterControlType.type_III_7, # 8: ConverterControlType.type_IV_I, # 9: ConverterControlType.type_IV_II} for entry in devices["VSC"]: elm = dev.VSC() elm.bus_from = bus_dict[entry['bus_from']] elm.bus_to = bus_dict[entry['bus_to']] set_object_properties(elm, prop, entry) # if "control_mode" in entry.keys(): # elm.control_mode = modes[entry["control_mode"]] # elif "mode" in entry.keys(): # elm.control_mode = modes[entry["mode"]] if has_profiles: profile_entry = device_profiles_dict[elm.idtag] json_to_profile(elm.active_prof, profile_entry['active']) json_to_profile(elm.rate_prof, profile_entry['rate']) circuit.add_vsc(elm) if "HVDC Line" in devices.keys(): if 'HVDC Line' in profiles.keys(): device_profiles_dict = {e['id']: e for e in profiles["HVDC Line"]} has_profiles = True else: device_profiles_dict = dict() has_profiles = False hvdc_ctrl_dict = dict() hvdc_ctrl_dict[HvdcControlType.type_1_Pset.value] = HvdcControlType.type_1_Pset hvdc_ctrl_dict[HvdcControlType.type_0_free.value] = HvdcControlType.type_0_free prop = [('id', 'idtag'), ('name', 'name'), ('name_code', 'code'), ('active', 'active'), ('rate', 'rate'), ('Pset', 'Pset'), ('vset_from', 'Vset_f'), ('vset_to', 'Vset_t'), ('contingency_factor1', 'contingency_factor'), ('length', 'length'), ('r', 'r'), ('angle_droop', 'angle_droop'), ('min_firing_angle_f', 'min_firing_angle_f'), ('max_firing_angle_f', 'max_firing_angle_f'), ('min_firing_angle_t', 'min_firing_angle_t'), ('max_firing_angle_t', 'max_firing_angle_t'), ('overload_cost', 'overload_cost'), ] for entry in devices["HVDC Line"]: elm = dev.HvdcLine() elm.bus_from = bus_dict[entry['bus_from']] elm.bus_to = bus_dict[entry['bus_to']] set_object_properties(elm, prop, entry) if "control_mode" in entry.keys(): elm.control_mode = hvdc_ctrl_dict[entry["control_mode"]] if has_profiles: profile_entry = device_profiles_dict[elm.idtag] json_to_profile(elm.active_prof, profile_entry['active']) json_to_profile(elm.rate_prof, profile_entry['rate']) json_to_profile(elm.Pset_prof, profile_entry['Pset']) json_to_profile(elm.Vset_f_prof, profile_entry['vset_from']) json_to_profile(elm.Vset_t_prof, profile_entry['vset_to']) json_to_profile(elm.overload_cost_prof, profile_entry['overload_cost']) circuit.add_hvdc(elm) else: logger.add('The Json structure does not have a Circuit inside the devices!') return MultiCircuit() if 'contingencies' in data.keys(): circuit.set_contingencies( contingencies=parse_contingencies(data['contingencies']) ) # fill x, y logger += circuit.fill_xy_from_lat_lon() return circuit
[docs] def parse_json_data_v2(data: dict, logger: Logger): """ New Json parser :param data: :param logger: :return: """ devices = data['devices'] profiles = data['profiles'] if DeviceType.CircuitDevice.value in devices.keys(): dta = devices[DeviceType.CircuitDevice.value] circuit = MultiCircuit(name=str(dta['name']), Sbase=float(dta['sbase']), fbase=float(dta['fbase']), idtag=str(dta['id'])) jcircuit = devices["Circuit"] circuit.Sbase = jcircuit["sbase"] # Countries country_dict = dict() if 'Country' in devices.keys(): elms = devices["Country"] for jentry in elms: elm = dev.Country(idtag=str(jentry['id']), code=str(jentry['code']), name=str(jentry['name'])) circuit.add_country(elm) country_dict[elm.idtag] = elm else: elm = dev.Country(idtag=None, code='Default', name='Default') circuit.add_country(elm) # Areas areas_dict = dict() if 'Area' in devices.keys(): elms = devices["Area"] for jentry in elms: elm = dev.Area(idtag=str(jentry['id']), code=str(jentry['code']), name=str(jentry['name'])) circuit.add_area(elm) areas_dict[elm.idtag] = elm else: elm = dev.Area(idtag=None, code='Default', name='Default') circuit.add_area(elm) # Zones zones_dict = dict() if 'Zone' in devices.keys(): elms = devices["Zone"] for jentry in elms: elm = dev.Zone(idtag=str(jentry['id']), code=str(jentry['code']), name=str(jentry['name'])) circuit.add_zone(elm) zones_dict[elm.idtag] = elm else: elm = dev.Zone(idtag=None, code='Default', name='Default') circuit.add_zone(elm) # Substations substations_dict = dict() if 'Substation' in devices.keys(): elms = devices["Substation"] for jentry in elms: elm = dev.Substation(idtag=str(jentry['id']), code=str(jentry['code']), name=str(jentry['name'])) circuit.add_substation(elm) substations_dict[elm.idtag] = elm else: elm = dev.Substation(idtag=None, code='Default', name='Default') circuit.add_substation(elm) # buses bus_dict = dict() if 'Bus' in devices.keys(): buses = devices["Bus"] for jentry in buses: area_id = str(jentry['area']) if 'area' in jentry.keys() else '' zone_id = str(jentry['zone']) if 'zone' in jentry.keys() else '' substation_id = str(jentry['Substation']) if 'Substation' in jentry.keys() else '' country_id = str(jentry['country']) if 'country' in jentry.keys() else '' area = areas_dict.get(area_id, None) zone = zones_dict.get(zone_id, None) substation = substations_dict.get(substation_id, None) country = country_dict.get(country_id, None) bus = dev.Bus(name=str(jentry['name']), idtag=str(jentry['id']), Vnom=float(jentry['vnom']), vmin=float(jentry['vmin']), vmax=float(jentry['vmax']), r_fault=float(jentry['rf']), x_fault=float(jentry['xf']), xpos=float(jentry['x']), ypos=float(jentry['y']), height=float(jentry['h']), width=float(jentry['w']), active=bool(jentry['active']), is_slack=bool(jentry['is_slack']), area=area, zone=zone, substation=substation, country=country, longitude=float(jentry['lon']), latitude=float(jentry['lat'])) bus_dict[jentry['id']] = bus circuit.add_bus(bus) if 'Generator' in devices.keys(): generators = devices["Generator"] for jentry in generators: if bool(jentry['is_controlled']): control_mode = GeneratorControlMode.V else: control_mode = GeneratorControlMode.Q gen = dev.Generator(name=str(jentry['name']), idtag=str(jentry['id']), P=float(jentry['p']), power_factor=float(jentry['pf']), vset=float(jentry['vset']), control_mode=control_mode, Qmin=float(jentry['qmin']), Qmax=float(jentry['qmax']), Snom=float(jentry['snom']), active=bool(jentry['active']), Pmin=float(jentry['pmin']), Pmax=float(jentry['pmax']), Cost=float(jentry['cost']), ) gen.bus = bus_dict[jentry['bus']] circuit.add_generator(gen.bus, gen) if 'Battery' in devices.keys(): batteries = devices["Battery"] for jentry in batteries: if bool(jentry['is_controlled']): control_mode = GeneratorControlMode.V else: control_mode = GeneratorControlMode.Q gen = dev.Battery(name=str(jentry['name']), idtag=str(jentry['id']), P=float(jentry['p']), power_factor=float(jentry['pf']), vset=float(jentry['vset']), control_mode=control_mode, Qmin=float(jentry['qmin']), Qmax=float(jentry['qmax']), Snom=float(jentry['snom']), active=bool(jentry['active']), Pmin=float(jentry['pmin']), Pmax=float(jentry['pmax']), Cost=float(jentry['cost']), ) gen.bus = bus_dict[jentry['bus']] circuit.add_battery(gen.bus, gen) if 'Load' in devices.keys(): loads = devices["Load"] for jentry in loads: elm = dev.Load(name=str(jentry['name']), idtag=str(jentry['id']), P=float(jentry['p']), Q=float(jentry['q']), active=bool(jentry['active'])) elm.bus = bus_dict[jentry['bus']] circuit.add_load(elm.bus, elm) if "Shunt" in devices.keys(): shunts = devices["Shunt"] for jentry in shunts: elm = dev.Shunt(name=str(jentry['name']), idtag=str(jentry['id']), G=float(jentry['g']), B=float(jentry['b']), active=bool(jentry['active'])) elm.bus = bus_dict[jentry['bus']] circuit.add_shunt(elm.bus, elm) if "Line" in devices.keys(): lines = devices["Line"] for entry in lines: elm = dev.Line(bus_from=bus_dict[entry['bus_from']], bus_to=bus_dict[entry['bus_to']], name=str(entry['name']), idtag=str(entry['id']), r=float(entry['r']), x=float(entry['x']), b=float(entry['b']), rate=float(entry['rate']), active=entry['active'], length=float(entry['length']), ) circuit.add_line(elm, logger=logger) if "Transformer" in devices.keys() or "Transformer2w" in devices.keys(): if "Transformer" in devices.keys(): transformers = devices["Transformer"] elif "Transformer2w" in devices.keys(): transformers = devices["Transformer2w"] else: raise Exception('Transformer key not found') for entry in transformers: elm = dev.Transformer2W(bus_from=bus_dict[entry['bus_from']], bus_to=bus_dict[entry['bus_to']], name=str(entry['name']), idtag=str(entry['id']), r=float(entry['r']), x=float(entry['x']), g=float(entry['g']), b=float(entry['b']), rate=float(entry['rate']), active=bool(entry['active']), tap_module=float(entry['tap_module']), tap_phase=float(entry['tap_angle']), ) circuit.add_transformer2w(elm) if "VSC" in devices.keys(): vsc = devices["VSC"] # TODO: call correct_buses_connection() if "HVDC Line" in devices.keys(): hvdc = devices["HVDC Line"] # fill x, y logger += circuit.fill_xy_from_lat_lon() return circuit else: logger.add('The Json structure does not have a Circuit inside the devices!') return MultiCircuit()
[docs] def parse_json(file_name) -> MultiCircuit: """ Parse JSON file into Circuit :param file_name: :return: VeraGrid MultiCircuit """ data = json.load(open(file_name)) return parse_json_data(data)
# def save_json_file_v3_old(file_path: str, circuit: MultiCircuit, simulation_drivers: Union[None, List[Any]] = None): # """ # Save JSON file # :param file_path: file path # :param circuit: VeraGrid MultiCircuit element # :param simulation_drivers: List of Simulation Drivers (optional) # """ # elements = dict() # element_profiles = dict() # units_dict = dict() # logger = Logger() # # # add the circuit # elements[DeviceType.CircuitDevice.value] = circuit.get_properties_dict() # units_dict[DeviceType.CircuitDevice.value] = circuit.get_units_dict() # element_profiles[DeviceType.CircuitDevice.value] = circuit.get_profiles_dict() # # # idelly, these list go in dependency order # all_lists = [circuit.substations, # circuit.zones, # circuit.areas, # circuit.countries, # circuit.technologies, # circuit.contingency_groups, # circuit.contingencies, # circuit.investments_groups, # circuit.investments, # circuit.buses, # circuit.connectivity_nodes] # all_lists += circuit.get_injection_devices_lists() # all_lists += circuit.get_branch_lists() # # # add the devices # for device_list in all_lists: # for elm in device_list: # # pack the bus data into a dictionary # key = elm.device_type.value # add_to_dict(main_dict=elements, # data_to_append=elm.get_properties_dict(), # key=key) # add_to_dict(main_dict=element_profiles, # data_to_append=get_profiles_dict(elm), # key=key) # # # results # results = dict() # if simulation_drivers is not None: # for driver in simulation_drivers: # if driver is not None: # # if driver.name == 'Power Flow': # # bus_data = dict() # for i, elm in enumerate(circuit.buses): # bus_data[elm.idtag] = {'vm': np.abs(driver.results.voltage[i]), # 'va': np.angle(driver.results.voltage[i])} # # branch_data = dict() # for i, elm in enumerate(circuit.get_branches_wo_hvdc()): # branch_data[elm.idtag] = {'p': driver.results.Sf[i].real, # 'q': driver.results.Sf[i].imag, # 'losses': driver.results.losses[i].real} # # for i, elm in enumerate(circuit.hvdc_lines): # branch_data[elm.idtag] = {'p': driver.results.hvdc_Pf[i].real, # 'q': 0, # 'losses': driver.results.hvdc_losses[i].real} # # results["power_flow"] = {'bus': bus_data, # 'branch': branch_data} # # elif driver.name == 'Time Series': # # bus_data = dict() # for i, elm in enumerate(circuit.buses): # bus_data[elm.idtag] = {'vm': np.abs(driver.results.voltage[:, i]).tolist(), # 'va': np.angle(driver.results.voltage[:, i]).tolist()} # # branch_data = dict() # for i, elm in enumerate(circuit.get_branches_wo_hvdc()): # branch_data[elm.idtag] = {'p': driver.results.Sf[:, i].real.tolist(), # 'q': driver.results.Sf[:, i].imag.tolist(), # 'losses': driver.results.losses[:, i].real.tolist()} # # for i, elm in enumerate(circuit.hvdc_lines): # branch_data[elm.idtag] = {'p': driver.results.hvdc_Pf[:, i].real, # 'q': 0, # 'losses': driver.results.hvdc_losses[:, i].real} # # results["time_series"] = {'bus': bus_data, # 'branch': branch_data} # # data = {'version': '3', # 'review': '3', # 'software': 'VeraGrid', # 'units': units_dict, # 'devices': elements, # 'profiles': element_profiles, # 'contingencies': get_contingencies_dict(circuit=circuit), # 'results': results, # } # # data_str = json.dumps(data, indent=True, cls=CustomJSONizer) # # # Save json to a text file # text_file = open(file_path, "w") # text_file.write(data_str) # text_file.close() # # return logger
[docs] def get_obj_ref(elm): """ get the idtag and if none return an empty str :param elm: :return: """ return elm.idtag if elm is not None else ''
[docs] def save_json_file_v3(file_path: str, circuit: MultiCircuit, simulation_drivers: List[DriverToSave] | None = None): """ Save JSON file :param file_path: file path :param circuit: VeraGrid MultiCircuit element :param simulation_drivers: List of Simulation Drivers (optional) """ logger = Logger() units_dict = dict() elements = dict() element_profiles = dict() # add the circuit elements["Circuit"] = {'id': circuit.idtag, 'phases': 'ps', 'name': circuit.name, 'sbase': circuit.Sbase, 'fbase': circuit.fBase, 'model_version': circuit.model_version, 'user_name': circuit.user_name, 'comments': circuit.comments} element_profiles["Circuit"] = {'time': circuit.get_time_profile_as_list()} # Add area-like devices elements['Country'] = [{'id': elm.idtag, 'name': elm.name, 'code': elm.code} for elm in circuit.get_countries()] elements["Community"] = [{'id': elm.idtag, 'name': elm.name, 'code': elm.code} for elm in circuit.get_communities()] elements["Region"] = [{'id': elm.idtag, 'name': elm.name, 'code': elm.code} for elm in circuit.get_regions()] elements["Municipality"] = [{'id': elm.idtag, 'name': elm.name, 'code': elm.code} for elm in circuit.get_municipalities()] elements['Area'] = [{'id': elm.idtag, 'name': elm.name, 'code': elm.code} for elm in circuit.get_areas()] elements['Zone'] = [{'id': elm.idtag, 'name': elm.name, 'code': elm.code} for elm in circuit.get_zones()] elements['Substation'] = [{'id': elm.idtag, 'name': elm.name, 'code': elm.code, 'area': get_obj_ref(elm.area), 'zone': get_obj_ref(elm.zone), 'country': get_obj_ref(elm.country), 'community': get_obj_ref(elm.community), 'region': get_obj_ref(elm.region), 'municipality': get_obj_ref(elm.municipality), 'address': elm.address} for elm in circuit.get_substations()] elements['Voltage level'] = [{'id': elm.idtag, 'name': elm.name, 'code': elm.code, 'v_nom': elm.Vnom, 'substation': get_obj_ref(elm.substation)} for elm in circuit.get_voltage_levels()] # Add buses elements['Bus'] = [{'id': elm.idtag, 'type': elm.determine_bus_type().value, 'phases': 'ps', 'name': elm.name, 'name_code': elm.code, 'active': elm.active, 'is_slack': bool(elm.is_slack), 'is_internal': bool(elm.internal), 'is_dc': bool(elm.is_dc), 'vnom': elm.Vnom, 'vmin': elm.Vmin, 'vmax': elm.Vmax, 'rf': elm.r_fault, 'xf': elm.x_fault, 'x': elm.x, 'y': elm.y, 'h': elm.h, 'w': elm.w, 'lat': elm.latitude, 'lon': elm.longitude, 'alt': 0.0, 'country': get_obj_ref(elm.country), 'area': get_obj_ref(elm.area), 'zone': get_obj_ref(elm.zone), 'Substation': get_obj_ref(elm.substation), } for elm in circuit.get_buses()] element_profiles['Bus'] = [{'id': elm.idtag, 'active': profile_to_json(elm.active_prof)} for elm in circuit.get_buses()] # bus bars elements["BusBar"] = [{'id': elm.idtag, 'name': elm.name, 'code': elm.code, 'voltage_level': get_obj_ref(elm.voltage_level), } for elm in circuit.get_bus_bars()] # load elements['Load'] = [{'id': elm.idtag, 'type': 'load', 'phases': 'ps', 'name': elm.name, 'name_code': elm.code, 'bus': get_obj_ref(elm.bus), 'active': bool(elm.active), 'g': elm.G, 'b': elm.B, 'ir': elm.Ir, 'ii': elm.Ii, 'p': elm.P, 'q': elm.Q, 'shedding_cost': elm.Cost } for elm in circuit.get_loads()] element_profiles['Load'] = [{'id': elm.idtag, 'active': profile_to_json(elm.active_prof), 'p': profile_to_json(elm.P_prof), 'q': profile_to_json(elm.Q_prof), 'ir': profile_to_json(elm.Ir_prof), 'ii': profile_to_json(elm.Ii_prof), 'g': profile_to_json(elm.G_prof), 'b': profile_to_json(elm.B_prof)} for elm in circuit.get_loads()] # static generator elements['Static Generator'] = [{'id': elm.idtag, 'type': 'load', 'phases': 'ps', 'name': elm.name, 'name_code': elm.code, 'bus': get_obj_ref(elm.bus), 'active': bool(elm.active), 'p': elm.P, 'q': elm.Q, 'shedding_cost': elm.Cost } for elm in circuit.get_static_generators()] element_profiles['Static Generator'] = [{'id': elm.idtag, 'active': profile_to_json(elm.active_prof), 'p': profile_to_json(elm.P_prof), 'q': profile_to_json(elm.Q_prof)} for elm in circuit.get_static_generators()] # controllable shunt elements['Controllable shunt'] = [{'id': elm.idtag, 'type': 'load', 'phases': 'ps', 'name': elm.name, 'name_code': elm.code, 'bus': get_obj_ref(elm.bus), 'active': bool(elm.active), 'g_steps': elm.g_steps.tolist(), 'b_steps': elm.b_steps.tolist(), 'step': elm.step, 'shedding_cost': elm.Cost } for elm in circuit.get_controllable_shunts()] element_profiles['Controllable shunt'] = [{'id': elm.idtag, 'active': profile_to_json(elm.active_prof), 'step': profile_to_json(elm.step_prof), } for elm in circuit.get_controllable_shunts()] # current injection elements['Current injection'] = [{'id': elm.idtag, 'type': 'load', 'phases': 'ps', 'name': elm.name, 'name_code': elm.code, 'bus': get_obj_ref(elm.bus), 'active': bool(elm.active), 'ir': elm.Ir, 'ii': elm.Ii, 'shedding_cost': elm.Cost } for elm in circuit.get_loads()] element_profiles['Current injection'] = [{'id': elm.idtag, 'active': profile_to_json(elm.active_prof), 'ir': profile_to_json(elm.Ir_prof), 'ii': profile_to_json(elm.Ii_prof)} for elm in circuit.get_loads()] # External grid elements["External grid"] = [{'id': elm.idtag, 'type': 'external_grid', 'phases': 'ps', 'name': elm.name, 'name_code': elm.code, 'bus': get_obj_ref(elm.bus), 'active': bool(elm.active), 'Vm': elm.Vm, 'Va': elm.Va, 'P': elm.P, 'Q': elm.Q, 'Cost': elm.Cost } for elm in circuit.get_external_grids()] element_profiles["External grid"] = [{'id': elm.idtag, 'active': profile_to_json(elm.active_prof), 'Vm_prof': profile_to_json(elm.Vm_prof), 'Va_prof': profile_to_json(elm.Va_prof), 'P_prof': profile_to_json(elm.P_prof), 'Q_prof': profile_to_json(elm.Q_prof), 'Cost_prof': profile_to_json(elm.Cost_prof) } for elm in circuit.get_external_grids()] # generators elements['Generator'] = [{'id': elm.idtag, 'type': 'generator', 'phases': 'ps', 'name': elm.name, 'name_code': elm.code, 'bus': get_obj_ref(elm.bus), 'active': elm.active, 'is_controlled': elm.is_controlled, 'p': elm.P, 'pf': elm.Pf, 'vset': elm.Vset, 'snom': elm.Snom, 'qmin': elm.Qmin, 'qmax': elm.Qmax, 'q_curve': elm.q_curve.str(), 'pmin': elm.Pmin, 'pmax': elm.Pmax, 'cost2': elm.Cost2, 'cost1': elm.Cost, 'cost0': elm.Cost0, 'startup_cost': elm.startup_cost, 'shutdown_cost': elm.shutdown_cost, 'min_time_up': elm.min_time_up, 'min_time_down': elm.min_time_down, 'ramp_up': elm.ramp_up, 'ramp_down': elm.ramp_down, 'capex': elm.capex, 'opex': elm.opex, 'build_status': str(elm.build_status.value).lower(), 'technology': "", } for elm in circuit.get_generators()] element_profiles['Generator'] = [{'id': elm.idtag, 'active': profile_to_json(elm.active_prof), 'p': profile_to_json(elm.P_prof), 'v': profile_to_json(elm.Vset_prof), 'pf': profile_to_json(elm.Pf_prof)} for elm in circuit.get_generators()] # batteries elements['Battery'] = [{'id': elm.idtag, 'type': 'battery', 'phases': 'ps', 'name': elm.name, 'name_code': elm.code, 'bus': get_obj_ref(elm.bus), 'active': elm.active, 'is_controlled': elm.is_controlled, 'p': elm.P, 'vset': elm.Vset, 'pf': elm.Pf, 'snom': elm.Snom, 'enom': elm.Enom, 'qmin': elm.Qmin, 'qmax': elm.Qmax, 'pmin': elm.Pmin, 'pmax': elm.Pmax, 'cost': elm.Cost, 'cost2': elm.Cost2, 'cost1': elm.Cost, 'cost0': elm.Cost0, 'startup_cost': elm.StartupCost, 'shutdown_cost': elm.ShutdownCost, 'min_time_up': elm.MinTimeUp, 'min_time_down': elm.MinTimeDown, 'ramp_up': elm.RampUp, 'ramp_down': elm.RampDown, 'capex': elm.capex, 'opex': elm.opex, 'build_status': str(elm.build_status.value).lower(), 'charge_efficiency': elm.charge_efficiency, 'discharge_efficiency': elm.discharge_efficiency, 'min_soc': elm.min_soc, 'max_soc': elm.max_soc, 'soc_0': elm.soc_0, 'min_soc_charge': elm.min_soc_charge, 'charge_per_cycle': elm.charge_per_cycle, 'discharge_per_cycle': elm.discharge_per_cycle, 'technology': "" } for elm in circuit.get_batteries()] element_profiles['Battery'] = [{'id': elm.idtag, 'active': profile_to_json(elm.active_prof), 'p': profile_to_json(elm.P_prof), 'v': profile_to_json(elm.Vset_prof), 'pf': profile_to_json(elm.Pf_prof)} for elm in circuit.get_batteries()] # shunt elements["Shunt"] = [{'id': elm.idtag, 'type': 'load', 'phases': 'ps', 'name': elm.name, 'name_code': elm.code, 'bus': get_obj_ref(elm.bus), 'active': bool(elm.active), 'g': elm.G, 'b': elm.B, 'g0': elm.G0, 'b0': elm.B0, 'capex': elm.capex, 'opex': elm.opex, 'build_status': str(elm.build_status.value).lower(), } for elm in circuit.get_shunts()] element_profiles["Shunt"] = [{'id': elm.idtag, 'active': profile_to_json(elm.active_prof), 'g': profile_to_json(elm.G_prof), 'b': profile_to_json(elm.B_prof)} for elm in circuit.get_shunts()] # Line elements["Line"] = [{'id': elm.idtag, 'type': 'line', 'phases': 'ps', 'name': elm.name, 'name_code': elm.code, 'bus_from': get_obj_ref(elm.bus_from), 'bus_to': get_obj_ref(elm.bus_to), 'cn_from': get_obj_ref(elm.cn_from), 'cn_to': get_obj_ref(elm.cn_to), 'active': elm.active, 'rate': elm.rate, 'contingency_factor1': elm.contingency_factor, 'contingency_factor2': elm.contingency_factor, 'contingency_factor3': elm.contingency_factor, 'r': elm.R, 'x': elm.X, 'b': elm.B, 'length': elm.length, 'base_temperature': elm.temp_base, 'operational_temperature': elm.temp_oper, 'alpha': elm.alpha, 'overload_cost': elm.Cost, 'capex': elm.capex, 'opex': elm.opex, 'build_status': str(elm.build_status.value).lower(), 'locations': [] } for elm in circuit.get_lines()] element_profiles["Line"] = [{'id': elm.idtag, 'active': profile_to_json(elm.active_prof), 'rate': profile_to_json(elm.rate_prof), 'contingency_factor1': profile_to_json( elm.contingency_factor_prof)} for elm in circuit.get_lines()] # DC Line elements["DC line"] = [{'id': elm.idtag, 'type': 'line', 'phases': 'ps', 'name': elm.name, 'name_code': elm.code, 'bus_from': get_obj_ref(elm.bus_from), 'bus_to': get_obj_ref(elm.bus_to), 'cn_from': get_obj_ref(elm.cn_from), 'cn_to': get_obj_ref(elm.cn_to), 'active': elm.active, 'rate': elm.rate, 'contingency_factor1': elm.contingency_factor, 'contingency_factor2': elm.contingency_factor, 'contingency_factor3': elm.contingency_factor, 'r': elm.R, 'length': elm.length, 'base_temperature': elm.temp_base, 'operational_temperature': elm.temp_oper, 'alpha': elm.alpha, 'overload_cost': elm.Cost, 'capex': elm.capex, 'opex': elm.opex, 'build_status': str(elm.build_status.value).lower(), 'locations': [] } for elm in circuit.get_dc_lines()] element_profiles["DC line"] = [{'id': elm.idtag, 'active': profile_to_json(elm.active_prof), 'rate': profile_to_json(elm.rate_prof), 'contingency_factor1': profile_to_json( elm.contingency_factor_prof)} for elm in circuit.get_dc_lines()] # Transformer 2W control_modes = {TapModuleControl.fixed: None, TapModuleControl.Vm: "Vm", TapModuleControl.Qf: "Qf", TapModuleControl.Qt: "Qt", TapPhaseControl.fixed: None, TapPhaseControl.Pf: "Pf", TapPhaseControl.Pt: "Pt", } elements["Transformer2w"] = [{'id': elm.idtag, 'type': 'transformer', 'phases': 'ps', 'name': elm.name, 'name_code': elm.code, 'bus_from': get_obj_ref(elm.bus_from), 'bus_to': get_obj_ref(elm.bus_to), 'cn_from': get_obj_ref(elm.cn_from), 'cn_to': get_obj_ref(elm.cn_to), 'active': elm.active, 'rate': elm.rate, 'contingency_factor1': elm.contingency_factor, 'contingency_factor2': elm.contingency_factor, 'contingency_factor3': elm.contingency_factor, 'Vnomf': elm.get_from_to_nominal_voltages()[0], 'Vnomt': elm.get_from_to_nominal_voltages()[1], 'hv': elm.HV, 'lv': elm.LV, 'r': elm.R, 'x': elm.X, 'g': elm.G, 'b': elm.B, 'tap_module': elm.tap_module, 'min_tap_module': elm.tap_module_min, 'max_tap_module': elm.tap_module_max, 'id_tap_module_table': "", 'tap_angle': elm.tap_phase, 'min_tap_angle': elm.tap_phase_min, 'max_tap_angle': elm.tap_phase_max, 'id_tap_angle_table': "", 'tap_phase_control_mode': control_modes[elm.tap_phase_control_mode], 'tap_module_control_mode': control_modes[elm.tap_module_control_mode], # 'min_tap_position': self.tap_changer.min_tap, # 'max_tap_position': self.tap_changer.max_tap, # 'tap_inc_reg_down': self.tap_changer.inc_reg_down, # 'tap_inc_reg_up': self.tap_changer.inc_reg_up, # 'virtual_tap_from': tap_f, # 'virtual_tap_to': tap_t, # 'bus_to_regulated': self.bus_to_regulated, 'vset': elm.vset, 'pset': elm.Pset, 'base_temperature': elm.temp_base, 'operational_temperature': elm.temp_oper, 'alpha': elm.alpha, 'overload_cost': elm.Cost, 'capex': elm.capex, 'opex': elm.opex, 'build_status': str(elm.build_status.value).lower(), } for elm in circuit.get_transformers2w()] element_profiles["Transformer2w"] = [{'id': elm.idtag, 'active': profile_to_json(elm.active_prof), 'rate': profile_to_json(elm.rate_prof), 'contingency_factor1': profile_to_json( elm.contingency_factor_prof)} for elm in circuit.get_transformers2w()] # Windings elements["Windings"] = [{'id': elm.idtag, 'type': 'transformer', 'phases': 'ps', 'name': elm.name, 'name_code': elm.code, 'bus_from': get_obj_ref(elm.bus_from), 'bus_to': get_obj_ref(elm.bus_to), 'cn_from': get_obj_ref(elm.cn_from), 'cn_to': get_obj_ref(elm.cn_to), 'active': elm.active, 'rate': elm.rate, 'contingency_factor1': elm.contingency_factor, 'contingency_factor2': elm.contingency_factor, 'contingency_factor3': elm.contingency_factor, 'Vnomf': elm.get_from_to_nominal_voltages()[0], 'Vnomt': elm.get_from_to_nominal_voltages()[1], 'hv': elm.HV, 'lv': elm.LV, 'r': elm.R, 'x': elm.X, 'g': elm.G, 'b': elm.B, 'tap_module': elm.tap_module, 'min_tap_module': elm.tap_module_min, 'max_tap_module': elm.tap_module_max, 'id_tap_module_table': "", 'tap_angle': elm.tap_phase, 'min_tap_angle': elm.tap_phase_min, 'max_tap_angle': elm.tap_phase_max, 'id_tap_angle_table': "", 'tap_phase_control_mode': control_modes[elm.tap_phase_control_mode], 'tap_module_control_mode': control_modes[elm.tap_module_control_mode], # 'min_tap_position': self.tap_changer.min_tap, # 'max_tap_position': self.tap_changer.max_tap, # 'tap_inc_reg_down': self.tap_changer.inc_reg_down, # 'tap_inc_reg_up': self.tap_changer.inc_reg_up, # 'virtual_tap_from': tap_f, # 'virtual_tap_to': tap_t, # 'bus_to_regulated': self.bus_to_regulated, 'vset': elm.vset, 'pset': elm.Pset, 'base_temperature': elm.temp_base, 'operational_temperature': elm.temp_oper, 'alpha': elm.alpha, 'overload_cost': elm.Cost, 'capex': elm.capex, 'opex': elm.opex, 'build_status': str(elm.build_status.value).lower(), } for elm in circuit.get_windings()] element_profiles["Windings"] = [{'id': elm.idtag, 'active': profile_to_json(elm.active_prof), 'rate': profile_to_json(elm.rate_prof), 'contingency_factor1': profile_to_json( elm.contingency_factor_prof)} for elm in circuit.get_windings()] # Transformer3w elements["Transformer3w"] = [{'id': elm.idtag, 'type': 'transformer', 'phases': 'ps', 'name': elm.name, 'name_code': elm.code, 'bus_0': get_obj_ref(elm.bus0), 'bus_1': get_obj_ref(elm.bus1), 'bus_2': get_obj_ref(elm.bus2), 'bus_3': get_obj_ref(elm.bus3), 'active': elm.active, 'winding1': get_obj_ref(elm.winding1), 'winding2': get_obj_ref(elm.winding2), 'winding3': get_obj_ref(elm.winding3), } for elm in circuit.get_transformers3w()] # Series reactances elements["Series reactance"] = [{'id': elm.idtag, 'type': 'series_reactance', 'phases': 'ps', 'name': elm.name, 'name_code': elm.code, 'bus_from': get_obj_ref(elm.bus_from), 'bus_to': get_obj_ref(elm.bus_to), 'cn_from': get_obj_ref(elm.cn_from), 'cn_to': get_obj_ref(elm.cn_to), 'active': elm.active, 'rate': elm.rate, 'contingency_factor1': elm.contingency_factor, 'contingency_factor2': elm.contingency_factor, 'contingency_factor3': elm.contingency_factor, 'r': elm.R, 'x': elm.X, 'base_temperature': elm.temp_base, 'operational_temperature': elm.temp_oper, 'alpha': elm.alpha, 'overload_cost': elm.Cost, 'capex': elm.capex, 'opex': elm.opex, 'build_status': str(elm.build_status.value).lower(), } for elm in circuit.get_series_reactances()] element_profiles["Series reactance"] = [{'id': elm.idtag, 'active': profile_to_json(elm.active_prof), 'rate': profile_to_json(elm.rate_prof), 'contingency_factor1': profile_to_json( elm.contingency_factor_prof)} for elm in circuit.get_series_reactances()] # UPFC elements["UPFC"] = [{'id': elm.idtag, 'type': 'upfc', 'phases': 'ps', 'name': elm.name, 'name_code': elm.code, 'bus_from': get_obj_ref(elm.bus_from), 'bus_to': get_obj_ref(elm.bus_to), 'cn_from': get_obj_ref(elm.cn_from), 'cn_to': get_obj_ref(elm.cn_to), 'active': elm.active, 'rate': elm.rate, 'contingency_factor1': elm.contingency_factor, 'contingency_factor2': elm.contingency_factor, 'contingency_factor3': elm.contingency_factor, 'rl': 0.0, 'xl': 0.0, 'bl': 0.0, 'rs': elm.R, 'xs': elm.X, 'rsh': elm.Rsh, 'xsh': elm.Xsh, 'vsh': elm.Vsh, 'Pfset': elm.Pfset, 'Qfset': elm.Qfset, 'overload_cost': elm.Cost, 'capex': elm.capex, 'opex': elm.opex, 'build_status': str(elm.build_status.value).lower(), } for elm in circuit.get_upfc()] element_profiles["UPFC"] = [{'id': elm.idtag, 'active': profile_to_json(elm.active_prof), 'rate': profile_to_json(elm.rate_prof), 'contingency_factor1': profile_to_json( elm.contingency_factor_prof)} for elm in circuit.get_upfc()] # VSC # modes = {ConverterControlType.type_0_free: 0, # ConverterControlType.type_I_1: 1, # ConverterControlType.type_I_2: 2, # ConverterControlType.type_I_3: 3, # ConverterControlType.type_II_4: 4, # ConverterControlType.type_II_5: 5, # ConverterControlType.type_III_6: 6, # ConverterControlType.type_III_7: 7, # ConverterControlType.type_IV_I: 8, # ConverterControlType.type_IV_II: 9} elements["VSC"] = [{'id': elm.idtag, 'type': 'vsc', 'phases': 'ps', 'name': elm.name, 'name_code': elm.code, 'bus_from': get_obj_ref(elm.bus_from), 'bus_to': get_obj_ref(elm.bus_to), 'cn_from': get_obj_ref(elm.cn_from), 'cn_to': get_obj_ref(elm.cn_to), 'active': elm.active, 'rate': elm.rate, 'contingency_factor1': elm.contingency_factor, 'contingency_factor2': elm.contingency_factor, 'contingency_factor3': elm.contingency_factor, 'r': elm.R, 'x': elm.X, 'g': elm.G0sw, 'm': elm.tap_module, 'm_min': elm.tap_module_min, 'm_max': elm.tap_module_max, 'theta': elm.tap_phase, 'theta_min': elm.tap_phase_min, 'theta_max': elm.tap_phase_max, 'Beq': elm.Beq, 'Beq_min': elm.Beq_min, 'Beq_max': elm.Beq_max, 'alpha1': elm.alpha1, 'alpha2': elm.alpha2, 'alpha3': elm.alpha3, 'k': elm.k, 'kdp': elm.control1_val_droop, 'Pfset': elm.Pset, 'Qfset': elm.Qset, 'vac_set': elm.vset, 'vdc_set': elm.vset, # 'control_mode': modes[elm.control_mode], 'overload_cost': elm.Cost, 'capex': elm.capex, 'opex': elm.opex, 'build_status': str(elm.build_status.value).lower(), } for elm in circuit.get_vsc()] element_profiles["VSC"] = [{'id': elm.idtag, 'active': profile_to_json(elm.active_prof), 'rate': profile_to_json(elm.rate_prof), 'contingency_factor1': profile_to_json( elm.contingency_factor_prof)} for elm in circuit.get_vsc()] # HVDC elements["HVDC Line"] = [{'id': elm.idtag, 'type': 'hvdc', 'phases': 'ps', 'name': elm.name, 'name_code': elm.code, 'bus_from': get_obj_ref(elm.bus_from), 'bus_to': get_obj_ref(elm.bus_to), 'cn_from': get_obj_ref(elm.cn_from), 'cn_to': get_obj_ref(elm.cn_to), 'active': elm.active, 'rate': elm.rate, 'control_mode': elm.control_mode.value, 'contingency_factor1': elm.contingency_factor, 'contingency_factor2': elm.contingency_factor, 'contingency_factor3': elm.contingency_factor, 'r': elm.r, 'length': elm.length, 'loss_factor': elm.loss_factor, 'angle_droop': elm.angle_droop, 'vset_from': elm.Vset_f, 'vset_to': elm.Vset_t, 'Pset': elm.Pset, 'min_firing_angle_f': elm.min_firing_angle_f, 'max_firing_angle_f': elm.max_firing_angle_f, 'min_firing_angle_t': elm.min_firing_angle_t, 'max_firing_angle_t': elm.max_firing_angle_t, 'overload_cost': elm.Cost, 'base_temperature': 20, 'operational_temperature': 20, 'alpha': 0.00330, 'capex': elm.capex, 'opex': elm.opex, 'build_status': str(elm.build_status.value).lower(), 'locations': [] } for elm in circuit.get_hvdc()] element_profiles["HVDC Line"] = [{'id': elm.idtag, 'active': profile_to_json(elm.active_prof), 'rate': profile_to_json(elm.rate_prof), 'contingency_factor1': profile_to_json( elm.contingency_factor_prof), 'Pset': profile_to_json(elm.Pset_prof), 'vset_from': profile_to_json(elm.Vset_f_prof), 'vset_to': profile_to_json(elm.Vset_t_prof), 'overload_cost': profile_to_json(elm.Cost_prof)} for elm in circuit.get_hvdc()] # results results = dict() if simulation_drivers is not None: for driver in simulation_drivers: if driver is not None: if driver.tpe == SimulationTypes.PowerFlow_run: bus_data = dict() for i, elm in enumerate(circuit.buses): bus_data[elm.idtag] = {'vm': np.abs(driver.results.voltage[i]), 'va': np.angle(driver.results.voltage[i])} branch_data = dict() for i, elm in enumerate(circuit.get_branches(add_vsc=False, add_hvdc=False, add_switch=True)): branch_data[elm.idtag] = {'p': driver.results.Sf[i].real, 'q': driver.results.Sf[i].imag, 'losses': driver.results.losses[i].real} for i, elm in enumerate(circuit.hvdc_lines): branch_data[elm.idtag] = {'p': driver.results.Pf_hvdc[i].real, 'q': 0, 'losses': driver.results.losses_hvdc[i].real} results["power_flow"] = {'bus': bus_data, 'branch': branch_data} elif driver.tpe == SimulationTypes.PowerFlowTimeSeries_run: bus_data = dict() for i, elm in enumerate(circuit.buses): bus_data[elm.idtag] = {'vm': np.abs(driver.results.voltage[:, i]).tolist(), 'va': np.angle(driver.results.voltage[:, i]).tolist()} branch_data = dict() for i, elm in enumerate(circuit.get_branches(add_vsc=False, add_hvdc=False, add_switch=True)): branch_data[elm.idtag] = {'p': driver.results.Sf[:, i].real.tolist(), 'q': driver.results.Sf[:, i].imag.tolist(), 'losses': driver.results.losses[:, i].real.tolist()} for i, elm in enumerate(circuit.hvdc_lines): branch_data[elm.idtag] = {'p': driver.results.Pf_hvdc[:, i].real, 'q': 0, 'losses': driver.results.losses_hvdc[:, i].real} results["time_series"] = {'bus': bus_data, 'branch': branch_data} data = {'version': '3', 'review': '4', 'software': 'VeraGrid', 'units': units_dict, 'devices': elements, 'profiles': element_profiles, 'contingencies': get_contingencies_dict(circuit=circuit), 'results': results, } data_str = json.dumps(data, indent=True, cls=CustomJSONizer) # Save json to a text file text_file = open(file_path, "w") text_file.write(data_str) text_file.close() return logger