Source code for VeraGridEngine.Compilers.Gslv.conversion

# 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
from VeraGridEngine.Devices.Aggregation.area import Area
from VeraGridEngine.Devices.Aggregation.branch_group import BranchGroup
from VeraGridEngine.Devices.Aggregation.country import Country
from VeraGridEngine.Devices.Aggregation.facility import Facility
from VeraGridEngine.Devices.Aggregation.investments_group import InvestmentsGroup
from VeraGridEngine.Devices.Aggregation.market_unit import MarketUnit
from VeraGridEngine.Devices.Aggregation.modelling_authority import ModellingAuthority
from VeraGridEngine.Devices.Aggregation.municipality import Municipality
from VeraGridEngine.Devices.Aggregation.region import Region
from VeraGridEngine.Devices.Aggregation.zone import Zone
from VeraGridEngine.Devices.Associations.emission_gas import EmissionGas
from VeraGridEngine.Devices.Associations.fuel import Fuel
from VeraGridEngine.Devices.Associations.technology import Technology
from VeraGridEngine.Devices.Events.contingency_group import ContingencyGroup
from VeraGridEngine.Devices.Substation.substation import Substation
from VeraGridEngine.Devices.Substation.voltage_level import VoltageLevel
from VeraGridEngine.Compilers.Gslv.activation import pg
from VeraGridEngine.DataStructures.numerical_circuit import NumericalCircuit
from VeraGridEngine.Devices.multi_circuit import MultiCircuit
from VeraGridEngine.basic_structures import IntVec
import numpy as np
from typing import (
    Dict,
    List,
    TYPE_CHECKING,
    Tuple,
    Union,
)
from VeraGridEngine.Compilers.Gslv.Devices.areas import add_areas
from VeraGridEngine.Compilers.Gslv.Devices.zones import add_zones
from VeraGridEngine.Compilers.Gslv.Devices.countries import add_countries
from VeraGridEngine.Compilers.Gslv.Devices.municipalities import add_municipalities
from VeraGridEngine.Compilers.Gslv.Devices.regions import add_regions
from VeraGridEngine.Compilers.Gslv.Devices.branch_groups import add_branch_groups
from VeraGridEngine.Compilers.Gslv.Devices.substations import add_substations
from VeraGridEngine.Compilers.Gslv.Devices.voltage_levels import add_voltage_levels
from VeraGridEngine.Compilers.Gslv.Devices.contingencies import add_contingency_groups, add_contingencies
from VeraGridEngine.Compilers.Gslv.Devices.investments import add_investment_groups, add_investments
from VeraGridEngine.Compilers.Gslv.Devices.facilities import add_facilities
from VeraGridEngine.Compilers.Gslv.Devices.market_units import add_market_units
from VeraGridEngine.Compilers.Gslv.Devices.modelling_authorities import add_modelling_authorities
from VeraGridEngine.Compilers.Gslv.Devices.associations import add_emission_gases, add_fuels, add_technologies
from VeraGridEngine.Compilers.Gslv.Devices.buses import add_buses
from VeraGridEngine.Compilers.Gslv.Devices.loads import add_loads
from VeraGridEngine.Compilers.Gslv.Devices.static_generators import add_static_generators
from VeraGridEngine.Compilers.Gslv.Devices.shunts import add_shunts
from VeraGridEngine.Compilers.Gslv.Devices.controllable_shunts import add_controllable_shunts
from VeraGridEngine.Compilers.Gslv.Devices.generators import add_generators
from VeraGridEngine.Compilers.Gslv.Devices.batteries import add_battery_data
from VeraGridEngine.Compilers.Gslv.Devices.lines import add_lines
from VeraGridEngine.Compilers.Gslv.Devices.dc_lines import add_dc_lines
from VeraGridEngine.Compilers.Gslv.Devices.transformers import add_transformers
from VeraGridEngine.Compilers.Gslv.Devices.transformers3w import add_transformers3w
from VeraGridEngine.Compilers.Gslv.Devices.vsc import add_vscs
from VeraGridEngine.Compilers.Gslv.Devices.hvdc_line import add_hvdcs

if TYPE_CHECKING:
    from VeraGridEngine.Simulations.OPF.opf_results import OptimalPowerFlowResults


[docs] class GslvDicts: """ Hold the VeraGrid-to-GSLV object lookup dictionaries produced during conversion. """ __slots__ = ( "area_dict", "zone_dict", "substation_dict", "voltage_level_dict", "country_dict", "facility_dict", "market_unit_dict", "modelling_authorities_dict", "branch_groups_dict", "municipalities_dict", "regions_dict", "con_groups_dict", "inv_groups_dict", "technology_dict", "fuel_dict", "emission_gas_dict", ) def __init__(self) -> None: """ Initialize every conversion lookup dictionary before the conversion stages fill them. :return: None. """ self.area_dict: Dict[Area, "pg.Area"] = dict() self.zone_dict: Dict[Zone, "pg.Zone"] = dict() self.substation_dict: Dict[Substation, "pg.Substation"] = dict() self.voltage_level_dict: Dict[VoltageLevel, "pg.VoltageLevel"] = dict() self.country_dict: Dict[Country, "pg.Country"] = dict() self.facility_dict: Dict[Facility, "pg.Facility"] = dict() self.market_unit_dict: Dict[MarketUnit, "pg.MarketUnit"] = dict() self.modelling_authorities_dict: Dict[ModellingAuthority, "pg.ModellingAuthority"] = dict() self.branch_groups_dict: Dict[BranchGroup, "pg.BranchGroup"] = dict() self.municipalities_dict: Dict[Municipality, "pg.Municipality"] = dict() self.regions_dict: Dict[Region, "pg.Region"] = dict() self.con_groups_dict: Dict[ContingencyGroup, "pg.ContingencyGroup"] = dict() self.inv_groups_dict: Dict[InvestmentsGroup, "pg.InvestmentGroup"] = dict() self.technology_dict: Dict[Technology, "pg.Technology"] = dict() self.fuel_dict: Dict[Fuel, "pg.Fuel"] = dict() self.emission_gas_dict: Dict[EmissionGas, "pg.EmissionGas"] = dict()
[docs] def to_gslv(circuit: MultiCircuit, use_time_series: bool, time_indices: Union[IntVec, None] = None, override_branch_controls: bool = False, opf_results: Union[None, OptimalPowerFlowResults] = None, add_three_phase_data: bool = False) -> Tuple["pg.MultiCircuit", GslvDicts]: """ Convert VeraGrid circuit to GSLV :param circuit: MultiCircuit :param use_time_series: compile the time series from VeraGrid? otherwise just the snapshot :param time_indices: Array of time indices :param override_branch_controls: If true the branch controls are set to Fix :param opf_results: :param add_three_phase_data: Export explicit three-phase device data when possible. :return: pg.MultiCircuit instance """ dicts = GslvDicts() if time_indices is None: n_time = circuit.get_time_number() if use_time_series else 1 if n_time == 0: n_time = 1 else: n_time = len(time_indices) pg_grid = pg.MultiCircuit(name=circuit.name, nt=n_time, Sbase=circuit.Sbase, fBase=circuit.fBase, idtag=circuit.idtag) dicts.area_dict = add_areas(circuit=circuit, gslv_grid=pg_grid) dicts.zone_dict = add_zones(circuit=circuit, gslv_grid=pg_grid) dicts.substation_dict = add_substations(circuit=circuit, gslv_grid=pg_grid, n_time=n_time) dicts.voltage_level_dict = add_voltage_levels(circuit=circuit, gslv_grid=pg_grid, substations_dict=dicts.substation_dict) dicts.country_dict = add_countries(circuit=circuit, gslv_grid=pg_grid) for substation in circuit.substations: if substation.country is None: pass else: dicts.substation_dict[substation].country = dicts.country_dict[substation.country] dicts.facility_dict = add_facilities(circuit=circuit, gslv_grid=pg_grid) dicts.market_unit_dict = add_market_units(circuit=circuit) dicts.technology_dict = add_technologies(circuit=circuit, gslv_grid=pg_grid) dicts.fuel_dict = add_fuels(circuit=circuit, gslv_grid=pg_grid) dicts.emission_gas_dict = add_emission_gases(circuit=circuit, gslv_grid=pg_grid) dicts.modelling_authorities_dict = add_modelling_authorities(circuit=circuit, gslv_grid=pg_grid) dicts.branch_groups_dict = add_branch_groups(circuit=circuit, gslv_grid=pg_grid) dicts.municipalities_dict = add_municipalities(circuit=circuit, gslv_grid=pg_grid) dicts.regions_dict = add_regions(circuit=circuit, gslv_grid=pg_grid) dicts.con_groups_dict = add_contingency_groups(circuit=circuit, gslv_grid=pg_grid) add_contingencies(circuit=circuit, gslv_grid=pg_grid, n_time=n_time, groups_dict=dicts.con_groups_dict) dicts.inv_groups_dict = add_investment_groups(circuit=circuit, gslv_grid=pg_grid) add_investments(circuit=circuit, gslv_grid=pg_grid, groups_dict=dicts.inv_groups_dict) bus_dict = add_buses( circuit=circuit, gslv_grid=pg_grid, use_time_series=use_time_series, n_time=n_time, time_indices=time_indices, area_dict=dicts.area_dict, zone_dict=dicts.zone_dict, substation_dict=dicts.substation_dict, voltage_level_dict=dicts.voltage_level_dict, country_dict=dicts.country_dict, ) add_loads( circuit=circuit, gslv_grid=pg_grid, bus_dict=bus_dict, facility_dict=dicts.facility_dict, technology_dict=dicts.technology_dict, use_time_series=use_time_series, n_time=n_time, time_indices=time_indices, add_three_phase_data=add_three_phase_data, ) add_static_generators( circuit=circuit, gslv_grid=pg_grid, bus_dict=bus_dict, facility_dict=dicts.facility_dict, technology_dict=dicts.technology_dict, time_series=use_time_series, n_time=n_time, time_indices=time_indices, ) add_shunts( circuit=circuit, gslv_grid=pg_grid, bus_dict=bus_dict, facility_dict=dicts.facility_dict, technology_dict=dicts.technology_dict, time_series=use_time_series, n_time=n_time, time_indices=time_indices, add_three_phase_data=add_three_phase_data, ) add_controllable_shunts( circuit=circuit, gslv_grid=pg_grid, bus_dict=bus_dict, facility_dict=dicts.facility_dict, technology_dict=dicts.technology_dict, time_series=use_time_series, n_time=n_time, time_indices=time_indices, add_three_phase_data=add_three_phase_data, ) add_generators( circuit=circuit, gslv_grid=pg_grid, bus_dict=bus_dict, facility_dict=dicts.facility_dict, technology_dict=dicts.technology_dict, fuel_dict=dicts.fuel_dict, emission_gas_dict=dicts.emission_gas_dict, market_unit_dict=dicts.market_unit_dict, time_series=use_time_series, n_time=n_time, time_indices=time_indices, opf_results=opf_results, add_three_phase_data=add_three_phase_data, ) add_battery_data( circuit=circuit, gslv_grid=pg_grid, bus_dict=bus_dict, facility_dict=dicts.facility_dict, technology_dict=dicts.technology_dict, fuel_dict=dicts.fuel_dict, emission_gas_dict=dicts.emission_gas_dict, market_unit_dict=dicts.market_unit_dict, time_series=use_time_series, n_time=n_time, time_indices=time_indices, opf_results=opf_results, add_three_phase_data=add_three_phase_data, ) add_lines( circuit=circuit, gslv_grid=pg_grid, bus_dict=bus_dict, branch_groups_dict=dicts.branch_groups_dict, time_series=use_time_series, n_time=n_time, time_indices=time_indices, add_three_phase_data=add_three_phase_data, ) add_transformers( circuit=circuit, gslv_grid=pg_grid, bus_dict=bus_dict, branch_groups_dict=dicts.branch_groups_dict, time_series=use_time_series, n_time=n_time, time_indices=time_indices, override_controls=override_branch_controls, add_three_phase_data=add_three_phase_data, ) add_transformers3w( circuit=circuit, gslv_grid=pg_grid, bus_dict=bus_dict, time_series=use_time_series, n_time=n_time, time_indices=time_indices, override_controls=override_branch_controls ) add_vscs( circuit=circuit, gslv_grid=pg_grid, bus_dict=bus_dict, time_series=use_time_series, n_time=n_time, time_indices=time_indices ) add_dc_lines( circuit=circuit, gslv_grid=pg_grid, bus_dict=bus_dict, time_series=use_time_series, n_time=n_time, time_indices=time_indices ) add_hvdcs( circuit=circuit, gslv_grid=pg_grid, bus_dict=bus_dict, time_series=use_time_series, n_time=n_time, time_indices=time_indices ) return pg_grid, dicts
[docs] class FakeAdmittances: """ Fake admittances class needed to make the translation """ __slots__ = ( 'Ybus', 'Yf', 'Yt', ) def __init__(self) -> None: """ Build one placeholder admittance container. :return: None. """ self.Ybus = None self.Yf = None self.Yt = None
[docs] def get_snapshots_from_gslv(circuit: MultiCircuit, override_branch_controls: bool = False) -> List[NumericalCircuit]: """ :param circuit: :param override_branch_controls: :return: """ gslv_grid, _ = to_gslv(circuit, use_time_series=False, override_branch_controls=override_branch_controls) logger = pg.Logger() npa_data_lst = pg.compile(gslv_grid, logger=logger, t_idx=0).split_into_islands(logger=logger) data_lst = list() for npa_data in npa_data_lst: data = NumericalCircuit(nbus=0, nbr=0, nhvdc=0, nvsc=0, nload=0, ngen=0, nbatt=0, nshunt=0, nfluidnode=0, nfluidturbine=0, nfluidpump=0, nfluidp2x=0, nfluidpath=0, sbase=0, t_idx=0) conn = npa_data.get_connectivity_matrices() power_injections = npa_data.get_power_injections() current_injections = npa_data.get_current_injections() tpes = npa_data.get_simulation_indices(power_injections.real) adm = npa_data.get_admittance_matrices() series_adm = npa_data.get_series_admittances(conn) qmax_bus, qmin_bus = npa_data.get_reactive_power_limits() data.Vbus_ = npa_data.bus_data.Vbus.reshape(-1, 1) data.Sbus_ = power_injections.reshape(-1, 1) data.Ibus_ = current_injections.reshape(-1, 1) data.passive_branch_data.names = np.array(npa_data.passive_branch_data.names) data.passive_branch_data.virtual_tap_f = npa_data.passive_branch_data.virtual_tap_f data.passive_branch_data.virtual_tap_t = npa_data.passive_branch_data.virtual_tap_t data.passive_branch_data.original_idx = npa_data.passive_branch_data.original_idx data.bus_data.names = np.array(npa_data.bus_data.names) data.bus_data.original_idx = npa_data.bus_data.original_idx data.admittances_ = FakeAdmittances() data.admittances_.Ybus = adm.Ybus data.admittances_.Yf = adm.Yf data.admittances_.Yt = adm.Yt # The current wrapper does not expose NumericalCircuit::getLinearAdmittanceMatrices. # The compatibility layer keeps VeraGrid's expected fields populated from the available admittance matrices. data.Bbus_ = -adm.Ybus.imag data.Bf_ = -adm.Yf.imag data.Yseries_ = series_adm.Yseries data.Yshunt_ = series_adm.Yshunt data.B1_ = data.Bbus_ data.B2_ = data.Bbus_ data.Cf_ = conn.Cf data.Ct_ = conn.Ct data.bus_data.bus_types = tpes.types data.pq_ = tpes.pq data.pv_ = tpes.pv data.vd_ = tpes.vd data.pqpv_ = tpes.no_slack data.Qmax_bus_ = qmax_bus data.Qmin_bus_ = qmin_bus data_lst.append(data) return data_lst