Пример #1
0
def test_build_flowsheet():
    model = run_chlorination_block_example(fix_free_chlorine=True)
    property_models.build_prop(model, base="TDS")
    build_translator_from_RO_to_chlorination_block(model)
    # Here, we set 'has_feed' to True because RO is our first block in the flowsheet
    kwargs_desal = {
        "has_desal_feed": True,
        "is_twostage": False,
        "has_ERD": False,
        "RO_type": "0D",
        "RO_base": "TDS",
        "RO_level": "detailed",
    }
    desal_port = desalination.build_desalination(model, **kwargs_desal)
    desalination.scale_desalination(model, **kwargs_desal)
    desalination.initialize_desalination(model, **kwargs_desal)

    # Add the connecting arcs
    model.fs.S1 = Arc(source=desal_port["out"],
                      destination=model.fs.RO_to_Chlor.inlet)
    model.fs.S2 = Arc(
        source=model.fs.RO_to_Chlor.outlet,
        destination=model.fs.ideal_naocl_mixer_unit.inlet_stream,
    )
    TransformationFactory("network.expand_arcs").apply_to(model)

    # Unfix inlet stream for mixer
    unfix_ideal_naocl_mixer_inlet_stream(model)
    check_dof(model)
def solve_flowsheet(**desal_kwargs):
    if desal_kwargs == {}:
        desal_kwargs = flowsheet_two_stage.desal_kwargs

    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})
    build(m, **desal_kwargs)
    TransformationFactory("network.expand_arcs").apply_to(m)

    # scale
    scale(m, **desal_kwargs)
    calculate_scaling_factors(m)

    # initialize
    initialize(m, **desal_kwargs)

    check_dof(m)
    solve_block(m, tee=False, fail_flag=True)

    # report
    print("==================================="
          "\n          Simulation          ")
    report(m, **desal_kwargs)

    return m
def solve_flowsheet(**desal_kwargs):
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})
    build(m, **desal_kwargs)
    TransformationFactory("network.expand_arcs").apply_to(m)

    # scale
    calculate_scaling_factors(m.fs.tb_pretrt_to_desal)
    scale(m, **desal_kwargs)
    calculate_scaling_factors(m)

    # initialize
    m.fs.feed.initialize()
    propagate_state(m.fs.s_pretrt_tb)
    optarg = {'nlp_scaling_method': 'user-scaling'}
    m.fs.tb_pretrt_to_desal.initialize(optarg=optarg)
    initialize(m, **desal_kwargs)

    check_dof(m)
    solve_block(m, tee=False, fail_flag=True)

    # report
    report(m, **desal_kwargs)

    return m
Пример #4
0
def run_ideal_naocl_mixer_example(fixed_dosage=False):
    model = ConcreteModel()
    model.fs = FlowsheetBlock(default={"dynamic": False})

    # Add properties to model
    build_ideal_naocl_prop(model)

    # Add mixer to the model
    build_ideal_naocl_mixer_unit(model)

    # Set some inlet values
    set_ideal_naocl_mixer_inlets(model)

    # Fix the inlets for a solve
    fix_ideal_naocl_mixer_inlets(model)

    # unfix the flow_mol for the naocl_stream and fix dosing rate (alt form)
    if fixed_dosage == True:
        model.fs.ideal_naocl_mixer_unit.naocl_stream.flow_mol[0].unfix()
        model.fs.ideal_naocl_mixer_unit.dosing_rate.fix()

    check_dof(model)

    # initializer mixer
    initialize_ideal_naocl_mixer(model.fs.ideal_naocl_mixer_unit)

    solve_block(model, tee=True)

    display_results_of_ideal_naocl_mixer(model.fs.ideal_naocl_mixer_unit)

    return model
Пример #5
0
def solve_RO(base="TDS", level="simple"):
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})
    property_models.build_prop(m, base="TDS")

    build_RO(m, base=base, level=level)

    # specify feed
    property_models.specify_feed(m.fs.RO.feed_side.properties[0, 0],
                                 base="TDS")
    m.fs.RO.feed_side.properties[0, 0].pressure.fix(50e5)

    # scaling
    calculate_scaling_factors(m)

    # initialize
    m.fs.RO.initialize(optarg={"nlp_scaling_method": "user-scaling"})

    m.fs.RO.display()
    check_dof(m)
    solve_block(m)

    m.fs.RO.report()

    return m
def run_chlorination_block_example(fix_free_chlorine=False):
    model = ConcreteModel()
    model.fs = FlowsheetBlock(default={"dynamic": False})

    # Build the partial flowsheet of a mixer and chlorination unit
    build_ideal_naocl_chlorination_block(model, expand_arcs=True)

    # test the naocl_chlorination_costing
    model.fs.treated_flow_vol = Expression(expr=0.85 * pyunits.m**3 /
                                           pyunits.s)
    costing.build_costing(model)

    # set some values (using defaults for testing)
    set_ideal_naocl_mixer_inlets(
        model,
        dosing_rate_of_NaOCl_mg_per_s=0.4,
        inlet_water_density_kg_per_L=1,
        inlet_temperature_K=298,
        inlet_pressure_Pa=101325,
        inlet_flow_mol_per_s=25,
    )
    set_ideal_naocl_chlorination_inlets(model)

    # fix only the inlets for the mixer
    fix_ideal_naocl_mixer_inlets(model)
    initialize_ideal_naocl_mixer(model.fs.ideal_naocl_mixer_unit)

    # scale and initialize the chlorination unit
    state_args = scale_ideal_naocl_chlorination(
        model.fs.ideal_naocl_chlorination_unit,
        model.fs.ideal_naocl_rxn_params,
        model.fs.ideal_naocl_thermo_params,
        ideal_naocl_reaction_config,
    )

    # initialize the unit
    initialize_ideal_naocl_chlorination(model.fs.ideal_naocl_chlorination_unit,
                                        state_args,
                                        debug_out=False)

    check_dof(model)

    # Scale the full model and call the seq_decomp_initializer
    seq_decomp_initializer(model)

    if fix_free_chlorine:
        setup_block_to_solve_naocl_dosing_rate(model)

    model.fs.costing.initialize()

    results = solver.solve(model, tee=True)
    assert_optimal_termination(results)

    display_results_of_ideal_naocl_mixer(model.fs.ideal_naocl_mixer_unit)
    display_results_of_chlorination_unit(
        model.fs.ideal_naocl_chlorination_unit)

    return model
def test_build_and_scale():

    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})

    # check_build(m, build_func=pretreatment_softening.build)  # assert_units_consistent fails for stoich_reactor
    pretreatment_softening.build(m)
    TransformationFactory("network.expand_arcs").apply_to(m)
    check_dof(m)
    m.fs.feed.display()
Пример #8
0
def solve_pretreatment_NF(**kwargs):
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})

    property_models.build_prop(m, base=kwargs["NF_base"])
    build_pretreatment_NF(m, **kwargs)
    TransformationFactory("network.expand_arcs").apply_to(m)

    scale_pretreatment_NF(m, **kwargs)

    initialize_pretreatment_NF(m, **kwargs)

    check_dof(m)
    solve_block(m, tee=True, fail_flag=True)

    display_pretreatment_NF(m, **kwargs)
Пример #9
0
def solve_SepRO(base="TDS"):
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})
    property_models.build_prop(m, base=base)
    build_SepRO(m, base=base)
    property_models.specify_feed(m.fs.RO.mixed_state[0], base=base)

    check_dof(m)
    calculate_scaling_factors(m)
    solve_block(m)

    m.fs.RO.inlet.display()
    m.fs.RO.permeate.display()
    m.fs.RO.retentate.display()

    return m
Пример #10
0
def solve_SepNF(base="ion"):
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})
    property_models.build_prop(m, base=base)
    build_SepNF(m, base=base)
    property_models.specify_feed(m.fs.NF.mixed_state[0], base=base)

    m.fs.NF.mixed_state[0].mass_frac_phase_comp  # touching for tests
    check_dof(m)
    calculate_scaling_factors(m)
    solve_block(m)

    m.fs.NF.inlet.display()
    m.fs.NF.permeate.display()
    m.fs.NF.retentate.display()

    return m
Пример #11
0
def solve_ZONF(base="ion"):
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})

    property_models.build_prop(m, base=base)
    build_ZONF(m, base=base)
    property_models.specify_feed(m.fs.NF.feed_side.properties_in[0], base="ion")

    check_dof(m)
    calculate_scaling_factors(m)
    solve_block(m)

    m.fs.NF.inlet.display()
    m.fs.NF.permeate.display()
    m.fs.NF.retentate.display()

    return m
Пример #12
0
def solve_desalination(**kwargs):
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})
    property_models.build_prop(m, base="TDS")
    build_desalination(m, **kwargs)
    TransformationFactory("network.expand_arcs").apply_to(m)

    scale_desalination(m, **kwargs)

    initialize_desalination(m, **kwargs)

    check_dof(m)

    solve_block(m)

    display_desalination(m, **kwargs)

    return m
Пример #13
0
def solve_flowsheet_mvp_NF(**kwargs):
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})
    build_flowsheet_mvp_NF(m, **kwargs)
    TransformationFactory("network.expand_arcs").apply_to(m)

    # scale
    pretreatment_NF.scale_pretreatment_NF(m, **kwargs)
    calculate_scaling_factors(m.fs.tb_pretrt_to_desal)
    desalination.scale_desalination(m, **kwargs)
    calculate_scaling_factors(m)

    # initialize
    optarg = {"nlp_scaling_method": "user-scaling"}
    pretreatment_NF.initialize_pretreatment_NF(m, **kwargs)
    m.fs.pretrt_saturation.properties.initialize(optarg=optarg)
    propagate_state(m.fs.s_pretrt_tb)
    m.fs.tb_pretrt_to_desal.initialize(optarg=optarg)
    propagate_state(m.fs.s_tb_desal)
    desalination.initialize_desalination(m, **kwargs)
    m.fs.desal_saturation.properties.initialize()

    m.fs.costing.initialize()

    # check_build(m)
    # check_scaling(m)

    check_dof(m)
    solve_block(m, tee=False, fail_flag=True)

    pretreatment_NF.display_pretreatment_NF(m, **kwargs)
    m.fs.tb_pretrt_to_desal.report()
    desalination.display_desalination(m, **kwargs)
    print(
        "desalination solubility index:", value(m.fs.desal_saturation.saturation_index)
    )
    print(
        "pretreatment solubility index:", value(m.fs.pretrt_saturation.saturation_index)
    )
    print("water recovery:", value(m.fs.system_recovery))
    print("LCOW:", value(m.fs.costing.LCOW))
    print("CP modulus:", value(m.fs.desal_saturation.cp_modulus))

    return m
Пример #14
0
def solve():
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})
    build(m)
    TransformationFactory("network.expand_arcs").apply_to(m)

    scale(m)

    initialize(m)

    check_dof(m)

    # solve
    solve_block(m)

    # display
    display(m)

    return m
Пример #15
0
def solve_flowsheet(has_bypass=True):
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})
    build(m, has_bypass=has_bypass)
    TransformationFactory("network.expand_arcs").apply_to(m)

    # scale
    scale(m, has_bypass=has_bypass)
    calculate_scaling_factors(m)

    # initialize
    initialize(m, has_bypass=has_bypass)

    check_dof(m)
    solve_block(m, tee=True, fail_flag=True)

    # report
    report(m, has_bypass=has_bypass)

    return m
def run_ideal_naocl_chlorination_example():
    model = ConcreteModel()
    model.fs = FlowsheetBlock(default={"dynamic": False})

    # add properties to model
    build_ideal_naocl_prop(model)

    # add equilibrium unit
    build_ideal_naocl_chlorination_unit(model)

    # Set some inlet values
    set_ideal_naocl_chlorination_inlets(model)

    # fix the inlets
    fix_ideal_naocl_chlorination_inlets(model)

    check_dof(model)

    # scale the chlorination unit
    state_args = scale_ideal_naocl_chlorination(
        model.fs.ideal_naocl_chlorination_unit,
        model.fs.ideal_naocl_rxn_params,
        model.fs.ideal_naocl_thermo_params,
        ideal_naocl_reaction_config,
    )

    # initialize the unit
    initialize_ideal_naocl_chlorination(model.fs.ideal_naocl_chlorination_unit,
                                        state_args,
                                        debug_out=False)

    results = solver.solve(model, tee=True)
    assert_optimal_termination(results)

    display_results_of_chlorination_unit(
        model.fs.ideal_naocl_chlorination_unit)

    return model
Пример #17
0
def solve_flowsheet(**desal_kwargs):
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})
    build(m, **desal_kwargs)
    TransformationFactory("network.expand_arcs").apply_to(m)

    # scale
    scale(m, **desal_kwargs)
    calculate_scaling_factors(m)

    # initialize
    m.fs.feed.initialize()
    propagate_state(m.fs.s_pretrt_tb)
    initialize(m, **desal_kwargs)

    check_dof(m)
    solve_block(m, tee=False, fail_flag=True)

    # report
    print('==================================='
          '\n          Simulation          ')
    report(m, **desal_kwargs)

    return m
Пример #18
0
def solve_RO(base='TDS', level='simple'):
    m = ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})
    property_models.build_prop(m, base='TDS')

    build_RO(m, base=base, level=level)

    # specify feed
    property_models.specify_feed(m.fs.RO.feed_side.properties_in[0],
                                 base='TDS')
    m.fs.RO.feed_side.properties_in[0].pressure.fix(50e5)

    # scaling
    calculate_scaling_factors(m)

    # initialize
    m.fs.RO.initialize(optarg={'nlp_scaling_method': 'user-scaling'})

    check_dof(m)
    solve_block(m)

    m.fs.RO.report()

    return m
Пример #19
0
def set_up_optimization(m, system_recovery=0.50, **kwargs):
    set_optimization_components(m, system_recovery, **kwargs)
    check_dof(m, 6)
Пример #20
0
def test_property_seawater_ions():
    m = ConcreteModel()

    m.fs = FlowsheetBlock(default={"dynamic": False})
    m.fs.properties = property_seawater_ions.PropParameterBlock()
    m.fs.stream = m.fs.properties.build_state_block([0], default={})

    # specify
    feed_flow_mass = 1
    feed_mass_frac = {
        "Na": 11122e-6,
        "Ca": 382e-6,
        "Mg": 1394e-6,
        "SO4": 2136e-6,
        "Cl": 20300e-6,
    }
    m.fs.stream[0].flow_mass_phase_comp["Liq", "H2O"].fix(
        feed_flow_mass * (1 - sum(x for x in feed_mass_frac.values())))
    for s in feed_mass_frac:
        m.fs.stream[0].flow_mass_phase_comp["Liq", s].fix(feed_flow_mass *
                                                          feed_mass_frac[s])
    m.fs.stream[0].temperature.fix(273.15 + 25)
    m.fs.stream[0].pressure.fix(101325)

    m.fs.stream[0].mass_frac_phase_comp
    m.fs.stream[0].flow_mol_phase_comp

    # scaling
    m.fs.properties.set_default_scaling("flow_mass_phase_comp",
                                        1,
                                        index=("Liq", "H2O"))
    m.fs.properties.set_default_scaling("flow_mass_phase_comp",
                                        1e2,
                                        index=("Liq", "Na"))
    m.fs.properties.set_default_scaling("flow_mass_phase_comp",
                                        1e4,
                                        index=("Liq", "Ca"))
    m.fs.properties.set_default_scaling("flow_mass_phase_comp",
                                        1e3,
                                        index=("Liq", "Mg"))
    m.fs.properties.set_default_scaling("flow_mass_phase_comp",
                                        1e3,
                                        index=("Liq", "SO4"))
    m.fs.properties.set_default_scaling("flow_mass_phase_comp",
                                        1e2,
                                        index=("Liq", "Cl"))
    iscale.calculate_scaling_factors(m.fs)

    # checking state block
    assert_units_consistent(m)
    check_dof(m)

    # initialize
    m.fs.stream.initialize(optarg={"nlp_scaling_method": "user-scaling"})

    # solve
    solve_block(m)

    # check values
    assert value(m.fs.stream[0].mass_frac_phase_comp["Liq",
                                                     "H2O"]) == pytest.approx(
                                                         0.9647, rel=1e-3)
    assert value(m.fs.stream[0].flow_mol_phase_comp["Liq",
                                                    "Na"]) == pytest.approx(
                                                        0.4838, rel=1e-3)
    assert value(m.fs.stream[0].flow_mol_phase_comp["Liq",
                                                    "Ca"]) == pytest.approx(
                                                        9.531e-3, rel=1e-3)
def set_up_optimization(m, system_recovery=0.50, **kwargs):
    set_optimization_components(m, system_recovery, **kwargs)
    calculate_scaling_factors(m)
    check_dof(m, 7)
Пример #22
0
def set_up_optimization(m, system_recovery=0.7, **kwargs_flowsheet):
    is_twostage = kwargs_flowsheet["is_twostage"]

    # scale
    calculate_scaling_factors(m)

    # unfix variables
    m.fs.splitter.split_fraction[0, "bypass"].unfix()
    m.fs.splitter.split_fraction[0, "bypass"].setlb(0.001)
    m.fs.splitter.split_fraction[0, "bypass"].setub(0.99)

    m.fs.NF.area.unfix()
    m.fs.NF.area.setlb(10)
    m.fs.NF.area.setub(1000)

    m.fs.pump_RO.control_volume.properties_out[0].pressure.unfix()
    m.fs.pump_RO.control_volume.properties_out[0].pressure.setlb(20e5)
    m.fs.pump_RO.control_volume.properties_out[0].pressure.setub(75e5)

    m.fs.RO.area.unfix()
    m.fs.RO.area.setlb(10)
    m.fs.RO.area.setub(300)

    # Set lower bound for water flux at the RO outlet, based on a minimum net driving pressure, NDPmin
    m.fs.RO.NDPmin = Param(initialize=1e5, mutable=True, units=pyunits.Pa)

    m.fs.RO.flux_mass_phase_comp[0, 1, "Liq", "H2O"].setlb(
        value(m.fs.RO.A_comp[0, "H2O"] * m.fs.RO.dens_solvent * m.fs.RO.NDPmin)
    )

    if is_twostage:
        m.fs.max_allowable_pressure = Param(
            initialize=120e5, mutable=True, units=pyunits.pascal
        )
        m.fs.pump_RO2.control_volume.properties_out[0].pressure.unfix()
        m.fs.pump_RO2.control_volume.properties_out[0].pressure.setlb(20e5)
        m.fs.pump_RO2.control_volume.properties_out[0].pressure.setub(
            m.fs.max_allowable_pressure
        )

        m.fs.RO2.area.unfix()
        m.fs.RO2.area.setlb(10)
        m.fs.RO2.area.setub(300)

        # Set lower bound for water flux at the RO outlet, based on a minimum net driving pressure, NDPmin
        m.fs.RO2.NDPmin = Param(initialize=1e5, mutable=True, units=pyunits.Pa)
        m.fs.RO2.flux_mass_phase_comp[0, 1, "Liq", "H2O"].setlb(
            value(m.fs.RO2.A_comp[0, "H2O"] * m.fs.RO2.dens_solvent * m.fs.RO2.NDPmin)
        )

    # add additional constraints
    # fixed system recovery
    m.fs.system_recovery_target = Param(initialize=system_recovery, mutable=True)
    m.fs.system_recovery_tol = Param(initialize=5e-3, mutable=True)
    m.fs.eq_system_recovery = Constraint(
        expr=(
            m.fs.system_recovery_target,
            m.fs.system_recovery,
            m.fs.system_recovery_target + m.fs.system_recovery_tol,
        )
    )

    # saturation index
    m.fs.max_saturation_index = Param(initialize=1.0, mutable=True)
    m.fs.eq_max_saturation_index_desal = Constraint(
        expr=m.fs.desal_saturation.saturation_index <= m.fs.max_saturation_index
    )

    m.fs.max_conc_factor_target = Param(initialize=3.5, mutable=True)
    m.fs.eq_max_conc_NF = Constraint(
        expr=m.fs.NF.feed_side.properties_out[0].mass_frac_phase_comp["Liq", "Ca"]
        <= m.fs.max_conc_factor_target
        * m.fs.feed.properties[0].mass_frac_phase_comp["Liq", "Ca"]
    )

    # set objective
    m.fs.objective = Objective(expr=m.fs.costing.LCOW)

    # set additional constraints to limit local minima
    # NOTE: doesn't seem necessary with new objective
    if False:
        m.fs.inequality_RO_area = Constraint(expr=m.fs.RO.area >= m.fs.RO2.area)
        min_pressure_increase = 1e5
        m.fs.inequality_RO_pressure = Constraint(
            expr=m.fs.pump_RO.control_volume.properties_out[0].pressure
            + min_pressure_increase
            <= m.fs.pump_RO2.control_volume.properties_out[0].pressure
        )
        m.fs.inequality_RO_permeate = Constraint(
            expr=m.fs.RO.permeate_side.properties_mixed[0].flow_vol_phase["Liq"]
            >= m.fs.RO2.permeate_side.properties_mixed[0].flow_vol_phase["Liq"]
        )

    check_dof(m, dof_expected=6 if is_twostage else 4)