Hide code cell content
###############################################################################
# The Institute for the Design of Advanced Energy Systems Integrated Platform
# Framework (IDAES IP) was produced under the DOE Institute for the
# Design of Advanced Energy Systems (IDAES).
#
# Copyright (c) 2018-2023 by the software owners: The Regents of the
# University of California, through Lawrence Berkeley National Laboratory,
# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon
# University, West Virginia University Research Corporation, et al.
###############################################################################


Mixer Unit Model with Ideal Property Package#

Author: Anuja Deshpande
Maintainer: Brandon Paul
Updated: 2023-06-01

Learning Outcomes#

• Demonstrate use of the Mixer unit model in IDAES

• Demonstrate different options available

Problem Statement#

In this example, we will be mixing liquid benzene and liquid toluene streams to form a mixture. The inlet conditions are as follows:

Stream 1:

Benzene Flow Rate = 100 mol/s

Pressure = 101325 Pa

Temperature = 353 K

Stream 2

Toluene Flow Rate = 100 mol/s

Pressure = 202650 Pa

Temperature = 356 K

We will look at two cases in this tutorial:

• Case 1: Specify the number of inlets to the mixer, and set the momentum_mixing type set to “minimize”

• Case 2: Specify the inlet names, and set momentum_mixing type set to “equality” (in this case, pressure will be specified for only one inlet stream)

Note: When the momentum mixing type is set to ‘minimize’, the mixed stream pressure takes the minimum value among all inlet stream pressures. When the momentum mixing type is set to ‘equality’, the mixed stream, along with all inlet streams have the same value of pressure.

Setting up the problem in IDAES#

In the following cell, we will be importing the necessary components from Pyomo and IDAES.

# Import objects from pyomo package
from pyomo.environ import ConcreteModel, SolverFactory, value

# Import the main FlowsheetBlock from IDAES. The flowsheet block will contain the unit model
from idaes.core import FlowsheetBlock

# Import the mixer unit model
from idaes.models.unit_models import Mixer, MomentumMixingType

# Import idaes logger to set output levels
import idaes.logger as idaeslog

# Import the BTX_ideal property package to create a properties block for the flowsheet
from idaes.models.properties.activity_coeff_models import BTX_activity_coeff_VLE

# Import the degrees_of_freedom function from the idaes.core.util.model_statistics package
# DOF = Number of Model Variables - Number of Model Constraints
from idaes.core.util.model_statistics import degrees_of_freedom

# Create the ConcreteModel and the FlowsheetBlock objects, and attach the flowsheet block to it.
m = ConcreteModel()

m.fs = FlowsheetBlock(
dynamic=False
)  # dynamic or ss flowsheet needs to be specified here

# Add properties parameter block to the flowsheet with specifications
m.fs.properties = BTX_activity_coeff_VLE.BTXParameterBlock(
valid_phase="Liq", activity_coeff_model="Ideal"
)


Case 1:#

Specify the number of inlets to the mixer, and set the momentum_mixing type set to “minimize”.

# Create an instance of the mixer unit, attaching it to the flowsheet
# Specify that the property package to be used with the mixer is the
# one we created earlier, the number of mixer inlets is 2, and momentum
# mixing type is minimize

m.fs.mixer_1 = Mixer(
property_package=m.fs.properties,
num_inlets=2,
momentum_mixing_type=MomentumMixingType.minimize,
)

# Call the degrees_of_freedom function, get initial DOF
DOF_initial = degrees_of_freedom(m)
print("The initial degrees of freedom is: {0}".format(DOF_initial))

The initial degrees of freedom is: 10


For case 1, we chose to specify only the number of inlets and names were not specified. When this option is selected, the inlets are named as “inlet_1”, “inlet_2” and so on depending on the number of inlets specified. In the following cell, we will use this naming convention to specify the inlet conditions.

# Fix the inlet conditions

# Benzene stream
m.fs.mixer_1.inlet_1.flow_mol.fix(100)  # converting to mol/s as unit basis is mol/s
m.fs.mixer_1.inlet_1.mole_frac_comp[0, "benzene"].fix(1)
m.fs.mixer_1.inlet_1.mole_frac_comp[0, "toluene"].fix(0)
m.fs.mixer_1.inlet_1.pressure.fix(101325)  # Pa
m.fs.mixer_1.inlet_1.temperature.fix(353)  # K

# Toluene stream
m.fs.mixer_1.inlet_2.flow_mol.fix(100)  # converting to mol/s as unit basis is mol/s
m.fs.mixer_1.inlet_2.mole_frac_comp[0, "benzene"].fix(0)
m.fs.mixer_1.inlet_2.mole_frac_comp[0, "toluene"].fix(1)
m.fs.mixer_1.inlet_2.pressure.fix(202650)  # Pa
m.fs.mixer_1.inlet_2.temperature.fix(356)  # K

# Call the degrees_of_freedom function, get final DOF
DOF_final = degrees_of_freedom(m)
print("The final degrees of freedom is: {0}".format(DOF_final))

The final degrees of freedom is: 0


Flowsheet Initialization#

# Initialize the flowsheet, and set the output at WARNING
m.fs.mixer_1.initialize(outlvl=idaeslog.WARNING)


Obtaining Simulation Results#

# Solve the simulation using ipopt
# Note: If the degrees of freedom = 0, we have a square problem
opt = SolverFactory("ipopt")
result = opt.solve(m, tee=True)

Ipopt 3.13.2:

******************************************************************************
This program contains Ipopt, a library for large-scale nonlinear optimization.
Ipopt is released as open source code under the Eclipse Public License (EPL).

This version of Ipopt was compiled from source code available at
https://github.com/IDAES/Ipopt as part of the Institute for the Design of
Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE
Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.

This version of Ipopt was compiled using HSL, a collection of Fortran codes
for large-scale scientific computation.  All technical papers, sales and
publicity material resulting from use of the HSL codes within IPOPT must
contain the following acknowledgement:
HSL, a collection of Fortran codes for large-scale scientific
computation. See http://www.hsl.rl.ac.uk.
******************************************************************************

This is Ipopt version 3.13.2, running with linear solver ma27.

Number of nonzeros in equality constraint Jacobian...:       68
Number of nonzeros in inequality constraint Jacobian.:        0
Number of nonzeros in Lagrangian Hessian.............:       31

Total number of variables............................:       25
variables with only lower bounds:        3
variables with lower and upper bounds:        8
variables with only upper bounds:        0
Total number of equality constraints.................:       25
Total number of inequality constraints...............:        0
inequality constraints with only lower bounds:        0
inequality constraints with lower and upper bounds:        0
inequality constraints with only upper bounds:        0

iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
0  0.0000000e+00 3.58e+02 1.00e+00  -1.0 0.00e+00    -  0.00e+00 0.00e+00   0
1  0.0000000e+00 3.58e+00 1.00e-02  -1.0 1.00e-02    -  9.90e-01 9.90e-01h  1
2  0.0000000e+00 3.54e-02 1.98e-03  -1.0 1.00e-04    -  9.90e-01 9.90e-01h  1
3  0.0000000e+00 9.31e-10 1.32e+01  -1.0 9.90e-07    -  1.00e+00 1.00e+00h  1

Number of Iterations....: 3

(scaled)                 (unscaled)
Objective...............:   0.0000000000000000e+00    0.0000000000000000e+00
Dual infeasibility......:   0.0000000000000000e+00    0.0000000000000000e+00
Constraint violation....:   2.0968859831870735e-12    9.3132257461547852e-10
Complementarity.........:   0.0000000000000000e+00    0.0000000000000000e+00
Overall NLP error.......:   2.0968859831870735e-12    9.3132257461547852e-10

Number of objective function evaluations             = 4
Number of objective gradient evaluations             = 4
Number of equality constraint evaluations            = 4
Number of inequality constraint evaluations          = 0
Number of equality constraint Jacobian evaluations   = 4
Number of inequality constraint Jacobian evaluations = 0
Number of Lagrangian Hessian evaluations             = 3
Total CPU secs in IPOPT (w/o function evaluations)   =      0.000
Total CPU secs in NLP function evaluations           =      0.000

EXIT: Optimal Solution Found.



View Results#

# Display output report
m.fs.mixer_1.report()

====================================================================================
Unit : fs.mixer_1                                                          Time: 0.0
------------------------------------------------------------------------------------
Stream Table
Units       inlet_1  inlet_2   Outlet
flow_mol                mole / second     100      100      200.00
mole_frac_comp benzene  dimensionless       1        0     0.50000
mole_frac_comp toluene  dimensionless       0        1     0.50000
temperature                    kelvin     353      356      354.61
pressure                       pascal  101325   202650  1.0133e+05
====================================================================================


Case 2#

For case 2, we will specify the inlet names for the two inlets, and set momentum_mixing type set to “equality” (in this case, pressure will be specified for only one inlet stream). We will name the 2 inlets as “benzene_inlet” and “toluene_inlet”.

# Create an instance of another mixer unit, attaching it to the same flowsheet.
# Specify that the property package to be used with the mixer is the one we created earlier,
# inlet list is specified but names are specified, and momentum mixing type is equality

m.fs.mixer_2 = Mixer(
property_package=m.fs.properties,
inlet_list=["benzene_inlet", "toluene_inlet"],
momentum_mixing_type=MomentumMixingType.equality,
)

# Check the required degrees of freedom
DOF_init = degrees_of_freedom(m.fs.mixer_2)
print("The initial degrees of freedom is: {0}".format(DOF_init))

The initial degrees of freedom is: 9


We see that the degrees of freedom has dropped by 1 to 9 when compared with case 1. This is because we selected the momentum_mixing_type as MomentumMixingType.equality which basically adds a constraint that equates the pressure between all inlets and the outlet. Therefore, when we specify the inlet confitions in the next cell, we will define the pressure for only the benzene_inlet stream.

# Fix the stream inlet conditions

# Benzene stream
m.fs.mixer_2.benzene_inlet.flow_mol.fix(
100
)  # converting to mol/s as unit basis is mol/s
m.fs.mixer_2.benzene_inlet.mole_frac_comp[0, "benzene"].fix(1)
m.fs.mixer_2.benzene_inlet.mole_frac_comp[0, "toluene"].fix(0)
m.fs.mixer_2.benzene_inlet.pressure.fix(
101325
)  # Pa , Another option is m1.fs.mixer2.inlet2.pressure.fix(202650)
m.fs.mixer_2.benzene_inlet.temperature.fix(353)  # K

# Toluene stream
m.fs.mixer_2.toluene_inlet.flow_mol.fix(
100
)  # converting to mol/s as unit basis is mol/s
m.fs.mixer_2.toluene_inlet.mole_frac_comp[0, "benzene"].fix(0)
m.fs.mixer_2.toluene_inlet.mole_frac_comp[0, "toluene"].fix(1)
m.fs.mixer_2.toluene_inlet.temperature.fix(356)  # K

DOF_final = degrees_of_freedom(m.fs.mixer_2)
print("The final degrees of freedom is: {0}".format(DOF_final))

The final degrees of freedom is: 0


Flowsheet Initialization#

# Initialize the flowsheet, and set the output at WARNING

m.fs.mixer_2.initialize(outlvl=idaeslog.WARNING)


Obtaining Simulation Results#

# Solve the simulation using ipopt
# Note: If the degrees of freedom = 0, we have a square problem
opt = SolverFactory("ipopt")
result = opt.solve(m.fs.mixer_2, tee=True)

Ipopt 3.13.2:

******************************************************************************
This program contains Ipopt, a library for large-scale nonlinear optimization.
Ipopt is released as open source code under the Eclipse Public License (EPL).

This version of Ipopt was compiled from source code available at
https://github.com/IDAES/Ipopt as part of the Institute for the Design of
Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE
Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.

This version of Ipopt was compiled using HSL, a collection of Fortran codes
for large-scale scientific computation.  All technical papers, sales and
publicity material resulting from use of the HSL codes within IPOPT must
contain the following acknowledgement:
HSL, a collection of Fortran codes for large-scale scientific
computation. See http://www.hsl.rl.ac.uk.
******************************************************************************

This is Ipopt version 3.13.2, running with linear solver ma27.

Number of nonzeros in equality constraint Jacobian...:       66
Number of nonzeros in inequality constraint Jacobian.:        0
Number of nonzeros in Lagrangian Hessian.............:       30

Total number of variables............................:       24
variables with only lower bounds:        4
variables with lower and upper bounds:        8
variables with only upper bounds:        0
Total number of equality constraints.................:       24
Total number of inequality constraints...............:        0
inequality constraints with only lower bounds:        0
inequality constraints with lower and upper bounds:        0
inequality constraints with only upper bounds:        0

iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
0  0.0000000e+00 3.58e+02 1.00e+00  -1.0 0.00e+00    -  0.00e+00 0.00e+00   0
1  0.0000000e+00 3.58e+00 1.00e-02  -1.0 1.00e-02    -  9.90e-01 9.90e-01h  1
2  0.0000000e+00 3.54e-02 1.98e-03  -1.0 1.00e-04    -  9.90e-01 9.90e-01h  1
3  0.0000000e+00 9.31e-10 1.32e+01  -1.0 9.90e-07    -  1.00e+00 1.00e+00h  1

Number of Iterations....: 3

(scaled)                 (unscaled)
Objective...............:   0.0000000000000000e+00    0.0000000000000000e+00
Dual infeasibility......:   0.0000000000000000e+00    0.0000000000000000e+00
Constraint violation....:   2.0968859831870735e-12    9.3132257461547852e-10
Complementarity.........:   0.0000000000000000e+00    0.0000000000000000e+00
Overall NLP error.......:   2.0968859831870735e-12    9.3132257461547852e-10

Number of objective function evaluations             = 4
Number of objective gradient evaluations             = 4
Number of equality constraint evaluations            = 4
Number of inequality constraint evaluations          = 0
Number of equality constraint Jacobian evaluations   = 4
Number of inequality constraint Jacobian evaluations = 0
Number of Lagrangian Hessian evaluations             = 3
Total CPU secs in IPOPT (w/o function evaluations)   =      0.001
Total CPU secs in NLP function evaluations           =      0.000

EXIT: Optimal Solution Found.



View Results#

# Display a readable report
m.fs.mixer_2.report()

====================================================================================
Unit : fs.mixer_2                                                          Time: 0.0
------------------------------------------------------------------------------------
Stream Table
Units       benzene_inlet  toluene_inlet   Outlet
flow_mol                mole / second        100           100.00       200.00
mole_frac_comp benzene  dimensionless          1           0.0000      0.50000
mole_frac_comp toluene  dimensionless          0           1.0000      0.50000
temperature                    kelvin        353           356.00       354.61
pressure                       pascal     101325       1.0132e+05   1.0132e+05
====================================================================================