Partload efficiency curve modelling in Gurobi
Dear community,
I would like to model the efficiency of a heat pump as a function of its load level, e.g., efficiency(T) = a*load_level(T)+b, where a and b are constants and T is time.
I have two variables "installed_capacity" and "power(T)", so the load_level(T) is defined as installed_capacity/power(T). But Gurobi does not accept this argument (division only allowed for constants).
Secondly, I also tried a piecewise linear approximation for the partload efficiency curve.
def part_load_eff(load_level, c1, c2, c3):
return c1  c2/(2**(load_level/c3))
part_load_steps = np.linspace(0, 1, 5)
efficiency_steps = part_load_eff(part_load_steps, 3.8299, 3.8236, 0.14659)
v_load_level = m.addVar(lb=0, ub=1, vtype=GRB.CONTINUOUS)
v_efficiency = m.addVar(lb=0, ub=p_hp_cop_max, vtype=GRB.CONTINUOUS)
v_weights = m.addVars(len(part_load_steps), lb=0, ub=1, vtype=GRB.CONTINUOUS)
sos2 = m.addSOS(GRB.SOS_TYPE2, v_weights)
m.addConstr(quicksum(v_weights) == 1)
m.addConstr(quicksum([v_weights[i]*part_load_steps[i] for i in range(len(part_load_steps))]) == v_load_level)
m.addConstr(quicksum([v_weights[i]*efficiency_steps[i] for i in range(len(efficiency_steps))]) == v_efficiency)
But then in this way, the time dimension is not represented (because efficiency varies with time). Does any of you have any suggestion to make this constraint work properly?
Regards
Buddi

UPDATE  Another try using table lookup method
p_hp_cop = {0:1.5, 0.2:2.3, 0.4:3.4, 0.6:3.7, 0.8:3.85} #Create a lookup table (dict) for different load levels (key) and efficiency (value)
model.addConstrs(v_hp_cop[T] == max([v for (k,v) in p_hp_cop.items() if k*v_installed_capacity<=v_hp_power[T]]) for T in Time)
This also doesn't work and always returns the highest efficiency irrespective of what the load level is. Looking forward to some wise suggestions to implement partload efficiency curves.

Hi Buddi,
Could you try adding the constraint load_level(T) * power(T) = installed_capacity for each time T? Gurobi 9.0 supports bilinear constraints like this. When doing this, be sure to set the NonConvex parameter to 2.
Eli

Thank you Eli. So I added (with Gurobi 9.0);
model.Params.NonConvex = 2
model.addConstrs(v_hp_load_level[T]*v_hp_power[T] == v_installed_capacity for T in Time)
There were some problems but after I uninstalled everything and reinstalled again, it started working. The challenge I have now is with the computational time. In that regard, especially because my model has a large number of timesteps, I would prefer a simpler table lookup kind of a method. Do you know how it can be implemented?
Please sign in to leave a comment.
Comments
3 comments