def test_setInputs_outlet_state_block(): # vapor-liquid (Wilson) m.fs1.state_block_Wilson_vl.flow_mol.fix(1) m.fs1.state_block_Wilson_vl.temperature.fix(368) m.fs1.state_block_Wilson_vl.pressure.fix(101325) m.fs1.state_block_Wilson_vl.mole_frac["benzene"].fix(0.5) assert degrees_of_freedom(m.fs1.state_block_Wilson_vl) == 4 # liquid only (Wilson) m.fs1.state_block_Wilson_l.flow_mol.fix(1) m.fs1.state_block_Wilson_l.temperature.fix(368) m.fs1.state_block_Wilson_l.pressure.fix(101325) m.fs1.state_block_Wilson_l.mole_frac["benzene"].fix(0.5) assert degrees_of_freedom(m.fs1.state_block_Wilson_l) == 0 # vapour only (Wilson) m.fs1.state_block_Wilson_v.flow_mol.fix(1) m.fs1.state_block_Wilson_v.temperature.fix(368) m.fs1.state_block_Wilson_v.pressure.fix(101325) m.fs1.state_block_Wilson_v.mole_frac["benzene"].fix(0.5) assert degrees_of_freedom(m.fs1.state_block_Wilson_v) == 0
def test_setInputs_inlet_state_block(): # vapor-liquid (Wilson) m.fs.state_block_Wilson_vl.flow_mol.fix(1) m.fs.state_block_Wilson_vl.temperature.fix(368) m.fs.state_block_Wilson_vl.pressure.fix(101325) m.fs.state_block_Wilson_vl.mole_frac["benzene"].fix(0.5) m.fs.state_block_Wilson_vl.mole_frac["toluene"].fix(0.5) assert degrees_of_freedom(m.fs.state_block_Wilson_vl) == 4 # Fix Wilson specific variables m.fs.state_block_Wilson_vl.vol_mol_comp.fix() m.fs.state_block_Wilson_vl.tau.fix() assert degrees_of_freedom(m.fs.state_block_Wilson_vl) == 0 # liquid only (Wilson) m.fs.state_block_Wilson_l.flow_mol.fix(1) m.fs.state_block_Wilson_l.temperature.fix(368) m.fs.state_block_Wilson_l.pressure.fix(101325) m.fs.state_block_Wilson_l.mole_frac["benzene"].fix(0.5) m.fs.state_block_Wilson_l.mole_frac["toluene"].fix(0.5) assert degrees_of_freedom(m.fs.state_block_Wilson_l) == 0 # vapour only (Wilson) m.fs.state_block_Wilson_v.flow_mol.fix(1) m.fs.state_block_Wilson_v.temperature.fix(368) m.fs.state_block_Wilson_v.pressure.fix(101325) m.fs.state_block_Wilson_v.mole_frac["benzene"].fix(0.5) m.fs.state_block_Wilson_v.mole_frac["toluene"].fix(0.5) assert degrees_of_freedom(m.fs.state_block_Wilson_v) == 0
def test_setInputs_inlet_state_blocks(): # vapor-liquid m.fs.state_block_vl.flow_mol.fix(1) m.fs.state_block_vl.temperature.fix(368) m.fs.state_block_vl.pressure.fix(101325) m.fs.state_block_vl.mole_frac["benzene"].fix(0.5) m.fs.state_block_vl.mole_frac["toluene"].fix(0.5) assert degrees_of_freedom(m.fs.state_block_vl) == 0 # liquid only m.fs.state_block_l.flow_mol.fix(1) m.fs.state_block_l.temperature.fix(362) m.fs.state_block_l.pressure.fix(101325) m.fs.state_block_l.mole_frac["benzene"].fix(0.5) m.fs.state_block_l.mole_frac["toluene"].fix(0.5) assert degrees_of_freedom(m.fs.state_block_l) == 0 # vapor only m.fs.state_block_v.flow_mol.fix(1) m.fs.state_block_v.temperature.fix(375) m.fs.state_block_v.pressure.fix(101325) m.fs.state_block_v.mole_frac["benzene"].fix(0.5) m.fs.state_block_v.mole_frac["toluene"].fix(0.5) assert degrees_of_freedom(m.fs.state_block_v) == 0
def test_setInputs_inlet_state_block(): # vapor-liquid (NRTL) m.fs.state_block_NRTL_vl.flow_mol.fix(1) m.fs.state_block_NRTL_vl.temperature.fix(368) m.fs.state_block_NRTL_vl.pressure.fix(101325) m.fs.state_block_NRTL_vl.mole_frac["benzene"].fix(0.5) m.fs.state_block_NRTL_vl.mole_frac["toluene"].fix(0.5) assert degrees_of_freedom(m.fs.state_block_NRTL_vl) == 6 # Fix NRTL specific variables and check if DOF is 0 m.fs.state_block_NRTL_vl.alpha.fix() m.fs.state_block_NRTL_vl.tau.fix() assert degrees_of_freedom(m.fs.state_block_NRTL_vl) == 0 # liquid only (NRTL) m.fs.state_block_NRTL_l.flow_mol.fix(1) m.fs.state_block_NRTL_l.temperature.fix(368) m.fs.state_block_NRTL_l.pressure.fix(101325) m.fs.state_block_NRTL_l.mole_frac["benzene"].fix(0.5) m.fs.state_block_NRTL_l.mole_frac["toluene"].fix(0.5) assert degrees_of_freedom(m.fs.state_block_NRTL_l) == 0 # vapour only (NRTL) m.fs.state_block_NRTL_v.flow_mol.fix(1) m.fs.state_block_NRTL_v.temperature.fix(368) m.fs.state_block_NRTL_v.pressure.fix(101325) m.fs.state_block_NRTL_v.mole_frac["benzene"].fix(0.5) m.fs.state_block_NRTL_v.mole_frac["toluene"].fix(0.5) assert degrees_of_freedom(m.fs.state_block_NRTL_v) == 0
def test_setInputs(): """Set inlet and operating conditions for co-current heat exchanger.""" # HX dimensions m.fs.HX_co_current.d_shell.fix(1.04) m.fs.HX_co_current.d_tube_outer.fix(0.01167) m.fs.HX_co_current.d_tube_inner.fix(0.01067) m.fs.HX_co_current.N_tubes.fix(1176) m.fs.HX_co_current.shell_length.fix(4.85) m.fs.HX_co_current.tube_length.fix(4.85) m.fs.HX_co_current.shell_heat_transfer_coefficient.fix(2000) m.fs.HX_co_current.tube_heat_transfer_coefficient.fix(51000) # Boundary conditions for t in m.fs.time: # Unit HX01 # NETL baseline study m.fs.HX_co_current.shell_inlet.flow_mol[0].fix(2300) # mol/s m.fs.HX_co_current.shell_inlet.temperature[0].fix(676) # K m.fs.HX_co_current.shell_inlet.pressure[0].fix(7.38E6) # Pa m.fs.HX_co_current.shell_inlet.vapor_frac[0].fix(1) m.fs.HX_co_current.tube_inlet.flow_mol[0].fix(26.6) # mol/s m.fs.HX_co_current.tube_inlet.temperature[0].fix(529) # K m.fs.HX_co_current.tube_inlet.pressure[0].fix(2.65E7) # Pa m.fs.HX_co_current.tube_inlet.vapor_frac[0].fix(0) assert degrees_of_freedom(m.fs.HX_co_current) == 0 """Set inlet and operating conditions for counter-current heat exchanger.""" # HX dimensions m.fs.HX_counter_current.d_shell.fix(1.04) m.fs.HX_counter_current.d_tube_outer.fix(0.01167) m.fs.HX_counter_current.d_tube_inner.fix(0.01067) m.fs.HX_counter_current.N_tubes.fix(1176) m.fs.HX_counter_current.shell_length.fix(4.85) m.fs.HX_counter_current.tube_length.fix(4.85) m.fs.HX_counter_current.shell_heat_transfer_coefficient.fix(2000) m.fs.HX_counter_current.tube_heat_transfer_coefficient.fix(51000) # Boundary conditions for t in m.fs.time: # Unit HX01 # NETL baseline study m.fs.HX_counter_current.shell_inlet.flow_mol[0].fix(2300) # mol/s m.fs.HX_counter_current.shell_inlet.temperature[0].fix(676) # K m.fs.HX_counter_current.shell_inlet.pressure[0].fix(7.38E6) # Pa m.fs.HX_counter_current.shell_inlet.vapor_frac[0].fix(1) m.fs.HX_counter_current.tube_inlet.flow_mol[0].fix(26.6) # mol/s m.fs.HX_counter_current.tube_inlet.temperature[0].fix(529) # K m.fs.HX_counter_current.tube_inlet.pressure[0].fix(2.65E7) # Pa m.fs.HX_counter_current.tube_inlet.vapor_frac[0].fix(0) assert degrees_of_freedom(m.fs.HX_counter_current) == 0
def test_initialization_isentropic(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.props = pp.Iapws95ParameterBlock() m.fs.pc = PressureChanger(default={ "property_package": m.fs.props, "thermodynamic_assumption": ThermodynamicAssumption.isentropic}) init_state = { "flow_mol": 27.5e3, "pressure": 2e6, "enth_mol": 4000 } m.fs.pc.inlet.flow_mol.fix(27.5e3) m.fs.pc.inlet.enth_mol.fix(4000) m.fs.pc.inlet.pressure.fix(2e6) m.fs.pc.deltaP.fix(-1e3) m.fs.pc.efficiency_isentropic.fix(0.83) assert degrees_of_freedom(m) == 0 m.fs.pc.initialize(state_args=init_state, outlvl=5, optarg={'tol': 1e-6}) assert (pytest.approx(27.5e3, abs=1e-2) == m.fs.pc.outlet.flow_mol[0].value) assert (pytest.approx(3999.979732728688, abs=1e-2) == m.fs.pc.outlet.enth_mol[0].value) assert (pytest.approx(1999000.0, abs=1e-2) == m.fs.pc.outlet.pressure[0].value) solver.solve(m)
def test_initialization_isothermal(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.props = pp.Iapws95ParameterBlock() m.fs.pc = PressureChanger(default={ "property_package": m.fs.props, "thermodynamic_assumption": ThermodynamicAssumption.isothermal}) m.fs.pc.deltaP.fix(-1e3) m.fs.pc.inlet.flow_mol.fix(27.5e3) m.fs.pc.inlet.enth_mol.fix(4000) m.fs.pc.inlet.pressure.fix(2e6) assert degrees_of_freedom(m) == 0 init_state = { "flow_mol": 27.5e3, "pressure": 2e6, "enth_mol": 4000 } m.fs.pc.initialize(state_args=init_state, outlvl=5) assert (pytest.approx(27500.0, abs=1e-2) == m.fs.pc.outlet.flow_mol[0].value) assert (pytest.approx(3999.984582673592, abs=1e-2) == m.fs.pc.outlet.enth_mol[0].value) assert (pytest.approx(1999000.0, abs=1e-2) == m.fs.pc.outlet.pressure[0].value) solver.solve(m)
def test_initialize_heat_exchanger(build_heat_exchanger): m = build_heat_exchanger init_state1 = {"flow_mol": 100, "pressure": 101325, "enth_mol": 4000} init_state2 = {"flow_mol": 100, "pressure": 101325, "enth_mol": 3500} m.fs.heat_exchanger.area.fix(1000) m.fs.heat_exchanger.overall_heat_transfer_coefficient.fix(100) prop_in_1 = m.fs.heat_exchanger.side_1.properties_in[0] prop_out_1 = m.fs.heat_exchanger.side_1.properties_out[0] prop_in_2 = m.fs.heat_exchanger.side_2.properties_in[0] prop_out_2 = m.fs.heat_exchanger.side_2.properties_out[0] prop_in_1.flow_mol.fix(100) prop_in_1.pressure.fix(101325) prop_in_1.enth_mol.fix(4000) prop_in_2.flow_mol.fix(100) prop_in_2.pressure.fix(101325) prop_in_2.enth_mol.fix(3000) m.fs.heat_exchanger.heat_duty.value = 10000 m.fs.heat_exchanger.initialize(state_args_1=init_state1, state_args_2=init_state2, outlvl=5) solver.solve(m) assert degrees_of_freedom(m) == 0 print(value(m.fs.heat_exchanger.delta_temperature[0])) print(value(m.fs.heat_exchanger.side_1.heat[0])) print(value(m.fs.heat_exchanger.side_2.heat[0])) assert abs(value(prop_in_1.temperature) - 326.1667075078748) <= 1e-4 assert abs(value(prop_out_1.temperature) - 313.81921851031814) <= 1e-4 assert abs(value(prop_in_2.temperature) - 312.88896252921734) <= 1e-4 assert abs(value(prop_out_2.temperature) - 325.23704823703537) <= 1e-4 assert abs(value(prop_in_1.phase_frac["Liq"]) - 1) <= 1e-6 assert abs(value(prop_out_1.phase_frac["Liq"]) - 1) <= 1e-6 assert abs(value(prop_in_1.phase_frac["Vap"]) - 0) <= 1e-6 assert abs(value(prop_out_1.phase_frac["Vap"]) - 0) <= 1e-6
def test_initialize(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = BTXParameterBlock() m.fs.ff = FeedFlash(default={"property_package": m.fs.properties}) m.fs.ff.flow_mol.fix(1) m.fs.ff.temperature.fix(368) m.fs.ff.pressure.fix(101325) m.fs.ff.mole_frac[0, "benzene"].fix(0.5) m.fs.ff.mole_frac[0, "toluene"].fix(0.5) assert degrees_of_freedom(m) == 0 m.fs.ff.initialize(outlvl=5, optarg={'tol': 1e-6}) assert (pytest.approx(101325.0, abs=1e3) == m.fs.ff.outlet.pressure[0].value) assert (pytest.approx(368.00, abs=1e-0) == m.fs.ff.outlet.temperature[0].value) assert (pytest.approx(1.0, abs=1e-2) == m.fs.ff.outlet.flow_mol[0].value) assert (pytest.approx(0.3961, abs=1e-3) == m.fs.ff.control_volume. properties_out[0].flow_mol_phase["Vap"].value)
def test_tutorial_3(): f = import_file(join(example, "Tutorial_3_Dynamic_Flowsheets")) m, results = f.main() # Check for optimal solution assert results.solver.termination_condition == TerminationCondition.optimal assert results.solver.status == SolverStatus.ok assert degrees_of_freedom(m) == 0 assert m.fs.time.last() == 20.0 assert len(m.fs.time) == 51 assert (m.fs.Tank2.outlet.flow_vol[20.0].value == pytest.approx(1.0, abs=1e-2)) assert (m.fs.Tank2.outlet.conc_mol_comp[20.0, "Ethanol"].value == pytest.approx( 43.62, abs=1e-1)) assert ( m.fs.Tank2.outlet.conc_mol_comp[20.0, "EthylAcetate"].value == pytest.approx( 1.65, abs=1e-1)) assert (m.fs.Tank2.outlet.conc_mol_comp[20.0, "NaOH"].value == pytest.approx( 6.38, abs=1e-1)) assert (m.fs.Tank2.outlet.conc_mol_comp[20.0, "SodiumAcetate"].value == pytest.approx(43.62, abs=1e-1)) assert (m.fs.Tank2.outlet.conc_mol_comp[20.0, "H2O"].value == pytest.approx( 55388.0, abs=1)) assert (m.fs.Tank2.outlet.pressure[20.0].value == pytest.approx(101325, abs=1)) assert (m.fs.Tank2.outlet.temperature[20.0].value == pytest.approx( 303.66, abs=1e-1))
def test_tutorial_2(): f = import_file(join(example, "Tutorial_2_Basic_Flowsheet_Optimization")) m, results = f.main() # Check for optimal solution assert results.solver.termination_condition == TerminationCondition.optimal assert results.solver.status == SolverStatus.ok assert degrees_of_freedom(m) == 1 assert (m.fs.Tank2.outlet.flow_vol[0].value == pytest.approx(1.0, abs=1e-2)) assert (m.fs.Tank2.outlet.conc_mol_comp[0, "Ethanol"].value == pytest.approx( 92.106, abs=1e-2)) assert ( m.fs.Tank2.outlet.conc_mol_comp[0, "EthylAcetate"].value == pytest.approx( 7.894, abs=1e-2)) assert (m.fs.Tank2.outlet.conc_mol_comp[0, "NaOH"].value == pytest.approx( 7.894, abs=1e-2)) assert (m.fs.Tank2.outlet.conc_mol_comp[0, "SodiumAcetate"].value == pytest.approx(92.106, abs=1e-2)) assert (m.fs.Tank2.outlet.conc_mol_comp[0, "H2O"].value == pytest.approx( 55388.0, abs=1)) assert (m.fs.Tank2.outlet.pressure[0].value == pytest.approx(101325, abs=1)) assert (m.fs.Tank2.outlet.temperature[0].value == pytest.approx(304.23, abs=1e-1)) assert (m.fs.Tank1.volume[0].value == pytest.approx(1.215, abs=1e-2)) assert (m.fs.Tank2.volume[0].value == pytest.approx(1.785, abs=1e-2))
def test_initialize(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = SaponificationParameterBlock() m.fs.prod = Product(default={"property_package": m.fs.properties}) m.fs.prod.flow_vol.fix(1.0e-03) m.fs.prod.conc_mol_comp[0, "H2O"].fix(55388.0) m.fs.prod.conc_mol_comp[0, "NaOH"].fix(100.0) m.fs.prod.conc_mol_comp[0, "EthylAcetate"].fix(100.0) m.fs.prod.conc_mol_comp[0, "SodiumAcetate"].fix(0.0) m.fs.prod.conc_mol_comp[0, "Ethanol"].fix(0.0) m.fs.prod.temperature.fix(303.15) m.fs.prod.pressure.fix(101325.0) assert degrees_of_freedom(m) == 0 m.fs.prod.initialize(outlvl=5, optarg={'tol': 1e-6}) assert m.fs.prod.inlet.flow_vol[0].value == 1.0e-03 assert m.fs.prod.inlet.conc_mol_comp[0, "H2O"].value == 55388.0 assert m.fs.prod.inlet.conc_mol_comp[0, "NaOH"].value == 100.0 assert m.fs.prod.inlet.conc_mol_comp[0, "EthylAcetate"].value == 100.0 assert m.fs.prod.inlet.conc_mol_comp[0, "SodiumAcetate"].value == 0.0 assert m.fs.prod.inlet.conc_mol_comp[0, "Ethanol"].value == 0.0
def test_setInputs(): m.fs.flash.inlet.flow_mol.fix(1) m.fs.flash.inlet.temperature.fix(368) m.fs.flash.inlet.pressure.fix(101325) m.fs.flash.inlet.mole_frac[0, "benzene"].fix(0.5) m.fs.flash.inlet.mole_frac[0, "toluene"].fix(0.5) m.fs.flash.heat_duty.fix(0) m.fs.flash.deltaP.fix(0) assert degrees_of_freedom(m) == 0
def test_initialize(build_turbine): """Initialize a turbine model""" m = build_turbine # set inlet m.fs.turb.inlet.enth_mol[0].value = 47115 m.fs.turb.inlet.flow_mol[0].value = 15000 m.fs.turb.inlet.pressure[0].value = 8e4 m.fs.turb.initialize(outlvl=1) for c in active_equalities(m): assert (abs(c.body() - c.lower) < 1e-4) assert (degrees_of_freedom(m) == 3 ) #inlet was't fixed and still shouldn't be
def test_initialize(build_turbine): """Initialize a turbine model""" m = build_turbine # set inlet m.fs.turb.inlet.enth_mol[0].value = 70000 m.fs.turb.inlet.flow_mol[0].value = 15000 m.fs.turb.inlet.pressure[0].value = 8e6 m.fs.turb.efficiency_isentropic.fix(0.8) m.fs.turb.ratioP.fix(0.7) m.fs.turb.initialize(outlvl=4) for c in active_equalities(m): assert (abs(c.body() - c.lower) < 1e-4) assert (degrees_of_freedom(m) == 3 ) #inlet was't fixed and still shouldn't be
def test_initialize(build_turbine): """Initialize a turbine model""" m = build_turbine hin = iapws95_ph.htpx(T=880, P=2.4233e7) # set inlet m.fs.turb.inlet.enth_mol[0].value = hin m.fs.turb.inlet.flow_mol[0].value = 26000 / 4.0 m.fs.turb.inlet.pressure[0].value = 2.4233e7 m.fs.turb.initialize(outlvl=1) for c in active_equalities(m): assert (abs(c.body() - c.lower) < 1e-4) assert (degrees_of_freedom(m) == 3 ) #inlet was't fixed and still shouldn't be
def test_heater_q1(build_heater): m = build_heater m.fs.heater.inlet.enth_mol.fix(4000) m.fs.heater.inlet.flow_mol.fix(100) m.fs.heater.inlet.pressure.fix(101325) m.fs.heater.heat_duty[0].fix(100 * 20000) m.fs.heater.initialize() assert degrees_of_freedom(m) == 0 solver.solve(m) prop_in = m.fs.heater.control_volume.properties_in[0] prop_out = m.fs.heater.control_volume.properties_out[0] assert abs(value(prop_in.temperature) - 326.1667075078748) <= 1e-4 assert abs(value(prop_out.temperature) - 373.12429584768876) <= 1e-4 assert abs(value(prop_in.phase_frac["Liq"]) - 1) <= 1e-6 assert abs(value(prop_out.phase_frac["Liq"]) - 0.5953218682380845) <= 1e-6 assert abs(value(prop_in.phase_frac["Vap"]) - 0) <= 1e-6 assert abs(value(prop_out.phase_frac["Vap"]) - 0.40467813176191547) <= 1e-6
def test_initialize(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = SaponificationParameterBlock() m.fs.reactions = SaponificationReactionParameterBlock( default={"property_package": m.fs.properties}) m.fs.cstr = CSTR( default={ "property_package": m.fs.properties, "reaction_package": m.fs.reactions, "has_equilibrium_reactions": False, "has_heat_transfer": False, "has_pressure_change": False }) m.fs.cstr.inlet.flow_vol.fix(1.0e-03) m.fs.cstr.inlet.conc_mol_comp[0, "H2O"].fix(55388.0) m.fs.cstr.inlet.conc_mol_comp[0, "NaOH"].fix(100.0) m.fs.cstr.inlet.conc_mol_comp[0, "EthylAcetate"].fix(100.0) m.fs.cstr.inlet.conc_mol_comp[0, "SodiumAcetate"].fix(0.0) m.fs.cstr.inlet.conc_mol_comp[0, "Ethanol"].fix(0.0) m.fs.cstr.inlet.temperature.fix(303.15) m.fs.cstr.inlet.pressure.fix(101325.0) m.fs.cstr.control_volume.volume.fix(1.5e-03) assert degrees_of_freedom(m) == 0 m.fs.cstr.initialize(outlvl=5, optarg={'tol': 1e-6}) assert (pytest.approx(101325.0, abs=1e-2) == m.fs.cstr.outlet.pressure[0].value) assert (pytest.approx(303.15, abs=1e-2) == m.fs.cstr.outlet.temperature[0].value) assert (pytest.approx( 20.80, abs=1e-2) == m.fs.cstr.outlet.conc_mol_comp[0, "EthylAcetate"].value)
def test_initialize(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = SaponificationParameterBlock() m.fs.reactions = SaponificationReactionParameterBlock( default={"property_package": m.fs.properties}) m.fs.rstoic = StoichiometricReactor( default={ "property_package": m.fs.properties, "reaction_package": m.fs.reactions, "has_heat_transfer": False, "has_pressure_change": False }) m.fs.rstoic.inlet.flow_vol.fix(1.0) m.fs.rstoic.inlet.conc_mol_comp[0, "H2O"].fix(55388.0) m.fs.rstoic.inlet.conc_mol_comp[0, "NaOH"].fix(100.0) m.fs.rstoic.inlet.conc_mol_comp[0, "EthylAcetate"].fix(100.0) m.fs.rstoic.inlet.conc_mol_comp[0, "SodiumAcetate"].fix(0.0) m.fs.rstoic.inlet.conc_mol_comp[0, "Ethanol"].fix(0.0) m.fs.rstoic.inlet.temperature.fix(303.15) m.fs.rstoic.inlet.pressure.fix(101325.0) m.fs.rstoic.rate_reaction_extent[:, 'R1'].fix( 0.9 * m.fs.rstoic.inlet.conc_mol_comp[0, "NaOH"].value) assert degrees_of_freedom(m) == 0 m.fs.rstoic.initialize(outlvl=5, optarg={'tol': 1e-6}) assert (pytest.approx(101325.0, abs=1e-2) == m.fs.rstoic.outlet.pressure[0].value) assert (pytest.approx(303.15, abs=1e-2) == m.fs.rstoic.outlet.temperature[0].value) assert (pytest.approx( 90, abs=1e-2) == m.fs.rstoic.outlet.conc_mol_comp[0, "Ethanol"].value)
def test_fwh_model(): model = pyo.ConcreteModel() model.fs = FlowsheetBlock( default={ "dynamic": False, "default_property_package": Iapws95ParameterBlock() }) model.fs.properties = model.fs.config.default_property_package model.fs.fwh = FWH0D( default={ "has_desuperheat": True, "has_drain_cooling": True, "has_drain_mixer": True, "property_package": model.fs.properties }) model.fs.fwh.desuperheat.inlet_1.flow_mol.fix(100) model.fs.fwh.desuperheat.inlet_1.flow_mol.unfix() model.fs.fwh.desuperheat.inlet_1.pressure.fix(201325) model.fs.fwh.desuperheat.inlet_1.enth_mol.fix(60000) model.fs.fwh.drain_mix.drain.flow_mol.fix(1) model.fs.fwh.drain_mix.drain.pressure.fix(201325) model.fs.fwh.drain_mix.drain.enth_mol.fix(20000) model.fs.fwh.cooling.inlet_2.flow_mol.fix(400) model.fs.fwh.cooling.inlet_2.pressure.fix(101325) model.fs.fwh.cooling.inlet_2.enth_mol.fix(3000) model.fs.fwh.condense.area.fix(1000) model.fs.fwh.condense.overall_heat_transfer_coefficient.fix(100) model.fs.fwh.desuperheat.area.fix(1000) model.fs.fwh.desuperheat.overall_heat_transfer_coefficient.fix(10) model.fs.fwh.cooling.area.fix(1000) model.fs.fwh.cooling.overall_heat_transfer_coefficient.fix(10) model.fs.fwh.initialize(optarg={"max_iter": 50}) assert (degrees_of_freedom(model) == 0) assert ( abs(pyo.value(model.fs.fwh.desuperheat.inlet_1.flow_mol[0]) - 98.335) < 0.01)
def test_build(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = SaponificationParameterBlock() m.fs.sj = StateJunction(default={"property_package": m.fs.properties}) assert hasattr(m.fs.sj, "inlet") assert len(m.fs.sj.inlet.vars) == 4 assert hasattr(m.fs.sj.inlet, "flow_vol") assert hasattr(m.fs.sj.inlet, "conc_mol_comp") assert hasattr(m.fs.sj.inlet, "temperature") assert hasattr(m.fs.sj.inlet, "pressure") assert hasattr(m.fs.sj, "outlet") assert len(m.fs.sj.outlet.vars) == 4 assert hasattr(m.fs.sj.outlet, "flow_vol") assert hasattr(m.fs.sj.outlet, "conc_mol_comp") assert hasattr(m.fs.sj.outlet, "temperature") assert hasattr(m.fs.sj.outlet, "pressure") assert degrees_of_freedom(m) == 0
def main(): # Create a Concrete Model as the top level object m = ConcreteModel() # Add a flowsheet object to the model m.fs = FlowsheetBlock(default={"dynamic": False}) # Add property packages to flowsheet library m.fs.thermo_params = thermo_props.HDAParameterBlock() m.fs.reaction_params = reaction_props.HDAReactionParameterBlock( default={"property_package": m.fs.thermo_params}) # Create unit models m.fs.M101 = Mixer( default={ "property_package": m.fs.thermo_params, "inlet_list": ["toluene_feed", "hydrogen_feed", "vapor_recycle"] }) m.fs.H101 = Heater( default={ "property_package": m.fs.thermo_params, "has_pressure_change": False, "has_phase_equilibrium": True }) m.fs.R101 = StoichiometricReactor( default={ "property_package": m.fs.thermo_params, "reaction_package": m.fs.reaction_params, "has_heat_of_reaction": True, "has_heat_transfer": True, "has_pressure_change": False }) m.fs.F101 = Flash( default={ "property_package": m.fs.thermo_params, "has_heat_transfer": True, "has_pressure_change": True }) m.fs.S101 = Splitter( default={ "property_package": m.fs.thermo_params, "ideal_separation": False, "outlet_list": ["purge", "recycle"] }) # This is needed to avoid pressure degeneracy in recylce loop m.fs.C101 = PressureChanger( default={ "property_package": m.fs.thermo_params, "compressor": True, "thermodynamic_assumption": ThermodynamicAssumption.isothermal }) m.fs.F102 = Flash( default={ "property_package": m.fs.thermo_params, "has_heat_transfer": True, "has_pressure_change": True }) m.fs.H101.control_volume.scaling_factor_energy = 1e-3 m.fs.R101.control_volume.scaling_factor_energy = 1e-3 m.fs.F101.control_volume.scaling_factor_energy = 1e-3 m.fs.C101.control_volume.scaling_factor_energy = 1e-3 m.fs.F102.control_volume.scaling_factor_energy = 1e-3 # Connect units m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet) m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet) m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet) m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet) m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet) m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.vapor_recycle) m.fs.s10 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet) TransformationFactory("network.expand_arcs").apply_to(m) # Set operating conditions m.fs.M101.toluene_feed.flow_mol_phase_comp[0, "Vap", "benzene"].fix(1e-5) m.fs.M101.toluene_feed.flow_mol_phase_comp[0, "Vap", "toluene"].fix(1e-5) m.fs.M101.toluene_feed.flow_mol_phase_comp[0, "Vap", "hydrogen"].fix(1e-5) m.fs.M101.toluene_feed.flow_mol_phase_comp[0, "Vap", "methane"].fix(1e-5) m.fs.M101.toluene_feed.flow_mol_phase_comp[0, "Liq", "benzene"].fix(1e-5) m.fs.M101.toluene_feed.flow_mol_phase_comp[0, "Liq", "toluene"].fix(0.30) m.fs.M101.toluene_feed.flow_mol_phase_comp[0, "Liq", "hydrogen"].fix(1e-5) m.fs.M101.toluene_feed.flow_mol_phase_comp[0, "Liq", "methane"].fix(1e-5) m.fs.M101.toluene_feed.temperature.fix(303.2) m.fs.M101.toluene_feed.pressure.fix(350000) m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, "Vap", "benzene"].fix(1e-5) m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, "Vap", "toluene"].fix(1e-5) m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, "Vap", "hydrogen"].fix(0.30) m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, "Vap", "methane"].fix(0.02) m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, "Liq", "benzene"].fix(1e-5) m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, "Liq", "toluene"].fix(1e-5) m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, "Liq", "hydrogen"].fix(1e-5) m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, "Liq", "methane"].fix(1e-5) m.fs.M101.hydrogen_feed.temperature.fix(303.2) m.fs.M101.hydrogen_feed.pressure.fix(350000) m.fs.H101.outlet.temperature.fix(600) m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1)) m.fs.R101.conv_constraint = Constraint( expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, "Vap", "toluene"] == ( m.fs.R101.inlet.flow_mol_phase_comp[0, "Vap", "toluene"] - m.fs.R101.outlet.flow_mol_phase_comp[0, "Vap", "toluene"])) m.fs.R101.conversion.fix(0.75) m.fs.R101.heat_duty.fix(0) m.fs.F101.vap_outlet.temperature.fix(325.0) m.fs.F101.deltaP.fix(0) m.fs.S101.split_fraction[0, "purge"].fix(0.2) m.fs.C101.outlet.pressure.fix(350000) m.fs.F102.vap_outlet.temperature.fix(375) m.fs.F102.deltaP.fix(-200000) # Define expressions # Product purity m.fs.purity = Expression( expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, "Vap", "benzene"] / (m.fs.F102.vap_outlet.flow_mol_phase_comp[0, "Vap", "benzene"] + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, "Vap", "toluene"])) # Operating cost ($/yr) m.fs.cooling_cost = Expression(expr=0.212e-7 * -m.fs.F101.heat_duty[0] + 0.212e-7 * -m.fs.R101.heat_duty[0]) m.fs.heating_cost = Expression(expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]) m.fs.operating_cost = Expression( expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))) print(degrees_of_freedom(m)) # Initialize Units # Define method for initialising each block def function(unit): unit.initialize(outlvl=1) # Create instance of sequential decomposition tool seq = SequentialDecomposition() seq.options.select_tear_method = "heuristic" seq.options.tear_method = "Wegstein" seq.options.iterLim = 5 # Determine tear stream and calculation order G = seq.create_graph(m) heu_result = seq.tear_set_arcs(G, method="heuristic") order = seq.calculation_order(G) # Display tear stream and calculation order for o in heu_result: print(o.name) for o in order: for oo in o: print(oo.name) # Set guesses for tear stream tear_guesses = { "flow_mol_phase_comp": { (0, "Vap", "benzene"): 1e-5, (0, "Vap", "toluene"): 1e-5, (0, "Vap", "hydrogen"): 0.30, (0, "Vap", "methane"): 0.02, (0, "Liq", "benzene"): 1e-5, (0, "Liq", "toluene"): 0.30, (0, "Liq", "hydrogen"): 1e-5, (0, "Liq", "methane"): 1e-5 }, "temperature": { 0: 303 }, "pressure": { 0: 350000 } } seq.set_guesses_for(m.fs.H101.inlet, tear_guesses) # Run sequential initialisation seq.run(m, function) # # Create a solver solver = SolverFactory('ipopt') solver.options = {'tol': 1e-6} solver.options = {'tol': 1e-6, 'max_iter': 5000} results = solver.solve(m, tee=True) # Print results print("M101 Outlet") m.fs.M101.outlet.display() print("H101 Outlet") m.fs.H101.outlet.display() print("R101 Outlet") m.fs.R101.outlet.display() print("F101") m.fs.F101.liq_outlet.display() m.fs.F101.vap_outlet.display() print("F102") m.fs.F102.liq_outlet.display() m.fs.F102.vap_outlet.display() print("Purge") m.fs.S101.purge.display() print("Purity:", value(m.fs.purity)) # Optimize process m.fs.objective = Objective(sense=minimize, expr=m.fs.operating_cost) # Decision variables m.fs.H101.outlet.temperature.unfix() m.fs.R101.heat_duty.unfix() m.fs.F101.vap_outlet.temperature.unfix() m.fs.F102.vap_outlet.temperature.unfix() m.fs.F102.deltaP.unfix() # Variable bounds m.fs.H101.outlet.temperature[0].setlb(500) m.fs.H101.outlet.temperature[0].setub(600) m.fs.R101.outlet.temperature[0].setlb(600) m.fs.R101.outlet.temperature[0].setub(800) m.fs.F101.vap_outlet.temperature[0].setlb(298.0) m.fs.F101.vap_outlet.temperature[0].setub(450.0) m.fs.F102.vap_outlet.temperature[0].setlb(298.0) m.fs.F102.vap_outlet.temperature[0].setub(450.0) m.fs.F102.vap_outlet.pressure[0].setlb(105000) m.fs.F102.vap_outlet.pressure[0].setub(110000) # Additional Constraints m.fs.overhead_loss = Constraint( expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, "Vap", "benzene"] <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, "Vap", "benzene"]) m.fs.product_flow = Constraint( expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, "Vap", "benzene"] >= 0.15) m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80) # Create a solver solver = SolverFactory('ipopt') solver.options = {'tol': 1e-6} solver.options = {'tol': 1e-6, 'max_iter': 5000} results = solver.solve(m, tee=True) # Print optimization results print() print("Optimal Solution") m.fs.operating_cost.display() m.fs.H101.heat_duty.display() m.fs.R101.heat_duty.display() m.fs.F101.heat_duty.display() m.fs.F102.heat_duty.display() # Print results print("M101 Outlet") m.fs.M101.outlet.display() print("H101 Outlet") m.fs.H101.outlet.display() print("R101 Outlet") m.fs.R101.outlet.display() print("F101") m.fs.F101.liq_outlet.display() m.fs.F101.vap_outlet.display() print("F102") m.fs.F102.liq_outlet.display() m.fs.F102.vap_outlet.display() print("Purge") m.fs.S101.purge.display() print("Recycle") m.fs.S101.recycle.display() print("Purity:", value(m.fs.purity)) # For testing purposes return (m, results)
def test_initialize_temperature(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = MethaneCombustionParameterBlock() m.fs.gibbs = GibbsReactor(default={ "property_package": m.fs.properties, "has_heat_transfer": True }) m.fs.gibbs.inlet.flow_mol_comp[0, "H2"].fix(10.0) m.fs.gibbs.inlet.flow_mol_comp[0, "N2"].fix(150.0) m.fs.gibbs.inlet.flow_mol_comp[0, "O2"].fix(40.0) m.fs.gibbs.inlet.flow_mol_comp[0, "CO2"].fix(1e-5) m.fs.gibbs.inlet.flow_mol_comp[0, "CH4"].fix(30.0) m.fs.gibbs.inlet.flow_mol_comp[0, "CO"].fix(1e-5) m.fs.gibbs.inlet.flow_mol_comp[0, "H2O"].fix(1e-5) m.fs.gibbs.inlet.flow_mol_comp[0, "NH3"].fix(1e-5) m.fs.gibbs.inlet.temperature[0].fix(1500.0) m.fs.gibbs.inlet.pressure[0].fix(101325.0) m.fs.gibbs.outlet.temperature[0].fix(2844.38) assert degrees_of_freedom(m) == 0 m.fs.gibbs.initialize(outlvl=5, optarg={'tol': 1e-6}, state_args={ 'temperature': 2844.38, 'pressure': 101325.0, 'flow_mol_comp': { 'CH4': 1e-5, 'CO': 23.0, 'CO2': 7.05, 'H2': 29.0, 'H2O': 41.0, 'N2': 150.0, 'NH3': 1e-5, 'O2': 1.0 } }) assert (pytest.approx( 0.0, abs=1e-2) == m.fs.gibbs.outlet.flow_mol_comp[0, "CH4"].value) assert (pytest.approx( 22.614, abs=1e-2) == m.fs.gibbs.outlet.flow_mol_comp[0, "CO"].value) assert (pytest.approx( 7.386, abs=1e-2) == m.fs.gibbs.outlet.flow_mol_comp[0, "CO2"].value) assert (pytest.approx( 28.806, abs=1e-2) == m.fs.gibbs.outlet.flow_mol_comp[0, "H2"].value) assert (pytest.approx( 41.194, abs=1e-2) == m.fs.gibbs.outlet.flow_mol_comp[0, "H2O"].value) assert (pytest.approx( 150.0, abs=1e-2) == m.fs.gibbs.outlet.flow_mol_comp[0, "N2"].value) assert (pytest.approx( 0.0, abs=1e-2) == m.fs.gibbs.outlet.flow_mol_comp[0, "NH3"].value) assert (pytest.approx( 0.710, abs=1e-2) == m.fs.gibbs.outlet.flow_mol_comp[0, "O2"].value) assert (pytest.approx(161882.3, abs=1e-2) == m.fs.gibbs.heat_duty[0].value) assert (pytest.approx(101325.0, abs=1e-2) == m.fs.gibbs.outlet.pressure[0].value)
def test_initialize(): """Make a turbine model and make sure it doesn't throw exception""" m = build_turbine_for_run_test() turb = m.fs.turb # Set the inlet of the turbine p = 2.4233e7 hin = iapws95_ph.htpx(T=880, P=p) m.fs.turb.inlet_split.inlet.enth_mol[0].fix(hin) m.fs.turb.inlet_split.inlet.flow_mol[0].fix(26000) m.fs.turb.inlet_split.inlet.pressure[0].fix(p) # Set the inlet of the ip section, which is disconnected # here to insert reheater p = 7.802e+06 hin = iapws95_ph.htpx(T=880, P=p) m.fs.turb.ip_stages[1].inlet.enth_mol[0].value = hin m.fs.turb.ip_stages[1].inlet.flow_mol[0].value = 25220.0 m.fs.turb.ip_stages[1].inlet.pressure[0].value = p for i, s in turb.hp_stages.items(): s.ratioP[:] = 0.88 s.efficiency_isentropic[:] = 0.9 for i, s in turb.ip_stages.items(): s.ratioP[:] = 0.85 s.efficiency_isentropic[:] = 0.9 for i, s in turb.lp_stages.items(): s.ratioP[:] = 0.82 s.efficiency_isentropic[:] = 0.9 turb.hp_split[4].split_fraction[0, "outlet_2"].fix(0.03) turb.hp_split[7].split_fraction[0, "outlet_2"].fix(0.03) turb.ip_split[5].split_fraction[0, "outlet_2"].fix(0.04) turb.ip_split[14].split_fraction[0, "outlet_2"].fix(0.04) turb.ip_split[14].split_fraction[0, "outlet_3"].fix(0.15) turb.lp_split[4].split_fraction[0, "outlet_2"].fix(0.04) turb.lp_split[7].split_fraction[0, "outlet_2"].fix(0.04) turb.lp_split[9].split_fraction[0, "outlet_2"].fix(0.04) turb.lp_split[11].split_fraction[0, "outlet_2"].fix(0.04) # Congiure with reheater for a full test turb.ip_stages[1].inlet.unfix() turb.inlet_split.inlet.flow_mol.unfix() turb.inlet_mix.use_equal_pressure_constraint() turb.initialize(outlvl=1) for t in m.fs.time: m.fs.reheat.inlet.flow_mol[t].value = \ value(turb.hp_split[7].outlet_1_state[t].flow_mol) m.fs.reheat.inlet.enth_mol[t].value = \ value(turb.hp_split[7].outlet_1_state[t].enth_mol) m.fs.reheat.inlet.pressure[t].value = \ value(turb.hp_split[7].outlet_1_state[t].pressure) m.fs.reheat.initialize(outlvl=4) def reheat_T_rule(b, t): return m.fs.reheat.control_volume.properties_out[t].temperature == 880 m.fs.reheat.temperature_out_equation = Constraint( m.fs.reheat.flowsheet().config.time, rule=reheat_T_rule) TransformationFactory("network.expand_arcs").apply_to(m) m.fs.turb.outlet_stage.control_volume.properties_out[0].pressure.fix() assert (degrees_of_freedom(m) == 0) solver.solve(m, tee=True) for c in active_equalities(m): assert (abs(c.body() - c.lower) < 1e-4) return m
def initialize(blk, flow_vol=None, temperature=None, pressure=None, conc_mol_comp=None, state_vars_fixed=False, hold_state=False, outlvl=0, solver='ipopt', optarg={'tol': 1e-8}): ''' Initialisation routine for property package. Keyword Arguments: flow_mol_comp : value at which to initialize component flows (default=None) pressure : value at which to initialize pressure (default=None) temperature : value at which to initialize temperature (default=None) outlvl : sets output level of initialisation routine * 0 = no output (default) * 1 = return solver state for each step in routine * 2 = include solver output infomation (tee=True) state_vars_fixed: Flag to denote if state vars have already been fixed. - True - states have already been fixed by the control volume 1D. Control volume 0D does not fix the state vars, so will be False if this state block is used with 0D blocks. - False - states have not been fixed. The state block will deal with fixing/unfixing. optarg : solver options dictionary object (default=None) solver : str indicating whcih solver to use during initialization (default = 'ipopt') hold_state : flag indicating whether the initialization routine should unfix any state variables fixed during initialization (default=False). - True - states varaibles are not unfixed, and a dict of returned containing flags for which states were fixed during initialization. - False - state variables are unfixed after initialization by calling the relase_state method Returns: If hold_states is True, returns a dict containing flags for which states were fixed during initialization. ''' # Deactivate the constraints specific for outlet block i.e. # when defined state is False for k in blk.keys(): if blk[k].config.defined_state is False: blk[k].conc_water_eqn.deactivate() if state_vars_fixed is False: # Fix state variables if not already fixed Fflag = {} Pflag = {} Tflag = {} Cflag = {} for k in blk.keys(): # Fix state vars if not already fixed if blk[k].flow_vol.fixed is True: Fflag[k] = True else: Fflag[k] = False if flow_vol is None: blk[k].flow_vol.fix(1.0) else: blk[k].flow_vol.fix(flow_vol) for j in blk[k]._params.component_list: if blk[k].conc_mol_comp[j].fixed is True: Cflag[k, j] = True else: Cflag[k, j] = False if conc_mol_comp is None: if j == "H2O": blk[k].conc_mol_comp[j].fix(55388.0) else: blk[k].conc_mol_comp[j].fix(100.0) else: blk[k].conc_mol_comp[j].fix(conc_mol_comp[j]) if blk[k].pressure.fixed is True: Pflag[k] = True else: Pflag[k] = False if pressure is None: blk[k].pressure.fix(101325.0) else: blk[k].pressure.fix(pressure) if blk[k].temperature.fixed is True: Tflag[k] = True else: Tflag[k] = False if temperature is None: blk[k].temperature.fix(298.15) else: blk[k].temperature.fix(temperature) # If input block, return flags, else release state flags = {"Fflag": Fflag, "Pflag": Pflag, "Tflag": Tflag, "Cflag": Cflag} else: # Check when the state vars are fixed already result in dof 0 for k in blk.keys(): if degrees_of_freedom(blk[k]) != 0: raise Exception("State vars fixed but degrees of freedom " "for state block is not zero during " "initialization.") opt = SolverFactory(solver) opt.options = optarg # Post initialization reactivate constraints specific for # all blocks other than the inlet for k in blk.keys(): if not blk[k].config.defined_state: blk[k].conc_water_eqn.activate() if state_vars_fixed is False: if hold_state is True: return flags else: blk.release_state(flags) if outlvl > 0: if outlvl > 0: _log.info('{} Initialisation Complete.'.format(blk.name))
def initialize(blk, flow_mol=None, mole_frac=None, temperature=None, pressure=None, state_vars_fixed=False, hold_state=False, outlvl=1, solver='ipopt', optarg={'tol': 1e-8}): """ Initialisation routine for property package. Keyword Arguments: flow_mol_comp : value at which to initialize component flows (default=None) pressure : value at which to initialize pressure (default=None) temperature : value at which to initialize temperature (default=None) outlvl : sets output level of initialisation routine * 0 = no output (default) * 1 = return solver state for each step in routine * 2 = include solver output infomation (tee=True) optarg : solver options dictionary object (default=None) state_vars_fixed: Flag to denote if state vars have already been fixed. - True - states have already been fixed by the control volume 1D. Control volume 0D does not fix the state vars, so will be False if this state block is used with 0D blocks. - False - states have not been fixed. The state block will deal with fixing/unfixing. solver : str indicating whcih solver to use during initialization (default = 'ipopt') hold_state : flag indicating whether the initialization routine should unfix any state variables fixed during initialization (default=False). - True - states varaibles are not unfixed, and a dict of returned containing flags for which states were fixed during initialization. - False - state variables are unfixed after initialization by calling the relase_state method Returns: If hold_states is True, returns a dict containing flags for which states were fixed during initialization. """ _log.info('Starting {} initialisation'.format(blk.name)) # Deactivate the constraints specific for outlet block i.e. # when defined state is False for k in blk.keys(): if blk[k].config.defined_state is False: blk[k].sum_mole_frac_out.deactivate() # Fix state variables if not already fixed if state_vars_fixed is False: Fflag = {} Xflag = {} Pflag = {} Tflag = {} for k in blk.keys(): if blk[k].flow_mol.fixed is True: Fflag[k] = True else: Fflag[k] = False if flow_mol is None: blk[k].flow_mol.fix(1.0) else: blk[k].flow_mol.fix(flow_mol) for j in blk[k]._params.component_list: if blk[k].mole_frac[j].fixed is True: Xflag[k, j] = True else: Xflag[k, j] = False if mole_frac is None: blk[k].mole_frac[j].fix( 1 / len(blk[k]._params.component_list)) else: blk[k].mole_frac[j].fix(mole_frac[j]) if blk[k].pressure.fixed is True: Pflag[k] = True else: Pflag[k] = False if pressure is None: blk[k].pressure.fix(101325.0) else: blk[k].pressure.fix(pressure) if blk[k].temperature.fixed is True: Tflag[k] = True else: Tflag[k] = False if temperature is None: blk[k].temperature.fix(325) else: blk[k].temperature.fix(temperature) # --------------------------------------------------------------------- # If input block, return flags, else release state flags = { "Fflag": Fflag, "Xflag": Xflag, "Pflag": Pflag, "Tflag": Tflag } else: # Check when the state vars are fixed already result in dof 0 for k in blk.keys(): if degrees_of_freedom(blk[k]) != 0: raise Exception("State vars fixed but degrees of freedom " "for state block is not zero during " "initialization.") # Set solver options if outlvl > 1: stee = True else: stee = False if optarg is None: sopt = {'tol': 1e-8} else: sopt = optarg opt = SolverFactory('ipopt') opt.options = sopt # --------------------------------------------------------------------- # If present, initialize bubble and dew point calculations for k in blk.keys(): if hasattr(blk[k], "eq_temperature_bubble"): calculate_variable_from_constraint( blk[k].temperature_bubble, blk[k].eq_temperature_bubble) if hasattr(blk[k], "eq_temperature_dew"): calculate_variable_from_constraint(blk[k].temperature_dew, blk[k].eq_temperature_dew) if hasattr(blk[k], "eq_pressure_bubble"): calculate_variable_from_constraint(blk[k].pressure_bubble, blk[k].eq_pressure_bubble) if hasattr(blk[k], "eq_pressure_dew"): calculate_variable_from_constraint(blk[k].pressure_dew, blk[k].eq_pressure_dew) if outlvl > 0: _log.info("Dew and bubble points initialization for " "{} completed".format(blk.name)) # --------------------------------------------------------------------- # If flash, initialize T1 and Teq for k in blk.keys(): if blk[k].config.has_phase_equilibrium: blk[k]._t1.value = max(blk[k].temperature.value, blk[k].temperature_bubble.value) blk[k]._teq.value = min(blk[k]._t1.value, blk[k].temperature_dew.value) if outlvl > 0: _log.info("Equilibrium temperature initialization for " "{} completed".format(blk.name)) # --------------------------------------------------------------------- # Initialize flow rates and compositions # TODO : This will need ot be generalised more when we move to a # modular implementation for k in blk.keys(): if blk[k]._params.config.valid_phase == "Liq": blk[k].flow_mol_phase['Liq'].value = \ blk[k].flow_mol.value for j in blk[k]._params.component_list: blk[k].mole_frac_phase['Liq', j].value = \ blk[k].mole_frac[j].value elif blk[k]._params.config.valid_phase == "Vap": blk[k].flow_mol_phase['Vap'].value = \ blk[k].flow_mol.value for j in blk[k]._params.component_list: blk[k].mole_frac_phase['Vap', j].value = \ blk[k].mole_frac[j].value else: # Seems to work best with default values for phase flows for j in blk[k]._params.component_list: blk[k].mole_frac_phase['Vap', j].value = \ blk[k].mole_frac[j].value blk[k].mole_frac_phase['Liq', j].value = \ blk[k].mole_frac[j].value calculate_variable_from_constraint( blk[k].pressure_sat[j], blk[k].eq_pressure_sat[j]) # --------------------------------------------------------------------- # Solve phase equilibrium constraints for k in blk.keys(): for c in blk[k].component_objects(Constraint): # Deactivate all property constraints if c.local_name not in ("total_flow_balance", "component_flow_balances", "equilibrium_constraint", "sum_mole_frac", "_t1_constraint", "_teq_constraint", "eq_pressure_dew", "eq_pressure_bubble", "eq_temperature_dew", "eq_temperature_bubble", "eq_pressure_sat"): c.deactivate() results = solve_indexed_blocks(opt, [blk], tee=stee) if outlvl > 0: if results.solver.termination_condition \ == TerminationCondition.optimal: _log.info("Phase state initialization for " "{} completed".format(blk.name)) else: _log.warning("Phase state initialization for " "{} failed".format(blk.name)) # --------------------------------------------------------------------- # Initialize other properties for k in blk.keys(): for c in blk[k].component_objects(Constraint): # Activate all constraints except sum_mole_frac_out if c.local_name not in ("sum_mole_frac_out"): c.activate() if outlvl > 0: if results.solver.termination_condition \ == TerminationCondition.optimal: _log.info("Property initialization for " "{} completed".format(blk.name)) else: _log.warning("Property initialization for " "{} failed".format(blk.name)) # --------------------------------------------------------------------- # Return state to initial conditions for k in blk.keys(): if (blk[k].config.defined_state is False): blk[k].sum_mole_frac_out.activate() if state_vars_fixed is False: if hold_state is True: return flags else: blk.release_state(flags) if outlvl > 0: _log.info("Initialisation completed for {}".format(blk.name))
def initialize(self, *args, **kwargs): config = self.config # sorter ref to config for less line splitting sp = StoreSpec.value_isfixed_isactive(only_fixed=True) istate = to_json(self, return_dict=True, wts=sp) # the initilization here isn't straight forward since the heat exchanger # may have 3 stages and they are countercurrent. For simplicity each # stage in initialized with the same cooling water inlet conditions then # the whole feedwater heater is solved together. There are more robust # approaches which can be implimented if the need arises. # initialize desuperheat if include if config.has_desuperheat: if config.has_drain_cooling: _set_port(self.desuperheat.inlet_2, self.cooling.inlet_2) else: _set_port(self.desuperheat.inlet_2, self.condense.inlet_2) self.desuperheat.initialize(*args, **kwargs) self.desuperheat.inlet_1.flow_mol.unfix() if config.has_drain_mixer: _set_port(self.drain_mix.steam, self.desuperheat.outlet_1) else: _set_port(self.condense.inlet_1, self.desuperheat.outlet_1) # fix the steam and fwh inlet for init self.desuperheat.inlet_1.fix() self.desuperheat.inlet_1.flow_mol.unfix() #unfix for extract calc # initialize mixer if included if config.has_drain_mixer: self.drain_mix.steam.fix() self.drain_mix.drain.fix() self.drain_mix.outlet.unfix() self.drain_mix.initialize(*args, **kwargs) _set_port(self.condense.inlet_1, self.drain_mix.outlet) if config.has_desuperheat: self.drain_mix.steam.unfix() else: self.drain_mix.steam.flow_mol.unfix() # Initialize condense section if config.has_drain_cooling: _set_port(self.condense.inlet_2, self.cooling.inlet_2) self.cooling.inlet_2.fix() else: self.condense.inlet_2.fix() self.condense.initialize(*args, **kwargs) # Initialize drain cooling if included if config.has_drain_cooling: _set_port(self.cooling.inlet_1, self.condense.outlet_1) self.cooling.initialize(*args, **kwargs) # Solve all together outlvl = kwargs.get("outlvl", 0) opt = SolverFactory(kwargs.get("solver", "ipopt")) opt.options = kwargs.get("oparg", {}) tee = True if outlvl >= 3 else False assert(degrees_of_freedom(self)==0) results = opt.solve(self, tee=tee) if results.solver.termination_condition == TerminationCondition.optimal: if outlvl >= 2: _log.info('{} Initialization Complete.'.format(self.name)) else: _log.warning('{} Initialization Failed.'.format(self.name)) from_json(self, sd=istate, wts=sp)
def test_initialize_total_flow(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = SaponificationParameterBlock() m.fs.sb = Separator(default={ "property_package": m.fs.properties, "ideal_separation": False, "split_basis": SplittingType.totalFlow}) m.fs.sb.inlet.flow_vol.fix(1.0e-03) m.fs.sb.inlet.conc_mol_comp[0, "H2O"].fix(55388.0) m.fs.sb.inlet.conc_mol_comp[0, "NaOH"].fix(100.0) m.fs.sb.inlet.conc_mol_comp[0, "EthylAcetate"].fix(100.0) m.fs.sb.inlet.conc_mol_comp[0, "SodiumAcetate"].fix(0.0) m.fs.sb.inlet.conc_mol_comp[0, "Ethanol"].fix(0.0) m.fs.sb.inlet.temperature.fix(303.15) m.fs.sb.inlet.pressure.fix(101325.0) m.fs.sb.split_fraction[0, "outlet_1"].fix(0.2) assert degrees_of_freedom(m) == 0 m.fs.sb.initialize(outlvl=5, optarg={'tol': 1e-6}) assert (pytest.approx(0.2, abs=1e-3) == m.fs.sb.split_fraction[0, "outlet_1"].value) assert (pytest.approx(0.8, abs=1e-3) == m.fs.sb.split_fraction[0, "outlet_2"].value) assert (pytest.approx(101325.0, abs=1e-2) == m.fs.sb.outlet_1.pressure[0].value) assert (pytest.approx(303.15, abs=1e-2) == m.fs.sb.outlet_1.temperature[0].value) assert (pytest.approx(2e-4, abs=1e-6) == m.fs.sb.outlet_1.flow_vol[0].value) assert (pytest.approx(55388.0, abs=1e-2) == m.fs.sb.outlet_1.conc_mol_comp[0, "H2O"].value) assert (pytest.approx(100.0, abs=1e-2) == m.fs.sb.outlet_1.conc_mol_comp[0, "NaOH"].value) assert (pytest.approx(100.0, abs=1e-2) == m.fs.sb.outlet_1.conc_mol_comp[0, "EthylAcetate"].value) assert (pytest.approx(0.0, abs=1e-2) == m.fs.sb.outlet_1.conc_mol_comp[0, "SodiumAcetate"].value) assert (pytest.approx(0.0, abs=1e-2) == m.fs.sb.outlet_1.conc_mol_comp[0, "Ethanol"].value) assert (pytest.approx(101325.0, abs=1e-2) == m.fs.sb.outlet_2.pressure[0].value) assert (pytest.approx(303.15, abs=1e-2) == m.fs.sb.outlet_2.temperature[0].value) assert (pytest.approx(8e-4, abs=1e-6) == m.fs.sb.outlet_2.flow_vol[0].value) assert (pytest.approx(55388.0, abs=1e-2) == m.fs.sb.outlet_2.conc_mol_comp[0, "H2O"].value) assert (pytest.approx(100.0, abs=1e-2) == m.fs.sb.outlet_2.conc_mol_comp[0, "NaOH"].value) assert (pytest.approx(100.0, abs=1e-2) == m.fs.sb.outlet_2.conc_mol_comp[0, "EthylAcetate"].value) assert (pytest.approx(0.0, abs=1e-2) == m.fs.sb.outlet_2.conc_mol_comp[0, "SodiumAcetate"].value) assert (pytest.approx(0.0, abs=1e-2) == m.fs.sb.outlet_2.conc_mol_comp[0, "Ethanol"].value)
def initialize(blk, flow_mol_comp=None, temperature=None, pressure=None, hold_state=False, outlvl=0, state_vars_fixed=False, solver='ipopt', optarg={'tol': 1e-8}): ''' Initialisation routine for property package. Keyword Arguments: flow_mol_comp : value at which to initialize component flows (default=None) pressure : value at which to initialize pressure (default=None) temperature : value at which to initialize temperature (default=None) outlvl : sets output level of initialisation routine * 0 = no output (default) * 1 = return solver state for each step in routine * 2 = include solver output infomation (tee=True) state_vars_fixed: Flag to denote if state vars have already been fixed. - True - states have already been fixed by the control volume 1D. Control volume 0D does not fix the state vars, so will be False if this state block is used with 0D blocks. - False - states have not been fixed. The state block will deal with fixing/unfixing. optarg : solver options dictionary object (default=None) solver : str indicating whcih solver to use during initialization (default = 'ipopt') hold_state : flag indicating whether the initialization routine should unfix any state variables fixed during initialization (default=False). - True - states varaibles are not unfixed, and a dict of returned containing flags for which states were fixed during initialization. - False - state variables are unfixed after initialization by calling the relase_state method Returns: If hold_states is True, returns a dict containing flags for which states were fixed during initialization. ''' if state_vars_fixed is False: # Fix state variables if not already fixed Fcflag = {} Pflag = {} Tflag = {} for k in blk.keys(): for j in blk[k]._params.component_list: if blk[k].flow_mol_comp[j].fixed is True: Fcflag[k, j] = True else: Fcflag[k, j] = False if flow_mol_comp is None: blk[k].flow_mol_comp[j].fix(1.0) else: blk[k].flow_mol_comp[j].fix(flow_mol_comp[j]) if blk[k].pressure.fixed is True: Pflag[k] = True else: Pflag[k] = False if pressure is None: blk[k].pressure.fix(101325.0) else: blk[k].pressure.fix(pressure) if blk[k].temperature.fixed is True: Tflag[k] = True else: Tflag[k] = False if temperature is None: blk[k].temperature.fix(1500.0) else: blk[k].temperature.fix(temperature) for j in blk[k]._params.component_list: blk[k].mole_frac[j] = \ (value(blk[k].flow_mol_comp[j]) / sum(value(blk[k].flow_mol_comp[i]) for i in blk[k]._params.component_list)) # If input block, return flags, else release state flags = {"Fcflag": Fcflag, "Pflag": Pflag, "Tflag": Tflag} else: # Check when the state vars are fixed already result in dof 0 for k in blk.keys(): if degrees_of_freedom(blk[k]) != 0: raise Exception("State vars fixed but degrees of freedom " "for state block is not zero during " "initialization.") # Set solver options if outlvl > 1: stee = True else: stee = False opt = SolverFactory(solver) opt.options = optarg # --------------------------------------------------------------------- # Initialise values for k in blk.keys(): for j in blk[k]._params.component_list: if hasattr(blk[k], "cp_shomate_eqn"): calculate_variable_from_constraint( blk[k].cp_mol_comp[j], blk[k].cp_shomate_eqn[j]) if hasattr(blk[k], "enthalpy_shomate_eqn"): calculate_variable_from_constraint( blk[k].enth_mol_phase_comp["Vap", j], blk[k].enthalpy_shomate_eqn[j]) if hasattr(blk[k], "entropy_shomate_eqn"): calculate_variable_from_constraint( blk[k].entr_mol_phase_comp["Vap", j], blk[k].entropy_shomate_eqn[j]) if hasattr(blk[k], "partial_gibbs_energy_eqn"): calculate_variable_from_constraint( blk[k].gibbs_mol_phase_comp["Vap", j], blk[k].partial_gibbs_energy_eqn[j]) if hasattr(blk[k], "ideal_gas"): calculate_variable_from_constraint( blk[k].dens_mol_phase["Vap"], blk[k].ideal_gas) if hasattr(blk[k], "mixture_heat_capacity_eqn"): calculate_variable_from_constraint( blk[k].cp_mol, blk[k].mixture_heat_capacity_eqn) if hasattr(blk[k], "mixture_enthalpy_eqn"): calculate_variable_from_constraint(blk[k].enth_mol, blk[k].mixture_enthalpy_eqn) if hasattr(blk[k], "mixture_entropy_eqn"): calculate_variable_from_constraint(blk[k].entr_mol, blk[k].mixture_entropy_eqn) if hasattr(blk[k], "total_flow_eqn"): calculate_variable_from_constraint(blk[k].flow_mol, blk[k].total_flow_eqn) if hasattr(blk[k], "mixture_gibbs_eqn"): calculate_variable_from_constraint(blk[k].gibbs_mol, blk[k].mixture_gibbs_eqn) results = solve_indexed_blocks(opt, blk, tee=stee) if outlvl > 0: if results.solver.termination_condition \ == TerminationCondition.optimal: _log.info('{} Initialisation Step 1 Complete.'.format( blk.name)) else: _log.warning('{} Initialisation Step 1 Failed.'.format( blk.name)) # --------------------------------------------------------------------- if outlvl > 0: if outlvl > 0: _log.info('{} Initialisation Complete.'.format(blk.name)) if state_vars_fixed is False: if hold_state is True: return flags else: blk.release_state(flags)
def initialize(self, state_args={}, outlvl=0, solver='ipopt', optarg={ 'tol': 1e-6, 'max_iter': 30 }): """ Initialize the turbine stage model. This deactivates the specialized constraints, then does the isentropic turbine initialization, then reactivates the constraints and solves. Args: state_args (dict): Initial state for property initialization outlvl (int): Amount of output (0 to 3) 0 is lowest solver (str): Solver to use for initialization optarg (dict): Solver arguments dictionary """ stee = True if outlvl >= 3 else False # sp is what to save to make sure state after init is same as the start # saves value, fixed, and active state, doesn't load originally free # values, this makes sure original problem spec is same but initializes # the values of free vars sp = StoreSpec.value_isfixed_isactive(only_fixed=True) istate = to_json(self, return_dict=True, wts=sp) # fix inlet and free outlet for t in self.flowsheet().config.time: for k, v in self.inlet.vars.items(): v[t].fix() for k, v in self.outlet.vars.items(): v[t].unfix() # If there isn't a good guess for efficiency or outlet pressure # provide something reasonable. eff = self.efficiency_isentropic[t] eff.fix( eff.value if value(eff) > 0.3 and value(eff) < 1.0 else 0.8) # for outlet pressure try outlet pressure, pressure ratio, delta P, # then if none of those look reasonable use a pressure ratio of 0.8 # to calculate outlet pressure Pout = self.outlet.pressure[t] Pin = self.inlet.pressure[t] prdp = value((self.deltaP[t] - Pin) / Pin) if self.deltaP[t].fixed: Pout.value = value(Pin - Pout) if self.ratioP[t].fixed: Pout.value = value(self.ratioP[t] * Pin) if value(Pout / Pin) > 0.99 or value(Pout / Pin) < 0.1: if value(self.ratioP[t]) < 0.99 and value( self.ratioP[t]) > 0.1: Pout.fix(value(Pin * self.ratioP[t])) elif prdp < 0.99 and prdp > 0.1: Pout.fix(value(prdp * Pin)) else: Pout.fix(value(Pin * 0.8)) else: Pout.fix() self.deltaP[t] = value(Pout - Pin) self.ratioP[t] = value(Pout / Pin) self.deltaP[:].unfix() self.ratioP[:].unfix() for t in self.flowsheet().config.time: self.properties_isentropic[t].pressure.value = \ value(self.outlet.pressure[t]) self.properties_isentropic[t].flow_mol.value = \ value(self.inlet.flow_mol[t]) self.properties_isentropic[t].enth_mol.value = \ value(self.inlet.enth_mol[t]*0.95) self.outlet.flow_mol[t].value = \ value(self.inlet.flow_mol[t]) self.outlet.enth_mol[t].value = \ value(self.inlet.enth_mol[t]*0.95) # Make sure the initialization problem has no degrees of freedom # This shouldn't happen here unless there is a bug in this dof = degrees_of_freedom(self) try: assert (dof == 0) except: _log.exception("degrees_of_freedom = {}".format(dof)) raise # one bad thing about reusing this is that the log messages aren't # really compatible with being nested inside another initialization super(TurbineStageData, self).initialize(state_args=state_args, outlvl=outlvl, solver=solver, optarg=optarg) # reload original spec from_json(self, sd=istate, wts=sp)