Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
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
Exemplo n.º 4
0
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)
Exemplo n.º 5
0
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
Exemplo n.º 6
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
Exemplo n.º 7
0
    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)
Exemplo n.º 8
0
    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)
Exemplo n.º 10
0
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)
Exemplo n.º 11
0
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()
Exemplo n.º 12
0
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
Exemplo n.º 13
0
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
Exemplo n.º 14
0
    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)
Exemplo n.º 15
0
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
Exemplo n.º 16
0
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
Exemplo n.º 17
0
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
Exemplo n.º 18
0
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)
Exemplo n.º 19
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)
Exemplo n.º 20
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)
Exemplo n.º 21
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
Exemplo n.º 23
0
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')
Exemplo n.º 24
0
def test_initialize_dyn(build_turbine_dyn):
    """Initialize a turbine model"""
    m = build_turbine_dyn
    hin = iapws95.htpx(T=880, P=2.4233e7)
    """
Exemplo n.º 25
0
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)
Exemplo n.º 27
0
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
Exemplo n.º 28
0
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()
Exemplo n.º 29
0
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)