Ejemplo n.º 1
0
def run_full_load(m, solver):
    """ Set the model up for off-design pressure driven flow.  Run 480 MW case.

    Args:
        m: (ConcreteModel) model to run
        solver: (Solver)

    Returns:
        None
    """
    m.fs.feed_fuel1.flow_mol.unfix()
    # For initialization, flow was specified and and valve opening calculated
    m.fs.valve01.control_volume.properties_in[0].flow_mol.unfix()
    m.fs.valve02.control_volume.properties_in[0].flow_mol.unfix()
    m.fs.valve03.control_volume.properties_in[0].flow_mol.unfix()
    # deltaP will be whatever is needed to satisfy the power requirment
    m.fs.vsv.deltaP.unfix()
    # The compressor efficiency is a little high since it doesn't include
    # throttling in the valve use to approximate VSV.
    m.fs.cmp1.efficiency_isentropic.fix(0.92)
    m.fs.cmp1.ratioP.fix(17.5) # lowering this ratio, just means less pressure
                               # drop in the VSV valve, decresing throttle loss
    # Exhaust pressure will be a bit over ATM due to HRSG. This will come from
    # HRSG model when coupled to form NGCC model
    m.fs.gts3.control_volume.properties_out[0].pressure.fix(102594)
    # Don't know how much blade cooling air is needed for off desing case, but
    # full load flows were based on WVU model.  For now just leave valves at
    # fixed opening.
    m.fs.valve01.valve_opening.fix()
    m.fs.valve02.valve_opening.fix()
    m.fs.valve03.valve_opening.fix()
    # Feeds
    # Air at compressor inlet
    m.fs.feed_air1.temperature.fix(288.15)
    m.fs.feed_air1.pressure.fix(103421)
    # Gas at fuel injection
    m.fs.feed_fuel1.temperature.fix(310.928)
    m.fs.feed_fuel1.pressure.fix(3.10264e6)
    # It looks like the O2 or air/fuel ratio is actually determined to roughly
    # get a constant exhaust temperature.  In a real gas turbine there are
    # probably a lot of complex factors, but here we fix the exhaust temp.
    m.fs.cmbout_o2_mol_frac.unfix()
    m.fs.exhaust_1.temperature.fix(910)
    # Fix the gross power output
    m.fs.gt_power[0].fix(-480e6) # Watts negative because is power out
    # Solve
    iscale.constraint_autoscale_large_jac(m)
    return solver.solve(m, tee=True)
Ejemplo n.º 2
0
    def test_scale_with_ignore_constraint_scale(self):
        """Make sure ignore_constraint_scaling ignores given scaling factors.
        """
        m = pyo.ConcreteModel()
        m.a = pyo.Var([1, 2], initialize=1)
        m.c = pyo.Constraint(expr=(0, m.a[1] + m.a[2], 1))
        m.scaling_factor = pyo.Suffix(direction=pyo.Suffix.EXPORT)
        m.scaling_factor[m.c] = 1e6

        jac, jac_scaled, nlp = sc.constraint_autoscale_large_jac(
            m, ignore_constraint_scaling=True)
        assert m.scaling_factor[m.c] == pytest.approx(1)
Ejemplo n.º 3
0
def main(
    comps,
    rxns,
    phases,
    air_comp,
    ng_comp,
    m=None,
    initialize=True,
    flow_scale=0.896):
    """Generate and initialize the gas turbine flowsheet. This method returns
    a model and solver. The flow_scale argument can be used to scale the turnine
    up or down with the same relative performace.

    Args:
        comps: (set of str) a set of componets
        rxns: (dict) reactions with reaction name key and key component for
            conversion calculations
        phases: (list) phases potentially present
        air_comp: (dict) mole-fraction air composition
        ng_comp: (dict) mole-fraction natural gas composition
        m: (ConcreteModel) model to add flowsheet too.  If None create a new one.
        initialize: (bool) If true initialize the flowsheet
        flow_scale: (float) flow scale multiplier to scale the performace curves
            up or down. Original nominal volumetric flow/new nominal volumetric
            flow (default=0.896).

    Returns:
        (ConcreteModel) model, (Solver) solver
    """
    expand_arcs = pyo.TransformationFactory("network.expand_arcs")
    #
    # Model, flowsheet and properties
    #
    if m is None:
        m = pyo.ConcreteModel("Gas Turbine Model")
    if not hasattr(m, "fs"):
        m.fs = FlowsheetBlock(default={"dynamic": False})
        
    air_species = {"CO2","Ar","H2O","O2","N2"}
    cmb_species = {"CH4","C2H6","C2H4","C3H8","C4H10","CO",
                    "H2S","H2","O2","H2O","CO2","N2","Ar","SO2"}
    fuel_species = {"H2","CH4","C2H6","C2H4","C3H8","C4H10"}
    flue_species = {"CO2","Ar","H2O","O2","N2","SO2"}
    
    # Assuming the turbine runs lean, so there's still oxygen left after
    # combustion
    for comp,conc in air_comp.items():
        if conc < 1E-12:
            air_species.remove(comp)
            cmb_species.remove(comp)
            flue_species.remove(comp)
    for comp,conc in ng_comp.items():
        if conc < 1E-12:
            if comp in fuel_species:
                cmb_species.remove(comp)
            if comp == "H2S":
                cmb_species.remove("H2S")
                cmb_species.remove("SO2")
                flue_species.remove("SO2")
    for comp in fuel_species:
        if comp not in ng_comp.keys():
            cmb_species.remove(comp)
            
    
    m.fs.air_prop_params = GenericParameterBlock(
        default=get_prop(air_species, phases))
    m.fs.cmb_prop_params = GenericParameterBlock(
        default=get_prop(cmb_species, phases))
    m.fs.flue_prop_params = GenericParameterBlock(
        default=get_prop(flue_species, phases))
    
    prop_packages = {m.fs.air_prop_params,m.fs.cmb_prop_params,
                     m.fs.flue_prop_params}

    
    m.fs.gas_prop_params = GenericParameterBlock(default=get_prop(comps, phases))
    m.fs.gas_prop_params.set_default_scaling("mole_frac_comp", 10)
    m.fs.gas_prop_params.set_default_scaling("mole_frac_phase_comp", 10)
    _mf_scale = {
        "Ar":100,
        "O2":100,
        "H2S":1000,
        "SO2":1000,
        "H2":1000,
        "CO":1000,
        "C2H4":1000,
        "C2H6":1000,
        "C3H8":1000,
        "C4H10":1000,
        "CO2":1000}
    for pp in prop_packages:
        pp.set_default_scaling("mole_frac_comp", 10)
        pp.set_default_scaling("mole_frac_phase_comp", 10)
        for c, s in _mf_scale.items():
            if c in pp.component_list:
                pp.set_default_scaling(
                    "mole_frac_comp", s, index=c)
                pp.set_default_scaling(
                    "mole_frac_phase_comp", s, index=("Vap", c))
        pp.set_default_scaling(
            "enth_mol_phase", 1e-3, index="Vap")

    m.fs.gas_combustion = GenericReactionParameterBlock(
        default=get_rxn(m.fs.cmb_prop_params, rxns))
    # Variable for mole-fraction of O2 in the flue gas.  To initialize the model
    # will use a fixed value here.
    m.fs.cmbout_o2_mol_frac = pyo.Var(m.fs.time, initialize=0.1157)
    m.fs.cmbout_o2_mol_frac.fix()
    #
    # Unit models
    #
    # inlet/outlet blocks
    m.fs.feed_air1 = um.Feed(default={"property_package": m.fs.air_prop_params})
    m.fs.feed_fuel1 = um.Feed(default={"property_package": m.fs.cmb_prop_params})
    m.fs.exhaust_1 = um.Product(default={"property_package": m.fs.flue_prop_params})
    # Valve roughly approximating variable stator vanes to control air flow.
    m.fs.vsv = um.Valve(default={
        "valve_function_callback":um.ValveFunctionType.linear,
        "property_package": m.fs.air_prop_params})
    # Comprssor for air
    m.fs.cmp1 = um.Compressor(default={
        "property_package": m.fs.air_prop_params,
        "support_isentropic_performance_curves":True})
    # Blade cooling air splitter
    m.fs.splt1 = um.Separator(default={
        "property_package": m.fs.air_prop_params,
        "outlet_list":["air04", "air05", "air07", "air09"]})
    # Three valves for blade cooling air.
    m.fs.valve01 = um.Valve(default={
        "valve_function_callback":um.ValveFunctionType.linear,
        "property_package": m.fs.air_prop_params})
    m.fs.valve02 = um.Valve(default={
        "valve_function_callback":um.ValveFunctionType.linear,
        "property_package": m.fs.air_prop_params})
    m.fs.valve03 = um.Valve(default={
        "valve_function_callback":um.ValveFunctionType.linear,
        "property_package": m.fs.air_prop_params})
    # Mixer for fuel injection. Since this is a steady state model the pressure
    # drop on the fuel control valve is lumped into this mixer
    m.fs.inject_translator = um.Translator(default={"inlet_property_package": m.fs.air_prop_params,
                                      "outlet_property_package": m.fs.cmb_prop_params,
                                      "outlet_state_defined": False})
    
    m.fs.inject1 = um.Mixer(default={
        "property_package": m.fs.cmb_prop_params,
        "inlet_list":["gas", "air"],
        "momentum_mixing_type":um.MomentumMixingType.none})
    # Three blade cooling air mixers. The blade cooling isn't explicitly modeled
    # so these mainly just maintain the proper mass and enegy balance.
    m.fs.translator1 = um.Translator(default={"inlet_property_package": m.fs.air_prop_params,
                                      "outlet_property_package": m.fs.flue_prop_params,
                                      "outlet_state_defined": False})
    m.fs.mx1 = um.Mixer(default={
        "property_package": m.fs.flue_prop_params,
        "inlet_list":["gas", "air"],
        "momentum_mixing_type":um.MomentumMixingType.equality})
    m.fs.translator2 = um.Translator(default={"inlet_property_package": m.fs.air_prop_params,
                                      "outlet_property_package": m.fs.flue_prop_params,
                                      "outlet_state_defined": False})
    m.fs.mx2 = um.Mixer(default={
        "property_package": m.fs.flue_prop_params,
        "inlet_list":["gas", "air"],
        "momentum_mixing_type":um.MomentumMixingType.equality})
    m.fs.translator3 = um.Translator(default={"inlet_property_package": m.fs.air_prop_params,
                                      "outlet_property_package": m.fs.flue_prop_params,
                                      "outlet_state_defined": False})
    m.fs.mx3 = um.Mixer(default={
        "property_package": m.fs.flue_prop_params,
        "inlet_list":["gas", "air"],
        "momentum_mixing_type":um.MomentumMixingType.equality})
    # Combustor, for now assuming complete reactions and no NOx
    m.fs.cmb1 = um.StoichiometricReactor(default={
        "property_package": m.fs.cmb_prop_params,
        "reaction_package": m.fs.gas_combustion,
        "has_pressure_change": True})
    m.fs.flue_translator = um.Translator(default={"inlet_property_package": m.fs.cmb_prop_params,
                                      "outlet_property_package": m.fs.flue_prop_params,
                                      "outlet_state_defined": False})
    # Three gas turbine stages, with performance curves for all three added by
    # the performance_curves() fuctions.
    m.fs.gts1 = um.Turbine(default={
        "property_package": m.fs.flue_prop_params,
        "support_isentropic_performance_curves":True})
    m.fs.gts2 = um.Turbine(default={
        "property_package": m.fs.flue_prop_params,
        "support_isentropic_performance_curves":True})
    m.fs.gts3 = um.Turbine(default={
        "property_package": m.fs.flue_prop_params,
        "support_isentropic_performance_curves":True})
    performance_curves(m)
    #
    # Additional constraints/expressions
    #
    # to make this simpler, just deal with VSV valve-approximation pressure drop
    # and forget the opening
    m.fs.vsv.pressure_flow_equation.deactivate()
    # O2 fraction in combustor constraint (to set var)
    @m.fs.Constraint(m.fs.time)
    def o2_flow(b, t):
        return m.fs.cmb1.control_volume.properties_out[t].mole_frac_comp["O2"] \
            == m.fs.cmbout_o2_mol_frac[t]
    # Fuel injector pressure is the air pressure. This lumps in the gas valve
    @m.fs.inject1.Constraint(m.fs.time)
    def mxpress_eqn(b, t):
        return b.mixed_state[t].pressure == b.air_state[t].pressure
    # The pressure drop in the cumbustor is just a fixed 5%.
    @m.fs.cmb1.Constraint(m.fs.time)
    def pressure_drop_eqn(b, t):
        return (0.95 ==
            b.control_volume.properties_out[t].pressure /
            b.control_volume.properties_in[t].pressure)
    # Constraints for complete combustion, use key compoents and 100% conversion
    @m.fs.cmb1.Constraint(m.fs.time, rxns.keys())
    def reaction_extent(b, t, r):
        k = rxns[r]
        prp = b.control_volume.properties_in[t]
        stc = -m.fs.gas_combustion.rate_reaction_stoichiometry[r, "Vap", k]
        extent = b.rate_reaction_extent[t, r]
        return extent == prp.flow_mol*prp.mole_frac_comp[k]/stc
    # Calculate the total gas turnine gross power output.
    @m.fs.Expression(m.fs.time)
    def gt_power_expr(b, t):
        return (
            m.fs.cmp1.control_volume.work[t] +
            m.fs.gts1.control_volume.work[t] +
            m.fs.gts2.control_volume.work[t] +
            m.fs.gts3.control_volume.work[t])
    # Add a varable and constraint for gross power.  This allows fixing power
    # for simulations where a specific power output is desired.
    m.fs.gt_power = pyo.Var(m.fs.time)
    @m.fs.Constraint(m.fs.time)
    def gt_power_eqn(b, t):
        return b.gt_power[t] == b.gt_power_expr[t]
    
    # Rules for translator blocks
    def rule_flow_mol_comp(blk,t,j):
        return blk.properties_in[t].flow_mol_comp[j] == blk.properties_out[t].flow_mol_comp[j]
    def rule_temperature(blk,t):
        return blk.properties_in[t].temperature == blk.properties_out[t].temperature
    def rule_pressure(blk,t):
        return blk.properties_in[t].pressure == blk.properties_out[t].pressure
    def rule_zero_flow(blk,t,j):
        return blk.properties_out[t].flow_mol_comp[j] == 0

    
    for blk in {m.fs.inject_translator, m.fs.translator1, m.fs.translator2, m.fs.translator3,
                m.fs.flue_translator}:
        blk.temperature_eqn = pyo.Constraint(m.fs.time, rule=rule_temperature)
        blk.pressure_eqn = pyo.Constraint(m.fs.time, rule=rule_pressure)

    m.fs.inject_translator.flow_mole_comp_eqn = pyo.Constraint(m.fs.time, air_species,
                                                  rule = rule_flow_mol_comp)   
    m.fs.inject_translator.zero_flow_eqn = pyo.Constraint(m.fs.time,
                        cmb_species-air_species, rule = rule_zero_flow)
    
    for blk in {m.fs.translator1, m.fs.translator2, m.fs.translator3}:
        blk.flow_mole_comp_eqn = pyo.Constraint(m.fs.time, air_species,
                                                      rule = rule_flow_mol_comp)
        blk.zero_flow_eqn = pyo.Constraint(m.fs.time, flue_species-air_species,
                                                     rule = rule_zero_flow)
        
    m.fs.flue_translator.flow_mole_comp_eqn = pyo.Constraint(m.fs.time, flue_species,
                                                  rule = rule_flow_mol_comp)
    #
    # Arcs
    #
    # Arc names are imoprtant here becuase they match the PFD and are used for
    # tagging stream quantities
    m.fs.fuel01 = Arc(source=m.fs.feed_fuel1.outlet, destination=m.fs.inject1.gas)
    m.fs.air01 = Arc(source=m.fs.feed_air1.outlet, destination=m.fs.vsv.inlet)
    m.fs.air02 = Arc(source=m.fs.vsv.outlet, destination=m.fs.cmp1.inlet)
    m.fs.air03 = Arc(source=m.fs.cmp1.outlet, destination=m.fs.splt1.inlet)
    m.fs.air04a = Arc(source=m.fs.splt1.air04, destination=m.fs.inject_translator.inlet)
    m.fs.air04b = Arc(source=m.fs.inject_translator.outlet, destination=m.fs.inject1.air)
    m.fs.air05 = Arc(source=m.fs.splt1.air05, destination=m.fs.valve01.inlet)
    m.fs.air06a = Arc(source=m.fs.valve01.outlet, destination=m.fs.translator1.inlet)
    m.fs.air06b = Arc(source=m.fs.translator1.outlet, destination=m.fs.mx1.air)
    m.fs.air07 = Arc(source=m.fs.splt1.air07, destination=m.fs.valve02.inlet)
    m.fs.air08a = Arc(source=m.fs.valve02.outlet, destination=m.fs.translator2.inlet)
    m.fs.air08b = Arc(source=m.fs.translator2.outlet, destination=m.fs.mx2.air)
    m.fs.air09 = Arc(source=m.fs.splt1.air09, destination=m.fs.valve03.inlet)
    m.fs.air10a = Arc(source=m.fs.valve03.outlet, destination=m.fs.translator3.inlet)
    m.fs.air10b = Arc(source=m.fs.translator3.outlet, destination=m.fs.mx3.air)
    m.fs.g01 = Arc(source=m.fs.inject1.outlet, destination=m.fs.cmb1.inlet)
    m.fs.g02a = Arc(source=m.fs.cmb1.outlet, destination=m.fs.flue_translator.inlet)
    m.fs.g02b = Arc(source=m.fs.flue_translator.outlet, destination=m.fs.gts1.inlet)
    m.fs.g03 = Arc(source=m.fs.gts1.outlet, destination=m.fs.mx1.gas)
    m.fs.g04 = Arc(source=m.fs.mx1.outlet, destination=m.fs.gts2.inlet)
    m.fs.g05 = Arc(source=m.fs.gts2.outlet, destination=m.fs.mx2.gas)
    m.fs.g06 = Arc(source=m.fs.mx2.outlet, destination=m.fs.gts3.inlet)
    m.fs.g07 = Arc(source=m.fs.gts3.outlet, destination=m.fs.mx3.gas)
    m.fs.g08 = Arc(source=m.fs.mx3.outlet, destination=m.fs.exhaust_1.inlet)
    # Create arc constraints
    expand_arcs.apply_to(m)
    #
    # Tag model
    #
    tags, tag_format = tag_model(m)
    #
    # Set some scaling
    #
    for i in ["air05", "air07", "air09"]:
        iscale.set_scaling_factor(m.fs.splt1.split_fraction[0.0, i], 100)
    iscale.set_scaling_factor(m.fs.valve01.control_volume.work, 1e-8)
    iscale.set_scaling_factor(m.fs.valve02.control_volume.work, 1e-8)
    iscale.set_scaling_factor(m.fs.valve03.control_volume.work, 1e-8)
    iscale.set_scaling_factor(m.fs.vsv.control_volume.work, 1e-8)
    iscale.set_scaling_factor(m.fs.cmp1.control_volume.work, 1e-8)
    iscale.set_scaling_factor(m.fs.gts1.control_volume.work, 1e-8)
    iscale.set_scaling_factor(m.fs.gts2.control_volume.work, 1e-8)
    iscale.set_scaling_factor(m.fs.gts3.control_volume.work, 1e-8)
    iscale.set_scaling_factor(
        m.fs.gts1.control_volume.properties_in[0].flow_mol, 1e-5)
    iscale.set_scaling_factor(
        m.fs.gts2.control_volume.properties_in[0].flow_mol, 1e-5)
    iscale.set_scaling_factor(
        m.fs.gts3.control_volume.properties_in[0].flow_mol, 1e-5)
    iscale.set_scaling_factor(
        m.fs.gts1.control_volume.properties_out[0].flow_mol, 1e-5)
    iscale.set_scaling_factor(
        m.fs.gts2.control_volume.properties_out[0].flow_mol, 1e-5)
    iscale.set_scaling_factor(
        m.fs.gts3.control_volume.properties_out[0].flow_mol, 1e-5)

    for i, v in m.fs.cmb1.control_volume.rate_reaction_extent.items():
        if i[1] == "ch4_cmb":
            iscale.set_scaling_factor(v, 1e-2)
        else:
            iscale.set_scaling_factor(v, 1)
    for i, c in m.fs.cmb1.reaction_extent.items():
            iscale.constraint_scaling_transform(c, 1e-2)
    for i, v in m.fs.cmb1.control_volume.rate_reaction_generation.items():
        if i[2] in ["O2", "CO2", "CH4", "H2O"]:
            iscale.set_scaling_factor(v, 0.001)
        else:
            iscale.set_scaling_factor(v, 0.1)
    for v in m.fs.cmp1.deltaP.values():
        iscale.set_scaling_factor(v, 1e-6)
    for v in m.fs.gts1.deltaP.values():
        iscale.set_scaling_factor(v, 1e-6)
    for v in m.fs.gts2.deltaP.values():
        iscale.set_scaling_factor(v, 1e-6)
    for v in m.fs.gts3.deltaP.values():
        iscale.set_scaling_factor(v, 1e-6)
    for v in m.fs.valve01.deltaP.values():
        iscale.set_scaling_factor(v, 1e-6)
    for v in m.fs.valve02.deltaP.values():
        iscale.set_scaling_factor(v, 1e-6)
    for v in m.fs.valve03.deltaP.values():
        iscale.set_scaling_factor(v, 1e-6)
    for c in m.fs.o2_flow.values():
        iscale.constraint_scaling_transform(c, 10)
    for c in m.fs.gt_power_eqn.values():
        iscale.constraint_scaling_transform(c, 1e-8)
    for c in m.fs.mx1.enthalpy_mixing_equations.values():
        iscale.constraint_scaling_transform(c, 1e-8)
    for c in m.fs.mx2.enthalpy_mixing_equations.values():
        iscale.constraint_scaling_transform(c, 1e-8)
    for c in m.fs.mx3.enthalpy_mixing_equations.values():
        iscale.constraint_scaling_transform(c, 1e-8)
    for c in m.fs.inject1.enthalpy_mixing_equations.values():
        iscale.constraint_scaling_transform(c, 1e-8)
    for c in m.fs.gts1.performance_curve.head_isen_eqn.values():
        iscale.constraint_scaling_transform(c, 1e-5)
    for c in m.fs.gts1.performance_curve.eff_isen_eqn.values():
        iscale.constraint_scaling_transform(c, 2)
    for c in m.fs.gts2.performance_curve.head_isen_eqn.values():
        iscale.constraint_scaling_transform(c, 1e-5)
    for c in m.fs.gts2.performance_curve.eff_isen_eqn.values():
        iscale.constraint_scaling_transform(c, 2)
    for c in m.fs.gts3.performance_curve.head_isen_eqn.values():
        iscale.constraint_scaling_transform(c, 1e-5)
    for c in m.fs.gts3.performance_curve.eff_isen_eqn.values():
        iscale.constraint_scaling_transform(c, 2)
    for c in m.fs.inject1.mxpress_eqn.values():
        iscale.constraint_scaling_transform(c, 1e-5)
    #
    # Calculate scaling factors/scaling transform of constraints
    #
    iscale.calculate_scaling_factors(m)
    #
    # Set basic model inputs for initialization
    #
    # compressor
    m.fs.vsv.deltaP.fix(-100)
    m.fs.cmp1.efficiency_isentropic.fix(0.9)
    m.fs.cmp1.ratioP.fix(19.075)
    # blabe cooling air valves use expected flow to calculate valve flow
    # coefficients, so here set expected flow and after init the opening will
    # be the fixed var.
    m.fs.valve01.control_volume.properties_in[0].flow_mol.fix(2315)
    m.fs.valve02.control_volume.properties_in[0].flow_mol.fix(509)
    m.fs.valve03.control_volume.properties_in[0].flow_mol.fix(354)
    m.fs.valve01.valve_opening.unfix()
    m.fs.valve02.valve_opening.unfix()
    m.fs.valve03.valve_opening.unfix()
    # Feed streams
    # Air at compressor inlet
    m.fs.feed_air1.flow_mol[:] = 34875.9
    m.fs.feed_air1.temperature.fix(288.15)
    m.fs.feed_air1.pressure.fix(101047)
    for i, v in air_comp.items():
        m.fs.feed_air1.mole_frac_comp[:,i].fix(v)
    # Gas at fuel injection
    m.fs.feed_fuel1.flow_mol.fix(1348.8)
    m.fs.feed_fuel1.temperature.fix(310.928)
    m.fs.feed_fuel1.pressure.fix(3.10264e6)
    for i, v in ng_comp.items():
        m.fs.feed_fuel1.mole_frac_comp[:,i].fix(v)
    #
    # Initialization
    #
    solver = pyo.SolverFactory('ipopt')
    if initialize:
        # feeds
        m.fs.feed_air1.initialize()
        m.fs.feed_fuel1.initialize()
        # compressor
        propagate_state(m.fs.air01)
        m.fs.vsv.initialize()
        propagate_state(m.fs.air02)
        m.fs.cmp1.initialize()
        # splitter
        propagate_state(m.fs.air03)
        m.fs.splt1.split_fraction[0, "air05"].fix(0.0916985*0.73)
        m.fs.splt1.split_fraction[0, "air07"].fix(0.0916985*0.27*0.59)
        m.fs.splt1.split_fraction[0, "air09"].fix(0.0916985*0.27*0.41)
        m.fs.splt1.initialize()
        m.fs.splt1.split_fraction[0, "air05"].unfix()
        m.fs.splt1.split_fraction[0, "air07"].unfix()
        m.fs.splt1.split_fraction[0, "air09"].unfix()
        # inject
        propagate_state(m.fs.air04a)
        m.fs.inject_translator.initialize()
        propagate_state(m.fs.air04b)
        propagate_state(m.fs.fuel01)
        m.fs.inject1.mixed_state[0].pressure = pyo.value(m.fs.inject1.air.pressure[0])
        m.fs.inject1.initialize()
        # combustor
        propagate_state(m.fs.g01)
        m.fs.cmb1.initialize()
        # gas turbine stage 1
        propagate_state(m.fs.g02a)
        m.fs.flue_translator.initialize()
        propagate_state(m.fs.g02b)
        m.fs.gts1.ratioP[0] = 0.7
        m.fs.gts1.initialize()
        # blade cooling air valve01, and calculate a flow coefficent
        propagate_state(m.fs.air05)
        m.fs.valve01.Cv = 2
        m.fs.valve01.Cv.unfix()
        m.fs.valve01.valve_opening.fix(0.85)
        m.fs.valve01.control_volume.properties_out[0].pressure.fix(
            pyo.value(m.fs.gts1.control_volume.properties_out[0].pressure))
        m.fs.valve01.initialize()
        m.fs.valve01.control_volume.properties_out[0].pressure.unfix()
        m.fs.valve01.Cv.fix()
        m.fs.valve01.valve_opening.unfix()
        # mixer 1
        propagate_state(m.fs.air06a)
        m.fs.translator1.initialize()
        propagate_state(m.fs.air06b)
        propagate_state(m.fs.g03)
        m.fs.mx1.mixed_state[0].pressure = pyo.value(m.fs.mx1.gas.pressure[0])
        m.fs.mx1.initialize()
        # gas turbine stage 2
        propagate_state(m.fs.g04)
        m.fs.gts2.ratioP[0] = 0.7
        m.fs.gts2.initialize()
        # blade cooling air valve02, and calculate a flow coefficent
        propagate_state(m.fs.air07)
        m.fs.valve02.Cv = 2
        m.fs.valve02.Cv.unfix()
        m.fs.valve02.valve_opening.fix(0.85)
        m.fs.valve02.control_volume.properties_out[0].pressure.fix(
            pyo.value(m.fs.gts2.control_volume.properties_out[0].pressure))
        m.fs.valve02.initialize()
        m.fs.valve02.control_volume.properties_out[0].pressure.unfix()
        m.fs.valve02.Cv.fix()
        m.fs.valve02.valve_opening.unfix()
        # mixer 2
        propagate_state(m.fs.air08a)
        m.fs.translator2.initialize()
        propagate_state(m.fs.air08b)
        propagate_state(m.fs.g05)
        m.fs.mx2.mixed_state[0].pressure = pyo.value(m.fs.mx2.gas.pressure[0])
        m.fs.mx2.initialize()
        # gas turbine stage 3
        propagate_state(m.fs.g06)
        m.fs.gts3.ratioP[0] = 0.7
        m.fs.gts3.initialize()
        # blade cooling air valve03, and calculate a flow coefficent
        propagate_state(m.fs.air09)
        m.fs.valve03.Cv = 2
        m.fs.valve03.Cv.unfix()
        m.fs.valve03.valve_opening.fix(0.85)
        m.fs.valve03.control_volume.properties_out[0].pressure.fix(
            pyo.value(m.fs.gts3.control_volume.properties_out[0].pressure))
        m.fs.valve03.initialize()
        m.fs.valve03.control_volume.properties_out[0].pressure.unfix()
        m.fs.valve03.Cv.fix()
        m.fs.valve03.valve_opening.unfix()
        # mixer 3
        propagate_state(m.fs.air10a)
        m.fs.translator3.initialize()
        propagate_state(m.fs.air10b)
        propagate_state(m.fs.g07)
        m.fs.mx3.mixed_state[0].pressure = pyo.value(m.fs.mx3.gas.pressure[0])
        m.fs.mx3.initialize()
        # product blocks
        propagate_state(m.fs.g08)
        m.fs.exhaust_1.initialize()
        # Solve
        iscale.constraint_autoscale_large_jac(m)
        solver.solve(m, tee=True)
    return m, solver