# Licensed under the Apache License, Version 2, which is in the LICENSE file. """ Illustrate the use of switch to construct and run a toy model with three load zones and two investment period where the first investment period has more temporal resolution than the second. Note, the results from this have not been fully evaluated. For this to work, you need to ensure that the switch_mod package directory is in your python search path. See the README for more info. """ from pyomo.environ import * from pyomo.opt import SolverFactory from switch_mod.utilities import define_AbstractModel switch_model = define_AbstractModel( "switch_mod", "local_td", "project.no_commit", "fuel_markets", "trans_build", "trans_dispatch" ) switch_instance = switch_model.load_inputs(inputs_dir="inputs") opt = SolverFactory("cplex") results = opt.solve(switch_instance, keepfiles=False, tee=False) switch_model.save_results(results, switch_instance, "outputs") # results.write() switch_instance.pprint()
#!/usr/local/bin/python # Copyright 2015 The Switch Authors. All rights reserved. # Licensed under the Apache License, Version 2, which is in the LICENSE file. """ Illustrate the use of switch to construct and run a very simple production-cost model with a single load zone, one investment period, and four timepoints. Includes variable generation. For this to work, you need to ensure that the switch_mod package directory is in your python search path. See the README for more info. """ from pyomo.environ import * from pyomo.opt import SolverFactory from switch_mod.utilities import define_AbstractModel switch_model = define_AbstractModel('switch_mod', 'local_td', 'project.no_commit', 'fuel_cost') switch_instance = switch_model.load_inputs(inputs_dir="inputs") opt = SolverFactory("cplex") results = opt.solve(switch_instance, keepfiles=False, tee=False) switch_instance.load(results) results.write() switch_instance.pprint()
behavior. In both versions of incremental heat rate tables, I gave natural gas combustion turbines a very minor heat rate penalty to discourage committing more capacity than is needed. I changed the incremental heat rate to 99 percent of the full load heat rate, with 1 percent of the fuel use incurred at 0 electricity output. For this to work, you need to ensure that the switch_mod package directory is in your python search path. See the README for more info. """ from pyomo.environ import * from pyomo.opt import SolverFactory from switch_mod.utilities import define_AbstractModel switch_model = define_AbstractModel( 'switch_mod', 'local_td', 'project.unitcommit', 'fuel_cost') switch_instance = switch_model.load_inputs(inputs_dir="inputs") opt = SolverFactory("cplex") results = opt.solve(switch_instance, keepfiles=False, tee=False) switch_model.save_results(results, switch_instance, "outputs") # Dump all results # switch_instance.load(results) # results.write() switch_instance.pprint()
#!/usr/local/bin/python # Copyright 2015 The Switch Authors. All rights reserved. # Licensed under the Apache License, Version 2, which is in the LICENSE file. """ Illustrate the use of switch to construct and run a very simple model with a single load zone, one investment period, and two timepoints. This model neglects local transmission and distribution as well. For this to work, you need to ensure that the switch_mod package directory is in your python search path. See the README for more info. """ from pyomo.environ import * from switch_mod.utilities import define_AbstractModel import switch_mod.utilities switch_model = define_AbstractModel( 'switch_mod', 'project.no_commit', 'fuel_cost', 'sunk_costs') switch_instance = switch_model.load_inputs(inputs_dir="inputs") opt = switch_mod.utilities.default_solver() results = opt.solve(switch_instance, keepfiles=False, tee=False) switch_instance.load(results) results.write() switch_instance.pprint()
# Copyright 2015 The Switch Authors. All rights reserved. # Licensed under the Apache License, Version 2, which is in the LICENSE file. """ Illustrate the use of switch to construct and run a toy model with three load zones and two investment period where the first investment period has more temporal resolution than the second. Note, the results from this have not been fully evaluated. For this to work, you need to ensure that the switch_mod package directory is in your python search path. See the README for more info. """ from pyomo.environ import * from pyomo.opt import SolverFactory from switch_mod.utilities import define_AbstractModel switch_model = define_AbstractModel('switch_mod', 'local_td', 'project.no_commit', 'fuel_markets', 'trans_build', 'trans_dispatch') switch_instance = switch_model.load_inputs(inputs_dir="inputs") opt = SolverFactory("cplex") results = opt.solve(switch_instance, keepfiles=False, tee=False) switch_model.save_results(results, switch_instance, "outputs") # results.write() switch_instance.pprint()
import switch_mod.utilities as utilities import sys, os from pyomo.environ import * print "creating model for scenario input generation..." try: module_fh = open(os.path.join(inputs_dir, 'modules'), 'r') except IOError, exc: sys.exit('Failed to open input file: {}'.format(exc)) module_list = [line.rstrip('\n') for line in module_fh] module_list.insert(0,'switch_mod') model = utilities.define_AbstractModel(*module_list) print "model successfully created..." print "loading inputs into model..." instance = model.load_inputs(inputs_dir=inputs_dir) print "inputs successfully loaded..." def save_dat_files(): if not os.path.exists(os.path.join(inputs_dir, pysp_subdir)): os.makedirs(os.path.join(inputs_dir, pysp_subdir)) ############## # RootNode.dat
# Licensed under the Apache License, Version 2, which is in the LICENSE file. """ Illustrate the use of switch to construct and run a toy model with three load zones and two investment period where the first investment period has more temporal resolution than the second. Note, the results from this have not been fully evaluated. For this to work, you need to ensure that the switch_mod package directory is in your python search path. See the README for more info. """ from pyomo.environ import * from pyomo.opt import SolverFactory from switch_mod.utilities import define_AbstractModel switch_model = define_AbstractModel( 'switch_mod', 'local_td', 'project.no_commit', 'fuel_markets', 'trans_build', 'trans_dispatch') switch_instance = switch_model.load_inputs(inputs_dir="inputs") opt = SolverFactory("cplex") results = opt.solve(switch_instance, keepfiles=False, tee=False) switch_model.save_results(results, switch_instance, "outputs") results.write() switch_instance.pprint()
#!/usr/local/bin/python # Copyright 2015 The Switch Authors. All rights reserved. # Licensed under the Apache License, Version 2, which is in the LICENSE file. """ Illustrate the use of switch to construct and run a very simple model with a single load zone, one investment period, and two timepoints. This model neglects local transmission and distribution as well. For this to work, you need to ensure that the switch_mod package directory is in your python search path. See the README for more info. """ from pyomo.environ import * from pyomo.opt import SolverFactory from switch_mod.utilities import define_AbstractModel switch_model = define_AbstractModel('switch_mod', 'project.no_commit', 'fuel_cost', 'sunk_costs') switch_instance = switch_model.load_inputs(inputs_dir="inputs") opt = SolverFactory("cplex") results = opt.solve(switch_instance, keepfiles=False, tee=False) switch_instance.load(results) results.write() switch_instance.pprint()
#!/usr/local/bin/python # Copyright 2015 The Switch Authors. All rights reserved. # Licensed under the Apache License, Version 2, which is in the LICENSE file. """ Illustrate the use of switch to construct and run a very simple production-cost model with a single load zone, one investment period, and four timepoints. Includes variable generation. For this to work, you need to ensure that the switch_mod package directory is in your python search path. See the README for more info. """ from pyomo.environ import * from pyomo.opt import SolverFactory from switch_mod.utilities import define_AbstractModel switch_model = define_AbstractModel('switch_mod', 'local_td', 'project.unitcommit', 'project.unitcommit.discrete', 'fuel_cost') switch_instance = switch_model.load_data(inputs_dir="inputs") opt = SolverFactory("cplex") results = opt.solve(switch_instance, keepfiles=False, tee=False) switch_instance.load(results) results.write() switch_instance.pprint()
def solve( inputs='inputs', outputs='outputs', rps=True, renewables=True, demand_response=False, ev=None, pumped_hydro=False, ph_year=None, ph_mw=None, tag=None, thread=None, nthreads=3 ): # load and solve the model, using specified configuration # NOTE: this version solves repeatedly with different DR targets global switch_model, switch_instance, results, output_dir modules = ['switch_mod', 'fuel_cost', 'project.no_commit', 'switch_patch', 'batteries'] if rps: modules.append('rps') if not renewables: modules.append('no_renewables') if demand_response: modules.append('simple_dr') # repeat with a range of DR shares all_dr_shares = [0.00, 0.20, 0.40, 0.05, 0.15, 0.25, 0.35, 0.30, 0.10] if thread is None: dr_shares = all_dr_shares else: # take every nth element from all_dr_shares, starting with element i, where i=thread (1-based) and n=nthreads dr_shares = [all_dr_shares[x] for x in range(thread-1, len(all_dr_shares), nthreads)] else: # no_demand_response dr_shares = [0.00] if ev is None: # not specified, leave out ev's pass elif ev: # user asked for ev modules.append('ev') else: # user asked for no_ev (count transport emissions but don't allow EVs) modules.append('no_ev') if pumped_hydro: modules.append('pumped_hydro') log('using modules: {m}\n'.format(m=modules)) log("defining model... "); tic() switch_model = define_AbstractModel(*modules) switch_model.iis = Suffix(direction=Suffix.IMPORT) switch_model.dual = Suffix(direction=Suffix.IMPORT) # force construction of a fixed amount of pumped hydro if ph_mw is not None: print "Forcing construction of {m} MW of pumped hydro.".format(m=ph_mw) switch_model.Build_Pumped_Hydro_MW = Constraint(switch_model.LOAD_ZONES, rule=lambda m, z: m.Pumped_Hydro_Capacity_MW[z, m.PERIODS.last()] == ph_mw ) # force construction of pumped hydro only in a certain period if ph_year is not None: print "Allowing construction of pumped hydro only in {p}.".format(p=ph_year) switch_model.Build_Pumped_Hydro_Year = Constraint( switch_model.LOAD_ZONES, switch_model.PERIODS, rule=lambda m, z, p: m.BuildPumpedHydroMW[z, p] == 0 if p != ph_year else Constraint.Skip ) toc() # done defining model log("loading model data from {} dir... ".format(inputs)); tic() switch_instance = switch_model.load_inputs(inputs_dir=inputs) toc() output_dir = outputs setup_results_dir() create_batch_results_file(switch_instance, tag=tag) log("dr_shares = " + str(dr_shares) + "\n") for dr_share in dr_shares: if demand_response: switch_instance.demand_response_max_share = dr_share switch_instance.preprocess() tic() log("solving model with max DR={dr}...\n".format(dr=dr_share)) results = opt.solve(switch_instance, keepfiles=False, tee=True, # options='dualopt', # not sure how to put this in opt.options symbolic_solver_labels=True, suffixes=['dual', 'iis']) log("Solver finished; "); toc() # results.write() log("loading solution... "); tic() # Pyomo changed their interface for loading results somewhere # between 4.0.x and 4.1.x in a way that was not backwards compatible. # Make the code accept either version if hasattr(switch_instance, 'solutions'): # Works in Pyomo version 4.1.x switch_instance.solutions.load_from(results) else: # Works in Pyomo version 4.0.9682 switch_instance.load(results) toc() if results.solver.termination_condition == TerminationCondition.infeasible: print "Model was infeasible; Irreducible Infeasible Set (IIS) returned by solver:" print "\n".join(c.cname() for c in switch_instance.iis) if util.interactive_session: print "Unsolved model is available as switch_instance." raise RuntimeError("Infeasible model") if util.interactive_session: print "Model solved successfully." print "Solved model is available as switch_instance." print "\n\n=======================================================" print "Solved model" print "=======================================================" print "Total cost: ${v:,.0f}".format(v=value(switch_instance.Minimize_System_Cost)) if pumped_hydro: switch_instance.BuildPumpedHydroMW.pprint() append_batch_results(switch_instance, tag=tag) t = "" if tag is None else str(tag) + "_" write_results(switch_instance, tag=t+'dr_share_'+str(dr_share))
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../../../switch'))) import util from pyomo.environ import * from pyomo.opt import SolverFactory, SolverStatus, TerminationCondition import switch_mod.utilities as utilities print "loading model..." switch_modules = ( 'switch_mod', 'project.unitcommit', 'project.unitcommit.discrete', 'fuel_cost' ) utilities.load_modules(switch_modules) switch_model = utilities.define_AbstractModel(switch_modules) switch_model.iis = Suffix(direction=Suffix.IMPORT) inputs_dir = 'inputs' switch_data = utilities.load_data(switch_model, inputs_dir, switch_modules) switch_instance = switch_model.create(switch_data) opt = SolverFactory("cplex", tee=True, solver_io="nl") # tell cplex to find an irreducible infeasible set (and report it) opt.options['iisfind'] = 1 # relax the integrality constraints, to allow commitment constraints to match up with # number of units available opt.options['mipgap'] = 0.001 print "solving model..."
'batteries' ] # customize module list based on environment variables (if set) add_modules = os.getenv("INCLUDE_MODULES", None): if add_modules is not None: print "Adding modules: {}".format(add_modules) module_list.extend(add_modules.split(" ")) drop_modules = os.getenv("EXCLUDE_MODULES", None): if drop_modules is not None: print "Excluding modules: {}".format(drop_modules) for m in drop_modules.split(" "): module_list.remove(m) model = define_AbstractModel(*module_list) # add dummy expressions to keep runph happy # note: we may need to delve into the objective expression # and apportion its elements between these based on whether # they are in the build_variables list or not model.BuildCost = Expression(rule=lambda m: 0.0) model.OperateCost = Expression(rule=lambda m: m.Minimize_System_Cost.expr) # define upper and lower reduced costs to use when setting rho # model.iis = Suffix(direction=Suffix.IMPORT) model.dual = Suffix(direction=Suffix.IMPORT) model.urc = Suffix(direction=Suffix.IMPORT) model.lrc = Suffix(direction=Suffix.IMPORT) model.rc = Suffix(direction=Suffix.IMPORT) # always create the model when the module is imported, # so it can be used by runph
#!/usr/local/bin/python # Copyright 2015 The Switch Authors. All rights reserved. # Licensed under the Apache License, Version 2, which is in the LICENSE file. """ Illustrate the use of switch to construct and run a very simple model with a single load zone, one investment period, and one timepoint. For this to work, you need to ensure that the switch_mod package directory is in your python search path. See the README for more info. """ from pyomo.environ import * from pyomo.opt import SolverFactory from switch_mod.utilities import define_AbstractModel switch_model = define_AbstractModel( 'switch_mod', 'local_td', 'project.discrete_build', 'project.no_commit', 'fuel_markets') switch_instance = switch_model.load_inputs(inputs_dir="inputs") opt = SolverFactory("cplex") results = opt.solve(switch_instance, keepfiles=False, tee=False) switch_instance.load(results) results.write() switch_instance.pprint()
def solve( inputs_dir='inputs', inputs_subdir='', outputs_dir='outputs', rps=True, renewables=True, wind=None, central_pv=None, batteries=True, demand_response_simple=True, dr_shares=[0.3], ev=True, pumped_hydro=True, ph_year=None, ph_mw=None, hydrogen=True, fed_subsidies=False, biofuel_limit=0.05, ev_flat=False, scenario_name=None, tag=None ): # load and solve the model, using specified configuration # NOTE: this version solves repeatedly with different DR targets global switch_model, switch_instance, results, output_dir # quick fix to use scenario name and (optional) tag tag = None if scenario_name is None else append_tag(scenario_name, tag) # quick fix for inputs_dir / inputs_subdir inputs_dir = os.path.join(inputs_dir, inputs_subdir) modules = ['switch_mod', 'fuel_markets', 'fuel_markets_expansion', 'project.no_commit', 'switch_patch', 'rps'] modules.append('emission_rules') # no burning LSFO after 2017 except in cogen plants for m in ['ev', 'pumped_hydro', 'fed_subsidies', 'demand_response_simple', 'hydrogen', 'batteries']: if locals()[m] is True: modules.append(m) if demand_response_simple is not True: dr_shares = [0.00] # TODO: treat the 'no_*' modules as standard scenario names # (i.e., include no_renewables, etc. instead of excluding renewables, etc.) if renewables is False: modules.append('no_renewables') if wind is False: modules.append('no_wind') if central_pv is False: modules.append('no_central_pv') if ev is False: # user asked for no_ev (count transport emissions but don't allow EVs) modules.append('no_ev') log('using modules: {m}\n'.format(m=modules)) log("defining model... "); tic() switch_model = define_AbstractModel(*modules) switch_model.iis = Suffix(direction=Suffix.IMPORT) switch_model.dual = Suffix(direction=Suffix.IMPORT) # TODO: put scenario flags into a switch_model.config dictionary and then # do the following model modifications within the respective modules. # force construction of a fixed amount of pumped hydro if ph_mw is not None: print "Forcing construction of {m} MW of pumped hydro.".format(m=ph_mw) switch_model.Build_Pumped_Hydro_MW = Constraint(switch_model.LOAD_ZONES, rule=lambda m, z: m.Pumped_Hydro_Capacity_MW[z, m.PERIODS.last()] == ph_mw ) # force construction of pumped hydro only in a certain period if ph_year is not None: print "Allowing construction of pumped hydro only in {p}.".format(p=ph_year) switch_model.Build_Pumped_Hydro_Year = Constraint( switch_model.PH_PROJECTS, switch_model.PERIODS, rule=lambda m, pr, pe: m.BuildPumpedHydroMW[pr, pe] == 0 if pe != ph_year else Constraint.Skip ) if biofuel_limit is not None: print "Limiting (bio)fuels to {l}% of electricity production.".format(l=biofuel_limit*100.0) switch_model.rps_fuel_limit = biofuel_limit if ev_flat and ev: print "Charging EVs as baseload." switch_model.ChargeEVs_flat = Constraint( switch_model.LOAD_ZONES, switch_model.TIMEPOINTS, rule=lambda m, z, tp: m.ChargeEVs[z, tp] * m.ts_duration_hrs[m.tp_ts[tp]] == m.ev_mwh_ts[z, m.tp_ts[tp]] ) # add an alternative objective function that smoothes out various non-cost variables def Smooth_Free_Variables_obj_rule(m): # minimize production (i.e., maximize curtailment / minimize losses) obj = sum( getattr(m, component)[lz, t] for lz in m.LOAD_ZONES for t in m.TIMEPOINTS for component in m.LZ_Energy_Components_Produce) # also minimize the magnitude of demand adjustments if hasattr(m, "DemandResponse"): print "Will smooth DemandResponse." obj = obj + sum(m.DemandResponse[z, t]*m.DemandResponse[z, t] for z in m.LOAD_ZONES for t in m.TIMEPOINTS) # also minimize the magnitude of EV charging if hasattr(m, "ChargeEVs"): print "Will smooth EV charging." obj = obj + sum(m.ChargeEVs[z, t]*m.ChargeEVs[z, t] for z in m.LOAD_ZONES for t in m.TIMEPOINTS) return obj switch_model.Smooth_Free_Variables = Objective(rule=Smooth_Free_Variables_obj_rule, sense=minimize) toc() # done defining model log("loading model data from {} dir... ".format(inputs_dir)); tic() switch_instance = switch_model.load_inputs(inputs_dir=inputs_dir) toc() if rps is False: # deactivate the main RPS constraint # (we do this instead of omitting the whole RPS module, # so we can report RPS-qualified power even if the RPS is not in effect) # NOTE: for now, there's no easy way to pass solver flags into individual modules # which would probably be a cleaner solution switch_instance.RPS_Enforce.deactivate() switch_instance.preprocess() # investigate the cost_components_annual elements # import pdb; pdb.set_trace() output_dir = outputs_dir # assign to global variable with slightly different name (ugh) setup_results_dir() create_batch_results_file(switch_instance, scenario=tag) log("dr_shares = " + str(dr_shares) + "\n") for dr_share in dr_shares: if demand_response_simple: switch_instance.demand_response_max_share = dr_share switch_instance.preprocess() log("solving model with max DR={dr}...\n".format(dr=dr_share)) # make sure the minimum-cost objective is in effect switch_instance.Smooth_Free_Variables.deactivate() switch_instance.Minimize_System_Cost.activate() results = _solve(switch_instance) if results.solver.termination_condition == TerminationCondition.infeasible: print "Model was infeasible; Irreducible Infeasible Set (IIS) returned by solver:" print "\n".join(c.cname() for c in switch_instance.iis) if util.interactive_session: print "Unsolved model is available as switch_instance." raise RuntimeError("Infeasible model") append_batch_results(switch_instance, scenario=tag+'_unsmooth') if len(dr_shares) > 1: t = ("" if tag is None else str(tag) + '_') + 'dr_share_' + str(dr_share) else: t = tag if solver == "cplex": # Freeze all direct-cost variables, and then solve the model against # a smoothing objective instead of a cost objective. # (only applied for quadratic solvers, i.e., cplex) write_results(switch_instance, tag=t+'_unsmooth') # keep pre-smoothing results, in case smoothing crashes old_duals = [ (z, t, switch_instance.dual[switch_instance.Energy_Balance[z, t]]) for z in switch_instance.LOAD_ZONES for t in switch_instance.TIMEPOINTS] fix_obj_expression(switch_instance.Minimize_System_Cost) switch_instance.Minimize_System_Cost.deactivate() switch_instance.Smooth_Free_Variables.activate() switch_instance.preprocess() log("smoothing free variables...\n") results = _solve(switch_instance) # restore hourly duals from the original solution for (z, t, d) in old_duals: switch_instance.dual[switch_instance.Energy_Balance[z, t]] = d # unfix the variables fix_obj_expression(switch_instance.Minimize_System_Cost, False) log("finished smoothing free variables; "); toc() if util.interactive_session: print "Model solved successfully." print "Solved model is available as switch_instance." print "\n\n=======================================================" print "Solved model" print "=======================================================" print "Total cost: ${v:,.0f}".format(v=value(switch_instance.Minimize_System_Cost)) # if pumped_hydro: # switch_instance.BuildPumpedHydroMW.pprint() if hasattr(switch_instance, "ChargeBattery"): double_charge = [ ( z, t, switch_instance.ChargeBattery[z, t].value, switch_instance.DischargeBattery[z, t].value ) for z in switch_instance.LOAD_ZONES for t in switch_instance.TIMEPOINTS if switch_instance.ChargeBattery[z, t].value > 0 and switch_instance.DischargeBattery[z, t].value > 0 ] if len(double_charge) > 0: print "" print "WARNING: batteries are simultaneously charged and discharged in some hours." print "This is usually done to relax the biofuel limit." for (z, t, c, d) in double_charge: print 'ChargeBattery[{z}, {t}]={c}, DischargeBattery[{z}, {t}]={d}'.format( z=z, t=switch_instance.tp_timestamp[t], c=c, d=d ) append_batch_results(switch_instance, scenario=tag) if len(dr_shares) > 1: t = ("" if tag is None else str(tag) + '_') + 'dr_share_' + str(dr_share) else: t = tag write_results(switch_instance, tag=t)
# number of units available opt.options['mipgap'] = 0.001 print "loading model..." # tell pyomo to make all parameters mutable by default # (I only need to change lz_demand_mw, but this is currently the only way to make # any parameter mutable without changing the core code.) # NOTE: this causes errors like "TypeError: unhashable type: '_ParamData'" # when any parameters are used as indexes into a set (e.g., m.ts_scale_to_period[ts]) # This may be a pyomo bug, but it's hard to work around in the short term. # Param.DefaultMutable = True switch_model = define_AbstractModel( 'switch_mod', 'fuel_cost', 'project.no_commit', #'project.unitcommit', 'project.unitcommit.discrete', 'demand_response', 'rps', 'switch_patch' ) #switch_model.iis = Suffix(direction=Suffix.IMPORT) switch_model.dual = Suffix(direction=Suffix.IMPORT) switch_instance = switch_model.load_inputs(inputs_dir="inputs") results = None # defined globally for convenient access in interactive session def iterate(): global switch_model, switch_instance, results # NOTE: some evil magic in demand_response # turns on bid adjusting behavior if "adj_bad_bids" is in the tag # or bid dropping behavior if "drop_bad_bids" is in the tag tag = 'accel_rps_fixed_ce_1'
#!/usr/local/bin/python # Copyright 2015 The Switch Authors. All rights reserved. # Licensed under the Apache License, Version 2, which is in the LICENSE file. """ Illustrate the use of switch to construct and run a very simple model with a single load zone, one investment period, and two timepoints. This expands on copperplate0.py by adding a few more types of generators as well as local transmission and distribution. For this to work, you need to ensure that the switch_mod package directory is in your python search path. See the README for more info. """ from pyomo.environ import * from pyomo.opt import SolverFactory from switch_mod.utilities import define_AbstractModel switch_model = define_AbstractModel( 'switch_mod', 'local_td', 'project.no_commit', 'fuel_markets') switch_instance = switch_model.load_inputs(inputs_dir="inputs") opt = SolverFactory("cplex") results = opt.solve(switch_instance, keepfiles=False, tee=False) switch_instance.load(results) results.write() switch_instance.pprint()
into gen_inc_heat_rates.tab if you want to play around with the model behavior. In both versions of incremental heat rate tables, I gave natural gas combustion turbines a very minor heat rate penalty to discourage committing more capacity than is needed. I changed the incremental heat rate to 99 percent of the full load heat rate, with 1 percent of the fuel use incurred at 0 electricity output. For this to work, you need to ensure that the switch_mod package directory is in your python search path. See the README for more info. """ from pyomo.environ import * from pyomo.opt import SolverFactory from switch_mod.utilities import define_AbstractModel switch_model = define_AbstractModel("switch_mod", "local_td", "project.unitcommit", "fuel_cost") switch_instance = switch_model.load_inputs(inputs_dir="inputs") opt = SolverFactory("cplex") results = opt.solve(switch_instance, keepfiles=False, tee=False) switch_model.save_results(results, switch_instance, "outputs") # Dump all results # switch_instance.load(results) results.write() switch_instance.pprint()
def solve( inputs='inputs', rps=True, demand_response=True, renewables=True, ev=None, pumped_hydro=True, ph_year=None, ph_mw=None, tag=None ): global switch_model, switch_instance, results modules = ['switch_mod', 'fuel_cost', 'project.no_commit', 'switch_patch', 'batteries'] if rps: modules.append('rps') if not renewables: modules.append('no_renewables') if demand_response: modules.append('simple_dr') if ev is None: # not specified, leave out ev's pass elif ev: # user asked for ev modules.append('ev') else: # user asked for no_ev modules.append('no_ev') if pumped_hydro: modules.append('pumped_hydro') log('using modules: {m}\n'.format(m=modules)) log("defining model... "); tic() switch_model = define_AbstractModel(*modules) switch_model.iis = Suffix(direction=Suffix.IMPORT) switch_model.dual = Suffix(direction=Suffix.IMPORT) # force construction of a fixed amount of pumped hydro if pumped_hydro and ph_mw is not None: print "Forcing construction of {m} MW of pumped hydro.".format(m=ph_mw) switch_model.Build_Pumped_Hydro_MW = Constraint(switch_model.LOAD_ZONES, rule=lambda m, z: m.Pumped_Hydro_Capacity_MW[z, m.PERIODS.last()] == ph_mw ) # force construction of pumped hydro only in a certain period if pumped_hydro and ph_year is not None: print "Allowing construction of pumped hydro only in {p}.".format(p=ph_year) switch_model.Build_Pumped_Hydro_Year = Constraint( switch_model.LOAD_ZONES, switch_model.PERIODS, rule=lambda m, z, p: m.BuildPumpedHydroMW[z, p] == 0 if p != ph_year else Constraint.Skip ) toc() # done defining model log("loading model data from {} dir... ".format(inputs)); tic() switch_instance = switch_model.load_inputs(inputs_dir=inputs) toc() log("solving model...\n"); tic() results = opt.solve(switch_instance, keepfiles=False, tee=True, symbolic_solver_labels=True, suffixes=['dual', 'iis']) log("Solver finished; "); toc() # results.write() log("loading solution... "); tic() # Pyomo changed their interface for loading results somewhere # between 4.0.x and 4.1.x in a way that was not backwards compatible. # Make the code accept either version if hasattr(switch_instance, 'solutions'): # Works in Pyomo version 4.1.x switch_instance.solutions.load_from(results) else: # Works in Pyomo version 4.0.9682 switch_instance.load(results) toc() if results.solver.termination_condition == TerminationCondition.infeasible: print "Model was infeasible; Irreducible Infeasible Set (IIS) returned by solver:" print "\n".join(c.cname() for c in switch_instance.iis) if util.interactive_session: print "Unsolved model is available as switch_instance." raise RuntimeError("Infeasible model") if util.interactive_session: print "Model solved successfully." print "Solved model is available as switch_instance." print "\n\n=======================================================" print "Solved model" print "=======================================================" print "Total cost: ${v:,.0f}".format(v=value(switch_instance.Minimize_System_Cost)) if pumped_hydro: switch_instance.BuildPumpedHydroMW.pprint() write_results(switch_instance, tag=tag)