Source code for hermess.config

# © 2024-2026 ETH Zurich
# Original author: Milos Katanic
# Simulation-only fork & maintainer: Maitraya Avadhut Desai
#
# Licensed under the GNU General Public License v3.0;
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
#     https://www.gnu.org/licenses/gpl-3.0.en.html
#
# This software is distributed "AS IS", WITHOUT WARRANTY OF ANY KIND,
# express or implied. See the License for specific language governing
# permissions and limitations under the License.
#
# Simulation-only fork of PowerDynamicEstimator
# (https://doi.org/10.5905/ethz-1007-842); dynamic state estimation removed.
# For inquiries, contact: mdesai@ethz.ch

from pathlib import Path
from typing import Any
from typing import Literal
import logging
from pydantic import BaseModel

IntegrationSchemeSim = Literal["idas", "collocation", "cvodes", "rk"]

Frequency = Literal[50, 60]
Levels = Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
Reference = Literal["coi", "single", "nom", "dist"]


[docs] class Config(BaseModel): """Holds all attributes controlling a simulation run.""" testsystemfile: str system_root: Path | None = ( None # absolute path to a system-definitions root; None → repo's hermess/systems/ ) omega_mode: Reference omega_single_idx: str | None = ( None # reference device for single-mode (None → use slack bus) ) fn: Frequency # 50 or 60 Sb: int # parameters in .txt table are assumed to be given for 100 MW # General input data ts: float # Simulation time step T_start: float # It has to be 0.0 T_end: float int_scheme_sim: IntegrationSchemeSim int_scheme_sim_options: dict = ( {} ) # Options passed to ca.integrator(), e.g. {"abstol": 1e-10} plot: bool plot_voltage: bool plot_diff: bool incl_lim: bool line_dyn: bool # Simulate with dynamic line models (differential equations) skip_disturance: bool # Run only simulation debug_check_init: bool # Run only simulation print_power_flow: bool # Print initial power flow to output small_signal_analysis: bool = ( False # Run small-signal eigenvalue/participation analysis at the # operating point (before the simulation) and show the figures ) log_level: Levels
[docs] def updated(self, **kwargs: Any) -> "Config": """Return a copy of this config with the given fields overridden. :param testsystemfile: The path to the system test case. :type testsystemfile: str :param fn: System frequency (currently only tested for 50 Hz). :type fn: float :param omega_mode: Reference frequency mode used in the simulation. Must be `'coi'`, `'single'`, `'nom'` or `'dist'`. :type omega_mode: str :param omega_single_idx: Reference device identifier (e.g. `"SG1"`) used only if `omega_mode='single'` (None → slack bus). :type omega_single_idx: str or None :param Sb: Base power of the grid in [MW]. Line parameters are assumed to be calculated using this base power. :type Sb: float :param ts: Simulation time step. :type ts: float :param T_start: Simulation start time (must currently be 0). :type T_start: float :param T_end: End time of the simulation. :type T_end: float :param plot: Enable or disable plotting. :type plot: bool :param plot_voltage: Whether to plot voltage data. :type plot_voltage: bool :param plot_diff: Whether to plot differential state data. :type plot_diff: bool :param incl_lim: If state limiters should be included in the simulation. If `False`, the simulation will be much faster. :type incl_lim: bool :param line_dyn: Simulate with line dynamic models (differential equations). :type line_dyn: bool :param skip_disturance: Skip disturbance simulation. :type skip_disturance: bool :param debug_check_init: Enable debug check for initialization of DAE system. :type debug_check_init: bool :param print_power_flow: Print initial power flow to output. :type print_power_flow: bool :param small_signal_analysis: Run the small-signal eigenvalue/participation analysis at the operating point (before the simulation) and show the frequency-banded participation figures plus the modal report. :type small_signal_analysis: bool :returns: A new instance of the :class:`Config` class configured with the provided parameters. :rtype: Config """ return self.model_copy(update=kwargs)
[docs] def get_log_level(self): """Returns the log level.""" valid_levels = { "DEBUG": logging.DEBUG, "INFO": logging.INFO, "WARNING": logging.WARNING, "ERROR": logging.ERROR, "CRITICAL": logging.CRITICAL, } return valid_levels[self.log_level]
config = Config( testsystemfile="IEEE39_bus_inverter", # testsystemfile="3_bus", omega_mode="nom", omega_single_idx="GFMI2", # reference device for single-mode (None → uses slack bus) fn=50, Sb=100, # parameters in .txt table are assumed to be given for 100 MW ts=0.0001, # Simulation time step T_start=0.0, # It has to be 0.0 T_end=10, int_scheme_sim="idas", int_scheme_sim_options={ # "abstol": 1e-12, # Absolute tolerance (default 1e-8) "reltol": 1e-14, # Relative tolerance (default 1e-6) "max_num_steps": 10000, # Max internal steps between output points "max_step_size": 0.01, # Max internal step size (0 = no limit) "jit": True, # Whether to JIT compile the integrator (requires CasADi with JIT support) }, # #########Plot############### plot=True, plot_voltage=True, plot_diff=True, log_level="WARNING", incl_lim=False, line_dyn=True, skip_disturance=False, debug_check_init=False, print_power_flow=True, small_signal_analysis=True, )