From cb9d092f6e9b5b49882c377ac6963421d8e5e567 Mon Sep 17 00:00:00 2001 From: Joseph McKinsey Date: Wed, 31 May 2023 15:19:21 -0600 Subject: [PATCH] Add load_y_matrix output --- LocalFeeder/FeederSimulator.py | 15 ++++++++++++--- LocalFeeder/component_definition.json | 3 ++- LocalFeeder/sender_cosim.py | 26 ++++++++++++++++++++++++++ LocalFeeder/tests/test_feeder.py | 27 +++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 4 deletions(-) diff --git a/LocalFeeder/FeederSimulator.py b/LocalFeeder/FeederSimulator.py index 6d39c2b..fac257e 100644 --- a/LocalFeeder/FeederSimulator.py +++ b/LocalFeeder/FeederSimulator.py @@ -139,6 +139,12 @@ def snapshot_run(self): Used for initialization. """ assert self._state != OpenDSSState.UNLOADED, f"{self._state}" + self.reenable() + dss.Text.Command("CalcVoltageBases") + dss.Text.Command("solve mode=snapshot") + self._state = OpenDSSState.SNAPSHOT_RUN + + def reenable(self): dss.Text.Command("Batchedit Load..* enabled=yes") dss.Text.Command("Batchedit Vsource..* enabled=yes") dss.Text.Command("Batchedit Isource..* enabled=yes") @@ -146,9 +152,6 @@ def snapshot_run(self): dss.Text.Command("Batchedit PVsystem..* enabled=yes") dss.Text.Command("Batchedit Capacitor..* enabled=yes") dss.Text.Command("Batchedit Storage..* enabled=no") - dss.Text.Command("CalcVoltageBases") - dss.Text.Command("solve mode=snapshot") - self._state = OpenDSSState.SNAPSHOT_RUN def download_data(self, bucket_name, update_loadshape_location=False): """Download data from bucket path.""" @@ -336,6 +339,12 @@ def get_load_y_matrix(self): dss.Text.Command("batchedit Load..* enabled=false") self._state = OpenDSSState.DISABLED_RUN + self.reenable() + + dss.Text.Command("CalcVoltageBases") + dss.Text.Command("set maxiterations=20") + dss.Text.Command("solve") + self._state = OpenDSSState.SOLVE_AT_TIME return coo_matrix( (Ymatrix.data, (permute[Ymatrix.row], permute[Ymatrix.col])), diff --git a/LocalFeeder/component_definition.json b/LocalFeeder/component_definition.json index af9bdaf..2c88254 100644 --- a/LocalFeeder/component_definition.json +++ b/LocalFeeder/component_definition.json @@ -19,6 +19,7 @@ {"type": "PowersReal", "port_id": "powers_real"}, {"type": "PowersImaginary", "port_id": "powers_imag"}, {"type": "Topology", "port_id": "topology"}, - {"type": "Injection", "port_id": "injections"} + {"type": "Injection", "port_id": "injections"}, + {"type": "", "port_id": "load_y_matrix"} ] } diff --git a/LocalFeeder/sender_cosim.py b/LocalFeeder/sender_cosim.py index d1a1bba..380104e 100644 --- a/LocalFeeder/sender_cosim.py +++ b/LocalFeeder/sender_cosim.py @@ -209,6 +209,7 @@ class CurrentData: PQ_injections_all: xr.core.dataarray.DataArray calculated_power: xr.core.dataarray.DataArray injections: Injection + load_y_matrix: Any def get_current_data(sim: FeederSimulator, Y): @@ -239,11 +240,14 @@ def get_current_data(sim: FeederSimulator, Y): ) PQ_injections_all[sim._source_indexes] = -calculated_power[sim._source_indexes] + + Y_load = sim.get_load_y_matrix() return CurrentData( feeder_voltages=feeder_voltages, PQ_injections_all=PQ_injections_all, calculated_power=calculated_power, injections=injections, + load_y_matrix=Y_load, ) @@ -292,6 +296,9 @@ def go_cosim(sim: FeederSimulator, config: FeederConfig, input_mapping: Dict[str pub_injections = h.helicsFederateRegisterPublication( vfed, "injections", h.HELICS_DATA_TYPE_STRING, "" ) + pub_load_y_matrix = h.helicsFederateRegisterPublication( + vfed, "load_y_matrix", h.HELICS_DATA_TYPE_STRING, "" + ) command_set_key = ( "unused/change_commands" @@ -342,12 +349,15 @@ def go_cosim(sim: FeederSimulator, config: FeederConfig, input_mapping: Dict[str f"Solve at hour {floored_timestamp.hour} second " f"{60*floored_timestamp.minute + floored_timestamp.second}" ) + + sim.snapshot_run() sim.solve( floored_timestamp.hour, 60 * floored_timestamp.minute + floored_timestamp.second, ) current_data = get_current_data(sim, initial_data.Y) + bad_bus_names = where_power_unbalanced( current_data.PQ_injections_all, current_data.calculated_power ) @@ -400,6 +410,22 @@ def go_cosim(sim: FeederSimulator, config: FeederConfig, input_mapping: Dict[str ) pub_injections.publish(current_data.injections.json()) + if config.use_sparse_admittance: + pub_load_y_matrix.publish( + sparse_to_admittance_sparse( + current_data.load_y_matrix, sim._AllNodeNames + ).json() + ) + else: + pub_load_y_matrix.publish( + AdmittanceMatrix( + admittance_matrix=numpy_to_y_matrix( + current_data.load_y_matrix.toarray() + ), + ids=sim._AllNodeNames + ).json() + ) + logger.info("end time: " + str(datetime.now())) h.helicsFederateDisconnect(vfed) diff --git a/LocalFeeder/tests/test_feeder.py b/LocalFeeder/tests/test_feeder.py index 23a43e5..f26e8e2 100644 --- a/LocalFeeder/tests/test_feeder.py +++ b/LocalFeeder/tests/test_feeder.py @@ -22,6 +22,26 @@ from sender_cosim import agg_to_ids +@pytest.fixture(scope="session", autouse=True) +def init_federate_simulation(): + federate_config = FeederSimulator.FeederConfig( + **{ + "use_smartds": False, + "profile_location": "gadal_ieee123/profiles", + "opendss_location": "gadal_ieee123/qsts", + "sensor_location": "gadal_ieee123/sensors.json", + "start_date": "2017-01-01 00:00:00", + "number_of_timesteps": 96, + "run_freq_sec": 900, + "topology_output": "../../outputs/topology.json", + "name": "feeder", + } + ) + logging.info("Initializating simulation data") + _ = FeederSimulator.FeederSimulator(federate_config) + return + + @pytest.fixture() def federate_config(): return FeederSimulator.FeederConfig( @@ -30,6 +50,7 @@ def federate_config(): "profile_location": "gadal_ieee123/profiles", "opendss_location": "gadal_ieee123/qsts", "sensor_location": "gadal_ieee123/sensors.json", + "existing_feeder_file": "opendss/master.dss", "start_date": "2017-01-01 00:00:00", "number_of_timesteps": 96, "run_freq_sec": 900, @@ -305,6 +326,12 @@ def simulation_middle(sim, Y): current_data.injections.power_real.ids ) + current_data_again = sender_cosim.get_current_data(sim, Y) + assert np.allclose( + current_data_again.feeder_voltages, + current_data.feeder_voltages + ) + assert '113' in current_data.PQ_injections_all.equipment_ids.data df = pd.DataFrame( {