Ejemplo n.º 1
0
def test_property_construction_unordered():
    """
    The purpose of this test is to make sure "chained construction"
    of properties happens properly. I.e. if we add a property that
    requires several other properties, these are added as well.
    """
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})
    m.fs.properties = GasPhaseParameterBlock()
    m.fs.state = m.fs.properties.build_state_block()

    nvar = 7
    ncon = 1
    assert len(list(m.component_data_objects(Var))) == nvar
    assert len(list(m.component_data_objects(Constraint))) == ncon

    # Access this property to force the construction of prerequisite
    # properties.
    m.fs.state.cp_mass

    # Make sure dependent properties have been properly added.
    assert hasattr(m.fs.state, "cp_mol")
    assert hasattr(m.fs.state, "cp_mol_comp")
    assert hasattr(m.fs.state, "mw")
    nvar += len(m.fs.state.cp_mol_comp)
    nvar += len(m.fs.state.cp_mol)
    nvar += len(m.fs.state.cp_mass)
    nvar += len(m.fs.state.mw)
    ncon += len(m.fs.state.cp_mol_comp)
    ncon += len(m.fs.state.cp_mol)
    ncon += len(m.fs.state.cp_mass)
    ncon += len(m.fs.state.mw)
    assert len(list(m.component_data_objects(Var))) == nvar
    assert len(list(m.component_data_objects(Constraint))) == ncon
Ejemplo n.º 2
0
    def _make_model(self):
        m = ConcreteModel()
        m.fs = FlowsheetBlock(default={"dynamic": False})

        m.fs.solid_properties = SolidPhaseParameterBlock()
        m.fs.solid_state = m.fs.solid_properties.build_state_block(default={
            "parameters": m.fs.solid_properties,
            "defined_state": True,
            })

        m.fs.gas_properties = GasPhaseParameterBlock()
        m.fs.gas_state = m.fs.gas_properties.build_state_block(default={
            "parameters": m.fs.gas_properties,
            "defined_state": True,
            })

        m.fs.reaction_properties = HeteroReactionParameterBlock(default={
            "solid_property_package": m.fs.solid_properties,
            "gas_property_package": m.fs.gas_properties,
            })
        m.fs.reaction_block = m.fs.reaction_properties.reaction_block_class(
                default={
                    "parameters": m.fs.reaction_properties,
                    "solid_state_block": m.fs.solid_state,
                    "gas_state_block": m.fs.gas_state,
                    "has_equilibrium": False,
                })

        for var in m.fs.gas_state.define_state_vars().values():
            var.fix()
        for var in m.fs.solid_state.define_state_vars().values():
            var.fix()
        return m
Ejemplo n.º 3
0
def test_property_construction_ordered():
    """
    The purpose of this test is to make sure each property can be
    constructed properly. Further, because we know that these
    variables form a DAG, we check that the addition of each new
    property adds one variable and constraint, i.e. that the
    matching defined in the parameter block is in topological order.
    """
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})
    m.fs.properties = GasPhaseParameterBlock()
    m.fs.state = m.fs.properties.build_state_block()

    nvar = 7
    ncon = 1
    assert len(list(m.component_data_objects(Var))) == nvar
    assert len(list(m.component_data_objects(Constraint))) == ncon

    matching = [
        ('mw', 'mw_eqn'),
        ('dens_mol', 'ideal_gas'),
        ('dens_mol_comp', 'comp_conc_eqn'),
        ('dens_mass', 'dens_mass_basis'),
        ('visc_d', 'visc_d_constraint'),
        ('diffusion_comp', 'diffusion_comp_constraint'),
        ('therm_cond', 'therm_cond_constraint'),
        ('cp_mol_comp', 'cp_shomate_eqn'),
        ('cp_mol', 'mixture_heat_capacity_eqn'),
        ('cp_mass', 'cp_mass_basis'),
        ('enth_mol_comp', 'enthalpy_shomate_eqn'),
        ('enth_mol', 'mixture_enthalpy_eqn'),
    ]

    # Make sure the matching captures all the non-state vars.
    state_vars = m.fs.state.define_state_vars()
    n_state_vars = len(state_vars)
    n_vars = len(m.fs.properties._metadata._properties)
    assert len(matching) == n_vars - n_state_vars

    # Make sure we can add constraints one at a time, and only
    # add one additional variable. This is specific to this
    # property package.
    for varname, conname in matching:
        assert varname not in state_vars
        var = getattr(m.fs.state, varname)
        con = getattr(m.fs.state, conname)
        dim = len(var)
        nvar += dim
        ncon += dim
        assert dim == len(con)
        assert isinstance(var, Var)
        assert isinstance(con, Constraint)
        assert len(list(m.component_data_objects(Var))) == nvar
        assert len(list(m.component_data_objects(Constraint))) == ncon
Ejemplo n.º 4
0
 def _make_model(self):
     m = ConcreteModel()
     m.fs = FlowsheetBlock(default={"dynamic": False})
     m.fs.properties = GasPhaseParameterBlock()
     m.fs.state = m.fs.properties.build_state_block(
         default={
             # defined_state True because we want to ensure the state
             # block is square.
             "defined_state": True,
         })
     for var in m.fs.state.define_state_vars().values():
         var.fix()
     return m
Ejemplo n.º 5
0
def test_state_vars():
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})

    m.fs.solid_properties = SolidPhaseParameterBlock()
    m.fs.solid_state = m.fs.solid_properties.build_state_block(
        default={
            "parameters": m.fs.solid_properties,
            "defined_state": True,
        })

    m.fs.gas_properties = GasPhaseParameterBlock()
    m.fs.gas_state = m.fs.gas_properties.build_state_block(
        default={
            "parameters": m.fs.gas_properties,
            "defined_state": True,
        })

    m.fs.reaction_properties = HeteroReactionParameterBlock(
        default={
            "solid_property_package": m.fs.solid_properties,
            "gas_property_package": m.fs.gas_properties,
        })
    m.fs.reaction_block = m.fs.reaction_properties.reaction_block_class(
        default={
            "parameters": m.fs.reaction_properties,
            "solid_state_block": m.fs.solid_state,
            "gas_state_block": m.fs.gas_state,
            "has_equilibrium": False,
        })

    for var in m.fs.gas_state.define_state_vars().values():
        var.fix()
    for var in m.fs.solid_state.define_state_vars().values():
        var.fix()

    # Note that these checks are necessary to trigger the construction of
    # the reaction block variables
    assert isinstance(m.fs.reaction_block.k_rxn, Var)
    assert isinstance(m.fs.reaction_block.OC_conv, Var)
    assert isinstance(m.fs.reaction_block.OC_conv_temp, Var)
    assert isinstance(m.fs.reaction_block.reaction_rate, Var)

    assert degrees_of_freedom(m) == 0

    rxn_vars = list(m.fs.reaction_block.component_data_objects(Var))
    rxn_cons = list(m.fs.reaction_block.component_data_objects(Constraint))
    assert len(rxn_vars) == 4
    assert len(rxn_cons) == 4
Ejemplo n.º 6
0
def rxn_prop():
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})

    # Set up thermo props and reaction props
    m.fs.solid_properties = SolidPhaseParameterBlock()
    m.fs.solid_state_block = m.fs.solid_properties.build_state_block(
        default={
            "parameters": m.fs.solid_properties,
            "defined_state": True
        })

    m.fs.gas_properties = GasPhaseParameterBlock()
    m.fs.gas_state_block = m.fs.gas_properties.build_state_block(
        default={
            "parameters": m.fs.gas_properties,
            "defined_state": True
        })

    m.fs.reactions = HeteroReactionParameterBlock(
        default={
            "solid_property_package": m.fs.solid_properties,
            "gas_property_package": m.fs.gas_properties
        })
    m.fs.unit = m.fs.reactions.reaction_block_class(
        default={
            "parameters": m.fs.reactions,
            "solid_state_block": m.fs.solid_state_block,
            "gas_state_block": m.fs.gas_state_block,
            "has_equilibrium": False
        })

    # Fix required variables to make reaction model square
    # (gas mixture and component densities,
    # solid particle porosity, density and component fractions)
    m.fs.gas_state_block.dens_mol.fix(10)
    m.fs.gas_state_block.dens_mol_comp.fix(10)
    m.fs.solid_state_block.particle_porosity.fix(0.23)
    m.fs.solid_state_block.mass_frac_comp["Fe2O3"].fix(0.244)
    m.fs.solid_state_block.mass_frac_comp["Fe3O4"].fix(0.202)
    m.fs.solid_state_block.mass_frac_comp["Al2O3"].fix(0.554)
    m.fs.solid_state_block.dens_mass_skeletal.fix(3125)
    m.fs.solid_state_block.temperature.fix(1183.15)  # K

    return m
Ejemplo n.º 7
0
def gas_prop():
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})

    # gas properties and state inlet block
    m.fs.properties = GasPhaseParameterBlock()
    m.fs.unit = m.fs.properties.build_state_block(default={
        "parameters": m.fs.properties,
        "defined_state": True
    })

    m.fs.unit.flow_mol.fix(1)
    m.fs.unit.temperature.fix(450)
    m.fs.unit.pressure.fix(1.60)
    m.fs.unit.mole_frac_comp["CO2"].fix(0.0004)
    m.fs.unit.mole_frac_comp["H2O"].fix(0.0093)
    m.fs.unit.mole_frac_comp["O2"].fix(0.2095)
    m.fs.unit.mole_frac_comp["N2"].fix(0.7808)

    return m
Ejemplo n.º 8
0
def test_indexed_state_block():
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})
    m.fs.properties = GasPhaseParameterBlock()
    m.fs.state = m.fs.properties.build_state_block([1, 2, 3])

    assert len(list(m.component_data_objects(Var))) == 21
    assert len(list(m.component_data_objects(Constraint))) == 3

    for i, state in m.fs.state.items():
        assert isinstance(state.flow_mol, Var)
        assert isinstance(state.temperature, Var)
        assert isinstance(state.pressure, Var)
        assert isinstance(state.mole_frac_comp, Var)

        assert isinstance(state.sum_component_eqn, Constraint)

        for name, var in state.define_state_vars().items():
            # State vars should be included in the metadata with no method
            assert name in m.fs.properties._metadata._properties
            assert m.fs.properties._metadata._properties[name]["method"] is None
Ejemplo n.º 9
0
def main():

    # ---------------------------------------------------------------------
    # Build model

    # Create a concrete model
    m = ConcreteModel()

    # Create a steady-state flowsheet
    m.fs = FlowsheetBlock(default={"dynamic": False})

    # Set up thermo-physical and reaction properties
    m.fs.gas_properties = GasPhaseParameterBlock()
    m.fs.solid_properties = SolidPhaseParameterBlock()

    m.fs.hetero_reactions = HeteroReactionParameterBlock(
            default={"solid_property_package": m.fs.solid_properties,
                     "gas_property_package": m.fs.gas_properties})

    # Build the BFB in the flowsheet
    m.fs.BFB = BubblingFluidizedBed(
            default={
                    "flow_type": "co_current",
                    "finite_elements": 5,
                    "transformation_method": "dae.collocation",
                    "gas_phase_config":
                    {"property_package": m.fs.gas_properties},
                    "solid_phase_config":
                    {"property_package": m.fs.solid_properties,
                     "reaction_package": m.fs.hetero_reactions
                     }})

    # ---------------------------------------------------------------------
    # Set design and operating variables of the BFB model

    # Fix design variables
    m.fs.BFB.number_orifice.fix(2500)  # [-]
    m.fs.BFB.bed_diameter.fix(6.5)  # m
    m.fs.BFB.bed_height.fix(5)  # m

    # Fix inlet port variables for gas and solid
    m.fs.BFB.gas_inlet.flow_mol[0].fix(1567.79)  # mol/s
    m.fs.BFB.gas_inlet.temperature[0].fix(373)  # K
    m.fs.BFB.gas_inlet.pressure[0].fix(1.86)  # bar
    m.fs.BFB.gas_inlet.mole_frac_comp[0, "O2"].fix(0.2095)
    m.fs.BFB.gas_inlet.mole_frac_comp[0, "N2"].fix(0.7808)
    m.fs.BFB.gas_inlet.mole_frac_comp[0, "CO2"].fix(0.0004)
    m.fs.BFB.gas_inlet.mole_frac_comp[0, "H2O"].fix(0.0093)

    m.fs.BFB.solid_inlet.flow_mass[0].fix(1230.865)  # kg/s
    # Particle porosity:
    # The porosity of the OC particle at the inlet is calculated from the
    # known bulk density of the fresh OC particle (3251.75 kg/m3), and the
    # skeletal density of the fresh OC particle (calculated from the known
    # composition of the fresh particle, and the skeletal density of its
    # components [see the solids property package])
    m.fs.BFB.solid_inlet.particle_porosity[0].fix(0.27)
    m.fs.BFB.solid_inlet.temperature[0].fix(1173.9)  # K
    m.fs.BFB.solid_inlet.mass_frac_comp[0, "Fe2O3"].fix(0.244162011502)
    m.fs.BFB.solid_inlet.mass_frac_comp[0, "Fe3O4"].fix(0.201998299487)
    m.fs.BFB.solid_inlet.mass_frac_comp[0, "Al2O3"].fix(0.553839689011)
    # ---------------------------------------------------------------------
    # Initialize reactor

    t_start = time.time()  # Run start time

    # State arguments for initializing property state blocks
    # Bubble and gas_emulsion temperatures are initialized at solid
    # temperature because thermal mass of solid >> thermal mass of gas
    blk = m.fs.BFB
    gas_phase_state_args = {
            'flow_mol': blk.gas_inlet.flow_mol[0].value,
            'temperature': blk.solid_inlet.temperature[0].value,
            'pressure': blk.gas_inlet.pressure[0].value,
            'mole_frac': {
                'O2': blk.gas_inlet.mole_frac_comp[0, 'O2'].value,
                'N2': blk.gas_inlet.mole_frac_comp[0, 'N2'].value,
                'CO2': blk.gas_inlet.mole_frac_comp[0, 'CO2'].value,
                'H2O': blk.gas_inlet.mole_frac_comp[0, 'H2O'].value}}
    solid_phase_state_args = {
            'flow_mass': blk.solid_inlet.flow_mass[0].value,
            'particle_porosity': blk.solid_inlet.particle_porosity[0].value,
            'temperature': blk.solid_inlet.temperature[0].value,
            'mass_frac': {
                    'Fe2O3': blk.solid_inlet.mass_frac_comp[0, 'Fe2O3'].value,
                    'Fe3O4': blk.solid_inlet.mass_frac_comp[0, 'Fe3O4'].value,
                    'Al2O3': blk.solid_inlet.mass_frac_comp[0, 'Al2O3'].value}}

    m.fs.BFB.initialize(outlvl=idaeslog.INFO,
                        gas_phase_state_args=gas_phase_state_args,
                        solid_phase_state_args=solid_phase_state_args)

    t_initialize = time.time()  # Initialization time

    # ---------------------------------------------------------------------
    # Final solve

    # Create a solver
    solver = SolverFactory('ipopt')
    solver.solve(m.fs.BFB, tee=True)

    t_simulation = time.time()  # Simulation time

    print("\n")
    print("----------------------------------------------------------")
    print('Total initialization time: ', value(t_initialize - t_start), " s")
    print("----------------------------------------------------------")

    print("\n")
    print("----------------------------------------------------------")
    print('Total simulation time: ', value(t_simulation - t_start), " s")
    print("----------------------------------------------------------")

    return m