diff --git a/gridappsd-python-lib/gridappsd/simulation.py b/gridappsd-python-lib/gridappsd/simulation.py index c1b77bf..9a65592 100644 --- a/gridappsd-python-lib/gridappsd/simulation.py +++ b/gridappsd-python-lib/gridappsd/simulation.py @@ -42,11 +42,11 @@ def asdict(self): @dataclass class ModelCreationConfig(ConfigBase): - load_scaling_factor: str = field(default="1") + load_scaling_factor: float = field(default=1) schedule_name: str = field(default="ieeezipload") - z_fraction: str = field(default="0") - i_fraction: str = field(default="1") - p_fraction: str = field(default="0") + z_fraction: float = field(default=0) + i_fraction: float = field(default=1) + p_fraction: float = field(default=0) randomize_zipload_fractions: bool = field(default=False) use_houses: bool = field(default=False) @@ -56,14 +56,28 @@ class ModelCreationConfig(ConfigBase): @dataclass class SimulationArgs(ConfigBase): - start_time: str = field(default="1655321830") - duration: str = field(default="300") - timestep_frequency: str = field(default="1000") - timestep_increment: str = field(default="1000") + start_time: int = field(default=1655321830) + duration: int = field(default=300) + publish_period: int = field(default=None) + interval: int = field(default=None) run_realtime: bool = field(default=True) pause_after_measurements: bool = field(default=False) simulation_name: str = field(default="ieee13nodeckt") + def __post_init_(self): + if self.run_realtime: + self.interval = 1 + if not self.publish_period: + self.publish_period = 3 + else: + if not self.interval: + self.interval = 60 + if not self.publish_period: + self.publish_period = 60 + if self.publish_period < self.interval: + raise RuntimeError("A simulation's publishing_period cannot be less than the simulation's timestep " + f"interval. please make the publishing_period >= interval!") + @dataclass class SimulatorArgs(ConfigBase): diff --git a/gridappsd-python-lib/tests/test_simulation.py b/gridappsd-python-lib/tests/test_simulation.py index 47dcceb..76dd8e2 100644 --- a/gridappsd-python-lib/tests/test_simulation.py +++ b/gridappsd-python-lib/tests/test_simulation.py @@ -16,50 +16,57 @@ @pytest.fixture def createGadObject(): - gad_user = os.environ.get('GRIDAPPSD_USER') - if gad_user is None: - os.environ['GRIDAPPSD_USER'] = 'system' - gad_password = os.environ.get('GRIDAPPSD_PASSWORD') - if gad_password is None: - os.environ['GRIDAPPSD_PASSWORD'] = 'manager' - return GridAPPSD() + gad_user = os.environ.get('GRIDAPPSD_USER') + if gad_user is None: + os.environ['GRIDAPPSD_USER'] = 'system' + gad_password = os.environ.get('GRIDAPPSD_PASSWORD') + if gad_password is None: + os.environ['GRIDAPPSD_PASSWORD'] = 'manager' + return GridAPPSD() @pytest.mark.integration def test_createSimulations(createGadObject): - gadObj = createGadObject - response = gadObj.query_model_info() - models = response.get("data", {}).get("models", {}) - start_time = int(datetime(year=2025, month=1, day=1, hour=0, minute=0, second=0, microsecond=0, tzinfo=timezone.utc).timestamp()) - simulationArgs = SimulationArgs(start_time=f"{start_time}", - duration="120", - run_realtime=False, - pause_after_measurements=False) - sim_config = SimulationConfig(simulation_config=simulationArgs) - modelsToRun = [ - "49AD8E07-3BF9-A4E2-CB8F-C3722F837B62", # IEEE 13 Node Test Feeder - "C1C3E687-6FFD-C753-582B-632A27E28507" # IEEE 123 Node Test Feeder - ] - for m in models: - if m.get("modelId") not in modelsToRun: - continue - line_name = m.get("modelId") - subregion_name = m.get("subRegionId") - region_name = m.get("regionId") - psc = PowerSystemConfig(Line_name=line_name, - SubGeographicalRegion_name=subregion_name, - GeographicalRegion_name=region_name) - sim_config.power_system_configs.append(psc) - sim_obj = Simulation(gapps=gadObj, run_config=sim_config) - def on_measurement(sim, ts, m): - global measurements_received - measurements_received += 1 - def on_simulation_complete(sim): - global simulation_is_complete - simulation_is_complete = True - sim_obj.add_onmeasurement_callback(on_measurement) - sim_obj.add_oncomplete_callback(on_simulation_complete) - sim_obj.start_simulation() - while not simulation_is_complete: - time.sleep(1) - assert measurements_received == 1 - gadObj.disconnect() + gadObj = createGadObject + response = gadObj.query_model_info() + models = response.get("data", {}).get("models", {}) + start_time = int(datetime(year=2025, + month=1, + day=1, + hour=0, + minute=0, + second=0, + microsecond=0, + tzinfo=timezone.utc).timestamp()) + simulationArgs = SimulationArgs(start_time=f"{start_time}", + duration="120", + run_realtime=False, + pause_after_measurements=False) + sim_config = SimulationConfig(simulation_config=simulationArgs) + modelsToRun = [ + "49AD8E07-3BF9-A4E2-CB8F-C3722F837B62", # IEEE 13 Node Test Feeder + "C1C3E687-6FFD-C753-582B-632A27E28507" # IEEE 123 Node Test Feeder + ] + for m in models: + if m.get("modelId") not in modelsToRun: + continue + line_name = m.get("modelId") + subregion_name = m.get("subRegionId") + region_name = m.get("regionId") + psc = PowerSystemConfig(Line_name=line_name, + SubGeographicalRegion_name=subregion_name, + GeographicalRegion_name=region_name) + sim_config.power_system_configs.append(psc) + sim_obj = Simulation(gapps=gadObj, run_config=sim_config) + def on_measurement(sim, ts, m): + global measurements_received + measurements_received += 1 + def on_simulation_complete(sim): + global simulation_is_complete + simulation_is_complete = True + sim_obj.add_onmeasurement_callback(on_measurement) + sim_obj.add_oncomplete_callback(on_simulation_complete) + sim_obj.start_simulation() + while not simulation_is_complete: + time.sleep(1) + assert measurements_received == 1 + gadObj.disconnect()