Source code for agentlib_flexquant.data_structures.mpcs

"""
Data models for MPC configurations in flexibility quantification.

This module defines Pydantic data models that encapsulate configuration parameters
for baseline, positive flexibility, and negative flexibility MPC controllers used
in flexquant. The models handle file paths, module configurations, variable
mappings, and optimization weights for MPC implementations.
"""
import pydantic
from agentlib_mpc.data_structures.mpc_datamodels import MPCVariable
from pydantic import ConfigDict, model_validator

import agentlib_flexquant.data_structures.globals as glbs
import agentlib_flexquant.utils.config_management as cmng


[docs]class BaseMPCData(pydantic.BaseModel): """Base class containing necessary data for the code creation of the different mpcs""" # files and paths created_flex_mpcs_file: str = "flex_agents.py" name_of_created_file: str results_suffix: str # modules module_types: dict class_name: str module_id: str # variables power_alias: str stored_energy_alias: str config_inputs_appendix: list[MPCVariable] = [] config_parameters_appendix: list[MPCVariable] = [] weights: list[MPCVariable] = pydantic.Field( default=[], description="Name and value of weights", ) model_config = ConfigDict(json_encoders={MPCVariable: lambda v: v.dict()})
[docs]class BaselineMPCData(BaseMPCData): """Data class for Baseline MPC""" # files and paths results_suffix: str = "_base.csv" name_of_created_file: str = "baseline.json" # modules module_types: dict = cmng.BASELINE_MODULE_TYPE_DICT class_name: str = "BaselineMPCModel" module_id: str = "Baseline" # variables power_alias: str = glbs.POWER_ALIAS_BASE stored_energy_alias: str = glbs.STORED_ENERGY_ALIAS_BASE power_variable: str = pydantic.Field( default="P_el", description=( "Name of the variable representing the electrical power in the baseline config" ), ) profile_deviation_weight: float = pydantic.Field( default=0, description="Weight of soft constraint for deviation from accepted flexible profile", ) power_unit: str = pydantic.Field( default="kW", description="Unit of the power variable" ) comfort_variable: str = pydantic.Field( default=None, description=( "Name of the slack variable representing the thermal comfort in the baseline config" ), ) profile_comfort_weight: float = pydantic.Field( default=1, description="Weight of soft constraint for discomfort", ) config_inputs_appendix: list[MPCVariable] = [ MPCVariable(name="_P_external", value=0, unit="W"), MPCVariable(name="in_provision", value=False), MPCVariable(name="rel_start", value=0, unit="s"), MPCVariable(name="rel_end", value=0, unit="s"), ] config_parameters_appendix: list[MPCVariable] = [] weights: list[MPCVariable] = pydantic.Field( default=[], description="Name and value of weights", ) model_config = ConfigDict(json_encoders={MPCVariable: lambda v: v.dict()})
[docs] @model_validator(mode="after") def update_config_parameters_appendix(self) -> "BaselineMPCData": """Update the config parameters appendix with profile deviation and comfort weights. Adds the profile deviation weight parameter and optionally the profile comfort weight parameter (if comfort_variable is enabled) to the config_parameters_appendix list as MPCVariable instances. """ self.config_parameters_appendix = [ MPCVariable( name=glbs.PROFILE_DEVIATION_WEIGHT, value=self.profile_deviation_weight, unit="-", description=( "Weight of soft constraint for deviation from accepted flexible profile" ), ) ] if self.comfort_variable: self.config_parameters_appendix.append( MPCVariable( name=glbs.PROFILE_COMFORT_WEIGHT, value=self.profile_comfort_weight, unit="-", description="Weight of soft constraint for discomfort", ) ) return self
[docs]class PFMPCData(BaseMPCData): """Data class for PF-MPC""" # files and paths results_suffix: str = "_pos_flex.csv" name_of_created_file: str = "pos_flex.json" # modules module_types: dict = cmng.SHADOW_MODULE_TYPE_DICT class_name: str = "PosFlexModel" module_id: str = "PosFlexMPC" # variables power_alias: str = glbs.POWER_ALIAS_POS stored_energy_alias: str = glbs.STORED_ENERGY_ALIAS_POS flex_cost_function: str = pydantic.Field( default=None, description="Cost function of the PF-MPC", ) # initialize market parameters with dummy values (0) config_parameters_appendix: list[MPCVariable] = [ MPCVariable(name=glbs.PREP_TIME, value=0, unit="s"), MPCVariable(name=glbs.MARKET_TIME, value=0, unit="s"), MPCVariable(name=glbs.FLEX_EVENT_DURATION, value=0, unit="s") ] config_inputs_appendix: list[MPCVariable] = [ MPCVariable(name="in_provision", value=False), ] weights: list[MPCVariable] = pydantic.Field( default=[], description="Name and value of weights", ) model_config = ConfigDict(json_encoders={MPCVariable: lambda v: v.dict()})
[docs]class NFMPCData(BaseMPCData): """Data class for PF-MPC""" # files and paths results_suffix: str = "_neg_flex.csv" name_of_created_file: str = "neg_flex.json" # modules module_types: dict = cmng.SHADOW_MODULE_TYPE_DICT class_name: str = "NegFlexModel" module_id: str = "NegFlexMPC" # variables power_alias: str = glbs.POWER_ALIAS_NEG stored_energy_alias: str = glbs.STORED_ENERGY_ALIAS_NEG flex_cost_function: str = pydantic.Field( default=None, description="Cost function of the NF-MPC", ) # initialize market parameters with dummy values (0) config_parameters_appendix: list[MPCVariable] = [ MPCVariable(name=glbs.PREP_TIME, value=0, unit="s"), MPCVariable(name=glbs.MARKET_TIME, value=0, unit="s"), MPCVariable(name=glbs.FLEX_EVENT_DURATION, value=0, unit="s") ] config_inputs_appendix: list[MPCVariable] = [ MPCVariable(name="in_provision", value=False), ] weights: list[MPCVariable] = pydantic.Field( default=[], description="Name and value of weights", ) model_config = ConfigDict(json_encoders={MPCVariable: lambda v: v.dict()})