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_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 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 test_initialize_unit(build_unit): m = build_unit # platen superheater m.fs.unit.diameter_in.fix(0.035) m.fs.unit.tube_thickness.fix(0.005) m.fs.unit.fin_thickness.fix(0.0035) m.fs.unit.slag_thickness[:].fix(0.001) m.fs.unit.fin_length.fix(0.00966) m.fs.unit.tube_length.fix(40.0) m.fs.unit.number_tubes.fix(200.0) m.fs.unit.therm_cond_slag.fix(1.3) m.fs.unit.control_volume.scaling_factor_holdup_energy = 1e-8 m.fs.unit.heat_fireside[:].fix(5.5e7) # initial guess hpl = iapws95.htpx(798.15 * pyo.units.K, 24790249.01 * pyo.units.Pa) m.fs.unit.inlet[:].flow_mol.fix(24194.177) m.fs.unit.inlet[:].enth_mol.fix(hpl) m.fs.unit.inlet[:].pressure.fix(24790249.01) state_args = { 'flow_mol': 24194.177, 'pressure': 24790249.01, 'enth_mol': hpl } initialization_tester(build_unit, dof=0, state_args=state_args)
def test_initialize_calc_cf(build_turbine): """Initialize a turbine model""" m = build_turbine hin = iapws95.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.ratioP[0].value = 0.6 m.fs.turb.initialize(outlvl=1, calculate_cf=True) eq_cons = activated_equalities_generator(m) for c in eq_cons: assert abs(c.body() - c.lower) < 1e-4 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.inlet.fix() solver.solve(m) assert m.fs.turb.ratioP[0].value == pytest.approx(0.6) assert degrees_of_freedom(m) == 0
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 test_verify(self, iapws): # Test the heater model against known test cases # Test cases from Aspen Plus 10 with iapws-95 cases = { "F": (1000, 1000, 1000, 1000), # mol/s "Tin": (300, 300, 300, 800), # K "Pin": (1000, 1000, 1000, 1000), # kPa "xin": (0, 0, 0, 1), # vapor fraction "Tout": (400, 400, 453.028, 300), # K "Pout": (1000, 100, 1000, 1000), # kPa "xout": (0, 1, 0.228898, 0), # vapor fraction "duty": (7566.19, 47145, 20000, -61684.4), # kW } for i in [0, 1, 2, 3]: F = cases["F"][i] Tin = cases["Tin"][i] Pin = cases["Pin"][i]*1000 xin = cases["xin"][i] hin = iapws95.htpx(T=Tin, P=Pin) Tout = cases["Tout"][i] Pout = cases["Pout"][i]*1000 xout = cases["xout"][i] duty = cases["duty"][i]*1000 if xout != 0 and xout != 1: hout = iapws95.htpx(T=Tout, x=xout) else: hout = iapws95.htpx(T=Tout, P=Pout) prop_in = iapws.fs.unit.control_volume.properties_in[0] prop_out = iapws.fs.unit.control_volume.properties_out[0] prop_in.flow_mol = F prop_in.enth_mol = hin prop_in.pressure = Pin iapws.fs.unit.deltaP[0] = Pout - Pin iapws.fs.unit.heat_duty[0] = duty results = solver.solve(iapws) # Check for optimal solution assert results.solver.termination_condition == \ TerminationCondition.optimal assert results.solver.status == SolverStatus.ok assert Tin == pytest.approx(value(prop_in.temperature), rel=1e-3) assert Tout == pytest.approx(value(prop_out.temperature), rel=1e-3) assert Pout == pytest.approx(value(prop_out.pressure), rel=1e-3) assert xout == pytest.approx(value(prop_out.vapor_frac), rel=1e-3)
def test_verify(self, iapws_turb): iapws = iapws_turb # Verify the turbine results against 3 known test cases # Case Data (90% isentropic efficency) # Run with Aspen Plus v10 using iapws-95 cases = { "F": (1000, 1000, 1000), # mol/s "Tin": (500, 800, 400), # K "Pin": (1000, 10000, 200), # kPa "W": (-1224.64, -1911.55, -1010.64), # kW "Tout": (463.435, 742.992, 382.442), # K "Pout": (700, 7000, 140), # kPa "xout": (1.0, 1.0, 0.9886), # vapor fraction "Tisen": (460.149, 738.224, 382.442), } for i in [0, 1, 2]: F = cases["F"][i] Tin = cases["Tin"][i] Tout = cases["Tout"][i] Pin = cases["Pin"][i] * 1000 Pout = cases["Pout"][i] * 1000 hin = iapws95.htpx(T=Tin * units.K, P=Pin * units.Pa) W = cases["W"][i] * 1000 Tis = cases["Tisen"][i] xout = cases["xout"][i] iapws.fs.unit.inlet.flow_mol[0].fix(F) iapws.fs.unit.inlet.enth_mol[0].fix(hin) iapws.fs.unit.inlet.pressure[0].fix(Pin) iapws.fs.unit.deltaP.fix(Pout - Pin) iapws.fs.unit.efficiency_isentropic.fix(0.9) iapws.fs.unit.initialize(optarg={'tol': 1e-6}) results = solver.solve(iapws) # Check for optimal solution assert results.solver.termination_condition == \ TerminationCondition.optimal assert results.solver.status == SolverStatus.ok Tout = pytest.approx(cases["Tout"][i], rel=1e-2) Pout = pytest.approx(cases["Pout"][i] * 1000, rel=1e-2) Pout = pytest.approx(cases["Pout"][i] * 1000, rel=1e-2) W = pytest.approx(cases["W"][i] * 1000, rel=1e-2) xout = pytest.approx(xout, rel=1e-2) prop_out = iapws.fs.unit.control_volume.properties_out[0] prop_in = iapws.fs.unit.control_volume.properties_in[0] prop_is = iapws.fs.unit.properties_isentropic[0] assert value(prop_in.temperature) == pytest.approx(Tin, rel=1e-3) assert value(prop_is.temperature) == pytest.approx(Tis, rel=1e-3) assert value(iapws.fs.unit.control_volume.work[0]) == W assert value(prop_out.pressure) == Pout assert value(prop_out.temperature) == Tout assert value(prop_out.vapor_frac) == xout
def test_discharge(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.steam_prop = Iapws95ParameterBlock() m.fs.therminol66_prop = ThermalOilParameterBlock() m.fs.discharge_hx = HeatExchanger( default={ "hot_side_name": "tube", "cold_side_name": "shell", "tube": { "property_package": m.fs.therminol66_prop }, "shell": { "property_package": m.fs.steam_prop }, "flow_pattern": HeatExchangerFlowPattern.countercurrent }) # Set inputs # Steam m.fs.discharge_hx.inlet_2.flow_mol[0].fix(4163) m.fs.discharge_hx.inlet_2.pressure[0].fix(1.379e+6) m.fs.discharge_hx.inlet_2.enth_mol[0].fix( htpx(T=300.15 * units.K, P=1.379e+6 * units.Pa)) # Thermal Oil m.fs.discharge_hx.inlet_1.flow_mass[0].fix(833.3) m.fs.discharge_hx.inlet_1.temperature[0].fix(256 + 273.15) m.fs.discharge_hx.inlet_1.pressure[0].fix(101325) # Designate the Area m.fs.discharge_hx.area.fix(12180) m.fs.discharge_hx.overall_heat_transfer_coefficient.fix(432.677) # Designate the U Value. m.fs.discharge_hx.initialize() m.fs.discharge_hx.heat_duty.fix(1.066e+08) m.fs.discharge_hx.area.unfix() solver = get_solver() results = solver.solve(m, tee=False) # Check for optimal solution assert results.solver.termination_condition == \ TerminationCondition.optimal assert results.solver.status == SolverStatus.ok # Tests to make sure the discharge cycle is functioning properly. assert value(m.fs.discharge_hx.outlet_1.temperature[0]) == \ pytest.approx(473.5, rel=1e-1) assert value(m.fs.discharge_hx.outlet_2.enth_mol[0]) == \ pytest.approx(27668.5, rel=1e-1)
def test_charge(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.steam_prop = Iapws95ParameterBlock() m.fs.therminol66_prop = ThermalOilParameterBlock() m.fs.charge_hx = HeatExchanger( default={ "shell": { "property_package": m.fs.steam_prop }, "tube": { "property_package": m.fs.therminol66_prop }, "flow_pattern": HeatExchangerFlowPattern.countercurrent }) # Set inputs # Steam m.fs.charge_hx.inlet_1.flow_mol[0].fix(4163) m.fs.charge_hx.inlet_1.enth_mol[0].fix( htpx(T=573.15 * units.K, P=5.0e+6 * units.Pa)) m.fs.charge_hx.inlet_1.pressure[0].fix(5.0e+6) # Thermal Oil m.fs.charge_hx.inlet_2.flow_mass[0].fix(833.3) m.fs.charge_hx.inlet_2.temperature[0].fix(200 + 273.15) m.fs.charge_hx.inlet_2.pressure[0].fix(101325) m.fs.charge_hx.area.fix(12180) m.fs.charge_hx.overall_heat_transfer_coefficient.fix(432.677) m.fs.charge_hx.initialize() m.fs.charge_hx.heat_duty.fix(1.066e+08) # Needed to make the system solve. m.fs.charge_hx.overall_heat_transfer_coefficient.unfix() solver = get_solver() results = solver.solve(m) # Check for optimal solution assert results.solver.termination_condition == \ TerminationCondition.optimal assert results.solver.status == SolverStatus.ok # Testing the exit values of the heat exchanger. assert value(m.fs.charge_hx.outlet_2.temperature[0]) == \ pytest.approx(528.83, rel=1e-1) assert value(m.fs.charge_hx.outlet_1.enth_mol[0]) == \ pytest.approx(27100.28, rel=1e-1)
def test_initialize_dyn(build_turbine_dyn): """Initialize a turbine model""" m = build_turbine_dyn hin = iapws95.htpx(T=880, P=2.4233e7) discretizer = TransformationFactory('dae.finite_difference') discretizer.apply_to(m, nfe=4, wrt=m.fs.time, scheme='BACKWARD') # fix inlet m.fs.turb.inlet.enth_mol.fix(hin) m.fs.turb.inlet.flow_mol.fix(26000 / 4.0) m.fs.turb.inlet.pressure.fix(2.4233e7) m.fs.turb.initialize()
def test_initialize(build_turbine): """Initialize a turbine model""" m = build_turbine hin = value(iapws95.htpx(T=880*pyunits.K, P=2.4233e7*pyunits.Pa)) # 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) eq_cons = activated_equalities_generator(m) for c in eq_cons: assert abs(c.body() - c.lower) < 1e-4 assert degrees_of_freedom(m)==3 #inlet was't fixed and still shouldn't be
def create_isentropic_compressor(f=1000, T_in=500, p_in=1e6, ratioP=1.5): m = pyo.ConcreteModel() m.fs = idaes_core.FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock() m.fs.unit = HelmIsentropicCompressor(default={"property_package": m.fs.properties}) hin = iapws95.htpx(T_in, p_in) # J/mol m.fs.unit.inlet.flow_mol[0].fix(f) m.fs.unit.inlet.enth_mol[0].fix(hin) m.fs.unit.inlet.pressure[0].fix(p_in) m.fs.unit.ratioP[0].fix(ratioP) m.fs.unit.efficiency_isentropic.fix(0.9) m.fs.unit.initialize() return m
def test_turbine_performance_way1(self): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock() def perf_callback(b): unit_hd = units.J / units.kg unit_vflw = units.m**3 / units.s @b.Constraint(m.fs.config.time) def pc_isen_eff_eqn(b, t): prnt = b.parent_block() vflw = prnt.control_volume.properties_in[t].flow_vol return prnt.efficiency_isentropic[ t] == 0.9 / 3.975 * vflw / unit_vflw @b.Constraint(m.fs.config.time) def pc_isen_head_eqn(b, t): prnt = b.parent_block() vflw = prnt.control_volume.properties_in[t].flow_vol return b.head_isentropic[t]/1000 == \ -75530.8/3.975/1000*vflw/unit_vflw*unit_hd m.fs.unit = Turbine( default={ "property_package": m.fs.properties, "support_isentropic_performance_curves": True, "isentropic_performance_curves": { "build_callback": perf_callback } }) # 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.initialize() assert degrees_of_freedom(m) == 0 assert_units_consistent(m.fs.unit) solver.solve(m, tee=True) assert value(m.fs.unit.efficiency_isentropic[0]) \ == pytest.approx(0.9, rel=1e-3) assert value(m.fs.unit.deltaP[0]) == pytest.approx(-3e5, rel=1e-3)
def test_initialize(build_turbine): """Initialize a turbine model""" hin = value(iapws95.htpx(T=880*pyunits.K, P=2.4233e7*pyunits.Pa)) # set inlet build_turbine.fs.turb.inlet.enth_mol[0].value = hin build_turbine.fs.turb.inlet.flow_mol[0].value = 26000/4.0 build_turbine.fs.turb.inlet.pressure[0].value = 2.4233e7 build_turbine.fs.turb.initialize(outlvl=1) eq_cons = activated_equalities_generator(build_turbine) for c in eq_cons: assert(abs(c.body() - c.lower) < 1e-4) assert degrees_of_freedom(build_turbine) == 3
def test_vapor_steady_state_initialize(build_valve_vapor): """Initialize a turbine model""" m = build_valve_vapor # set inlet hin = iapws95.htpx(T=880, P=2.4233e7) # set inlet m.fs.valve.inlet.enth_mol[0].value = hin m.fs.valve.inlet.flow_mol[0].value = 26000/4.0 m.fs.valve.inlet.pressure[0].value = 2.5e7 m.fs.valve.Cv.fix(0.01) m.fs.valve.initialize(outlvl=1) eq_cons = activated_equalities_generator(m) for c in eq_cons: 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_vapor_steady_state_initialize(build_valve_vapor): """Initialize a turbine model""" # set inlet hin = value(iapws95.htpx(T=880 * pyunits.K, P=2.4233e7 * pyunits.Pa)) # set inlet build_valve_vapor.fs.valve.inlet.enth_mol[0].value = hin build_valve_vapor.fs.valve.inlet.flow_mol[0].value = 26000 / 4.0 build_valve_vapor.fs.valve.inlet.pressure[0].value = 2.5e7 build_valve_vapor.fs.valve.Cv.fix(0.01) build_valve_vapor.fs.valve.initialize(outlvl=1) eq_cons = activated_equalities_generator(build_valve_vapor) for c in eq_cons: assert (abs(c.body() - c.lower) < 1e-4) # inlet was't fixed and still shouldn't be assert degrees_of_freedom(build_valve_vapor) == 3
def test_initialize_dyn(build_turbine_dyn): """Initialize a turbine model""" m = build_turbine_dyn hin = value(iapws95.htpx(T=880*pyunits.K, P=2.4233e7*pyunits.Pa)) discretizer = TransformationFactory('dae.finite_difference') discretizer.apply_to(m, nfe=4, wrt=m.fs.time, scheme='BACKWARD') # fix inlet m.fs.turb.inlet.enth_mol.fix(hin) m.fs.turb.inlet.flow_mol.fix(26000/4.0) m.fs.turb.inlet.pressure.fix(2.4233e7) m.fs.turb.flow_coeff[:].fix() m.fs.turb.initialize() eq_cons = activated_equalities_generator(m) for c in eq_cons: assert(abs(c.body() - c.lower) < 1e-4) assert(degrees_of_freedom(m)==0)
def test_initialize_dyn2(build_turbine_dyn): """Initialize a turbine model""" m = build_turbine_dyn hin = iapws95.htpx(T=880, P=2.4233e7) discretizer = TransformationFactory('dae.finite_difference') discretizer.apply_to(m, nfe=4, wrt=m.fs.time, scheme='BACKWARD') # fix inlet m.fs.turb.inlet.enth_mol.fix(hin) m.fs.turb.inlet.flow_mol.fix(26000/4.0) m.fs.turb.inlet.pressure.fix(2.4233e7) m.fs.turb.flow_coeff[:].fix() m.fs.turb.ratioP[0].value = 0.6 # used for flow coeff calc m.fs.turb.initialize(calculate_cf=True) eq_cons = activated_equalities_generator(m) for c in eq_cons: assert(abs(c.body() - c.lower) < 1e-4) assert m.fs.turb.ratioP[0].value == pytest.approx(0.6) assert(degrees_of_freedom(m)==0)
def test_initialize_unit(build_unit): m = build_unit # Set inputs h = pyo.value(iapws95.htpx(773.15 * pyunits.K, 2.5449e7 * pyunits.Pa)) print(h) m.fs.unit.tube_inlet.flow_mol[0].fix(24678.26) # mol/s m.fs.unit.tube_inlet.enth_mol[0].fix(h) # J/mol m.fs.unit.tube_inlet.pressure[0].fix(2.5449e7) # Pascals # FLUE GAS Inlet relative to a primary superheater FGrate = 5109.76 # mol/s equivalent of ~1930.08 klb/hr # Use FG molar composition to set component flow rates (baseline report) m.fs.unit.shell_inlet.flow_mol_comp[0, "H2O"].fix(FGrate * 8.69 / 100) m.fs.unit.shell_inlet.flow_mol_comp[0, "CO2"].fix(FGrate * 14.49 / 100) m.fs.unit.shell_inlet.flow_mol_comp[0, "N2"].fix(FGrate * 74.34 / 100) m.fs.unit.shell_inlet.flow_mol_comp[0, "O2"].fix(FGrate * 2.47 / 100) m.fs.unit.shell_inlet.flow_mol_comp[0, "NO"].fix(FGrate * 0.0006) m.fs.unit.shell_inlet.flow_mol_comp[0, "SO2"].fix(FGrate * 0.002) m.fs.unit.shell_inlet.temperature[0].fix(1102.335) m.fs.unit.shell_inlet.pressure[0].fix(100145) initialization_tester(build_unit, dof=0)
def test_verify(self, iapws): # Test the heater model against known test cases cases = { "F": (1000, 1000, 1000, 1000), # mol/s "Tin": (300, 300, 300, 800), # K "Pin": (1000, 1000, 1000, 1000), # kPa "xin": (0, 0, 0, 1), # vapor fraction "Tout": (400, 400, 453.028, 300), # K "Pout": (1000, 100, 1000, 1000), # kPa "xout": (0, 1, 0.228898, 0), # vapor fraction "duty": (7566.19, 47145, 20000, -61684.4), # kW } for i in [0, 1, 2, 3]: F = cases["F"][i] Tin = cases["Tin"][i] Pin = cases["Pin"][i] * 1000 hin = iapws95.htpx(T=Tin * pyunits.K, P=Pin * pyunits.Pa) Tout = cases["Tout"][i] Pout = cases["Pout"][i] * 1000 xout = cases["xout"][i] duty = cases["duty"][i] * 1000 prop_in = iapws.fs.unit.control_volume.properties_in[0] prop_out = iapws.fs.unit.control_volume.properties_out[0] prop_in.flow_mol = F prop_in.enth_mol = hin prop_in.pressure = Pin iapws.fs.unit.deltaP[0] = Pout - Pin iapws.fs.unit.heat_duty[0] = duty results = solver.solve(iapws) # Check for optimal solution assert check_optimal_termination(results) assert Tin == pytest.approx(value(prop_in.temperature), rel=1e-3) assert Tout == pytest.approx(value(prop_out.temperature), rel=1e-3) assert Pout == pytest.approx(value(prop_out.pressure), rel=1e-3) assert xout == pytest.approx(value(prop_out.vapor_frac), rel=1e-3)
def initialize(m, fileinput=None, outlvl=idaeslog.NOTSET): """ Initialize a mode from create_model(), set model inputs before initializing. Args: m (ConcreteModel): A Pyomo model from create_model() fileinput (str|None): File to load initialized model state from. If a file is supplied skip initialization routine. If None, initialize. Returns: solver: A Pyomo solver object, that can be used to solve the model. """ init_log = idaeslog.getInitLogger(m.name, outlvl, tag="flowsheet") solve_log = idaeslog.getSolveLogger(m.name, outlvl, tag="flowsheet") iscale.calculate_scaling_factors(m) solver = pyo.SolverFactory("ipopt") solver.options = { "tol": 1e-7, "linear_solver": "ma27", "max_iter": 40, } if fileinput is not None: init_log.info("Loading initial values from file: {}".format(fileinput)) ms.from_json(m, fname=fileinput) return solver init_log.info("Starting initialization") ############################################################################ # Initialize turbine # ############################################################################ # Extraction rates are calculated from the feedwater heater models, so to # initialize the turbine fix some initial guesses. They get unfixed after # solving the turbine m.fs.turb.outlet_stage.control_volume.properties_out[:].pressure.fix(3500) m.fs.turb.lp_split[11].split_fraction[:, "outlet_2"].fix(0.04403) m.fs.turb.lp_split[10].split_fraction[:, "outlet_2"].fix(0.04025) m.fs.turb.lp_split[8].split_fraction[:, "outlet_2"].fix(0.04362) m.fs.turb.lp_split[4].split_fraction[:, "outlet_2"].fix(0.08025) m.fs.turb.ip_split[10].split_fraction[:, "outlet_2"].fix(0.045) m.fs.turb.ip_split[10].split_fraction[:, "outlet_3"].fix(0.04) m.fs.turb.ip_split[5].split_fraction[:, "outlet_2"].fix(0.05557) m.fs.turb.hp_split[7].split_fraction[:, "outlet_2"].fix(0.09741) m.fs.turb.hp_split[4].split_fraction[:, "outlet_2"].fix(0.0740) # Put in a rough initial guess for the IP section inlet, since it is # disconnected from the HP section for the reheater. ip1_pin = 5.35e6 ip1_hin = pyo.value( iapws95.htpx(T=866 * pyo.units.K, P=ip1_pin * pyo.units.Pa)) ip1_fin = pyo.value(m.fs.turb.inlet_split.inlet.flow_mol[0]) m.fs.turb.ip_stages[1].inlet.enth_mol[:].value = ip1_hin m.fs.turb.ip_stages[1].inlet.flow_mol[:].value = ip1_fin m.fs.turb.ip_stages[1].inlet.pressure[:].value = ip1_pin # initialize turbine assert degrees_of_freedom(m.fs.turb) == 0 m.fs.turb.initialize(outlvl=outlvl, optarg=solver.options) with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: res = solver.solve(m.fs.turb, tee=slc.tee) init_log.info("Full turbine solve complete: {}".format( idaeslog.condition(res))) # The turbine outlet pressure is determined by the condenser once hooked up m.fs.turb.outlet_stage.control_volume.properties_out[:].pressure.unfix() # Extraction rates are calculated once the feedwater heater models are # added so unfix the splits. m.fs.turb.lp_split[11].split_fraction[:, "outlet_2"].unfix() m.fs.turb.lp_split[10].split_fraction[:, "outlet_2"].unfix() m.fs.turb.lp_split[8].split_fraction[:, "outlet_2"].unfix() m.fs.turb.lp_split[4].split_fraction[:, "outlet_2"].unfix() m.fs.turb.ip_split[10].split_fraction[:, "outlet_3"].unfix() m.fs.turb.ip_split[5].split_fraction[:, "outlet_2"].unfix() m.fs.turb.hp_split[7].split_fraction[:, "outlet_2"].unfix() m.fs.turb.hp_split[4].split_fraction[:, "outlet_2"].unfix() # Initialize the boiler feed pump turbine. _set_port(m.fs.bfpt.inlet, m.fs.turb.ip_split[10].outlet_3) m.fs.bfpt.control_volume.properties_out[:].pressure.fix(10000) m.fs.bfpt.efficiency_isentropic.fix() m.fs.bfpt.initialize(outlvl=idaeslog.DEBUG, optarg=solver.options) m.fs.bfpt.control_volume.properties_out[:].pressure.unfix() m.fs.bfpt.efficiency_isentropic.unfix() ############################################################################ # Condenser section # ############################################################################ # initialize condenser mixer _set_port(m.fs.condenser_mix.main, m.fs.turb.outlet_stage.outlet) _set_port(m.fs.condenser_mix.bfpt, m.fs.bfpt.outlet) m.fs.condenser_mix.initialize(outlvl=outlvl, optarg=solver.options) # initialize condenser hx _set_port(m.fs.condenser.inlet_1, m.fs.condenser_mix.outlet_tpx) _set_port(m.fs.condenser.outlet_2, m.fs.condenser.inlet_2) # This still has the outlet vapor fraction fixed at 0, so if that isn't # true for the initial pressure guess this could fail to initialize m.fs.condenser.inlet_1.fix() m.fs.condenser.inlet_1.pressure.unfix() with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: res = solver.solve(m.fs.condenser, tee=slc.tee) init_log.info("Condenser initialized: {}".format(idaeslog.condition(res))) init_log.info_high("Init condenser pressure: {}".format( m.fs.condenser.shell.properties_in[0].pressure.value)) m.fs.condenser.inlet_1.unfix() # initialize hotwell _set_port(m.fs.hotwell.condensate, m.fs.condenser.outlet_1_ph) m.fs.hotwell.initialize(outlvl=outlvl, optarg=solver.options) m.fs.hotwell.condensate.unfix() # initialize condensate pump _set_port(m.fs.cond_pump.inlet, m.fs.hotwell.outlet) m.fs.cond_pump.initialize(outlvl=outlvl, optarg=solver.options) ############################################################################ # Low-pressure FWH section # ############################################################################ # fwh1 m.fs.fwh1.drain_mix.drain.flow_mol[:] = 1000 m.fs.fwh1.drain_mix.drain.pressure[:] = 1e5 m.fs.fwh1.drain_mix.drain.enth_mol[:] = 6117 _set_port(m.fs.fwh1.condense.inlet_2, m.fs.cond_pump.outlet) _set_port(m.fs.fwh1.drain_mix.steam, m.fs.turb.lp_split[11].outlet_2) m.fs.fwh1.initialize(outlvl=outlvl, optarg=solver.options) # initialize fwh1 drain pump _set_port(m.fs.fwh1_pump.inlet, m.fs.fwh1.condense.outlet_1) m.fs.fwh1_pump.initialize(outlvl=5, optarg=solver.options) # initialize mixer to add fwh1 drain to feedwater _set_port(m.fs.fwh1_return.feedwater, m.fs.fwh1.condense.outlet_2) _set_port(m.fs.fwh1_return.fwh1_drain, m.fs.fwh1.condense.outlet_1) m.fs.fwh1_return.initialize(outlvl=outlvl, optarg=solver.options) m.fs.fwh1_return.feedwater.unfix() m.fs.fwh1_return.fwh1_drain.unfix() # fwh2 m.fs.fwh2.drain_mix.drain.flow_mol[:] = 100 m.fs.fwh2.drain_mix.drain.pressure[:] = 1.5e5 m.fs.fwh2.drain_mix.drain.enth_mol[:] = 7000 _set_port(m.fs.fwh2.cooling.inlet_2, m.fs.fwh1_return.outlet) _set_port(m.fs.fwh2.desuperheat.inlet_1, m.fs.turb.lp_split[10].outlet_2) m.fs.fwh2.initialize(outlvl=outlvl, optarg=solver.options) # fwh3 m.fs.fwh3.drain_mix.drain.flow_mol[:] = 100 m.fs.fwh3.drain_mix.drain.pressure[:] = 2.5e5 m.fs.fwh3.drain_mix.drain.enth_mol[:] = 8000 _set_port(m.fs.fwh3.cooling.inlet_2, m.fs.fwh2.desuperheat.outlet_2) _set_port(m.fs.fwh3.desuperheat.inlet_1, m.fs.turb.lp_split[8].outlet_2) m.fs.fwh3.initialize(outlvl=outlvl, optarg=solver.options) # fwh4 _set_port(m.fs.fwh4.cooling.inlet_2, m.fs.fwh3.desuperheat.outlet_2) _set_port(m.fs.fwh4.desuperheat.inlet_1, m.fs.turb.lp_split[4].outlet_2) m.fs.fwh4.initialize(outlvl=outlvl, optarg=solver.options) ############################################################################ # boiler feed pump and deaerator # ############################################################################ _set_port(m.fs.fwh5_da.feedwater, m.fs.fwh4.desuperheat.outlet_2) _set_port(m.fs.fwh5_da.steam, m.fs.turb.ip_split[10].outlet_2) m.fs.fwh5_da.drain.flow_mol[:] = 2000 m.fs.fwh5_da.drain.pressure[:] = 3e6 m.fs.fwh5_da.drain.enth_mol[:] = 9000 m.fs.fwh5_da.initialize(outlvl=outlvl, optarg=solver.options) _set_port(m.fs.bfp.inlet, m.fs.fwh5_da.outlet) m.fs.bfp.control_volume.properties_out[:].pressure.fix() m.fs.bfp.initialize(outlvl=outlvl, optarg=solver.options) m.fs.bfp.control_volume.properties_out[:].pressure.unfix() ############################################################################ # High-pressure feedwater heaters # ############################################################################ # fwh6 m.fs.fwh6.drain_mix.drain.flow_mol[:] = 1000 m.fs.fwh6.drain_mix.drain.pressure[:] = 1e7 m.fs.fwh6.drain_mix.drain.enth_mol[:] = 9500 _set_port(m.fs.fwh6.cooling.inlet_2, m.fs.bfp.outlet) _set_port(m.fs.fwh6.desuperheat.inlet_1, m.fs.turb.ip_split[5].outlet_2) m.fs.fwh6.initialize(outlvl=outlvl, optarg=solver.options) # fwh7 m.fs.fwh7.drain_mix.drain.flow_mol[:] = 2000 m.fs.fwh7.drain_mix.drain.pressure[:] = 1e7 m.fs.fwh7.drain_mix.drain.enth_mol[:] = 9500 _set_port(m.fs.fwh7.cooling.inlet_2, m.fs.fwh6.desuperheat.outlet_2) _set_port(m.fs.fwh7.desuperheat.inlet_1, m.fs.turb.hp_split[7].outlet_2) m.fs.fwh7.initialize(outlvl=outlvl, optarg=solver.options) # fwh8 _set_port(m.fs.fwh8.cooling.inlet_2, m.fs.fwh7.desuperheat.outlet_2) _set_port(m.fs.fwh8.desuperheat.inlet_1, m.fs.turb.hp_split[4].outlet_2) m.fs.fwh8.initialize(outlvl=outlvl, optarg=solver.options) with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: res = solver.solve(m, tee=slc.tee) init_log.info("Initialization Complete: {}".format( idaeslog.condition(res))) return solver
def initialize(m): # ------------- ECONOMIZER ----------------------------------------------- # BFW Boiler Feed Water inlet temeperature = 555 F = 563.706 K m.fs.ECON.side_1_inlet.flow_mol[0].fix(24194.177) # mol/s m.fs.ECON.side_1_inlet.enth_mol[0].fix(14990.97) m.fs.ECON.side_1_inlet.pressure[0].fix(26922222.222) # Pa # FLUE GAS Inlet from Primary Superheater FGrate = 21290.6999 # mol/s # Use FG molar composition to set component flow rates (baseline report) m.fs.ECON.side_2_inlet.flow_mol_comp[0, "H2O"].fix(FGrate * 8.69 / 100) m.fs.ECON.side_2_inlet.flow_mol_comp[0, "CO2"].fix(FGrate * 14.49 / 100) m.fs.ECON.side_2_inlet.flow_mol_comp[0, "N2"].fix(FGrate * 74.34 / 100) m.fs.ECON.side_2_inlet.flow_mol_comp[0, "O2"].fix(FGrate * 2.47 / 100) m.fs.ECON.side_2_inlet.flow_mol_comp[0, "NO"].fix(FGrate * 0.0006) m.fs.ECON.side_2_inlet.flow_mol_comp[0, "SO2"].fix(FGrate * 0.002) m.fs.ECON.side_2_inlet.temperature[0].fix(682.335) # K m.fs.ECON.side_2_inlet.pressure[0].fix(100145) # Pa # economizer design variables and parameters ITM = 0.0254 # inch to meter conversion # Based on NETL Baseline Report Rev3 m.fs.ECON.tube_di.fix((2 - 2 * 0.188) * ITM) # calc inner diameter # (2 = outer diameter, thickness = 0.188) m.fs.ECON.tube_thickness.fix(0.188 * ITM) # tube thickness m.fs.ECON.pitch_x.fix(3.5 * ITM) # pitch_y = (54.5) gas path transverse width /columns m.fs.ECON.pitch_y.fix(5.03 * ITM) m.fs.ECON.tube_length.fix(53.41 * 12 * ITM) # use tube length (53.41 ft) m.fs.ECON.tube_nrow.fix(36 * 2.5) # use to match baseline performance m.fs.ECON.tube_ncol.fix(130) # 130 from NETL m.fs.ECON.nrow_inlet.fix(2) m.fs.ECON.delta_elevation.fix(50) # parameters # heat transfer resistance due to tube side fouling (water scales) m.fs.ECON.tube_r_fouling = 0.000176 # heat transfer resistance due to tube shell fouling (ash deposition) m.fs.ECON.shell_r_fouling = 0.00088 if m.fs.ECON.config.has_radiation is True: m.fs.ECON.emissivity_wall.fix(0.7) # wall emissivity # correction factor for overall heat transfer coefficient m.fs.ECON.fcorrection_htc.fix(1.5) # correction factor for pressure drop calc tube side m.fs.ECON.fcorrection_dp_tube.fix(1.0) # correction factor for pressure drop calc shell side m.fs.ECON.fcorrection_dp_shell.fix(1.0) # --------- Primary Superheater ------------ # Steam from water wall hprsh = value(iapws95.htpx(773.15 * pyunits.K, 24865516.722 * pyunits.Pa)) print(hprsh) m.fs.PrSH.side_1_inlet.flow_mol[0].fix(24190.26) # mol/s m.fs.PrSH.side_1_inlet.enth_mol[0].fix(hprsh) # J/mol m.fs.PrSH.side_1_inlet.pressure[0].fix(2.5449e7) # Pascals # FLUE GAS Inlet from Primary Superheater FGrate = 21290.6999 * 0.18 # mol/s # Use FG molar composition to set component flow rates (baseline report) m.fs.PrSH.side_2_inlet.flow_mol_comp[0, "H2O"].fix(FGrate * 8.69 / 100) m.fs.PrSH.side_2_inlet.flow_mol_comp[0, "CO2"].fix(FGrate * 14.49 / 100) m.fs.PrSH.side_2_inlet.flow_mol_comp[0, "N2"].fix(FGrate * 74.34 / 100) m.fs.PrSH.side_2_inlet.flow_mol_comp[0, "O2"].fix(FGrate * 2.47 / 100) m.fs.PrSH.side_2_inlet.flow_mol_comp[0, "NO"].fix(FGrate * 0.0006) m.fs.PrSH.side_2_inlet.flow_mol_comp[0, "SO2"].fix(FGrate * 0.002) m.fs.PrSH.side_2_inlet.temperature[0].fix(1180.335) m.fs.PrSH.side_2_inlet.pressure[0].fix(100145) # Primary Superheater ITM = 0.0254 # inch to meter conversion m.fs.PrSH.tube_di.fix((2.5 - 2 * 0.165) * ITM) m.fs.PrSH.tube_thickness.fix(0.165 * ITM) m.fs.PrSH.pitch_x.fix(3 * ITM) # gas path transverse width 54.78 ft / number of columns m.fs.PrSH.pitch_y.fix(54.78 / 108 * 12 * ITM) m.fs.PrSH.tube_length.fix(53.13 * 12 * ITM) m.fs.PrSH.tube_nrow.fix(20 * 2) m.fs.PrSH.tube_ncol.fix(108) m.fs.PrSH.nrow_inlet.fix(4) m.fs.PrSH.delta_elevation.fix(50) m.fs.PrSH.tube_r_fouling = 0.000176 # (0.001 h-ft^2-F/BTU) m.fs.PrSH.shell_r_fouling = 0.003131 # (0.03131 - 0.1779 h-ft^2-F/BTU) if m.fs.PrSH.config.has_radiation is True: m.fs.PrSH.emissivity_wall.fix(0.7) # wall emissivity # correction factor for overall heat transfer coefficient m.fs.PrSH.fcorrection_htc.fix(1.5) # correction factor for pressure drop calc tube side m.fs.PrSH.fcorrection_dp_tube.fix(1.0) # correction factor for pressure drop calc shell side m.fs.PrSH.fcorrection_dp_shell.fix(1.0) # ----- Finishing Superheater ---------------------- # Steam from Platen Supeheater hfsh = value(iapws95.htpx(823.15 * pyunits.K, 24790249.01 * pyunits.Pa)) m.fs.FSH.side_1_inlet.flow_mol[0].fix(24194.177) # mol/s m.fs.FSH.side_1_inlet.enth_mol[0].fix(hfsh) # J/mol m.fs.FSH.side_1_inlet.pressure[0].fix(24790249.01) # Pascals # FLUE GAS Inlet from Primary Superheater FGrate = 21290.6999 # mol/s # Use FG molar composition to set component flow rates (baseline report) m.fs.FSH.side_2_inlet.flow_mol_comp[0, "H2O"].fix(FGrate * 8.69 / 100) m.fs.FSH.side_2_inlet.flow_mol_comp[0, "CO2"].fix(FGrate * 14.49 / 100) m.fs.FSH.side_2_inlet.flow_mol_comp[0, "N2"].fix(FGrate * 74.34 / 100) m.fs.FSH.side_2_inlet.flow_mol_comp[0, "O2"].fix(FGrate * 2.47 / 100) m.fs.FSH.side_2_inlet.flow_mol_comp[0, "NO"].fix(FGrate * 0.0006) m.fs.FSH.side_2_inlet.flow_mol_comp[0, "SO2"].fix(FGrate * 0.002) m.fs.FSH.side_2_inlet.temperature[0].fix(1300.335) m.fs.FSH.side_2_inlet.pressure[0].fix(100145) # Finishing Superheater ITM = 0.0254 # inch to meter conversion m.fs.FSH.tube_di.fix((2.5 - 2 * 0.165) * ITM) m.fs.FSH.tube_thickness.fix(0.165 * ITM) m.fs.FSH.pitch_x.fix(3 * ITM) # gas path transverse width 54.78 ft / number of columns m.fs.FSH.pitch_y.fix(54.78 / 108 * 12 * ITM) m.fs.FSH.tube_length.fix(53.13 * 12 * ITM) m.fs.FSH.tube_nrow.fix(8 * 2) m.fs.FSH.tube_ncol.fix(85) m.fs.FSH.nrow_inlet.fix(2) m.fs.FSH.delta_elevation.fix(50) m.fs.FSH.tube_r_fouling = 0.000176 # (0.001 h-ft^2-F/BTU) m.fs.FSH.shell_r_fouling = 0.003131 # (0.03131 - 0.1779 h-ft^2-F/BTU) if m.fs.FSH.config.has_radiation is True: m.fs.FSH.emissivity_wall.fix(0.7) # wall emissivity # correction factor for overall heat transfer coefficient m.fs.FSH.fcorrection_htc.fix(1.0) # correction factor for pressure drop calc tube side m.fs.FSH.fcorrection_dp_tube.fix(1.0) # correction factor for pressure drop calc shell side m.fs.FSH.fcorrection_dp_shell.fix(1.0) # ----- Reheater Superheater ---------------------- # Steam from HP Turbine outlet m.fs.RH.side_1_inlet.flow_mol[0].fix(21235.27) # mol/s m.fs.RH.side_1_inlet.enth_mol[0].fix(53942.7569) # J/mol m.fs.RH.side_1_inlet.pressure[0].fix(3677172.33638) # Pascals # FLUE GAS Inlet from Finishing Superheater FGrate = 21290.6999 * 0.85 # mol/s # Use FG molar composition to set component flow rates (baseline report) m.fs.RH.side_2_inlet.flow_mol_comp[0, "H2O"].fix(FGrate * 8.69 / 100) m.fs.RH.side_2_inlet.flow_mol_comp[0, "CO2"].fix(FGrate * 14.49 / 100) m.fs.RH.side_2_inlet.flow_mol_comp[0, "N2"].fix(FGrate * 74.34 / 100) m.fs.RH.side_2_inlet.flow_mol_comp[0, "O2"].fix(FGrate * 2.47 / 100) m.fs.RH.side_2_inlet.flow_mol_comp[0, "NO"].fix(FGrate * 0.0006) m.fs.RH.side_2_inlet.flow_mol_comp[0, "SO2"].fix(FGrate * 0.002) m.fs.RH.side_2_inlet.temperature[0].fix(1180.335) m.fs.RH.side_2_inlet.pressure[0].fix(100145) # Reheater Superheater ITM = 0.0254 # inch to meter conversion m.fs.RH.tube_di.fix((2.5 - 2 * 0.165) * ITM) m.fs.RH.tube_thickness.fix(0.11 * ITM) m.fs.RH.pitch_x.fix(3 * ITM) # gas path transverse width 54.08 ft / number of columns m.fs.RH.pitch_y.fix(54.08 / 108 * 12 * ITM) m.fs.RH.tube_length.fix(53.82 * 12 * ITM) m.fs.RH.tube_nrow.fix(18 * 2) m.fs.RH.tube_ncol.fix(82 + 70) m.fs.RH.nrow_inlet.fix(2) m.fs.RH.delta_elevation.fix(30) m.fs.RH.tube_r_fouling = 0.000176 # (0.001 h-ft^2-F/BTU) m.fs.RH.shell_r_fouling = 0.00088 # (0.03131 - 0.1779 h-ft^2-F/BTU) if m.fs.RH.config.has_radiation is True: m.fs.RH.emissivity_wall.fix(0.7) # wall emissivity # correction factor for overall heat transfer coefficient m.fs.RH.fcorrection_htc.fix(1.8) # correction factor for pressure drop calc tube side m.fs.RH.fcorrection_dp_tube.fix(1.0) # correction factor for pressure drop calc shell side m.fs.RH.fcorrection_dp_shell.fix(1.0) # Platen Superheater ------------------------------------------ hpl = value(iapws95.htpx(798.15 * pyunits.K, 24790249.01 * pyunits.Pa)) m.fs.PlSH.inlet[:].flow_mol.fix(24194.177) m.fs.PlSH.inlet[:].enth_mol.fix(hpl) m.fs.PlSH.inlet[:].pressure.fix(24790249.01) m.fs.PlSH.heat_duty[:].fix(5.5e7) # Water wall Superheater ------------------------------------------ hww = value(iapws95.htpx(588.15 * pyunits.K, 2.5449e7 * pyunits.Pa)) m.fs.Water_wall.inlet[:].flow_mol.fix(24194.177) m.fs.Water_wall.inlet[:].enth_mol.fix(hww) m.fs.Water_wall.inlet[:].pressure.fix(24865516.722) m.fs.Water_wall.heat_duty[:].fix(7.51e8) # 8.76e8 # splitter flue gas from Finishing SH to Reheater and Primary SH m.fs.Spl1.split_fraction[0, 'outlet_1'].fix(0.75) # 0.85) # FLUE GAS Inlet from Primary Superheater FGrate = 21290.6999 # mol/s # Use FG molar composition to set component flow rates (baseline report) m.fs.Spl1.inlet.flow_mol_comp[0, "H2O"].fix(FGrate * 8.69 / 100) m.fs.Spl1.inlet.flow_mol_comp[0, "CO2"].fix(FGrate * 14.49 / 100) m.fs.Spl1.inlet.flow_mol_comp[0, "N2"].fix(FGrate * 74.34 / 100) m.fs.Spl1.inlet.flow_mol_comp[0, "O2"].fix(FGrate * 2.47 / 100) m.fs.Spl1.inlet.flow_mol_comp[0, "NO"].fix(FGrate * 0.0006) m.fs.Spl1.inlet.flow_mol_comp[0, "SO2"].fix(FGrate * 0.002) m.fs.Spl1.inlet.temperature[0].fix(1180.335) m.fs.Spl1.inlet.pressure[0].fix(100145) # mixer (econ inlet) fluegas outlet from reheater and primary superheater # Mixer inlets ['Reheat_out', 'PrSH_out'] m.fs.mix1.Reheat_out.flow_mol_comp[0, "H2O"].fix(FGrate * 8.69 / 100) m.fs.mix1.Reheat_out.flow_mol_comp[0, "CO2"].fix(FGrate * 14.49 / 100) m.fs.mix1.Reheat_out.flow_mol_comp[0, "N2"].fix(FGrate * 74.34 / 100) m.fs.mix1.Reheat_out.flow_mol_comp[0, "O2"].fix(FGrate * 2.47 / 100) m.fs.mix1.Reheat_out.flow_mol_comp[0, "NO"].fix(FGrate * 0.0006) m.fs.mix1.Reheat_out.flow_mol_comp[0, "SO2"].fix(FGrate * 0.002) m.fs.mix1.Reheat_out.pressure.fix(100145) m.fs.mix1.Reheat_out.temperature.fix(731.5) # Fixed SprayWater as small flow and arbitrary conditions # (will be connected from FW pump splitter) m.fs.mix1.PrSH_out.flow_mol_comp[0, "H2O"].fix(FGrate * 8.69 / 100) m.fs.mix1.PrSH_out.flow_mol_comp[0, "CO2"].fix(FGrate * 14.49 / 100) m.fs.mix1.PrSH_out.flow_mol_comp[0, "N2"].fix(FGrate * 74.34 / 100) m.fs.mix1.PrSH_out.flow_mol_comp[0, "O2"].fix(FGrate * 2.47 / 100) m.fs.mix1.PrSH_out.flow_mol_comp[0, "NO"].fix(FGrate * 0.0006) m.fs.mix1.PrSH_out.flow_mol_comp[0, "SO2"].fix(FGrate * 0.002) m.fs.mix1.PrSH_out.pressure.fix(100145) m.fs.mix1.PrSH_out.temperature.fix(731.15) # Attemperator inputs hatt = value(iapws95.htpx(875.15 * pyunits.K, 24865516.722 * pyunits.Pa)) m.fs.ATMP1.Steam.flow_mol.fix(24194.177) m.fs.ATMP1.Steam.enth_mol.fix(hatt) m.fs.ATMP1.Steam.pressure.fix(24865516.722) # Fixed SprayWater from FW pump splitter (splitter is needded) hatt2 = value(iapws95.htpx(563.15 * pyunits.K, 2.5449e7 * pyunits.Pa)) m.fs.ATMP1.SprayWater_state[:].flow_mol.fix(0.001) m.fs.ATMP1.SprayWater_state[:].pressure.fix(1.22e8) m.fs.ATMP1.SprayWater_state[:].enth_mol.fix(hatt2) # --------- Initialization ------------------------------------------ # Initialize Units m.fs.ECON.initialize(outlvl=logging.INFO) m.fs.PrSH.initialize(outlvl=logging.INFO) m.fs.FSH.initialize(outlvl=logging.INFO) m.fs.RH.initialize(outlvl=logging.INFO) m.fs.PlSH.initialize(outlvl=logging.INFO) m.fs.Water_wall.initialize(outlvl=logging.INFO) m.fs.Spl1.initialize(outlvl=logging.INFO) m.fs.mix1.initialize(outlvl=logging.INFO) m.fs.ATMP1.initialize(outlvl=logging.INFO) print('initialization done')
def test_initialize_dyn(build_turbine_dyn): """Initialize a turbine model""" m = build_turbine_dyn hin = iapws95.htpx(T=880, P=2.4233e7) """
m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.steam_prop = Iapws95ParameterBlock() m.fs.therminol66_prop = ThermalOilParameterBlock() m.fs.discharge_hx = HeatExchanger( default={"hot_side_name": "tube", "cold_side_name": "shell", "tube": {"property_package": m.fs.therminol66_prop}, "shell": {"property_package": m.fs.steam_prop}, "flow_pattern": HeatExchangerFlowPattern.countercurrent}) # Set inputs #Steam m.fs.discharge_hx.inlet_2.flow_mol[0].fix(4163) m.fs.discharge_hx.inlet_2.pressure[0].fix(1.379e+6) m.fs.discharge_hx.inlet_2.enth_mol[0].fix(htpx(T=300.15*units.K, P=1.379e+6*units.Pa)) #Thermal Oil m.fs.discharge_hx.inlet_1.flow_mass[0].fix(833.3) m.fs.discharge_hx.inlet_1.temperature[0].fix(256 + 273.15) m.fs.discharge_hx.inlet_1.pressure[0].fix(101325) #Designate the Area m.fs.discharge_hx.area.fix(12180) m.fs.discharge_hx.overall_heat_transfer_coefficient.fix(432.677) #Designate the U Value. print("Degrees of Freedom =", degrees_of_freedom(m))
def test_boiler_hx(): 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 }) # Set inputs h = iapws95.htpx(773.15, 2.5449e7) print(h) m.fs.unit.side_1_inlet.flow_mol[0].fix(24678.26) # mol/s m.fs.unit.side_1_inlet.enth_mol[0].fix(h) # J/mol m.fs.unit.side_1_inlet.pressure[0].fix(2.5449e7) # Pascals # FLUE GAS Inlet from Primary Superheater FGrate = 28.3876e3 * 0.18 # mol/s equivalent of ~1930.08 klb/hr # Use FG molar composition to set component flow rates (baseline report) m.fs.unit.side_2_inlet.flow_mol_comp[0, "H2O"].fix(FGrate * 8.69 / 100) m.fs.unit.side_2_inlet.flow_mol_comp[0, "CO2"].fix(FGrate * 14.49 / 100) m.fs.unit.side_2_inlet.flow_mol_comp[0, "N2"].fix(FGrate * 74.34 / 100) m.fs.unit.side_2_inlet.flow_mol_comp[0, "O2"].fix(FGrate * 2.47 / 100) m.fs.unit.side_2_inlet.flow_mol_comp[0, "NO"].fix(FGrate * 0.0006) m.fs.unit.side_2_inlet.flow_mol_comp[0, "SO2"].fix(FGrate * 0.002) m.fs.unit.side_2_inlet.temperature[0].fix(1102.335) m.fs.unit.side_2_inlet.pressure[0].fix(100145) # Primary Superheater ITM = 0.0254 # inch to meter conversion m.fs.unit.tube_di.fix((2.5 - 2 * 0.165) * ITM) m.fs.unit.tube_thickness.fix(0.165 * ITM) m.fs.unit.pitch_x.fix(3 * ITM) # gas path transverse width 54.78 ft / number of columns m.fs.unit.pitch_y.fix(54.78 / 108 * 12 * ITM) m.fs.unit.tube_length.fix(53.13 * 12 * ITM) m.fs.unit.tube_nrow.fix(20 * 2) m.fs.unit.tube_ncol.fix(108) m.fs.unit.nrow_inlet.fix(4) m.fs.unit.delta_elevation.fix(50) m.fs.unit.tube_r_fouling = 0.000176 # (0.001 h-ft^2-F/BTU) m.fs.unit.tube_r_fouling = 0.003131 # (0.03131 - 0.1779 h-ft^2-F/BTU) if m.fs.unit.config.has_radiation is True: m.fs.unit.emissivity_wall.fix(0.7) # wall emissivity # correction factor for overall heat transfer coefficient m.fs.unit.fcorrection_htc.fix(1.5) # correction factor for pressure drop calc tube side m.fs.unit.fcorrection_dp_tube.fix(1.0) # correction factor for pressure drop calc shell side m.fs.unit.fcorrection_dp_shell.fix(1.0) assert degrees_of_freedom(m) == 0 m.fs.unit.initialize() # Create a solver solver = SolverFactory('ipopt') results = solver.solve(m) # Check for optimal solution assert results.solver.termination_condition == \ TerminationCondition.optimal assert results.solver.status == SolverStatus.ok assert value(m.fs.unit.side_1.properties_out[0].temperature) == \ pytest.approx(588.07, 1) assert value(m.fs.unit.side_2.properties_out[0].temperature) == \ pytest.approx(573.07, 1)
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 = pyo.value(iapws95.htpx(T=880 * pyo.units.K, P=p * pyo.units.Pa)) 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 = pyo.value(iapws95.htpx(T=880 * pyo.units.K, P=p * pyo.units.Pa)) 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.fix() for i in turb.throttle_valve: turb.throttle_valve[i].Cv.fix() turb.throttle_valve[i].valve_opening.fix() turb.inlet_split.inlet.flow_mol.unfix() turb.inlet_mix.use_equal_pressure_constraint() iscale.calculate_scaling_factors(m) turb.initialize(outlvl=1) turb.ip_stages[1].inlet.unfix() for t in m.fs.time: m.fs.reheat.inlet.flow_mol[t].value = \ pyo.value(turb.hp_split[7].outlet_1_state[t].flow_mol) m.fs.reheat.inlet.enth_mol[t].value = \ pyo.value(turb.hp_split[7].outlet_1_state[t].enth_mol) m.fs.reheat.inlet.pressure[t].value = \ pyo.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 = pyo.Constraint( m.fs.reheat.flowsheet().config.time, rule=reheat_T_rule) pyo.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) eq_cons = activated_equalities_generator(m) for c in eq_cons: assert abs(c.body() - c.lower) < 1e-4 return m
m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.steam_prop = Iapws95ParameterBlock() m.fs.therminol66_prop = ThermalOilParameterBlock() m.fs.charge_hx = HeatExchanger( default={"shell": {"property_package": m.fs.steam_prop}, "tube": {"property_package": m.fs.therminol66_prop}, "flow_pattern": HeatExchangerFlowPattern.countercurrent}) # Set inputs #Steam m.fs.charge_hx.inlet_1.flow_mol[0].fix(4163) m.fs.charge_hx.inlet_1.enth_mol[0].fix(htpx(T=573.15*units.K, P=5.0e+6*units.Pa)) m.fs.charge_hx.inlet_1.pressure[0].fix(5.0e+6) #Thermal Oil m.fs.charge_hx.inlet_2.flow_mass[0].fix(833.3) m.fs.charge_hx.inlet_2.temperature[0].fix(200 + 273.15) m.fs.charge_hx.inlet_2.pressure[0].fix(101325) m.fs.charge_hx.area.fix(12180) m.fs.charge_hx.overall_heat_transfer_coefficient.fix(432.677) print("Degrees of Freedom =", degrees_of_freedom(m)) m.fs.charge_hx.initialize()
def th( delta_temperature_callback=delta_temperature_underwood_tune_callback, tout_1=809.55, tout_2=788.53, ): 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, }) # Set inputs h = value(iapws95.htpx(773.15 * pyunits.K, 2.5449e7 * pyunits.Pa)) m.fs.unit.side_1_inlet.flow_mol[0].fix(24678.26) # mol/s m.fs.unit.side_1_inlet.enth_mol[0].fix(h) # J/mol m.fs.unit.side_1_inlet.pressure[0].fix(2.5449e7) # Pascals # FLUE GAS Inlet from Primary Superheater FGrate = 28.3876e3 * 0.18 # mol/s equivalent of ~1930.08 klb/hr # Use FG molar composition to set component flow rates (baseline report) m.fs.unit.side_2_inlet.flow_mol_comp[0, "H2O"].fix(FGrate * 8.69 / 100) m.fs.unit.side_2_inlet.flow_mol_comp[0, "CO2"].fix(FGrate * 14.49 / 100) m.fs.unit.side_2_inlet.flow_mol_comp[0, "N2"].fix(FGrate * 74.34 / 100) m.fs.unit.side_2_inlet.flow_mol_comp[0, "O2"].fix(FGrate * 2.47 / 100) m.fs.unit.side_2_inlet.flow_mol_comp[0, "NO"].fix(FGrate * 0.0006) m.fs.unit.side_2_inlet.flow_mol_comp[0, "SO2"].fix(FGrate * 0.002) m.fs.unit.side_2_inlet.temperature[0].fix(1102.335) m.fs.unit.side_2_inlet.pressure[0].fix(100145) # Primary Superheater ITM = 0.0254 # inch to meter conversion m.fs.unit.tube_di.fix((2.5 - 2 * 0.165) * ITM) m.fs.unit.tube_thickness.fix(0.165 * ITM) m.fs.unit.pitch_x.fix(3 * ITM) # gas path transverse width 54.78 ft / number of columns m.fs.unit.pitch_y.fix(54.78 / 108 * 12 * ITM) m.fs.unit.tube_length.fix(53.13 * 12 * ITM) m.fs.unit.tube_nrow.fix(20 * 2) m.fs.unit.tube_ncol.fix(108) m.fs.unit.nrow_inlet.fix(4) m.fs.unit.delta_elevation.fix(50) m.fs.unit.tube_r_fouling = 0.000176 # (0.001 h-ft^2-F/BTU) m.fs.unit.tube_r_fouling = 0.003131 # (0.03131 - 0.1779 h-ft^2-F/BTU) if m.fs.unit.config.has_radiation is True: m.fs.unit.emissivity_wall.fix(0.7) # wall emissivity # correction factor for overall heat transfer coefficient m.fs.unit.fcorrection_htc.fix(1.5) # correction factor for pressure drop calc tube side m.fs.unit.fcorrection_dp_tube.fix(1.0) # correction factor for pressure drop calc shell side m.fs.unit.fcorrection_dp_shell.fix(1.0) assert degrees_of_freedom(m) == 0 iscale.calculate_scaling_factors(m) m.fs.unit.initialize() results = solver.solve(m) # Check for optimal solution assert check_optimal_termination(results) assert value( m.fs.unit.side_1.properties_out[0].temperature) == pytest.approx( tout_1, abs=0.5) assert value( m.fs.unit.side_2.properties_out[0].temperature) == pytest.approx( tout_2, abs=0.5)