I have create a model using Pypsa and I am using gurobi solver to solve it. I am testing the time limit parameter of Gurobi. Here is how I am adding it to the model :
solverOptions = {
'LogFile': "gurobiLog",
'MIPGap': model_inputs['model_data']['solverMipGap'], # 0.001
'BarConvTol': model_inputs['model_data']['BarConvTol'], # 0.01
'TimeLimit': 200, # 200 Seconds
}
network.lopf(network.snapshots, solver_name='gurobi', solver_options=solverOptions, extra_functionality=extra_functionality)
I have set the time limit of 200 seconds here and I can see that in the Gurobi log file these parameters are getting applied there:
Gurobi 10.0.1 (win64) logging started Tue Dec 12 19:51:07 2023
Set parameter LogFile to value "gurobiLog"
Set parameter MIPGap to value 0.001
Set parameter BarConvTol to value 0.01
Set parameter TimeLimit to value 5
after 5 seconds in the log file I can see the solver is stopped and this message is printed :
Stopped in 136184 iterations and 5.04 seconds (280.23 work units)
Time limit reached
But in the code, I see this error:
network.lopf(network.snapshots, solver_name=solver, solver_options=solverOptions, extra_functionality=extra_functionality)
File "C:\Users\nvats\AppData\Local\Continuum\anaconda3\envs\production-cost-model_test\lib\site-packages\pypsa\components.py", line 769, in lopf
return network_lopf(self, **args)
File "C:\Users\nvats\AppData\Local\Continuum\anaconda3\envs\production-cost-model_test\lib\site-packages\pypsa\opf.py", line 2437, in network_lopf
extra_postprocessing=extra_postprocessing,
File "C:\Users\nvats\AppData\Local\Continuum\anaconda3\envs\production-cost-model_test\lib\site-packages\pypsa\opf.py", line 2296, in network_lopf_solve
options=solver_options
File "C:\Users\nvats\AppData\Local\Continuum\anaconda3\envs\production-cost-model_test\lib\site-packages\pyomo\opt\base\solvers.py", line 630, in solve
default_variable_value=self._default_variable_value)
File "C:\Users\nvats\AppData\Local\Continuum\anaconda3\envs\production-cost-model_test\lib\site-packages\pyomo\core\base\PyomoModel.py", line 228, in load_from
% str(results.solver.status))
ValueError: Cannot load a SolverResults object with bad status: aborted
I don't understand, it should return the solution that it found by that time but it's saying that it is aborted. Can anyone please help? Is there any other way of doing it? I am also adding my code here:
import pypsa
import numpy as np
import pandas as pd
from pyomo.environ import Constraint
from pyomo.environ import value
start_mt = 1
start_yr = 2022
end_mt = 12
end_yr = 2022
end_day = 31
frequency = 15
snapshots = pd.date_range("{}-{}-01".format(start_yr, start_mt), "{}-{}-{} 23:59".format(end_yr, end_mt, end_day),
freq=str(frequency) + "min")
np.random.seed(len(snapshots))
# Create a PyPSA network
network = pypsa.Network()
# Add a load bus
network.add("Bus", "Bus")
network.set_snapshots(snapshots)
load_profile = np.random.randint(2800, 3300, len(snapshots))
# Add the load to the network
network.add("Load", "Load profile", bus="Bus", p_set=load_profile)
# Define the generator data dictionary
generator_data = {
'coal1': {'capacity': 800, 'carrier': 'Coal', 'ramp up': 0.1, 'ramp down': 0.1, 'variable cost': 10, 'co2_emission_factor': 0.95},
'coal2': {'capacity': 600, 'carrier': 'Coal', 'ramp up': 0.1, 'ramp down': 0.1, 'variable cost': 11, 'co2_emission_factor': 0.95},
'coal3': {'capacity': 500, 'carrier': 'Coal', 'ramp up': 0.1, 'ramp down': 0.1, 'variable cost': 11, 'co2_emission_factor': 0.95},
'gas1': {'capacity': 600, 'carrier': 'Gas', 'ramp up': 0.05, 'ramp down': 0.05, 'variable cost': 12, 'co2_emission_factor': 0.45},
'gas2': {'capacity': 600, 'carrier': 'Gas', 'ramp up': 0.05, 'ramp down': 0.05, 'variable cost': 13, 'co2_emission_factor': 0.45},
'nuclear1': {'capacity': 300, 'carrier': 'Nuclear', 'ramp up': 0.01, 'ramp down': 0.01, 'variable cost': 4, 'co2_emission_factor': 0.03},
'nuclear2': {'capacity': 400, 'carrier': 'Nuclear', 'ramp up': 0.01, 'ramp down': 0.01, 'variable cost': 3, 'co2_emission_factor': 0.03},
'nuclear3': {'capacity': 250, 'carrier': 'Nuclear', 'ramp up': 0.01, 'ramp down': 0.01, 'variable cost': 3, 'co2_emission_factor': 0.03},
'solar1': {'capacity': 150, 'carrier': 'Solar', 'ramp up': 0.25, 'ramp down': 0.25, 'variable cost': 1, 'co2_emission_factor': 0.0},
'solar2': {'capacity': 200, 'carrier': 'Solar', 'ramp up': 0.25, 'ramp down': 0.25, 'variable cost': 2, 'co2_emission_factor': 0.0},
'backup': {'capacity': 1000, 'carrier': 'Import', 'ramp up': 0.25, 'ramp down': 0.25, 'variable cost': 2000, 'co2_emission_factor': 1.0},
}
# Add generators to the network
for name, data in generator_data.items():
network.add("Generator", name,
bus="Bus",
carrier=data['carrier'],
p_nom=data['capacity'],
marginal_cost=data['variable cost'],
ramp_limit_up=data['ramp up'],
ramp_limit_down=data['ramp down'],
)
print(network.generators.carrier.values)
network.add("Carrier", "Coal", co2_emissions=0.95)
network.add("Carrier", "Gas", co2_emissions=0.45)
network.add("Carrier", "Nuclear", co2_emissions=0.03)
network.add("Carrier", "Import", co2_emissions=1.0)
network.add("Carrier", "Solar", co2_emissions=0)
network.add(
"GlobalConstraint",
"CO2Limit",
carrier_attribute="co2_emissions",
sense="<=",
constant=50000000,
)
solver_name = "gurobi"
solverOptions = {
'LogFile': "gurobiLog",
'MIPGap': 0.001,
'BarConvTol': 0.01,
'TimeLimit': 5,
}
network.lopf(network.snapshots, solver_name=solver_name, solver_options=solverOptions)
csv_folder_name = 'model dump'
network.export_to_csv_folder(csv_folder_name)
dispatch = network.generators_t.p
total_gen = dispatch.sum()
co2 = sum([total_gen[gen] * data['co2_emission_factor'] for gen, data in generator_data.items()])
cost = sum([total_gen[gen] * data['variable cost'] for gen, data in generator_data.items()])
print('co2 emission = ', co2)
print('total cost = ', cost)
dispatch['load profile'] = load_profile
dispatch.to_excel('fuel wise dispatch.xlsx')
I ran your code just fine. The time limit is respected and works as intended. The only thing I had to change was the call to
lopf
. This caused a deprecation warning that clearly states that the methodoptimize
should be used instead. Everything worked fine with that change. Here's the final output with a time limit of 20 seconds:By the way: The Pyomo import statements in the beginning are not necessary as no Pyomo code is used here. They can safely be removed.