Commit bca64107 authored by ZZH's avatar ZZH

add inv eval 2024-12-30 14:52

parent f7b3f85d
# -*- coding:utf-8 -*-
"""
DATE:2024/12/30 10:18
"""
# -*- coding:utf-8 -*-
"""
DATE:2024/12/30 10:18
"""
# -*- coding:utf-8 -*-
"""
DATE:2024/12/30 10:16
"""
from gurobipy import Model, GRB
class EnergyModel:
def __init__(self, d_params):
self.load_year = d_params["load_year"]
self.imp_load_year = d_params["imp_load_year"]
self.cg_cost = d_params["cg_cost"]
self.es_cost = d_params["es_cost"]
self.cg_eff = d_params["cg_eff"]
self.es_eff = d_params["es_eff"]
self.work_hours_year = d_params["work_hours_year"]
self.ele_price = d_params["ele_price"]
self.max_invest_year = d_params["max_invest_year"]
def cri_calculate(self):
m = Model("Energy_Investment_Optimization")
P_ES = m.addVar(vtype=GRB.CONTINUOUS, name="P_ES")
P_CG = m.addVar(vtype=GRB.CONTINUOUS, name="P_CG")
IRR = m.addVar(vtype=GRB.CONTINUOUS, name="IRR")
E_CG = P_CG * self.cg_eff * self.work_hours_year
Revenue = self.ele_price * E_CG
Investment_Cost = P_ES * self.es_cost + P_CG * self.cg_cost
m.setObjective(IRR, GRB.MINIMIZE)
m.addConstr(IRR * Revenue == Investment_Cost,
"Critical_Load_Constraint")
m.addConstr(P_CG * self.cg_eff >= self.imp_load_year,
"Critical_Load_Constraint")
m.addConstr(P_ES * self.es_eff >= self.imp_load_year,
"Load_Constraint")
m.addConstr(P_ES * self.es_eff <= self.imp_load_year * 1.2,
"ES_Capacity_Constraint")
m.addConstr(P_CG * self.cg_eff <= self.imp_load_year * 1.2,
"CG_Capacity_Constraint")
m.optimize()
if m.status == GRB.OPTIMAL:
irr = Investment_Cost.getValue() / Revenue.getValue()
if irr > self.max_invest_year:
return {"Error": f"当前区域的投资回报比(IRR = {irr:.2f})高于"
f"设置的投资上限,建议不要投资。"}
else:
result = {
'pv': 0,
'es': P_ES.x,
'cg': P_CG.x,
'income_year': Revenue.getValue(),
'total_inv_cost': Investment_Cost.getValue(),
'irr': round(irr, 2)
}
return result
else:
return {"Error": "当前求解的限制条件不合理"}
def all_calculate(self, d_params):
pv_cost = d_params["pv_cost"]
sun_hrs_year = d_params["sun_hrs_year"]
max_load = d_params["max_load"]
min_load = d_params["min_load"]
pv_eff = d_params["pv_eff"]
pv_area = d_params["pv_area"]
pv_limit = d_params["pv_limit"]
pv_area_ele = 0.15
m = Model("Energy_Investment_Optimization")
P_PV = m.addVar(vtype=GRB.CONTINUOUS, name="P_PV")
P_ES = m.addVar(vtype=GRB.CONTINUOUS, name="P_ES")
P_CG = m.addVar(vtype=GRB.CONTINUOUS, name="P_CG")
IRR = m.addVar(vtype=GRB.CONTINUOUS, name="IRR")
E_PV = P_PV * sun_hrs_year * pv_eff
E_CG = P_CG * self.work_hours_year * self.cg_eff
Revenue = self.ele_price * self.load_year * self.work_hours_year
Investment_Cost = P_PV * pv_cost + P_ES * self.es_cost + P_CG * self.cg_cost
m.setObjective(IRR, GRB.MINIMIZE)
m.addConstr(E_PV + E_CG >= self.load_year * self.work_hours_year,
"IRR_Constraint")
m.addConstr(IRR * Revenue == Investment_Cost, "IRR_Constraint")
m.addConstr(P_PV * pv_eff + E_CG * self.cg_eff >= max_load,
"PV_Constraint")
m.addConstr(P_PV <= min(pv_area_ele * pv_area, pv_limit),
"PV_Limit_Constraint")
m.addConstr(P_CG * self.cg_eff >= self.imp_load_year, "CG_Constraint")
m.addConstr(P_CG * self.cg_eff + P_ES * self.es_eff >= min_load,
"CG_Min_Load_Constraint")
m.addConstr(P_ES * self.es_eff >= self.imp_load_year,
"ES_Load_Constraint")
m.addConstr(P_ES * self.es_eff >= 0.2 * pv_eff * P_PV,
"ES_PV_Constraint")
m.optimize()
if m.status == GRB.OPTIMAL:
irr = IRR.x
if irr > self.max_invest_year:
return {"Error": f"当前区域的投资回报比(IRR = {irr:.2f})高于"
f"设置的投资上限,建议不要投资。"}
else:
result = {
'pv': P_PV.x,
'es': P_ES.x,
'cg': P_CG.x,
'income_year': Revenue,
'total_inv_cost': Investment_Cost.getValue(),
'irr': round(irr, 2)
}
return result
else:
return {"Error": "当前求解的限制条件不合理"}
def sale_calculate(self, d_params):
pv_cost = d_params["pv_cost"]
sun_hrs_year = d_params["sun_hrs_year"]
max_load = d_params["max_load"]
min_load = d_params["min_load"]
pv_eff = d_params["pv_eff"]
pv_area = d_params["pv_area"]
pv_limit = d_params["pv_limit"]
sale_price = d_params["sale_price"]
sale_limit = d_params["sale_limit"]
sale_cost = d_params["sale_cost"]
pv_area_ele = 0.15
m = Model("Energy_Investment_Optimization")
P_PV = m.addVar(vtype=GRB.CONTINUOUS, name="P_PV")
P_ES = m.addVar(vtype=GRB.CONTINUOUS, name="P_ES")
P_CG = m.addVar(vtype=GRB.CONTINUOUS, name="P_CG")
IRR = m.addVar(vtype=GRB.CONTINUOUS, name="P_CG")
E_PV = P_PV * sun_hrs_year * pv_eff
E_CG = P_CG * self.work_hours_year * self.cg_eff
Revenue = (E_PV + E_CG) * self.ele_price + (
sale_price - sale_cost - self.ele_price) * (
E_PV + E_CG - self.load_year * self.work_hours_year)
# 这个不对
Investment_Cost = P_PV * pv_cost + P_ES * self.es_cost + P_CG * self.cg_cost
m.setObjective(IRR, GRB.MINIMIZE)
m.addConstr(IRR * Revenue == Investment_Cost)
m.addConstr(P_PV <= min(pv_area_ele * pv_area, pv_limit),
"PV_Limit_Constraint")
m.addConstr(P_CG * self.cg_eff >= self.imp_load_year, "CG_Constraint")
m.addConstr(P_CG * self.cg_eff + P_PV * pv_eff >= max_load,
"CG_Min_Load_Constraint")
m.addConstr(P_ES * self.es_eff >= 0.2 * pv_eff * P_PV,
"ES_PV_Constraint")
m.addConstr(
P_PV * pv_eff + P_ES * pv_eff + P_CG * self.cg_eff <= self.load_year + (
sale_limit / 24),
"Total_Constraint")
m.optimize()
if m.status == GRB.OPTIMAL:
irr = IRR.x
if irr > self.max_invest_year:
return {"Error": f"当前区域的投资回报比(IRR = {irr:.2f})高于"
f"设置的投资上限,建议不要投资。"}
else:
result = {
'pv': P_PV.x,
'es': P_ES.x,
'cg': P_CG.x,
'income_year': Revenue.getValue(),
'total_inv_cost': Investment_Cost.getValue(),
'irr': round(irr, 2)
}
return result
else:
return {"Error": "当前求解的限制条件不合理"}
def com_strategy(self, d_params):
pv_cost = d_params["pv_cost"]
sun_hrs_year = d_params["sun_hrs_year"]
max_load = d_params["max_load"]
min_load = d_params["min_load"]
pv_eff = d_params["pv_eff"]
pv_area = d_params["pv_area"]
pv_limit = d_params["pv_limit"]
sale_price = d_params["sale_price"]
sale_limit = d_params["sale_limit"]
sale_cost = d_params["sale_cost"]
pv_area_ele = 0.15
m = Model("Energy_Investment_Optimization")
P_PV = m.addVar(vtype=GRB.CONTINUOUS, name="P_PV")
P_ES = m.addVar(vtype=GRB.CONTINUOUS, name="P_ES")
P_CG = m.addVar(vtype=GRB.CONTINUOUS, name="P_CG")
IRR = m.addVar(vtype=GRB.CONTINUOUS, name="P_CG")
coefficient_of_combined_objective_1 = 0.5
coefficient_of_combined_objective_2 = 0.4
coefficient_of_combined_objective_3 = 0.1
E_PV = P_PV * sun_hrs_year * pv_eff
E_CG = P_CG * self.work_hours_year * self.cg_eff
Revenue = (
self.ele_price * self.load_year * self.work_hours_year) + (
sale_price - sale_cost) * (
E_PV + E_CG - self.load_year * self.work_hours_year)
Investment_Cost = P_PV * pv_cost + P_ES * self.es_cost + P_CG * self.cg_cost
m.setObjective(IRR, GRB.MINIMIZE)
m.addConstr(IRR * Revenue == Investment_Cost)
m.addConstr(P_PV * pv_eff + E_CG * self.cg_eff >= max_load,
"PV_Constraint")
m.addConstr(P_PV <= min(pv_area_ele * pv_area, pv_limit),
"PV_Limit_Constraint")
m.addConstr(
P_CG * self.cg_eff >= coefficient_of_combined_objective_1 * self.imp_load_year,
"CG_Constraint")
m.addConstr(P_CG * self.cg_eff + P_ES * self.es_eff >= 1.2 * min_load,
"CG_Min_Load_Constraint")
m.addConstr(
P_ES * self.es_eff >= coefficient_of_combined_objective_2 * pv_eff * P_PV,
"ES_PV_Constraint")
m.addConstr(
P_PV * pv_eff + P_ES * pv_eff + P_CG * self.cg_eff <= self.load_year + (
sale_limit / 24),
"Total_Constraint")
m.optimize()
if m.status == GRB.OPTIMAL:
irr = Investment_Cost.getValue() / Revenue.getValue()
if irr > self.max_invest_year:
return {"提示": f"当前区域的投资回报比(IRR = {irr:.2f})高于"
f"设置的投资上限,建议不要投资。"}
else:
result = {
'pv': P_PV.x,
'es': P_ES.x,
'cg': P_CG.x,
'income_year': Revenue.getValue(),
'total_inv_cost': Investment_Cost.getValue(),
'irr': round(irr, 2)
}
return result
else:
return {"Error": "当前求解的限制条件不合理"}
if __name__ == '__main__':
load_year = 4500 # 年均负荷(kw)
imp_load_year = 2000 # 年均重要负荷(kw)
es_cost = 1500 # 储能成本 元/kw
pv_cost = 800 # 光伏成本 元/kw
ele_price = 1.4 # 电价
cg_cost = 8000 # 煤制气成本加上燃料成本 元/kw
sale_price = 1000 # 售电价格
sale_cost = 0.5 # 售电成本
work_hours_year = 2000 # 每年的工作时长为2000小时
sun_hrs_year = 1300 # 每年的光照时长为1300小时
max_load = 6000 # kw
min_load = 2400 # kw
pv_area = 50000 # 当前场地的光伏建设面积最大面积平方米
pv_eff = 0.8 # 光伏效率
max_invest_year = 5 # 当前投资收益最大限制
pv_limit = 7000 # 光伏最大限制
sale_limit = 100000 # 售电限制kw*h
ems_model = EnergyModel(dict(load_year=load_year,
imp_load_year=imp_load_year,
es_cost=es_cost, ele_price=ele_price,
cg_cost=cg_cost,
work_hours_year=work_hours_year,
max_invest_year=max_invest_year,
cg_eff=0.8, es_eff=0.8))
rlt_cri = ems_model.cri_calculate()
print("rlt_cri", rlt_cri)
rlt_all = ems_model.all_calculate(dict(pv_cost=pv_cost,
sun_hrs_year=sun_hrs_year,
max_load=max_load,
min_load=min_load,
pv_eff=pv_eff,
pv_area=pv_area,
pv_limit=pv_limit))
print("rlt_all", rlt_all)
rlt_sale = ems_model.sale_calculate(dict(pv_cost=pv_cost,
sun_hrs_year=sun_hrs_year,
max_load=max_load,
min_load=min_load,
pv_eff=pv_eff,
pv_area=pv_area,
pv_limit=pv_limit,
sale_price=sale_price,
sale_limit=sale_limit,
sale_cost=sale_cost))
print("rlt_sale", rlt_sale)
rlt_com = ems_model.com_strategy(dict(pv_cost=pv_cost,
sun_hrs_year=sun_hrs_year,
max_load=max_load,
min_load=min_load,
pv_eff=pv_eff,
pv_area=pv_area,
pv_limit=pv_limit,
sale_price=sale_price,
sale_limit=sale_limit,
sale_cost=sale_cost))
print("rlt_com", rlt_com)
# -*- coding:utf-8 -*-
"""
DATE:2024/12/30 11:43
"""
from dataclasses import dataclass
from pot_libs.sanic_api import Model
from pot_libs.sanic_api.column import Opt, Float, Int, List, Str
@dataclass
class EmsInvEvalReq(Model):
load_year: float = Opt(Float("年均负荷(kw)").eg(4500))
imp_load_year: float = Opt(Float("年均重要负荷(kw)").eg(2000))
es_cost: float = Opt(Float("储能成本 元/kw").eg(1500))
pv_cost: float = Opt(Float("年均负荷(kw)").eg(800))
ele_price: float = Opt(Float("电价").eg(1.4))
cg_cost: float = Opt(Float("煤制气成本加上燃料成本 元/kw").eg(8000))
sale_price: float = Opt(Float("售电价格").eg(1000))
sale_cost: float = Opt(Float("售电成本价格").eg(0.5))
work_hours_year: float = Opt(Float("每年的工作时长").eg(2000))
sun_hrs_year: float = Opt(Float("每年的光照时长").eg(1300))
max_load: float = Opt(Float("").eg(6000))
min_load: float = Opt(Float("").eg(2400))
pv_area: float = Opt(Float("光伏建设最大面积").eg(50000))
pv_eff: float = Opt(Float("光伏效率").eg(0.8))
max_invest_year: float = Opt(Float("当前投资收益最大限制").eg(5))
pv_limit: float = Opt(Float("光伏最大限制").eg(7000))
sale_limit: float = Opt(Float("售电限制kw*h").eg(100000))
cg_eff: float = Opt(Float("煤制气效率").eg(0.8))
es_eff: float = Opt(Float("充电效率").eg(0.8))
goal: int = Int("1保重要负荷2保所有负荷3可联网售电4综合成本最优").eg(1)
@dataclass
class EmsInvEvalRsp(Model):
pv: float = Opt(Float("光伏配置").eg(4500))
es: float = Opt(Float("储能配置").eg(4500))
cg: float = Opt(Float("煤制气").eg(4500))
income_year: float = Opt(Float("年收益").eg(4500))
total_inv_cost: float = Opt(Float("总投资成本").eg(4500))
irr: float = Opt(Float("投资回报率").eg(0.1))
# -*- coding:utf-8 -*-
"""
DATE:2024/12/30 10:16
"""
# -*- coding:utf-8 -*-
"""
DATE:2024/12/30 13:41
"""
from unify_api.algo.ems.ems import EnergyModel
async def inv_eval(d_params):
load_year = d_params["load_year"]
imp_load_year = d_params["imp_load_year"]
es_cost = d_params["es_cost"]
ele_price = d_params["ele_price"]
cg_cost = d_params["cg_cost"]
work_hours_year = d_params["work_hours_year"]
max_invest_year = d_params["max_invest_year"]
cg_eff = d_params["cg_eff"]
es_eff = d_params["es_eff"]
pv_cost = d_params["pv_cost"]
sun_hrs_year = d_params["sun_hrs_year"]
max_load = d_params["max_load"]
min_load = d_params["min_load"]
pv_eff = d_params["pv_eff"]
pv_area = d_params["pv_area"]
pv_limit = d_params["pv_limit"]
sale_price = d_params["sale_price"]
sale_limit = d_params["sale_limit"]
sale_cost = d_params["sale_cost"]
goal = d_params["goal"]
rlt_cfg = {}
ems_model = EnergyModel(dict(load_year=load_year,
imp_load_year=imp_load_year,
es_cost=es_cost, ele_price=ele_price,
cg_cost=cg_cost,
work_hours_year=work_hours_year,
max_invest_year=max_invest_year,
cg_eff=cg_eff, es_eff=es_eff))
if goal == 1:
rlt_cfg = ems_model.cri_calculate()
elif goal == 2:
rlt_cfg = ems_model.all_calculate(dict(pv_cost=pv_cost,
sun_hrs_year=sun_hrs_year,
max_load=max_load,
min_load=min_load,
pv_eff=pv_eff,
pv_area=pv_area,
pv_limit=pv_limit))
elif goal == 3:
rlt_cfg = ems_model.sale_calculate(dict(pv_cost=pv_cost,
sun_hrs_year=sun_hrs_year,
max_load=max_load,
min_load=min_load,
pv_eff=pv_eff,
pv_area=pv_area,
pv_limit=pv_limit,
sale_price=sale_price,
sale_limit=sale_limit,
sale_cost=sale_cost))
elif goal == 4:
rlt_cfg = ems_model.com_strategy(dict(pv_cost=pv_cost,
sun_hrs_year=sun_hrs_year,
max_load=max_load,
min_load=min_load,
pv_eff=pv_eff,
pv_area=pv_area,
pv_limit=pv_limit,
sale_price=sale_price,
sale_limit=sale_limit,
sale_cost=sale_cost))
return rlt_cfg
# -*- coding:utf-8 -*-
"""
DATE:2024/12/30 10:15
"""
from pot_libs.sanic_api import summary
from unify_api.modules.inv_eval.service.ems_srv import inv_eval
from unify_api.modules.inv_eval.components.ems_cps import (
EmsInvEvalReq, EmsInvEvalRsp
)
@summary("投资汇报测算")
async def post_inv_eval(req, body: EmsInvEvalReq) -> EmsInvEvalRsp:
try:
load_year = body.load_year or 0
imp_load_year = body.imp_load_year or 0
es_cost = body.es_cost or 0
pv_cost = body.pv_cost or 0
ele_price = body.ele_price or 0
cg_cost = body.cg_cost or 0
sale_price = body.sale_price or 0
sale_cost = body.sale_cost or 0
work_hours_year = body.work_hours_year or 0
sun_hrs_year = body.sun_hrs_year or 0
max_load = body.max_load or 0
min_load = body.min_load or 0
pv_area = body.pv_area or 0
pv_eff = body.pv_eff or 0
max_invest_year = body.max_invest_year or 0
pv_limit = body.pv_limit or 0
sale_limit = body.sale_limit or 0
cg_eff = body.cg_eff or 0.8
es_eff = body.es_eff or 0.8
goal = body.goal
d_params = dict(load_year=load_year, imp_load_year=imp_load_year,
es_cost=es_cost, pv_cost=pv_cost, ele_price=ele_price,
cg_cost=cg_cost, work_hours_year=work_hours_year,
max_invest_year=max_invest_year,
cg_eff=cg_eff, es_eff=es_eff,
sun_hrs_year=sun_hrs_year,
max_load=max_load, min_load=min_load,
pv_eff=pv_eff, pv_area=pv_area, pv_limit=pv_limit,
sale_price=sale_price, sale_limit=sale_limit,
sale_cost=sale_cost, goal=goal)
cfg = await inv_eval(d_params)
return EmsInvEvalRsp(pv=cfg.get("pv", 0), es=cfg.get("es", 0),
cg=cfg.get("cg", 0),
income_year=cfg.get("income_year", 0),
irr=cfg.get("irr", 0))
except Exception as e:
return EmsInvEvalRsp(pv=0, es=0, cg=0, income_year=0, irr=0)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment