def test_case_sensitive_shortnamelabeler(self): m = self.m lbl = ShortNameLabeler(20, '_') self.assertEqual(lbl(m.mycomp), 'mycomp') self.assertEqual(lbl(m.that), 'that') self.assertEqual(lbl(self.long1), 'longcomponentname_1_') self.assertEqual(lbl(self.long2), 'nentnamerighthere_2_') self.assertEqual(lbl(self.long3), 'ngonebutdifferent_3_') self.assertEqual(lbl(self.long4), 'longcomponentname_4_') self.assertEqual(lbl(self.long5), 'gcomponentname_1__5_') self.assertEqual(lbl(m.myblock), 'myblock') self.assertEqual(lbl(m.myblock.mystreet), 'myblock_mystreet') self.assertEqual(lbl(m.ind[3]), 'ind_3_') self.assertEqual(lbl(m.ind[10]), 'ind_10_') self.assertEqual(lbl(m.ind[1]), 'ind_1_') self.assertEqual(lbl(self.thecopy), '_myblock_mystreet_') # Test name collision m._myblock = Block() m._myblock.mystreet_ = Var() self.assertEqual(lbl(m.mycomp), 'mycomp_6_') self.assertEqual(lbl(m._myblock.mystreet_), 'myblock_mystreet__7_') self.assertEqual(lbl(m.MyComp), 'MyComp')
def test_str(self): m = ConcreteModel() m.b = Block() # Note that we are testing the string representation of a slice, # not if the slice is valid s = m.b[...].x[:, 1:2, 1:5:2, ::1, 5, 'a'].component('foo', kwarg=1) self.assertEqual( str(s), "b[...].x[:, 1:2, 1:5:2, ::1, 5, 'a'].component('foo', kwarg=1)") # To test set / del, we want to form the IndexedComponent_slice # without evaluating it s = m.b[...] self.assertEqual( str( IndexedComponent_slice( s, (IndexedComponent_slice.del_attribute, 'bogus'))), 'del b[...].bogus') self.assertEqual( str( IndexedComponent_slice( s, (IndexedComponent_slice.set_attribute, 'bogus', 10))), 'b[...].bogus = 10')
def test_nested_reference_nonuniform_index_size(self): m = ConcreteModel() m.I = Set(initialize=[1, 2]) m.J = Set(initialize=[3, 4]) m.b = Block(m.I) m.b[1].x = Var([(3, 3), (3, 4), (4, 3), (4, 4)], bounds=(1, None)) m.b[2].x = Var(m.J, m.J, bounds=(2, None)) m.r = Reference(m.b[:].x[:, :]) self.assertIs(m.r.ctype, Var) self.assertIs(type(m.r.index_set()), UnorderedSetOf) self.assertEqual(len(m.r), 2 * 2 * 2) self.assertEqual(m.r[1, 3, 3].lb, 1) self.assertEqual(m.r[2, 4, 3].lb, 2) self.assertIn((1, 3, 3), m.r) self.assertIn((2, 4, 4), m.r) self.assertNotIn(0, m.r) self.assertNotIn((1, 0), m.r) self.assertNotIn((1, 3, 0), m.r) self.assertNotIn((1, 3, 3, 0), m.r) with self.assertRaises(KeyError): m.r[0]
def test_solve_linear_GDP_unbounded(self): m = ConcreteModel() m.GDPopt_utils = Block() m.x = Var(bounds=(-1, 10)) m.y = Var(bounds=(2, 3)) m.z = Var() m.d = Disjunction(expr=[[m.x + m.y >= 5], [m.x - m.y <= 3]]) m.o = Objective(expr=m.z) m.GDPopt_utils.variable_list = [m.x, m.y, m.z] m.GDPopt_utils.disjunct_list = [ m.d._autodisjuncts[0], m.d._autodisjuncts[1] ] output = StringIO() with LoggingIntercept(output, 'pyomo.contrib.gdpopt', logging.WARNING): solver_data = GDPoptSolveData() solver_data.timing = Container() with time_code(solver_data.timing, 'main', is_main_timer=True): solve_linear_GDP( m, solver_data, GDPoptSolver.CONFIG(dict(mip_solver=mip_solver))) self.assertIn( "Linear GDP was unbounded. Resolving with arbitrary bound values", output.getvalue().strip())
def get_costing(self, module=costing, Mat_factor="stain_steel", mover_type="compressor", compressor_type="centrifugal", driver_mover_type="electrical_motor", pump_type="centrifugal", pump_type_factor='1.4', pump_motor_type_factor='open', year=None): if not hasattr(self.flowsheet(), "costing"): self.flowsheet().get_costing(year=year) self.costing = Block() module.pressure_changer_costing( self.costing, Mat_factor=Mat_factor, mover_type=mover_type, compressor_type=compressor_type, driver_mover_type=driver_mover_type, pump_type=pump_type, pump_type_factor=pump_type_factor, pump_motor_type_factor=pump_motor_type_factor)
def get_model(): # Borrowed this test model from the trust region tests m = ConcreteModel() m.z = Var(range(3), domain=Reals, initialize=2.) m.x = Var(range(4), initialize=2.) m.x[1] = 1.0 m.x[2] = 0.0 m.x[3] = None m.b1 = Block() m.b1.e1 = Expression(expr=m.x[0] + m.x[1]) m.b1.e2 = Expression(expr=m.x[0] / m.x[2]) m.b1.e3 = Expression(expr=m.x[3] * m.x[1]) m.b1.e4 = Expression(expr=log(m.x[2])) m.b1.e5 = Expression(expr=log(m.x[2] - 2)) def blackbox(a, b): return sin(a - b) m.bb = ExternalFunction(blackbox) m.obj = Objective( expr=(m.z[0]-1.0)**2 + (m.z[0]-m.z[1])**2 + (m.z[2]-1.0)**2 \ + (m.x[0]-1.0)**4 + (m.x[1]-1.0)**6 # + m.bb(m.x[0],m.x[1]) ) m.c1 = Constraint(expr=m.x[0] * m.z[0]**2 + m.bb(m.x[0], m.x[1]) == 2 * sqrt(2.0)) m.c2 = Constraint(expr=m.z[2]**4 * m.z[1]**2 + m.z[1] == 8 + sqrt(2.0)) m.c3 = Constraint(expr=m.x[1] == 3) m.c4 = Constraint(expr=0 == 3 / m.x[2]) m.c5 = Constraint(expr=0 == log(m.x[2])) m.c6 = Constraint(expr=0 == log(m.x[2] - 4)) m.c7 = Constraint(expr=0 == log(m.x[3])) m.p1 = Param(mutable=True, initialize=1) m.c8 = Constraint(expr=m.x[1] <= 1 / m.p1) m.p1 = 0 return m
def setUp(self): # Borrowed this test model from the trust region tests m = ConcreteModel(name="tm") m.z = Var(range(3), domain=Reals, initialize=2.) m.x = Var(range(2), initialize=2.) m.x[1] = 1.0 m.b1 = Block() m.b1.e1 = Expression(expr=m.x[0] + m.x[1]) def blackbox(a, b): return sin(a - b) self.bb = ExternalFunction(blackbox) m.obj = Objective( expr=(m.z[0]-1.0)**2 + (m.z[0]-m.z[1])**2 + (m.z[2]-1.0)**2 \ + (m.x[0]-1.0)**4 + (m.x[1]-1.0)**6 # + m.bb(m.x[0],m.x[1]) ) m.c1 = Constraint(expr=m.x[0] * m.z[0]**2 + self.bb(m.x[0], m.x[1]) == 2 * sqrt(2.0)) m.c2 = Constraint(expr=m.z[2]**4 * m.z[1]**2 + m.z[1] == 8 + sqrt(2.0)) self.m = m.clone()
def test_ctype_detection(self): m = ConcreteModel() m.js = Set(initialize=[1, (2, 3)], dimen=None) m.b = Block([1, 2]) m.b[1].x = Var(m.js) m.b[1].y = Var() m.b[1].z = Var([1, 2]) m.b[2].x = Param(initialize=0) m.b[2].y = Var() m.b[2].z = Var([1, 2]) m.x = Reference(m.b[:].x[...]) self.assertIs(type(m.x), IndexedComponent) m.y = Reference(m.b[:].y[...]) self.assertIs(type(m.y), IndexedVar) self.assertIs(m.y.ctype, Var) m.y1 = Reference(m.b[:].y[...], ctype=None) self.assertIs(type(m.y1), IndexedComponent) self.assertIs(m.y1.ctype, IndexedComponent) m.z = Reference(m.b[:].z) self.assertIs(type(m.z), IndexedComponent) self.assertIs(m.z.ctype, IndexedComponent)
def test_stats3(self): model = ConcreteModel() model.x = Var([1,2]) def obj_rule(model, i): return sum_product(model.x) model.obj = Objective([1,2], rule=obj_rule) def c_rule(model, i): expr = 0 for j in [1,2]: expr += j*model.x[j] return expr == 0 model.c = Constraint([1,2], rule=c_rule) # model.B = Block() model.B.x = Var([1,2]) model.B.o = ObjectiveList() model.B.o.add(model.B.x[1]) model.B.o.add(model.B.x[2]) model.B.c = ConstraintList() model.B.c.add(model.x[1] == 0) model.B.c.add(model.x[2] == 0) self.assertEqual(model.nvariables(), 4) self.assertEqual(model.nobjectives(), 4) self.assertEqual(model.nconstraints(), 4)
def extensive_recycle_model(self): def build_in_out(b): b.flow_in = Var(m.comps) b.mass_in = Var() b.temperature_in = Var() b.pressure_in = Var() b.expr_var_idx_in = Var(m.comps) @b.Expression(m.comps) def expr_idx_in(b, i): return -b.expr_var_idx_in[i] b.expr_var_in = Var() b.expr_in = -b.expr_var_in b.flow_out = Var(m.comps) b.mass_out = Var() b.temperature_out = Var() b.pressure_out = Var() b.expr_var_idx_out = Var(m.comps) @b.Expression(m.comps) def expr_idx_out(b, i): return -b.expr_var_idx_out[i] b.expr_var_out = Var() b.expr_out = -b.expr_var_out b.inlet = Port(rule=inlet) b.outlet = Port(rule=outlet) b.initialize = MethodType(initialize, b) def inlet(b): return dict(flow=(b.flow_in, Port.Extensive), mass=(b.mass_in, Port.Extensive), temperature=b.temperature_in, pressure=b.pressure_in, expr_idx=(b.expr_idx_in, Port.Extensive), expr=(b.expr_in, Port.Extensive)) def outlet(b): return dict(flow=(b.flow_out, Port.Extensive), mass=(b.mass_out, Port.Extensive), temperature=b.temperature_out, pressure=b.pressure_out, expr_idx=(b.expr_idx_out, Port.Extensive), expr=(b.expr_out, Port.Extensive)) def initialize(self): for i in self.flow_out: self.flow_out[i].value = value(self.flow_in[i]) self.mass_out.value = value(self.mass_in) for i in self.expr_var_idx_out: self.expr_var_idx_out[i].value = value(self.expr_var_idx_in[i]) self.expr_var_out.value = value(self.expr_var_in) self.temperature_out.value = value(self.temperature_in) self.pressure_out.value = value(self.pressure_in) def nop(self): pass m = ConcreteModel() m.comps = Set(initialize=["A", "B", "C"]) # Feed m.feed = Block() m.feed.flow_out = Var(m.comps) m.feed.mass_out = Var() m.feed.temperature_out = Var() m.feed.pressure_out = Var() m.feed.expr_var_idx_out = Var(m.comps) @m.feed.Expression(m.comps) def expr_idx_out(b, i): return -b.expr_var_idx_out[i] m.feed.expr_var_out = Var() m.feed.expr_out = -m.feed.expr_var_out m.feed.outlet = Port(rule=outlet) m.feed.initialize = MethodType(nop, m.feed) # Mixer m.mixer = Block() build_in_out(m.mixer) # Pass through m.unit = Block() build_in_out(m.unit) # Splitter m.splitter = Block() build_in_out(m.splitter) # Prod m.prod = Block() m.prod.flow_in = Var(m.comps) m.prod.mass_in = Var() m.prod.temperature_in = Var() m.prod.pressure_in = Var() m.prod.actual_var_idx_in = Var(m.comps) m.prod.actual_var_in = Var() @m.prod.Port() def inlet(b): return dict(flow=(b.flow_in, Port.Extensive), mass=(b.mass_in, Port.Extensive), temperature=b.temperature_in, pressure=b.pressure_in, expr_idx=(b.actual_var_idx_in, Port.Extensive), expr=(b.actual_var_in, Port.Extensive)) m.prod.initialize = MethodType(nop, m.prod) # Arcs @m.Arc(directed=True) def stream_feed_to_mixer(m): return (m.feed.outlet, m.mixer.inlet) @m.Arc(directed=True) def stream_mixer_to_unit(m): return (m.mixer.outlet, m.unit.inlet) @m.Arc(directed=True) def stream_unit_to_splitter(m): return (m.unit.outlet, m.splitter.inlet) @m.Arc(directed=True) def stream_splitter_to_mixer(m): return (m.splitter.outlet, m.mixer.inlet) @m.Arc(directed=True) def stream_splitter_to_prod(m): return (m.splitter.outlet, m.prod.inlet) # Split Fraction rec = 0.1 prod = 1 - rec m.splitter.outlet.set_split_fraction(m.stream_splitter_to_mixer, rec) m.splitter.outlet.set_split_fraction(m.stream_splitter_to_prod, prod) # Expand Arcs TransformationFactory("network.expand_arcs").apply_to(m) # Fix Feed m.feed.flow_out['A'].fix(100) m.feed.flow_out['B'].fix(200) m.feed.flow_out['C'].fix(300) m.feed.mass_out.fix(400) m.feed.expr_var_idx_out['A'].fix(10) m.feed.expr_var_idx_out['B'].fix(20) m.feed.expr_var_idx_out['C'].fix(30) m.feed.expr_var_out.fix(40) m.feed.temperature_out.fix(450) m.feed.pressure_out.fix(128) return m
def test_power_law_equil_no_order(): m = ConcreteModel() # # Add a test thermo package for validation m.pparams = PhysicalParameterTestBlock() # Add a solid phase for testing m.pparams.sol = SolidPhase() m.thermo = m.pparams.build_state_block([1]) # Create a dummy reaction parameter block m.rparams = GenericReactionParameterBlock( default={ "property_package": m.pparams, "base_units": { "time": pyunits.s, "mass": pyunits.kg, "amount": pyunits.mol, "length": pyunits.m, "temperature": pyunits.K }, "equilibrium_reactions": { "r1": { "stoichiometry": { ("p1", "c1"): -1, ("p1", "c2"): 2, ("sol", "c1"): -3, ("sol", "c2"): 4 }, "equilibrium_form": power_law_equil, "concentration_form": ConcentrationForm.moleFraction } } }) # Create a dummy state block m.rxn = Block([1]) add_object_reference(m.rxn[1], "phase_component_set", m.pparams._phase_component_set) add_object_reference(m.rxn[1], "params", m.rparams) add_object_reference(m.rxn[1], "state_ref", m.thermo[1]) m.rxn[1].k_eq = Var(["r1"], initialize=1) power_law_equil.build_parameters( m.rparams.reaction_r1, m.rparams.config.equilibrium_reactions["r1"]) # Check parameter construction assert isinstance(m.rparams.reaction_r1.reaction_order, Var) assert len(m.rparams.reaction_r1.reaction_order) == 6 assert m.rparams.reaction_r1.reaction_order["p1", "c1"].value == -1 assert m.rparams.reaction_r1.reaction_order["p1", "c2"].value == 2 assert m.rparams.reaction_r1.reaction_order["p2", "c1"].value == 0 assert m.rparams.reaction_r1.reaction_order["p2", "c2"].value == 0 # Solids should have zero order, as they are excluded assert m.rparams.reaction_r1.reaction_order["sol", "c1"].value == 0 assert m.rparams.reaction_r1.reaction_order["sol", "c2"].value == 0 # Check reaction form rform = power_law_equil.return_expression(m.rxn[1], m.rparams.reaction_r1, "r1", 300) assert str(rform) == str(m.rxn[1].k_eq["r1"] == ( m.thermo[1].mole_frac_phase_comp[ "p1", "c1"]**m.rparams.reaction_r1.reaction_order["p1", "c1"] * m.thermo[1].mole_frac_phase_comp[ "p1", "c2"]**m.rparams.reaction_r1.reaction_order["p1", "c2"]))
def test_power_law_rate_with_order(): m = ConcreteModel() # # Add a test thermo package for validation m.pparams = PhysicalParameterTestBlock() m.thermo = m.pparams.build_state_block([1]) m.rparams = GenericReactionParameterBlock( default={ "property_package": m.pparams, "base_units": { "time": pyunits.s, "mass": pyunits.kg, "amount": pyunits.mol, "length": pyunits.m, "temperature": pyunits.K }, "rate_reactions": { "r1": { "stoichiometry": { ("p1", "c1"): -1, ("p1", "c2"): 2 }, "rate_form": power_law_rate, "concentration_form": ConcentrationForm.moleFraction, "parameter_data": { "reaction_order": { ("p1", "c1"): 1, ("p1", "c2"): 2, ("p2", "c1"): 3, ("p2", "c2"): 4 } } } } }) # Create a dummy state block m.rxn = Block([1]) add_object_reference(m.rxn[1], "phase_component_set", m.pparams._phase_component_set) add_object_reference(m.rxn[1], "params", m.rparams) add_object_reference(m.rxn[1], "state_ref", m.thermo[1]) m.rxn[1].k_rxn = Var(["r1"], initialize=1) power_law_rate.build_parameters(m.rparams.reaction_r1, m.rparams.config.rate_reactions["r1"]) # Check parameter construction assert isinstance(m.rparams.reaction_r1.reaction_order, Var) assert len(m.rparams.reaction_r1.reaction_order) == 4 assert m.rparams.reaction_r1.reaction_order["p1", "c1"].value == 1 assert m.rparams.reaction_r1.reaction_order["p1", "c2"].value == 2 assert m.rparams.reaction_r1.reaction_order["p2", "c1"].value == 3 assert m.rparams.reaction_r1.reaction_order["p2", "c2"].value == 4 # Check reaction form rform = power_law_rate.return_expression(m.rxn[1], m.rparams.reaction_r1, "r1", 300) assert str(rform) == str( m.rxn[1].k_rxn["r1"] * (m.thermo[1].mole_frac_phase_comp["p1", "c1"]** m.rparams.reaction_r1.reaction_order["p1", "c1"] * m.thermo[1].mole_frac_phase_comp["p1", "c2"]** m.rparams.reaction_r1.reaction_order["p1", "c2"] * m.thermo[1].mole_frac_phase_comp["p2", "c1"]** m.rparams.reaction_r1.reaction_order["p2", "c1"] * m.thermo[1].mole_frac_phase_comp["p2", "c2"]** m.rparams.reaction_r1.reaction_order["p2", "c2"]))
def construct(self, data=None): Block.construct(self, data)
class Foo(Block().__class__): def __init__(self, *args, **kwds): kwds.setdefault('ctype', Foo) super(Foo, self).__init__(*args, **kwds)
def build_multiperiod_design(m, flowsheet, initialization=None, unfix_dof=None, flowsheet_options={}, initialization_options={}, unfix_dof_options={}, solver=None, verbose=True, stochastic=False, multiyear=False, multiple_days=False, **kwargs): """ This function constructs multiperiod optimization model """ # Create timer object timer = TicTocTimer() timer.tic("Processing input information.") if stochastic: # If True, set_scenarios must either be passed as an argument, # or it should defined as an attribute of the model if "set_scenarios" in kwargs: set_scenarios = kwargs["set_scenarios"] elif hasattr(m, "set_scenarios"): set_scenarios = m.set_scenarios else: raise Exception(f"stochastic option is set to True, but set_scenarios has " f"not been defined. Either pass set_scenarios as an argument " f"or define it as an attribute of the model.") if multiyear: # If True, set_years must either be passed as an argument, # or it should defined as an attribute of the model if "set_years" in kwargs: set_years = kwargs["set_years"] elif hasattr(m, "set_years"): set_years = m.set_years else: raise Exception(f"multiyear option is set to True, but set_years has " f"not been defined. Either pass set_years as an argument " f"or define it as an attribute of the model.") if multiple_days: # If True, set_days must either be passed as an argument, # or it should defined as an attribute of the model if "set_days" in kwargs: set_days = kwargs["set_days"] elif hasattr(m, "set_days"): set_days = m.set_days else: raise Exception(f"multiple_days option is set to True, but set_days has " f"not been defined. Either pass set_days as an argument " f"or define it as an attribute of the model.") # Set of time periods if "set_time" in kwargs: set_time = kwargs["set_time"] elif hasattr(m, "set_time"): set_time = m.set_time else: raise Exception(f"set_time is a required option. Either pass set_time as " f"an argument or define it as an attribute of the model.") # Set solver object if solver is None: solver = get_solver() # Construct the set of time periods if multiyear and multiple_days: set_period = [(t, d, y) for y in set_years for d in set_days for t in set_time] elif multiple_days: set_period = [(t, d) for d in set_days for t in set_time] else: set_period = [t for t in set_time] """ Period rule """ timer.toc("Beginning the formulation of the multiperiod problem.") def _period_model_rule(options, verbose_flag): def _period_model(blk): if verbose_flag: print("Constructing flowsheet model for ", blk.name) flowsheet(blk, options=options) return _period_model def _build_scenario_model(blk): blk.period = Block(set_period, rule=_period_model_rule(flowsheet_options, verbose)) return blk # Construct the multiperiod model if stochastic: m.scenario = Block(set_scenarios, rule=_build_scenario_model) else: _build_scenario_model(m) timer.toc("Completed the formulation of the multiperiod problem") """ Initialization routine """ if initialization is None: print("*** WARNING *** Initialization function is not provided. " "Returning the multiperiod model without initialization.") return b = ConcreteModel() flowsheet(b, options=flowsheet_options) initialization(b, options=initialization_options) result = solver.solve(b) try: assert check_optimal_termination(result) except AssertionError: print(f"Flowsheet did not converge to optimality " f"after fixing the degrees of freedom.") raise # Save the solution in json file to_json(b, fname="temp_initialized_model.json") timer.toc("Created an instance of the flowsheet and initialized it.") # Initialize the multiperiod optimization model if stochastic: for s in set_scenarios: for p in set_period: from_json(m.scenario[s].period[p], fname="temp_initialized_model.json") else: for p in set_period: from_json(m.period[p], fname="temp_initialized_model.json") timer.toc("Initialized the entire multiperiod optimization model.") """ Unfix the degrees of freedom in each period model for optimization model """ if unfix_dof is None: print("*** WARNING *** unfix_dof function is not provided. " "Returning the model without unfixing degrees of freedom") return if stochastic: for s in set_scenarios: for p in set_period: unfix_dof(m.scenario[s].period[p], options=unfix_dof_options) else: for p in set_period: unfix_dof(m.period[p], options=unfix_dof_options) timer.toc("Unfixed the degrees of freedom from each period model.")
def test_propagate_state(): m = ConcreteModel() def block_rule(b): b.s = Set(initialize=[1, 2]) b.v1 = Var() b.v2 = Var(b.s) b.e1 = Expression(expr=b.v1) @b.Expression(b.s) def e2(blk, i): return b.v2[i] * b.v1 b.p1 = Param(mutable=True, initialize=5) b.p2 = Param(b.s, mutable=True, initialize=6) b.port1 = Port() b.port1.add(b.v1, "V1") b.port1.add(b.v2, "V2") b.port2 = Port() b.port2.add(b.v1, "V1") b.port2.add(b.e2, "V2") b.port3 = Port() b.port3.add(b.e1, "V1") b.port3.add(b.v2, "V2") b.port4 = Port() b.port4.add(b.p1, "V1") b.port4.add(b.v2, "V2") b.port5 = Port() b.port5.add(b.v1, "V1") b.port5.add(b.p2, "V2") b.port6 = Port() b.port6.add(b.v1, "V1") b.port6.add(b.v1, "V2") return m.b1 = Block(rule=block_rule) m.b2 = Block(rule=block_rule) m.s1 = Arc(source=m.b1.port1, destination=m.b2.port1) m.s2 = Arc(source=m.b1.port1, destination=m.b2.port2) m.s3 = Arc(source=m.b1.port1, destination=m.b2.port3) m.s4 = Arc(source=m.b1.port1, destination=m.b2.port4) m.s5 = Arc(source=m.b1.port1, destination=m.b2.port5) m.s6 = Arc(source=m.b1.port2, destination=m.b2.port1) m.s7 = Arc(source=m.b1.port3, destination=m.b2.port1) m.s8 = Arc(source=m.b1.port4, destination=m.b2.port1) m.s9 = Arc(source=m.b1.port5, destination=m.b2.port1) m.s10 = Arc(source=m.b1.port6, destination=m.b2.port1) m.s11 = Arc(source=m.b2.port6, destination=m.b1.port1) # Set values on first block m.b1.v1.value = 10 m.b1.v2[1].value = 20 m.b1.v2[2].value = 30 # Make sure vars in block 2 haven't been changed accidentally assert m.b2.v1.value is None assert m.b2.v2[1].value is None assert m.b2.v2[2].value is None propagate_state(m.s1) # Check that values were propagated correctly assert m.b2.v1.value == m.b1.v1.value assert m.b2.v2[1].value == m.b1.v2[1].value assert m.b2.v2[2].value == m.b1.v2[2].value assert m.b1.v1.fixed is False assert m.b1.v2[1].fixed is False assert m.b1.v2[2].fixed is False assert m.b2.v1.fixed is False assert m.b2.v2[1].fixed is False assert m.b2.v2[2].fixed is False with pytest.raises(TypeError): propagate_state(m.s2) with pytest.raises(TypeError): propagate_state(m.s3) with pytest.raises(TypeError): propagate_state(m.s4) with pytest.raises(TypeError): propagate_state(m.s5) propagate_state(m.s6) assert value(m.b1.v1) == value(m.b2.v1) assert value(m.b1.e2[1]) == value(m.b2.v2[1]) assert value(m.b1.e2[2]) == value(m.b2.v2[2]) propagate_state(m.s7) assert value(m.b1.e1) == value(m.b2.v1) assert value(m.b1.v2[1]) == value(m.b2.v2[1]) assert value(m.b1.v2[2]) == value(m.b2.v2[2]) propagate_state(m.s8) assert value(m.b1.p1) == value(m.b2.v1) assert value(m.b1.v2[1]) == value(m.b2.v2[1]) assert value(m.b1.v2[2]) == value(m.b2.v2[2]) propagate_state(m.s9) assert value(m.b1.v1) == value(m.b2.v1) assert value(m.b1.p2[1]) == value(m.b2.v2[1]) assert value(m.b1.p2[2]) == value(m.b2.v2[2]) with pytest.raises(KeyError): propagate_state(m.s10) with pytest.raises(KeyError): propagate_state(m.s11)
def get_costing(self, module=costing): if not hasattr(self.flowsheet(), 'costing'): self.flowsheet().get_costing() self.costing = Block() module.hx_costing(self.costing)
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 test_inactive_target(self): m = ConcreteModel() m.b = Block() m.b.deactivate() TransformationFactory('gdp.fix_disjuncts').apply_to(m.b)
def initialize(self, state_args_feed=None, state_args_liq=None, state_args_vap=None, solver=None, optarg=None, outlvl=idaeslog.NOTSET): init_log = idaeslog.getInitLogger(self.name, outlvl, tag="unit") solve_log = idaeslog.getSolveLogger(self.name, outlvl, tag="unit") init_log.info("Begin initialization.") solverobj = get_solver(solver, optarg) feed_flags = self.feed_tray.initialize(solver=solver, optarg=optarg, outlvl=outlvl) self.propagate_stream_state(source=self.feed_tray.vap_out, destination=self.condenser.inlet) self.condenser.initialize(solver=solver, optarg=optarg, outlvl=outlvl) self.propagate_stream_state(source=self.feed_tray.liq_out, destination=self.reboiler.inlet) self.reboiler.initialize(solver=solver, optarg=optarg, outlvl=outlvl) # initialize the rectification section for i in self._rectification_index: self.propagate_stream_state( source=self.condenser.reflux, destination=self.rectification_section[i].liq_in) self.propagate_stream_state( source=self.feed_tray.vap_out, destination=self.rectification_section[i].vap_in) if i == 1: rect_liq_flags = self.rectification_section[i]. \ initialize(hold_state_liq=True, hold_state_vap=False, solver=solver, optarg=optarg, outlvl=outlvl) elif i == len(self._rectification_index): rect_vap_flags = \ self.rectification_section[i]. \ initialize(hold_state_liq=False, hold_state_vap=True, solver=solver, optarg=optarg, outlvl=outlvl) else: self.rectification_section[i].initialize(solver=solver, optarg=optarg, outlvl=outlvl) # initialize the stripping section for i in self._stripping_index: self.propagate_stream_state( source=self.feed_tray.liq_out, destination=self.stripping_section[i].liq_in) self.propagate_stream_state( source=self.reboiler.vapor_reboil, destination=self.stripping_section[i].vap_in) if i == self.config.feed_tray_location + 1: strip_liq_flags = self.stripping_section[i]. \ initialize(hold_state_liq=True, hold_state_vap=False, solver=solver, optarg=optarg, outlvl=outlvl) elif i == self.config.number_of_trays: strip_vap_flags = self.stripping_section[i]. \ initialize(hold_state_liq=False, hold_state_vap=True, solver=solver, optarg=optarg, outlvl=outlvl) else: self.stripping_section[i].initialize(solver=None, optarg=optarg, outlvl=outlvl) # For initialization purposes and to enable solving individual sections # creating a temp block. Note that this temp block is a reference to # the rectification, stripping, and feed sections. Also, expanded arcs # are added to the temp block as the initialization solve proceeds. self._temp_block = Block() self._temp_block.rectification = Block() # adding reference to the rectification section and the expanded # vapor and liquid arcs self._temp_block.rectification.trays = Reference( self.rectification_section) self._temp_block.rectification.expanded_liq_stream = Reference( self.rectification_liq_stream[:].expanded_block) self._temp_block.rectification.expanded_vap_stream = Reference( self.rectification_vap_stream[:].expanded_block) with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: res = solverobj.solve(self._temp_block.rectification, tee=slc.tee) init_log.info("Rectification section initialization status {}.".format( idaeslog.condition(res))) self._temp_block.stripping = Block() # adding reference to the stripping section and the expanded # vapor and liquid arcs self._temp_block.stripping.trays = Reference(self.stripping_section) self._temp_block.stripping.expanded_liq_stream = Reference( self.stripping_liq_stream[:].expanded_block) self._temp_block.stripping.expanded_vap_stream = Reference( self.stripping_vap_stream[:].expanded_block) with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: res = solverobj.solve(self._temp_block.stripping, tee=slc.tee) init_log.info("Stripping section initialization status {}.".format( idaeslog.condition(res))) # releasing the fixed inlets for the vap in to the rectification # to enable connection with the feed tray vap out self.rectification_section[len(self._rectification_index)]. \ properties_in_vap. \ release_state(flags=rect_vap_flags, outlvl=outlvl) # releasing the fixed inlets for the liq in to the stripping # to enable connection with the feed tray liq out self.stripping_section[self.config.feed_tray_location + 1]. \ properties_in_liq. \ release_state(flags=strip_liq_flags, outlvl=outlvl) # Adding the feed tray to temp block solve self._temp_block.feed_tray = Reference(self.feed_tray) self._temp_block.expanded_feed_liq_stream_in = Reference( self.feed_liq_in.expanded_block) self._temp_block.expanded_feed_liq_stream_out = Reference( self.feed_liq_out.expanded_block) self._temp_block.expanded_feed_vap_stream_in = Reference( self.feed_vap_in.expanded_block) self._temp_block.expanded_feed_vap_stream_out = Reference( self.feed_vap_out.expanded_block) with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: res = solverobj.solve(self._temp_block, tee=slc.tee) init_log.info("Column section initialization status {}.".format( idaeslog.condition(res))) self.rectification_section[1]. \ properties_in_liq. \ release_state(flags=rect_liq_flags, outlvl=outlvl) # Adding the condenser to the temp block solve self._temp_block.condenser = Reference(self.condenser) self._temp_block.expanded_condenser_vap_in = Reference( self.condenser_vap_in.expanded_block) self._temp_block.expanded_condenser_reflux_out = Reference( self.condenser_reflux_out.expanded_block) with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: res = solverobj.solve(self._temp_block, tee=slc.tee) init_log.info( "Column section + Condenser initialization status {}.".format( idaeslog.condition(res))) self.stripping_section[self.config.number_of_trays]. \ properties_in_vap. \ release_state(flags=strip_vap_flags, outlvl=outlvl) # Delete the _temp_block as next solve is solving the entire column. # If we add the reboiler to the temp block, it will be similar to # solving the original block. This ensures that if # initialize is triggered twice, there is no implicit replacing # component error. self.del_component(self._temp_block) with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: res = solverobj.solve(self, tee=slc.tee) init_log.info( "Column section + Condenser + Reboiler initialization status {}.". format(idaeslog.condition(res))) # release feed tray state once initialization is complete self.feed_tray.properties_in_feed.\ release_state(flags=feed_flags, outlvl=outlvl)
def b_rule(b, c): b.bb = Block(m.time, rule=bb_rule)
def build(m, section='desalination', pretrt_type='NF', **kwargs): if section == 'desalination': m.fs.desal_saturation = Block() m.fs.desal_saturation.properties = m.fs.prop_eNRTL.build_state_block([0], default={}) sb_eNRTL = m.fs.desal_saturation.properties[0] elif section == 'pretreatment': m.fs.pretrt_saturation = Block() m.fs.pretrt_saturation.properties = m.fs.prop_eNRTL.build_state_block([0], default={}) sb_eNRTL = m.fs.pretrt_saturation.properties[0] else: raise ValueError('{section} is not an expected section for building the saturation index' ''.format(section=section)) # populate initial values populate_eNRTL_state_vars(sb_eNRTL, base='FpcTP') # ksp = 3.9e-9 # Gibbs energy gives 3.9e-8, but this fits expectations better ksp = 3.2e-9 # This fits expectations even better # constraints if section == 'desalination': sb_dilute = m.fs.tb_pretrt_to_desal.properties_in[0] if kwargs['is_twostage']: sb_perm = m.fs.mixer_permeate.mixed_state[0] sb_conc = m.fs.RO2.feed_side.properties[0, 1] sb_conc_inter = m.fs.RO2.feed_side.properties_interface[0, 1] else: sb_perm = m.fs.RO.mixed_permeate[0] sb_conc = m.fs.RO.feed_side.properties[0, 1] sb_conc_inter = m.fs.RO.feed_side.properties_interface[0, 1] m.fs.desal_saturation.cp_modulus = Expression( expr=sb_conc_inter.conc_mass_phase_comp['Liq', 'TDS'] / sb_conc.conc_mass_phase_comp['Liq', 'TDS']) # constraints m.fs.desal_saturation.eq_temperature = Constraint( expr=sb_eNRTL.temperature == sb_conc.temperature) m.fs.desal_saturation.eq_pressure = Constraint( expr=sb_eNRTL.pressure == sb_conc.pressure) if pretrt_type == 'NF': # assumes pretreatment uses the ion property basis comp_match_dict = {'Na_+': 'Na', 'Ca_2+': 'Ca', 'Mg_2+': 'Mg', 'SO4_2-': 'SO4', 'Cl_-': 'Cl', 'H2O': 'H2O'} @m.fs.desal_saturation.Constraint(comp_match_dict.keys()) def eq_flow_mol_balance(b, j): if j in ['Cl_-', 'Na_+']: bulk_flow = (sb_dilute.flow_mol_phase_comp['Liq', comp_match_dict[j]] - sb_perm.flow_mass_phase_comp['Liq', 'TDS'] / (58.44e-3 * pyunits.kg / pyunits.mol)) return (sb_eNRTL.flow_mol_phase_comp['Liq', j] == bulk_flow * m.fs.desal_saturation.cp_modulus) elif j in ['Ca_2+', 'Mg_2+', 'SO4_2-']: return (sb_eNRTL.flow_mol_phase_comp['Liq', j] == sb_dilute.flow_mol_phase_comp['Liq', comp_match_dict[j]] * m.fs.desal_saturation.cp_modulus) elif j == 'H2O': return (sb_eNRTL.flow_mol_phase_comp['Liq', j] == sb_conc.flow_mol_phase_comp['Liq', 'H2O']) elif pretrt_type == 'softening': # assumes pretreatment uses the softening property basis comp_match_dict = {'Na_+': 'NaCl', 'Ca_2+': 'Ca(HCO3)2', 'Mg_2+': 'Mg(HCO3)2', 'SO4_2-': 'SO4_2-', 'Cl_-': 'Cl_-', 'H2O': 'H2O'} @m.fs.desal_saturation.Constraint(comp_match_dict.keys()) def eq_flow_mol_balance(b, j): if j == 'Na_+': bulk_flow = (sb_dilute.flow_mol_phase_comp['Liq', 'NaCl'] - sb_perm.flow_mass_phase_comp['Liq', 'TDS'] / (58.44e-3 * pyunits.kg / pyunits.mol)) return (sb_eNRTL.flow_mol_phase_comp['Liq', j] == bulk_flow * m.fs.desal_saturation.cp_modulus) if j in 'Cl_-': bulk_flow = (sb_dilute.flow_mol_phase_comp['Liq', 'Cl_-'] + sb_dilute.flow_mol_phase_comp['Liq', 'NaCl'] - sb_perm.flow_mass_phase_comp['Liq', 'TDS'] / (58.44e-3 * pyunits.kg / pyunits.mol)) return (sb_eNRTL.flow_mol_phase_comp['Liq', j] == bulk_flow * m.fs.desal_saturation.cp_modulus) elif j in ['Ca_2+', 'Mg_2+', 'SO4_2-']: return (sb_eNRTL.flow_mol_phase_comp['Liq', j] == sb_dilute.flow_mol_phase_comp['Liq', comp_match_dict[j]] * m.fs.desal_saturation.cp_modulus) elif j == 'H2O': return (sb_eNRTL.flow_mol_phase_comp['Liq', j] == sb_conc.flow_mol_phase_comp['Liq', 'H2O']) m.fs.desal_saturation.saturation_index = Var( initialize=0.5, bounds=(1e-8, 10), units=pyunits.dimensionless, doc="Gypsum saturation index") m.fs.desal_saturation.eq_saturation_index = Constraint( expr=m.fs.desal_saturation.saturation_index == sb_eNRTL.act_phase_comp["Liq", "Ca_2+"] * sb_eNRTL.act_phase_comp["Liq", "SO4_2-"] * sb_eNRTL.act_phase_comp["Liq", "H2O"] ** 2 / ksp) elif section == 'pretreatment': comp_match_dict = {'Na_+': 'Na', 'Ca_2+': 'Ca', 'Mg_2+': 'Mg', 'SO4_2-': 'SO4', 'Cl_-': 'Cl', 'H2O': 'H2O'} sb_conc = m.fs.NF.feed_side.properties_out[0] m.fs.pretrt_saturation.eq_temperature = Constraint( expr=sb_eNRTL.temperature == sb_conc.temperature) m.fs.pretrt_saturation.eq_pressure = Constraint( expr=sb_eNRTL.pressure == sb_conc.pressure) @m.fs.pretrt_saturation.Constraint(comp_match_dict.keys()) def eq_flow_mol_balance(b, j): return (sb_eNRTL.flow_mol_phase_comp['Liq', j] == sb_conc.flow_mol_phase_comp['Liq', comp_match_dict[j]]) m.fs.pretrt_saturation.saturation_index = Var( initialize=0.5, bounds=(1e-8, 1e6), units=pyunits.dimensionless, doc="Gypsum saturation index") m.fs.pretrt_saturation.eq_saturation_index = Constraint( expr=m.fs.pretrt_saturation.saturation_index == sb_eNRTL.act_phase_comp["Liq", "Ca_2+"] * sb_eNRTL.act_phase_comp["Liq", "SO4_2-"] * sb_eNRTL.act_phase_comp["Liq", "H2O"] ** 2 / ksp)
def test_indexed_target(self): m = ConcreteModel() m.s = RangeSet(2) m.b = Block(m.s) m.b[1].bb = Block() TransformationFactory('gdp.fix_disjuncts').apply_to(m.b)
def simple_recycle_model(self): m = ConcreteModel() m.comps = Set(initialize=["A", "B", "C"]) # Feed m.feed = Block() m.feed.flow_out = Var(m.comps) m.feed.temperature_out = Var() m.feed.pressure_out = Var() m.feed.expr_var_idx_out = Var(m.comps) @m.feed.Expression(m.comps) def expr_idx_out(b, i): return -b.expr_var_idx_out[i] m.feed.expr_var_out = Var() m.feed.expr_out = -m.feed.expr_var_out @m.feed.Port() def outlet(b): return dict(flow=b.flow_out, temperature=b.temperature_out, pressure=b.pressure_out, expr_idx=b.expr_idx_out, expr=b.expr_out) def initialize_feed(self): pass m.feed.initialize = MethodType(initialize_feed, m.feed) # Mixer m.mixer = Block() m.mixer.flow_in_side_1 = Var(m.comps) m.mixer.temperature_in_side_1 = Var() m.mixer.pressure_in_side_1 = Var() m.mixer.expr_var_idx_in_side_1 = Var(m.comps) @m.mixer.Expression(m.comps) def expr_idx_in_side_1(b, i): return -b.expr_var_idx_in_side_1[i] m.mixer.expr_var_in_side_1 = Var() m.mixer.expr_in_side_1 = -m.mixer.expr_var_in_side_1 m.mixer.flow_in_side_2 = Var(m.comps) m.mixer.temperature_in_side_2 = Var() m.mixer.pressure_in_side_2 = Var() m.mixer.expr_var_idx_in_side_2 = Var(m.comps) @m.mixer.Expression(m.comps) def expr_idx_in_side_2(b, i): return -b.expr_var_idx_in_side_2[i] m.mixer.expr_var_in_side_2 = Var() m.mixer.expr_in_side_2 = -m.mixer.expr_var_in_side_2 m.mixer.flow_out = Var(m.comps) m.mixer.temperature_out = Var() m.mixer.pressure_out = Var() m.mixer.expr_var_idx_out = Var(m.comps) @m.mixer.Expression(m.comps) def expr_idx_out(b, i): return -b.expr_var_idx_out[i] m.mixer.expr_var_out = Var() m.mixer.expr_out = -m.mixer.expr_var_out @m.mixer.Port() def inlet_side_1(b): return dict(flow=b.flow_in_side_1, temperature=b.temperature_in_side_1, pressure=b.pressure_in_side_1, expr_idx=b.expr_idx_in_side_1, expr=b.expr_in_side_1) @m.mixer.Port() def inlet_side_2(b): return dict(flow=b.flow_in_side_2, temperature=b.temperature_in_side_2, pressure=b.pressure_in_side_2, expr_idx=b.expr_idx_in_side_2, expr=b.expr_in_side_2) @m.mixer.Port() def outlet(b): return dict(flow=b.flow_out, temperature=b.temperature_out, pressure=b.pressure_out, expr_idx=b.expr_idx_out, expr=b.expr_out) def initialize_mixer(self): for i in self.flow_out: self.flow_out[i].value = \ value(self.flow_in_side_1[i] + self.flow_in_side_2[i]) for i in self.expr_var_idx_out: self.expr_var_idx_out[i].value = \ value(self.expr_var_idx_in_side_1[i] + self.expr_var_idx_in_side_2[i]) self.expr_var_out.value = \ value(self.expr_var_in_side_1 + self.expr_var_in_side_2) assert self.temperature_in_side_1 == self.temperature_in_side_2 self.temperature_out.value = value(self.temperature_in_side_1) assert self.pressure_in_side_1 == self.pressure_in_side_2 self.pressure_out.value = value(self.pressure_in_side_1) m.mixer.initialize = MethodType(initialize_mixer, m.mixer) # Pass through m.unit = Block() m.unit.flow_in = Var(m.comps) m.unit.temperature_in = Var() m.unit.pressure_in = Var() m.unit.expr_var_idx_in = Var(m.comps) @m.unit.Expression(m.comps) def expr_idx_in(b, i): return -b.expr_var_idx_in[i] m.unit.expr_var_in = Var() m.unit.expr_in = -m.unit.expr_var_in m.unit.flow_out = Var(m.comps) m.unit.temperature_out = Var() m.unit.pressure_out = Var() m.unit.expr_var_idx_out = Var(m.comps) @m.unit.Expression(m.comps) def expr_idx_out(b, i): return -b.expr_var_idx_out[i] m.unit.expr_var_out = Var() m.unit.expr_out = -m.unit.expr_var_out @m.unit.Port() def inlet(b): return dict(flow=b.flow_in, temperature=b.temperature_in, pressure=b.pressure_in, expr_idx=b.expr_idx_in, expr=b.expr_in) @m.unit.Port() def outlet(b): return dict(flow=b.flow_out, temperature=b.temperature_out, pressure=b.pressure_out, expr_idx=b.expr_idx_out, expr=b.expr_out) def initialize_unit(self): for i in self.flow_out: self.flow_out[i].value = value(self.flow_in[i]) for i in self.expr_var_idx_out: self.expr_var_idx_out[i].value = value(self.expr_var_idx_in[i]) self.expr_var_out.value = value(self.expr_var_in) self.temperature_out.value = value(self.temperature_in) self.pressure_out.value = value(self.pressure_in) m.unit.initialize = MethodType(initialize_unit, m.unit) # Splitter m.splitter = Block() @m.splitter.Block(m.comps) def flow_in(b, i): b.flow = Var() m.splitter.temperature_in = Var() m.splitter.pressure_in = Var() m.splitter.expr_var_idx_in = Var(m.comps) @m.splitter.Expression(m.comps) def expr_idx_in(b, i): return -b.expr_var_idx_in[i] m.splitter.expr_var_in = Var() m.splitter.expr_in = -m.splitter.expr_var_in m.splitter.flow_out_side_1 = Var(m.comps) m.splitter.temperature_out_side_1 = Var() m.splitter.pressure_out_side_1 = Var() m.splitter.expr_var_idx_out_side_1 = Var(m.comps) @m.splitter.Expression(m.comps) def expr_idx_out_side_1(b, i): return -b.expr_var_idx_out_side_1[i] m.splitter.expr_var_out_side_1 = Var() m.splitter.expr_out_side_1 = -m.splitter.expr_var_out_side_1 m.splitter.flow_out_side_2 = Var(m.comps) m.splitter.temperature_out_side_2 = Var() m.splitter.pressure_out_side_2 = Var() m.splitter.expr_var_idx_out_side_2 = Var(m.comps) @m.splitter.Expression(m.comps) def expr_idx_out_side_2(b, i): return -b.expr_var_idx_out_side_2[i] m.splitter.expr_var_out_side_2 = Var() m.splitter.expr_out_side_2 = -m.splitter.expr_var_out_side_2 @m.splitter.Port() def inlet(b): return dict(flow=Reference(b.flow_in[:].flow), temperature=b.temperature_in, pressure=b.pressure_in, expr_idx=b.expr_idx_in, expr=b.expr_in) @m.splitter.Port() def outlet_side_1(b): return dict(flow=b.flow_out_side_1, temperature=b.temperature_out_side_1, pressure=b.pressure_out_side_1, expr_idx=b.expr_idx_out_side_1, expr=b.expr_out_side_1) @m.splitter.Port() def outlet_side_2(b): return dict(flow=b.flow_out_side_2, temperature=b.temperature_out_side_2, pressure=b.pressure_out_side_2, expr_idx=b.expr_idx_out_side_2, expr=b.expr_out_side_2) def initialize_splitter(self): recycle = 0.1 prod = 1 - recycle for i in self.flow_in: self.flow_out_side_1[i].value \ = prod * value(self.flow_in[i].flow) self.flow_out_side_2[i].value \ = recycle * value(self.flow_in[i].flow) for i in self.expr_var_idx_in: self.expr_var_idx_out_side_1[i].value = \ prod * value(self.expr_var_idx_in[i]) self.expr_var_idx_out_side_2[i].value = \ recycle * value(self.expr_var_idx_in[i]) self.expr_var_out_side_1.value = prod * value(self.expr_var_in) self.expr_var_out_side_2.value = recycle * value(self.expr_var_in) self.temperature_out_side_1.value = value(self.temperature_in) self.temperature_out_side_2.value = value(self.temperature_in) self.pressure_out_side_1.value = value(self.pressure_in) self.pressure_out_side_2.value = value(self.pressure_in) m.splitter.initialize = MethodType(initialize_splitter, m.splitter) # Prod m.prod = Block() m.prod.flow_in = Var(m.comps) m.prod.temperature_in = Var() m.prod.pressure_in = Var() m.prod.actual_var_idx_in = Var(m.comps) m.prod.actual_var_in = Var() @m.prod.Port() def inlet(b): return dict(flow=b.flow_in, temperature=b.temperature_in, pressure=b.pressure_in, expr_idx=b.actual_var_idx_in, expr=b.actual_var_in) def initialize_prod(self): pass m.prod.initialize = MethodType(initialize_prod, m.prod) # Arcs @m.Arc(directed=True) def stream_feed_to_mixer(m): return (m.feed.outlet, m.mixer.inlet_side_1) @m.Arc(directed=True) def stream_mixer_to_unit(m): return (m.mixer.outlet, m.unit.inlet) @m.Arc(directed=True) def stream_unit_to_splitter(m): return (m.unit.outlet, m.splitter.inlet) @m.Arc(directed=True) def stream_splitter_to_mixer(m): return (m.splitter.outlet_side_2, m.mixer.inlet_side_2) @m.Arc(directed=True) def stream_splitter_to_prod(m): return (m.splitter.outlet_side_1, m.prod.inlet) # Expand Arcs TransformationFactory("network.expand_arcs").apply_to(m) # Fix Feed m.feed.flow_out['A'].fix(100) m.feed.flow_out['B'].fix(200) m.feed.flow_out['C'].fix(300) m.feed.expr_var_idx_out['A'].fix(10) m.feed.expr_var_idx_out['B'].fix(20) m.feed.expr_var_idx_out['C'].fix(30) m.feed.expr_var_out.fix(40) m.feed.temperature_out.fix(450) m.feed.pressure_out.fix(128) return m
def test_trans_block_name_collision(self): m = self.makeModel() m._core_add_slack_variables = Block() TransformationFactory('core.add_slack_variables').apply_to(m) xblock = m.component("_core_add_slack_variables_4") self.assertIsInstance(xblock, Block)
def build(self): ''' Callable method for Block construction. ''' # Call super.build() to initialize Block # In this case we are replicating the super.build to get around a # chicken-and-egg problem # The super.build tries to validate units, but they have not been set # and cannot be set until the config block is created by super.build super(ReactionParameterBlock, self).build() # Validate and set base units of measurement self.get_metadata().add_default_units(self.config.base_units) units_meta = self.get_metadata().default_units for key, unit in self.config.base_units.items(): if key in [ 'time', 'length', 'mass', 'amount', 'temperature', "current", "luminous intensity" ]: if not isinstance(unit, _PyomoUnit): raise ConfigurationError( "{} recieved unexpected units for quantity {}: {}. " "Units must be instances of a Pyomo unit object.". format(self.name, key, unit)) else: raise ConfigurationError( "{} defined units for an unexpected quantity {}. " "Generic reaction packages only support units for the 7 " "base SI quantities.".format(self.name, key)) # Check that main 5 base units are assigned for k in ['time', 'length', 'mass', 'amount', 'temperature']: if not isinstance(units_meta[k], _PyomoUnit): raise ConfigurationError( "{} units for quantity {} were not assigned. " "Please make sure to provide units for all base units " "when configuring the reaction package.".format( self.name, k)) # TODO: Need way to tie reaction package to a specfic property package self._validate_property_parameter_units() self._validate_property_parameter_properties() # Call configure method to set construction arguments self.configure() # Build core components self._reaction_block_class = GenericReactionBlock # Alias associated property package to keep line length down ppack = self.config.property_package # Construct rate reaction attributes if required if len(self.config.rate_reactions) > 0: # Construct rate reaction index self.rate_reaction_idx = Set( initialize=self.config.rate_reactions.keys()) # Construct rate reaction stoichiometry dict self.rate_reaction_stoichiometry = {} for r, rxn in self.config.rate_reactions.items(): for p, j in ppack._phase_component_set: self.rate_reaction_stoichiometry[(r, p, j)] = 0 if rxn.stoichiometry is None: raise ConfigurationError( "{} rate reaction {} was not provided with a " "stoichiometry configuration argument.".format( self.name, r)) else: for k, v in rxn.stoichiometry.items(): if k[0] not in ppack.phase_list: raise ConfigurationError( "{} stoichiometry for rate reaction {} " "included unrecognised phase {}.".format( self.name, r, k[0])) if k[1] not in ppack.component_list: raise ConfigurationError( "{} stoichiometry for rate reaction {} " "included unrecognised component {}.".format( self.name, r, k[1])) self.rate_reaction_stoichiometry[(r, k[0], k[1])] = v # Check that a method was provided for the rate form if rxn.rate_form is None: raise ConfigurationError( "{} rate reaction {} was not provided with a " "rate_form configuration argument.".format( self.name, r)) # Construct equilibrium reaction attributes if required if len(self.config.equilibrium_reactions) > 0: # Construct rate reaction index self.equilibrium_reaction_idx = Set( initialize=self.config.equilibrium_reactions.keys()) # Construct equilibrium reaction stoichiometry dict self.equilibrium_reaction_stoichiometry = {} for r, rxn in self.config.equilibrium_reactions.items(): for p, j in ppack._phase_component_set: self.equilibrium_reaction_stoichiometry[(r, p, j)] = 0 if rxn.stoichiometry is None: raise ConfigurationError( "{} equilibrium reaction {} was not provided with a " "stoichiometry configuration argument.".format( self.name, r)) else: for k, v in rxn.stoichiometry.items(): if k[0] not in ppack.phase_list: raise ConfigurationError( "{} stoichiometry for equilibrium reaction {} " "included unrecognised phase {}.".format( self.name, r, k[0])) if k[1] not in ppack.component_list: raise ConfigurationError( "{} stoichiometry for equilibrium reaction {} " "included unrecognised component {}.".format( self.name, r, k[1])) self.equilibrium_reaction_stoichiometry[(r, k[0], k[1])] = v # Check that a method was provided for the equilibrium form if rxn.equilibrium_form is None: raise ConfigurationError( "{} equilibrium reaction {} was not provided with a " "equilibrium_form configuration argument.".format( self.name, r)) # Add a master reaction index which includes both types of reactions if (len(self.config.rate_reactions) > 0 and len(self.config.equilibrium_reactions) > 0): self.reaction_idx = Set( initialize=(self.rate_reaction_idx | self.equilibrium_reaction_idx)) elif len(self.config.rate_reactions) > 0: self.reaction_idx = Set(initialize=self.rate_reaction_idx) elif len(self.config.equilibrium_reactions) > 0: self.reaction_idx = Set(initialize=self.equilibrium_reaction_idx) else: raise BurntToast("{} Generic property package failed to construct " "master reaction Set. This should not happen. " "Please contact the IDAES developers with this " "bug".format(self.name)) # Construct blocks to contain parameters for each reaction for r in self.reaction_idx: self.add_component("reaction_" + str(r), Block()) # Build parameters if len(self.config.rate_reactions) > 0: for r in self.rate_reaction_idx: rblock = getattr(self, "reaction_" + r) r_config = self.config.rate_reactions[r] order_init = {} for p, j in ppack._phase_component_set: if "reaction_order" in r_config.parameter_data: try: order_init[p, j] = r_config.parameter_data[ "reaction_order"][p, j] except KeyError: order_init[p, j] = 0 else: # Assume elementary reaction and use stoichiometry try: if r_config.stoichiometry[p, j] < 0: # These are reactants, but order is -ve stoic order_init[p, j] = -r_config.stoichiometry[p, j] else: # Anything else is a product, not be included order_init[p, j] = 0 except KeyError: order_init[p, j] = 0 rblock.reaction_order = Var(ppack._phase_component_set, initialize=order_init, doc="Reaction order", units=None) for val in self.config.rate_reactions[r].values(): try: val.build_parameters(rblock, self.config.rate_reactions[r]) except AttributeError: pass if len(self.config.equilibrium_reactions) > 0: for r in self.equilibrium_reaction_idx: rblock = getattr(self, "reaction_" + r) r_config = self.config.equilibrium_reactions[r] order_init = {} for p, j in ppack._phase_component_set: if "reaction_order" in r_config.parameter_data: try: order_init[p, j] = r_config.parameter_data[ "reaction_order"][p, j] except KeyError: order_init[p, j] = 0 else: # Assume elementary reaction and use stoichiometry try: # Here we use the stoic. coeff. directly # However, solids should be excluded as they # normally do not appear in the equilibrium # relationship pobj = ppack.get_phase(p) if not pobj.is_solid_phase(): order_init[p, j] = r_config.stoichiometry[p, j] else: order_init[p, j] = 0 except KeyError: order_init[p, j] = 0 rblock.reaction_order = Var(ppack._phase_component_set, initialize=order_init, doc="Reaction order", units=None) for val in self.config.equilibrium_reactions[r].values(): try: val.build_parameters( rblock, self.config.equilibrium_reactions[r]) except AttributeError: pass # As a safety check, make sure all Vars in reaction blocks are fixed for v in self.component_objects(Var, descend_into=True): for i in v: if v[i].value is None: raise ConfigurationError( "{} parameter {} was not assigned" " a value. Please check your configuration " "arguments.".format(self.name, v.local_name)) v[i].fix()
def build(self): super().build() if self.config.property_package_feed is None: raise ConfigurationError( "Users must provide a feed property package to the evaporator unit model" ) if self.config.property_package_vapor is None: raise ConfigurationError( "Users must provide a vapor property package to the evaporator unit model" ) # this creates blank scaling factors, which are populated later self.scaling_factor = Suffix(direction=Suffix.EXPORT) # Next, get the base units of measurement from the property definition units_meta_feed = ( self.config.property_package_feed.get_metadata().get_derived_units) # Add shared unit model variables self.U = Var( initialize=1e3, bounds=(10, 1e4), units=pyunits.J * pyunits.s**-1 * pyunits.m**-2 * pyunits.K**-1, ) self.area = Var(initialize=1e2, bounds=(1e-1, 1e4), units=pyunits.m**2) self.delta_temperature_in = Var(initialize=1e1, bounds=(1e-8, 1e3), units=pyunits.K) self.delta_temperature_out = Var(initialize=1e1, bounds=(1e-8, 1e3), units=pyunits.K) self.lmtd = Var(initialize=1e1, bounds=(1e-8, 1e3), units=pyunits.K) # Add feed_side block self.feed_side = Block() # Add unit variables to feed self.feed_side.heat_transfer = Var(initialize=1e4, bounds=(1, 1e10), units=pyunits.J * pyunits.s**-1) # Add feed_side state blocks # Feed state block tmp_dict = dict(**self.config.property_package_args_feed) tmp_dict["has_phase_equilibrium"] = False tmp_dict["parameters"] = self.config.property_package_feed tmp_dict["defined_state"] = True # feed inlet defined self.feed_side.properties_feed = ( self.config.property_package_feed.state_block_class( self.flowsheet().config.time, doc="Material properties of feed inlet", default=tmp_dict, )) # Brine state block tmp_dict["defined_state"] = False # brine outlet not yet defined self.feed_side.properties_brine = ( self.config.property_package_feed.state_block_class( self.flowsheet().config.time, doc="Material properties of brine outlet", default=tmp_dict, )) # Vapor state block tmp_dict = dict(**self.config.property_package_args_vapor) tmp_dict["has_phase_equilibrium"] = False tmp_dict["parameters"] = self.config.property_package_vapor tmp_dict["defined_state"] = False # vapor outlet not yet defined self.feed_side.properties_vapor = ( self.config.property_package_vapor.state_block_class( self.flowsheet().config.time, doc="Material properties of vapor outlet", default=tmp_dict, )) # Add condenser self.condenser = Condenser( default={"property_package": self.config.property_package_vapor}) # Add ports - oftentimes users interact with these rather than the state blocks self.add_port(name="inlet_feed", block=self.feed_side.properties_feed) self.add_port(name="outlet_brine", block=self.feed_side.properties_brine) self.add_port(name="outlet_vapor", block=self.feed_side.properties_vapor) self.add_port(name="inlet_condenser", block=self.condenser.control_volume.properties_in) self.add_port(name="outlet_condenser", block=self.condenser.control_volume.properties_out) ### FEED SIDE CONSTRAINTS ### # Mass balance @self.feed_side.Constraint( self.flowsheet().time, self.config.property_package_feed.component_list, doc="Mass balance", ) def eq_mass_balance(b, t, j): lb = b.properties_vapor[t].flow_mass_phase_comp["Liq", "H2O"].lb b.properties_vapor[t].flow_mass_phase_comp["Liq", "H2O"].fix(lb) if j == "H2O": return ( b.properties_feed[t].flow_mass_phase_comp["Liq", "H2O"] == b.properties_brine[t].flow_mass_phase_comp["Liq", "H2O"] + b.properties_vapor[t].flow_mass_phase_comp["Vap", "H2O"]) else: return (b.properties_feed[t].flow_mass_phase_comp["Liq", j] == b.properties_brine[t].flow_mass_phase_comp["Liq", j]) # Energy balance @self.feed_side.Constraint(self.flowsheet().time, doc="Energy balance") def eq_energy_balance(b, t): return (b.heat_transfer + b.properties_feed[t].enth_flow == b.properties_brine[t].enth_flow + b.properties_vapor[t].enth_flow_phase["Vap"]) # Brine pressure @self.feed_side.Constraint(self.flowsheet().time, doc="Brine pressure") def eq_brine_pressure(b, t): return b.properties_brine[t].pressure == b.properties_brine[ t].pressure_sat # Vapor pressure @self.feed_side.Constraint(self.flowsheet().time, doc="Vapor pressure") def eq_vapor_pressure(b, t): return b.properties_vapor[t].pressure == b.properties_brine[ t].pressure # Vapor temperature @self.feed_side.Constraint(self.flowsheet().time, doc="Vapor temperature") def eq_vapor_temperature(b, t): return (b.properties_vapor[t].temperature == b.properties_brine[t].temperature) # return b.properties_vapor[t].temperature == 0.5*(b.properties_out[t].temperature + b.properties_in[t].temperature) ### EVAPORATOR CONSTRAINTS ### # Temperature difference in @self.Constraint(self.flowsheet().time, doc="Temperature difference in") def eq_delta_temperature_in(b, t): return (b.delta_temperature_in == b.condenser.control_volume.properties_in[t].temperature - b.feed_side.properties_brine[t].temperature) # Temperature difference out @self.Constraint(self.flowsheet().time, doc="Temperature difference out") def eq_delta_temperature_out(b, t): return (b.delta_temperature_out == b.condenser.control_volume.properties_out[t].temperature - b.feed_side.properties_brine[t].temperature) # log mean temperature @self.Constraint(self.flowsheet().time, doc="Log mean temperature difference") def eq_lmtd(b, t): dT_in = b.delta_temperature_in dT_out = b.delta_temperature_out temp_units = pyunits.get_units(dT_in) dT_avg = (dT_in + dT_out) / 2 # external function that ruturns the real root, for the cuberoot of negitive # numbers, so it will return without error for positive and negitive dT. b.cbrt = ExternalFunction(library=functions_lib(), function="cbrt", arg_units=[temp_units**3]) return b.lmtd == b.cbrt((dT_in * dT_out * dT_avg)) * temp_units # Heat transfer between feed side and condenser @self.Constraint(self.flowsheet().time, doc="Heat transfer balance") def eq_heat_balance(b, t): return b.feed_side.heat_transfer == -b.condenser.control_volume.heat[ t] # Evaporator heat transfer @self.Constraint(self.flowsheet().time, doc="Evaporator heat transfer") def eq_evaporator_heat(b, t): return b.feed_side.heat_transfer == b.U * b.area * b.lmtd
def get_costing(self, module=costing, year=None, **kwargs): if not hasattr(self.flowsheet(), "costing"): self.flowsheet().get_costing(year=year) self.costing = Block() module.hx_costing(self.costing, **kwargs)
def build(self): ''' Callable method for Block construction. ''' # Call super.build() to initialize Block # In this case we are replicating the super.build to get around a # chicken-and-egg problem # The super.build tries to validate units, but they have not been set # and cannot be set until the config block is created by super.build super(ReactionParameterBlock, self).build() self.default_scaling_factor = {} # Set base units of measurement self.get_metadata().add_default_units(self.config.base_units) # TODO: Need way to tie reaction package to a specfic property package self._validate_property_parameter_units() self._validate_property_parameter_properties() # Call configure method to set construction arguments self.configure() # Build core components self._reaction_block_class = GenericReactionBlock # Alias associated property package to keep line length down ppack = self.config.property_package if not hasattr(ppack, "_electrolyte") or not ppack._electrolyte: pc_set = ppack._phase_component_set elif ppack.config.state_components.name == "true": pc_set = ppack.true_phase_component_set elif ppack.config.state_components.name == "apparent": pc_set = ppack.apparent_phase_component_set else: raise BurntToast() # Construct rate reaction attributes if required if len(self.config.rate_reactions) > 0: # Construct rate reaction index self.rate_reaction_idx = Set( initialize=self.config.rate_reactions.keys()) # Construct rate reaction stoichiometry dict self.rate_reaction_stoichiometry = {} for r, rxn in self.config.rate_reactions.items(): for p, j in pc_set: self.rate_reaction_stoichiometry[(r, p, j)] = 0 if rxn.stoichiometry is None: raise ConfigurationError( "{} rate reaction {} was not provided with a " "stoichiometry configuration argument.".format( self.name, r)) else: for k, v in rxn.stoichiometry.items(): if k[0] not in ppack.phase_list: raise ConfigurationError( "{} stoichiometry for rate reaction {} " "included unrecognised phase {}.".format( self.name, r, k[0])) if k[1] not in ppack.component_list: raise ConfigurationError( "{} stoichiometry for rate reaction {} " "included unrecognised component {}.".format( self.name, r, k[1])) self.rate_reaction_stoichiometry[(r, k[0], k[1])] = v # Check that a method was provided for the rate form if rxn.rate_form is None: _log.debug( "{} rate reaction {} was not provided with a " "rate_form configuration argument. This is suitable " "for processes using stoichiometric reactors, but not " "for those using unit operations which rely on " "reaction rate.".format(self.name, r)) # Construct equilibrium reaction attributes if required if len(self.config.equilibrium_reactions) > 0: # Construct equilibrium reaction index self.equilibrium_reaction_idx = Set( initialize=self.config.equilibrium_reactions.keys()) # Construct equilibrium reaction stoichiometry dict self.equilibrium_reaction_stoichiometry = {} for r, rxn in self.config.equilibrium_reactions.items(): for p, j in pc_set: self.equilibrium_reaction_stoichiometry[(r, p, j)] = 0 if rxn.stoichiometry is None: raise ConfigurationError( "{} equilibrium reaction {} was not provided with a " "stoichiometry configuration argument.".format( self.name, r)) else: for k, v in rxn.stoichiometry.items(): if k[0] not in ppack.phase_list: raise ConfigurationError( "{} stoichiometry for equilibrium reaction {} " "included unrecognised phase {}.".format( self.name, r, k[0])) if k[1] not in ppack.component_list: raise ConfigurationError( "{} stoichiometry for equilibrium reaction {} " "included unrecognised component {}.".format( self.name, r, k[1])) self.equilibrium_reaction_stoichiometry[(r, k[0], k[1])] = v # Check that a method was provided for the equilibrium form if rxn.equilibrium_form is None: raise ConfigurationError( "{} equilibrium reaction {} was not provided with a " "equilibrium_form configuration argument.".format( self.name, r)) # Add a master reaction index which includes both types of reactions if (len(self.config.rate_reactions) > 0 and len(self.config.equilibrium_reactions) > 0): self.reaction_idx = Set( initialize=(self.rate_reaction_idx | self.equilibrium_reaction_idx)) elif len(self.config.rate_reactions) > 0: self.reaction_idx = Set(initialize=self.rate_reaction_idx) elif len(self.config.equilibrium_reactions) > 0: self.reaction_idx = Set(initialize=self.equilibrium_reaction_idx) else: raise BurntToast("{} Generic property package failed to construct " "master reaction Set. This should not happen. " "Please contact the IDAES developers with this " "bug".format(self.name)) # Construct blocks to contain parameters for each reaction for r in self.reaction_idx: self.add_component("reaction_" + str(r), Block()) # Build parameters if len(self.config.rate_reactions) > 0: for r in self.rate_reaction_idx: rblock = getattr(self, "reaction_" + r) r_config = self.config.rate_reactions[r] order_init = {} for p, j in pc_set: if "reaction_order" in r_config.parameter_data: try: order_init[p, j] = r_config.parameter_data[ "reaction_order"][p, j] except KeyError: order_init[p, j] = 0 else: # Assume elementary reaction and use stoichiometry try: if r_config.stoichiometry[p, j] < 0: # These are reactants, but order is -ve stoic order_init[p, j] = -r_config.stoichiometry[p, j] else: # Anything else is a product, not be included order_init[p, j] = 0 except KeyError: order_init[p, j] = 0 rblock.reaction_order = Var(pc_set, initialize=order_init, doc="Reaction order", units=None) for val in self.config.rate_reactions[r].values(): try: val.build_parameters(rblock, self.config.rate_reactions[r]) except AttributeError: pass if len(self.config.equilibrium_reactions) > 0: for r in self.equilibrium_reaction_idx: rblock = getattr(self, "reaction_" + r) r_config = self.config.equilibrium_reactions[r] order_init = {} for p, j in pc_set: if "reaction_order" in r_config.parameter_data: try: order_init[p, j] = r_config.parameter_data[ "reaction_order"][p, j] except KeyError: order_init[p, j] = 0 else: # Assume elementary reaction and use stoichiometry try: # Here we use the stoic. coeff. directly # However, solids should be excluded as they # normally do not appear in the equilibrium # relationship pobj = ppack.get_phase(p) if not pobj.is_solid_phase(): order_init[p, j] = r_config.stoichiometry[p, j] else: order_init[p, j] = 0 except KeyError: order_init[p, j] = 0 rblock.reaction_order = Var(pc_set, initialize=order_init, doc="Reaction order", units=None) for val in self.config.equilibrium_reactions[r].values(): try: val.build_parameters( rblock, self.config.equilibrium_reactions[r]) except AttributeError: pass except KeyError as err: # This likely arises from mismatched true and apparent # species sets. Reaction packages must use the same # basis as the associated thermo properties # Raise an exception to inform the user raise PropertyPackageError( "{} KeyError encountered whilst constructing " "reaction parameters. This may be due to " "mismatched state_components between the " "Reaction Package and the associated Physical " "Property Package - Reaction Packages must use the" "same basis (true or apparent species) as the " "Physical Property Package.".format(self.name), err) # As a safety check, make sure all Vars in reaction blocks are fixed for v in self.component_objects(Var, descend_into=True): for i in v: if v[i].value is None: raise ConfigurationError( "{} parameter {} was not assigned" " a value. Please check your configuration " "arguments.".format(self.name, v.local_name)) v[i].fix() # Set default scaling factors if self.config.default_scaling_factors is not None: self.default_scaling_factor.update( self.config.default_scaling_factors) # Finally, call populate_default_scaling_factors method to fill blanks iscale.populate_default_scaling_factors(self)
def _reformulate(self, c, param, uncset, counterpart, root=False): """ Reformulate an uncertain constraint or objective c: Constraint or Objective param: UncParam uncset: UncSet counterpart: Block """ # Check constraint/objective repn = self.generate_repn_param(c) assert repn.is_linear(), ( "Constraint {} should be linear in " "unc. parameters".format(c.name)) # Generate robust counterpart det = quicksum(x[0]*x[1].nominal for x in zip(repn.linear_coefs, repn.linear_vars)) det += repn.constant param_var_dict = {id(param): var for param, var in zip(repn.linear_vars, repn.linear_coefs)} # padding = sqrt( var^T * cov^-1 * var ) padding = quicksum(param_var_dict[id(param[ind_i])] * uncset.cov[i][j] * param_var_dict[id(param[ind_j])] for i, ind_i in enumerate(param) for j, ind_j in enumerate(param)) if c.ctype is Constraint: # For upper bound: det + padding <= b if c.has_ub(): counterpart.upper = Block() if root: expr = det + sqrt(padding) <= c.upper robust = Constraint(expr=expr) else: counterpart.upper.padding = Var(bounds=(0, float('inf'))) pvar = counterpart.upper.padding robust = Constraint(expr=det + pvar <= c.upper()) deterministic = Constraint(expr=padding <= pvar**2) counterpart.upper.det = deterministic counterpart.upper.rob = robust # For lower bound: det - padding >= b if c.has_lb(): counterpart.lower = Block() if root: expr = det - sqrt(padding) >= c.lower robust = Constraint(expr=expr) else: counterpart.lower.padding = Var(bounds=(0, float('inf'))) pvar = counterpart.lower.padding robust = Constraint(expr=c.lower() <= det - pvar) deterministic = Constraint(expr=padding <= pvar**2) counterpart.lower.det = deterministic counterpart.lower.rob = robust else: # For minimization: min det + padding # For maximization: max det - padding sense = c.sense if root: expr = det + c.sense*sqrt(padding) robust = Objective(expr=expr, sense=sense) else: counterpart.padding = Var(bounds=(0, float('inf'))) pvar = counterpart.padding robust = Objective(expr=det + sense*pvar, sense=sense) deterministic = Constraint(expr=padding <= pvar**2) counterpart.det = deterministic counterpart.rob = robust