def _make_feed_arcs(self): self.feed_liq_in = Arc( source=self.rectification_section[ self.config.feed_tray_location - 1].liq_out, destination=self.feed_tray.liq_in ) self.feed_liq_out = Arc( source=self.feed_tray.liq_out, destination=self.stripping_section[ self.config.feed_tray_location + 1].liq_in ) self.feed_vap_in = Arc( source=self.stripping_section[ self.config.feed_tray_location + 1].vap_out, destination=self.feed_tray.vap_in ) self.feed_vap_out = Arc( source=self.feed_tray.vap_out, destination=self.rectification_section[ self.config.feed_tray_location - 1].vap_in )
def HX1D_array_model(): # An example of maximum perversity. Dynamics, 1D control volumes, and # an indexed unit unit_set = range(3) time_set = [0,5] time_units=pyunits.s fs_cfg = { "dynamic": True, "time_set": time_set, "time_units": time_units} m = ConcreteModel() m.fs = FlowsheetBlock(default=fs_cfg) m.fs.properties = thermo_props.SaponificationParameterBlock() m.fs.unit_array = HX1D(unit_set,default={ "shell_side": {"property_package": m.fs.properties}, "tube_side": {"property_package": m.fs.properties}}) def tube_stream_array_rule(b, i): return {'source':b.unit_array[i].tube_outlet, 'destination':b.unit_array[i+1].tube_inlet} m.fs.tube_stream_array = Arc(range(2), rule=tube_stream_array_rule) def shell_stream_array_rule(b, i): return {'source':b.unit_array[i+1].shell_outlet, 'destination':b.unit_array[i].shell_inlet} m.fs.shell_stream_array = Arc(range(1,-1,-1), rule=shell_stream_array_rule) TransformationFactory("network.expand_arcs").apply_to(m) return m
def test_build_flowsheet(): model = run_chlorination_block_example(fix_free_chlorine=True) property_models.build_prop(model, base="TDS") build_translator_from_RO_to_chlorination_block(model) # Here, we set 'has_feed' to True because RO is our first block in the flowsheet kwargs_desal = { "has_desal_feed": True, "is_twostage": False, "has_ERD": False, "RO_type": "0D", "RO_base": "TDS", "RO_level": "detailed", } desal_port = desalination.build_desalination(model, **kwargs_desal) desalination.scale_desalination(model, **kwargs_desal) desalination.initialize_desalination(model, **kwargs_desal) # Add the connecting arcs model.fs.S1 = Arc(source=desal_port["out"], destination=model.fs.RO_to_Chlor.inlet) model.fs.S2 = Arc( source=model.fs.RO_to_Chlor.outlet, destination=model.fs.ideal_naocl_mixer_unit.inlet_stream, ) TransformationFactory("network.expand_arcs").apply_to(model) # Unfix inlet stream for mixer unfix_ideal_naocl_mixer_inlet_stream(model) check_dof(model)
def m(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.thermo_params = thermo_props.SaponificationParameterBlock() m.fs.reaction_params = rxn_props.SaponificationReactionParameterBlock( default={"property_package": m.fs.thermo_params}) m.fs.tank1 = CSTR(default={"property_package": m.fs.thermo_params, "reaction_package": m.fs.reaction_params}) m.fs.tank2 = CSTR(default={"property_package": m.fs.thermo_params, "reaction_package": m.fs.reaction_params}) m.fs.tank_array = CSTR( range(3), default={"property_package": m.fs.thermo_params, "reaction_package": m.fs.reaction_params}) m.fs.stream = Arc(source=m.fs.tank1.outlet, destination=m.fs.tank2.inlet) def stream_array_rule(b, i): return (b.tank_array[i].outlet, b.tank_array[i+1].inlet) m.fs.stream_array = Arc(range(2), rule=stream_array_rule) TransformationFactory("network.expand_arcs").apply_to(m) return m
def build_turbine_for_run_test(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95_ph.Iapws95ParameterBlock() # roughly based on NETL baseline studies m.fs.turb = TurbineMultistage( default={ "property_package": m.fs.properties, "num_hp": 7, "num_ip": 14, "num_lp": 11, "hp_split_locations": [4, 7], "ip_split_locations": [5, 14], "lp_split_locations": [4, 7, 9, 11], "hp_disconnect": [7], "ip_split_num_outlets": { 14: 3 } }) # Add reheater m.fs.reheat = Heater(default={"property_package": m.fs.properties}) m.fs.hp_to_reheat = Arc(source=m.fs.turb.hp_split[7].outlet_1, destination=m.fs.reheat.inlet) m.fs.reheat_to_ip = Arc(source=m.fs.reheat.outlet, destination=m.fs.turb.ip_stages[1].inlet) return m
def _make_condenser_arcs(self): self.condenser_vap_in = Arc( source=self.rectification_section[1].vap_out, destination=self.condenser.inlet) self.condenser_reflux_out = Arc( source=self.condenser.reflux, destination=self.rectification_section[1].liq_in)
def _make_reboiler_arcs(self): self.reboiler_liq_in = Arc( source=self.stripping_section[self.config.number_of_trays].liq_out, destination=self.reboiler.inlet) self.reboiler_vap_out = Arc(source=self.reboiler.vapor_reboil, destination=self.stripping_section[ self.config.number_of_trays].vap_in)
def define_heatx_streams(m, h): """ Declare all steams in the heat exchanger network via the SOFC model built before. Optional keyword arguments: --------------------------- :param m: SOFC model :param h: the heat exchanger network :return: heat exchanger network after declaring all steams """ h.fs.Split2.inlet.flow_mol.fix(m.fs.Burner.outlet.flow_mol[0].value) h.fs.HX1a.tube_inlet.flow_mol.fix(m.fs.Mix1.outlet.flow_mol[0].value) h.fs.HX2a.tube_inlet.flow_mol.fix(m.fs.Split1.outlet_1.flow_mol[0].value) h.fs.HX2b.tube_inlet.flow_mol.fix(m.fs.Split1.outlet_2.flow_mol[0].value) material = ["CH4", "CO", "CO2", "H2", "H2O", "N2", "NH3", "O2"] for i in material: h.fs.Split2.inlet.mole_frac_comp[0, i].\ fix(m.fs.Burner.outlet.mole_frac_comp[0, i].value) h.fs.HX1a.tube_inlet.mole_frac_comp[0, i].\ fix(m.fs.Mix1.outlet.mole_frac_comp[0, i].value) h.fs.HX2a.tube_inlet.mole_frac_comp[0, i].\ fix(m.fs.Split1.outlet_1.mole_frac_comp[0, i].value) h.fs.HX2b.tube_inlet.mole_frac_comp[0, i].\ fix(m.fs.Split1.outlet_2.mole_frac_comp[0, i].value) h.fs.Split2.inlet.temperature.fix(m.fs.Burner.outlet.temperature[0].value) h.fs.Split2.inlet.pressure.fix(m.fs.Burner.outlet.pressure[0].value) h.fs.HX1a.tube_inlet.temperature.fix(m.fs.Mix1.outlet.temperature[0].value) h.fs.HX1a.tube_inlet.pressure.fix(m.fs.Mix1.outlet.pressure[0].value) h.fs.HX2a.tube_inlet.temperature.\ fix(m.fs.Split1.outlet_1.temperature[0].value) h.fs.HX2a.tube_inlet.pressure.fix(m.fs.Split1.outlet_1.pressure[0].value) h.fs.HX2b.tube_inlet.temperature.\ fix(m.fs.Split1.outlet_2.temperature[0].value) h.fs.HX2b.tube_inlet.pressure.fix(m.fs.Split1.outlet_2.pressure[0].value) # Declare all Streams h.fs.stream0 = Arc(source=h.fs.Split2.outlet_1, destination=h.fs.HX1a.shell_inlet) h.fs.stream1 = Arc(source=h.fs.Split2.outlet_2, destination=h.fs.HX2a.shell_inlet) h.fs.stream2 = Arc(source=h.fs.Split2.outlet_3, destination=h.fs.HX2b.shell_inlet) h.fs.stream3 = Arc(source=h.fs.HX1a.shell_outlet, destination=h.fs.HX1b.inlet) TransformationFactory("network.expand_arcs").apply_to(h) return h
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_create_stream_table_dataframe_from_StateBlock_time(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False, "time_set": [3]}) m.fs.thermo_params = thermo_props.SaponificationParameterBlock() m.fs.reaction_params = rxn_props.SaponificationReactionParameterBlock( default={"property_package": m.fs.thermo_params}) m.fs.tank1 = CSTR(default={"property_package": m.fs.thermo_params, "reaction_package": m.fs.reaction_params}) m.fs.tank2 = CSTR(default={"property_package": m.fs.thermo_params, "reaction_package": m.fs.reaction_params}) m.fs.stream = Arc(source=m.fs.tank1.outlet, destination=m.fs.tank2.inlet) TransformationFactory("network.expand_arcs").apply_to(m) df = create_stream_table_dataframe({ "state": m.fs.tank1.control_volume.properties_out}, time_point=3) assert df.loc["Pressure"]["state"] == 101325 assert df.loc["Temperature"]["state"] == 298.15 assert df.loc["Volumetric Flowrate"]["state"] == 1.0 assert df.loc["Molar Concentration H2O"]["state"] == 100.0 assert df.loc["Molar Concentration NaOH"]["state"] == 100.0 assert df.loc["Molar Concentration EthylAcetate"]["state"] == 100.0 assert df.loc["Molar Concentration SodiumAcetate"]["state"] == 100.0 assert df.loc["Molar Concentration Ethanol"]["state"] == 100.0
def build_components(m, has_bypass=True): # build flowsheet property_models.build_prop(m, base='ion') pretrt_port = pretreatment_NF.build_pretreatment_NF(m, NF_type='ZO', NF_base='ion', has_bypass=has_bypass) property_models.build_prop(m, base='TDS') translator_block.build_tb(m, base_inlet='ion', base_outlet='TDS', name_str='tb_pretrt_to_desal') # Arc to translator block m.fs.s_pretrt_tb = Arc(source=pretrt_port['out'], destination=m.fs.tb_pretrt_to_desal.inlet) property_models.build_prop(m, base='eNRTL') gypsum_saturation_index.build(m, section='pretreatment') m.fs.NF.area.fix(175) if has_bypass: m.fs.splitter.split_fraction[0, 'bypass'].fix(0.50) m.fs.removal_Ca = Expression( expr=( m.fs.feed.properties[0].flow_mass_phase_comp['Liq', 'Ca'] - m.fs.mixer.mixed_state[0].flow_mass_phase_comp['Liq', 'Ca']) / m.fs.feed.properties[0].flow_mass_phase_comp['Liq', 'Ca']) m.fs.removal_Mg = Expression( expr=( m.fs.feed.properties[0].flow_mass_phase_comp['Liq', 'Mg'] - m.fs.mixer.mixed_state[0].flow_mass_phase_comp['Liq', 'Mg']) / m.fs.feed.properties[0].flow_mass_phase_comp['Liq', 'Mg'])
def model(): m = pyo.ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.prop_water = iapws95.Iapws95ParameterBlock() n_waterwalls = 10 m.fs.ww_zones = pyo.RangeSet(n_waterwalls) m.fs.Waterwalls = WaterwallSection( m.fs.ww_zones, default={ "dynamic": False, "has_holdup": False, "property_package": m.fs.prop_water, "has_heat_transfer": True, "has_pressure_change": True, }, ) def arc_rule(b, i): return { "source": m.fs.Waterwalls[i].outlet, "destination": m.fs.Waterwalls[i + 1].inlet } m.arc = Arc(pyo.RangeSet(n_waterwalls - 1), rule=arc_rule) # Pyomo expands arcs writing constraints outlet unit 1 = inlet unit 2 pyo.TransformationFactory("network.expand_arcs").apply_to(m) return m
def build_components(m, has_bypass=True): # build flowsheet property_models.build_prop(m, base="ion") pretrt_port = pretreatment_NF.build_pretreatment_NF(m, NF_type="ZO", NF_base="ion", has_bypass=has_bypass) property_models.build_prop(m, base="TDS") translator_block.build_tb(m, base_inlet="ion", base_outlet="TDS", name_str="tb_pretrt_to_desal") # Arc to translator block m.fs.s_pretrt_tb = Arc(source=pretrt_port["out"], destination=m.fs.tb_pretrt_to_desal.inlet) property_models.build_prop(m, base="eNRTL") gypsum_saturation_index.build(m, section="pretreatment") m.fs.NF.area.fix(175) if has_bypass: m.fs.splitter.split_fraction[0, "bypass"].fix(0.50) m.fs.removal_Ca = Expression( expr=( m.fs.feed.properties[0].flow_mass_phase_comp["Liq", "Ca"] - m.fs.mixer.mixed_state[0].flow_mass_phase_comp["Liq", "Ca"]) / m.fs.feed.properties[0].flow_mass_phase_comp["Liq", "Ca"]) m.fs.removal_Mg = Expression( expr=( m.fs.feed.properties[0].flow_mass_phase_comp["Liq", "Mg"] - m.fs.mixer.mixed_state[0].flow_mass_phase_comp["Liq", "Mg"]) / m.fs.feed.properties[0].flow_mass_phase_comp["Liq", "Mg"])
def _make_rectification_arcs(self): self._rectification_stream_index = RangeSet( 1, self.config.feed_tray_location - 2) def rule_liq_stream(self, i): return {"source": self.rectification_section[i].liq_out, "destination": self.rectification_section[i + 1].liq_in} def rule_vap_stream(self, i): return {"source": self.rectification_section[i + 1].vap_out, "destination": self.rectification_section[i].vap_in} self.rectification_liq_stream = Arc( self._rectification_stream_index, rule=rule_liq_stream) self.rectification_vap_stream = Arc( self._rectification_stream_index, rule=rule_vap_stream)
def test_flowsheet_report_with_arcs(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.thermo_params = thermo_props.SaponificationParameterBlock() m.fs.reaction_params = rxn_props.SaponificationReactionParameterBlock( default={"property_package": m.fs.thermo_params}) m.fs.tank1 = CSTR( default={ "property_package": m.fs.thermo_params, "reaction_package": m.fs.reaction_params }) m.fs.tank2 = CSTR( default={ "property_package": m.fs.thermo_params, "reaction_package": m.fs.reaction_params }) m.fs.stream = Arc(source=m.fs.tank1.outlet, destination=m.fs.tank2.inlet) TransformationFactory("network.expand_arcs").apply_to(m) df = m.fs._get_stream_table_contents() assert df.loc["Pressure"]["stream"] == 101325 assert df.loc["Temperature"]["stream"] == 298.15 assert df.loc["Volumetric Flowrate"]["stream"] == 1.0 assert df.loc["Molar Concentration H2O"]["stream"] == 100.0 assert df.loc["Molar Concentration NaOH"]["stream"] == 100.0 assert df.loc["Molar Concentration EthylAcetate"]["stream"] == 100.0 assert df.loc["Molar Concentration SodiumAcetate"]["stream"] == 100.0 assert df.loc["Molar Concentration Ethanol"]["stream"] == 100.0
def demo_flowsheet(): """Semi-complicated demonstration flowsheet. """ m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.BT_props = BTXParameterBlock() m.fs.M01 = Mixer(default={"property_package": m.fs.BT_props}) m.fs.H02 = Heater(default={"property_package": m.fs.BT_props}) m.fs.F03 = Flash(default={"property_package": m.fs.BT_props}) m.fs.s01 = Arc(source=m.fs.M01.outlet, destination=m.fs.H02.inlet) m.fs.s02 = Arc(source=m.fs.H02.outlet, destination=m.fs.F03.inlet) TransformationFactory("network.expand_arcs").apply_to(m.fs) m.fs.properties = SWCO2ParameterBlock() m.fs.main_compressor = PressureChanger( default={'dynamic': False, 'property_package': m.fs.properties, 'compressor': True, 'thermodynamic_assumption': ThermodynamicAssumption.isentropic}) m.fs.bypass_compressor = PressureChanger( default={'dynamic': False, 'property_package': m.fs.properties, 'compressor': True, 'thermodynamic_assumption': ThermodynamicAssumption.isentropic}) m.fs.turbine = PressureChanger( default={'dynamic': False, 'property_package': m.fs.properties, 'compressor': False, 'thermodynamic_assumption': ThermodynamicAssumption.isentropic}) m.fs.boiler = Heater(default={'dynamic': False, 'property_package': m.fs.properties, 'has_pressure_change': True}) m.fs.FG_cooler = Heater(default={'dynamic': False, 'property_package': m.fs.properties, 'has_pressure_change': True}) m.fs.pre_boiler = Heater(default={'dynamic': False, 'property_package': m.fs.properties, 'has_pressure_change': False}) m.fs.HTR_pseudo_tube = Heater(default={'dynamic': False, 'property_package': m.fs.properties, 'has_pressure_change': True}) m.fs.LTR_pseudo_tube = Heater(default={'dynamic': False, 'property_package': m.fs.properties, 'has_pressure_change': True}) return m.fs
def model(self): m = ConcreteModel() m.db = Database() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.params = WaterParameterBlock(default={"solute_list": ["cod"]}) m.fs.unit = CofermentationZO(default={ "property_package": m.fs.params, "database": m.db }) m.fs.feed1 = FeedZO(default={ "property_package": m.fs.params, }) m.fs.feed2 = FeedZO(default={ "property_package": m.fs.params, }) m.fs.feed1.flow_vol[0].fix( value( pyunits.convert(32.1 * pyunits.L / pyunits.day, to_units=pyunits.m**3 / pyunits.s))) m.fs.feed1.conc_mass_comp[0, "cod"].fix( value( pyunits.convert( 69781.93146 * pyunits.mg / pyunits.L, to_units=pyunits.kg / pyunits.m**3, ))) m.fs.feed2.flow_vol[0].fix( value( pyunits.convert(3.21 * pyunits.L / pyunits.day, to_units=pyunits.m**3 / pyunits.s))) m.fs.feed2.conc_mass_comp[0, "cod"].fix( value( pyunits.convert(1e4 * pyunits.mg / pyunits.L, to_units=pyunits.kg / pyunits.m**3))) m.fs.feed1_to_coferm = Arc(source=m.fs.feed1.outlet, destination=m.fs.unit.inlet1) m.fs.feed2_to_coferm = Arc(source=m.fs.feed2.outlet, destination=m.fs.unit.inlet2) TransformationFactory("network.expand_arcs").apply_to(m) return m
def create_model(m): """Create unit models""" m.fs.ww_zones = pyo.RangeSet(10) m.fs.drum = Drum( default={ "property_package": m.fs.prop_water, "has_holdup": False, "has_heat_transfer": True, "has_pressure_change": True, }) m.fs.downcomer = Downcomer( default={ "property_package": m.fs.prop_water, "has_holdup": False, "has_heat_transfer": True, }) m.fs.Waterwalls = WaterwallSection( m.fs.ww_zones, default={ "dynamic": False, "has_holdup": False, "property_package": m.fs.prop_water, "has_heat_transfer": True, "has_pressure_change": True, }, ) m.fs.stream_drum_out = Arc(source=m.fs.drum.liquid_outlet, destination=m.fs.downcomer.inlet) m.fs.stream_dcmr_out = Arc(source=m.fs.downcomer.outlet, destination=m.fs.Waterwalls[1].inlet) def arc_rule(b, i): return { "source": m.fs.Waterwalls[i].outlet, "destination": m.fs.Waterwalls[i + 1].inlet } m.arc = Arc(pyo.RangeSet(9), rule=arc_rule) m.fs.stream_ww14 = Arc(source=m.fs.Waterwalls[10].outlet, destination=m.fs.drum.water_steam_inlet) # pyomo arcs expand constraints for inlet = outlet ports pyo.TransformationFactory("network.expand_arcs").apply_to(m)
def test_propagate_state_indexed_fixed(): m = ConcreteModel() def block_rule(b): b.s = Set(initialize=[1, 2]) b.v1 = Var() b.v2 = Var(b.s) b.p = Port(b.s) b.p[1].add(b.v1, "V1") b.p[2].add(b.v2, "V2") return m.b1 = Block(rule=block_rule) m.b2 = Block(rule=block_rule) def arc_rule(m, i): return {'source': m.b1.p[i], 'destination': m.b2.p[i]} m.s1 = Arc([1, 2], rule=arc_rule) # 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 # Fix v1 in block 2 m.b2.v1.fix(500) propagate_state(m.s1[1]) # Check that values were propagated correctly assert m.b2.v1.value == 500 assert m.b1.v1.fixed is False assert m.b2.v1.fixed is True propagate_state(m.s1[1], overwrite_fixed=True) # Check that values were propagated correctly assert m.b2.v1.value == 10 assert m.b1.v1.fixed is False assert m.b2.v1.fixed is True propagate_state(m.s1[2]) # Check that values were propagated correctly 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.v2[1].fixed is False assert m.b1.v2[2].fixed is False assert m.b2.v2[1].fixed is False assert m.b2.v2[2].fixed is False
def _make_stripping_arcs(self): self._stripping_stream_index = RangeSet( self.config.feed_tray_location + 1, self.config.number_of_trays - 1) def rule_liq_stream(self, i): return {"source": self.stripping_section[i].liq_out, "destination": self.stripping_section[i + 1].liq_in} def rule_vap_stream(self, i): return {"source": self.stripping_section[i + 1].vap_out, "destination": self.stripping_section[i].vap_in} self.stripping_liq_stream = Arc( self._stripping_stream_index, rule=rule_liq_stream) self.stripping_vap_stream = Arc( self._stripping_stream_index, rule=rule_vap_stream)
def build_components(m, pretrt_type="NF", **kwargs): kwargs_desalination = { k: kwargs[k] for k in ( "has_desal_feed", "is_twostage", "has_ERD", "RO_type", "RO_base", "RO_level", ) } desal_port = desalination.build_desalination(m, **kwargs_desalination) m.fs.s_tb_desal = Arc(source=m.fs.tb_pretrt_to_desal.outlet, destination=desal_port["in"]) if pretrt_type == "softening": property_models.build_prop(m, base="eNRTL") gypsum_saturation_index.build(m, section="desalination", pretrt_type=pretrt_type, **kwargs) m.fs.RO.area.fix(80) m.fs.pump_RO.control_volume.properties_out[0].pressure.fix(60e5) if kwargs["is_twostage"]: m.fs.RO2.area.fix(20) m.fs.pump_RO2.control_volume.properties_out[0].pressure.fix(90e5) # touch some properties used in optimization if kwargs["is_twostage"]: product_water_sb = m.fs.mixer_permeate.mixed_state[0] else: product_water_sb = m.fs.RO.mixed_permeate[0] feed_flow_vol = 0.0009769808 # value of feed flowrate using the seawater property package with 1 kg/s mass flowrate m.fs.system_recovery = Expression(expr=product_water_sb.flow_vol / feed_flow_vol) # RO recovery m.fs.RO_recovery = Var( initialize=0.5, bounds=(0.01, 0.99), doc="Total volumetric water recovery for RO", ) m.fs.eq_RO_recovery = Constraint( expr=m.fs.RO_recovery == product_water_sb.flow_vol / m.fs.tb_pretrt_to_desal.properties_out[0].flow_vol) # annual water production m.fs.treated_flow_vol = Expression(expr=product_water_sb.flow_vol) costing.build_costing(m, **kwargs) return desal_port
def build_flowsheet(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.BT_props = BTXParameterBlock() m.fs.M01 = Mixer(default={"property_package": m.fs.BT_props}) m.fs.H02 = Heater(default={"property_package": m.fs.BT_props}) m.fs.F03 = Flash(default={"property_package": m.fs.BT_props}) m.fs.s01 = Arc(source=m.fs.M01.outlet, destination=m.fs.H02.inlet) m.fs.s02 = Arc(source=m.fs.H02.outlet, destination=m.fs.F03.inlet) TransformationFactory("network.expand_arcs").apply_to(m.fs) return m
def build(): # flowsheet set up m = ConcreteModel() m.db = Database() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.prop = prop_ZO.WaterParameterBlock( default={"solute_list": ["cod", "hydrogen", "methane"]}) # unit models m.fs.feed = FeedZO(default={"property_package": m.fs.prop}) m.fs.metab_hydrogen = MetabZO(default={ "property_package": m.fs.prop, "database": m.db, "process_subtype": "hydrogen", }, ) m.fs.metab_methane = MetabZO(default={ "property_package": m.fs.prop, "database": m.db, "process_subtype": "methane", }, ) m.fs.product_hydrogen = Product(default={"property_package": m.fs.prop}) m.fs.product_methane = Product(default={"property_package": m.fs.prop}) m.fs.product_H2O = Product(default={"property_package": m.fs.prop}) # connections m.fs.s01 = Arc(source=m.fs.feed.outlet, destination=m.fs.metab_hydrogen.inlet) m.fs.s02 = Arc(source=m.fs.metab_hydrogen.treated, destination=m.fs.metab_methane.inlet) m.fs.s03 = Arc(source=m.fs.metab_hydrogen.byproduct, destination=m.fs.product_hydrogen.inlet) m.fs.s04 = Arc(source=m.fs.metab_methane.byproduct, destination=m.fs.product_methane.inlet) m.fs.s05 = Arc(source=m.fs.metab_methane.treated, destination=m.fs.product_H2O.inlet) TransformationFactory("network.expand_arcs").apply_to(m) # scaling iscale.calculate_scaling_factors(m) return m
def build(): # flowsheet set up m = ConcreteModel() m.db = Database() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.prop = prop_ZO.WaterParameterBlock( default={ "solute_list": ["bod", "tss", "ammonium_as_nitrogen", "nitrate", "nitrogen"] }) # unit models m.fs.feed = FeedZO(default={"property_package": m.fs.prop}) m.fs.mabr = MABRZO(default={ "property_package": m.fs.prop, "database": m.db, }, ) m.fs.dmbr = DMBRZO(default={ "property_package": m.fs.prop, "database": m.db, }, ) m.fs.pump = PumpElectricityZO(default={ "property_package": m.fs.prop, "database": m.db, }, ) m.fs.product_H2O = Product(default={"property_package": m.fs.prop}) # connections m.fs.s01 = Arc(source=m.fs.feed.outlet, destination=m.fs.pump.inlet) m.fs.s02 = Arc(source=m.fs.pump.outlet, destination=m.fs.mabr.inlet) m.fs.s03 = Arc(source=m.fs.mabr.treated, destination=m.fs.dmbr.inlet) m.fs.s04 = Arc(source=m.fs.dmbr.treated, destination=m.fs.product_H2O.inlet) TransformationFactory("network.expand_arcs").apply_to(m) # scaling iscale.calculate_scaling_factors(m) return m
def _make_arcs(self): # make arcs self.liq_stream_index = RangeSet(0, self.config.number_of_trays) self.vap_stream_index = RangeSet(1, self.config.number_of_trays + 1) def rule_liq_stream(self, i): if i == 0: return { "source": self.condenser.reflux, "destination": self.tray[i + 1].liq_in } elif i == self.config.number_of_trays: return { "source": self.tray[i].liq_out, "destination": self.reboiler.inlet } else: return { "source": self.tray[i].liq_out, "destination": self.tray[i + 1].liq_in } def rule_vap_stream(self, i): if i == 1: return { "source": self.tray[i].vap_out, "destination": self.condenser.inlet } elif i == self.config.number_of_trays + 1: return { "source": self.reboiler.vapor_reboil, "destination": self.tray[i - 1].vap_in } else: return { "source": self.tray[i].vap_out, "destination": self.tray[i - 1].vap_in } self.liq_stream = Arc(self.liq_stream_index, rule=rule_liq_stream) self.vap_stream = Arc(self.vap_stream_index, rule=rule_vap_stream)
def build(m): # Properties m.fs.properties_feed = props_sw.SeawaterParameterBlock() m.fs.properties_vapor = props_w.WaterParameterBlock() # Evaporator m.fs.evaporator = Evaporator( default={ "property_package_feed": m.fs.properties_feed, "property_package_vapor": m.fs.properties_vapor, }) # Compressor m.fs.compressor = Compressor( default={"property_package": m.fs.properties_vapor}) # Connections m.fs.s01 = Arc(source=m.fs.evaporator.outlet_vapor, destination=m.fs.compressor.inlet) m.fs.s02 = Arc(source=m.fs.compressor.outlet, destination=m.fs.evaporator.inlet_condenser) TransformationFactory("network.expand_arcs").apply_to(m)
def build(self): super().build() config = self.config # sorter ref to config for less line splitting # All feedwater heaters have a condensing section _set_prop_pack(config.condense, config) self.condense = FWHCondensing0D(default=config.condense) # Add a mixer to add the drain stream from another feedwater heater if config.has_drain_mixer: mix_cfg = { "dynamic": False, "inlet_list": ["steam", "drain"], "property_package": config.property_package, "momentum_mixing_type": MomentumMixingType.none, } self.drain_mix = Mixer(default=mix_cfg) @self.drain_mix.Constraint(self.drain_mix.flowsheet().config.time) def mixer_pressure_constraint(b, t): """ Constraint to set the drain mixer pressure to the pressure of the steam extracted from the turbine. The drain inlet should always be a higher pressure than the steam inlet. """ return b.steam_state[t].pressure == b.mixed_state[t].pressure # Connect the mixer to the condensing section inlet self.SMX = Arc(source=self.drain_mix.outlet, destination=self.condense.inlet_1) # Add a desuperheat section before the condensing section if config.has_desuperheat: _set_prop_pack(config.desuperheat, config) self.desuperheat = HeatExchanger(default=config.desuperheat) # set default area less than condensing section area, this will # almost always be overridden by the user fixing an area later self.desuperheat.area.value = 10 if config.has_drain_mixer: self.SDS = Arc(source=self.desuperheat.outlet_1, destination=self.drain_mix.steam) else: self.SDS = Arc(source=self.desuperheat.outlet_1, destination=self.condense.inlet_1) self.FW2 = Arc(source=self.condense.outlet_2, destination=self.desuperheat.inlet_2) # Add a drain cooling section after the condensing section if config.has_drain_cooling: _set_prop_pack(config.cooling, config) self.cooling = HeatExchanger(default=config.cooling) # set default area less than condensing section area, this will # almost always be overridden by the user fixing an area later self.cooling.area.value = 10 self.FW1 = Arc(source=self.cooling.outlet_2, destination=self.condense.inlet_2) self.SC = Arc(source=self.condense.outlet_1, destination=self.cooling.inlet_1) TransformationFactory("network.expand_arcs").apply_to(self)
def build(self): # Call UnitModel.build to setup dynamics super(HydrogenTurbineData, self).build() self.compressor = Compressor( default={"property_package": self.config.property_package}) self.stoic_reactor = StoichiometricReactor( default={"property_package": self.config.property_package, "reaction_package": self.config.reaction_package, "has_heat_of_reaction": True, "has_heat_transfer": False, "has_pressure_change": False}) self.turbine = Turbine( default={"property_package": self.config.property_package}) # Declare var for reactor conversion self.stoic_reactor.conversion = Var(initialize=0.75, bounds=(0, 1)) stoic_reactor_in = self.stoic_reactor.control_volume.properties_in[0.0] stoic_reactor_out = self.stoic_reactor.control_volume.properties_out[0.0] self.stoic_reactor.conv_constraint = Constraint( expr=self.stoic_reactor.conversion * stoic_reactor_in.flow_mol_comp["hydrogen"] == (stoic_reactor_in.flow_mol_comp["hydrogen"] - stoic_reactor_out.flow_mol_comp["hydrogen"])) # Connect arcs self.comp_to_reactor = Arc( source=self.compressor.outlet, destination=self.stoic_reactor.inlet) self.reactor_to_turbine = Arc( source=self.stoic_reactor.outlet, destination=self.turbine.inlet) TransformationFactory("network.expand_arcs").apply_to(self)
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_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")