首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >增加一个限制,以防止电池同时放电

增加一个限制,以防止电池同时放电
EN

Stack Overflow用户
提问于 2022-10-04 16:15:18
回答 1查看 46关注 0票数 0

我正试图在不同的市场上寻找购买和销售能源电池的最佳调度方式。我遇到了一个问题,就是电池在同一个市场上同时充放电。我的约束是如何避免同时充放电的?

这里是我的例子:

代码语言:javascript
复制
def battery_optimisation(data: pd.DataFrame, technical_parameters=None, include_revenue=True, solver: str='glpk'):
    
    # Battery's technical specification
    MIN_BATTERY_CAPACITY = 0
    MAX_BATTERY_CAPACITY = 100
    MAX_RAW_POWER = 40
    INITIAL_CAPACITY = 0 
    EFFICIENCY = 1

    battery = ConcreteModel()

    solvername='glpk'
    solverpath_folder='C:\\glpk-4.65\\w64'
    solverpath_exe='C:\\glpk-4.65\\w64\\glpsol' 

    opt = SolverFactory(solver,executable=solverpath_exe)

    battery.Period = Set(initialize=list(data.period), ordered=True)
    
    battery.Price = Param(initialize=list(data.spot_hourly), within=Any)
    battery.intraday = Param(initialize=list(data.id_hourly), within=Any)
    battery.fcr_hourly = Param(initialize=list(data.fcr_hourly), within=Any)
    battery.afrr_up = Param(initialize=list(data.afrr_up_energy_hourly), within=Any)
    battery.afrr_down = Param(initialize=list(data.afrr_down_energy_hourly), within=Any)

    # battery variables
    battery.Capacity = Var(battery.Period, bounds=(MIN_BATTERY_CAPACITY, MAX_BATTERY_CAPACITY))
    battery.Charge_power = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
    battery.Discharge_power = Var(battery.Period, bounds=(0, MAX_RAW_POWER))

    battery.charge_power_dah = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
    battery.discharge_power_dah = Var(battery.Period, bounds=(0, MAX_RAW_POWER))

    battery.charge_power_intra = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
    battery.discharge_power_intra = Var(battery.Period, bounds=(0, MAX_RAW_POWER))

    battery.charge_power_fcr = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
    battery.discharge_power_fcr = Var(battery.Period, bounds=(0, MAX_RAW_POWER))

    battery.charge_power_afrr = Var(battery.Period, bounds=(0, MAX_RAW_POWER))
    battery.discharge_power_afrr = Var(battery.Period, bounds=(0, MAX_RAW_POWER))

    battery.power_balance =Var(battery.Period, doc='binary variable', within=Binary, initialize=0)
    battery.power_p = Var(battery.Period, doc='energy derivative with respect to time',  initialize=0)

    # Set constraints for the battery
    # Defining the battery objective (function to be maximise)

    def maximise_profit(battery):

        rev = sum(data.id_hourly[i] * (battery.discharge_power_intra[i] / 2 * EFFICIENCY) for i in battery.Period) + \
              sum(data.fcr_hourly[i] * (battery.discharge_power_fcr[i] / 2 * EFFICIENCY) for i in battery.Period) + \
              sum(data.afrr_up_energy_hourly[i] * (battery.discharge_power_afrr[i] / 2 * EFFICIENCY) for i in battery.Period) + \
              sum(data.spot_hourly[i] * (battery.discharge_power_dah[i] / 2 * EFFICIENCY) for i in battery.Period) 

        cost = sum(data.id_hourly[i] * (battery.charge_power_intra[i] / 2)  for i in battery.Period) + \
               sum(data.fcr_hourly[i] * (battery.charge_power_fcr[i] / 2)  for i in battery.Period) + \
               sum(data.afrr_down_energy_hourly[i] * (battery.charge_power_afrr[i] / 2)  for i in battery.Period) + \
               sum(data.spot_hourly[i] * (battery.charge_power_dah[i] / 2)  for i in battery.Period) 

        return rev - cost

    # CONSTRAINT - BATTERY CAN'T CHARGE OVER CAPACITY
    def over_charge(battery, i):

        battery_charge = battery.charge_power_intra[i] + \
                         battery.charge_power_fcr[i]  + \
                         battery.charge_power_afrr[i] + \
                         battery.charge_power_dah[i]   
        
        return battery_charge <= (MAX_BATTERY_CAPACITY - battery.Capacity[i]) * 2 / EFFICIENCY

    # CONSTRAINT - CAN DISCHARGE MORE THAN CAPITY
    def over_discharge(battery, i):
        
        battery_charge =  battery.discharge_power_intra[i] + \
                          battery.discharge_power_fcr[i] + \
                          battery.discharge_power_afrr[i] + \
                          battery.discharge_power_dah[i]  

        return battery_charge <= battery.Capacity[i] * 2


    # CONSTRAINT - BATTERY CAN'T DISCHARGE IF PRICES ARE NEGATIVE
    def negative_discharge_spot(battery, i):
        # if the spot price is not positive, suppress discharge
        if battery.Price.extract_values_sparse()[None][i] <= 0:
            return battery.Discharge_power[i] == 0

        # otherwise skip the current constraint    
        return Constraint.Skip

    # CONSTRAINT - CAPACITY RULE
    def capacity_constraint(battery, i):
        # Assigning battery's starting capacity at the beginning
        if i == battery.Period.first():
            return battery.Capacity[i] == INITIAL_CAPACITY
        # if not update the capacity normally    

        battery_capacity = (battery.Capacity[i-1] \
                        + ((battery.charge_power_intra[i-1] / 2 * EFFICIENCY) \
                        + (battery.charge_power_fcr[i-1] / 2 * EFFICIENCY) \
                        + (battery.charge_power_afrr[i-1] / 2 * EFFICIENCY) \
                        + (battery.charge_power_dah[i-1] / 2 * EFFICIENCY)) \
                        - ((battery.discharge_power_intra[i-1] / 2) \
                        + (battery.discharge_power_fcr[i-1] / 2) \
                        + (battery.discharge_power_afrr[i-1] / 2) \
                        + (battery.discharge_power_dah[i-1] / 2)))

        return battery.Capacity[i] == battery_capacity

    # def _p_balance(battery, i):
    #     return battery.discharge_power_fcr[i] <= 0 | battery.charge_power_fcr[i] <= 0

    # Set constraint and objective for the battery
    battery.capacity_constraint = Constraint(battery.Period, rule=capacity_constraint)
    battery.over_charge = Constraint(battery.Period, rule=over_charge)
    battery.over_discharge = Constraint(battery.Period, rule=over_discharge)
    battery.negative_discharge = Constraint(battery.Period, rule=negative_discharge_spot)
    battery.objective = Objective(rule=maximise_profit, sense=maximize)
    # battery._p_balance = Constraint(battery.Period, rule=_p_balance)

    # Maximise the objective
    opt.solve(battery, tee=False)

如果你看看结果,你可以看到,在'FCR‘市场,它是同时充放电。

我试过了:

天真的方法。提供一个OR-条件: def _p_balance(电池,i):返回battery.discharge_power_fcri == 0\ battery.charge_power_fcri == 0

乘数: def _p_balance(电池,i):返回battery.discharge_power_fcri * battery.charge_power_fcri == 0

->这使得这个问题非线性化,而GLPK不支持这个问题.

EN

回答 1

Stack Overflow用户

发布于 2022-10-04 17:33:48

这不是一个完整的答案,但太长,不能发表评论。

你这里没有“电池”的模型。我认为,你有一个4个能源市场的市场模型。

您的代码中没有多少解释性注释,但我认为您有4个市场: IntraDay、Day、FCR、AFRR,每个市场都有相应的价格和成本。因此,你实际上是在建立一个分销系统的模型,如果有一些价格差异来生产你所展示的产品,这将是完全合法的。如果FCR成本低,价格高(在FCR市场和其他市场),您可以大量购买,并在相同的市场或其他市场出售,这似乎正在发生。

所以,如果我们看看你的目标函数,尤指。FCR部分是孤立的,它显示您使用相同的成本值作为两个成本的乘数& rev.。唯一的区别是效率。...And您的效率被设置为1,所以成本是中立的,无论你做什么在FCR市场,所以解决方案提供可能有充放电.OBJ值将与此无关。所以,试着把你的效率稍微改变为<1,我想你会看到(部分)改进。

还有一个nits:您将Capacity[i]作为变量。通常,“容量”是一个固定值,类似于10 is。我会把它重新命名为“控告”或“国家”

当价格是负的时候你不应该限制排放..。OBJ应该为您处理这一问题,我认为效率的变化将消除这一限制。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73950740

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档