diff --git a/.github/workflows/pull_request_tests.yml b/.github/workflows/pull_request_tests.yml index a4793b5..b9a9d28 100644 --- a/.github/workflows/pull_request_tests.yml +++ b/.github/workflows/pull_request_tests.yml @@ -9,7 +9,7 @@ jobs: matrix: os: [ubuntu-latest, macos-latest] #os: [ubuntu-latest, macos-latest, windows-latest] - python-version: ["3.7", "3.10", "3.11"] + python-version: ["3.9", "3.11"] steps: - uses: actions/checkout@v2 diff --git a/pyproject.toml b/pyproject.toml index 1329b2a..a276a0e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,7 +37,6 @@ dependencies = [ "toml", "xlrd", "loguru", - # "powersystem-data-models" ] [project.scripts] diff --git a/pypsse/__init__.py b/pypsse/__init__.py index a82b376..72f26f5 100644 --- a/pypsse/__init__.py +++ b/pypsse/__init__.py @@ -1 +1 @@ -__version__ = "1.1.1" +__version__ = "1.1.2" diff --git a/pypsse/cli/explore.py b/pypsse/cli/explore.py index e609721..d8c3867 100644 --- a/pypsse/cli/explore.py +++ b/pypsse/cli/explore.py @@ -3,6 +3,7 @@ from loguru import logger import pandas as pd import click +import toml from pypsse.common import EXPORTS_SETTINGS_FILENAME, SIMULATION_SETTINGS_FILENAME from pypsse.models import ExportFileOptions, SimulationSettings @@ -93,18 +94,27 @@ def explore(project_path, simulations_file, export_file_path, load_filter, load, msg = "Simulation file not found. Use -s to choose a valid settings file" "if its name differs from the default file name." assert file_path.exists(), msg - x = Simulator.from_setting_files(file_path) + + simulation_settings = toml.load(file_path) + simulation_settings = SimulationSettings(**simulation_settings) + simulation_settings.helics.cosimulation_mode = False + x = Simulator(simulation_settings) buses = set(x.raw_data.buses) quantities = { - 'Loads': ['MVA', 'FmA', 'FmB', 'FmC', 'FmD', 'Fel', 'PFel'], + 'Loads': ['MVA', "IL", "YL", 'FmA', 'FmB', 'FmC', 'FmD', 'Fel', 'PFel'], 'Induction_generators': ['MVA'], 'Machines': ['MVA', 'PERCENT'], } results = x.sim.read_subsystems(quantities, buses) + + # print(results.keys()) + print(results["LOAD_P"]) + # quit() + had_comp_models = False if "Loads_FmA" in results: had_comp_models = True - + load_dict = {} bus_load_real = {} bus_load_imag = {} @@ -114,22 +124,33 @@ def explore(project_path, simulations_file, export_file_path, load_filter, load, load_dict[bus] = [] bus_load_real[bus] = 0 bus_load_imag[bus] = 0 - is_comp_load = [] + load_bus_id = f'{bus}_{ld_id}' if had_comp_models: is_comp = True if f'{bus}_{ld_id}' in results["Loads_FmA"] else False else: is_comp = False - is_comp_load.append(is_comp) + + is_comp_load[bus] = is_comp load_dict[bus].append(ld_id) key = f"{ld_id} _{bus}" if len(ld_id) == 1 else f"{ld_id}_{bus}" - bus_load_real[bus] += results["Loads_MVA"][key].real - bus_load_imag[bus] += results["Loads_MVA"][key].imag + key2 = f"{bus}_{ld_id}".replace(" ", "") + load_p = max( + results["Loads_MVA"][key].real + results["Loads_IL"][key].real + results["Loads_YL"][key].real, + results["LOAD_P"][key2] *100 if key2 in results["LOAD_P"] else 0 + ) + load_q = max( + results["Loads_MVA"][key].imag + results["Loads_IL"][key].imag + results["Loads_YL"][key].imag, + results["LOAD_Q"][key2] *100 if key2 in results["LOAD_Q"] else 0 + ) + + bus_load_real[bus] += load_p + bus_load_imag[bus] += load_q generator_dict = {} bus_gen = {} for bus, gen_id in x.raw_data.generators: - if bus not in load_dict: + if bus not in generator_dict: generator_dict[bus] = [] bus_gen[bus] = 0 key = f"{gen_id} _{bus}" if len(gen_id) == 1 else f"{gen_id}_{bus}" @@ -156,29 +177,36 @@ def explore(project_path, simulations_file, export_file_path, load_filter, load, results = pd.DataFrame(results) - if filter: - if load_filter and load: + + results["total P load [MW]"] = results["total P load [MW]"] + results["total Q load [MVar]"] = results["total Q load [MVar]"] + + if load_filter: + if load: results=results[results["has load"] == True] - elif load_filter and not load: + elif not load: results=results[results["has load"] == False] - if gen_filter and generation: - results=results[results["has generation"] == True] - elif gen_filter and not generation: - results=results[results["has generation"] == False] - - if load_filter and comp_load: + if comp_load: results=results[results["is load comp"] == True] - elif load_filter and not comp_load: + elif not comp_load: results=results[results["is load comp"] == False] - load_lower, load_upper = [float(x) for x in load_bounds.split("/")] - gen_lower, gen_upper = [float(x) for x in gen_bounds.split("/")] - if apply_bounds: - results=results[(results["total P load [MW]"] >= load_lower) & (results["total P load [MW]"] <= load_upper)] - results=results[(results["total generation [MVA]"] >= gen_lower) & (results["total generation [MVA]"] <= gen_upper)] - + if gen_filter: + if generation: + results=results[results["has generation"] == True] + elif not generation: + results=results[results["has generation"] == False] + + load_lower, load_upper = [float(x) for x in load_bounds.split("/")] + gen_lower, gen_upper = [float(x) for x in gen_bounds.split("/")] + if apply_bounds: + results=results[(results["total P load [MW]"] >= load_lower) & (results["total P load [MW]"] <= load_upper)] + results=results[(results["total generation [MVA]"] >= gen_lower) & (results["total generation [MVA]"] <= gen_upper)] + + print(results) results.to_csv(export_file_path) + logger.info(f"Results exported to {export_file_path.absolute()}") diff --git a/pypsse/cli/run.py b/pypsse/cli/run.py index 614e8c2..1a67dcf 100644 --- a/pypsse/cli/run.py +++ b/pypsse/cli/run.py @@ -4,8 +4,11 @@ from pathlib import Path +from loguru import logger import click +import toml +from pypsse.models import SimulationSettings from pypsse.common import SIMULATION_SETTINGS_FILENAME from pypsse.simulator import Simulator @@ -28,5 +31,15 @@ def run(project_path, simulations_file=None): msg = "Simulation file not found. Use -s to choose a valid settings file" "if its name differs from the default file name." assert file_path.exists(), msg + + simulation_settiings = toml.load(file_path) + simulation_settiings = SimulationSettings(**simulation_settiings) + + logger.level(simulation_settiings.log.logging_level.value) + if simulation_settiings.log.log_to_external_file: + log_path = Path(project_path) / "Logs" / "pypsse.log" + logger.add(log_path) + x = Simulator.from_setting_files(file_path) + x.run() diff --git a/pypsse/enumerations.py b/pypsse/enumerations.py index bb19708..4a6c37c 100644 --- a/pypsse/enumerations.py +++ b/pypsse/enumerations.py @@ -66,14 +66,14 @@ class ModelProperties(str, Enum): ANGLED = "ANGLED" -class LoggingLevels(IntEnum): +class LoggingLevels(str, Enum): "logging level setting options" - NOTSET = 0 - DEBUG = 10 - INFO = 20 - WARN = 30 - ERROR = 40 - CRITICAL = 50 + NOTSET = "INFO" + DEBUG = "DEBUG" + INFO = "INFO" + WARNING = "WARNING" + ERROR = "ERROR" + CRITICAL = "CRITICAL" class SubscriptionFileRequiredColumns(str, Enum):