def _setup_concave(b, nsegs, indx): if not hasattr(b, 'sets'): if indx is None: b.sets = Set() else: b.sets = Set(dimen=len(indx)) if not hasattr(b, 'underest'): if indx is not None: b.underest = Constraint(b.sets) else: b.underest = Constraint() if not hasattr(b, 'segs'): b.segs = RangeSet(nsegs) b.segs_m1 = RangeSet(nsegs - 1, within=b.segs) else: if nsegs != len(b.segs): raise ValueError( 'We do not currently support different segment counts within the same set of McCormick relaxations.' ) if not hasattr(b, 'x_defn'): if indx is not None: b.x_defn = Constraint(b.sets, ['lb', 'ub']) else: b.x_defn = Constraint(['lb', 'ub']) if not hasattr(b, 'delta'): if indx is not None: b.delta = Var(b.sets, b.segs, domain=NonNegativeReals, initialize=0) else: b.delta = Var(b.segs, domain=NonNegativeReals, initialize=0) if not hasattr(b, 'delta_defn'): if indx is not None: b.delta_defn = Constraint(b.sets, b.segs, ['lb', 'ub']) else: b.delta_defn = Constraint(b.segs, ['lb', 'ub']) if not hasattr(b, 'omega'): if indx is not None: b.omega = Var(b.sets, b.segs_m1, domain=Binary) else: b.omega = Var(b.segs_m1, domain=Binary) if not hasattr(b, 'omega_exist'): if indx is not None: b.omega_exist = Constraint(b.sets) else: b.omega_exist = Constraint() if not hasattr(b, 'w'): # define bilinear w = y * x if indx is not None: b.w = Var(b.sets, domain=NonNegativeReals) else: b.w = Var(domain=NonNegativeReals) if not hasattr(b, 'overest'): if indx is not None: b.overest = Constraint(b.sets, ['lb', 'ub']) else: b.overest = Constraint(['lb', 'ub']) if not hasattr(b, 'w_defn'): if indx is not None: b.w_defn = Constraint(b.sets, ['lb1', 'ub1', 'lb2', 'ub2']) else: b.w_defn = Constraint(['lb1', 'ub1', 'lb2', 'ub2'])
def Model_Creation(model): ''' This function creates the instance for the resolution of the optimization in Pyomo. :param model: Pyomo model as defined in the Micro-Grids library. ''' # Time parameters model.Periods = Param( within=NonNegativeReals ) # Number of periods of analysis of the energy variables model.Years = Param() # Number of years of the project model.StartDate = Param() # Start date of the analisis model.PlotTime = Param() # Quantity of days that are going to be plot model.PlotDay = Param() # Start day for the plot model.PlotScenario = Param() model.Scenarios = Param() # Classes Parameters model.Classes = Param( within=NonNegativeReals ) #Creation of a set from 1 to the number of classes of the thermal part #SETS model.periods = RangeSet( 1, model.Periods ) # Creation of a set from 1 to the number of periods in each year model.years = RangeSet( 1, model.Years ) # Creation of a set from 1 to the number of years of the project model.scenario = RangeSet( 1, model.Scenarios ) # Creation of a set from 1 to the numbero scenarios to analized model.classes = RangeSet( 1, model.Classes ) # Creation of a set from 1 to the number of classes of the thermal part # PARAMETERS # Parameters of the PV model.PV_Nominal_Capacity = Param( within=NonNegativeReals) # Nominal capacity of the PV in W/unit model.Inverter_Efficiency = Param() # Efficiency of the inverter in % model.PV_invesment_Cost = Param( within=NonNegativeReals) # Cost of solar panel in USD/W model.PV_Energy_Production = Param( model.scenario, model.periods, within=NonNegativeReals, initialize=Initialize_PV_Energy ) # Energy produccion of a solar panel in W # Parameters of the SC (Solare Collectors) model.SC_Nominal_Capacity = Param( within=NonNegativeReals) #Nominal capacity of the Solar Collectors model.SC_investment_Cost = Param( within=NonNegativeReals) # Cost of SC pannel in USD/W model.SC_Energy_Production = Param(model.scenario, model.classes, model.periods, within=NonNegativeReals, initialize=Initialize_SC_Energy) # Parameters of the battery bank model.Charge_Battery_Efficiency = Param( ) # Efficiency of the charge of the battery in % model.Discharge_Battery_Efficiency = Param( ) # Efficiency of the discharge of the battery in % model.Deep_of_Discharge = Param( ) # Deep of discharge of the battery (Deep_of_Discharge) in % model.Maximun_Battery_Charge_Time = Param( within=NonNegativeReals ) # Minimun time of charge of the battery in hours model.Maximun_Battery_Discharge_Time = Param( within=NonNegativeReals ) # Maximun time of discharge of the battery in hours model.Battery_Reposition_Time = Param( within=NonNegativeReals ) # Period of repocition of the battery in years model.Battery_Invesment_Cost = Param( within=NonNegativeReals) # Cost of battery # Parameters of the TANK storage model.Tank_Efficiency = Param() # Efficiency of the tank % model.Tank_Invesment_Cost = Param( within=NonNegativeReals) # Cost of unit Tank USD/W model.Deep_of_Tank_Discharge = Param() model.Maximun_Tank_Discharge_Time = Param(within=NonNegativeReals) # Parametes of the diesel generator model.Generator_Efficiency = Param( ) # Generator efficiency to trasform heat into electricity % model.Low_Heating_Value = Param() # Low heating value of the diesel in W/L model.Diesel_Unitary_Cost = Param( within=NonNegativeReals) # Cost of diesel in USD/L model.Generator_Invesment_Cost = Param( within=NonNegativeReals) # Cost of the diesel generator # Parameters of the Boiler model.Boiler_Efficiency = Param() # Boiler efficiency % model.Low_Heating_Value_NG = Param( ) # Low heating value of the natural gas in W/L model.NG_Unitary_Cost = Param( within=NonNegativeReals) # Cost of natural gas in USD/L model.Boiler_Invesment_Cost = Param( within=NonNegativeReals) # Cost of the NG Boiler # Parameters of the Electric Resistance model.Electric_Resistance_Efficiency = Param( ) # Electric Resistance efficiency % model.Resistance_Invesment_Cost = Param(within=NonNegativeReals) # Parameters of the Energy balance model.Energy_Demand = Param( model.scenario, model.periods, initialize=Initialize_Demand) # Energy Energy_Demand in W model.Lost_Load_Probability = Param( within=NonNegativeReals) # Lost load probability in % model.Value_Of_Lost_Load = Param( within=NonNegativeReals) # Value of lost load in USD/W model.Thermal_Energy_Demand = Param( model.scenario, model.classes, model.periods, initialize=Initialize_Thermal_Demand) # Thermal Energy Demand in W # Parameters of the proyect model.Delta_Time = Param(within=NonNegativeReals) # Time step in hours model.Porcentage_Funded = Param( within=NonNegativeReals ) # Porcentaje of the total investment that is Porcentage_Porcentage_Funded by a bank or another entity in % model.Project_Years = Param( model.years, initialize=Initialize_years) # Years of the project model.Maintenance_Operation_Cost_PV = Param( within=NonNegativeReals ) # Percentage of the total investment spend in operation and management of solar panels in each period in % model.Maintenance_Operation_Cost_Battery = Param( within=NonNegativeReals ) # Percentage of the total investment spend in operation and management of solar panels in each period in % model.Maintenance_Operation_Cost_Generator = Param( within=NonNegativeReals ) # Percentage of the total investment spend in operation and management of solar panels in each period in % model.Discount_Rate = Param() # Discount rate of the project in % model.Interest_Rate_Loan = Param() # Interest rate of the loan in % model.Scenario_Weight = Param(model.scenario, within=NonNegativeReals) ######### model.Users_Number_Class = Param( model.classes, within=NonNegativeReals ) # This parameter defines the number of users for each class model.Maintenance_Operation_Cost_SC = Param( within=NonNegativeReals ) # Percentage of the total investment spend in operation and management of solar collectors in each period in % model.Maintenance_Operation_Cost_Boiler = Param( within=NonNegativeReals ) # Percentage of the total investment spend in operation and management of boiler in each period in % model.Maintenance_Operation_Cost_Tank = Param( within=NonNegativeReals ) # Percentage of the total investment spend in operation and management of tank in each period in % model.Maintenance_Operation_Cost_Resistance = Param( within=NonNegativeReals ) # Percentage of the total investment spend in operation and management of resistance in each period in % # VARIABLES # Variables associated to the solar panels model.PV_Units = Var( within=NonNegativeReals) # Number of units of solar panels model.Total_Energy_PV = Var( model.scenario, model.periods, within=NonNegativeReals) # Energy generated for the Pv sistem in Wh model.SC_Units = Var( model.classes, within=NonNegativeReals) # Number of units of solar collector model.Total_Energy_SC = Var( model.scenario, model.classes, model.periods, within=NonNegativeReals) # Energy generated by solar collectors # Variables associated to the battery bank model.Battery_Nominal_Capacity = Var( within=NonNegativeReals) # Capacity of the battery bank in Wh model.Energy_Battery_Flow_Out = Var( model.scenario, model.periods, within=NonNegativeReals) # Battery discharge energy in wh model.Energy_Battery_Flow_In = Var( model.scenario, model.periods, within=NonNegativeReals) # Battery charge energy in wh model.State_Of_Charge_Battery = Var( model.scenario, model.periods, within=NonNegativeReals) # State of Charge of the Battery in wh model.Maximun_Charge_Power = Var() # Maximun charge power in w model.Maximun_Discharge_Power = Var() #Maximun discharge power in w # Variables associated to the storage TANK model.Tank_Nominal_Capacity = Var( model.classes, within=NonNegativeReals) # Capacity of the tank in Wh model.Energy_Tank_Flow_Out = Var( model.scenario, model.classes, model.periods, within=NonNegativeReals) # Tank unit discharge energy in Wh model.SOC_Tank = Var( model.scenario, model.classes, model.periods, within=NonNegativeReals) # State of Charge of the Tank in wh model.Maximun_Tank_Discharge_Power = Var(model.classes) # Variables associated to the diesel generator model.Generator_Nominal_Capacity = Var( within=NonNegativeReals) # Capacity of the diesel generator in Wh model.Diesel_Consume = Var( model.scenario, model.periods, within=NonNegativeReals ) # Diesel consumed to produce electric energy in L model.Generator_Energy = Var( model.scenario, model.periods, within=NonNegativeReals) # Energy generated for the Diesel generator model.Diesel_Cost_Total = Var(model.scenario, within=NonNegativeReals) ## Variables associated to the Boiler model.Boiler_Nominal_Capacity = Var( model.classes, within=NonNegativeReals) # Capacity of the boiler in Wh model.NG_Consume = Var( model.scenario, model.classes, model.periods, within=NonNegativeReals ) # Natural Gas consumed to produce thermal energy in Kg (considering Liquified Natural Gas) model.Boiler_Energy = Var( model.scenario, model.classes, model.periods, within=NonNegativeReals) # Energy generated by the boiler model.NG_Cost_Total = Var(model.scenario, within=NonNegativeReals) # Variables associated to the RESISTANCE model.Nominal_Power_Resistance = Var( model.classes, within=NonNegativeReals ) # Electric Nominal power of the thermal resistance model.Resistance_Thermal_Energy = Var( model.scenario, model.classes, model.periods, within=NonNegativeReals ) # Total Electric power considering all the users in each class model.Total_Electrical_Resistance_Demand = Var( model.scenario, model.periods, within=NonNegativeReals ) # Total Resistance Energy required by the electrical supply considered in the electric energy balance # Varialbles associated to the energy balance model.Lost_Load = Var( model.scenario, model.periods, within=NonNegativeReals) # Energy not suply by the system kWh model.Lost_Load_Th = Var( model.scenario, model.classes, model.periods, within=NonNegativeReals) # Energy not suply by the system kWh model.Energy_Curtailment = Var( model.scenario, model.periods, within=NonNegativeReals) # Curtailment of solar energy in kWh model.Scenario_Lost_Load_Cost = Var(model.scenario, within=NonNegativeReals) #### model.Scenario_Lost_Load_Cost_Th = Var(model.scenario, within=NonNegativeReals) #### model.Thermal_Energy_Curtailment = Var(model.scenario, model.classes, model.periods, within=NonNegativeReals) model.Total_Thermal_Energy_Demand = Var( model.scenario, model.classes, model.periods, within=NonNegativeReals ) # This is the thermal demand considering all the users in that class # Variables associated to the financial costs model.SC_Financial_Cost = Var( within=NonNegativeReals ) # Financial cost of SC technology considering all the classes model.Tank_Financial_Cost = Var( within=NonNegativeReals ) # Financial cost of Tank technology considering all the classes (he investment tank costs include the resistance cost) model.Boiler_Financial_Cost = Var( within=NonNegativeReals ) # Financial cost of Boiler technology considering all the classes model.Resistance_Financial_Cost = Var( within=NonNegativeReals ) # Financial cost of Boiler technology considering all the classes # Variables associated to the project model.Cost_Financial = Var( within=NonNegativeReals) # Financial cost of each period in USD model.Scenario_Net_Present_Cost = Var(model.scenario, within=NonNegativeReals) #### model.Initial_Inversion = Var(within=NonNegativeReals) model.Operation_Maintenance_Cost = Var(within=NonNegativeReals) model.Total_Finalcial_Cost = Var(within=NonNegativeReals) model.Battery_Reposition_Cost = Var(within=NonNegativeReals)
# Under the terms of Contract DE-NA0003525 with National Technology and # Engineering Solutions of Sandia, LLC, the U.S. Government retains certain # rights in this software. # This software is distributed under the 3-clause BSD License. # ___________________________________________________________________________ from pyomo.environ import ConcreteModel, RangeSet, Param, Var, Reals, Binary, Objective, Constraint, ConstraintList import math N = 5 M = 6 P = 3 model = ConcreteModel() model.Locations = RangeSet(1,N) model.Customers = RangeSet(1,M) def d_rule(model, n, m): return math.sin(n*2.33333+m*7.99999) model.d = Param(model.Locations, model.Customers, initialize=d_rule, within=Reals) model.x = Var(model.Locations, model.Customers, bounds=(0.0,1.0)) model.y = Var(model.Locations, within=Binary) def rule(model): return sum( [model.d[n,m]*model.x[n,m] for n in model.Locations for m in model.Customers] ) model.obj = Objective(rule=rule)
def test_nonnegativity_transformation_2(self): self.model.S = RangeSet(0, 10) self.model.T = Set(initialize=["foo", "bar"]) # Unindexed, singly indexed, and doubly indexed variables with # explicit bounds self.model.x1 = Var(bounds=(-3, 3)) self.model.y1 = Var(self.model.S, bounds=(-3, 3)) self.model.z1 = Var(self.model.S, self.model.T, bounds=(-3, 3)) # Unindexed, singly indexed, and doubly indexed variables with # rule-defined bounds def boundsRule(*args): return (-4, 4) self.model.x2 = Var(bounds=boundsRule) self.model.y2 = Var(self.model.S, bounds=boundsRule) self.model.z2 = Var(self.model.S, self.model.T, bounds=boundsRule) # Unindexed, singly indexed, and doubly indexed variables with # explicit domains self.model.x3 = Var(domain=NegativeReals) self.model.y3 = Var(self.model.S, domain=NegativeIntegers) self.model.z3 = Var(self.model.S, self.model.T, domain=Reals) # Unindexed, singly indexed, and doubly indexed variables with # rule-defined domains def domainRule(*args): if len(args) == 1 or args[0] == 0: return NonNegativeReals elif args[0] == 1: return NonNegativeIntegers elif args[0] == 2: return NonPositiveReals elif args[0] == 3: return NonPositiveIntegers elif args[0] == 4: return NegativeReals elif args[0] == 5: return NegativeIntegers elif args[0] == 6: return PositiveReals elif args[0] == 7: return PositiveIntegers elif args[0] == 8: return Reals elif args[0] == 9: return Integers elif args[0] == 10: return Binary else: return NonNegativeReals self.model.x4 = Var(domain=domainRule) self.model.y4 = Var(self.model.S, domain=domainRule) self.model.z4 = Var(self.model.S, self.model.T, domain=domainRule) instance = self.model.create_instance() xfrm = TransformationFactory('core.nonnegative_vars') transformed = xfrm.create_using(instance) # Make sure everything is nonnegative for c in ('x', 'y', 'z'): for n in ('1', '2', '3', '4'): var = transformed.__getattribute__(c + n) for ndx in var._index: self.assertTrue(self.nonnegativeBounds(var[ndx]))
def test_standard_form_transform_2(self): """ Same as #1, but adds constraints """ self.model.S = RangeSet(0, 10) self.model.T = Set(initialize=["foo", "bar"]) # Unindexed, singly indexed, and doubly indexed variables with # explicit bounds self.model.x1 = Var(bounds=(-3, 3)) self.model.y1 = Var(self.model.S, bounds=(-3, 3)) self.model.z1 = Var(self.model.S, self.model.T, bounds=(-3, 3)) # Unindexed, singly indexed, and doubly indexed variables with # rule-defined bounds def boundsRule(*args): return (-4, 4) self.model.x2 = Var(bounds=boundsRule) self.model.y2 = Var(self.model.S, bounds=boundsRule) self.model.z2 = Var(self.model.S, self.model.T, bounds=boundsRule) # Unindexed, singly indexed, and doubly indexed variables with # explicit domains self.model.x3 = Var(domain=NegativeReals, bounds=(-10, 10)) self.model.y3 = Var(self.model.S, domain=NegativeIntegers, bounds=(-10, 10)) self.model.z3 = Var(self.model.S, self.model.T, domain=Reals, bounds=(-10, 10)) # Unindexed, singly indexed, and doubly indexed variables with # rule-defined domains def domainRule(*args): if len(args) == 1: arg = 0 else: arg = args[1] if len(args) == 1 or arg == 0: return NonNegativeReals elif arg == 1: return NonNegativeIntegers elif arg == 2: return NonPositiveReals elif arg == 3: return NonPositiveIntegers elif arg == 4: return NegativeReals elif arg == 5: return NegativeIntegers elif arg == 6: return PositiveReals elif arg == 7: return PositiveIntegers elif arg == 8: return Reals elif arg == 9: return Integers elif arg == 10: return Binary else: return Reals self.model.x4 = Var(domain=domainRule, bounds=(-10, 10)) self.model.y4 = Var(self.model.S, domain=domainRule, bounds=(-10, 10)) self.model.z4 = Var(self.model.S, self.model.T, domain=domainRule, bounds=(-10, 10)) # Add some constraints def makeXConRule(var): def xConRule(model, var): return (-1, var, 1) def makeYConRule(var): def yConRule(model, var, s): return (-1, var[s], 1) def makeZConRule(var): def zConRule(model, var, s, t): return (-1, var[s, t], 1) for n in ('1', '2', '3', '4'): self.model.__setattr__( "x" + n + "_constraint", Constraint( rule=makeXConRule(self.model.__getattribute__("x" + n)))) self.model.__setattr__( "y" + n + "_constraint", Constraint( rule=makeYConRule(self.model.__getattribute__("y" + n)))) self.model.__setattr__( "z" + n + "_constraint", Constraint( rule=makeZConRule(self.model.__getattribute__("z" + n)))) def objRule(model): return sum(5*sum_product(model.__getattribute__(c+n)) \ for c in ('x', 'y', 'z') for n in ('1', '2', '3', '4')) self.model.obj = Objective(rule=objRule) transform = StandardForm() instance = self.model.create_instance() transformed = transform(instance) opt = SolverFactory("glpk") instance_sol = opt.solve(instance) transformed_sol = opt.solve(transformed) self.assertEqual( instance_sol["Solution"][0]["Objective"]['obj']["value"], transformed_sol["Solution"][0]["Objective"]['obj']["value"])
def Model_Creation_Dispatch(model): ''' This function creates the instance for the resolution of the optimization in Pyomo. The problem is solved by discretizing the efficiency curve of the generators and uses binary variables :param model: Pyomo model as defined in the Micro-Grids library. ''' from pyomo.environ import Param, RangeSet, NonNegativeReals, Var, NonNegativeIntegers from Initialize import Initialize_Demand, \ Initialize_Demand_Dispatch, Initialize_Renewable_Energy_Dispatch, Marginal_Cost_Generator,\ Start_Cost, Marginal_Cost_Generator_1, Battery_Reposition_Cost # Import library with initialitation funtions for the parameters # Time parameters model.Periods = Param(within=NonNegativeReals) # Number of periods of analysis of the energy variables model.StartDate = Param() # Start date of the analisis model.Generator_Type = Param() model.Renewable_Source = Param() #SETS model.periods = RangeSet(1, model.Periods) # Creation of a set from 1 to the number of periods in each year model.generator_type = RangeSet(1, model.Generator_Type) model.renewable_source = RangeSet(1, model.Renewable_Source) # PARAMETERS # Parameters of the Renewable energy model.Renewable_Inverter_Efficiency = Param(model.renewable_source) # Efficiency of the inverter in % model.Renewable_Energy_Production = Param(model.renewable_source, model.periods, within=NonNegativeReals, initialize=Initialize_Renewable_Energy_Dispatch) # Energy produccion of a solar panel in W # Parameters of the battery bank model.Charge_Battery_Efficiency = Param() # Efficiency of the charge of the battery in % model.Discharge_Battery_Efficiency = Param() # Efficiency of the discharge of the battery in % model.Deep_of_Discharge = Param() # Deep of discharge of the battery (Deep_of_Discharge) in % model.Maximun_Battery_Charge_Time = Param(within=NonNegativeReals) # Minimun time of charge of the battery in hours model.Maximun_Battery_Discharge_Time = Param(within=NonNegativeReals) # Maximun time of discharge of the battery in hours model.Battery_Nominal_Capacity = Param(within=NonNegativeReals) # Capacity of the battery bank in Wh model.Battery_Initial_SOC = Param(within=NonNegativeReals) model.Battery_Electronic_Invesmente_Cost = Param(within=NonNegativeReals) model.Battery_Invesment_Cost = Param(within=NonNegativeReals) # Cost of battery model.Battery_Cycles = Param(within=NonNegativeReals) model.Unitary_Battery_Reposition_Cost = Param(within=NonNegativeReals, initialize=Battery_Reposition_Cost) # Parametes of the diesel generator model.Generator_Efficiency = Param(model.generator_type, within=NonNegativeReals) model.Generator_Min_Out_Put = Param(model.generator_type, within=NonNegativeReals) model.Low_Heating_Value = Param(model.generator_type) # Low heating value of the diesel in W/L model.Fuel_Cost = Param(model.generator_type, within=NonNegativeReals) # Cost of diesel in USD/L model.Marginal_Cost_Generator_1 = Param(model.generator_type, initialize=Marginal_Cost_Generator_1) model.Cost_Increase = Param(model.generator_type, within=NonNegativeReals) model.Generator_Nominal_Capacity = Param(model.generator_type, within=NonNegativeReals) model.Start_Cost_Generator = Param(model.generator_type, within=NonNegativeReals, initialize=Start_Cost) model.Marginal_Cost_Generator = Param(model.generator_type, initialize=Marginal_Cost_Generator) # Parameters of the Energy balance model.Energy_Demand = Param(model.periods, initialize=Initialize_Demand_Dispatch) # Energy Energy_Demand in W model.Value_Of_Lost_Load = Param(within=NonNegativeReals) # Value of lost load in USD/W # Parameters of the proyect model.Delta_Time = Param(within=NonNegativeReals) # Time step in hours # VARIABLES # Variables associated to the battery bank model.Energy_Battery_Flow_Out = Var(model.periods, within=NonNegativeReals) # Battery discharge energy in wh model.Energy_Battery_Flow_In = Var(model.periods, within=NonNegativeReals) # Battery charge energy in wh model.State_Of_Charge_Battery = Var(model.periods, within=NonNegativeReals) # State of Charge of the Battery in wh model.Maximun_Charge_Power= Var(within=NonNegativeReals) # Maximun charge power in w model.Maximun_Discharge_Power = Var(within=NonNegativeReals) #Maximun discharge power in w # Variables associated to the diesel generator model.Generator_Energy = Var(model.generator_type, model.periods, within=NonNegativeReals) model.Generator_Energy_Integer = Var(model.generator_type, model.periods, within=NonNegativeIntegers) # Varialbles associated to the energy balance model.Lost_Load = Var(model.periods, within=NonNegativeReals) # Energy not suply by the system kWh model.Energy_Curtailment = Var(model.periods, within=NonNegativeReals) # Curtailment of solar energy in kWh
def test_xfrm_special_atoms_nonroot(self): m = ConcreteModel() m.s = RangeSet(3) m.Y = BooleanVar(m.s) m.p = LogicalConstraint( expr=m.Y[1].implies(atleast(2, m.Y[1], m.Y[2], m.Y[3]))) TransformationFactory('core.logical_to_linear').apply_to(m) Y_aug = m.logic_to_linear.augmented_vars self.assertEqual(len(Y_aug), 1) self.assertEqual(Y_aug[1].domain, BooleanSet) _constrs_contained_within( self, [ (None, sum(m.Y[:].get_associated_binary()) - \ (1 + 2 * Y_aug[1].get_associated_binary()), 0), (1, (1 - m.Y[1].get_associated_binary()) + \ Y_aug[1].get_associated_binary(), None), (None, 2 - 2 * (1 - Y_aug[1].get_associated_binary()) - \ sum(m.Y[:].get_associated_binary()), 0) ], m.logic_to_linear.transformed_constraints) m = ConcreteModel() m.s = RangeSet(3) m.Y = BooleanVar(m.s) m.p = LogicalConstraint( expr=m.Y[1].implies(atmost(2, m.Y[1], m.Y[2], m.Y[3]))) TransformationFactory('core.logical_to_linear').apply_to(m) Y_aug = m.logic_to_linear.augmented_vars self.assertEqual(len(Y_aug), 1) self.assertEqual(Y_aug[1].domain, BooleanSet) _constrs_contained_within( self, [ (None, sum(m.Y[:].get_associated_binary()) - \ (1 - Y_aug[1].get_associated_binary() + 2), 0), (1, (1 - m.Y[1].get_associated_binary()) + \ Y_aug[1].get_associated_binary(), None), (None, 3 - 3 * Y_aug[1].get_associated_binary() - \ sum(m.Y[:].get_associated_binary()), 0) ], m.logic_to_linear.transformed_constraints) m = ConcreteModel() m.s = RangeSet(3) m.Y = BooleanVar(m.s) m.p = LogicalConstraint( expr=m.Y[1].implies(exactly(2, m.Y[1], m.Y[2], m.Y[3]))) TransformationFactory('core.logical_to_linear').apply_to(m) Y_aug = m.logic_to_linear.augmented_vars self.assertEqual(len(Y_aug), 3) self.assertEqual(Y_aug[1].domain, BooleanSet) _constrs_contained_within( self, [ (1, (1 - m.Y[1].get_associated_binary()) + \ Y_aug[1].get_associated_binary(), None), (None, sum(m.Y[:].get_associated_binary()) - \ (1 - Y_aug[1].get_associated_binary() + 2), 0), (None, 2 - 2 * (1 - Y_aug[1].get_associated_binary()) - \ sum(m.Y[:].get_associated_binary()), 0), (1, sum(Y_aug[:].get_associated_binary()), None), (None, sum(m.Y[:].get_associated_binary()) - \ (1 + 2 * (1 - Y_aug[2].get_associated_binary())), 0), (None, 3 - 3 * (1 - Y_aug[3].get_associated_binary()) - \ sum(m.Y[:].get_associated_binary()), 0), ], m.logic_to_linear.transformed_constraints) # Note: x is now a variable m = ConcreteModel() m.s = RangeSet(3) m.Y = BooleanVar(m.s) m.x = Var(bounds=(1, 3)) m.p = LogicalConstraint( expr=m.Y[1].implies(exactly(m.x, m.Y[1], m.Y[2], m.Y[3]))) TransformationFactory('core.logical_to_linear').apply_to(m) Y_aug = m.logic_to_linear.augmented_vars self.assertEqual(len(Y_aug), 3) self.assertEqual(Y_aug[1].domain, BooleanSet) _constrs_contained_within( self, [ (1, (1 - m.Y[1].get_associated_binary()) + \ Y_aug[1].get_associated_binary(), None), (None, sum(m.Y[:].get_associated_binary()) - \ (m.x + 2 * (1 - Y_aug[1].get_associated_binary())), 0), (None, m.x - 3 * (1 - Y_aug[1].get_associated_binary()) - \ sum(m.Y[:].get_associated_binary()), 0), (1, sum(Y_aug[:].get_associated_binary()), None), (None, sum(m.Y[:].get_associated_binary()) - \ (m.x - 1 + 3 * (1 - Y_aug[2].get_associated_binary())), 0), (None, m.x + 1 - 4 * (1 - Y_aug[3].get_associated_binary()) - \ sum(m.Y[:].get_associated_binary()), 0), ], m.logic_to_linear.transformed_constraints)
def test_solve1(self): model = ConcreteModel() model.A = RangeSet(1, 4) model.x = Var(model.A, bounds=(-1, 1)) def obj_rule(model): return sum_product(model.x) model.obj = Objective(rule=obj_rule) def c_rule(model): expr = 0 for i in model.A: expr += i * model.x[i] return expr == 0 model.c = Constraint(rule=c_rule) opt = SolverFactory('glpk') results = opt.solve(model, symbolic_solver_labels=True) model.solutions.store_to(results) results.write(filename=join(currdir, "solve1.out"), format='json') self.assertMatchesJsonBaseline(join(currdir, "solve1.out"), join(currdir, "solve1.txt"), tolerance=1e-4) # def d_rule(model): return model.x[1] >= 0 model.d = Constraint(rule=d_rule) model.d.deactivate() results = opt.solve(model) model.solutions.store_to(results) results.write(filename=join(currdir, "solve1x.out"), format='json') self.assertMatchesJsonBaseline(join(currdir, "solve1x.out"), join(currdir, "solve1.txt"), tolerance=1e-4) # model.d.activate() results = opt.solve(model) model.solutions.store_to(results) results.write(filename=join(currdir, "solve1a.out"), format='json') self.assertMatchesJsonBaseline(join(currdir, "solve1a.out"), join(currdir, "solve1a.txt"), tolerance=1e-4) # model.d.deactivate() def e_rule(model, i): return model.x[i] >= 0 model.e = Constraint(model.A, rule=e_rule) for i in model.A: model.e[i].deactivate() results = opt.solve(model) model.solutions.store_to(results) results.write(filename=join(currdir, "solve1y.out"), format='json') self.assertMatchesJsonBaseline(join(currdir, "solve1y.out"), join(currdir, "solve1.txt"), tolerance=1e-4) # model.e.activate() results = opt.solve(model) model.solutions.store_to(results) results.write(filename=join(currdir, "solve1b.out"), format='json') self.assertMatchesJsonBaseline(join(currdir, "solve1b.out"), join(currdir, "solve1b.txt"), tolerance=1e-4)
def test_solve_with_pickle_then_clone(self): # This tests github issue Pyomo-#65 model = ConcreteModel() model.A = RangeSet(1, 4) model.b = Block() model.b.x = Var(model.A, bounds=(-1, 1)) model.b.obj = Objective(expr=sum_product(model.b.x)) model.c = Constraint(expr=model.b.x[1] >= 0) opt = SolverFactory('glpk') self.assertEqual(len(model.solutions), 0) results = opt.solve(model, symbolic_solver_labels=True) self.assertEqual(len(model.solutions), 1) # self.assertEqual(model.solutions[0].gap, 0.0) #self.assertEqual(model.solutions[0].status, SolutionStatus.feasible) self.assertEqual(model.solutions[0].message, None) # buf = pickle.dumps(model) tmodel = pickle.loads(buf) self.assertEqual(len(tmodel.solutions), 1) self.assertEqual(tmodel.solutions[0].gap, 0.0) #self.assertEqual(tmodel.solutions[0].status, SolutionStatus.feasible) self.assertEqual(tmodel.solutions[0].message, None) self.assertIn(id(tmodel.b.obj), tmodel.solutions[0]._entry['objective']) self.assertIs( tmodel.b.obj, tmodel.solutions[0]._entry['objective'][id(tmodel.b.obj)][0]()) inst = tmodel.clone() # make sure the clone has all the attributes self.assertTrue(hasattr(inst, 'A')) self.assertTrue(hasattr(inst, 'b')) self.assertTrue(hasattr(inst.b, 'x')) self.assertTrue(hasattr(inst.b, 'obj')) self.assertTrue(hasattr(inst, 'c')) # and that they were all copied self.assertIsNot(inst.A, tmodel.A) self.assertIsNot(inst.b, tmodel.b) self.assertIsNot(inst.b.x, tmodel.b.x) self.assertIsNot(inst.b.obj, tmodel.b.obj) self.assertIsNot(inst.c, tmodel.c) # Make sure the solution is on the new model self.assertTrue(hasattr(inst, 'solutions')) self.assertEqual(len(inst.solutions), 1) self.assertEqual(inst.solutions[0].gap, 0.0) #self.assertEqual(inst.solutions[0].status, SolutionStatus.feasible) self.assertEqual(inst.solutions[0].message, None) # Spot-check some components and make sure all the weakrefs in # the ModelSOlution got updated self.assertIn(id(inst.b.obj), inst.solutions[0]._entry['objective']) _obj = inst.solutions[0]._entry['objective'][id(inst.b.obj)] self.assertIs(_obj[0](), inst.b.obj) for v in [1, 2, 3, 4]: self.assertIn(id(inst.b.x[v]), inst.solutions[0]._entry['variable']) _v = inst.solutions[0]._entry['variable'][id(inst.b.x[v])] self.assertIs(_v[0](), inst.b.x[v])
def bb(bb, j): bb.I = RangeSet(i * j) bb.y = Var(bb.I, initialize=lambda m, i: i)
def b(b, i): b.K = RangeSet(10, 10 * i, 10)
def build(self): """Build the model. Args: None Returns: None """ # Call UnitModel.build to setup dynamics super(TrayColumnData, self).build() # Create set for constructing indexed trays if self.config.number_of_trays is not None: self.tray_index = RangeSet(1, self.config.number_of_trays) else: raise ConfigurationError("The config argument number_of_trays " "needs to specified and cannot be None.") # Add trays # TODO: # 1. Add support for multiple feed tray locations # 2. Add support for specifying which trays have side draws self.tray = Tray(self.tray_index, default={ "has_liquid_side_draw": self.config.has_liquid_side_draw, "has_vapor_side_draw": self.config.has_vapor_side_draw, "has_heat_transfer": self.config.has_heat_transfer, "has_pressure_change": self.config.has_pressure_change, "property_package": self.config.property_package, "property_package_args": self.config.property_package_args }, initialize={ self.config.feed_tray_location: { "is_feed_tray": True, "has_liquid_side_draw": self.config.has_liquid_side_draw, "has_vapor_side_draw": self.config.has_vapor_side_draw, "has_heat_transfer": self.config.has_heat_transfer, "has_pressure_change": self.config.has_pressure_change, "property_package": self.config.property_package, "property_package_args": self.config.property_package_args } }) # Add condenser self.condenser = Condenser( default={ "condenser_type": self.config.condenser_type, "temperature_spec": self.config.condenser_temperature_spec, "property_package": self.config.property_package, "property_package_args": self.config.property_package_args }) # Add reboiler self.reboiler = Reboiler( default={ "has_boilup_ratio": True, "has_pressure_change": self.config.has_pressure_change, "property_package": self.config.property_package, "property_package_args": self.config.property_package_args }) # Add extension to the feed port self.feed = Port( extends=self.tray[self.config.feed_tray_location].feed) # Construct arcs between trays, condenser, and reboiler self._make_arcs() TransformationFactory("network.expand_arcs").apply_to(self)
def build_eight_process_flowsheet(): """Build flowsheet for the 8 process problem.""" m = ConcreteModel(name='DuranEx3 Disjunctive') """Set declarations""" m.streams = RangeSet(2, 25, doc="process streams") m.units = RangeSet(1, 8, doc="process units") """Parameter and initial point declarations""" # FIXED COST INVESTMENT COEFF FOR PROCESS UNITS # Format: process #: cost fixed_cost = {1: 5, 2: 8, 3: 6, 4: 10, 5: 6, 6: 7, 7: 4, 8: 5} m.CF = Param(m.units, initialize=fixed_cost) def fixed_cost_bounds(m, unit): return (0, m.CF[unit]) m.yCF = Var(m.units, initialize=0, bounds=fixed_cost_bounds) # VARIABLE COST COEFF FOR PROCESS UNITS - STREAMS # Format: stream #: cost variable_cost = {3: -10, 5: -15, 9: -40, 19: 25, 21: 35, 25: -35, 17: 80, 14: 15, 10: 15, 2: 1, 4: 1, 18: -65, 20: -60, 22: -80} CV = m.CV = Param(m.streams, initialize=variable_cost, default=0) # initial point information for stream flows initX = {2: 2, 3: 1.5, 6: 0.75, 7: 0.5, 8: 0.5, 9: 0.75, 11: 1.5, 12: 1.34, 13: 2, 14: 2.5, 17: 2, 18: 0.75, 19: 2, 20: 1.5, 23: 1.7, 24: 1.5, 25: 0.5} """Variable declarations""" # FLOWRATES OF PROCESS STREAMS m.flow = Var(m.streams, domain=NonNegativeReals, initialize=initX, bounds=(0, 10)) # OBJECTIVE FUNCTION CONSTANT TERM CONSTANT = m.constant = Param(initialize=122.0) """Constraint definitions""" # INPUT-OUTPUT RELATIONS FOR process units 1 through 8 m.use_unit_1or2 = Disjunction( expr=[ # use unit 1 disjunct [m.yCF[1] == m.CF[1], exp(m.flow[3]) - 1 == m.flow[2], m.flow[4] == 0, m.flow[5] == 0], # use unit 2 disjunct [m.yCF[2] == m.CF[2], exp(m.flow[5] / 1.2) - 1 == m.flow[4], m.flow[2] == 0, m.flow[3] == 0] ]) m.use_unit_3ornot = Disjunction( expr=[ # Use unit 3 disjunct [m.yCF[3] == m.CF[3], 1.5 * m.flow[9] + m.flow[10] == m.flow[8]], # No unit 3 disjunct [m.flow[9] == 0, m.flow[10] == m.flow[8]] ]) m.use_unit_4or5ornot = Disjunction( expr=[ # Use unit 4 disjunct [m.yCF[4] == m.CF[4], 1.25 * (m.flow[12] + m.flow[14]) == m.flow[13], m.flow[15] == 0], # Use unit 5 disjunct [m.yCF[5] == m.CF[5], m.flow[15] == 2 * m.flow[16], m.flow[12] == 0, m.flow[14] == 0], # No unit 4 or 5 disjunct [m.flow[15] == 0, m.flow[12] == 0, m.flow[14] == 0] ]) m.use_unit_6or7ornot = Disjunction( expr=[ # use unit 6 disjunct [m.yCF[6] == m.CF[6], exp(m.flow[20] / 1.5) - 1 == m.flow[19], m.flow[21] == 0, m.flow[22] == 0], # use unit 7 disjunct [m.yCF[7] == m.CF[7], exp(m.flow[22]) - 1 == m.flow[21], m.flow[19] == 0, m.flow[20] == 0], # No unit 6 or 7 disjunct [m.flow[21] == 0, m.flow[22] == 0, m.flow[19] == 0, m.flow[20] == 0] ]) m.use_unit_8ornot = Disjunction( expr=[ # use unit 8 disjunct [m.yCF[8] == m.CF[8], exp(m.flow[18]) - 1 == m.flow[10] + m.flow[17]], # no unit 8 disjunct [m.flow[10] == 0, m.flow[17] == 0, m.flow[18] == 0] ]) # Mass balance equations m.massbal1 = Constraint(expr=m.flow[13] == m.flow[19] + m.flow[21]) m.massbal2 = Constraint( expr=m.flow[17] == m.flow[9] + m.flow[16] + m.flow[25]) m.massbal3 = Constraint(expr=m.flow[11] == m.flow[12] + m.flow[15]) m.massbal4 = Constraint( expr=m.flow[3] + m.flow[5] == m.flow[6] + m.flow[11]) m.massbal5 = Constraint(expr=m.flow[6] == m.flow[7] + m.flow[8]) m.massbal6 = Constraint(expr=m.flow[23] == m.flow[20] + m.flow[22]) m.massbal7 = Constraint(expr=m.flow[23] == m.flow[14] + m.flow[24]) # process specifications m.specs1 = Constraint(expr=m.flow[10] <= 0.8 * m.flow[17]) m.specs2 = Constraint(expr=m.flow[10] >= 0.4 * m.flow[17]) m.specs3 = Constraint(expr=m.flow[12] <= 5 * m.flow[14]) m.specs4 = Constraint(expr=m.flow[12] >= 2 * m.flow[14]) # pure integer constraints m.use4implies6or7 = Constraint( expr=m.use_unit_6or7ornot.disjuncts[0].indicator_var + m.use_unit_6or7ornot.disjuncts[1].indicator_var - m.use_unit_4or5ornot.disjuncts[0].indicator_var == 0) m.use3implies8 = Constraint( expr=m.use_unit_3ornot.disjuncts[0].indicator_var - m.use_unit_8ornot.disjuncts[0].indicator_var <= 0) """Profit (objective) function definition""" m.profit = Objective(expr=sum( m.yCF[unit] for unit in m.units) + sum(m.flow[stream] * CV[stream] for stream in m.streams) + CONSTANT, sense=minimize) """Bound definitions""" # x (flow) upper bounds x_ubs = {3: 2, 5: 2, 9: 2, 10: 1, 14: 1, 17: 2, 19: 2, 21: 2, 25: 3} for i, x_ub in iteritems(x_ubs): m.flow[i].setub(x_ub) # Optimal solution uses units 2, 4, 6, 8 with objective value 68. return m
def Model_Creation(model, Renewable_Penetration, Battery_Independence): #%% PARAMETERS "Project parameters" model.Periods = Param( within=NonNegativeReals ) # Number of periods of analysis of the energy variables model.Years = Param( within=NonNegativeReals) # Number of years of the project model.Step_Duration = Param(within=NonNegativeReals) model.Min_Last_Step_Duration = Param(within=NonNegativeReals) model.Delta_Time = Param(within=NonNegativeReals) # Time step in hours model.StartDate = Param() # Start date of the analisis model.Scenarios = Param(within=NonNegativeReals) model.Discount_Rate = Param( within=NonNegativeReals) # Discount rate of the project in % model.Investment_Cost_Limit = Param(within=NonNegativeReals) model.Steps_Number = Param(initialize=Initialize_Upgrades_Number) model.RES_Sources = Param(within=NonNegativeReals) model.Generator_Types = Param(within=NonNegativeReals) "Sets" model.periods = RangeSet( 1, model.Periods ) # Creation of a set from 1 to the number of periods in each year model.years = RangeSet( 1, model.Years ) # Creation of a set from 1 to the number of years of the project model.scenarios = RangeSet( 1, model.Scenarios ) # Creation of a set from 1 to the number of scenarios to analized model.renewable_sources = RangeSet( 1, model.RES_Sources ) # Creation of a set from 1 to the number of RES technologies to analized model.generator_types = RangeSet( 1, model.Generator_Types ) # Creation of a set from 1 to the number of generators types to analized model.steps = RangeSet( 1, model.Steps_Number ) # Creation of a set from 1 to the number of investment decision steps model.years_steps = Set( dimen=2, initialize=Initialize_YearUpgrade_Tuples ) # 2D set of tuples: it associates each year to the corresponding investment decision step model.Scenario_Weight = Param(model.scenarios, within=NonNegativeReals) "Parameters of RES" model.RES_Names = Param(model.renewable_sources) # RES names model.RES_Nominal_Capacity = Param( model.renewable_sources, within=NonNegativeReals) # Nominal capacity of the RES in W/unit model.RES_Inverter_Efficiency = Param( model.renewable_sources) # Efficiency of the inverter in % model.RES_Specific_Investment_Cost = Param( model.renewable_sources, within=NonNegativeReals) # Cost of RES in USD/W model.RES_Specific_OM_Cost = Param( model.renewable_sources, within=NonNegativeReals ) # Percentage of the total investment spend in operation and management of solar panels in each period in % model.RES_Lifetime = Param(model.renewable_sources, within=NonNegativeReals) model.RES_Unit_Energy_Production = Param( model.scenarios, model.renewable_sources, model.periods, within=NonNegativeReals, initialize=Initialize_RES_Energy) # Energy production of a RES in Wh if Renewable_Penetration > 0: model.Renewable_Penetration = Renewable_Penetration "Parameters of the battery bank" model.Battery_Specific_Investment_Cost = Param( ) # Specific investment cost of the battery bank [USD/Wh] model.Battery_Specific_Electronic_Investment_Cost = Param( within=NonNegativeReals ) # Specific investment cost of non-replaceable parts (electronics) of the battery bank [USD/Wh] model.Battery_Specific_OM_Cost = Param( within=NonNegativeReals ) # Percentage of the total investment spend in operation and management of batteries in each period in % model.Battery_Discharge_Battery_Efficiency = Param( ) # Efficiency of the discharge of the battery in % model.Battery_Charge_Battery_Efficiency = Param( ) # Efficiency of the charge of the battery in % model.Battery_Depth_of_Discharge = Param( ) # Depth of discharge of the battery (Depth_of_Discharge) in % model.Maximum_Battery_Discharge_Time = Param( within=NonNegativeReals ) # Minimum time of charge of the battery in hours model.Maximum_Battery_Charge_Time = Param( within=NonNegativeReals ) # Maximum time of discharge of the battery in hours model.Battery_Cycles = Param(within=NonNegativeReals) model.Unitary_Battery_Replacement_Cost = Param( within=NonNegativeReals, initialize=Initialize_Battery_Unit_Repl_Cost) model.Battery_Initial_SOC = Param(within=NonNegativeReals) if Battery_Independence > 0: model.Battery_Independence = Battery_Independence model.Battery_Min_Capacity = Param( model.steps, initialize=Initialize_Battery_Minimum_Capacity) "Parameters of the genset" model.Generator_Names = Param(model.generator_types) # Generators names model.Generator_Efficiency = Param( model.generator_types, within=NonNegativeReals ) # Generator efficiency to trasform heat into electricity % model.Generator_Specific_Investment_Cost = Param( model.generator_types, within=NonNegativeReals) # Cost of the diesel generator model.Generator_Specific_OM_Cost = Param( model.generator_types, within=NonNegativeReals) # Cost of the diesel generator model.Generator_Lifetime = Param(model.generator_types, within=NonNegativeReals) model.Fuel_Names = Param(model.generator_types) # Fuel names model.Fuel_LHV = Param( model.generator_types, within=NonNegativeReals) # Low heating value of the diesel in W/L model.Fuel_Specific_Cost = Param(model.generator_types, within=NonNegativeReals) model.Generator_Marginal_Cost = Param( model.scenarios, model.years, model.generator_types, initialize=Initialize_Generator_Marginal_Cost) "Parameters of the electricity balance" model.Energy_Demand = Param( model.scenarios, model.years, model.periods, initialize=Initialize_Demand) # Energy Energy_Demand in W model.Lost_Load_Fraction = Param( within=NonNegativeReals) # Lost load maxiumum admittable fraction in % model.Lost_Load_Specific_Cost = Param( within=NonNegativeReals) # Value of lost load in USD/Wh "Parameters of the plot" model.RES_Colors = Param( model.renewable_sources) # HEX color codes for RES model.Battery_Color = Param() # HEX color codes for Battery bank model.Generator_Colors = Param( model.generator_types) # HEX color codes for Generators model.Lost_Load_Color = Param() # HEX color codes for Lost load model.Curtailment_Color = Param() # HEX color codes for Curtailment #%% VARIABLES "Variables associated to the RES" model.RES_Units = Var(model.steps, model.renewable_sources, within=NonNegativeReals) # Number of units of RES model.RES_Energy_Production = Var( model.scenarios, model.years, model.renewable_sources, model.periods, within=NonNegativeReals) # Energy generated by the RES sistem in Wh "Variables associated to the battery bank" model.Battery_Nominal_Capacity = Var( model.steps, within=NonNegativeReals) # Capacity of the battery bank in Wh model.Battery_Outflow = Var( model.scenarios, model.years, model.periods, within=NonNegativeReals) # Battery discharge energy in Wh model.Battery_Inflow = Var( model.scenarios, model.years, model.periods, within=NonNegativeReals) # Battery charge energy in Wh model.Battery_SOC = Var( model.scenarios, model.years, model.periods, within=NonNegativeReals) # State of Charge of the Battery in Wh model.Battery_Maximum_Charge_Power = Var(model.steps, within=NonNegativeReals) model.Battery_Maximum_Discharge_Power = Var(model.steps, within=NonNegativeReals) model.Battery_Replacement_Cost_Act = Var(model.scenarios, within=NonNegativeReals) model.Battery_Replacement_Cost_NonAct = Var(model.scenarios, within=NonNegativeReals) "Variables associated to the diesel generator" model.Generator_Nominal_Capacity = Var( model.steps, model.generator_types, within=NonNegativeReals) # Capacity of the diesel generator in Wh model.Generator_Energy_Production = Var( model.scenarios, model.years, model.generator_types, model.periods, within=NonNegativeReals) # Energy generated by the Diesel generator model.Total_Fuel_Cost_Act = Var(model.scenarios, model.generator_types, within=NonNegativeReals) model.Total_Fuel_Cost_NonAct = Var(model.scenarios, model.generator_types, within=NonNegativeReals) "Variables associated to the energy balance" model.Lost_Load = Var( model.scenarios, model.years, model.periods, within=NonNegativeReals) # Energy not supplied by the system kWh model.Energy_Curtailment = Var( model.scenarios, model.years, model.periods, within=NonNegativeReals) # Curtailment of RES in kWh model.Scenario_Lost_Load_Cost_Act = Var(model.scenarios, within=NonNegativeReals) model.Scenario_Lost_Load_Cost_NonAct = Var(model.scenarios, within=NonNegativeReals) "Variables associated to the project" model.Net_Present_Cost = Var(within=NonNegativeReals) model.Scenario_Net_Present_Cost = Var(model.scenarios, within=NonNegativeReals) model.Investment_Cost = Var(within=NonNegativeReals) model.Salvage_Value = Var(within=NonNegativeReals) model.Total_Variable_Cost_Act = Var(within=NonNegativeReals) model.Operation_Maintenance_Cost_Act = Var(within=NonNegativeReals) model.Operation_Maintenance_Cost_NonAct = Var(within=NonNegativeReals) model.Total_Scenario_Variable_Cost_Act = Var(model.scenarios, within=NonNegativeReals) model.Total_Scenario_Variable_Cost_NonAct = Var(model.scenarios, within=NonNegativeReals)
def build_eight_process_flowsheet(): """Build flowsheet for the 8 process problem.""" m = ConcreteModel(name='DuranEx3 Disjunctive') """Set declarations""" m.streams = RangeSet(2, 25, doc="process streams") m.units = RangeSet(1, 8, doc="process units") """Parameter and initial point declarations""" # FIXED COST INVESTMENT COEFF FOR PROCESS UNITS # Format: process #: cost fixed_cost = {1: 5, 2: 8, 3: 6, 4: 10, 5: 6, 6: 7, 7: 4, 8: 5} CF = m.CF = Param(m.units, initialize=fixed_cost) # VARIABLE COST COEFF FOR PROCESS UNITS - STREAMS # Format: stream #: cost variable_cost = {3: -10, 5: -15, 9: -40, 19: 25, 21: 35, 25: -35, 17: 80, 14: 15, 10: 15, 2: 1, 4: 1, 18: -65, 20: -60, 22: -80} CV = m.CV = Param(m.streams, initialize=variable_cost, default=0) # initial point information for stream flows initX = {2: 2, 3: 1.5, 6: 0.75, 7: 0.5, 8: 0.5, 9: 0.75, 11: 1.5, 12: 1.34, 13: 2, 14: 2.5, 17: 2, 18: 0.75, 19: 2, 20: 1.5, 23: 1.7, 24: 1.5, 25: 0.5} """Variable declarations""" # FLOWRATES OF PROCESS STREAMS m.flow = Var(m.streams, domain=NonNegativeReals, initialize=initX, bounds=(0, 10)) # OBJECTIVE FUNCTION CONSTANT TERM CONSTANT = m.constant = Param(initialize=122.0) """Constraint definitions""" # INPUT-OUTPUT RELATIONS FOR process units 1 through 8 m.use_unit1 = Disjunct() m.use_unit1.inout1 = Constraint(expr=exp(m.flow[3]) - 1 == m.flow[2]) m.use_unit1.no_unit2_flow1 = Constraint(expr=m.flow[4] == 0) m.use_unit1.no_unit2_flow2 = Constraint(expr=m.flow[5] == 0) m.use_unit2 = Disjunct() m.use_unit2.inout2 = Constraint( expr=exp(m.flow[5] / 1.2) - 1 == m.flow[4]) m.use_unit2.no_unit1_flow1 = Constraint(expr=m.flow[2] == 0) m.use_unit2.no_unit1_flow2 = Constraint(expr=m.flow[3] == 0) m.use_unit3 = Disjunct() m.use_unit3.inout3 = Constraint( expr=1.5 * m.flow[9] + m.flow[10] == m.flow[8]) m.no_unit3 = Disjunct() m.no_unit3.no_unit3_flow1 = Constraint(expr=m.flow[9] == 0) m.no_unit3.flow_pass_through = Constraint(expr=m.flow[10] == m.flow[8]) m.use_unit4 = Disjunct() m.use_unit4.inout4 = Constraint( expr=1.25 * (m.flow[12] + m.flow[14]) == m.flow[13]) m.use_unit4.no_unit5_flow = Constraint(expr=m.flow[15] == 0) m.use_unit5 = Disjunct() m.use_unit5.inout5 = Constraint(expr=m.flow[15] == 2 * m.flow[16]) m.use_unit5.no_unit4_flow1 = Constraint(expr=m.flow[12] == 0) m.use_unit5.no_unit4_flow2 = Constraint(expr=m.flow[14] == 0) m.no_unit4or5 = Disjunct() m.no_unit4or5.no_unit5_flow = Constraint(expr=m.flow[15] == 0) m.no_unit4or5.no_unit4_flow1 = Constraint(expr=m.flow[12] == 0) m.no_unit4or5.no_unit4_flow2 = Constraint(expr=m.flow[14] == 0) m.use_unit6 = Disjunct() m.use_unit6.inout6 = Constraint( expr=exp(m.flow[20] / 1.5) - 1 == m.flow[19]) m.use_unit6.no_unit7_flow1 = Constraint(expr=m.flow[21] == 0) m.use_unit6.no_unit7_flow2 = Constraint(expr=m.flow[22] == 0) m.use_unit7 = Disjunct() m.use_unit7.inout7 = Constraint(expr=exp(m.flow[22]) - 1 == m.flow[21]) m.use_unit7.no_unit6_flow1 = Constraint(expr=m.flow[19] == 0) m.use_unit7.no_unit6_flow2 = Constraint(expr=m.flow[20] == 0) m.no_unit6or7 = Disjunct() m.no_unit6or7.no_unit7_flow1 = Constraint(expr=m.flow[21] == 0) m.no_unit6or7.no_unit7_flow2 = Constraint(expr=m.flow[22] == 0) m.no_unit6or7.no_unit6_flow = Constraint(expr=m.flow[19] == 0) m.no_unit6or7.no_unit6_flow2 = Constraint(expr=m.flow[20] == 0) m.use_unit8 = Disjunct() m.use_unit8.inout8 = Constraint( expr=exp(m.flow[18]) - 1 == m.flow[10] + m.flow[17]) m.no_unit8 = Disjunct() m.no_unit8.no_unit8_flow1 = Constraint(expr=m.flow[10] == 0) m.no_unit8.no_unit8_flow2 = Constraint(expr=m.flow[17] == 0) m.no_unit8.no_unit8_flow3 = Constraint(expr=m.flow[18] == 0) # Mass balance equations m.massbal1 = Constraint(expr=m.flow[13] == m.flow[19] + m.flow[21]) m.massbal2 = Constraint( expr=m.flow[17] == m.flow[9] + m.flow[16] + m.flow[25]) m.massbal3 = Constraint(expr=m.flow[11] == m.flow[12] + m.flow[15]) m.massbal4 = Constraint( expr=m.flow[3] + m.flow[5] == m.flow[6] + m.flow[11]) m.massbal5 = Constraint(expr=m.flow[6] == m.flow[7] + m.flow[8]) m.massbal6 = Constraint(expr=m.flow[23] == m.flow[20] + m.flow[22]) m.massbal7 = Constraint(expr=m.flow[23] == m.flow[14] + m.flow[24]) # process specifications m.specs1 = Constraint(expr=m.flow[10] <= 0.8 * m.flow[17]) m.specs2 = Constraint(expr=m.flow[10] >= 0.4 * m.flow[17]) m.specs3 = Constraint(expr=m.flow[12] <= 5 * m.flow[14]) m.specs4 = Constraint(expr=m.flow[12] >= 2 * m.flow[14]) # pure integer constraints m.use1or2 = Disjunction(expr=[m.use_unit1, m.use_unit2]) m.use4or5maybe = Disjunction( expr=[m.use_unit4, m.use_unit5, m.no_unit4or5]) m.use4or5 = Constraint( expr=m.use_unit4.indicator_var + m.use_unit5.indicator_var <= 1) m.use6or7maybe = Disjunction( expr=[m.use_unit6, m.use_unit7, m.no_unit6or7]) m.use4implies6or7 = Constraint( expr=m.use_unit6.indicator_var + m.use_unit7.indicator_var - m.use_unit4.indicator_var == 0) m.use3maybe = Disjunction(expr=[m.use_unit3, m.no_unit3]) m.either3ornot = Constraint( expr=m.use_unit3.indicator_var + m.no_unit3.indicator_var == 1) m.use8maybe = Disjunction(expr=[m.use_unit8, m.no_unit8]) m.use3implies8 = Constraint( expr=m.use_unit3.indicator_var - m.use_unit8.indicator_var <= 0) """Profit (objective) function definition""" m.profit = Objective(expr=sum( getattr(m, 'use_unit%s' % (unit,)).indicator_var * CF[unit] for unit in m.units) + sum(m.flow[stream] * CV[stream] for stream in m.streams) + CONSTANT, sense=minimize) """Bound definitions""" # x (flow) upper bounds x_ubs = {3: 2, 5: 2, 9: 2, 10: 1, 14: 1, 17: 2, 19: 2, 21: 2, 25: 3} for i, x_ub in x_ubs.items(): m.flow[i].setub(x_ub) # # optimal solution # m.use_unit1.indicator_var = 0 # m.use_unit2.indicator_var = 1 # m.use_unit3.indicator_var = 0 # m.no_unit3.indicator_var = 1 # m.use_unit4.indicator_var = 1 # m.use_unit5.indicator_var = 0 # m.no_unit4or5.indicator_var = 0 # m.use_unit6.indicator_var = 1 # m.use_unit7.indicator_var = 0 # m.no_unit6or7.indicator_var = 0 # m.use_unit8.indicator_var = 1 # m.no_unit8.indicator_var = 0 return m
def make_invalid(m): m.I = RangeSet(3) m.x = Var(m.I) m.c = Constraint(expr=sum(m.x[i] for i in m.I) >= 0)
def Model_Creation_binary(model): ''' This function creates the instance for the resolution of the optimization in Pyomo. The problem is solved by discretizing the efficiency curve of the generators and uses binary variables :param model: Pyomo model as defined in the Micro-Grids library. ''' from pyomo.environ import Param, RangeSet, NonNegativeReals, Var, Binary, NonNegativeIntegers from Initialize import Initialize_years, Initialize_Demand, Initialize_PV_Energy, Marginal_Cost_Generator, Start_Cost,Marginal_Cost_Generator_1 # Import library with initialitation funtions for the parameters # Time parameters model.Periods = Param(within=NonNegativeReals) # Number of periods of analysis of the energy variables model.Years = Param() # Number of years of the project model.StartDate = Param() # Start date of the analisis model.PlotTime = Param() # Quantity of days that are going to be plot model.PlotDay = Param() # Start day for the plot model.Scenarios = Param() model.PlotScenario = Param() #SETS model.periods = RangeSet(1, model.Periods) # Creation of a set from 1 to the number of periods in each year model.years = RangeSet(1, model.Years) # Creation of a set from 1 to the number of years of the project model.Slops = RangeSet(1,2) model.scenario = RangeSet(1, model.Scenarios) # Creation of a set from 1 to the numbero scenarios to analized # PARAMETERS # Parameters of the PV model.PV_Nominal_Capacity = Param(within=NonNegativeReals) # Nominal capacity of the PV in W/unit model.Inverter_Efficiency = Param() # Efficiency of the inverter in % model.PV_invesment_Cost = Param(within=NonNegativeReals) # Cost of solar panel in USD/W model.PV_Energy_Production = Param(model.scenario, model.periods, within=NonNegativeReals, initialize=Initialize_PV_Energy) # Energy produccion of a solar panel in W # Parameters of the battery bank model.Charge_Battery_Efficiency = Param() # Efficiency of the charge of the battery in % model.Discharge_Battery_Efficiency = Param() # Efficiency of the discharge of the battery in % model.Deep_of_Discharge = Param() # Deep of discharge of the battery (Deep_of_Discharge) in % model.Maximun_Battery_Charge_Time = Param(within=NonNegativeReals) # Minimun time of charge of the battery in hours model.Maximun_Battery_Discharge_Time = Param(within=NonNegativeReals) # Maximun time of discharge of the battery in hours model.Battery_Reposition_Time = Param(within=NonNegativeReals) # Period of repocition of the battery in years model.Battery_Invesment_Cost = Param(within=NonNegativeReals) # Cost of battery # Parametes of the diesel generator model.Generator_Effiency = Param(within=NonNegativeReals) model.Generator_Min_Out_Put = Param(within=NonNegativeReals) model.Generator_Efficiency = Param() # Generator efficiency to trasform heat into electricity % model.Low_Heating_Value = Param() # Low heating value of the diesel in W/L model.Diesel_Cost = Param(within=NonNegativeReals) # Cost of diesel in USD/L model.Generator_Invesment_Cost = Param(within=NonNegativeReals) # Cost of the diesel generator model.Marginal_Cost_Generator_1 = Param(initialize=Marginal_Cost_Generator_1) model.Cost_Increase = Param(within=NonNegativeReals) model.Generator_Nominal_Capacity = Param(within=NonNegativeReals) model.Start_Cost_Generator = Param(within=NonNegativeReals, initialize=Start_Cost) model.Marginal_Cost_Generator = Param(initialize=Marginal_Cost_Generator) # Parameters of the Energy balance model.Energy_Demand = Param(model.scenario,model.periods, initialize=Initialize_Demand) # Energy Energy_Demand in W model.Lost_Load_Probability = Param() # Lost load probability in % model.Value_Of_Lost_Load = Param(within=NonNegativeReals) # Value of lost load in USD/W # Parameters of the proyect model.Delta_Time = Param(within=NonNegativeReals) # Time step in hours model.Porcentage_Funded = Param(within=NonNegativeReals) # Porcentaje of the total investment that is Porcentage_Porcentage_Funded by a bank or another entity in % model.Project_Years = Param(model.years, initialize= Initialize_years) # Years of the project model.Maintenance_Operation_Cost_PV = Param(within=NonNegativeReals) # Percentage of the total investment spend in operation and management of solar panels in each period in % model.Maintenance_Operation_Cost_Battery = Param(within=NonNegativeReals) # Percentage of the total investment spend in operation and management of solar panels in each period in % model.Maintenance_Operation_Cost_Generator = Param(within=NonNegativeReals) # Percentage of the total investment spend in operation and management of solar panels in each period in % model.Discount_Rate = Param() # Discount rate of the project in % model.Interest_Rate_Loan = Param() # Interest rate of the loan in % model.Scenario_Weight = Param(model.scenario, within=NonNegativeReals) # VARIABLES # Variables associated to the solar panels model.PV_Units = Var(within=NonNegativeReals) # Number of units of solar panels model.Total_Energy_PV = Var(model.scenario,model.periods, within=NonNegativeReals) # Energy generated for the Pv sistem in Wh # Variables associated to the battery bank model.Battery_Nominal_Capacity = Var(within=NonNegativeReals) # Capacity of the battery bank in Wh model.Energy_Battery_Flow_Out = Var(model.scenario,model.periods, within=NonNegativeReals) # Battery discharge energy in wh model.Energy_Battery_Flow_In = Var(model.scenario,model.periods, within=NonNegativeReals) # Battery charge energy in wh model.State_Of_Charge_Battery = Var(model.scenario,model.periods, within=NonNegativeReals) # State of Charge of the Battery in wh model.Maximun_Charge_Power= Var() # Maximun charge power in w model.Maximun_Discharge_Power = Var() #Maximun discharge power in w # Variables associated to the diesel generator model.Period_Total_Cost_Generator = Var(model.scenario,model.periods, within=NonNegativeReals) model.Energy_Generator_Total = Var(model.scenario, model.periods, within=NonNegativeReals) model.Binary_generator_1 = Var(model.scenario,model.periods, within=Binary) model.Integer_generator = Var(within=NonNegativeIntegers) model.Total_Cost_Generator = Var(model.scenario,within=NonNegativeReals) model.Generator_Total_Period_Energy = Var(model.scenario,model.periods, within=NonNegativeReals) model.Generator_Energy_Integer = Var(model.scenario, model.periods, within=NonNegativeIntegers) model.Last_Energy_Generator = Var(model.scenario, model.periods, within=NonNegativeReals) # Varialbles associated to the energy balance model.Lost_Load = Var(model.scenario,model.periods, within=NonNegativeReals) # Energy not suply by the system kWh model.Energy_Curtailment = Var(model.scenario,model.periods, within=NonNegativeReals) # Curtailment of solar energy in kWh # Variables associated to the project model.Cost_Financial = Var(within=NonNegativeReals) # Financial cost of each period in USD model.Initial_Inversion = Var(within=NonNegativeReals) model.Operation_Maintenance_Cost = Var(within=NonNegativeReals) model.Total_Finalcial_Cost = Var(within=NonNegativeReals) model.Battery_Reposition_Cost = Var(within=NonNegativeReals) model.Scenario_Lost_Load_Cost = Var(model.scenario, within=NonNegativeReals) #### model.Sceneario_Generator_Total_Cost = Var(model.scenario, within=NonNegativeReals) model.Scenario_Net_Present_Cost = Var(model.scenario, within=NonNegativeReals)
def _populate(b, *args): b.A = RangeSet(1, 3) b.v = Var() b.vv = Var(m.A) b.p = Param()
def Model_Creation(model, Renewable_Penetration,Battery_Independency): ''' This function creates the instance for the resolution of the optimization in Pyomo. :param model: Pyomo model as defined in the Micro-Grids library. ''' from pyomo.environ import Param, RangeSet, NonNegativeReals, Var, NonNegativeIntegers # Import library with initialitation funtions for the parameters from Initialize import Initialize_years, Initialize_Demand, Battery_Reposition_Cost,\ Initialize_Renewable_Energy, Marginal_Cost_Generator_1,Min_Bat_Capacity, Start_Cost,\ Marginal_Cost_Generator, Capital_Recovery_Factor # Time parameters model.Periods = Param(within=NonNegativeReals) # Number of periods of analysis of the energy variables model.Years = Param() # Number of years of the project model.StartDate = Param() # Start date of the analisis model.Scenarios = Param() model.Renewable_Source = Param() model.Generator_Type = Param() #SETS model.periods = RangeSet(1, model.Periods) # Creation of a set from 1 to the number of periods in each year model.years = RangeSet(1, model.Years) # Creation of a set from 1 to the number of years of the project model.scenario = RangeSet(1, model.Scenarios) # Creation of a set from 1 to the numbero scenarios to analized model.renewable_source = RangeSet(1, model.Renewable_Source) model.generator_type = RangeSet(1, model.Generator_Type) # PARAMETERS model.Scenario_Weight = Param(model.scenario, within=NonNegativeReals) ######### # Parameters of the PV model.Renewable_Nominal_Capacity = Param(model.renewable_source, within=NonNegativeReals) # Nominal capacity of the PV in W/unit model.Renewable_Inverter_Efficiency = Param(model.renewable_source) # Efficiency of the inverter in % model.Renewable_Invesment_Cost = Param(model.renewable_source, within=NonNegativeReals) # Cost of solar panel in USD/W model.Renewable_Energy_Production = Param(model.scenario,model.renewable_source, model.periods, within=NonNegativeReals, initialize=Initialize_Renewable_Energy) # Energy produccion of a solar panel in W # Parameters of the battery bank model.Charge_Battery_Efficiency = Param() # Efficiency of the charge of the battery in % model.Discharge_Battery_Efficiency = Param() # Efficiency of the discharge of the battery in % model.Deep_of_Discharge = Param() # Deep of discharge of the battery (Deep_of_Discharge) in % model.Maximun_Battery_Charge_Time = Param(within=NonNegativeReals) # Minimun time of charge of the battery in hours model.Maximun_Battery_Discharge_Time = Param(within=NonNegativeReals) # Maximun time of discharge of the battery in hours model.Battery_Invesment_Cost = Param() # Cost of battery model.Battery_Electronic_Invesmente_Cost = Param(within=NonNegativeReals) model.Battery_Cycles = Param(within=NonNegativeReals) model.Unitary_Battery_Reposition_Cost = Param(within=NonNegativeReals, initialize=Battery_Reposition_Cost) model.Battery_Initial_SOC = Param(within=NonNegativeReals) if Battery_Independency > 0: model.Battery_Independency = Battery_Independency model.Battery_Min_Capacity = Param(initialize=Min_Bat_Capacity) # Parametes of the diesel generator if model.formulation == 'LP': model.Generator_Efficiency = Param(model.generator_type) model.Low_Heating_Value = Param(model.generator_type) model.Fuel_Cost = Param(model.generator_type, within=NonNegativeReals) model.Generator_Invesment_Cost = Param(model.generator_type, within=NonNegativeReals) model.Marginal_Cost_Generator_1 = Param(model.generator_type, initialize=Marginal_Cost_Generator_1) elif model.formulation == 'MILP': model.Generator_Min_Out_Put = Param(model.generator_type, within=NonNegativeReals) model.Generator_Efficiency = Param(model.generator_type) # Generator efficiency to trasform heat into electricity % model.Low_Heating_Value = Param(model.generator_type) # Low heating value of the diesel in W/L model.Fuel_Cost = Param(model.generator_type, within=NonNegativeReals) # Cost of diesel in USD/L model.Generator_Invesment_Cost = Param(model.generator_type,within=NonNegativeReals) # Cost of the diesel generator model.Marginal_Cost_Generator_1 = Param(model.generator_type, initialize=Marginal_Cost_Generator_1) model.Cost_Increase = Param(model.generator_type, within=NonNegativeReals) model.Generator_Nominal_Capacity = Param(model.generator_type, within=NonNegativeReals) model.Start_Cost_Generator = Param(model.generator_type, within=NonNegativeReals, initialize=Start_Cost) model.Marginal_Cost_Generator = Param(model.generator_type, initialize=Marginal_Cost_Generator) # Parameters of the Energy balance model.Energy_Demand = Param(model.scenario, model.periods, initialize=Initialize_Demand) # Energy Energy_Demand in W model.Value_Of_Lost_Load = Param(within=NonNegativeReals) # Value of lost load in USD/W if Renewable_Penetration > 0: model.Renewable_Penetration = Renewable_Penetration # Parameters of the proyect model.Delta_Time = Param(within=NonNegativeReals) # Time step in hours model.Project_Years = Param(model.years, initialize= Initialize_years) # Years of the project model.Maintenance_Operation_Cost_Renewable = Param(model.renewable_source, within=NonNegativeReals) # Percentage of the total investment spend in operation and management of solar panels in each period in % model.Maintenance_Operation_Cost_Battery = Param(within=NonNegativeReals) # Percentage of the total investment spend in operation and management of solar panels in each period in % model.Maintenance_Operation_Cost_Generator = Param(model.generator_type, within=NonNegativeReals) # Percentage of the total investment spend in operation and management of solar panels in each period in % model.Discount_Rate = Param() # Discount rate of the project in % model.Capital_Recovery_Factor = Param(within=NonNegativeReals, initialize= Capital_Recovery_Factor) # VARIABLES # Variables associated to the solar panels model.Renewable_Units = Var(model.renewable_source, within=NonNegativeReals,bounds= (10,50000)) # Number of units of solar panels # Variables associated to the battery bank bat = 700000 model.Battery_Nominal_Capacity = Var(within=NonNegativeReals,bounds= (0,bat)) # Capacity of the battery bank in Wh model.Energy_Battery_Flow_Out = Var(model.scenario, model.periods, within=NonNegativeReals,bounds=(0,bat)) # Battery discharge energy in wh model.Energy_Battery_Flow_In = Var(model.scenario, model.periods, within=NonNegativeReals,bounds=(0,bat)) # Battery charge energy in wh model.State_Of_Charge_Battery = Var(model.scenario, model.periods, within=NonNegativeReals) # State of Charge of the Battery in wh model.Maximun_Charge_Power = Var(within=NonNegativeReals,bounds=(0,bat)) model.Maximun_Discharge_Power = Var(within=NonNegativeReals,bounds=(0,bat)) # Variables associated to the diesel generator if model.formulation == 'LP': model.Generator_Nominal_Capacity = Var(model.generator_type, within=NonNegativeReals) # Capacity of the diesel generator in Wh model.Generator_Energy = Var(model.scenario,model.generator_type, model.periods, within=NonNegativeReals) # Energy generated for the Diesel generator elif model.formulation == 'MILP': def gen(model,g): if g == 1: return 1 else: return 1 def bounds_N(model,g): if g == 1: return (1,2) else: return (1,2) def bounds_E(model,s,g,t): if g == 1: return (0,2) else: return (0,2) model.Generator_Energy = Var(model.scenario, model.generator_type, model.periods, within=NonNegativeReals) model.Integer_generator = Var(model.generator_type, within=NonNegativeIntegers, initialize=gen, bounds=bounds_N) model.Generator_Total_Period_Energy = Var(model.scenario, model.generator_type, model.periods, within=NonNegativeReals) model.Generator_Energy_Integer = Var(model.scenario, model.generator_type, model.periods, within=NonNegativeIntegers, bounds=bounds_E) model.Last_Energy_Generator = Var(model.scenario, model.generator_type, model.periods, within=NonNegativeReals) # Varialbles associated to the energy balance if model.Lost_Load_Probability > 0: model.Lost_Load = Var(model.scenario, model.periods, within=NonNegativeReals) # Energy not suply by the system kWh model.Energy_Curtailment = Var(model.scenario, model.periods, within=NonNegativeReals ,bounds=(0,100000)) # Curtailment of solar energy in kWh
def build_constrained_layout_model(): """Build the model.""" m = ConcreteModel(name="2-D constrained layout") m.rectangles = RangeSet(3, doc="Three rectangles") m.circles = RangeSet(2, doc="Two circles") m.rect_length = Param(m.rectangles, initialize={ 1: 5, 2: 7, 3: 3 }, doc="Rectangle length") m.rect_height = Param(m.rectangles, initialize={ 1: 6, 2: 5, 3: 3 }, doc="Rectangle height") m.circle_x = Param(m.circles, initialize={ 1: 15, 2: 50 }, doc="x-coordinate of circle center") m.circle_y = Param(m.circles, initialize={ 1: 10, 2: 80 }, doc="y-coordinate of circle center") m.circle_r = Param(m.circles, initialize={ 1: 6, 2: 5 }, doc="radius of circle") @m.Param(m.rectangles, doc="Minimum feasible x value for rectangle") def x_min(m, rect): return min(m.circle_x[circ] - m.circle_r[circ] + m.rect_length[rect] / 2 for circ in m.circles) @m.Param(m.rectangles, doc="Maximum feasible x value for rectangle") def x_max(m, rect): return max(m.circle_x[circ] + m.circle_r[circ] - m.rect_length[rect] / 2 for circ in m.circles) @m.Param(m.rectangles, doc="Minimum feasible y value for rectangle") def y_min(m, rect): return min(m.circle_y[circ] - m.circle_r[circ] + m.rect_height[rect] / 2 for circ in m.circles) @m.Param(m.rectangles, doc="Maximum feasible y value for rectangle") def y_max(m, rect): return max(m.circle_y[circ] + m.circle_r[circ] - m.rect_height[rect] / 2 for circ in m.circles) m.ordered_rect_pairs = Set(initialize=m.rectangles * m.rectangles, filter=lambda _, r1, r2: r1 != r2) m.rect_pairs = Set(initialize=[(r1, r2) for r1, r2 in m.ordered_rect_pairs if r1 < r2]) m.rect_sep_penalty = Param( m.rect_pairs, initialize={ (1, 2): 300, (1, 3): 240, (2, 3): 100 }, doc="Penalty for separation distance between two rectangles.") def x_bounds(m, rect): return m.x_min[rect], m.x_max[rect] def y_bounds(m, rect): return m.y_min[rect], m.y_max[rect] m.rect_x = Var(m.rectangles, doc="x-coordinate of rectangle center", bounds=x_bounds) m.rect_y = Var(m.rectangles, doc="y-coordinate of rectangle center", bounds=y_bounds) m.dist_x = Var(m.rect_pairs, doc="x-axis separation between rectangle pair") m.dist_y = Var(m.rect_pairs, doc="y-axis separation between rectangle pair") m.min_dist_cost = Objective(expr=sum(m.rect_sep_penalty[r1, r2] * (m.dist_x[r1, r2] + m.dist_y[r1, r2]) for (r1, r2) in m.rect_pairs)) @m.Constraint(m.ordered_rect_pairs, doc="x-distance between rectangles") def dist_x_defn(m, r1, r2): return m.dist_x[tuple(sorted([r1, r2]))] >= m.rect_x[r2] - m.rect_x[r1] @m.Constraint(m.ordered_rect_pairs, doc="y-distance between rectangles") def dist_y_defn(m, r1, r2): return m.dist_y[tuple(sorted([r1, r2]))] >= m.rect_y[r2] - m.rect_y[r1] @m.Disjunction(m.rect_pairs, doc="Make sure that none of the rectangles overlap in " "either the x or y dimensions.") def no_overlap(m, r1, r2): return [ m.rect_x[r1] + m.rect_length[r1] / 2 <= (m.rect_x[r2] - m.rect_length[r2] / 2), m.rect_y[r1] + m.rect_height[r1] / 2 <= (m.rect_y[r2] - m.rect_height[r2] / 2), m.rect_x[r2] + m.rect_length[r2] / 2 <= (m.rect_x[r1] - m.rect_length[r1] / 2), m.rect_y[r2] + m.rect_height[r2] / 2 <= (m.rect_y[r1] - m.rect_height[r1] / 2), ] @m.Disjunction(m.rectangles, doc="Each rectangle must be in a circle.") def rectangle_in_circle(m, r): return [ [ # Rectangle lower left corner in circle (m.rect_x[r] - m.rect_length[r] / 2 - m.circle_x[c])**2 + (m.rect_y[r] + m.rect_height[r] / 2 - m.circle_y[c])**2 <= m.circle_r[c]**2, # rectangle upper left corner in circle (m.rect_x[r] - m.rect_length[r] / 2 - m.circle_x[c])**2 + (m.rect_y[r] - m.rect_height[r] / 2 - m.circle_y[c])**2 <= m.circle_r[c]**2, # rectangle lower right corner in circle (m.rect_x[r] + m.rect_length[r] / 2 - m.circle_x[c])**2 + (m.rect_y[r] + m.rect_height[r] / 2 - m.circle_y[c])**2 <= m.circle_r[c]**2, # rectangle upper right corner in circle (m.rect_x[r] + m.rect_length[r] / 2 - m.circle_x[c])**2 + (m.rect_y[r] - m.rect_height[r] / 2 - m.circle_y[c])**2 <= m.circle_r[c]**2, ] for c in m.circles ] return m
def build(self): super(Iapws95ParameterBlockData, self).build() self.state_block_class = Iapws95StateBlock # Location of the *.so or *.dll file for external functions self.plib = _so self.available = os.path.isfile(self.plib) # Phase list self.private_phase_list = Set(initialize=["Vap", "Liq"]) if self.config.phase_presentation == PhaseType.MIX: self.phase_list = Set(initialize=["Mix"]) elif self.config.phase_presentation == PhaseType.LG: self.phase_list = Set(initialize=["Vap", "Liq"]) elif self.config.phase_presentation == PhaseType.L: self.phase_list = Set(initialize=["Liq"]) elif self.config.phase_presentation == PhaseType.G: self.phase_list = Set(initialize=["Vap"]) # State var set self.state_vars = self.config.state_vars # Component list - a list of component identifiers self.component_list = Set(initialize=['H2O']) # List of phase equilibrium self.phase_equilibrium_idx = Set(initialize=[1]) self.phase_equilibrium_list = {1: ["H2O", ("Vap", "Liq")]} # Parameters, these should match what's in the C code self.temperature_crit = Param(initialize=647.096, doc='Critical temperature [K]') self.pressure_crit = Param(initialize=2.2064e7, doc='Critical pressure [Pa]') self.dens_mass_crit = Param(initialize=322, doc='Critical density [kg/m3]') self.gas_const = Param(initialize=8.3144598, doc='Gas Constant [J/mol/K]') self.mw = Param(initialize=0.01801528, doc='Molecular weight [kg/mol]') #Thermal conductivity parameters. # "Release on the IAPWS Formulation 2011 for the Thermal Conductivity of # Ordinary Water Substance" self.tc_L0 = Param(RangeSet(0, 5), initialize={ 0: 2.443221e-3, 1: 1.323095e-2, 2: 6.770357e-3, 3: -3.454586e-3, 4: 4.096266e-4 }, doc="0th order themalcondutivity paramters") self.tc_L1 = Param(RangeSet(0, 5), RangeSet(0, 6), initialize={ (0, 0): 1.60397357, (1, 0): 2.33771842, (2, 0): 2.19650529, (3, 0): -1.21051378, (4, 0): -2.7203370, (0, 1): -0.646013523, (1, 1): -2.78843778, (2, 1): -4.54580785, (3, 1): 1.60812989, (4, 1): 4.57586331, (0, 2): 0.111443906, (1, 2): 1.53616167, (2, 2): 3.55777244, (3, 2): -0.621178141, (4, 2): -3.18369245, (0, 3): 0.102997357, (1, 3): -0.463045512, (2, 3): -1.40944978, (3, 3): 0.0716373224, (4, 3): 1.1168348, (0, 4): -0.0504123634, (1, 4): 0.0832827019, (2, 4): 0.275418278, (3, 4): 0.0, (4, 4): -0.19268305, (0, 5): 0.00609859258, (1, 5): -0.00719201245, (2, 5): -0.0205938816, (3, 5): 0.0, (4, 5): 0.012913842 }, doc="1st order themalcondutivity paramters") #Viscosity paramters #"Release on the IAPWS Formulation 2008 for the Viscosity of # Ordinary Water Substance " self.visc_H0 = Param(RangeSet(0, 4), initialize={ 0: 1.67752, 1: 2.20462, 2: 0.6366564, 3: -0.241605 }, doc="0th order viscosity parameters") self.visc_H1 = Param(RangeSet(0, 6), RangeSet(0, 7), initialize={ (0, 0): 5.20094e-1, (1, 0): 8.50895e-2, (2, 0): -1.08374, (3, 0): -2.89555e-1, (4, 0): 0.0, (5, 0): 0.0, (0, 1): 2.22531e-1, (1, 1): 9.99115e-1, (2, 1): 1.88797, (3, 1): 1.26613, (4, 1): 0.0, (5, 1): 1.20573e-1, (0, 2): -2.81378e-1, (1, 2): -9.06851e-1, (2, 2): -7.72479e-1, (3, 2): -4.89837e-1, (4, 2): -2.57040e-1, (5, 2): 0.0, (0, 3): 1.61913e-1, (1, 3): 2.57399e-1, (2, 3): 0.0, (3, 3): 0.0, (4, 3): 0.0, (5, 3): 0.0, (0, 4): -3.25372e-2, (1, 4): 0.0, (2, 4): 0.0, (3, 4): 6.98452e-2, (4, 4): 0.0, (5, 4): 0.0, (0, 5): 0.0, (1, 5): 0.0, (2, 5): 0.0, (3, 5): 0.0, (4, 5): 8.72102e-3, (5, 5): 0.0, (0, 6): 0.0, (1, 6): 0.0, (2, 6): 0.0, (3, 6): -4.35673e-3, (4, 6): 0.0, (5, 6): -5.93264e-4 }, doc="1st order viscosity parameters") self.smoothing_pressure_over = Param( mutable=True, initialize=1e-4, doc='Smooth max parameter (pressure over)') self.smoothing_pressure_under = Param( mutable=True, initialize=1e-4, doc='Smooth max parameter (pressure under)')
def _make_params(self): self.P = Param(initialize=self.config.passes, units=None, doc="Total number of passes for hot or cold fluid") self.PH = RangeSet(self.P, doc="Set of hot fluid passes") self.PC = RangeSet(self.P, doc="Set of cold fluid passes(equal to PH)") self.plate_thermal_cond = Param( mutable=True, initialize=self.config.plate_thermal_cond, units=pyunits.W / pyunits.m / pyunits.K, doc="Plate thermal conductivity") self.plate_thick = Param(mutable=True, initialize=self.config.plate_thickness, units=pyunits.m, doc="Plate thickness") self.port_dia = Param(mutable=True, initialize=self.config.port_diameter, units=pyunits.m, doc=" Port diameter of plate ") self.Np = Param(self.PH, units=None, doc="Number of channels in each pass", mutable=True) # Number of channels in each pass for i in self.PH: self.Np[i].value = self.config.channel_list[i - 1] # --------------------------------------------------------------------- # Assign plate specifications # effective plate length & width _effective_plate_length = self.config.plate_vertical_dist - \ self.config.port_diameter _effective_plate_width = self.config.plate_horizontal_dist + \ self.config.port_diameter self.plate_length = Expression(expr=_effective_plate_length) self.plate_width = Expression(expr=_effective_plate_width) # Area of single plate _total_active_plate_number = 2 * sum(self.config.channel_list) - 1 -\ self.config.divider_plate_number self.plate_area = Expression(expr=self.config.total_area / _total_active_plate_number, doc="Heat transfer area of single plate") # Plate gap if self.config.plate_gap is None: _total_plate_number = 2 * sum(self.config.channel_list) + 1 +\ self.config.divider_plate_number _plate_pitch = self.config.plate_pact_length / _total_plate_number _plate_gap = _plate_pitch - self.config.plate_thickness else: _plate_gap = self.config.plate_gap self.plate_gap = Expression(expr=_plate_gap) # Surface enlargement factor if self.config.surface_enlargement_factor is None: _projected_plate_area = _effective_plate_length * _effective_plate_width _surface_enlargement_factor = self.plate_area / _projected_plate_area else: _surface_enlargement_factor = self.config.surface_enlargement_factor self.surface_enlargement_factor = Expression( expr=_surface_enlargement_factor) # Channel equivalent diameter self.channel_dia = Expression(expr=2 * self.plate_gap / _surface_enlargement_factor, doc=" Channel equivalent diameter") # heat transfer parameters self.param_a = Var(initialize=0.3, bounds=(0.2, 0.4), units=None, doc='Nusselt parameter') self.param_b = Var(initialize=0.663, bounds=(0.3, 0.7), units=None, doc='Nusselt parameter') self.param_c = Var(initialize=1 / 3.0, bounds=(1e-5, 2), units=None, doc='Nusselt parameter') self.param_a.fix(0.4) self.param_b.fix(0.663) self.param_c.fix(0.333)
def test_nonnegative_transform_3(self): self.model.S = RangeSet(0, 10) self.model.T = Set(initialize=["foo", "bar"]) # Unindexed, singly indexed, and doubly indexed variables with # explicit bounds self.model.x1 = Var(bounds=(-3, 3)) self.model.y1 = Var(self.model.S, bounds=(-3, 3)) self.model.z1 = Var(self.model.S, self.model.T, bounds=(-3, 3)) # Unindexed, singly indexed, and doubly indexed variables with # rule-defined bounds def boundsRule(*args): return (-4, 4) self.model.x2 = Var(bounds=boundsRule) self.model.y2 = Var(self.model.S, bounds=boundsRule) self.model.z2 = Var(self.model.S, self.model.T, bounds=boundsRule) # Unindexed, singly indexed, and doubly indexed variables with # explicit domains self.model.x3 = Var(domain=NegativeReals, bounds=(-10, 10)) self.model.y3 = Var(self.model.S, domain=NegativeIntegers, bounds=(-10, 10)) self.model.z3 = Var(self.model.S, self.model.T, domain=Reals, bounds=(-10, 10)) # Unindexed, singly indexed, and doubly indexed variables with # rule-defined domains def domainRule(*args): if len(args) == 1: arg = 0 else: arg = args[1] if len(args) == 1 or arg == 0: return NonNegativeReals elif arg == 1: return NonNegativeIntegers elif arg == 2: return NonPositiveReals elif arg == 3: return NonPositiveIntegers elif arg == 4: return NegativeReals elif arg == 5: return NegativeIntegers elif arg == 6: return PositiveReals elif arg == 7: return PositiveIntegers elif arg == 8: return Reals elif arg == 9: return Integers elif arg == 10: return Binary else: return Reals self.model.x4 = Var(domain=domainRule, bounds=(-10, 10)) self.model.y4 = Var(self.model.S, domain=domainRule, bounds=(-10, 10)) self.model.z4 = Var(self.model.S, self.model.T, domain=domainRule, bounds=(-10, 10)) def objRule(model): return sum(5*sum_product(model.__getattribute__(c+n)) \ for c in ('x', 'y', 'z') for n in ('1', '2', '3', '4')) self.model.obj = Objective(rule=objRule) transform = TransformationFactory('core.nonnegative_vars') instance = self.model.create_instance() transformed = transform.create_using(instance) opt = SolverFactory("glpk") instance_sol = opt.solve(instance) transformed_sol = opt.solve(transformed) self.assertEqual( instance_sol["Solution"][0]["Objective"]['obj']["value"], transformed_sol["Solution"][0]["Objective"]['obj']["value"])
Weights = [30, 90, 50, 70, 60, 50] # In quintal Costs = [50, 100, 80, 85, 92, 115] # Thousand of euros # Componets of metal in each block (given in percetange) Cs = [ [93, 76, 74, 65, 72, 68], # Ferro [5, 13, 11, 16, 6, 23], # Cromo [0, 11, 12, 14, 20, 8], # Nichel [2, 0, 3, 5, 2, 1] ] # Impurità # Create concrete model m = ConcreteModel() # Set of indices m.I = RangeSet(0, len(Blocks) - 1) # Variables def fb(m, i): return 0, Weights[i] m.x = Var(m.I, domain=NonNegativeReals, bounds=fb) # Objective Function m.obj = Objective(expr=sum(Costs[i] * m.x[i] for i in m.I)) # Production Constraints m.c1 = Constraint(expr=sum(Cs[0][i] / 100 * m.x[i] for i in m.I) >= 65)
maximize, Objective, Param, RangeSet, SolverFactory, summation, TransformationFactory, value, Var, ) from pyomo.gdp import Disjunct, Disjunction def build_model(case="Growth"): m = ConcreteModel() m.months = RangeSet(0, 120, doc="10 years") m.discount_rate = Param(initialize=0.08, doc="8%") m.conv_setup_time = Param(initialize=12) m.modular_setup_time = Param(initialize=3) m.modular_teardown_time = Param(initialize=3) m.conventional_salvage_value = Param(initialize=0.05, doc="5%") m.module_salvage_value = Param(initialize=0.3, doc="30%") @m.Param(m.months, doc="Discount factor") def discount_factor(m, mo): return (1 + m.discount_rate / 12)**(-mo / 12) @m.Param(m.months, doc="Value of each unit of production") def production_value(m, mo): return (7 / 12) * m.discount_factor[mo]
def add_concave_linear_underest(b, name, nsegs, x, f, f_expr, *sets, **kwargs): exists = kwargs.get('exists', 1.0) bb = kwargs.get('block_bounds', {}) if not isinstance(sets, tuple): sets = (sets, ) segs = b.segs = RangeSet(nsegs) segs_m1 = b.segs_m1 = RangeSet(nsegs - 1) sets_segs = sets + (segs, ) sets_segs_m1 = sets + (segs_m1, ) def calc_lengths(m, *i): i = i if i else None # change empty tuple to None return (ub(x[i], bb) - lb(x[i], bb)) / nsegs seg_length = b.seg_length = Param(*sets, initialize=calc_lengths) delta = b.delta = Var(*sets_segs, domain=NonNegativeReals) for i_seg in delta._index: if not isinstance(i_seg, tuple): # if we're getting a singleton (not defined over a set) i = None else: i = i_seg[:-1] delta[i_seg].setub(seg_length[i]) w = b.w = Var(*sets_segs_m1, domain=Binary) def x_defn(m, *i): i = i if i else None # change empty tuple to None return x[i] == lb(x[i], bb) + sum(delta[cc(i, s)] for s in segs) - \ (1 - exists) * (lb(x[i], bb) - lb(x[i])) # TODO: this restricts the upper bound of x[i] when the unit does not exist. This is fine if x[i] = 0 when the unit doesn't exist, but is a hack otherwise. b.x_defn = Constraint(*sets, rule=x_defn) def f_lb(m, *i): if len(i) == 0: i = None if abs(seg_length[i]) < 1E-10: return f[i] >= f_expr(*cc(i, lb(x[i], bb))) - \ (1 - exists) * (f_expr(*cc(i, lb(x[i], bb))) - f_expr(*cc(i, lb(x[i])))) return f[i] >= f_expr(*cc(i, lb(x[i], bb))) + \ sum((f_expr(*cc(i, lb(x[i], bb) + s * seg_length[i])) - f_expr(*cc(i, lb(x[i], bb) + (s - 1) * seg_length[i])) ) / seg_length[i] * delta[cc(i, s)] for s in segs) - \ (1 - exists) * (f_expr(*cc(i, lb(x[i], bb))) - f_expr(*cc(i, lb(x[i])))) b.f_lb = Constraint(*sets, rule=f_lb) def delta_lb(m, *i_seg): # split out the segment from the sets i, seg = i_seg[:-1], i_seg[-1] return seg_length[i] * w[i, seg] <= delta[ i, seg] if seg < nsegs else Constraint.NoConstraint b.delta_lb = Constraint(*sets_segs, rule=delta_lb) def delta_ub(m, *i_seg): i, seg = i_seg[:-1], i_seg[-1] return delta[i, seg] <= seg_length[i] * w[ i, seg - 1] if seg > 1 else Constraint.NoConstraint b.delta_ub = Constraint(*sets_segs, rule=delta_ub)
def __init__(self, convex=True, *args, **kwargs): """Create the flowsheet.""" kwargs.setdefault('name', 'DuranEx3') super(EightProcessFlowsheet, self).__init__(*args, **kwargs) m = self """Set declarations""" I = m.I = RangeSet(2, 25, doc="process streams") J = m.J = RangeSet(1, 8, doc="process units") m.PI = RangeSet(1, 4, doc="integer constraints") m.DS = RangeSet(1, 4, doc="design specifications") """ 1: Unit 8 2: Unit 8 3: Unit 4 4: Unit 4 """ m.MB = RangeSet(1, 7, doc="mass balances") """Material balances: 1: 4-6-7 2: 3-5-8 3: 4-5 4: 1-2 5: 1-2-3 6: 6-7-4 7: 6-7 """ """Parameter and initial point declarations""" # FIXED COST INVESTMENT COEFF FOR PROCESS UNITS # Format: process #: cost fixed_cost = {1: 5, 2: 8, 3: 6, 4: 10, 5: 6, 6: 7, 7: 4, 8: 5} CF = m.CF = Param(J, initialize=fixed_cost) # VARIABLE COST COEFF FOR PROCESS UNITS - STREAMS # Format: stream #: cost variable_cost = { 3: -10, 5: -15, 9: -40, 19: 25, 21: 35, 25: -35, 17: 80, 14: 15, 10: 15, 2: 1, 4: 1, 18: -65, 20: -60, 22: -80 } CV = m.CV = Param(I, initialize=variable_cost, default=0) # initial point information for equipment selection (for each NLP # subproblem) initY = { 'sub1': { 1: 1, 2: 0, 3: 1, 4: 1, 5: 0, 6: 0, 7: 1, 8: 1 }, 'sub2': { 1: 0, 2: 1, 3: 1, 4: 1, 5: 0, 6: 1, 7: 0, 8: 1 }, 'sub3': { 1: 1, 2: 0, 3: 1, 4: 0, 5: 1, 6: 0, 7: 0, 8: 1 } } # initial point information for stream flows initX = { 1: 0, 2: 2, 3: 1.5, 4: 0, 5: 0, 6: 0.75, 7: 0.5, 8: 0.5, 9: 0.75, 10: 0, 11: 1.5, 12: 1.34, 13: 2, 14: 2.5, 15: 0, 16: 0, 17: 2, 18: 0.75, 19: 2, 20: 1.5, 21: 0, 22: 0, 23: 1.7, 24: 1.5, 25: 0.5 } """Variable declarations""" # BINARY VARIABLE DENOTING EXISTENCE-NONEXISTENCE Y = m.Y = Var(J, domain=Binary, initialize=initY['sub1']) # FLOWRATES OF PROCESS STREAMS X = m.X = Var(I, domain=NonNegativeReals, initialize=initX) # OBJECTIVE FUNCTION CONSTANT TERM CONSTANT = m.constant = Param(initialize=122.0) """Constraint definitions""" # INPUT-OUTPUT RELATIONS FOR process units 1 through 8 m.inout3 = Constraint(expr=1.5 * m.X[9] + m.X[10] == m.X[8]) m.inout4 = Constraint(expr=1.25 * (m.X[12] + m.X[14]) == m.X[13]) m.inout5 = Constraint(expr=m.X[15] == 2 * m.X[16]) if convex: m.inout1 = Constraint(expr=exp(m.X[3]) - 1 <= m.X[2]) m.inout2 = Constraint(expr=exp(m.X[5] / 1.2) - 1 <= m.X[4]) m.inout7 = Constraint(expr=exp(m.X[22]) - 1 <= m.X[21]) m.inout8 = Constraint(expr=exp(m.X[18]) - 1 <= m.X[10] + m.X[17]) m.inout6 = Constraint(expr=exp(m.X[20] / 1.5) - 1 <= m.X[19]) else: m.inout1 = Constraint(expr=exp(m.X[3]) - 1 == m.X[2]) m.inout2 = Constraint(expr=exp(m.X[5] / 1.2) - 1 == m.X[4]) m.inout7 = Constraint(expr=exp(m.X[22]) - 1 == m.X[21]) m.inout8 = Constraint(expr=exp(m.X[18]) - 1 == m.X[10] + m.X[17]) m.inout6 = Constraint(expr=exp(m.X[20] / 1.5) - 1 == m.X[19]) # Mass balance equations m.massbal1 = Constraint(expr=m.X[13] == m.X[19] + m.X[21]) m.massbal2 = Constraint(expr=m.X[17] == m.X[9] + m.X[16] + m.X[25]) m.massbal3 = Constraint(expr=m.X[11] == m.X[12] + m.X[15]) m.massbal4 = Constraint(expr=m.X[3] + m.X[5] == m.X[6] + m.X[11]) m.massbal5 = Constraint(expr=m.X[6] == m.X[7] + m.X[8]) m.massbal6 = Constraint(expr=m.X[23] == m.X[20] + m.X[22]) m.massbal7 = Constraint(expr=m.X[23] == m.X[14] + m.X[24]) # process specifications m.specs1 = Constraint(expr=m.X[10] <= 0.8 * m.X[17]) m.specs2 = Constraint(expr=m.X[10] >= 0.4 * m.X[17]) m.specs3 = Constraint(expr=m.X[12] <= 5 * m.X[14]) m.specs4 = Constraint(expr=m.X[12] >= 2 * m.X[14]) # Logical constraints (big-M) for each process. # These allow for flow iff unit j exists m.logical1 = Constraint(expr=m.X[2] <= 10 * m.Y[1]) m.logical2 = Constraint(expr=m.X[4] <= 10 * m.Y[2]) m.logical3 = Constraint(expr=m.X[9] <= 10 * m.Y[3]) m.logical4 = Constraint(expr=m.X[12] + m.X[14] <= 10 * m.Y[4]) m.logical5 = Constraint(expr=m.X[15] <= 10 * m.Y[5]) m.logical6 = Constraint(expr=m.X[19] <= 10 * m.Y[6]) m.logical7 = Constraint(expr=m.X[21] <= 10 * m.Y[7]) m.logical8 = Constraint(expr=m.X[10] + m.X[17] <= 10 * m.Y[8]) # pure integer constraints m.pureint1 = Constraint(expr=m.Y[1] + m.Y[2] == 1) m.pureint2 = Constraint(expr=m.Y[4] + m.Y[5] <= 1) m.pureint3 = Constraint(expr=m.Y[6] + m.Y[7] - m.Y[4] == 0) m.pureint4 = Constraint(expr=m.Y[3] - m.Y[8] <= 0) """Cost (objective) function definition""" m.cost = Objective(expr=sum(Y[j] * CF[j] for j in J) + sum(X[i] * CV[i] for i in I) + CONSTANT, sense=minimize) """Bound definitions""" # x (flow) upper bounds # x_ubs = {3: 2, 5: 2, 9: 2, 10: 1, 14: 1, 17: 2, 19: 2, 21: 2, 25: 3} x_ubs = { 2: 10, 3: 2, 4: 10, 5: 2, 9: 2, 10: 1, 14: 1, 17: 2, 18: 10, 19: 2, 20: 10, 21: 2, 22: 10, 25: 3 } # add bounds for variables in nonlinear constraints for i, x_ub in x_ubs.items(): X[i].setub(x_ub)
def _make_vars(self): ''' This section is for variables within this model.''' # Number of waterwall zones is given by config, # Optionally the model could contain a platen and a roof superheater self.deltaP = Var(self.flowsheet().config.time, initialize=1000, doc='Pressure drop of secondary air ' 'through windbox and burner [Pa]') self.zones = RangeSet(self.config.number_of_zones) self.fcorrection_heat_ww = Var(self.flowsheet().config.time, initialize=1, doc='Correction factor ' 'for waterwall heat duty') if self.config.has_platen_superheater is True: self.fcorrection_heat_platen = Var(self.flowsheet().config.time, initialize=1, doc='Correction factor for ' 'platen SH heat duty') # wall temperatures of water wall zones self.wall_temperature_waterwall = Var(self.flowsheet().config.time, self.zones, initialize=700.0, doc='Wall temperature [K] in ' 'Waterwall zones') # heat duties for water wall zones self.waterwall_heat = Var(self.flowsheet().config.time, self.zones, initialize=2.0e7, doc='Heat duty [W] or heat loss ' 'to waterwall zones') if self.config.has_platen_superheater is True: # heat duty to platen super heater self.platen_heat = Var(self.flowsheet().config.time, initialize=6.0e7, doc='Platen superheater heat duty [W]') # wall temperature of platen superheater self.wall_temperature_platen = Var(self.flowsheet().config.time, initialize=800.0, doc='Platen superheater' ' wall temperature [K]') if self.config.has_roof_superheater is True: # heat duty to roof superheater self.roof_heat = Var(self.flowsheet().config.time, initialize=5e6, doc='Roof superheater heat duty [W]') # wall temperature of roof superheater self.wall_temperature_roof = Var(self.flowsheet().config.time, initialize=800.0, doc='Roof superheater ' 'wall temperature [K]') # PA/coal temperature, usually fixed around 150 F self.temperature_coal = Var(self.flowsheet().config.time, initialize=338.7, doc='Coal temperature in K') # overall Stoichiometric ratio, used to calculate total # combustion air flowrate # If SR is a function of load or raw coal flow rate, # specify constraint in flowsheet model self.SR = Var(self.flowsheet().config.time, initialize=1.15, doc='Overall furnace Stoichiometric ratio - SR') # lower furnace Stoichiometric ratio self.SR_lf = Var(self.flowsheet().config.time, initialize=1.15, doc='Lower furnace Stoichiometric ratio' ' - SR excluding overfire air') # PA to coal mass flow ratio, # typically 2.0 depending on load or mill curve # usually this is an input of surrogate model self.ratio_PA2coal = Var(self.flowsheet().config.time, initialize=2.0, doc='Primary air to coal ratio') # mass flow rate of raw coal fed to mill # (raw coal flow without moisture vaporization in mill) self.flowrate_coal_raw = Var(self.flowsheet().config.time, initialize=25.0, doc='Raw coal mass flowrate [kg/s]') # mass flow rate of coal to burners after moisture vaporization in mill self.flowrate_coal_burner = Var(self.flowsheet().config.time, initialize=20.0, doc='Mass flowrate coal to burners ' 'with moisture' ' partially vaporized in mill [kg/s]') # raw coal moisture mass fraction (on as received basis), # can change with time to represent HHV change on as received basis self.mf_H2O_coal_raw = Var(self.flowsheet().config.time, initialize=0.15, doc='Raw coal mass fraction of' ' moisture on as received basis') # moisture mass fraction of coal to burners after mill, # calculated based on fraction of moistures vaporized in mill self.mf_H2O_coal_burner = Var(self.flowsheet().config.time, initialize=0.15, doc='Mass fraction of moisture' ' on as received basis') # Fraction of moisture vaporized in mill, # set in flowsheet as a function of coal flow rate, default is 0.6 self.frac_moisture_vaporized = Var(self.flowsheet().config.time, initialize=0.6, doc='Fraction of coal' ' moisture vaporized in mill') # Vaporized moisture mass flow rate @self.Expression(self.flowsheet().config.time, doc="Vaporized moisture mass flowrate [kg/s]") def flowrate_moist_vaporized(b, t): return b.flowrate_coal_raw[t] * b.mf_H2O_coal_raw[t] \ * b.frac_moisture_vaporized[t] # Elemental composition of dry coal, assuming fixed over time # They are usually fixed as user inputs self.mf_C_coal_dry = Var(initialize=0.5, doc='Mass fraction of C on dry basis') self.mf_H_coal_dry = Var(initialize=0.05, doc='Mass fraction of H on dry basis') self.mf_O_coal_dry = Var(initialize=0.1, doc='Mass fraction of O on dry basis') self.mf_N_coal_dry = Var(initialize=0.1, doc='Mass fraction of N on dry basis') self.mf_S_coal_dry = Var(initialize=0.05, doc='Mass fraction of S on dry basis') self.mf_Ash_coal_dry = Var(initialize=0.2, doc='Mass fraction of Ash on dry basis') # High heating value of dry coal, usally as a fixed user input self.hhv_coal_dry = Var(initialize=1e7, doc='High heating value (HHV)' 'of coal on dry basis J/kg') # Fraction of unburned carbon (actually all organic elements) in # flyash, predicted by surrogate model. # When generating the surrogate, sum up all elements in # flyash from fireside boiler model outputs self.ubc_in_flyash = Var(self.flowsheet().config.time, initialize=0.01, doc='Unburned carbon and' ' other organic elements in fly ash') # mole fraction of NO in flue gas, predicted by surrogate model # usually mole fraction is very close to mass fraction of NO self.frac_mol_NOx_fluegas = Var(self.flowsheet().config.time, initialize=1e-4, doc='Mole fraction of NOx in flue gas') # NOx in lb/MMBTU, NO is converted to NO2 as NOx @self.Expression(self.flowsheet().config.time, doc="NOx in lb/MMBTU") def nox_lb_mmbtu(b, t): return b.flue_gas_outlet.flow_mol_comp[t, "NO"] * 0.046 * 2.20462 \ / (b.flowrate_coal_raw[t] * (1-b.mf_H2O_coal_raw[t]) * b.hhv_coal_dry/1.054e9) # coal flow rate after mill @self.Constraint(self.flowsheet().config.time, doc="Coal flow rate to burners after mill") def flowrate_coal_burner_eqn(b, t): return b.flowrate_coal_burner[t] == b.flowrate_coal_raw[t] \ - b.flowrate_moist_vaporized[t] # moisture mass fraction in coal after mill @self.Constraint(self.flowsheet().config.time, doc="Moisture mass fraction for coal after mill") def mf_H2O_coal_burner_eqn(b, t): return b.flowrate_coal_raw[t] * b.mf_H2O_coal_raw[t] == \ b.flowrate_coal_burner[t] * b.mf_H2O_coal_burner[t] \ + b.flowrate_moist_vaporized[t] # fraction of daf elements on dry basis @self.Expression(doc="Mass fraction of dry ash free (daf)") def mf_daf_dry(b): return 1 - b.mf_Ash_coal_dry @self.Expression(self.flowsheet().config.time, doc="Ash mass flow rate kg/s") def flowrate_ash(b, t): return b.flowrate_coal_raw[t] * \ (1-b.mf_H2O_coal_raw[t])*b.mf_Ash_coal_dry @self.Expression(self.flowsheet().config.time, doc="Dry ash free - daf_coal flow rate " "in fuel fed to the boiler kg/s") def flowrate_daf_fuel(b, t): return b.flowrate_coal_raw[t] * \ (1-b.mf_H2O_coal_raw[t]) * b.mf_daf_dry @self.Expression(self.flowsheet().config.time, doc="Dry ash free (daf) coal flow rate in fly ash") def flowrate_daf_flyash(b, t): return b.flowrate_ash[t] / (1.0 - b.ubc_in_flyash[t]) \ * b.ubc_in_flyash[t] @self.Expression(self.flowsheet().config.time, doc="Burned daf coal flow rate") def flowrate_daf_burned(b, t): return b.flowrate_daf_fuel[t] - b.flowrate_daf_flyash[t] @self.Expression(self.flowsheet().config.time, doc="Coal burnout") def coal_burnout(b, t): return b.flowrate_daf_burned[t] / b.flowrate_daf_fuel[t] @self.Expression(doc="Dry ash free - daf C mass fraction") def mf_C_daf(b): return b.mf_C_coal_dry / b.mf_daf_dry @self.Expression(doc="Dry ash free - daf H mass fraction") def mf_H_daf(b): return b.mf_H_coal_dry / b.mf_daf_dry @self.Expression(doc="Dry ash free - daf O mass fraction") def mf_O_daf(b): return b.mf_O_coal_dry / b.mf_daf_dry @self.Expression(doc="Dry ash free - daf N mass fraction") def mf_N_daf(b): return b.mf_N_coal_dry / b.mf_daf_dry @self.Expression(doc="Dry ash free - daf S mass fraction") def mf_S_daf(b): return b.mf_S_coal_dry / b.mf_daf_dry @self.Expression(doc="Dry ash free high heating value in J/kg") def hhv_daf(b): return b.hhv_coal_dry / b.mf_daf_dry @self.Expression(doc="Heat of combustion at constant " "pressure on daf basis in J/kg") # Note that measure HHV is the heat of combustion at constant volume def dhcoal(b): return -b.hhv_daf + const.gas_constant * 298.15 / 2 \ * (-b.mf_H_daf/2/b.atomic_mass_H + b.mf_O_daf/b.atomic_mass_O + b.mf_N_daf/b.atomic_mass_N) @self.Expression(doc="Carbon heat of reaction - dhc J/kg") def dhc(b): return -94052 * 4.184 / b.atomic_mass_C * b.mf_C_daf @self.Expression(doc="Hydrogen heat of reaction - dhh in J/kg") def dhh(b): return -68317.4 * 4.184 / b.atomic_mass_H / 2 * b.mf_H_daf @self.Expression(doc="Sulfur heat of reaction - dhs in J/kg") def dhs(b): return -70940 * 4.184 / b.atomic_mass_S * b.mf_S_daf @self.Expression(doc="Heat of formation for daf coal in J/kg") def hf_daf(b): return b.dhc + b.dhh + b.dhs - b.dhcoal @self.Expression(self.flowsheet().config.time, doc="Heat of formation of " "moisture-containing coal to burners") def hf_coal(b, t): return b.hf_daf * (1-b.mf_H2O_coal_burner[t]) * b.mf_daf_dry \ + b.mf_H2O_coal_burner[t]*(-68317.4)*4.184/(b.atomic_mass_H*2 + b.atomic_mass_O) @self.Expression(doc="Average atomic mass of daf coal") def am_daf(b): return 1 / ( b.mf_C_daf / b.atomic_mass_C + b.mf_H_daf / b.atomic_mass_H + b.mf_O_daf / b.atomic_mass_O + b.mf_N_daf / b.atomic_mass_N + b.mf_S_daf / b.atomic_mass_S) @self.Expression(self.flowsheet().config.time, doc="Gt1 or Einstein quantum theory function for daf " "coal sensible heat calculation") def gt1(b, t): return 1 / (exp(380 / b.temperature_coal[t]) - 1) # since flyash and flue gas outlet temperature is not fixed self.gt1_flyash = Var(self.flowsheet().config.time, initialize=1, doc='Gt1 or Einstein quantum theory function' ' for daf part of flyash') @self.Constraint(self.flowsheet().config.time, doc="Gt1 or Einstein quantum theory " "for daf part of flyash") def gt1_flyash_eqn(b, t): return b.gt1_flyash[t] \ * (exp(380/b.flue_gas[t].temperature)-1) == 1 @self.Expression(self.flowsheet().config.time, doc="Gt2 or Einstein quantum theory " "function for daf coal " "sensible heat calculation for high temperature") def gt2(b, t): return 1 / (exp(1800 / b.temperature_coal[t]) - 1) # declare variable rather than use expression # since flyash and flue gas outlet temperature is not fixed self.gt2_flyash = Var(self.flowsheet().config.time, initialize=1, doc='Gt2 or Einstein quantum theory function ' 'for daf part of flyash') @self.Constraint(self.flowsheet().config.time, doc="Gt2 or Einstein quantum theory function " "for daf part of flyash") def gt2_flyash_eqn(b, t): return b.gt2_flyash[t] \ * (exp(1800/b.flue_gas[t].temperature)-1) == 1 @self.Expression(self.flowsheet().config.time, doc="Sensible heat of daf coal") def hs_daf(b, t): return const.gas_constant / b.am_daf * (380 * (b.gt1[t] - 0.3880471566) + 3600 * (b.gt2[t] - 0.002393883)) @self.Expression(self.flowsheet().config.time, doc="Sensible heat for daf part of flyash") def hs_daf_flyash(b, t): return const.gas_constant / b.am_daf * ( 380 * (b.gt1_flyash[t] - 0.3880471566) + 3600 * (b.gt2_flyash[t] - 0.002393883)) @self.Expression(self.flowsheet().config.time, doc="Sensible heat of coal to burners") def hs_coal(b, t): return (1-b.mf_H2O_coal_burner[t]) * b.mf_daf_dry * b.hs_daf[t] \ + b.mf_H2O_coal_burner[t]*4184*(b.temperature_coal[t]-298.15) \ + (1-b.mf_H2O_coal_burner[t]) * b.mf_Ash_coal_dry \ * (593 * (b.temperature_coal[t]-298.15) + 0.293*(b.temperature_coal[t]**2 - 298.15**2)) @self.Expression(self.flowsheet().config.time, doc="Total enthalpy of " "moisture-containing coal to burners") def h_coal(b, t): return b.hs_coal[t] + b.hf_coal[t] # variable for O2 mole fraction in flue gas on dry basis # it can be used for data reconciliation and parameter estimation self.fluegas_o2_pct_dry = Var(self.flowsheet().config.time, initialize=3, doc='Mol percent of O2 on dry basis')