def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) def eta_val(m, value): return 0 < value <= 1 def noneornonnegativereal(m, value): return (value is None) or value >= 0 self.eta = Param(default=1, validate=eta_val, mutable=True, doc='efficiency of the converter (within (0,1))') self.pmax = Param(default=None, validate=noneornonnegativereal, mutable=True) self.p_in = Var(self.time, within=NonNegativeReals) self.p_out = Var(self.time, within=NonNegativeReals) @self.Constraint(self.time) def _pmax(m, t): if m.pmax.value is None: return Constraint.Skip return m.p_out[t] <= m.pmax @self.Constraint(self.time) def efficiency(m, t): return m.p_out[t] == m.eta * m.p_in[t] self.inlet = Port(initialize={'f': (self.p_in, Port.Conservative)}) self.outlet = Port(initialize={'f': (self.p_out, Port.Conservative)})
def add_ports(self, name, member_dict, doc=None): """ This is a method to build Port objects in the SkeletonUnitModel and populate them with appropriate port members as specified. User can add as many inlet and outlet ports as required. Keyword Args: name : name to use for Port object. dict : dictionary containing variables to be added to the port doc : doc string for Port object Returns: A Pyomo Port object and associated components. """ # Validate that member_dict is a dict if not isinstance(member_dict, dict): raise ConfigurationError( "member_dict should be a dictionary " "with the keys being the name assigned(strings) and " "values being the variable objects declared in the model.") # Create empty Port p = Port(noruleinit=True, doc=doc) # Add port object to model setattr(self, name, p) # Populate port and map names to actual variables as defined for k in member_dict.keys(): p.add(member_dict[k], name=k)
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 build(self): """ """ super().build() time = self.flowsheet().config.time self.create_outlets() self.electricity = Var(time, domain=NonNegativeReals, initialize=0.0, doc="Electricity into control volume", units=pyunits.kW) self.electricity_in = Port(noruleinit=True, doc="A port for electricity flow") self.electricity_in.add(self.electricity, "electricity") self.split_fraction = Var(self.outlet_list, time, bounds=(0, 1), initialize=1.0 / len(self.outlet_list), doc="Split fractions for outlet streams") @self.Constraint(time, doc="Split constraint") def sum_split(b, t): return 1 == sum(b.split_fraction[o, t] for o in b.outlet_list) @self.Constraint(time, self.outlet_list, doc="Electricity constraint") def electricity_eqn(b, t, o): outlet_obj = getattr(b, o + "_elec") return outlet_obj[t] == b.split_fraction[o, t] * b.electricity[t]
def test_port_copy(): m = ConcreteModel() m.b1 = Block() m.b2 = Block() m.b1.x = Var(initialize=3) m.b1.y = Var([0, 1], initialize={0: 4, 1: 5}) m.b1.z = Var([0, 1], ["A", "B"], initialize={ (0, "A"): 6, (0, "B"): 7, (1, "A"): 8, (1, "B"): 9 }) m.b2.x = Var(initialize=1) m.b2.y = Var([0, 1], initialize=1) m.b2.z = Var([0, 1], ["A", "B"], initialize=1) m.b1.port = Port() m.b2.port = Port() m.b1.port.add(m.b1.x, "x") m.b1.port.add(m.b1.y, "y") m.b1.port.add(m.b1.z, "z") m.b2.port.add(m.b2.x, "x") m.b2.port.add(m.b2.y, "y") m.b2.port.add(m.b2.z, "z") copy_port_values(m.b2.port, m.b1.port) assert (m.b2.x == 3) assert (m.b2.y[0] == 4) assert (m.b2.y[1] == 5) assert (m.b2.z[0, "A"] == 6) assert (m.b2.z[0, "B"] == 7) assert (m.b2.z[1, "A"] == 8) assert (m.b2.z[1, "B"] == 9)
def _add_ports(self): """Method to construct the ports for the tray.""" # Add feed inlet port if self.config.is_feed_tray: self.add_inlet_port(name="feed", block=self.properties_in_feed) # Add liquid and vapor inlet ports self.add_inlet_port(name="liq_in", block=self.properties_in_liq) self.add_inlet_port(name="vap_in", block=self.properties_in_vap) # Add liquid outlet port self.liq_out = Port(noruleinit=True, doc="liquid outlet from tray") # Add liquid side draw port if selected if self.config.has_liquid_side_draw: self.liq_side_sf = Var( initialize=0.01, doc="split fraction for the liquid side draw") self.liq_side_draw = Port(noruleinit=True, doc="liquid side draw.") self._make_phase_split( port=self.liq_side_draw, phase=self._liquid_set, has_liquid_side_draw=self.config.has_liquid_side_draw, side_sf=self.liq_side_sf) # Populate the liquid outlet port with the remaining liquid # after the side draw self._make_phase_split(port=self.liq_out, phase=self._liquid_set, side_sf=1 - self.liq_side_sf) else: # Populate the liquid outlet port when no liquid side draw self._make_phase_split(port=self.liq_out, phase=self._liquid_set, side_sf=1) # Add the vapor outlet port self.vap_out = Port(noruleinit=True, doc="vapor outlet from tray") # Add vapor side draw port if selected if self.config.has_vapor_side_draw: self.vap_side_sf = Var( initialize=0.01, doc="split fraction for the vapor side draw") self.vap_side_draw = Port(noruleinit=True, doc="vapor side draw.") self._make_phase_split( port=self.vap_side_draw, phase=self._vapor_set, has_vapor_side_draw=self.config.has_vapor_side_draw, side_sf=self.vap_side_sf) # Populate the vapor outlet port with the remaining vapor # after the vapor side draw self._make_phase_split(port=self.vap_out, phase=self._vapor_set, side_sf=1 - self.vap_side_sf) else: # Populate the vapor outlet port when no vapor side draw self._make_phase_split(port=self.vap_out, phase=self._vapor_set, side_sf=1)
def test_extends(self): m = ConcreteModel() m.x = Var() m.p1 = Port() m.p1.add(m.x, rule=Port.Extensive) m.p2 = Port(extends=m.p1) self.assertIs(m.p2.x, m.x) self.assertIs(m.p2.rule_for('x'), Port.Extensive) self.assertTrue(m.p2.is_extensive('x')) self.assertFalse(m.p2.is_equality('x'))
def _make_ports(self): # Add Ports for the reboiler # Inlet port (the vapor from the top tray) self.add_inlet_port() # Outlet ports that always exist irrespective of reboiler type self.bottoms = Port(noruleinit=True, doc="Bottoms stream.") self.vapor_reboil = Port(noruleinit=True, doc="Vapor outlet stream that is returned to " "to the bottom tray.")
class PEMElectrolyzerData(UnitModelBlockData): """ Simple 0D proton-exchange membrane electrolyzer model. Unit model to convert electricity and water into H2 gas. """ CONFIG = ConfigBlock() _make_pem_electrolyzer_config_block(CONFIG) def build(self): """Building model Args: None Returns: None """ # Call UnitModel.build to setup dynamics super(PEMElectrolyzerData, self).build() self.electricity_to_mol = Var(self.flowsheet().config.time, domain=Reals, initialize=0.0, doc="Efficiency", units=pyunits.mol/pyunits.kW/pyunits.second) self.electricity = Var(self.flowsheet().config.time, domain=Reals, initialize=0.0, doc="Electricity into control volume", units=pyunits.kW) self.electricity_in = Port(noruleinit=True, doc="A port for electricity flow") self.electricity_in.add(self.electricity, "electricity") self.outlet_state = self.config.property_package.build_state_block(self.flowsheet().config.time, default=self.config.property_package_args) self.add_outlet_port(name="outlet", block=self.outlet_state, doc="H2 out of electrolyzer") self.outlet.temperature.fix(300) self.outlet.pressure.fix(101325) @self.Constraint(self.flowsheet().config.time) def efficiency_curve(b, t): return pyunits.convert(b.outlet.flow_mol[t], to_units=pyunits.mol / pyunits.s) == b.electricity[t] * \ b.electricity_to_mol[t] def _get_performance_contents(self, time_point=0): return {"vars": {"Efficiency": self.electricity_to_mol[time_point]}} def initialize(self, **kwargs): self.outlet_state.initialize(hold_state=False)
def test_arc_lists(self): m = ConcreteModel() m.x = Var() m.p1 = Port() m.p2 = Port() m.p3 = Port() m.p4 = Port() m.p5 = Port() m.p1.add(m.x) m.p2.add(m.x) m.p3.add(m.x) m.p4.add(m.x) m.p5.add(m.x) m.a1 = Arc(source=m.p1, destination=m.p2) m.a2 = Arc(source=m.p1, destination=m.p3) m.a3 = Arc(source=m.p4, destination=m.p1) m.a4 = Arc(source=m.p5, destination=m.p1) self.assertEqual(len(m.p1.dests()), 2) self.assertEqual(len(m.p1.sources()), 2) self.assertEqual(len(m.p1.arcs()), 4) self.assertEqual(len(m.p2.dests()), 0) self.assertEqual(len(m.p2.sources()), 1) self.assertEqual(len(m.p2.arcs()), 1) self.assertIn(m.a1, m.p1.dests()) self.assertIn(m.a1, m.p2.sources()) self.assertNotIn(m.a1, m.p1.sources()) self.assertNotIn(m.a1, m.p2.dests()) self.assertEqual(len(m.p1.dests(active=True)), 2) self.assertEqual(len(m.p1.sources(active=True)), 2) self.assertEqual(len(m.p1.arcs(active=True)), 4) self.assertEqual(len(m.p2.dests(active=True)), 0) self.assertEqual(len(m.p2.sources(active=True)), 1) self.assertEqual(len(m.p2.arcs(active=True)), 1) self.assertIn(m.a1, m.p1.dests(active=True)) self.assertIn(m.a1, m.p2.sources(active=True)) self.assertNotIn(m.a1, m.p1.sources(active=True)) self.assertNotIn(m.a1, m.p2.dests(active=True)) m.a2.deactivate() self.assertNotIn(m.a2, m.p1.dests(active=True)) self.assertNotIn(m.a2, m.p3.sources(active=True)) self.assertIn(m.a2, m.p1.dests(active=False)) self.assertIn(m.a2, m.p3.sources(active=False)) self.assertIn(m.a2, m.p1.arcs(active=False)) self.assertIn(m.a2, m.p3.arcs(active=False)) self.assertIn(m.a2, m.p1.dests()) self.assertIn(m.a2, m.p3.sources()) self.assertIn(m.a2, m.p1.arcs()) self.assertIn(m.a2, m.p3.arcs())
def test_scale_arcs(): m = pyo.ConcreteModel() m.x = pyo.Var([1, 2, 3, 4]) m.y = pyo.Var([1, 2, 3, 4]) m.p1 = Port() m.p1.add(m.x[1], name="x") m.p1.add(m.y[1], name="y") m.p = Port([2, 3, 4]) m.p[2].add(m.x[2], name="x") m.p[2].add(m.y[2], name="y") m.p[3].add(m.x[3], name="x") m.p[3].add(m.y[3], name="y") m.p[4].add(m.x[4], name="x") m.p[4].add(m.y[4], name="y") def arc_rule(b, i): if i == 1: return (m.p1, m.p[2]) elif i == 2: return (m.p[3], m.p[4]) m.arcs = Arc([1, 2], rule=arc_rule) sc.set_scaling_factor(m.x, 10) sc.set_scaling_factor(m.y, 20) sc.set_scaling_factor(m.x[1], 5) # make sure there is no error if the scaling is done with unexpanded arcs sc.scale_arc_constraints(m) # expand and make sure it works pyo.TransformationFactory('network.expand_arcs').apply_to(m) sc.scale_arc_constraints(m) m.x[1] = 1 m.x[2] = 2 m.x[3] = 3 m.x[4] = 4 m.y[1] = 11 m.y[2] = 12 m.y[3] = 13 m.y[4] = 14 # for all the arc constraints the differnce is 1 the scale factor is the # smallest scale factor for variables in a constraint. Make sure the # constraints are scaled as expected. assert abs(m.arcs_expanded[1].x_equality.body()) == 5 assert abs(m.arcs_expanded[2].x_equality.body()) == 10 assert abs(m.arcs_expanded[1].y_equality.body()) == 20 assert abs(m.arcs_expanded[2].y_equality.body()) == 20
def test_default_indexed_constructor(self): model = ConcreteModel() model.c = Port([1, 2, 3]) self.assertEqual(len(model.c), 3) self.assertEqual(len(model.c[1].vars), 0) model = AbstractModel() model.c = Port([1, 2, 3]) self.assertEqual(len(model.c), 0) self.assertRaises(ValueError, model.c.__getitem__, 1) inst = model.create_instance() self.assertEqual(len(inst.c), 3) self.assertEqual(len(inst.c[1].vars), 0)
def test_gams_arc_in_active_constraint(self): m = ConcreteModel() m.b1 = Block() m.b2 = Block() m.b1.x = Var() m.b2.x = Var() m.b1.c = Port() m.b1.c.add(m.b1.x) m.b2.c = Port() m.b2.c.add(m.b2.x) m.c = Arc(source=m.b1.c, destination=m.b2.c) m.o = Objective(expr=m.b1.x) outs = StringIO() with self.assertRaises(RuntimeError): m.write(outs, format="gams")
def __init__(self, *args, flow_names=('flow_in', 'flow_out'), **kwargs): super().__init__(*args, **kwargs) self.intlet = Port( initialize={ 'f': (self.component(flow_names[0]), Port.Extensive, { 'include_splitfrac': False }) }) self.outlet = Port( initialize={ 'f': (self.component(flow_names[1]), Port.Extensive, { 'include_splitfrac': False }) })
def _create_lifecycle_model(self): self.include_lifecycle_count = True ################################## # Parameters # ################################## self.model.lifecycle_cost = pyomo.Param( doc="Lifecycle cost of " + self.block_set_name + " [$/lifecycle]", default=0.0, within=pyomo.NonNegativeReals, mutable=True, units=u.USD / u.lifecycle) ################################## # Variables # ################################## self.model.lifecycles = pyomo.Var( doc=self.block_set_name + " lifecycle count", domain=pyomo.NonNegativeReals, units=u.lifecycle) ################################## # Constraints # ################################## self.model.lifecycle_count = pyomo.Constraint( doc=self.block_set_name + " lifecycle counting", rule=self._lifecycle_count_rule ) # self._create_lifecycle_count_constraint() ################################## # Ports # ################################## self.model.lifecycles_port = Port() self.model.lifecycles_port.add(self.model.lifecycles) self.model.lifecycles_port.add(self.model.lifecycle_cost)
def test_gams_expanded_arcs(self): m = ConcreteModel() m.x = Var() m.y = Var() m.CON1 = Port() m.CON1.add(m.x, 'v') m.CON2 = Port() m.CON2.add(m.y, 'v') m.c = Arc(source=m.CON1, destination=m.CON2) TransformationFactory("network.expand_arcs").apply_to(m) m.o = Objective(expr=m.x) outs = StringIO() io_options = dict(symbolic_solver_labels=True) m.write(outs, format="gams", io_options=io_options) # no error if we're here, but check for some identifying string self.assertIn("x - y", outs.getvalue())
def _create_storage_port(storage): ################################## # Ports # ################################## storage.port = Port() storage.port.add(storage.charge_power) storage.port.add(storage.discharge_power)
def __init__(self, *args, flow_name='p', scale_fact='scale_fact', **kwds): super().__init__(*args, flow_name=flow_name, **kwds) scaled_flow_name = flow_name+'_scaled' self.add_component(scale_fact, Var(initialize=1, within=PositiveReals, doc='scaling factor within Positve reals')) self.add_component(scaled_flow_name, Var(self.time, doc='Scaled source flow')) def _flow_scaling(m, t): return m.find_component(scaled_flow_name)[t] == m.find_component(scale_fact)*m.find_component(flow_name)[t] def _debug_flow_scaling(m, t): return -0.000001, \ m.find_component(scaled_flow_name)[t] - m.find_component(scale_fact)*m.find_component(flow_name)[t],\ 0.000001 self.flow_scaling = Constraint(self.time, rule=_flow_scaling, doc='Constraint equality for flow scaling') self.debug_flow_scaling = Constraint(self.time, rule=_debug_flow_scaling, doc='Constraint equality for flow scaling') self.outlet = Port(initialize={'f': (self.component(scaled_flow_name), Port.Conservative)})
def test_potentially_variable(self): m = ConcreteModel() m.x = Var() m.p = Port() self.assertTrue(m.p.is_potentially_variable()) m.p.add(-m.x) self.assertTrue(m.p.is_potentially_variable())
def _create_trough_port(self, hybrid, t): hybrid.trough_port = Port( initialize={ 'cycle_generation': hybrid.trough_generation, 'system_load': hybrid.trough_load }) self.ports[t].append(hybrid.trough_port)
def _create_battery_port(self, hybrid, t): hybrid.battery_port = Port( initialize={ 'charge_power': hybrid.battery_charge, 'discharge_power': hybrid.battery_discharge }) self.ports[t].append(hybrid.battery_port)
def add_port(blk, name=None, block=None, doc=None): """ This is a method to build Port objects in a unit model and connect these to a specified StateBlock. Keyword Args: name : name to use for Port object. block : an instance of a StateBlock to use as the source to populate the Port object doc : doc string for Port object Returns: A Pyomo Port object and associated components. """ # Validate block object if not isinstance(block, StateBlock): raise ConfigurationError("{} block object provided to add_port " "method is not an instance of a " "StateBlock object. IDAES port objects " "should only be associated with " "StateBlocks.".format(blk.name)) # Create empty Port p = Port(noruleinit=True, doc=doc) setattr(blk, name, p) p._state_block = (block, ) # Get dict of Port members and names member_list = block[ blk.flowsheet().config.time.first()].define_port_members() # Create References for port members for s in member_list: if not member_list[s].is_indexed(): slicer = block[:].component(member_list[s].local_name) else: slicer = block[:].component(member_list[s].local_name)[...] r = Reference(slicer) setattr(blk, "_" + s + "_" + name + "_ref", r) # Add Reference to Port p.add(r, s) return p
def test_assert_units_consistent_all_components(self): # test all scalar components consistent u = units m = self._create_model_and_vars() m.obj = Objective(expr=m.dx / m.t - m.vx) m.con = Constraint(expr=m.dx / m.t == m.vx) # vars already added m.exp = Expression(expr=m.dx / m.t - m.vx) m.suff = Suffix(direction=Suffix.LOCAL) # params already added # sets already added m.rs = RangeSet(5) m.disj1 = Disjunct() m.disj1.constraint = Constraint(expr=m.dx / m.t <= m.vx) m.disj2 = Disjunct() m.disj2.constraint = Constraint(expr=m.dx / m.t <= m.vx) m.disjn = Disjunction(expr=[m.disj1, m.disj2]) # block tested as part of model m.extfn = ExternalFunction(python_callback_function, units=u.m / u.s, arg_units=[u.m, u.s]) m.conext = Constraint(expr=m.extfn(m.dx, m.t) - m.vx == 0) m.cset = ContinuousSet(bounds=(0, 1)) m.svar = Var(m.cset, units=u.m) m.dvar = DerivativeVar(sVar=m.svar, units=u.m / u.s) def prt1_rule(m): return {'avar': m.dx} def prt2_rule(m): return {'avar': m.dy} m.prt1 = Port(rule=prt1_rule) m.prt2 = Port(rule=prt2_rule) def arcrule(m): return dict(source=m.prt1, destination=m.prt2) m.arc = Arc(rule=arcrule) # complementarities do not work yet # The expression system removes the u.m since it is multiplied by zero. # We need to change the units_container to allow 0 when comparing units # m.compl = Complementarity(expr=complements(m.dx/m.t >= m.vx, m.dx == 0*u.m)) assert_units_consistent(m)
def test_state_block_retrieval_empty_port(): m = ConcreteModel() m.p = Port() with pytest.raises(ValueError, match="No block could be retrieved from Port p because it contains " "no components." ): df = create_stream_table_dataframe({"state": m.p})
def _create_grid_port(self, hybrid, t): hybrid.grid_port = Port( initialize={ 'system_generation': hybrid.system_generation, 'system_load': hybrid.system_load, 'electricity_sold': hybrid.electricity_sold, 'electricity_purchased': hybrid.electricity_purchased }) self.ports[t].append(hybrid.grid_port)
def block_rule(b): b.s = Set(initialize=[1, 2]) b.v1 = Var() b.v2 = Var(b.s) b.p = Port() b.p.add(b.v1, "V1") b.p.add(b.v2, "V2") return
def _create_grid_ports(grid): ################################## # Ports # ################################## grid.port = Port() grid.port.add(grid.system_generation) grid.port.add(grid.system_load) grid.port.add(grid.electricity_sold) grid.port.add(grid.electricity_purchased)
def __init__(self, *args, flow_name='flow', doc_flow='generic flow', **kwargs): """ :param str doc_flow: documentation for inherited units :param str flow_name: name of the flow variable """ super().__init__(*args, **kwargs) self.add_component(flow_name, Var(self.time, initialize=0, within=Reals, doc=doc_flow)) self.outlet = Port(initialize={'f': (self.component(flow_name), Port.Extensive, {'include_splitfrac': False})}, doc='output flow port using source convention. ')
def __init__(self, *args, flow_name='flow', **kwargs): """ :param str flow_name: name of the flow variable """ super().__init__(*args, **kwargs) self.add_component(flow_name, Var(self.time, initialize=0, within=Reals, doc='flow variable')) self.inlet = Port(initialize={'f': (self.component(flow_name), Port.Extensive, {'include_splitfrac': False})}, doc='Input flow inlet, using load convention')
def test_fixed(self): pipe = ConcreteModel() pipe.SPECIES = Set(initialize=['a', 'b', 'c']) pipe.flow = Var() pipe.composition = Var(pipe.SPECIES) pipe.pIn = Var(within=NonNegativeReals) pipe.OUT = Port() self.assertTrue(pipe.OUT.is_fixed()) pipe.OUT.add(pipe.flow, "flow") self.assertFalse(pipe.OUT.is_fixed()) pipe.flow.fix(0) self.assertTrue(pipe.OUT.is_fixed()) pipe.OUT.add(-pipe.pIn, "pressure") self.assertFalse(pipe.OUT.is_fixed()) pipe.pIn.fix(1) self.assertTrue(pipe.OUT.is_fixed()) pipe.OUT.add(pipe.composition, "composition") self.assertFalse(pipe.OUT.is_fixed()) pipe.composition['a'].fix(1) self.assertFalse(pipe.OUT.is_fixed()) pipe.composition['b'].fix(1) pipe.composition['c'].fix(1) self.assertTrue(pipe.OUT.is_fixed()) m = ConcreteModel() m.SPECIES = Set(initialize=['a', 'b', 'c']) m.flow = Var() m.composition = Var(m.SPECIES) m.pIn = Var(within=NonNegativeReals) m.port = Port() m.port.add(m.flow, "flow") m.port.add(-m.pIn, "pressure") m.port.add(m.composition, "composition") m.port.fix() self.assertTrue(m.port.is_fixed())