Skip to content

Commit

Permalink
Merge pull request #135 from NREL/feature/create-new-scenario
Browse files Browse the repository at this point in the history
extending cli to add ability to add a scenario to an existing project
  • Loading branch information
AadilLatif authored Feb 5, 2024
2 parents d5e1f46 + f71c153 commit f71af54
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 5 deletions.
2 changes: 1 addition & 1 deletion PyDSS/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "3.0.1"
__version__ = "3.0.2"


from PyDSS.utils.timing_utils import timer_stats_collector
Expand Down
58 changes: 58 additions & 0 deletions PyDSS/cli/add_scenario.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from pathlib import Path
import toml
import click
import os

from PyDSS.simulation_input_models import MappedControllers
from PyDSS.pydss_project import PyDssScenario
from PyDSS.common import CONTROLLER_TYPES, ControllerType

def build_scenario(project_path:str, scenario_name:str, controller_mapping:str):
project_path = Path(project_path)
controller_mapping_path = Path(controller_mapping)
assert project_path.exists(), "Provided project path does not exist"
assert (project_path / "Scenarios").exists(), "provided project is not a valid PyDSS project"
assert controller_mapping_path.exists(), "rovided controller_mapping file does not exist"
assert controller_mapping_path.suffix.lower() == ".toml", "controller_mapping should be a TOML file"

controller_map = toml.load(controller_mapping_path)
mapped_controllers = MappedControllers(**controller_map)
acceptable_controller_types = CONTROLLER_TYPES
controllers = {}
for controller in mapped_controllers.mapping:
settings_path_obj = Path(controller.controller_file)
assert controller.controller_type in ControllerType, \
f"{controller.controller_type} is not a valid contoller. Options are {acceptable_controller_types}"
assert settings_path_obj.exists(), \
f"file for controller type {controller.controller_type} does not exist"
controller_data = toml.load(settings_path_obj)
if controller_data:
if controller.controller_type in controllers:
msg= f"Multiple keys files for the same controller type {controller.controller_type}." \
"Each controller type can only be attached to a single file."
raise ValueError(msg)
controllers[controller.controller_type] = toml.load(settings_path_obj)
scenario_dir = project_path / "Scenarios" / scenario_name
scenario_obj = PyDssScenario(
[scenario_name], list(controllers.keys()), export_modes=None, visualization_types=None
)
scenario_obj.serialize(str(scenario_dir))

@click.argument("project-path", type=click.Path(exists=True))
@click.option(
"-s", "--scenario_name",
required=True,
help="name of the new scenario",
)
@click.option(
"-c", "--controller-mapping",
required=True,
default=None,
type=click.Path(exists=True),
help="JSON file that maps controller type to controller definition files",
)
@click.command()
def add_scenario(project_path:str, scenario_name:str, controller_mapping:str):
"""Add a new scenario to an existing project"""
build_scenario(project_path, scenario_name, controller_mapping)

3 changes: 0 additions & 3 deletions PyDSS/cli/edit_scenario.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
"""CLI to edit an existing project or scenario"""

import os
import sys

import click

from PyDSS.common import CONTROLLER_TYPES
Expand Down
4 changes: 3 additions & 1 deletion PyDSS/cli/pydss.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from PyDSS.cli.edit_scenario import edit_scenario
from PyDSS.cli.run_server import serve
from PyDSS.cli.reports import reports
from PyDSS.cli.add_scenario import add_scenario

logger = logging.getLogger(__name__)

Expand All @@ -29,8 +30,9 @@ def cli():
cli.add_command(extract)
cli.add_command(extract_element_files)
cli.add_command(run)
cli.add_command(add_scenario)
cli.add_command(edit_scenario)
cli.add_command(convert)
cli.add_command(controllers)
cli.add_command(serve)
cli.add_command(reports)
cli.add_command(reports)
9 changes: 9 additions & 0 deletions PyDSS/simulation_input_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
SimulationType,
SnapshotTimePointSelectionMode,
SIMULATION_SETTINGS_FILENAME,
ControllerType
)
from PyDSS.dataset_buffer import DEFAULT_MAX_CHUNK_BYTES
from PyDSS.utils.utils import dump_data, load_data
Expand Down Expand Up @@ -940,6 +941,14 @@ class SimulationSettingsModel(InputsBaseModel):
)


class ControllerMap(InputsBaseModel):
controller_type : ControllerType
controller_file : Path


class MappedControllers(InputsBaseModel):
mapping : List[ControllerMap] = []

def create_simulation_settings(path: Path, project_name: str, scenario_names: list, force=False):
"""Create a settings file with default values.
Expand Down
24 changes: 24 additions & 0 deletions tests/data/add_scenario/MotorStall.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
["Load.motor_1"]
Kp1 = 0.0
Np1 = 1.0
Kp2 = 12.0
Np2 = 3.2
Kq1 = 6.0
Nq1 = 2.0
Kq2 = 11.0
Nq2 = 2.5
Tth = 4.0
Frst = 0.20
LFadj = 0.0
Tth1t = 0.7
Tth2t = 1.9
Pfault = 3.0
Qfault = 5.0
Vstall = 0.55
Vbreak = 0.86
Vrstrt = 0.95
Tstall = 0.032
Trestart = 0.3
ratedKW = 7.00
ratedPF = 0.939
R_stall_pu = 0.10
3 changes: 3 additions & 0 deletions tests/data/add_scenario/controller_map.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[[mapping]]
controller_type = "MotorStall"
controller_file = "./tests/data/add_scenario/MotorStall.toml"
27 changes: 27 additions & 0 deletions tests/test_add_scenario.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from click.testing import CliRunner
from pathlib import Path
import tempfile
import shutil
import toml
import os

from PyDSS.cli.add_scenario import build_scenario

PYDSS_PROJECT = Path(__file__).parent / "data" / "project"
MAPPING_FILE = Path(__file__).parent / "data" / "add_scenario" / "controller_map.toml"



def test_add_scenario():

with tempfile.TemporaryDirectory() as tmpdirname:
tmpdirname_obj = Path(tmpdirname) / "tmp"
shutil.copytree(PYDSS_PROJECT, str(tmpdirname_obj))
settings_path = tmpdirname_obj / "simulation.toml"
settings = toml.load(settings_path)
settings['Project']['Project Path'] = str(tmpdirname_obj.absolute())
toml.dump(settings, open(settings_path, "w"))
build_scenario(str(tmpdirname_obj), "test_scenario", str(MAPPING_FILE))
assert (tmpdirname_obj / "Scenarios" / "test_scenario").exists()
assert (tmpdirname_obj / "Scenarios" / "test_scenario" / "pyControllerList" / "MotorStall.toml").exists()

0 comments on commit f71af54

Please sign in to comment.