Files
multi_energy_complementarity/test_storage_optimization.py
2025-12-25 18:06:12 +08:00

362 lines
14 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 多能互补系统储能容量优化计算程序测试用例
# 该文件包含单元测试和验证测试,确保程序在各种场景下的正确性。
# 作者: iFlow CLI
# 创建日期: 2025-12-25
import unittest
import numpy as np
from storage_optimization import (
optimize_storage_capacity,
validate_inputs,
calculate_energy_balance,
check_constraints,
SystemParameters
)
class TestStorageOptimization(unittest.TestCase):
"""储能优化程序测试类"""
def setUp(self):
"""测试前的准备工作"""
# 基础测试数据
self.solar_output = [0.0] * 6 + [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0, 0.0] + [0.0] * 6
self.wind_output = [2.0, 3.0, 4.0, 3.0, 2.0, 1.0] * 4
self.thermal_output = [5.0] * 24
self.load_demand = [3.0, 4.0, 5.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 18.0, 20.0, 18.0,
16.0, 14.0, 12.0, 10.0, 8.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0, 2.0]
self.params = SystemParameters(
max_curtailment_wind=0.1,
max_curtailment_solar=0.1,
max_grid_ratio=0.2,
storage_efficiency=0.9,
discharge_rate=1.0,
charge_rate=1.0
)
def test_validate_inputs_valid_data(self):
"""测试有效输入数据的验证"""
# 应该不抛出异常
validate_inputs(self.solar_output, self.wind_output, self.thermal_output,
self.load_demand, self.params)
def test_validate_inputs_invalid_length(self):
"""测试无效长度的输入数据"""
with self.assertRaises(ValueError):
validate_inputs([1.0] * 23, self.wind_output, self.thermal_output,
self.load_demand, self.params)
def test_validate_inputs_negative_values(self):
"""测试包含负值的输入数据"""
with self.assertRaises(ValueError):
validate_inputs([-1.0] + self.solar_output[1:], self.wind_output,
self.thermal_output, self.load_demand, self.params)
def test_validate_inputs_invalid_parameters(self):
"""测试无效的参数设置"""
invalid_params = SystemParameters(max_curtailment_wind=1.5) # 超出范围
with self.assertRaises(ValueError):
validate_inputs(self.solar_output, self.wind_output, self.thermal_output,
self.load_demand, invalid_params)
def test_calculate_energy_balance_basic(self):
"""测试基本电能平衡计算"""
result = calculate_energy_balance(
self.solar_output, self.wind_output, self.thermal_output,
self.load_demand, self.params, 10.0
)
# 检查返回结果包含所有必要的键
expected_keys = ['storage_profile', 'charge_profile', 'discharge_profile',
'curtailed_wind', 'curtailed_solar', 'grid_feed_in']
for key in expected_keys:
self.assertIn(key, result)
self.assertEqual(len(result[key]), 24)
# 检查储能状态不为负
self.assertTrue(all(soc >= 0 for soc in result['storage_profile']))
def test_check_constraints(self):
"""测试约束条件检查"""
# 先计算平衡结果
balance_result = calculate_energy_balance(
self.solar_output, self.wind_output, self.thermal_output,
self.load_demand, self.params, 10.0
)
# 检查约束
constraint_results = check_constraints(
self.solar_output, self.wind_output, self.thermal_output, balance_result, self.params
)
# 检查返回结果
expected_keys = ['total_curtailment_wind_ratio', 'total_curtailment_solar_ratio',
'total_grid_feed_in_ratio']
for key in expected_keys:
self.assertIn(key, constraint_results)
self.assertGreaterEqual(constraint_results[key], 0)
self.assertLessEqual(constraint_results[key], 1.0)
def test_optimize_storage_capacity_basic(self):
"""测试基本储能容量优化"""
result = optimize_storage_capacity(
self.solar_output, self.wind_output, self.thermal_output,
self.load_demand, self.params
)
# 检查返回结果结构
expected_keys = [
'required_storage_capacity', 'storage_profile', 'charge_profile',
'discharge_profile', 'curtailed_wind', 'curtailed_solar',
'grid_feed_in', 'total_curtailment_wind_ratio',
'total_curtailment_solar_ratio', 'total_grid_feed_in_ratio',
'energy_balance_check'
]
for key in expected_keys:
self.assertIn(key, result)
# 检查数值合理性
self.assertGreaterEqual(result['required_storage_capacity'], 0)
self.assertTrue(result['energy_balance_check'])
def test_zero_curtailment_scenario(self):
"""测试零弃风弃光场景"""
zero_curtail_params = SystemParameters(
max_curtailment_wind=0.0,
max_curtailment_solar=0.0,
max_grid_ratio=0.2,
storage_efficiency=0.9
)
result = optimize_storage_capacity(
self.solar_output, self.wind_output, self.thermal_output,
self.load_demand, zero_curtail_params
)
# 检查弃风弃光率是否为0
self.assertEqual(result['total_curtailment_wind_ratio'], 0.0)
self.assertEqual(result['total_curtailment_solar_ratio'], 0.0)
def test_high_grid_ratio_scenario(self):
"""测试高上网电量比例场景"""
high_grid_params = SystemParameters(
max_curtailment_wind=0.1,
max_curtailment_solar=0.1,
max_grid_ratio=0.5, # 高上网电量比例
storage_efficiency=0.9
)
result = optimize_storage_capacity(
self.solar_output, self.wind_output, self.thermal_output,
self.load_demand, high_grid_params
)
# 检查上网电量比例是否在约束范围内
self.assertLessEqual(result['total_grid_feed_in_ratio'], 0.5)
def test_energy_balance_verification(self):
"""测试能量平衡验证"""
result = optimize_storage_capacity(
self.solar_output, self.wind_output, self.thermal_output,
self.load_demand, self.params
)
# 手动验证能量平衡(使用新的计算方法)
total_generation = sum(self.thermal_output) + sum(self.wind_output) + sum(self.solar_output)
total_consumption = sum(self.load_demand)
total_curtailed = sum(result['curtailed_wind']) + sum(result['curtailed_solar'])
total_grid = sum(result['grid_feed_in'])
total_charge = sum(result['charge_profile'])
total_discharge = sum(result['discharge_profile'])
# 新的能量平衡计算:考虑储能效率
energy_from_storage = total_discharge / self.params.storage_efficiency
energy_to_storage = total_charge * self.params.storage_efficiency
energy_balance = total_generation + energy_from_storage - total_consumption - energy_to_storage - total_curtailed - total_grid
# 能量平衡误差应该在合理范围内(考虑储能效率损失)
tolerance = max(10.0, total_generation * 0.15)
self.assertLessEqual(abs(energy_balance), tolerance)
def test_extreme_high_load_scenario(self):
"""测试极高负荷场景"""
high_load = [50.0] * 24 # 极高负荷
result = optimize_storage_capacity(
self.solar_output, self.wind_output, self.thermal_output,
high_load, self.params
)
# 应该返回一个结果,即使系统可能不平衡
self.assertIsNotNone(result)
self.assertGreater(result['required_storage_capacity'], 0)
def test_extreme_low_load_scenario(self):
"""测试极低负荷场景"""
low_load = [0.1] * 24 # 极低负荷
result = optimize_storage_capacity(
self.solar_output, self.wind_output, self.thermal_output,
low_load, self.params
)
# 应该返回一个结果,可能有大量弃风弃光
self.assertIsNotNone(result)
self.assertGreaterEqual(result['total_curtailment_wind_ratio'], 0)
self.assertGreaterEqual(result['total_curtailment_solar_ratio'], 0)
class TestKnownScenarios(unittest.TestCase):
"""已知场景测试类"""
def test_perfect_balance_scenario(self):
"""测试完美平衡场景"""
# 设计一个完美平衡的场景
solar = [2.0] * 6 + [4.0] * 6 + [2.0] * 6 + [0.0] * 6 # 48 MW
wind = [3.0] * 12 + [1.0] * 12 # 48 MW
thermal = [6.0] * 24 # 144 MW (增加了1 MW每小时)
load = [10.0] * 24 # 恒定负荷 240 MW
# 总发电量: 48 + 48 + 144 = 240 MW与负荷平衡
params = SystemParameters(
max_curtailment_wind=0.1,
max_curtailment_solar=0.1,
max_grid_ratio=0.2,
storage_efficiency=0.9
)
result = optimize_storage_capacity(solar, wind, thermal, load, params)
# 验证结果
self.assertTrue(result['energy_balance_check'])
self.assertLessEqual(result['total_curtailment_wind_ratio'], params.max_curtailment_wind)
self.assertLessEqual(result['total_curtailment_solar_ratio'], params.max_curtailment_solar)
self.assertLessEqual(result['total_grid_feed_in_ratio'], params.max_grid_ratio)
def test_no_renewable_scenario(self):
"""测试无可再生能源场景"""
solar = [0.0] * 24
wind = [0.0] * 24
thermal = [10.0] * 24
load = [8.0] * 24
params = SystemParameters(
max_curtailment_wind=0.1,
max_curtailment_solar=0.1,
max_grid_ratio=0.2,
storage_efficiency=0.9
)
result = optimize_storage_capacity(solar, wind, thermal, load, params)
# 验证结果
self.assertTrue(result['energy_balance_check'])
self.assertEqual(result['total_curtailment_wind_ratio'], 0.0)
self.assertEqual(result['total_curtailment_solar_ratio'], 0.0)
self.assertGreaterEqual(result['total_grid_feed_in_ratio'], 0)
def run_performance_test():
"""运行性能测试"""
print("\n=== 性能测试 ===")
# 生成随机测试数据
np.random.seed(42)
solar = np.random.exponential(3, 24).tolist()
wind = np.random.exponential(2, 24).tolist()
thermal = np.random.uniform(3, 8, 24).tolist()
load = np.random.uniform(5, 15, 24).tolist()
params = SystemParameters()
import time
start_time = time.time()
result = optimize_storage_capacity(solar, wind, thermal, load, params)
end_time = time.time()
execution_time = end_time - start_time
print(f"执行时间: {execution_time:.4f}")
print(f"所需储能容量: {result['required_storage_capacity']:.2f} MWh")
print(f"能量平衡校验: {'通过' if result['energy_balance_check'] else '未通过'}")
class TestYearlyData(unittest.TestCase):
"""8760小时数据测试类"""
def setUp(self):
"""测试前的准备工作"""
# 生成简化的8760小时测试数据每小时的重复模式
daily_pattern = [3.0, 4.0, 5.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 18.0, 20.0, 18.0,
16.0, 14.0, 12.0, 10.0, 8.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0, 2.0]
self.yearly_load = daily_pattern * 365 # 24 * 365 = 8760
# 简化的发电数据
daily_solar = [0.0] * 6 + [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0, 0.0] + [0.0] * 6
daily_wind = [2.0, 3.0, 4.0, 3.0, 2.0, 1.0] * 4
daily_thermal = [5.0] * 24
self.yearly_solar = daily_solar * 365
self.yearly_wind = daily_wind * 365
self.yearly_thermal = daily_thermal * 365
self.params = SystemParameters(
max_curtailment_wind=0.1,
max_curtailment_solar=0.1,
max_grid_ratio=0.2,
storage_efficiency=0.9,
discharge_rate=1.0,
charge_rate=1.0
)
def test_yearly_data_validation(self):
"""测试8760小时数据验证"""
# 验证数据长度
self.assertEqual(len(self.yearly_solar), 8760)
self.assertEqual(len(self.yearly_wind), 8760)
self.assertEqual(len(self.yearly_thermal), 8760)
self.assertEqual(len(self.yearly_load), 8760)
# 验证不会抛出异常
validate_inputs(self.yearly_solar, self.yearly_wind, self.yearly_thermal,
self.yearly_load, self.params)
def test_yearly_basic_optimization(self):
"""测试8760小时基本优化"""
# 使用较小的迭代次数以加快测试
result = optimize_storage_capacity(
self.yearly_solar, self.yearly_wind, self.yearly_thermal,
self.yearly_load, self.params, max_iterations=50
)
# 检查返回结果结构
expected_keys = [
'required_storage_capacity', 'storage_profile', 'charge_profile',
'discharge_profile', 'curtailed_wind', 'curtailed_solar',
'grid_feed_in', 'total_curtailment_wind_ratio',
'total_curtailment_solar_ratio', 'total_grid_feed_in_ratio',
'energy_balance_check'
]
for key in expected_keys:
self.assertIn(key, result)
# 检查数据长度
self.assertEqual(len(result['storage_profile']), 8760)
self.assertEqual(len(result['charge_profile']), 8760)
self.assertEqual(len(result['discharge_profile']), 8760)
# 检查数值合理性
self.assertGreaterEqual(result['required_storage_capacity'], 0)
if __name__ == "__main__":
print("运行多能互补系统储能容量优化程序测试...")
# 运行单元测试
unittest.main(argv=[''], exit=False, verbosity=2)
# 运行性能测试
run_performance_test()