Coverage for agentlib_flexquant/data_structures/mpcs.py: 100%

67 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2025-10-20 14:09 +0000

1""" 

2Data models for MPC configurations in flexibility quantification. 

3 

4This module defines Pydantic data models that encapsulate configuration parameters 

5for baseline, positive flexibility, and negative flexibility MPC controllers used 

6in flexquant. The models handle file paths, module configurations, variable 

7mappings, and optimization weights for MPC implementations. 

8""" 

9import pydantic 

10from agentlib_mpc.data_structures.mpc_datamodels import MPCVariable 

11from pydantic import ConfigDict, model_validator 

12 

13import agentlib_flexquant.data_structures.globals as glbs 

14import agentlib_flexquant.utils.config_management as cmng 

15 

16 

17class BaseMPCData(pydantic.BaseModel): 

18 """Base class containing necessary data for the code creation of the different mpcs""" 

19 

20 # files and paths 

21 created_flex_mpcs_file: str = "flex_agents.py" 

22 name_of_created_file: str 

23 results_suffix: str 

24 # modules 

25 module_types: dict 

26 class_name: str 

27 module_id: str 

28 # variables 

29 power_alias: str 

30 stored_energy_alias: str 

31 config_inputs_appendix: list[MPCVariable] = [] 

32 config_parameters_appendix: list[MPCVariable] = [] 

33 weights: list[MPCVariable] = pydantic.Field( 

34 default=[], description="Name and value of weights", 

35 ) 

36 model_config = ConfigDict(json_encoders={MPCVariable: lambda v: v.dict()}) 

37 

38 

39class BaselineMPCData(BaseMPCData): 

40 """Data class for Baseline MPC""" 

41 

42 # files and paths 

43 results_suffix: str = "_base.csv" 

44 name_of_created_file: str = "baseline.json" 

45 # modules 

46 module_types: dict = cmng.BASELINE_MODULE_TYPE_DICT 

47 class_name: str = "BaselineMPCModel" 

48 module_id: str = "Baseline" 

49 # variables 

50 power_alias: str = glbs.POWER_ALIAS_BASE 

51 stored_energy_alias: str = glbs.STORED_ENERGY_ALIAS_BASE 

52 power_variable: str = pydantic.Field( 

53 default="P_el", 

54 description=( 

55 "Name of the variable representing the electrical power in the baseline config" 

56 ), 

57 ) 

58 profile_deviation_weight: float = pydantic.Field( 

59 default=0, 

60 description="Weight of soft constraint for deviation from accepted flexible profile", 

61 ) 

62 power_unit: str = pydantic.Field( 

63 default="kW", description="Unit of the power variable" 

64 ) 

65 comfort_variable: str = pydantic.Field( 

66 default=None, 

67 description=( 

68 "Name of the slack variable representing the thermal comfort in the baseline config" 

69 ), 

70 ) 

71 profile_comfort_weight: float = pydantic.Field( 

72 default=1, description="Weight of soft constraint for discomfort", 

73 ) 

74 config_inputs_appendix: list[MPCVariable] = [ 

75 MPCVariable(name="_P_external", value=0, unit="W"), 

76 MPCVariable(name="in_provision", value=False), 

77 MPCVariable(name="rel_start", value=0, unit="s"), 

78 MPCVariable(name="rel_end", value=0, unit="s"), 

79 ] 

80 

81 config_parameters_appendix: list[MPCVariable] = [] 

82 

83 weights: list[MPCVariable] = pydantic.Field( 

84 default=[], description="Name and value of weights", 

85 ) 

86 model_config = ConfigDict(json_encoders={MPCVariable: lambda v: v.dict()}) 

87 

88 @model_validator(mode="after") 

89 def update_config_parameters_appendix(self) -> "BaselineMPCData": 

90 """Update the config parameters appendix with profile deviation and comfort weights. 

91 

92 Adds the profile deviation weight parameter and optionally the profile comfort 

93 weight parameter (if comfort_variable is enabled) to the config_parameters_appendix 

94 list as MPCVariable instances. 

95 """ 

96 self.config_parameters_appendix = [ 

97 MPCVariable( 

98 name=glbs.PROFILE_DEVIATION_WEIGHT, 

99 value=self.profile_deviation_weight, 

100 unit="-", 

101 description=( 

102 "Weight of soft constraint for deviation from accepted flexible profile" 

103 ), 

104 ) 

105 ] 

106 if self.comfort_variable: 

107 self.config_parameters_appendix.append( 

108 MPCVariable( 

109 name=glbs.PROFILE_COMFORT_WEIGHT, 

110 value=self.profile_comfort_weight, 

111 unit="-", 

112 description="Weight of soft constraint for discomfort", 

113 ) 

114 ) 

115 return self 

116 

117 

118class PFMPCData(BaseMPCData): 

119 """Data class for PF-MPC""" 

120 

121 # files and paths 

122 results_suffix: str = "_pos_flex.csv" 

123 name_of_created_file: str = "pos_flex.json" 

124 # modules 

125 module_types: dict = cmng.SHADOW_MODULE_TYPE_DICT 

126 class_name: str = "PosFlexModel" 

127 module_id: str = "PosFlexMPC" 

128 # variables 

129 power_alias: str = glbs.POWER_ALIAS_POS 

130 stored_energy_alias: str = glbs.STORED_ENERGY_ALIAS_POS 

131 flex_cost_function: str = pydantic.Field( 

132 default=None, description="Cost function of the PF-MPC", 

133 ) 

134 # initialize market parameters with dummy values (0) 

135 config_parameters_appendix: list[MPCVariable] = [ 

136 MPCVariable(name=glbs.PREP_TIME, value=0, unit="s"), 

137 MPCVariable(name=glbs.MARKET_TIME, value=0, unit="s"), 

138 MPCVariable(name=glbs.FLEX_EVENT_DURATION, value=0, unit="s") 

139 ] 

140 config_inputs_appendix: list[MPCVariable] = [ 

141 MPCVariable(name="in_provision", value=False), 

142 ] 

143 weights: list[MPCVariable] = pydantic.Field( 

144 default=[], description="Name and value of weights", 

145 ) 

146 model_config = ConfigDict(json_encoders={MPCVariable: lambda v: v.dict()}) 

147 

148 

149class NFMPCData(BaseMPCData): 

150 """Data class for PF-MPC""" 

151 

152 # files and paths 

153 results_suffix: str = "_neg_flex.csv" 

154 name_of_created_file: str = "neg_flex.json" 

155 # modules 

156 module_types: dict = cmng.SHADOW_MODULE_TYPE_DICT 

157 class_name: str = "NegFlexModel" 

158 module_id: str = "NegFlexMPC" 

159 # variables 

160 power_alias: str = glbs.POWER_ALIAS_NEG 

161 stored_energy_alias: str = glbs.STORED_ENERGY_ALIAS_NEG 

162 flex_cost_function: str = pydantic.Field( 

163 default=None, description="Cost function of the NF-MPC", 

164 ) 

165 # initialize market parameters with dummy values (0) 

166 config_parameters_appendix: list[MPCVariable] = [ 

167 MPCVariable(name=glbs.PREP_TIME, value=0, unit="s"), 

168 MPCVariable(name=glbs.MARKET_TIME, value=0, unit="s"), 

169 MPCVariable(name=glbs.FLEX_EVENT_DURATION, value=0, unit="s") 

170 ] 

171 config_inputs_appendix: list[MPCVariable] = [ 

172 MPCVariable(name="in_provision", value=False), 

173 ] 

174 weights: list[MPCVariable] = pydantic.Field( 

175 default=[], description="Name and value of weights", 

176 ) 

177 model_config = ConfigDict(json_encoders={MPCVariable: lambda v: v.dict()})