You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pyomo与EnergyPlus协同优化:迭代更新EnergyPlus数值的方法咨询

解决Pyomo优化中EnergyPlus仅调用一次的问题

为啥现在只调用一次?

你当前代码里把室内温度定义成了Expression,Pyomo在构建这个表达式的时候,会用power_w的初始值(5000)调用一次Eplus算出温度,之后优化迭代时变量变了,Pyomo不会自动重新跑Eplus——因为Eplus的温度计算是外部黑箱,不是Pyomo能解析的代数运算,它不知道这个温度值会跟着变量变化。

怎么改才能让它每次迭代都更新温度?

核心是把Eplus的温度计算包装成Pyomo求解器能识别的外部黑箱函数,让求解器每次需要约束值的时候,都主动调用Eplus重新计算温度。下面是修改后的完整代码:

import pyomo.environ as pyo
import numpy as np
import matplotlib.pyplot as plt
from EPlus.model import TemperatureModel
from pyomo.opt import SolverFactory

# 初始化EnergyPlus模型
EPLUS_model = TemperatureModel("C:\\EnergyPlusV9-4-0")

# 创建Pyomo模型
model = pyo.ConcreteModel()

# 时间集合
model.time = pyo.Set(initialize=(range(30, 31 + 1, 30)))

# 优化变量:输入功率
model.power_w = pyo.Var(model.time, within=pyo.NonNegativeReals, bounds=(0, 40000), initialize=5000)

# 定义温度计算函数:输入功率,返回对应室内温度
def get_indoor_temp(power):
    # 调用EnergyPlus模拟,取第一个温度结果
    return EPLUS_model.T(np.zeros(96) + power)[0]

# 把这个函数注册成Pyomo的外部函数,让求解器能识别
model.calculate_temp = pyo.ExternalFunction(get_indoor_temp)

# 温度下限约束:直接用当前功率调用外部函数算温度,确保每次都更新
def temp_limit_rule(model, t):
    return model.calculate_temp(model.power_w[t]) >= 13
model.temp_constraint = pyo.Constraint(model.time, rule=temp_limit_rule)

# 目标函数:最小化总功耗
def minimize_power(model):
    return sum(model.power_w[t] for t in model.time)
model.total_power = pyo.Objective(rule=minimize_power, sense=pyo.minimize)

# 用IPOPT求解,开tee=True能看日志,确认Eplus是不是多次调用了
solver = SolverFactory('ipopt')
result = solver.solve(model, tee=True)

# 提取结果
solved_p = {t: model.power_w[t].value for t in model.time}
solved_t = {t: model.calculate_temp(model.power_w[t]()).value for t in model.time}

print("求解后的功率值:", solved_p)
print("对应的室内温度:", solved_t)

关键改动说明

  • 换掉Expression,用ExternalFunction:把温度计算逻辑包成外部函数后,IPOPT这类求解器在迭代时,每次需要计算约束值,都会调用这个函数,自然就会重新跑Eplus。
  • 直接在约束里调用外部函数:不再通过中间的Expression传递温度,避免Pyomo提前计算后就不再更新。
  • 开启tee看日志:可以在求解过程里看到Eplus是不是被多次调用,方便调试。

额外提醒

如果Eplus模拟很慢,频繁调用会拖慢优化速度,可以试试这两个办法:

  • 加个缓存:只有当功率变化超过某个阈值(比如100W)时,才重新跑Eplus,否则用之前的结果
  • 先搞个代理模型:用响应面、神经网络之类的快速模型替代Eplus做优化,收敛后再用Eplus验证最终结果
  • 梯度问题:IPOPT默认需要梯度信息,如果你的Eplus没法直接输出梯度,可以让IPOPT用有限差分近似梯度,加一行solver.options['finite_diff_rel_step'] = 1e-3就行

内容的提问来源于stack exchange,提问作者Brown

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 09:59:56