From bde2dcd27fde0203db9048334baf420be7e761a6 Mon Sep 17 00:00:00 2001 From: benceszirbik Date: Thu, 14 Mar 2024 20:55:44 +0100 Subject: [PATCH 1/4] rename function: form_rdfid from uuid or idtag --- src/GridCalEngine/IO/cim/cgmes/base.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/GridCalEngine/IO/cim/cgmes/base.py b/src/GridCalEngine/IO/cim/cgmes/base.py index c80fb3123..68de98694 100644 --- a/src/GridCalEngine/IO/cim/cgmes/base.py +++ b/src/GridCalEngine/IO/cim/cgmes/base.py @@ -65,18 +65,19 @@ def rfid2uuid(val): return val.replace('-', '').replace('_', '') -def get_uuid(string: str) -> str: +def form_rdfid(idtag: str) -> str: """ - Converts a simple string (without hyphens or underscores) to a UUID format. + Converts a simple string, eg. idtag (without hyphens or underscores) + to a UUID format. Args: - string (str): The input string without hyphens or underscores. + idtag (str): The input idtag without hyphens or underscores. Returns: - str: The corresponding UUID string with hyphens. + str: The corresponding UUID idtag with hyphens. """ - # Add hyphens to the simple string to create a valid UUID - formatted_uuid = f"{string[:8]}-{string[8:12]}-{string[12:16]}-{string[16:20]}-{string[20:]}" + # Add hyphens to the simple idtag to create a valid UUID + formatted_uuid = f"{idtag[:8]}-{idtag[8:12]}-{idtag[12:16]}-{idtag[16:20]}-{idtag[20:]}" try: # Validate and return the UUID UUID(formatted_uuid) From afec4dde2cdbe5b4afaf09bf76e5698fbb73ef93 Mon Sep 17 00:00:00 2001 From: benceszirbik Date: Thu, 14 Mar 2024 20:57:00 +0100 Subject: [PATCH 2/4] corrected voltage level association in MultiCircuit import --- .idea/workspace.xml | 27 +-- .../IO/cim/cgmes/cgmes_to_gridcal.py | 99 ++++++++--- .../IO/cim/cgmes/gridcal_to_cgmes.py | 159 ++++++++++++++---- 3 files changed, 222 insertions(+), 63 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 2fad431a4..45d13c623 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -29,7 +29,6 @@ - @@ -1294,7 +1293,7 @@ - + 1656059954202 @@ -1639,7 +1638,7 @@ - @@ -1685,8 +1684,6 @@ - - @@ -1709,8 +1706,10 @@ + - @@ -2147,25 +2146,33 @@ file://$PROJECT_DIR$/src/GridCalEngine/Simulations/ContingencyAnalysis/contingencies_report.py - 554 + 575 file://$PROJECT_DIR$/src/GridCalEngine/Simulations/ContingencyAnalysis/contingencies_report.py - 602 + 623 file://$PROJECT_DIR$/src/GridCalEngine/IO/cim/cgmes/cgmes_to_gridcal.py - 1003 + 1065 + + + + + + + @@ -2231,7 +2238,7 @@ - + diff --git a/src/GridCalEngine/IO/cim/cgmes/cgmes_to_gridcal.py b/src/GridCalEngine/IO/cim/cgmes/cgmes_to_gridcal.py index 6da6d5033..ce4abda21 100644 --- a/src/GridCalEngine/IO/cim/cgmes/cgmes_to_gridcal.py +++ b/src/GridCalEngine/IO/cim/cgmes/cgmes_to_gridcal.py @@ -30,7 +30,7 @@ get_windings, get_regulating_control, get_pu_values_power_transformer_end, get_slack_id) -from GridCalEngine.IO.cim.cgmes.gridcal_to_cgmes import gridcal_to_cgmes +from GridCalEngine.IO.cim.cgmes.gridcal_to_cgmes import gridcal_to_cgmes #TODO move them here from GridCalEngine.data_logger import DataLogger from GridCalEngine.IO.cim.cgmes.cgmes_v2_4_15.devices.identified_object import IdentifiedObject from GridCalEngine.IO.cim.cgmes.cgmes_v2_4_15.devices.terminal import Terminal @@ -162,6 +162,24 @@ def find_connections(cgmes_elm: IdentifiedObject, return calc_nodes, cns +def find_object_by_idtag(object_list, target_idtag): #TODO mone to somewhere + """ + Finds an object with the specified idtag + in the given object_list from a Multi Circuit. + + Args: + object_list (list[MyObject]): List of MyObject instances. + target_idtag (str): The uuid to search for. + + Returns: + MyObject or None: The found object or None if not found. + """ + for obj in object_list: + if obj.idtag == target_idtag: + return obj + return None + + def get_gcdev_calculation_nodes(cgmes_model: CgmesCircuit, gc_model: MultiCircuit, v_dict: Dict[str, Tuple[float, float]], @@ -885,21 +903,12 @@ def get_gcdev_switches(cgmes_model: CgmesCircuit, def get_gcdev_substations(cgmes_model: CgmesCircuit, - gcdev_model: MultiCircuit, - calc_node_dict: Dict[str, gcdev.Bus], - cn_dict: Dict[str, gcdev.ConnectivityNode], - device_to_terminal_dict: Dict[str, List[Terminal]], - logger: DataLogger - ) -> None: + gcdev_model: MultiCircuit) -> None: """ - Convert the CGMES substations to gcdev + Convert the CGMES substations to gcdev substations :param cgmes_model: CgmesCircuit :param gcdev_model: gcdevCircuit - :param calc_node_dict: Dict[str, gcdev.Bus] - :param cn_dict: Dict[str, gcdev.ConnectivityNode] - :param device_to_terminal_dict: Dict[str, Terminal] - :param logger: """ # convert substations for device_list in [cgmes_model.Substation_list]: @@ -916,7 +925,53 @@ def get_gcdev_substations(cgmes_model: CgmesCircuit, gcdev_model.add_substation(gcdev_elm) - # convert Busbars + +def get_gcdev_voltage_levels(cgmes_model: CgmesCircuit, + gcdev_model: MultiCircuit, + logger: DataLogger) -> None: + """ + Convert the CGMES voltage levels to gcdev voltage levels + + :param cgmes_model: CgmesCircuit + :param gcdev_model: gcdevCircuit + :param logger: + """ + for cgmes_elm in cgmes_model.VoltageLevel_list: + + gcdev_elm = gcdev.VoltageLevel( + idtag=cgmes_elm.uuid, + name=cgmes_elm.name, + Vnom=cgmes_elm.BaseVoltage.nominalVoltage + ) + + subs = find_object_by_idtag( + object_list=gcdev_model.substations, + target_idtag=cgmes_elm.Substation.uuid # gcdev_elm.idtag + ) + if subs: + gcdev_elm.substation = subs + + gcdev_model.add_voltage_level(gcdev_elm) + + +def get_gcdev_busbars(cgmes_model: CgmesCircuit, + gcdev_model: MultiCircuit, + calc_node_dict: Dict[str, gcdev.Bus], + cn_dict: Dict[str, gcdev.ConnectivityNode], + device_to_terminal_dict: Dict[str, List[Terminal]], + logger: DataLogger + ) -> None: + """ + Convert the CGMES busbars to gcdev busbars + + :param cgmes_model: CgmesCircuit + :param gcdev_model: gcdevCircuit + :param calc_node_dict: Dict[str, gcdev.Bus] + :param cn_dict: Dict[str, gcdev.ConnectivityNode] + :param device_to_terminal_dict: Dict[str, Terminal] + :param logger: + """ + # convert busbars for device_list in [cgmes_model.BusbarSection_list]: for cgmes_elm in device_list: @@ -943,7 +998,7 @@ def get_gcdev_substations(cgmes_model: CgmesCircuit, name=cgmes_elm.name, idtag=cgmes_elm.uuid, code=cgmes_elm.description, - substation=substation, + # substation=substation, #TODO fix it with VoltageLevel cn=cn ) gcdev_model.add_bus_bar(gcdev_elm) @@ -993,17 +1048,19 @@ def cgmes_to_gridcal(cgmes_model: CgmesCircuit, get_gcdev_shunts(cgmes_model, gc_model, calc_node_dict, cn_dict, device_to_terminal_dict, logger, Sbase) get_gcdev_switches(cgmes_model, gc_model, calc_node_dict, cn_dict, device_to_terminal_dict, logger, Sbase) - get_gcdev_substations(cgmes_model, gc_model, calc_node_dict, cn_dict, device_to_terminal_dict, logger) + get_gcdev_substations(cgmes_model, gc_model) + get_gcdev_voltage_levels(cgmes_model, gc_model, logger) + get_gcdev_busbars(cgmes_model, gc_model, calc_node_dict, cn_dict, device_to_terminal_dict, logger) print('debug') # Export with ET - start = time.time() - serializer = CimExporter(cgmes_model) - serializer.export() - end = time.time() - print("ET export time: ", end - start, "sec") + # start = time.time() + # serializer = CimExporter(cgmes_model) + # serializer.export() + # end = time.time() + # print("ET export time: ", end - start, "sec") # Gridcal to cgmes - # exported_cgmes = gridcal_to_cgmes(gc_model, logger) + cgmes_model_export = gridcal_to_cgmes(gc_model, logger) return gc_model diff --git a/src/GridCalEngine/IO/cim/cgmes/gridcal_to_cgmes.py b/src/GridCalEngine/IO/cim/cgmes/gridcal_to_cgmes.py index af27d7a51..8cb4bd654 100644 --- a/src/GridCalEngine/IO/cim/cgmes/gridcal_to_cgmes.py +++ b/src/GridCalEngine/IO/cim/cgmes/gridcal_to_cgmes.py @@ -1,19 +1,63 @@ from GridCalEngine.Devices import MultiCircuit -from GridCalEngine.IO.cim.cgmes.base import get_new_rfid, get_uuid +from GridCalEngine.IO.cim.cgmes.base import get_new_rfid, form_rdfid from GridCalEngine.IO.cim.cgmes.cgmes_circuit import CgmesCircuit +# import GridCalEngine.IO.cim.cgmes.cgmes_v2_4_15.devices as cgmes from GridCalEngine.IO.cim.cgmes.cgmes_v2_4_15.devices.base_voltage import BaseVoltage +from GridCalEngine.IO.cim.cgmes.cgmes_v2_4_15.devices.substation import Substation +from GridCalEngine.IO.cim.cgmes.cgmes_v2_4_15.devices.voltage_level import VoltageLevel from GridCalEngine.IO.cim.cgmes.cgmes_v2_4_15.devices.connectivity_node import ConnectivityNode from GridCalEngine.IO.cim.cgmes.cgmes_v2_4_15.devices.topological_node import TopologicalNode from GridCalEngine.IO.cim.cgmes.cgmes_v2_4_15.devices.sv_voltage import SvVoltage -from GridCalEngine.IO.cim.cgmes.cgmes_v2_4_15.devices.energy_consumer import EnergyConsumer +from GridCalEngine.IO.cim.cgmes.cgmes_v2_4_15.devices.conform_load import ConformLoad +from GridCalEngine.IO.cim.cgmes.cgmes_v2_4_15.devices.load_response_characteristic import LoadResponseCharacteristic from GridCalEngine.data_logger import DataLogger from typing import Dict, List, Tuple +# region UTILS def find_terms_connections(): pass # TODO +def find_object_by_uuid(object_list, target_uuid): #TODO mone to CGMES utils + """ + Finds an object with the specified uuid + in the given object_list from a CGMES Circuit. + + Args: + object_list (list[MyObject]): List of MyObject instances. + target_uuid (str): The uuid to search for. + + Returns: + MyObject or None: The found object or None if not found. + """ + for obj in object_list: + if obj.uuid == target_uuid: + return obj + return None + + +def find_object_by_vnom(object_list: List[BaseVoltage], target_vnom): + for obj in object_list: + if obj.nominalVoltage == target_vnom: + return obj + return None + +# endregion + +# region Convert functions from MC to CC +def get_cgmes_geograpical_regions(multi_circuit_model: MultiCircuit, + cgmes_model: CgmesCircuit, + logger: DataLogger): + pass + + +def get_cgmes_subgeograpical_regions(multi_circuit_model: MultiCircuit, + cgmes_model: CgmesCircuit, + logger: DataLogger): + pass + + def get_cgmes_base_voltages(multi_circuit_model: MultiCircuit, cgmes_model: CgmesCircuit, logger: DataLogger): @@ -26,38 +70,89 @@ def get_cgmes_base_voltages(multi_circuit_model: MultiCircuit, new_rdfid = get_new_rfid() base_volt = BaseVoltage(rdfid=new_rdfid) base_volt.name = f'_BV_{int(bus.Vnom)}' + base_volt.nominalVoltage = bus.Vnom cgmes_model.BaseVoltage_list.append(base_volt) return +def get_cgmes_substations(multi_circuit_model: MultiCircuit, + cgmes_model: CgmesCircuit, + logger: DataLogger): + + for mc_elm in multi_circuit_model.substations: + + substation = Substation(rdfid=form_rdfid(mc_elm.idtag)) + substation.name = mc_elm.name + substation.Region = find_object_by_uuid( + object_list=cgmes_model.SubGeographicalRegion_list, + target_uuid=mc_elm.idtag #TODO Community.idtag! + ) + + cgmes_model.Substation_list.append(substation) + + +def get_cgmes_voltage_levels(multi_circuit_model: MultiCircuit, + cgmes_model: CgmesCircuit, + logger: DataLogger): + + for mc_elm in multi_circuit_model.voltage_levels: + + vl = VoltageLevel(rdfid=form_rdfid(mc_elm.idtag)) + vl.name = mc_elm.name + vl.BaseVoltage = find_object_by_vnom( + object_list=cgmes_model.BaseVoltage_list, + target_vnom=mc_elm.Vnom + ) + # vl.Bays = later + + if mc_elm.substation is not None: + substation: Substation = find_object_by_uuid( + object_list=cgmes_model.Substation_list, + target_uuid=mc_elm.substation.idtag + ) + if substation: + vl.Substation = substation + + # link back + if substation.VoltageLevels is None: + substation.VoltageLevels = set() + substation.VoltageLevels.add(vl) + + cgmes_model.VoltageLevel_list.append(vl) + + def get_cgmes_cn_tn_nodes(multi_circuit_model: MultiCircuit, cgmes_model: CgmesCircuit, logger: DataLogger): for bus in multi_circuit_model.buses: - # Topological Node + new_rdfid = get_new_rfid() tn = TopologicalNode(new_rdfid) tn.name = bus.name - # tn.BaseVoltage = BaseVoltage + tn.BaseVoltage = find_object_by_vnom( + object_list=cgmes_model.BaseVoltage_list, + target_vnom=bus.Vnom + ) # tn.ConnectivityNodeContainer = VoltageLevel + #TODO bus should have association for VoltageLevel first + # and the voltagelevel to the substation - cn = ConnectivityNode(rdfid=get_uuid(bus.idtag)) + cn = ConnectivityNode(rdfid=form_rdfid(bus.idtag)) + cn.name = bus.name cn.TopologicalNode = tn - # cn.ConnectivityNodeContainer = VoltageLevel + # cn.ConnectivityNodeContainer = VoltageLevel same as for tn cgmes_model.ConnectivityNode_list.append(cn) cgmes_model.TopologicalNode_list.append(tn) - - return -def get_svvoltages(v_dict: Dict[str, Tuple[float, float]], - cgmes_model: CgmesCircuit, - logger: DataLogger) -> CgmesCircuit: +def get_cgmes_svvoltages(v_dict: Dict[str, Tuple[float, float]], + cgmes_model: CgmesCircuit, + logger: DataLogger) -> CgmesCircuit: """ Creates a CgmesCircuit SvVoltage_list. @@ -68,7 +163,7 @@ def get_svvoltages(v_dict: Dict[str, Tuple[float, float]], Returns: CgmesCircuit: A CgmesCircuit object with SvVoltage_list populated. """ - # should it come from the results? + #TODO should it come from the results? for uuid, (v, angle) in v_dict.items(): # Create an SvVoltage instance for each entry in v_dict sv_voltage = SvVoltage( @@ -87,26 +182,20 @@ def get_cgmes_loads(multicircuit_model: MultiCircuit, cgmes_model: CgmesCircuit, logger: DataLogger): - cgmes_model.EnergyConsumer_list = [] # TODO find connections find_terms_connections() - for load in multicircuit_model.loads: - # TODO How do we determine what the MultiCircuit Load corresponds to in the Cgmes object? Is it EnergyConsumer, ConformLoad, NonConformLoad - # all can be ConformLoad! and LoadResponseChar - ec = EnergyConsumer() - ec.uuid = load.idtag - ec.description = load.code - ec.name = load.name - ec.p = load.P - ec.q = load.Q - cgmes_model.EnergyConsumer_list.append(ec) - # load.bus contains the Terminal connections - - -def process_mc_buses(multicircuit_model: MultiCircuit, - cgmes_model: CgmesCircuit, - logger: DataLogger): - pass + for mc_elm in multicircuit_model.loads: + # TODO How do we determine what the MultiCircuit mc_elm corresponds to in the Cgmes object? Is it EnergyConsumer, Conformmc_elm, NonConformmc_elm + # mc_elm.bus contains the Terminal connections ? + # all can be Conformmc_elm! and mc_elmResponseChar + cl = ConformLoad(rdfid=form_rdfid(mc_elm.idtag)) + cl.description = mc_elm.code + cl.name = mc_elm.name + cl.p = mc_elm.P + cl.q = mc_elm.Q + cgmes_model.ConformLoad_list.append(cl) + +# endregion def gridcal_to_cgmes(gc_model: MultiCircuit, logger: DataLogger) -> CgmesCircuit: @@ -119,15 +208,21 @@ def gridcal_to_cgmes(gc_model: MultiCircuit, logger: DataLogger) -> CgmesCircuit """ cgmes_circuit = CgmesCircuit() - + + get_cgmes_geograpical_regions(gc_model, cgmes_circuit, logger) + get_cgmes_subgeograpical_regions(gc_model, cgmes_circuit, logger) + get_cgmes_base_voltages(gc_model, cgmes_circuit, logger) + get_cgmes_substations(gc_model, cgmes_circuit, logger) + get_cgmes_voltage_levels(gc_model, cgmes_circuit, logger) + get_cgmes_cn_tn_nodes(gc_model, cgmes_circuit, logger) #TODO How to determine the device_to_terminal_dict, calc_node_dict, and cn_dict dictionaries? # What are the appropriate data types in MultiCircuit that provide the connectivity? #TODO Determine multicircuit terminals here to be able to define connections - #get_cgmes_loads(cgmes_model=cgmes_circuit, multicircuit_model=gc_model, logger=logger) # Fill up loads in cgmes_object + get_cgmes_loads(gc_model, cgmes_circuit, logger) return cgmes_circuit From df2a07f82c7fe779edddfbc3622a1ccbd82ab228 Mon Sep 17 00:00:00 2001 From: Carlos-Alegre Date: Fri, 15 Mar 2024 14:30:47 +0100 Subject: [PATCH 3/4] Small changes to structure + Docstrings --- .../OPF/NumericalMethods/ac_opf.py | 213 ++++++------ .../NumericalMethods/ac_opf_derivatives.py | 323 ++++++++++-------- .../Utils/NumericalMethods/ips.py | 42 +-- src/trunk/acopf/acopf_run.py | 16 +- 4 files changed, 322 insertions(+), 272 deletions(-) diff --git a/src/GridCalEngine/Simulations/OPF/NumericalMethods/ac_opf.py b/src/GridCalEngine/Simulations/OPF/NumericalMethods/ac_opf.py index 73a769091..9efcf8e22 100644 --- a/src/GridCalEngine/Simulations/OPF/NumericalMethods/ac_opf.py +++ b/src/GridCalEngine/Simulations/OPF/NumericalMethods/ac_opf.py @@ -171,59 +171,57 @@ def compute_analytic_structures(x, mu, lmbda, compute_jac: bool, compute_hess: b k_m, k_tau, c0, c1, c2, c_s, c_v, Sbase, rates, il, nll, ig, nig, Sg_undis, ctQ, use_bound_slacks) -> IpsFunctionReturn: """ - - :param x: - :param mu: - :param lmbda: - :param compute_jac: - :param compute_hess: - :param admittances: - :param Cg: - :param R: - :param X: - :param Sd: - :param slack: - :param from_idx: - :param to_idx: - :param f_nd_dc: - :param t_nd_dc: - :param fdc: - :param tdc: - :param ndc: - :param pq: - :param pv: - :param Pf_nondisp: - :param Pdcmax: - :param V_U: - :param V_L: - :param P_U: - :param P_L: - :param tanmax: - :param Q_U: - :param Q_L: - :param tapm_max: - :param tapm_min: - :param tapt_max: - :param tapt_min: - :param alltapm: - :param alltapt: - :param k_m: - :param k_tau: - :param c0: - :param c1: - :param c2: - :param c_s: - :param c_v: - :param Sbase: - :param rates: - :param il: - :param nll: - :param ig: - :param nig: - :param Sg_undis: - :param ctQ: - :param use_bound_slacks: - :return: + A function that computes the optimization model for a NumericalCircuit object and returns the values of the + equations and their derivatives computed analyitically + :param x: State vector + :param mu: Vector of mu multipliers + :param lmbda: Vector of lambda multipliers + :param compute_jac: Boolean that indicates if the Jacobians have to be calculated + :param compute_hess: Boolean that indicates if the Hessians have to be calculated + :param admittances: Object with all the admittance parameters stored + :param Cg: Generator connectivity matrix + :param R: Line Resistance + :param X: Line inductance + :param Sd: Load powers + :param slack: Index of slack buses + :param from_idx: Index of 'from' buses for each line + :param to_idx: Index of 'to' buses for each line + :param fdc: Index of the 'from' buses for the dispatchable DC links + :param tdc: Index of the 'to' buses for the dispatchable DC links + :param ndc: Number of dispatchable DC links + :param pq: Index of PQ buses + :param pv: Index of PV buses + :param Pdcmax: Bound for power transmission in a DC link + :param V_U: upper bound for voltage module per bus + :param V_L: lower bound for voltage module per bus + :param P_U: upper bound for active power generation per generator + :param P_L: lower bound for active power generation per generator + :param Q_U: upper bound for reactive power generation per generator + :param Q_L: lower bound for reactive power generation per generator + :param tapm_max: Upper bound for tap module per transformer + :param tapm_min: Lower bound for tap module per transformer + :param tapt_max: Upper bound for tap phase per transformer + :param tapt_min: Lower bound for tap phase per transformer + :param tanmax: Maximum value of tan(phi), where phi is the angle of the complex generation, for each generator + :param alltapm: value of all the tap modules, including the non controlled ones + :param alltapt: value of all the tap phases, including the non controlled ones + :param k_m: Index of module controlled transformers + :param k_tau: Index of phase controlles transformers + :param c0: Base cost of each generator + :param c1: Linear cost of each generator + :param c2: Quadratic cost of each generator + :param c_s: Cost of overloading each line + :param c_v: Cost of over or undervoltage for each bus + :param Sbase: Base power + :param rates: Line loading limits + :param il: Index of monitored lines + :param nll: Number of monitored lines + :param ig: Index of dispatchable generators + :param nig: Number of dispatchable generators + :param Sg_undis: undispatchable complex power + :param ctQ: Boolean that indicates if the Reactive control applies + :param use_bound_slacks: Determine if there will be bound slacks in the optimization model + :return: Object with all the model equations and derivatives stored """ M, N = admittances.Cf.shape Ng = len(ig) @@ -278,56 +276,56 @@ def evaluate_power_flow_debug(x, mu, lmbda, compute_jac, compute_hess, admittanc rates, il, nll, ig, nig, Sg_undis, ctQ, use_bound_slacks, h=1e-5) -> IpsFunctionReturn: """ - :param x: - :param mu: - :param lmbda: - :param compute_jac: - :param compute_hess: - :param admittances: - :param Cg: - :param R: - :param X: - :param Sd: - :param slack: - :param from_idx: - :param to_idx: - :param fdc: - :param tdc: - :param ndc: - :param pq: - :param pv: - :param Pdcmax: - :param V_U: - :param V_L: - :param P_U: - :param P_L: - :param tanmax: - :param Q_U: - :param Q_L: - :param tapm_max: - :param tapm_min: - :param tapt_max: - :param tapt_min: - :param alltapm: - :param alltapt: - :param k_m: - :param k_tau: - :param c0: - :param c1: - :param c2: - :param c_s: - :param c_v: - :param Sbase: - :param rates: - :param il: - :param nll: - :param ig: - :param nig: - :param Sg_undis: - :param ctQ: - :param use_bound_slacks: - :param h: - :return: + :param x: State vector + :param mu: Vector of mu multipliers + :param lmbda: Vector of lambda multipliers + :param compute_jac: Boolean that indicates if the Jacobians have to be calculated + :param compute_hess: Boolean that indicates if the Hessians have to be calculated + :param admittances: Object with all the admittance parameters stored + :param Cg: Generator connectivity matrix + :param R: Line Resistance + :param X: Line inductance + :param Sd: Load powers + :param slack: Index of slack buses + :param from_idx: Index of 'from' buses for each line + :param to_idx: Index of 'to' buses for each line + :param fdc: Index of the 'from' buses for the dispatchable DC links + :param tdc: Index of the 'to' buses for the dispatchable DC links + :param ndc: Number of dispatchable DC links + :param pq: Index of PQ buses + :param pv: Index of PV buses + :param Pdcmax: Bound for power transmission in a DC link + :param V_U: upper bound for voltage module per bus + :param V_L: lower bound for voltage module per bus + :param P_U: upper bound for active power generation per generator + :param P_L: lower bound for active power generation per generator + :param Q_U: upper bound for reactive power generation per generator + :param Q_L: lower bound for reactive power generation per generator + :param tapm_max: Upper bound for tap module per transformer + :param tapm_min: Lower bound for tap module per transformer + :param tapt_max: Upper bound for tap phase per transformer + :param tapt_min: Lower bound for tap phase per transformer + :param tanmax: Maximum value of tan(phi), where phi is the angle of the complex generation, for each generator + :param alltapm: value of all the tap modules, including the non controlled ones + :param alltapt: value of all the tap phases, including the non controlled ones + :param k_m: Index of module controlled transformers + :param k_tau: Index of phase controlles transformers + :param c0: Base cost of each generator + :param c1: Linear cost of each generator + :param c2: Quadratic cost of each generator + :param c_s: Cost of overloading each line + :param c_v: Cost of over or undervoltage for each bus + :param Sbase: Base power + :param rates: Line loading limits + :param il: Index of monitored lines + :param nll: Number of monitored lines + :param ig: Index of dispatchable generators + :param nig: Number of dispatchable generators + :param Sg_undis: undispatchable complex power + :param ctQ: Boolean that indicates if the Reactive control applies + :param use_bound_slacks: Determine if there will be bound slacks in the optimization model + :param h: Tolerance used for the autodiferentiation + :return: return the resulting error between the autodif and the analytic derivation """ mats_analytic = compute_analytic_structures(x, mu, lmbda, compute_jac, compute_hess, admittances, Cg, R, X, Sd, @@ -474,8 +472,8 @@ def ac_optimal_power_flow(nc: NumericalCircuit, :param use_autodiff: use the autodiff version of the structures :param pf_init: Initialize with power flow :param Sbus_pf: Sbus initial solution - :param voltage_pf: Voltage initl solution - :param plot_error: Plot the error? + :param voltage_pf: Voltage initial solution + :param plot_error: Plot the error evolution. Default: False :param use_bound_slacks: add voltage module and branch loading slack variables? (default true) :param logger: Logger :return: NonlinearOPFResults @@ -547,7 +545,6 @@ def ac_optimal_power_flow(nc: NumericalCircuit, nll = len(il) ngg = len(ig) - #nalldc = nc.nhvdc hvdc_nondisp = np.where(nc.hvdc_data.dispatchable == 0)[0] hvdc_disp = np.where(nc.hvdc_data.dispatchable == 1)[0] @@ -813,8 +810,8 @@ def run_nonlinear_opf(grid: MultiCircuit, :param use_autodiff: Use autodiff? :param pf_init: Initialize with a power flow? :param Sbus_pf0: Sbus initial solution - :param voltage_pf0: Voltage initl solution - :param plot_error: Plot the error? + :param voltage_pf0: Voltage initial solution + :param plot_error: Plot the error evolution :param use_bound_slacks: add voltage module and branch loading slack variables? (default true) :param logger: Logger object :return: NonlinearOPFResults diff --git a/src/GridCalEngine/Simulations/OPF/NumericalMethods/ac_opf_derivatives.py b/src/GridCalEngine/Simulations/OPF/NumericalMethods/ac_opf_derivatives.py index 8848c6a14..234a2805f 100644 --- a/src/GridCalEngine/Simulations/OPF/NumericalMethods/ac_opf_derivatives.py +++ b/src/GridCalEngine/Simulations/OPF/NumericalMethods/ac_opf_derivatives.py @@ -43,12 +43,12 @@ def x2var(x: Vec, :param nVm: number of voltage module vars :param nPg: number of generator active power vars :param nQg: number of generator reactive power vars - :param npq: - :param M: - :param ntapm: - :param ntapt: - :param ndc: - :return: + :param npq: number of PQ buses + :param M: number of monitored lines + :param ntapm: number of module controlled transformers + :param ntapt: number of phase controlled transformers + :param ndc: number of dispatchable DC links + :return: Tuple of sliced variables """ a = 0 b = nVa @@ -125,14 +125,14 @@ def var2x(Va: Vec, :param Vm: Voltage modules :param Pg: Generator active powers :param Qg: Generator reactive powers - :param sl_sf: - :param sl_st: - :param sl_vmax: - :param sl_vmin: - :param tapm: - :param tapt: - :param Pfdc: - :return: [Va, Vm, Pg, Qg, sl_sf, sl_st, sl_vmax, sl_vmin, tapm, tapt, Pfdc] + :param sl_sf: Bound slacks for the 'from' power through a line + :param sl_st: Bound slacks for the 'to' power through a line + :param sl_vmax: Bound slacks for the maximum voltage of the buses + :param sl_vmin: Bound slacks for the minimum voltage of the buses + :param tapm: Tap modules + :param tapt: Tap phases + :param Pfdc: From power of the dispatchable DC links + :return: The stacked state vector [Va, Vm, Pg, Qg, sl_sf, sl_st, sl_vmax, sl_vmin, tapm, tapt, Pfdc] """ return np.r_[Va, Vm, Pg, Qg, sl_sf, sl_st, sl_vmax, sl_vmin, tapm, tapt, Pfdc] @@ -149,16 +149,16 @@ def compute_branch_power_derivatives(alltapm: Vec, lil_matrix]: """ - :param alltapm: - :param alltapt: - :param V: - :param k_m: - :param k_tau: - :param Cf: - :param Ct: - :param R: - :param X: - :return: [dSbusdm, dSfdm, dStdm, dSbusdt, dSfdt, dStdt] + :param alltapm: Vector with all the tap module, including the non-controlled ones + :param alltapt: Vector with all the tap phases, including the non-controlled ones + :param V: Complex voltages + :param k_m: List with the index of the module controlled transformers + :param k_tau: List with the index of the phase controlled transformers + :param Cf: From connectivity matrix + :param Ct: To connectivity matrix + :param R: Line resistances + :param X: Line inductances + :return: Power first derivatives with respect to the tap variables [dSbusdm, dSfdm, dStdm, dSbusdt, dSfdt, dStdt] """ ys = 1.0 / (R + 1.0j * X + 1e-20) @@ -220,24 +220,24 @@ def compute_branch_power_second_derivatives(alltapm: Vec, lil_matrix, lil_matrix, lil_matrix, lil_matrix, lil_matrix, lil_matrix]: """ - :param alltapm: - :param alltapt: - :param vm: - :param va: - :param k_m: - :param k_tau: - :param il: - :param Cf: - :param Ct: - :param R: - :param X: - :param F: - :param T: - :param lam: - :param mu: - :param Sf: - :param St: - :return: + :param alltapm: Vector with all the tap module, including the non-controlled ones + :param alltapt: Vector with all the tap phase, including the non-controlled ones + :param vm: Voltage modules + :param va: Voltage angles + :param k_m: List with the index of the module controlled transformers + :param k_tau: List with the index of the phase controlled transformers + :param il: List with the index of the monitored lines + :param Cf: From connectivity matrix + :param Ct: To connectivity matrix + :param R: Line resistances + :param X: Line inductances + :param F: Indexes of the 'from' buses + :param T: Indexes of the 'to' buses + :param lam: Lambda multiplier + :param mu: Mu multiplier + :param Sf: From powers + :param St: To powers + :return: Power second derivatives with respect to tap variables """ ys = 1.0 / (R + 1.0j * X + 1e-20) V = vm * np.exp(1j * va) @@ -406,22 +406,22 @@ def compute_branch_power_second_derivatives(alltapm: Vec, def eval_f(x: Vec, Cg: csr_matrix, k_m: Vec, k_tau: Vec, nll: int, c0: Vec, c1: Vec, c2: Vec, c_s: Vec, c_v: Vec, ig: Vec, npq: int, ndc: int, Sbase: float, use_bound_slacks: bool) -> float: """ - - :param x: - :param Cg: - :param k_m: - :param k_tau: - :param nll: - :param c0: - :param c1: - :param c2: - :param c_s: - :param c_v: - :param ig: - :param npq: - :param ndc: - :param Sbase: - :return: + Calculates the value of the objective function at the current state (given by x) + :param x: State vector + :param Cg: Generation connectivity matrix + :param k_m: List with the index of the module controlled transformers + :param k_tau: List with the index of the phase controlled transformers + :param nll: Number of monitored lines + :param c0: Base cost of generators + :param c1: Linear cost of generators + :param c2: Quadratic cost of generators + :param c_s: Cost of overloading a line + :param c_v: Cost of over or undervoltages + :param ig: Dispatchable generators + :param npq: Number of pq buses + :param ndc: Number of dispatchable DC links + :param Sbase: Base power (per unit reference) + :return: Scalar value: Cost of operation (objective function) """ N, _ = Cg.shape # Check Ng = len(ig) @@ -442,25 +442,29 @@ def eval_g(x: Vec, Ybus: csr_matrix, Yf: csr_matrix, Cg: csr_matrix, Sd: CxVec, pv: Vec, f_nd_dc: Vec, t_nd_dc: Vec, fdc: Vec, tdc: Vec, Pf_nondisp: Vec, k_m: Vec, k_tau: Vec, Vm_max: Vec, Sg_undis: CxVec, slack: Vec, use_bound_slacks: bool) -> Tuple[Vec, Vec]: """ - - :param x: - :param Ybus: - :param Yf: - :param Cg: - :param Sd: + Calculates the equality constraints at the current state (given by x) + :param x: State vector + :param Ybus: Bus admittance matrix + :param Yf: From admittance matrix + :param Cg: Generators connectivity matrix + :param Sd: Loads vector :param ig: indices of dispatchable gens :param nig: indices of non dispatchable gens - :param nll: - :param npq: - :param pv: - :param fdc: - :param tdc: - :param k_m: - :param k_tau: - :param Vm_max: + :param nll: Number of monitored lines + :param npq: Number of pq buses + :param pv: Index of PV buses + :param f_nd_dc: Index of 'from' buses of non dispatchable DC links + :param t_nd_dc: Index of 'to' buses of non dispatchable DC links + :param fdc: Index of 'from' buses of dispatchable DC links + :param tdc: Index of 'to' buses of dispatchable DC links + :param k_m: Index of module controlled transformers + :param k_tau: Index of phase controlled transformers + :param Vm_max: Maximum bound for voltage :param Sg_undis: undispatchable complex power - :param slack: - :return: + :param slack: Index of slack buses + :param use_bound_slacks: Determine if there will be bound slacks in the optimization model + :return: Vector with the value of each equality constraint G = [g1(x), ... gn(x)] s.t. gi(x) = 0. It also + returns the value of the power injections S """ M, N = Yf.shape Ng = len(ig) @@ -495,33 +499,35 @@ def eval_h(x: Vec, Yf: csr_matrix, Yt: csr_matrix, from_idx: Vec, to_idx: Vec, p tapm_min: Vec, tapt_max: Vec, tapt_min: Vec, Pdcmax: Vec, rates: Vec, il: Vec, ig: Vec, tanmax: Vec, ctQ: ReactivePowerControlMode, use_bound_slacks: bool) -> Tuple[Vec, CxVec, CxVec]: """ - - :param x: - :param Yf: - :param Yt: - :param from_idx: - :param to_idx: - :param pq: - :param k_m: - :param k_tau: - :param Vm_max: - :param Vm_min: - :param Pg_max: - :param Pg_min: - :param Qg_max: - :param Qg_min: - :param tapm_max: - :param tapm_min: - :param tapt_max: - :param tapt_min: - :param Pdcmax: - :param rates: - :param il: relevant lines to check rating - :param ig: - :param tanmax: - :param ctQ: - :return: [hval, Sftot, Sttot] + Calculates the inequality constraints at the current state (given by x) + :param x: State vector + :param Yf: From admittance matrix + :param Yt: To admittance matrix + :param from_idx: Vector with the indices of the 'from' buses for each line + :param to_idx: Vector with the indices of the 'from' buses for each line + :param pq: Index of PQ buses + :param k_m: Index of module controlled transformers + :param k_tau: Index of phase controlles transformers + :param Vm_max: upper bound for voltage module per bus + :param vm_min: lower bound for voltage module per bus + :param pg_max: upper bound for active power generation per generator + :param pg_min: lower bound for active power generation per generator + :param qg_max: upper bound for reactive power generation per generator + :param qg_min: lower bound for reactive power generation per generator + :param tapm_max: Upper bound for tap module per transformer + :param tapm_min: Lower bound for tap module per transformer + :param tapt_max: Upper bound for tap phase per transformer + :param tapt_min: Lower bound for tap phase per transformer + :param Pdcmax: Bound for power transmission in a DC link + :param rates: Rates for branch power at each line + :param il: Index of monitored lines + :param ig: Index of dispatchable generators + :param tanmax: Maximum value of tan(phi), where phi is the angle of the complex generation, for each generator + :param ctQ: Boolean indicating if limits to reactive power generation realted to active generation apply + :return: Vector with the value of each inequality constraint H = [h1(x), ... hn(x)] s.t. hi(x) <= 0 and the + calculated from and to branch powers. """ + M, N = Yf.shape Ng = len(ig) ntapm = len(k_m) @@ -596,41 +602,42 @@ def jacobians_and_hessians(x: Vec, c1: Vec, c2: Vec, c_s: Vec, c_v: Vec, Cg: csr compute_hess: bool) -> Tuple[Vec, csc, csc, csc, csc, csc]: """ - - :param x: - :param c1: - :param c2: - :param c_s: - :param c_v: - :param Cg: - :param Cf: - :param Ct: - :param Yf: - :param Yt: - :param Ybus: - :param Sbase: - :param il: relevant lines to check rating - :param ig: - :param slack: - :param pq: - :param pv: - :param tanmax: - :param alltapm: - :param alltapt: - :param fdc: - :param tdc: - :param k_m: - :param k_tau: - :param mu: - :param lmbda: - :param R: - :param X: - :param F: - :param T: - :param ctQ: - :param compute_jac: - :param compute_hess: - :return: + Calculates the jacobians and hessians of the objective function and the equality and inequality constraints + at the current state given by x + :param x: State vector + :param c1: Linear cost of each generator + :param c2: Quadratic cost of each generator + :param c_s: Cost of overloading each line + :param c_v: Cost of over or undervoltage for each bus + :param Cg: Generator connectivity matrix + :param Cf: From connectivity matrix + :param Ct:To connectivity matrix + :param Yf: From admittance matrix + :param Yt: To admittance matrix + :param Ybus: Bus admittance matrix + :param Sbase: Base power + :param il: Index of monitored lines + :param ig: Index of dispatchable generatora + :param slack: Index of slack buses + :param pq: Index of PQ buses + :param pv: Index of PV buses + :param tanmax: Maximum value of tan(phi), where phi is the angle of the complex generation, for each generator + :param alltapm: value of all the tap modules, including the non controlled ones + :param alltapt: value of all the tap phases, including the non controlled ones + :param fdc: Index of the 'from' buses for the dispatchable DC links + :param tdc: Index of the 'to' buses for the dispatchable DC links + :param k_m: Index of the module controlled transformers + :param k_tau: Index of the phase controlled transformers + :param mu: Vector of mu multipliers + :param lmbda: Vector of lambda multipliers + :param R: Line Resistance + :param X: Line inductance + :param F: Index of the 'form' bus for each line + :param T: Index of the 'to' bus for each line + :param ctQ: Boolean that indicates if the Reactive control applies + :param compute_jac: Boolean that indicates if the Jacobians have to be calculated + :param compute_hess: Boolean that indicates if the Hessians have to be calculated + :return: Jacobians and hessians matrices for the objective function and the equality and inequality constraints """ Mm, N = Yf.shape M = len(il) @@ -756,6 +763,52 @@ def jacobians_and_hessians(x: Vec, c1: Vec, c2: Vec, c_s: Vec, c_v: Vec, Cg: csr # INEQUALITY CONSTRAINTS GRAD ---------------------------------------------------------------------------------- + """ + The following comments illustrate the shapes of the equality constraints gradients: + + Hx = + NV + +---------+ + | HSf | M + +---------+ + | HSt | M + +---------+ + | Hvu | N + +---------+ + | Hpu | Ng + +---------+ + | Hqu | Ng + +---------+ + | Hvl | N + +---------+ + | Hpl | Ng + +---------+ + | Hql | Ng + +---------+ + | Hslsf | M + +---------+ + | Hslst | M + +---------+ + | Hslvmax | npq + +---------+ + | Hslvmin | npq + +---------+ + | Htapmu | ntapm + +---------+ + | Htapml | ntapm + +---------+ + | Htaptu | ntapt + +---------+ + | Htaptl | ntapt + +---------+ + | Hqmax | Ng (if ctQ==True), 0 else + +---------+ + | Hdcu | ndc + +---------+ + | Hdcl | ndc + +---------+ + """ + Vfmat = diags(Cf[il, :] @ V) Vtmat = diags(Ct[il, :] @ V) diff --git a/src/GridCalEngine/Utils/NumericalMethods/ips.py b/src/GridCalEngine/Utils/NumericalMethods/ips.py index b05d3b3e6..5123ca836 100644 --- a/src/GridCalEngine/Utils/NumericalMethods/ips.py +++ b/src/GridCalEngine/Utils/NumericalMethods/ips.py @@ -38,7 +38,7 @@ def step_calculation(v: Vec, dv: Vec, tau: float = 0.99995): :param v: Array of multipliers or slack variables :param dv: Variation calculated in the Newton step :param tau: Factor to be not exactly 1 - :return: + :return: step size value for the given multipliers """ k = np.flatnonzero(dv < 0.0) if len(k) > 0: @@ -85,8 +85,8 @@ def calc_error(dx, dz, dmu, dlmbda): def max_abs(x: Vec): """ Compute max abs efficiently - :param x: - :return: + :param x: State vector + :return: Inf-norm of the state vector """ max_val = 0.0 for x_val in x: @@ -100,11 +100,11 @@ def max_abs(x: Vec): def calc_feascond(g: Vec, h: Vec, x: Vec, z: Vec): """ Calculate the feasible conditions - :param g: - :param h: - :param x: - :param z: - :return: + :param g: Equality values + :param h: Inequality values + :param x: State vector + :param z: Vector of z slack variables + :return: Feasibility condition value """ return max(max_abs(g), np.max(h)) / (1.0 + max(max_abs(x), max_abs(z))) @@ -112,20 +112,20 @@ def calc_feascond(g: Vec, h: Vec, x: Vec, z: Vec): def calc_gradcond(lx: Vec, lam: Vec, mu: Vec): """ calculate the gradient conditions - :param lx: - :param lam: - :param mu: - :return: + :param lx: Gradient of the lagrangian + :param lam: Vector of lambda multipliers + :param mu: Vector of mu multipliers + :return: Gradient condition value """ return max_abs(lx) / (1 + max(max_abs(lam), max_abs(mu))) def calc_ccond(mu: Vec, z: Vec, x: Vec): """ - :param mu: - :param z: - :param x: - :return: + :param mu: Vector of mu mutipliers + :param z: Vector of z slack variables + :param x: State vector + :return: Vector of ccond """ return (mu @ z) / (1.0 + max_abs(x)) @@ -133,9 +133,9 @@ def calc_ccond(mu: Vec, z: Vec, x: Vec): def calc_ocond(f: float, f_prev: float): """ - :param f: - :param f_prev: - :return: + :param f: Value of objective funciton + :param f_prev: Previous value of objective function + :return: Variation of the objective function """ return abs(f - f_prev) / (1.0 + abs(f_prev)) @@ -283,7 +283,7 @@ def interior_point_solver(x0: Vec, :param func: A function pointer called with (x, mu, lmbda, *args) that returns (f, G, H, fx, Gx, Hx, fxx, Gxx, Hxx) :param arg: Tuple of arguments to call func: func(x, mu, lmbda, *arg) :param max_iter: Maximum number of iterations - :param tol: Expected tolerance + :param tol: Convergence tolerance :param pf_init: Use the power flow solution as initial values :param trust: Amount of trust in the initial Newton derivative length estimation :param verbose: 0 to 3 (the larger, the more verbose) @@ -302,7 +302,7 @@ def interior_point_solver(x0: Vec, rho_upper = 1.0 + nabla e = np.ones(n_ineq) - # Our init + # Our init, which computes the multipliers as a solution of the KKT conditions if pf_init: z0 = 1.0 z = z0 * np.ones(n_ineq) diff --git a/src/trunk/acopf/acopf_run.py b/src/trunk/acopf/acopf_run.py index eb5fb6b7b..9be84570e 100644 --- a/src/trunk/acopf/acopf_run.py +++ b/src/trunk/acopf/acopf_run.py @@ -130,7 +130,7 @@ def linn5bus_example(): grid.add_load(bus5, gce.Load('load 5', P=50, Q=20)) # add Lines connecting the buses - #grid.add_line(gce.Line(bus1, bus2, name='line 1-2', r=0.05, x=0.11, b=0.02, rate=1000)) + grid.add_line(gce.Line(bus1, bus2, name='line 1-2', r=0.05, x=0.11, b=0.02, rate=1000)) grid.add_line(gce.Line(bus1, bus3, name='line 1-3', r=0.05, x=0.11, b=0.02, rate=1000)) grid.add_line(gce.Line(bus1, bus5, name='line 1-5', r=0.03, x=0.08, b=0.02, rate=1000)) grid.add_line(gce.Line(bus2, bus3, name='line 2-3', r=0.04, x=0.09, b=0.02, rate=1000)) @@ -142,10 +142,11 @@ def linn5bus_example(): tap_module=0.95, tap_phase=-0.02, r=0.05, x=0.11, tap_phase_max=0.5, tap_module_max=1.1, tap_phase_min=-0.5, tap_module_min=0.9, rate=1000) - grid.add_transformer2w(tr1) - + #grid.add_transformer2w(tr1) + opf_options = gce.OptimalPowerFlowOptions(solver=gce.SolverType.NONLINEAR_OPF, verbose=1, ips_tolerance=1e-8, + ips_iterations=25) pf_options = gce.PowerFlowOptions(solver_type=gce.SolverType.NR, verbose=1) - run_nonlinear_opf(grid=grid, pf_options=pf_options, plot_error=True) + run_nonlinear_opf(grid=grid, pf_options=pf_options, opf_options=opf_options, plot_error=True) def two_grids_of_3bus(): @@ -291,7 +292,6 @@ def case_pegase89(): file_path = os.path.join(new_directory, 'Grids_and_profiles', 'grids', 'case89pegase.m') grid = gce.FileOpen(file_path).open() - #nc = compile_numerical_circuit_at(grid) opf_options = gce.OptimalPowerFlowOptions(solver=gce.SolverType.NONLINEAR_OPF, verbose=1, ips_iterations=100, ips_tolerance=1e-7) pf_options = gce.PowerFlowOptions(solver_type=gce.SolverType.NR, verbose=1) @@ -368,13 +368,13 @@ def casehvdc(): if __name__ == '__main__': # example_3bus_acopf() # case_3bus() - # linn5bus_example() - two_grids_of_3bus() + linn5bus_example() + # two_grids_of_3bus() # case9() # case14() # case_gb() # case6ww() - # case_pegase89() + #case_pegase89() # case300() # casepegase13k() # casehvdc() From c421d722db8c3ea73ddf45f07809c80b4f0473c4 Mon Sep 17 00:00:00 2001 From: santi Date: Sat, 16 Mar 2024 12:00:15 +0000 Subject: [PATCH 4/4] Added system scaler --- .idea/workspace.xml | 188 +- src/GridCal/Gui/LoadDesigner/icons_rc.py | 2 +- src/GridCal/Gui/LoadDesigner/load_designer.py | 17 +- .../{gui.py => load_designer_ui.py} | 4 +- .../{gui.ui => load_designer_ui.ui} | 0 .../Gui/LoadDesigner/update_gui_file.py | 4 +- src/GridCal/Gui/Main/ConsoleLog.py | 2 +- src/GridCal/Gui/Main/MainWindow.py | 244 +- src/GridCal/Gui/Main/MainWindow.ui | 13 + .../Gui/Main/SubClasses/Model/objects.py | 10 + src/GridCal/Gui/Main/icons.qrc | 1 + src/GridCal/Gui/Main/icons/scale.svg | 59 + src/GridCal/Gui/Main/icons_rc.py | 52527 ++++++++-------- src/GridCal/Gui/SystemScaler/__init__.py | 0 src/GridCal/Gui/SystemScaler/icons.qrc | 14 + .../Gui/SystemScaler/icons/auto-link-rnd.svg | 99 + .../Gui/SystemScaler/icons/auto-link.svg | 73 + src/GridCal/Gui/SystemScaler/icons/copy.svg | 58 + .../Gui/SystemScaler/icons/copy2down.svg | 72 + src/GridCal/Gui/SystemScaler/icons/delete.svg | 58 + src/GridCal/Gui/SystemScaler/icons/gear.svg | 58 + .../SystemScaler/icons/import_profiles.svg | 72 + .../Gui/SystemScaler/icons/link-to-all.svg | 103 + .../SystemScaler/icons/link-to-selection.svg | 103 + .../Gui/SystemScaler/icons/multiply.svg | 69 + src/GridCal/Gui/SystemScaler/icons_rc.py | 1488 + src/GridCal/Gui/SystemScaler/system_scaler.py | 286 + .../Gui/SystemScaler/system_scaler_ui.py | 106 + .../Gui/SystemScaler/system_scaler_ui.ui | 148 + .../Gui/SystemScaler/update_gui_file.py | 9 + src/GridCalEngine/Devices/multi_circuit.py | 58 +- src/GridCalEngine/Devices/profile.py | 25 +- 32 files changed, 29728 insertions(+), 26242 deletions(-) rename src/GridCal/Gui/LoadDesigner/{gui.py => load_designer_ui.py} (99%) rename src/GridCal/Gui/LoadDesigner/{gui.ui => load_designer_ui.ui} (100%) create mode 100644 src/GridCal/Gui/Main/icons/scale.svg create mode 100644 src/GridCal/Gui/SystemScaler/__init__.py create mode 100644 src/GridCal/Gui/SystemScaler/icons.qrc create mode 100644 src/GridCal/Gui/SystemScaler/icons/auto-link-rnd.svg create mode 100644 src/GridCal/Gui/SystemScaler/icons/auto-link.svg create mode 100644 src/GridCal/Gui/SystemScaler/icons/copy.svg create mode 100644 src/GridCal/Gui/SystemScaler/icons/copy2down.svg create mode 100644 src/GridCal/Gui/SystemScaler/icons/delete.svg create mode 100644 src/GridCal/Gui/SystemScaler/icons/gear.svg create mode 100644 src/GridCal/Gui/SystemScaler/icons/import_profiles.svg create mode 100644 src/GridCal/Gui/SystemScaler/icons/link-to-all.svg create mode 100644 src/GridCal/Gui/SystemScaler/icons/link-to-selection.svg create mode 100644 src/GridCal/Gui/SystemScaler/icons/multiply.svg create mode 100644 src/GridCal/Gui/SystemScaler/icons_rc.py create mode 100644 src/GridCal/Gui/SystemScaler/system_scaler.py create mode 100644 src/GridCal/Gui/SystemScaler/system_scaler_ui.py create mode 100644 src/GridCal/Gui/SystemScaler/system_scaler_ui.ui create mode 100644 src/GridCal/Gui/SystemScaler/update_gui_file.py diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 08afdc1b2..6412b8239 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -28,9 +28,39 @@