DHU_2.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. from copy import deepcopy
  2. import numpy as np
  3. import pandas as pd
  4. import pymc as pm
  5. try:
  6. import plotnine as gg
  7. except:
  8. pass
  9. import psychrolib
  10. psychrolib.SetUnitSystem(psychrolib.SI)
  11. get_Enthalpy = np.vectorize(psychrolib.GetMoistAirEnthalpy)
  12. from .._model._base import BaseModel
  13. from ..components.coil import CoolingCoil,SteamCoilFs,SteamCoilFs2
  14. from ..components.wheel import WheelS3
  15. from ..components.mixed import Mixed
  16. def record(name,var):
  17. pm.Deterministic(f'{name}_mu',var)
  18. def observe(name,var,observed,sigma=1):
  19. mu = pm.Deterministic(f'{name}_mu',var)
  20. sigma = pm.HalfNormal(f'{name}_sigma',sigma=sigma)
  21. pm.Normal(name,mu=mu,sigma=sigma,observed=observed)
  22. class DHU_2(BaseModel):
  23. def __init__(self) -> None:
  24. super().__init__()
  25. def fit(
  26. self,
  27. input_data : pd.DataFrame,
  28. observed_data: pd.DataFrame,
  29. plot_TVP : bool = True
  30. ):
  31. with pm.Model() as self.MODEL_PYMC:
  32. param_prior = {
  33. 'wheel_1' : WheelS3.prior('wheel_1'),
  34. 'wheel_2' : WheelS3.prior('wheel_2'),
  35. 'coil_2' : CoolingCoil.prior('coil_2'),
  36. 'coil_3' : CoolingCoil.prior('coil_3'),
  37. 'steamcoil_1': SteamCoilFs2.prior('steamcoil_1'),
  38. 'steamcoil_2': SteamCoilFs.prior('steamcoil_2'),
  39. 'F_air' : {
  40. 'F_air_F': 12, # 新风
  41. 'F_air_B': pm.TruncatedNormal('F_air_B',mu=25,sigma=1,initval=25,lower=0.1), # 回风
  42. 'F_air_R': pm.TruncatedNormal('F_air_R',mu=36,sigma=1,initval=36,lower=0.1), # 送风
  43. 'F_air_S': pm.TruncatedNormal('F_air_S',mu=3,sigma=1,initval=3,lower=0.1), # 补风
  44. }
  45. }
  46. res = DHU_2.model(
  47. Tin_F = input_data.coil_1_ToutA.values,
  48. Hin_F = input_data.coil_1_HoutA.values,
  49. HzP = None,
  50. HzR = None,
  51. FF_air = param_prior['F_air']['F_air_F'],
  52. FB_air = param_prior['F_air']['F_air_B'],
  53. FR_air = param_prior['F_air']['F_air_R'],
  54. FS_air = param_prior['F_air']['F_air_S'],
  55. coil_1_TinW = input_data.coil_1_TinW.values,
  56. coil_2_TinW = input_data.coil_2_TinW.values,
  57. coil_3_TinW = input_data.coil_3_TinW.values,
  58. coil_1_Val = input_data.coil_1_Val.values / 100,
  59. coil_2_Val = input_data.coil_2_Val.values / 100,
  60. coil_3_Val = input_data.coil_3_Val.values / 100,
  61. wheel_1_TinR = input_data.wheel_1_TinR.values,
  62. wheel_2_TinR = input_data.wheel_2_TinR.values,
  63. mixed_1_TinM = input_data.mixed_1_TinM.values,
  64. mixed_2_TinM = input_data.mixed_2_TinM.values,
  65. mixed_1_HinM = input_data.mixed_1_HinM.values,
  66. mixed_2_HinM = input_data.mixed_2_HinM.values,
  67. engine = 'pymc',
  68. param = param_prior
  69. )
  70. observe('mixed_1_ToutA',res['mixed_1']['ToutA'],observed=observed_data.mixed_1_ToutA.values)
  71. observe('mixed_1_DoutA',res['mixed_1']['DoutA'],observed=observed_data.mixed_1_DoutA.values)
  72. observe('wheel_1_ToutC',res['wheel_1']['ToutC'],observed=observed_data.wheel_1_ToutC.values)
  73. observe('coil_2_ToutA',res['coil_2']['ToutA'],observed=observed_data.coil_2_ToutA.values)
  74. observe('coil_2_DoutA',res['coil_2']['DoutA'],observed=observed_data.coil_2_DoutA.values)
  75. observe('wheel_2_ToutP',res['wheel_2']['ToutP'],observed=observed_data.wheel_2_ToutP.values)
  76. observe('wheel_2_DoutP',res['wheel_2']['DoutP'],observed=observed_data.wheel_2_DoutP.values)
  77. observe('wheel_2_ToutR',res['wheel_2']['ToutR'],observed=observed_data.wheel_2_ToutR.values)
  78. observe('steamcoil_1_FP',res['steamcoil_1']['FP'],observed=observed_data.steamcoil_1_FP.values,sigma=1000)
  79. observe('steamcoil_1_Fs',res['steamcoil_1']['Fs'],observed=observed_data.steamcoil_1_Fs.values,sigma=20)
  80. observe('steamcoil_2_Fs',res['steamcoil_2']['Fs'],observed=observed_data.steamcoil_2_Fs.values,sigma=20)
  81. record('wheel_2_ToutC',res['wheel_2']['ToutC'])
  82. record('mixed_2_ToutA',res['mixed_2']['ToutA'])
  83. param_posterior = pm.find_MAP(maxeval=50000)
  84. param_posterior_reorder = {'F_air':{'F':12}}
  85. for equp_name in param_prior.keys():
  86. param_posterior_reorder.setdefault(equp_name,{})
  87. for param_name,param_value in param_posterior.items():
  88. if '__' in param_name:
  89. continue
  90. if param_name.startswith(equp_name):
  91. param_name_adj = param_name.replace(f'{equp_name}_','')
  92. param_posterior_reorder[equp_name][param_name_adj] = param_value
  93. if plot_TVP:
  94. TVP_data = []
  95. for param_name in param_posterior.keys():
  96. if param_name.replace('_mu','') not in observed_data.columns:
  97. continue
  98. TVP_data.append(
  99. pd.DataFrame(
  100. {
  101. 'param_name': param_name.replace('_mu',''),
  102. 'real' : observed_data.loc[:,param_name.replace('_mu','')].values,
  103. 'pred' : param_posterior[param_name]
  104. }
  105. )
  106. )
  107. gg.options.figure_size = (10,10)
  108. plot = (
  109. pd.concat(TVP_data,axis=0)
  110. .pipe(gg.ggplot)
  111. + gg.aes(x='real',y='pred')
  112. + gg.geom_point()
  113. + gg.facet_wrap(facets='param_name',scales='free')
  114. + gg.geom_abline(intercept=0,slope=1,color='red')
  115. )
  116. plot.show()
  117. self.record_model(
  118. model_name = 'DHU',
  119. model = param_posterior_reorder,
  120. train_data = {'x':np.array([1])},
  121. train_metric = {'R2':1,'MAE':1,'MAPE':1}
  122. )
  123. return self
  124. def predict(self,input_data:pd.DataFrame) -> dict:
  125. param_posterior = self.model_info['model_DHU']
  126. res = DHU_2.model(
  127. Tin_F = input_data.coil_1_ToutA.values,
  128. Hin_F = input_data.coil_1_HoutA.values,
  129. HzP = None,
  130. HzR = None,
  131. FF_air = param_posterior['F_air']['F'],
  132. FB_air = param_posterior['F_air']['B'],
  133. FR_air = param_posterior['F_air']['R'],
  134. FS_air = param_posterior['F_air']['S'],
  135. coil_1_TinW = input_data.coil_1_TinW.values,
  136. coil_2_TinW = input_data.coil_2_TinW.values,
  137. coil_3_TinW = input_data.coil_3_TinW.values,
  138. coil_1_Val = input_data.coil_1_Val.values / 100,
  139. coil_2_Val = input_data.coil_2_Val.values / 100,
  140. coil_3_Val = input_data.coil_3_Val.values / 100,
  141. wheel_1_TinR = input_data.wheel_1_TinR.values,
  142. wheel_2_TinR = input_data.wheel_2_TinR.values,
  143. mixed_1_TinM = input_data.mixed_1_TinM.values,
  144. mixed_2_TinM = input_data.mixed_2_TinM.values,
  145. mixed_1_HinM = input_data.mixed_1_HinM.values,
  146. mixed_2_HinM = input_data.mixed_2_HinM.values,
  147. engine = 'numpy',
  148. param = param_posterior
  149. )
  150. return res
  151. def predict_system(self,input_data:pd.DataFrame) -> pd.DataFrame:
  152. pred_res = self.predict(input_data)
  153. system_output = {}
  154. for equp_name,output_info in pred_res.items():
  155. for output_name,output_value in output_info.items():
  156. system_output[f'{equp_name}_{output_name}'] = output_value
  157. system_output = pd.DataFrame(system_output)
  158. system_output['Fs'] = system_output.steamcoil_1_Fs + system_output.steamcoil_2_Fs
  159. return system_output
  160. @classmethod
  161. def model(
  162. cls,
  163. Tin_F, # 前表冷后温度
  164. Hin_F, # 前表冷后湿度
  165. HzP, # 处理侧风机频率
  166. HzR, # 再生侧风机频率
  167. FF_air,
  168. FB_air,
  169. FR_air,
  170. FS_air,
  171. coil_1_TinW, # 前表冷进水温度
  172. coil_2_TinW, # 中表冷进水温度
  173. coil_3_TinW, # 后表冷进水温度
  174. coil_1_Val, # 前表冷阀门开度
  175. coil_2_Val, # 中表冷阀门开度
  176. coil_3_Val, # 后表冷阀门开度
  177. wheel_1_TinR, # 前转轮再生侧温度
  178. wheel_2_TinR, # 后转轮再生侧温度
  179. mixed_1_TinM, # 回风温度(处理侧)
  180. mixed_1_HinM, # 回风湿度(处理侧)
  181. mixed_2_TinM, # 补风温度(再生侧)
  182. mixed_2_HinM, # 补风湿度(再生侧)
  183. engine,
  184. param
  185. ) -> dict:
  186. # 空气的质量流量
  187. # FF_air = 12 # 新风
  188. # FB_air = pm.TruncatedNormal('FB_air',mu=25,sigma=1,initval=25,lower=0.1) # 回风
  189. # FR_air = pm.TruncatedNormal('FR_air',mu=36,sigma=1,initval=36,lower=0.1) # 送风
  190. # FS_air = pm.TruncatedNormal('FS_air',mu=3,sigma=1,initval=3,lower=0.1) # 补风
  191. FO_air = FF_air + FB_air + FS_air - FR_air # 排风
  192. # 水的质量流量
  193. coil_2_FW = coil_2_Val
  194. coil_3_FW = coil_3_Val
  195. # 前转轮
  196. wheel_1_res = WheelS3.model(
  197. TinP = Tin_F,
  198. HinP = Hin_F,
  199. FP = FR_air - FB_air,
  200. TinR = wheel_1_TinR,
  201. HinR = 0,
  202. FR = FO_air,
  203. TinC = Tin_F,
  204. HinC = Hin_F,
  205. FC = FF_air+FB_air-FR_air,
  206. engine = engine,
  207. param = param['wheel_1']
  208. )
  209. # 处理侧混风(回风)
  210. mixed_1_res = Mixed.model(
  211. TinA = wheel_1_res['ToutP'],
  212. HinA = wheel_1_res['HoutP'],
  213. FA = FR_air - FB_air,
  214. TinM = mixed_1_TinM,
  215. HinM = mixed_1_HinM,
  216. FM = FB_air,
  217. engine = engine
  218. )
  219. # 中表冷
  220. coil_2_res = CoolingCoil.model(
  221. TinA = mixed_1_res['ToutA'],
  222. HinA = mixed_1_res['HoutA'],
  223. FA = FR_air,
  224. TinW = coil_2_TinW,
  225. FW = coil_2_FW,
  226. engine = engine,
  227. param = param['coil_2']
  228. )
  229. # 后转轮
  230. wheel_2_res = WheelS3.model(
  231. TinP = coil_2_res['ToutA'],
  232. HinP = coil_2_res['HoutA'],
  233. FP = FR_air,
  234. TinC = wheel_1_res['ToutC'],
  235. HinC = wheel_1_res['HoutC'],
  236. FC = FF_air+FB_air-FR_air,
  237. TinR = wheel_2_TinR,
  238. HinR = 0,
  239. FR = FO_air-FS_air,
  240. engine = engine,
  241. param = param['wheel_2'],
  242. )
  243. # 后表冷
  244. coil_3_res = CoolingCoil.model(
  245. TinA = wheel_2_res['ToutP'],
  246. HinA = wheel_2_res['HoutP'],
  247. FA = FR_air,
  248. TinW = coil_3_TinW,
  249. FW = coil_3_FW,
  250. engine = engine,
  251. param = param['coil_3']
  252. )
  253. # 后转轮湿度修正
  254. wheel_2_res_adj = WheelS3.model(
  255. TinP = coil_2_res['ToutA'],
  256. HinP = coil_2_res['HoutA'],
  257. FP = FR_air,
  258. TinC = wheel_1_res['ToutC'],
  259. HinC = wheel_1_res['HoutC'],
  260. FC = FF_air+FB_air-FR_air,
  261. TinR = wheel_2_TinR,
  262. HinR = wheel_2_res['HoutC'],
  263. FR = FO_air-FS_air,
  264. engine = engine,
  265. param = param['wheel_2'],
  266. )
  267. # 再生侧混风(排风)
  268. mixed_2_res = Mixed.model(
  269. TinA = wheel_2_res_adj['ToutR'],
  270. HinA = wheel_2_res_adj['HoutR'],
  271. FA = FO_air-FS_air,
  272. TinM = mixed_2_TinM,
  273. HinM = mixed_2_HinM,
  274. FM = FS_air,
  275. engine = engine
  276. )
  277. # 前转轮湿度修正
  278. wheel_1_res_adj = WheelS3.model(
  279. TinP = Tin_F,
  280. HinP = Hin_F,
  281. FP = FR_air - FB_air,
  282. TinR = wheel_1_TinR,
  283. HinR = mixed_2_res['HoutA'],
  284. FR = FO_air,
  285. TinC = Tin_F,
  286. HinC = Hin_F,
  287. FC = FF_air+FB_air-FR_air,
  288. engine = engine,
  289. param = param['wheel_1']
  290. )
  291. # 前蒸气盘管
  292. steamcoil_1_res = SteamCoilFs2.model(
  293. TinA = mixed_2_res['ToutA'],
  294. ToutA = wheel_1_TinR,
  295. FA = FO_air,
  296. param = param['steamcoil_1'],
  297. engine = engine
  298. )
  299. # 后蒸气盘管
  300. steamcoil_2_res = SteamCoilFs.model(
  301. TinA = wheel_2_res_adj['ToutC'],
  302. ToutA = wheel_2_TinR,
  303. FA = FO_air-FS_air,
  304. param = param['steamcoil_2'],
  305. engine = engine
  306. )
  307. return {
  308. 'coil_2' : coil_2_res,
  309. 'coil_3' : coil_3_res,
  310. 'wheel_1' : wheel_1_res_adj,
  311. 'wheel_2' : wheel_2_res_adj,
  312. 'mixed_1' : mixed_1_res,
  313. 'mixed_2' : mixed_2_res,
  314. 'steamcoil_1': steamcoil_1_res,
  315. 'steamcoil_2': steamcoil_2_res,
  316. 'F_air' : {
  317. 'FF_air': FF_air,
  318. 'FB_air': FB_air,
  319. 'FR_air': FR_air,
  320. 'FS_air': FS_air,
  321. 'FO_air': FO_air
  322. },
  323. 'summary':{}
  324. }