1. 项目概述:微电网经济调度的核心挑战
微电网经济调度是电力系统领域一个经典而复杂的优化问题。不同于传统电网,微电网需要协调分布式电源(如光伏、风机)、储能系统和负荷需求,在满足运行约束的前提下实现发电成本最小化。这个看似简单的目标背后,隐藏着诸多技术难点:
- 多时间尺度耦合:调度决策需要同时考虑分钟级、小时级甚至日级的功率平衡
- 非线性约束处理:机组爬坡率、储能充放电效率等约束往往呈现非线性特性
- 不确定性管理:可再生能源出力和负荷需求都存在预测误差
- 混合整数规划:机组启停状态引入离散变量,大幅增加求解难度
我最近用Python+Pyomo完整实现了这一优化过程,过程中踩过不少坑,也积累了一些实战经验。本文将手把手展示从问题建模到代码实现的完整流程,特别适合电力系统优化方向的初学者参考。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 问题建模与数学表达
2.1 基础模型构建
典型的微电网经济调度模型包含以下核心要素:
决策变量:
- P_g(t):第t时段常规机组发电功率
- u_g(t):第t时段机组启停状态(0/1变量)
- P_b(t):第t时段储能充放电功率(正为放电)
- E_b(t):第t时段储能剩余电量
目标函数:
最小化总运行成本:
code复制min Σ[C_f(P_g(t)) + C_su·u_g(t) + C_sd·(1-u_g(t-1))·u_g(t)]
其中C_f为燃料成本函数,通常为二次函数;C_su/C_sd分别为启停成本
主要约束条件:
- 功率平衡:
code复制P_g(t) + P_r(t) + P_b(t) = D(t)
- 机组运行约束:
code复制P_g_min·u_g(t) ≤ P_g(t) ≤ P_g_max·u_g(t)
|P_g(t) - P_g(t-1)| ≤ R·Δt
- 储能系统约束:
code复制E_b(t) = E_b(t-1) - (P_b(t)/η)·Δt
E_b_min ≤ E_b(t) ≤ E_b_max
|P_b(t)| ≤ P_b_max
2.2 模型线性化技巧
实际编程时需要特别注意两个非线性环节的处理:
燃料成本线性化:
将二次成本函数分段线性化,引入辅助变量λ_k和决策变量P_gk:
code复制C_f(P_g) ≈ Σ[λ_k·P_gk]
P_g = ΣP_gk
0 ≤ P_gk ≤ P_gk_max
储能效率处理:
充放电效率η通常不同,建议拆分为两个变量:
code复制P_b = P_bc - P_bd
E_b(t) = E_b(t-1) - (P_bc/η_c - P_bd·η_d)·Δt
3. Pyomo实现详解
3.1 环境配置与数据准备
建议使用Anaconda创建专用环境:
bash复制conda create -n microgrid python=3.8
conda activate microgrid
pip install pyomo glpk pandas numpy matplotlib
输入数据建议采用CSV格式存储,典型数据结构:
python复制# load_data.py
def load_case(case_file):
data = {
'time_step': 1.0, # 小时
'gen': {
'Pmax': 200, 'Pmin': 50,
'cost': [100, 0.5, 0.01], # 二次成本系数
'ramp': 100, # MW/h
'su_cost': 500, 'sd_cost': 300
},
'battery': {
'capacity': 300, # MWh
'Pmax': 100, # MW
'eff_ch': 0.95, 'eff_dis': 0.97,
'SOC_min': 0.2, 'SOC_max': 0.9
},
'load': pd.read_csv('load_profile.csv'),
'renewable': pd.read_csv('pv_generation.csv')
}
return data
3.2 模型构建核心代码
python复制# economic_dispatch.py
from pyomo.environ import *
def build_model(data):
model = ConcreteModel()
# 时间集合
T = len(data['load'])
model.T = Set(initialize=range(T))
# 变量定义
model.Pg = Var(model.T, bounds=(0, data['gen']['Pmax']))
model.Ug = Var(model.T, within=Binary)
model.Pb = Var(model.T, bounds=(-data['battery']['Pmax'], data['battery']['Pmax']))
model.Eb = Var(model.T, bounds=(
data['battery']['SOC_min']*data['battery']['capacity'],
data['battery']['SOC_max']*data['battery']['capacity']
))
# 目标函数
def obj_rule(m):
return sum(
data['gen']['cost'][0]*m.Ug[t] +
data['gen']['cost'][1]*m.Pg[t] +
data['gen']['cost'][2]*m.Pg[t]**2 +
data['gen']['su_cost']*(m.Ug[t] - m.Ug[t-1]) if t>0 else 0
for t in m.T
)
model.obj = Objective(rule=obj_rule, sense=minimize)
# 约束条件
def power_balance(m, t):
return m.Pg[t] + data['renewable'][t] + m.Pb[t] == data['load'][t]
model.power_balance = Constraint(model.T, rule=power_balance)
def ramp_limit(m, t):
if t == 0: return Constraint.Skip
return -data['gen']['ramp'] <= m.Pg[t] - m.Pg[t-1] <= data['gen']['ramp']
model.ramp_limit = Constraint(model.T, rule=ramp_limit)
def battery_soc(m, t):
if t == 0:
return m.Eb[t] == 0.5*data['battery']['capacity']
charge = m.Pb[t] if m.Pb[t] < 0 else 0
discharge = m.Pb[t] if m.Pb[t] > 0 else 0
return m.Eb[t] == m.Eb[t-1] - (
charge/data['battery']['eff_ch'] +
discharge*data['battery']['eff_dis']
)*data['time_step']
model.battery_soc = Constraint(model.T, rule=battery_soc)
return model
3.3 求解与结果分析
python复制def solve_model(model):
solver = SolverFactory('glpk') # 也可用cplex、gurobi等商业求解器
results = solver.solve(model)
return model, results
def visualize_results(model, data):
import matplotlib.pyplot as plt
Pg = [value(model.Pg[t]) for t in model.T]
Pb = [value(model.Pb[t]) for t in model.T]
load = data['load']
renewable = data['renewable']
plt.figure(figsize=(12,6))
plt.stackplot(range(len(load)),
renewable, Pg, Pb,
labels=['可再生能源','常规机组','储能'])
plt.plot(load, 'k--', label='总负荷')
plt.legend()
plt.xlabel('时间(h)')
plt.ylabel('功率(MW)')
plt.show()
4. 实战经验与避坑指南
4.1 常见报错与解决方法
问题1:求解器报"infeasible"错误
- 检查功率平衡约束是否严格相等,建议改为不等式并添加松弛变量
- 验证储能SOC初值是否在合理范围内
- 检查机组爬坡率约束是否过严
问题2:求解时间过长
- 尝试线性化所有非线性项
- 对于24小时以上调度,考虑使用滚动优化
- 商业求解器(cplex/gurobi)比开源求解器(glpk)快10-100倍
问题3:结果不符合物理直觉
- 检查所有变量的上下界设置
- 验证成本系数单位是否一致(¥/MW vs ¥/kWh)
- 绘制各变量时序图观察异常点
4.2 性能优化技巧
- 热启动策略:
python复制# 使用前一时段解作为初始值
for t in model.T:
if t > 0:
model.Pg[t].value = value(model.Pg[t-1])
model.Ug[t].value = value(model.Ug[t-1])
- 分段线性化进阶实现:
python复制# 在模型中添加分段线性化约束
model.num_segments = 5
segment_width = data['gen']['Pmax']/model.num_segments
model.lambda = Var(model.T, range(model.num_segments), bounds=(0,1))
def segment_cons(m, t):
return m.Pg[t] == sum(m.lambda[t,k]*k*segment_width for k in range(m.num_segments))
model.segment_cons = Constraint(model.T, rule=segment_cons)
- 并行计算配置:
python复制solver.options['threads'] = 4 # 使用多线程求解
5. 扩展应用与进阶方向
5.1 考虑不确定性的鲁棒优化
python复制# 在目标函数中加入惩罚项
def obj_robust_rule(m):
base_cost = ... # 原目标函数
penalty = sum( m.Pb[t]**2 for t in m.T ) * 0.1 # 抑制储能频繁充放电
return base_cost + penalty
5.2 多微电网协同调度
需要新增变量:
- 微电网间联络线功率P_ex(t)
- 交易价格λ(t)
新增约束:
code复制# 功率平衡修正
Pg_i(t) + Pb_i(t) + P_ex_i(t) = D_i(t)
# 联络线功率平衡
ΣP_ex_i(t) = 0
5.3 与MATLAB的混合编程
python复制# 使用matlab.engine调用MATLAB优化工具箱
import matlab.engine
eng = matlab.engine.start_matlab()
result = eng.fmincon(...) # 调用MATLAB求解器
实现过程中我最大的体会是:电力系统优化问题90%的工作在于正确建模和数据处理,代码实现反而相对直接。建议新手先从简单案例入手,逐步增加复杂度,同时养成绘制变量曲线验证结果的好习惯。
