diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 18cdd7287..ff7403954 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -28,8 +28,14 @@
-
-
+
+
+
+
+
+
+
+
@@ -70,7 +76,7 @@
@@ -127,93 +133,93 @@
- {
- "keyToString": {
- "ASKED_ADD_EXTERNAL_FILES": "true",
- "Git.Branch.Popup.ShowAllRemotes": "true",
- "MATLAB_INTERPRETER": "/usr/local/MATLAB/R2018a/bin/matlab",
- "Python tests.Nosetests for test_power_flow.test_zip.executor": "Debug",
- "Python tests.Nosetests for test_topology_processor.test_topology_rts.executor": "Debug",
- "Python tests.Nosetests for tests.test_ac_opf.executor": "Run",
- "Python tests.Nosetests for tests.test_ac_opf.test_pegase89.executor": "Debug",
- "Python tests.Nosetests for tests.test_hydro.executor": "Run",
- "Python tests.Nosetests for tests.test_latin_hypercube.test_lhs.executor": "Run",
- "Python tests.Nosetests for tests.test_opf_time_series.test_opf_ts.executor": "Run",
- "Python tests.Nosetests for tests.test_topology_processor.executor": "Run",
- "Python tests.Nosetests for tests.test_topology_processor.test_topology_rts.executor": "Run",
- "Python tests.Nosetests in admittance_matrix_test.py.executor": "Run",
- "Python tests.Nosetests in deep_copy_test.py.executor": "Run",
- "Python tests.Nosetests in test_topology_processor.py.executor": "Run",
- "Python tests.Nosetests in tests.executor": "Run",
- "Python tests.pytest for src.tests.test_cgmes_ieeee.executor": "Run",
- "Python tests.pytest for src.tests.test_cgmes_ieeee.test_ieee_grids.executor": "Debug",
- "Python tests.pytest for src.tests.test_cgmes_to_gridcal_ac_transformers.test_ac_transformers3w.executor": "Debug",
- "Python tests.pytest for src.tests.test_load_all_grids.test_all_grids.executor": "Run",
- "Python tests.pytest for src.tests.test_load_save_load.test_load_save_load.executor": "Run",
- "Python tests.pytest for src.tests.test_power_flow.executor": "Run",
- "Python tests.pytest for src.tests.test_power_flow.test_controllable_shunt.executor": "Run",
- "Python tests.pytest for src.tests.test_tutorials.test_define_grid_from_scratch_with_profiles.executor": "Debug",
- "Python tests.pytest for test_cgmes_ieeee.test_ieee_grids.executor": "Run",
- "Python tests.pytest for test_demo_5_node.test_demo_5_node.executor": "Run",
- "Python tests.pytest for test_derivatives.test_bus_derivatives.executor": "Run",
- "Python tests.pytest for test_load_save_load.test_load_save_load2.executor": "Run",
- "Python tests.pytest for test_nodal_capacity.test_linear_vs_nonlinear_ncap.executor": "Run",
- "Python tests.pytest for test_power_flow.test_fubm.executor": "Run",
- "Python tests.pytest for test_power_flow.test_power_flow_control_with_pst.executor": "Debug",
- "Python tests.pytest for test_power_flow.test_power_flow_control_with_pst_pt.executor": "Run",
- "Python tests.pytest for test_power_flow.test_qf_control_with_ltc.executor": "Run",
- "Python tests.pytest for test_power_flow.test_qt_control_with_ltc.executor": "Debug",
- "Python tests.pytest for test_power_flow.test_voltage_control_with_ltc.executor": "Run",
- "Python tests.pytest for test_power_flow.test_voltage_local_control_with_generation.executor": "Debug",
- "Python tests.pytest for test_power_flow.test_voltage_remote_control_with_generation.executor": "Debug",
- "Python tests.pytest for test_set_snapshot.test_set_snapshot.executor": "Run",
- "Python tests.pytest for test_sparse2.test_mat_mat_mult.executor": "Run",
- "Python tests.pytest for test_topology_processor.test_topology_4_nodes_A.executor": "Debug",
- "Python tests.pytest for test_topology_processor.test_topology_4_nodes_B.executor": "Debug",
- "Python tests.pytest for test_transformer_controls.test_v_control_true.executor": "Debug",
- "Python tests.pytest in test_cgmes_ieeee.py.executor": "Run",
- "Python tests.pytest in test_deep_copy.py.executor": "Run",
- "Python tests.pytest in test_load_save_load.py.executor": "Debug",
- "Python tests.pytest in test_power_flow.py.executor": "Run",
- "Python tests.pytest in test_profiles.py.executor": "Run",
- "Python tests.pytest in test_topology_processor.py.executor": "Run",
- "Python tests.pytest in test_transformer_controls.py.executor": "Run",
- "Python tests.pytest in tests.executor": "Run",
- "Python.AnalysisDialogue.executor": "Run",
- "Python.ExecuteGridCal.executor": "Run",
- "Python.GridCalMain.executor": "Run",
- "Python.auto_document_models.executor": "Run",
- "Python.cgmes_rdfs_graph.executor": "Run",
- "Python.crazy_lambda_shadowing.executor": "Run",
- "Python.download_stats.executor": "Run",
- "Python.fubm_example.executor": "Run",
- "Python.generate_ssl_key.executor": "Run",
- "Python.line_arrow.executor": "Run",
- "Python.line_arrow_2.executor": "Run",
- "Python.line_arrow_3.executor": "Run",
- "Python.make.executor": "Run",
- "Python.new_circuit_objects.executor": "Run",
- "Python.profile_dialogue.executor": "Run",
- "Python.pymoo_example.executor": "Debug",
- "Python.raw_imp_exp_test.executor": "Run",
- "Python.run.executor": "Run",
- "Python.update_gui_file.executor": "Run",
- "Python.upload_to_pypi.executor": "Run",
- "RunOnceActivity.OpenProjectViewOnStart": "true",
- "RunOnceActivity.ShowReadmeOnStart": "true",
- "WebServerToolWindowFactoryState": "false",
- "git-widget-placeholder": "199__finalize__cgmes__import",
- "last_opened_file_path": "/home/santi/Documentos/Git/GitHub/GridCal/src/GridCalEngine/Simulations/PowerFlow/NumericalMethods",
- "node.js.detected.package.eslint": "true",
- "node.js.selected.package.eslint": "(autodetect)",
- "node.js.selected.package.tslint": "(autodetect)",
- "nodejs_package_manager_path": "npm",
- "run.code.analysis.last.selected.profile": "aDefault",
- "settings.editor.selected.configurable": "com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable",
- "two.files.diff.last.used.file": "C:/WorkProjects/PycharmProjects/GridCal/src/trunk/cgmes_py_generator/cgmes_v2_4_15/cgmes_enums.py",
- "vue.rearranger.settings.migration": "true"
+
+}]]>
@@ -548,7 +554,7 @@
-
+
@@ -557,12 +563,12 @@
-
+
-
+
@@ -708,19 +714,19 @@
+
-
+
+
-
-
@@ -1497,7 +1503,8 @@
-
+
+
1656059954202
@@ -1842,7 +1849,7 @@
1698766404661
-
+
@@ -1889,8 +1896,6 @@
-
-
@@ -1914,7 +1919,9 @@
-
+
+
+
@@ -2293,9 +2300,9 @@
- file://$PROJECT_DIR$/src/GridCal/Gui/Diagrams/SchematicWidget/Branches/line_editor.py
- 210
-
+ file://$PROJECT_DIR$/src/GridCalEngine/Devices/Branches/line.py
+ 287
+
file://$PROJECT_DIR$/src/GridCalEngine/Devices/Branches/sequence_line_type.py
@@ -2342,51 +2349,36 @@
81
-
- file://$PROJECT_DIR$/src/GridCal/Gui/Diagrams/SchematicWidget/schematic_widget.py
- 3380
-
-
-
- file://$PROJECT_DIR$/src/GridCal/Gui/Main/SubClasses/io.py
- 157
-
-
-
- file://$PROJECT_DIR$/src/GridCal/Gui/Diagrams/SchematicWidget/schematic_widget.py
- 971
-
-
file://$PROJECT_DIR$/src/trunk/acdc_pf/ieee9_Kriti.py
81
- file://$PROJECT_DIR$/src/GridCal/Gui/Main/update_gui_file.py
- 19
-
+ file://$PROJECT_DIR$/src/GridCalEngine/IO/gridcal/pack_unpack.py
+ 1207
+
- file://$PROJECT_DIR$/src/GridCal/Gui/Main/SubClasses/Model/time_events.py
- 483
-
+ file://$PROJECT_DIR$/src/GridCalEngine/IO/gridcal/pack_unpack.py
+ 1221
+
- file://$PROJECT_DIR$/src/GridCal/Gui/Main/SubClasses/Model/time_events.py
- 480
-
+ file://$PROJECT_DIR$/src/GridCalEngine/IO/gridcal/pack_unpack.py
+ 1235
+
-
- file://$PROJECT_DIR$/src/GridCalEngine/Devices/multi_circuit.py
- 765
-
+ file://$PROJECT_DIR$/src/GridCal/Gui/Main/update_gui_file.py
+ 19
+
- file://$PROJECT_DIR$/src/GridCal/Gui/Main/SubClasses/Settings/configuration.py
- 440
-
+
+ file://$PROJECT_DIR$/src/GridCalEngine/Devices/Parents/editable_device.py
+ 736
+
file://$PROJECT_DIR$/src/GridCalEngine/DataStructures/numerical_circuit.py
@@ -2419,39 +2411,33 @@
-
- file://$PROJECT_DIR$/src/GridCalEngine/Devices/Parents/branch_parent.py
- 280
-
-
-
-
- file://$PROJECT_DIR$/src/GridCalEngine/Devices/Parents/branch_parent.py
- 284
-
+
+ file://$PROJECT_DIR$/src/GridCalEngine/IO/gridcal/pack_unpack.py
+ 1126
+
-
- file://$PROJECT_DIR$/src/GridCalEngine/Devices/Parents/branch_parent.py
- 287
-
+
+ file://$PROJECT_DIR$/src/GridCalEngine/IO/gridcal/pack_unpack.py
+ 1130
+
-
-
+
-
+
-
+
+
-
+
@@ -2463,8 +2449,8 @@
-
+
@@ -2476,8 +2462,8 @@
-
+
@@ -2487,14 +2473,14 @@
-
-
-
+
+
+
-
+
@@ -2523,8 +2509,8 @@
-
+
@@ -2565,8 +2551,8 @@
-
+
@@ -2584,8 +2570,8 @@
-
+
@@ -2857,7 +2843,7 @@
-
+
@@ -2875,13 +2861,13 @@
-
+
-
+
diff --git a/src/GridCal/Gui/Main/SubClasses/io.py b/src/GridCal/Gui/Main/SubClasses/io.py
index 924d529c1..479cda319 100644
--- a/src/GridCal/Gui/Main/SubClasses/io.py
+++ b/src/GridCal/Gui/Main/SubClasses/io.py
@@ -23,7 +23,7 @@
import GridCal.Gui.gui_functions as gf
import GridCal.Session.export_results_driver as exprtdrv
import GridCal.Session.file_handler as filedrv
-from GridCalEngine.Devices.multi_circuit import MultiCircuit
+
from GridCal.Gui.CoordinatesInput.coordinates_dialogue import CoordinatesInputGUI
from GridCal.Gui.general_dialogues import LogsDialogue, CustomQuestionDialogue
from GridCal.Gui.Diagrams.SchematicWidget.schematic_widget import SchematicWidget
@@ -32,10 +32,12 @@
from GridCal.Gui.RosetaExplorer.RosetaExplorer import RosetaExplorerGUI
from GridCal.Gui.Main.SubClasses.Settings.configuration import ConfigurationMain
+from GridCalEngine.Devices.multi_circuit import MultiCircuit
from GridCalEngine.Compilers.circuit_to_newton_pa import NEWTON_PA_AVAILABLE
from GridCalEngine.Compilers.circuit_to_pgm import PGM_AVAILABLE
from GridCalEngine.DataStructures.numerical_circuit import compile_numerical_circuit_at
from GridCalEngine.enumerations import CGMESVersions, SimulationTypes
+from GridCalEngine.basic_structures import Logger
from GridCalEngine.IO.gridcal.contingency_parser import import_contingencies_from_json, export_contingencies_json_file
from GridCalEngine.IO.cim.cgmes.cgmes_enums import cgmesProfile
from GridCalEngine.IO.gridcal.remote import RemoteInstruction
@@ -521,9 +523,17 @@ def export_circuit_differential(self):
"""
Prompt to add another circuit
"""
- self.open_file_threaded(post_function=self.post_create_circuit_differential,
- allow_diff_file_format=True,
- title="Load base grid to compare...")
+ # check that this circuit is ok
+ logger = Logger()
+ _, ok = self.circuit.get_all_elements_dict(logger=logger)
+
+ if ok:
+ self.open_file_threaded(post_function=self.post_create_circuit_differential,
+ allow_diff_file_format=True,
+ title="Load base grid to compare...")
+ else:
+ dlg = LogsDialogue('This circuit has duplicated idtags :(', logger)
+ dlg.exec_()
def post_create_circuit_differential(self):
"""
@@ -548,30 +558,37 @@ def post_create_circuit_differential(self):
# diff the circuit
new_circuit = self.open_file_thread_object.circuit
- # create the differential
- ok, diff_logger, dgrid = self.circuit.differentiate_circuits(new_circuit)
+ dict_logger = Logger()
+ _, dict_ok = new_circuit.get_all_elements_dict(logger=dict_logger)
- if diff_logger.has_logs():
- dlg = LogsDialogue('Grid differences', diff_logger)
- dlg.exec_()
+ if dict_ok:
+ # create the differential
+ ok, diff_logger, dgrid = self.circuit.differentiate_circuits(new_circuit)
- # select the file to save
- filename, type_selected = QtWidgets.QFileDialog.getSaveFileName(self, 'Save file',
- dgrid.name,
- "GridCal diff (*.dgridcal)")
+ if diff_logger.has_logs():
+ dlg = LogsDialogue('Grid differences', diff_logger)
+ dlg.exec_()
- if filename != '':
+ # select the file to save
+ filename, type_selected = QtWidgets.QFileDialog.getSaveFileName(self, 'Save file',
+ dgrid.name,
+ "GridCal diff (*.dgridcal)")
- # if the user did not enter the extension, add it automatically
- name, file_extension = os.path.splitext(filename)
+ if filename != '':
- if file_extension == '':
- filename = name + ".dgridcal"
+ # if the user did not enter the extension, add it automatically
+ name, file_extension = os.path.splitext(filename)
- # we were able to compose the file correctly, now save it
- self.save_file_now(filename=filename,
- type_selected=type_selected,
- grid=dgrid)
+ if file_extension == '':
+ filename = name + ".dgridcal"
+
+ # we were able to compose the file correctly, now save it
+ self.save_file_now(filename=filename,
+ type_selected=type_selected,
+ grid=dgrid)
+ else:
+ dlg = LogsDialogue('The base circuit has duplicated idtags :(', dict_logger)
+ dlg.exec()
def save_file_as(self):
"""
diff --git a/src/GridCalEngine/Devices/assets.py b/src/GridCalEngine/Devices/assets.py
index d238fa9db..f60dfad40 100644
--- a/src/GridCalEngine/Devices/assets.py
+++ b/src/GridCalEngine/Devices/assets.py
@@ -3207,7 +3207,7 @@ def get_contingency_groups_in(self,
group2index = {g: i for i, g in enumerate(self._contingency_groups)}
# get a dictionary of all objects
- all_devices = self.get_all_elements_dict()
+ all_devices, dict_ok = self.get_all_elements_dict()
# get the buses that match the filtering
buses = self.get_buses_by(filter_elements=grouping_elements)
@@ -5265,19 +5265,33 @@ def add_or_replace_object(self, api_obj: ALL_DEV_TYPES, logger: Logger) -> bool:
return found
- def get_all_elements_dict(self) -> dict[str, ALL_DEV_TYPES]:
+ def get_all_elements_dict(self, logger = Logger()) -> Tuple[Dict[str, ALL_DEV_TYPES], bool]:
"""
Get a dictionary of all elements
+ :param: logger: Logger
:return: Dict[idtag] -> object
"""
data = dict()
+ ok = True
for key, tpe in self.device_type_name_dict.items():
elements = self.get_elements_by_type(device_type=tpe)
for elm in elements:
- data[elm.idtag] = elm
- return data
+ e = data.get(elm.idtag, None)
+ if e is None:
+ data[elm.idtag] = elm
+ else:
+ logger.add_error(
+ msg="Duplicated idtag!",
+ device=elm.name,
+ device_class=elm.device_type.value,
+ device_property="idtag",
+ expected_value=f"{e.device_type.value}:{e.idtag}:{e.name}"
+ )
+ ok = False
+
+ return data, ok
def get_all_elements_dict_by_type(self,
add_locations: bool = False,
diff --git a/src/GridCalEngine/Devices/multi_circuit.py b/src/GridCalEngine/Devices/multi_circuit.py
index 67f08ffae..40f7a1538 100644
--- a/src/GridCalEngine/Devices/multi_circuit.py
+++ b/src/GridCalEngine/Devices/multi_circuit.py
@@ -1749,7 +1749,7 @@ def set_investments_status(self,
"""
if all_elements_dict is None:
- all_elements_dict = self.get_all_elements_dict()
+ all_elements_dict, dict_ok = self.get_all_elements_dict()
for inv in investments_list:
device_idtag = inv.device_idtag
@@ -1916,7 +1916,7 @@ def differentiate_circuits(self, base_grid: "MultiCircuit",
expected_value=self.get_snapshot_time_unix)
# get a dictionary of all the elements of the other circuit
- base_elements_dict = base_grid.get_all_elements_dict()
+ base_elements_dict, dict_ok = base_grid.get_all_elements_dict()
for elm_from_here in self.items(): # for every device...
action = ActionType.NoAction
@@ -2244,7 +2244,7 @@ def clean(self) -> Logger:
logger = Logger()
bus_set = set(self._buses)
cn_set = set(self._connectivity_nodes)
- all_dev = self.get_all_elements_dict()
+ all_dev, dict_ok = self.get_all_elements_dict()
nt = self.get_time_number()
self.clean_branches(nt=nt, bus_set=bus_set, cn_set=cn_set, logger=logger)
diff --git a/src/GridCalEngine/Simulations/InvestmentsEvaluation/Methods/mixed_variable_NSGA_2.py b/src/GridCalEngine/Simulations/InvestmentsEvaluation/Methods/mixed_variable_NSGA_2.py
index 6cb90afaf..649105c02 100644
--- a/src/GridCalEngine/Simulations/InvestmentsEvaluation/Methods/mixed_variable_NSGA_2.py
+++ b/src/GridCalEngine/Simulations/InvestmentsEvaluation/Methods/mixed_variable_NSGA_2.py
@@ -50,7 +50,7 @@ def __init__(self, grid: MultiCircuit, obj_func, n_obj):
self.grid = grid
- all_dict = self.grid.get_all_elements_dict()
+ all_dict, dict_ok = self.grid.get_all_elements_dict()
self.device_template_dict: Dict[BRANCH_TYPES, List[BRANCH_TEMPLATE_TYPES]] = dict()
# create the decision vars
diff --git a/src/GridCalEngine/Simulations/InvestmentsEvaluation/investments_evaluation_driver.py b/src/GridCalEngine/Simulations/InvestmentsEvaluation/investments_evaluation_driver.py
index 3a9f020fd..60e202757 100644
--- a/src/GridCalEngine/Simulations/InvestmentsEvaluation/investments_evaluation_driver.py
+++ b/src/GridCalEngine/Simulations/InvestmentsEvaluation/investments_evaluation_driver.py
@@ -243,7 +243,7 @@ def __init__(self,
self.max_iter = options.max_eval
# gather a dictionary of all the elements, this serves for the investments generation
- self.get_all_elements_dict = self.grid.get_all_elements_dict()
+ self.get_all_elements_dict, dict_ok = self.grid.get_all_elements_dict()
# compose useful arrays
self.vm_cost = np.array([e.Vm_cost for e in grid.get_buses()], dtype=float)
diff --git a/src/trunk/investments/InvestmentsEvaluation/investments_evaluation_driver.py b/src/trunk/investments/InvestmentsEvaluation/investments_evaluation_driver.py
index 18fe19e0e..c3218d52c 100644
--- a/src/trunk/investments/InvestmentsEvaluation/investments_evaluation_driver.py
+++ b/src/trunk/investments/InvestmentsEvaluation/investments_evaluation_driver.py
@@ -67,7 +67,7 @@ def __init__(self, grid: MultiCircuit,
self.nc: Union[NumericalCircuit, None] = None
# gather a dictionary of all the elements, this serves for the investments generation
- self.get_all_elements_dict = self.grid.get_all_elements_dict()
+ self.get_all_elements_dict, dict_ok = self.grid.get_all_elements_dict()
def get_steps(self):
"""