def basic_model(cb=delta_temperature_lmtd_callback): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock() m.fs.unit = HeatExchanger(default={ "shell": {"property_package": m.fs.properties}, "tube": {"property_package": m.fs.properties}, "delta_temperature_callback": cb, "flow_pattern": HeatExchangerFlowPattern.countercurrent}) # Set inputs m.fs.unit.inlet_1.flow_mol[0].fix(100) m.fs.unit.inlet_1.enth_mol[0].fix(4000) m.fs.unit.inlet_1.pressure[0].fix(101325) m.fs.unit.inlet_2.flow_mol[0].fix(100) m.fs.unit.inlet_2.enth_mol[0].fix(3500) m.fs.unit.inlet_2.pressure[0].fix(101325) m.fs.unit.area.fix(1000) m.fs.unit.overall_heat_transfer_coefficient.fix(100) assert degrees_of_freedom(m) == 0 m.fs.unit.get_costing() m.fs.unit.initialize() return m
def test_heater_tpx_lg_total_2(): """Test liquid/vapor form with T-P-x state vars and total mass balances. In this case you end up with all vapor at the end. """ m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock( default={ "phase_presentation": iapws95.PhaseType.LG, "state_vars": iapws95.StateVars.TPX }) m.fs.heater = Heater( default={ "property_package": m.fs.properties, "material_balance_type": MaterialBalanceType.componentTotal }) m.fs.heater.inlet.temperature.fix(326.1667075078748) m.fs.heater.inlet.vapor_frac.fix(0.0) m.fs.heater.inlet.flow_mol.fix(100) m.fs.heater.inlet.pressure.fix(101325) m.fs.heater.heat_duty[0].fix(100 * 50000) prop_in = m.fs.heater.control_volume.properties_in[0] prop_out = m.fs.heater.control_volume.properties_out[0] prop_out.temperature = 400 prop_out.vapor_frac = 0.9 m.fs.heater.initialize(outlvl=5) assert degrees_of_freedom(m) == 0 solver.solve(m, tee=True) assert abs(value(prop_out.temperature) - 534.6889772922356) <= 2e-4 assert abs(value(prop_in.phase_frac["Liq"]) - 1) <= 1e-2 assert abs(value(prop_out.phase_frac["Liq"]) - 0) <= 1e-2 assert abs(value(prop_in.phase_frac["Vap"]) - 0) <= 1e-2 assert abs(value(prop_out.phase_frac["Vap"]) - 1) <= 1e-2
def test_heater_ph_lg_total(): """Test liquid/vapor form with P-H state vars and total mass balances """ m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock( default={"phase_presentation": iapws95.PhaseType.LG}) m.fs.heater = Heater( default={ "property_package": m.fs.properties, "material_balance_type": MaterialBalanceType.componentTotal }) 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 value(prop_in.temperature) == pytest.approx(326.166707, rel=1e-5) assert value(prop_out.temperature) == pytest.approx(373.12429, rel=1e-5) assert value(prop_in.phase_frac["Liq"]) == pytest.approx(1, rel=1e-5) assert value(prop_out.phase_frac["Liq"]) == pytest.approx(0.5953219, rel=1e-5) assert value(prop_in.phase_frac["Vap"]) == pytest.approx(0, abs=1e-5) assert value(prop_out.phase_frac["Vap"]) == pytest.approx(0.4046781, rel=1e-4)
def build_turbine(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock() m.fs.turb = TurbineInletStage( default={"property_package": m.fs.properties}) return m
def test_heater_ph_l_phase(): """Test liquid phase only form with P-H state vars and phase mass balances """ m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock( default={"phase_presentation": iapws95.PhaseType.L}) m.fs.heater = Heater( default={ "property_package": m.fs.properties, "material_balance_type": MaterialBalanceType.componentPhase }) m.fs.heater.inlet.enth_mol.fix(3000) m.fs.heater.inlet.flow_mol.fix(100) m.fs.heater.inlet.pressure.fix(101325) m.fs.heater.heat_duty[0].fix(100 * 1000) 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) - 312.88896252921666) <= 1e-4 assert abs(value(prop_out.temperature) - 326.166707507874) <= 1e-4 assert abs(value(prop_in.phase_frac["Liq"]) - 1) <= 1e-6 assert abs(value(prop_out.phase_frac["Liq"]) - 1) <= 1e-6 assert abs(value(prop_in.phase_frac["Vap"]) - 0) <= 1e-6 assert abs(value(prop_out.phase_frac["Vap"]) - 0) <= 1e-6
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 test_condenser_steady(): m = pyo.ConcreteModel() m.fs = idaes.core.FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock() m.fs.unit = HelmNtuCondenser( default={ "dynamic": False, "shell": { "has_pressure_change": False, "property_package": m.fs.properties, }, "tube": { "has_pressure_change": False, "property_package": m.fs.properties, }, }) m.fs.unit.shell_inlet.flow_mol.fix(100) m.fs.unit.shell_inlet.pressure[:] = 9000 m.fs.unit.shell_inlet.enth_mol.fix(30000) m.fs.unit.tube_inlet.flow_mol.fix(1200) m.fs.unit.tube_inlet.pressure.fix(101325) m.fs.unit.tube_inlet.enth_mol.fix(1800) m.fs.unit.area.fix(1000) m.fs.unit.overall_heat_transfer_coefficient.fix(500) m.fs.unit.initialize(unfix='pressure') solver.solve(m) assert (pyo.value(m.fs.unit.shell_inlet.pressure[0]) == pytest.approx( 14036.3360, rel=1e-2))
def iapws_underwood(self): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock() m.fs.unit = HeatExchanger( default={ "shell": { "property_package": m.fs.properties }, "tube": { "property_package": m.fs.properties }, "delta_temperature_callback": delta_temperature_underwood_callback, "flow_pattern": HeatExchangerFlowPattern.countercurrent }) m.fs.unit.inlet_1.flow_mol[0].fix(100) m.fs.unit.inlet_1.enth_mol[0].fix(4000) m.fs.unit.inlet_1.pressure[0].fix(101325) m.fs.unit.inlet_2.flow_mol[0].fix(100) m.fs.unit.inlet_2.enth_mol[0].fix(3500) m.fs.unit.inlet_2.pressure[0].fix(101325) m.fs.unit.area.fix(1000) m.fs.unit.overall_heat_transfer_coefficient.fix(100) return m
def create_model_steady_state(f=100, p=5e5, h=5e4): """ Create a steady state heater model. """ m = pyo.ConcreteModel(name="Dynamic Heater Test") m.fs = FlowsheetBlock(default={"dynamic": False}) # Create a property parameter block m.fs.prop_water = iapws95.Iapws95ParameterBlock( default={"phase_presentation": iapws95.PhaseType.MIX}) m.fs.heater = Heater( default={ "has_holdup": False, "has_pressure_change": True, "material_balance_type": MaterialBalanceType.componentTotal, "property_package": m.fs.prop_water }) m.fs.heater.inlet.enth_mol.fix(50000) m.fs.heater.inlet.pressure.fix(5e5) m.fs.heater.inlet.flow_mol.fix(100) m.fs.heater.heat_duty.fix(0) m.fs.heater.deltaP.fix(0) m.fs.heater.initialize() solver = pyo.SolverFactory("ipopt") solver.options = {'tol': 1e-6, 'linear_solver': "ma27", 'max_iter': 25} return m, solver
def test_deprecated_delta_T_method(caplog): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.prop_steam = iapws95.Iapws95ParameterBlock() m.fs.prop_fluegas = FlueGasParameterBlock() caplog.clear() m.fs.unit = BoilerHeatExchanger( default={ "delta_temperature_callback": delta_temperature_lmtd_callback, "tube": { "property_package": m.fs.prop_steam }, "shell": { "property_package": m.fs.prop_fluegas }, "has_pressure_change": True, "has_holdup": True, "delta_T_method": HeatExchangerFlowPattern.countercurrent, "tube_arrangement": TubeArrangement.inLine, "side_1_water_phase": "Liq", "has_radiation": True, }) n_warn = 0 n_depreacted = 0 for record in caplog.records: if record.levelno == idaeslog.WARNING: n_warn += 1 if "deprecated" in record.msg: n_depreacted += 1 assert n_warn == 1 assert n_depreacted == 1 assert m.fs.unit.config.flow_pattern == HeatExchangerFlowPattern.countercurrent
def build_turbine_for_run_test(): m = pyo.ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock() # roughly based on NETL baseline studies m.fs.turb = HelmTurbineMultistage( 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 tu(delta_temperature_callback=delta_temperature_underwood_tune_callback): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = PhysicalParameterTestBlock() m.fs.prop_steam = iapws95.Iapws95ParameterBlock() m.fs.prop_fluegas = FlueGasParameterBlock() m.fs.unit = BoilerHeatExchanger( default={ "delta_temperature_callback": delta_temperature_callback, "tube": { "property_package": m.fs.prop_steam }, "shell": { "property_package": m.fs.prop_fluegas }, "has_pressure_change": True, "has_holdup": False, "flow_pattern": HeatExchangerFlowPattern.countercurrent, "tube_arrangement": TubeArrangement.inLine, "side_1_water_phase": "Liq", "has_radiation": True, }) assert_units_consistent(m)
def test_fwh_model(): model = pyo.ConcreteModel() model.fs = FlowsheetBlock(default={ "dynamic": False, "default_property_package": iapws95.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 concrete_tube(self): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock( default={"phase_presentation": iapws95.PhaseType.LG}) m.fs.unit = ConcreteTubeSide( default={ "property_package": m.fs.properties, "flow_type": HeatExchangerFlowPattern.cocurrent }) m.fs.unit.d_tube_outer.fix(0.01167) m.fs.unit.d_tube_inner.fix(0.01167) m.fs.unit.tube_length.fix(4.85) m.fs.unit.tube_heat_transfer_coefficient.fix(500) m.fs.unit.tube_inlet.flow_mol[0].fix(1) # mol/s m.fs.unit.tube_inlet.pressure[0].fix(101325) # Pa m.fs.unit.tube_inlet.enth_mol[0].\ fix(iapws95.htpx(300*pyunits.K, 101325*pyunits.Pa)) # K m.fs.unit.temperature_wall[0, :].fix(1000) return m
def get_initialized_model(self): """ Returns an initialized model for the PressureChanger unit model convergence evaluation Returns ------- Pyomo model : returns a pyomo model of the PressureChanger unit """ m = pe.ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.props = pp.Iapws95ParameterBlock() m.fs.pc = PressureChanger( default={ "property_package": m.fs.props, "thermodynamic_assumption": '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) init_state = {"flow_mol": 27.5e3, "pressure": 2e6, "enth_mol": 4000} m.fs.pc.initialize(state_args=init_state, outlvl=0) # Create a solver for initialization opt = self.get_solver() opt.solve(m) # return the initialized model return m
def build_turbine_dyn(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": True, "time_set": [0, 4]}) m.fs.properties = iapws95.Iapws95ParameterBlock() m.fs.turb = HelmTurbineInletStage( default={"property_package": m.fs.properties}) return m
def test_compressor(): m = pyo.ConcreteModel() m.fs = idaes.core.FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock() m.fs.unit1 = cmodels.Compressor(default={"property_package": m.fs.properties}) m.fs.unit2 = hmodels.HelmIsentropicCompressor(default={"property_package": m.fs.properties}) # set inputs Fin = 1000 # mol/s Tin = 500 # K Pin = 2222782.4 # Pa Pout = 2.7*Pin # Pa hin = pyo.value(iapws95.htpx(Tin*pyo.units.K, Pin*pyo.units.Pa)) # J/mol eff = 0.324 m.fs.unit1.inlet.flow_mol[0].fix(Fin) m.fs.unit2.inlet.flow_mol[0].fix(Fin) m.fs.unit1.inlet.enth_mol[0].fix(hin) m.fs.unit2.inlet.enth_mol[0].fix(hin) m.fs.unit1.inlet.pressure[0].fix(Pin) m.fs.unit2.inlet.pressure[0].fix(Pin) m.fs.unit1.outlet.pressure[0].fix(Pout) m.fs.unit2.outlet.pressure[0].fix(Pout) m.fs.unit1.efficiency_isentropic.fix(eff) m.fs.unit2.efficiency_isentropic.fix(eff) m.fs.unit1.initialize() m.fs.unit2.initialize() assert pyo.value(m.fs.unit1.control_volume.properties_out[0].temperature) == \ pytest.approx( pyo.value(m.fs.unit2.control_volume.properties_out[0].temperature), rel=1e-7 ) assert pyo.value(m.fs.unit1.control_volume.work[0]) == pytest.approx( pyo.value(m.fs.unit2.control_volume.work[0]), rel=1e-7)
def model_transport(self): # This model is used to test transport properties model = ConcreteModel() model.prop_param = iapws95.Iapws95ParameterBlock() model.prop_in = iapws95.Iapws95StateBlock( default={"parameters": model.prop_param}) return model
def build_phase_separator(): m = pyo.ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock() m.fs.unit = HelmPhaseSeparator( default={'property_package': m.fs.properties}) return m
def test_turbine(self): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock() m.fs.unit = PressureChanger( default={ "property_package": m.fs.properties, "thermodynamic_assumption": ThermodynamicAssumption.isentropic, "compressor": False }) # set inputs m.fs.unit.inlet.flow_mol[0].fix(1000) # mol/s Tin = 500 # K Pin = 1000000 # Pa Pout = 700000 # Pa hin = iapws95.htpx(Tin * units.K, Pin * units.Pa) m.fs.unit.inlet.enth_mol[0].fix(hin) m.fs.unit.inlet.pressure[0].fix(Pin) m.fs.unit.deltaP.fix(Pout - Pin) m.fs.unit.efficiency_isentropic.fix(0.9) m.fs.unit.initialize() m.fs.unit.get_costing() calculate_variable_from_constraint(m.fs.unit.costing.purchase_cost, m.fs.unit.costing.cp_cost_eq) assert degrees_of_freedom(m) == 0 assert_units_consistent(m.fs.unit) solver.solve(m, tee=True) assert m.fs.unit.costing.purchase_cost.value ==\ pytest.approx(213199, 1e-5)
def test_pump(): m = pyo.ConcreteModel() m.fs = idaes.core.FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock() m.fs.unit1 = cmodels.Pump(default={"property_package": m.fs.properties}) m.fs.unit2 = hmodels.HelmPump( default={"property_package": m.fs.properties}) # set inputs Fin = 1e4 # mol/s hin = 4000 # J/mol Pin = 101325 # Pa Pout = 2 * Pin # Pa eff = 0.7 m.fs.unit1.inlet.flow_mol[0].fix(Fin) m.fs.unit2.inlet.flow_mol[0].fix(Fin) m.fs.unit1.inlet.enth_mol[0].fix(hin) m.fs.unit2.inlet.enth_mol[0].fix(hin) m.fs.unit1.inlet.pressure[0].fix(Pin) m.fs.unit2.inlet.pressure[0].fix(Pin) m.fs.unit1.outlet.pressure[0].fix(Pout) m.fs.unit2.outlet.pressure[0].fix(Pout) m.fs.unit1.efficiency_pump.fix(eff) m.fs.unit2.efficiency_pump.fix(eff) m.fs.unit1.initialize() m.fs.unit2.initialize() assert pyo.value(m.fs.unit1.control_volume.work[0]) == pytest.approx( pyo.value(m.fs.unit2.control_volume.work[0]), rel=1e-7) assert pyo.value(m.fs.unit1.control_volume.properties_out[0].temperature) == \ pytest.approx( pyo.value(m.fs.unit2.control_volume.properties_out[0].temperature), rel=1e-7 )
def test_pump(self): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock() m.fs.unit = PressureChanger( default={ "property_package": m.fs.properties, "thermodynamic_assumption": ThermodynamicAssumption.pump, "compressor": True }) # set inputs m.fs.unit.inlet.flow_mol[0].fix(10000) m.fs.unit.inlet.enth_mol[0].fix(4000) m.fs.unit.inlet.pressure[0].fix(101325) m.fs.unit.deltaP.fix(50000) m.fs.unit.efficiency_pump.fix(0.9) iscale.calculate_scaling_factors(m) assert degrees_of_freedom(m) == 0 m.fs.unit.get_costing(pump_type='centrifugal', Mat_factor='nickel', pump_motor_type_factor='enclosed') m.fs.unit.initialize() # check costing block initialization assert m.fs.unit.costing.purchase_cost.value == \ pytest.approx(70115.019, abs=1e-2) assert_units_consistent(m.fs.unit) solver.solve(m, tee=True) assert m.fs.unit.costing.purchase_cost.value == \ pytest.approx(70115.0, 1e-5)
def test_heater_ph_l_phase_two(): """Test liquid phase only form with P-H state vars and phase mass balances where the result is a two phase mixture. For the P-H vars if there are two phases, using the liquid only properties will case the phase fraction to report all liquid even though really it is not. Only use this option if you are sure you do not have a vapor phase. """ m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock( default={"phase_presentation": iapws95.PhaseType.L}) m.fs.heater = Heater( default={ "property_package": m.fs.properties, "material_balance_type": MaterialBalanceType.componentPhase }) m.fs.heater.inlet.enth_mol.fix(3000) m.fs.heater.inlet.flow_mol.fix(100) m.fs.heater.inlet.pressure.fix(101325) m.fs.heater.heat_duty[0].fix(100 * 1000) 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) - 312.88896252921666) <= 1e-4 assert abs(value(prop_out.temperature) - 326.166707507874) <= 1e-4 assert abs(value(prop_in.phase_frac["Liq"]) - 1) <= 1e-6 assert abs(value(prop_out.phase_frac["Liq"]) - 1) <= 1e-6 assert abs(value(prop_in.phase_frac["Vap"]) - 0) <= 1e-6 assert abs(value(prop_out.phase_frac["Vap"]) - 0) <= 1e-6
def test_compressor(self): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock() m.fs.unit = PressureChanger( default={ "property_package": m.fs.properties, "thermodynamic_assumption": ThermodynamicAssumption.isentropic, "compressor": True }) # set inputs m.fs.unit.inlet.flow_mol[0].fix(10000) m.fs.unit.inlet.enth_mol[0].fix(4000) m.fs.unit.inlet.pressure[0].fix(101325) m.fs.unit.deltaP.fix(500000) m.fs.unit.efficiency_isentropic.fix(0.9) iscale.calculate_scaling_factors(m) assert degrees_of_freedom(m) == 0 m.fs.unit.get_costing(mover_type="compressor") m.fs.unit.initialize() assert m.fs.unit.costing.purchase_cost.value == \ pytest.approx(334598.679, abs=1e-3) assert_units_consistent(m.fs.unit) solver.solve(m, tee=True) assert m.fs.unit.costing.purchase_cost.value == \ pytest.approx(334598.679, abs=1e-3)
def test_heater_tpx_g_phase(): """Test vapor phase only form with T-P-x state vars and phase mass balances """ m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock( default={ "phase_presentation": iapws95.PhaseType.G, "state_vars": iapws95.StateVars.TPX }) m.fs.heater = Heater( default={ "property_package": m.fs.properties, "material_balance_type": MaterialBalanceType.componentPhase }) m.fs.heater.inlet.flow_mol.fix(100) m.fs.heater.inlet.temperature.fix(422.60419933276177) m.fs.heater.inlet.pressure.fix(101325) m.fs.heater.heat_duty[0].fix(100 * 10000) prop_in = m.fs.heater.control_volume.properties_in[0] prop_out = m.fs.heater.control_volume.properties_out[0] prop_out.temperature = 550 prop_out.pressure = 101325 prop_out.flow_mol = 100 m.fs.heater.initialize(outlvl=5) assert degrees_of_freedom(m) == 0 solver.solve(m) assert abs(value(prop_out.temperature) - 698.1604861702295) <= 1e-4 assert abs(value(prop_in.phase_frac["Liq"]) - 0) <= 1e-6 assert abs(value(prop_out.phase_frac["Liq"]) - 0) <= 1e-6 assert abs(value(prop_in.phase_frac["Vap"]) - 1) <= 1e-6 assert abs(value(prop_out.phase_frac["Vap"]) - 1) <= 1e-6
def test_config(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = PhysicalParameterTestBlock() m.fs.prop_steam = iapws95.Iapws95ParameterBlock() m.fs.prop_fluegas = FlueGasParameterBlock() m.fs.unit = BoilerHeatExchanger( default={ "side_1_property_package": m.fs.prop_steam, "side_2_property_package": m.fs.prop_fluegas, "has_pressure_change": True, "has_holdup": False, "delta_T_method": DeltaTMethod.counterCurrent, "tube_arrangement": TubeArrangement.inLine, "side_1_water_phase": "Liq", "has_radiation": True }) # Check unit config arguments # There are 8 to 10 arguments since you can add a side 1 and 2 config by # side_1, side_2, or whatever the user named them assert len(m.fs.unit.config) >= 12 and len(m.fs.unit.config) <= 16 assert not m.fs.unit.config.dynamic assert not m.fs.unit.config.has_holdup assert m.fs.unit.config.delta_T_method == \ DeltaTMethod.counterCurrent
def test_heater_tpx_lg_phase(): """Test liquid/vapor form with T-P-x state vars and phase mass balances. This again has the problem where the property package calculates a vapor fraction, but you have a mass balance for each phase. """ m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock( default={ "phase_presentation": iapws95.PhaseType.LG, "state_vars": iapws95.StateVars.TPX }) m.fs.heater = Heater( default={ "property_package": m.fs.properties, "material_balance_type": MaterialBalanceType.componentPhase }) m.fs.heater.inlet.temperature.fix(326.1667075078748) m.fs.heater.inlet.vapor_frac.fix(0.0) m.fs.heater.inlet.flow_mol.fix(100) m.fs.heater.inlet.pressure.fix(101325) m.fs.heater.heat_duty[0].fix(100 * 50000) assert degrees_of_freedom(m) == -1
def build_drum1D(): # Create a Concrete Model as the top level object m = pyo.ConcreteModel() # Add a flowsheet object to the model m.fs = FlowsheetBlock(default={"dynamic": False}) # Add property packages to flowsheet library m.fs.prop_water = iapws95.Iapws95ParameterBlock() m.fs.unit = Drum1D( default={ "property_package": m.fs.prop_water, "has_holdup": True, "has_heat_transfer": True, "has_pressure_change": True, "finite_elements": 4, "drum_inner_diameter": 1.2, "drum_thickness": 0.119 }) m.fs.unit.drum_length.fix(15.3256) m.fs.unit.level[:].fix(0.6) m.fs.unit.number_downcomer.fix(6) m.fs.unit.downcomer_diameter.fix(0.38) m.fs.unit.temperature_ambient[:].fix(298.15) m.fs.unit.insulation_thickness.fix(0.145) return m
def valve_model(self): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock() m.fs.valve = Valve( default={ "valve_function_callback": self.type, "property_package": m.fs.properties }) fin = 900 # mol/s pin = 200000 # Pa pout = 100000 # Pa tin = 300 # K hin = iapws95.htpx(T=tin * units.K, P=pin * units.Pa) # J/mol # Calculate the flow coefficient to give 1000 mol/s flow with given P if self.type == ValveFunctionType.linear: cv = 1000 / math.sqrt(pin - pout) / 0.5 elif self.type == ValveFunctionType.quick_opening: cv = 1000 / math.sqrt(pin - pout) / math.sqrt(0.5) elif self.type == ValveFunctionType.equal_percentage: cv = 1000 / math.sqrt(pin - pout) / 100**(0.5 - 1) # set inlet m.fs.valve.inlet.enth_mol[0].fix(hin) m.fs.valve.inlet.flow_mol[0].fix(fin) m.fs.valve.inlet.flow_mol[0].unfix() m.fs.valve.inlet.pressure[0].fix(pin) m.fs.valve.outlet.pressure[0].fix(pout) m.fs.valve.Cv.fix(cv) m.fs.valve.valve_opening.fix(0.5) iscale.calculate_scaling_factors(m) return m
def build_valve_liquid(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock() m.fs.valve = SteamValve(default={"property_package": m.fs.properties, "phase": "Liq"}) return m