Converter and avoiding nonConvex

Hello everyone

I am trying to model a small island system that contains PV, Wind and Battery storage as investment candidates. I have also set up a Diesel generator using the OffsetConverter to account for the non static efficiency. But this introduces the NonConvexity and turns the problem to an MILP. I have tried solving the model with Gurobi but even for a small system like mine it cant find a solution for a one year optimization (takes 2-3 days and then my laptop runs out of memory).

Do you have any suggestions on how to avoid this issue? I thought about using the PiecewiseLinearConverter but I am not sure if it will solve this issue if i try to capture the efficiency curve using a function. I am also not sure if I can implement a min_load for the generator either (meaning that I dont want it to operate below 50% capacity if it needs to operate)

Any help/suggestions would be appreciated

PS: Here is the Offset converter definition and the model size from Gurobi

Optimize a model with 113889 rows, 105131 columns and 293519 nonzeros
Model fingerprint: 0x7900b732
Variable types: 96371 continuous, 8760 integer (8760 binary)
Coefficient statistics:
Matrix range [1e-03, 1e+03]
Objective range [1e-01, 1e+05]
Bounds range [1e+00, 1e+05]
RHS range [7e-01, 4e+00]
Presolve removed 43811 rows and 52569 columns
Presolve time: 1.03s
Presolved: 70078 rows, 52562 columns, 188377 nonzeros
Variable types: 43802 continuous, 8760 integer (8760 binary)
Deterministic concurrent LP optimizer: primal and dual simplex
Showing primal log only…

elif diesel_gen_type ==2:
    min_load = 0.5
    max_load = 1.0
    min_efficiency = 0.299
    max_efficiency = 0.3698
    
    c1 = (max_load / max_efficiency - min_load / min_efficiency) / (
        max_load - min_load
    )
    c0 = min_load * (1 / min_efficiency - c1)
    
    diesel_generator = solph.components.OffsetConverter(
        label = 'diesel_generator',
        inputs = {bus_diesel: solph.flows.Flow()},
        outputs= {
            bus_electricity: solph.flows.Flow(
                min=min_load,
                max=max_load,
            nominal_value=1200, variable_costs= 50,
            nonconvex = solph.NonConvex(),
            
            ),
            },
                coefficients=(c0, c1),
        )

Hi @DPapad,

first of all, welcome do the board! Unluckily, part-load-efficiencies will always introduce integer variables if efficiency increases with load. Using PiecewiseLinearConverter will even worsen the problem.

There are a few things you might try, though:

  1. You can reduce the MipGap so that the solver already stops close to the optimum.
  2. Make sure, you have a distinct optimum. Sometimes, there are a bazillion options that are equally good. The solver might try them all to find the optimum. (Esp., storage should have a loss rate.)
  3. You can use temporal aggregation or a rolling horizon approach to have fewer time steps in the optimization. (Even simple things like considering only every nth day can bring good results.)

Hi,

I agree that to the best of my knowledge, non constant efficiency for generator is a nonconvexity, no matter the modeling tool (at least with its typical concave shape of the efficiency=f(power) which favors operation at nominal load) . And it is typically modeled with a MILP with one binary ON/OFF variable per time step.

In fact, just forbidding low load operation alone (i.e. with constant efficiency) is already a nonconvex constraint since the feasible set is not even connected ({0} \cup [P_{min}, P_{max}]). I find it quite well explained in MOSEK Modeling Cookbook / §9 Mixed integer optimization. Or at least it explains well the logic of the MILP formulation.

From the Gurobi model stats, I understand that you solve a problem with 1 year of data at a 1h timestep, and indeed @pschoen suggestion to reduce the number of days and/or enlarge the timestep are indeed relevant (which reminds me of Hoffman 2022 article https://www.sciencedirect.com/science/article/abs/pii/S0306261922004342)

Now, I don’t have timing results of MILP sizing, but I reread quickly @etienne.cuisinier 2023 article https://www.sciencedirect.com/science/article/abs/pii/S0360544223009933 and he indeed solved a MILP (called “MILP-OneShot”) on a 1 year at hourly timestep in 3 min with a 0.26% gap (relating to @pschoen 1st suggestion). However, this was for a fixed sizing. The sizing the problem (choosing among investment candidates to use your words) was solved with a LP, that is without the nonconvexities. This can point to a suboptimal/heuristic way to solve the problem:

  1. solve the sizing at constant efficiency and without minimal generator load
  2. for that sizing, resolve only the energy dispatch problem using a MILP to obtain actual operating costs

However, there is no guarantee that Problem 2 is feasible…