Translator¶
Tutorial: Translator Unit Model with Modular Property Package¶
Learning Outcomes¶
- Demonstrate use of the Translator unit model in IDAES
Problem Statement¶
In this tutorial, we will be transforming an inlet stream that uses the Benzene-Toluene Ideal property package to an outlet stream that uses a user-created configuration file. The state variables for each stream are as follows:
Inlet State Variables(FTPx):
Flow Rate = 100 mol/s
Temperature = 298 K
Pressure = 101325 Pa
Mole Fraction (benzene) = 0.6
Mole Fraction (toluene) = 0.4
Outlet State Variables (FcTP):
Benzene Molar Flow = 60 mol/s
Toluene Molar Flow = 40 mol/s
Temperature = 298 K
Pressure = 101325 Pa
The translator block is able to link two streams with different property packages, so it is required in complex flowsheets where separate property packages are used for different parts of the flowsheet. If the property packages being translated do not share the same state variables, the user may need to create constraints to complete this conversion. More information on the translator model can be found here: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/translator.html
For more details, please refer to the IDAES documentation: https://idaes-pse.readthedocs.io/en/stable
Importing necessary tools¶
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, Constraint, value, SolverFactory
# Import the solver
from idaes.core.solvers import get_solver
# Import the main FlowsheetBlock from IDAES. The flowsheet block will contain the unit model
from idaes.core import FlowsheetBlock
# Import the product unit model
from idaes.models.unit_models import Translator
# Import idaes logger to set output levels
import idaes.logger as idaeslog
# Import the modular property package to create a property block for the flowsheet
from idaes.models.properties.modular_properties.base.generic_property import GenericParameterBlock
# Import the BT_ideal property package to create a configuration file for the GenericParameterBlock based on the ideal eos
from idaes.models.properties.modular_properties.examples.BT_ideal import configuration as configuration_FTPx
# 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
Setting up the flowsheet¶
In the following cell, we will create the ConcreteModel
foundation and attach the steady state flowsheet.
More information on this general workflow can be found here: https://idaes-pse.readthedocs.io/en/stable/how_to_guides/workflow/general.html
m = ConcreteModel()
m.fs = FlowsheetBlock(dynamic=False) # dynamic or ss flowsheet needs to be specified here
In the following cell, we will create a configuration file that is similar to the BT_ideal configuration, except this example will use FcTP state variables rather than FTPx state variables.
# Import Component to create the benzene and toluene variables
from idaes.core import Component
# Import pyunits to define the units of variables
from pyomo.environ import units as pyunits
# Import potential phases
from idaes.core import LiquidPhase, VaporPhase
# Import the state definition
from idaes.models.properties.modular_properties.state_definitions import FcTP
# Import the ideal equation of state
from idaes.models.properties.modular_properties.eos.ideal import Ideal
# Import the phase equilibrium state
from idaes.models.properties.modular_properties.phase_equil import SmoothVLE
# Import the bubble dew method
from idaes.models.properties.modular_properties.phase_equil.bubble_dew import (
IdealBubbleDew,
)
# Import the fugacity term
from idaes.models.properties.modular_properties.phase_equil.forms import fugacity
# Import the following literature references
import idaes.models.properties.modular_properties.pure.Perrys as Perrys
import idaes.models.properties.modular_properties.pure.RPP4 as RPP4
import idaes.models.properties.modular_properties.pure.NIST as NIST
configuration_FcTP = {
"components": {
"benzene": {
"type": Component,
"dens_mol_liq_comp": Perrys,
"enth_mol_liq_comp": Perrys,
"enth_mol_ig_comp": RPP4,
"pressure_sat_comp": NIST,
"phase_equilibrium_form": {("Vap", "Liq"): fugacity},
"parameter_data": {
"mw": 78.1136e-3, # [1]
"pressure_crit": 48.9e5, # [1]
"temperature_crit": 562.2, # [1]
"dens_mol_liq_comp_coeff": {
"eqn_type": 1,
"1": 1.0162, # [2] pg. 2-98
"2": 0.2655,
"3": 562.16,
"4": 0.28212,
},
"cp_mol_ig_comp_coeff": {
"A": -3.392e1, # [1]
"B": 4.739e-1,
"C": -3.017e-4,
"D": 7.130e-8,
},
"cp_mol_liq_comp_coeff": {
"1": 1.29e2, # [2]
"2": -1.7e-1,
"3": 6.48e-4,
"4": 0,
"5": 0,
},
"enth_mol_form_liq_comp_ref": 49.0e3, # [3]
"enth_mol_form_vap_comp_ref": 82.9e3, # [3]
"pressure_sat_comp_coeff": {
"A": 4.72583, # [NIST]
"B": 1660.652,
"C": -1.461,
},
},
},
"toluene": {
"type": Component,
"dens_mol_liq_comp": Perrys,
"enth_mol_liq_comp": Perrys,
"enth_mol_ig_comp": RPP4,
"pressure_sat_comp": NIST,
"phase_equilibrium_form": {("Vap", "Liq"): fugacity},
"parameter_data": {
"mw": 92.1405e-3, # [1]
"pressure_crit": 41e5, # [1]
"temperature_crit": 591.8, # [1]
"dens_mol_liq_comp_coeff": {
"eqn_type": 1,
"1": 0.8488, # [2] pg. 2-98
"2": 0.26655,
"3": 591.8,
"4": 0.2878,
},
"cp_mol_ig_comp_coeff": {
"A": -2.435e1,
"B": 5.125e-1,
"C": -2.765e-4,
"D": 4.911e-8,
},
"cp_mol_liq_comp_coeff": {
"1": 1.40e2, # [2]
"2": -1.52e-1,
"3": 6.95e-4,
"4": 0,
"5": 0,
},
"enth_mol_form_liq_comp_ref": 12.0e3, # [3]
"enth_mol_form_vap_comp_ref": 50.1e3, # [3]
"pressure_sat_comp_coeff": {
"A": 4.07827, # [NIST]
"B": 1343.943,
"C": -53.773,
},
},
},
},
"phases": {
"Liq": {"type": LiquidPhase, "equation_of_state": Ideal},
"Vap": {"type": VaporPhase, "equation_of_state": Ideal},
},
"base_units": {
"time": pyunits.s,
"length": pyunits.m,
"mass": pyunits.kg,
"amount": pyunits.mol,
"temperature": pyunits.K,
},
"state_definition": FcTP,
"state_bounds": {
"flow_mol_comp": (0, 100, 1000, pyunits.mol / pyunits.s),
"temperature": (273.15, 300, 450, pyunits.K),
"pressure": (5e4, 1e5, 1e6, pyunits.Pa),
},
"pressure_ref": 1e5,
"temperature_ref": 300,
"phases_in_equilibrium": [("Vap", "Liq")],
"phase_equilibrium_state": {("Vap", "Liq"): SmoothVLE},
"bubble_dew_method": IdealBubbleDew,
}
In the following cell, we will be creating the translator unit model, assigning the appropriate property packages to it, and determining the initial degrees of freedom associated with the translator unit model.
m.fs.properties_FTPx = GenericParameterBlock(**configuration_FTPx) # Inlet property block
m.fs.properties_FcTP = GenericParameterBlock(**configuration_FcTP) # Outlet property block
m.fs.translator = Translator(
inlet_property_package=m.fs.properties_FTPx,
outlet_property_package=m.fs.properties_FcTP,
)
DOF_initial = degrees_of_freedom(m)
print('The initial degrees of freedom are: {0}'.format(DOF_initial))
The initial degrees of freedom are: 9
Fixing input specifications¶
In the following cell, we will be specifying the inlet conditions for the translator block.
# Fix the inlet conditions
m.fs.translator.inlet.flow_mol.fix(100) # converting to mol/s as unit basis is mol/s
m.fs.translator.inlet.mole_frac_comp[0, "benzene"].fix(0.6)
m.fs.translator.inlet.mole_frac_comp[0, "toluene"].fix(0.4)
m.fs.translator.inlet.pressure.fix(101325) # Pa
m.fs.translator.inlet.temperature.fix(298) # K
In the following cell, we will be adding the translator block constraints to define the relationship between the inlet and outlet property packages and re-evaluating the degrees of freedom to ensure the problem is square (i.e. DOF=0). Constraints should never be written to equate enthalpy and should equate temperature instead since enthalpy is a relative quantity that depends on the reference state, which may vary between property packages.
# Define a translator block to make the constraints more readable
blk = m.fs.translator
blk.eq_benzene_balance = Constraint(
expr=blk.properties_in[0].flow_mol * blk.properties_in[0].mole_frac_comp["benzene"]
== blk.properties_out[0].flow_mol_comp["benzene"]
)
blk.eq_toluene_balance = Constraint(
expr=blk.properties_in[0].flow_mol * blk.properties_in[0].mole_frac_comp["toluene"]
== blk.properties_out[0].flow_mol_comp["toluene"]
)
blk.eq_equal_temperature = Constraint(
expr=blk.properties_in[0].temperature == blk.properties_out[0].temperature
)
blk.eq_equal_pressure = Constraint(
expr=blk.properties_in[0].pressure == blk.properties_out[0].pressure
)
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¶
IDAES includes pre-written initialization routines for all unit models. Failing to initialize or having a poor intialization of a flowsheet may result in the problem being unsolvable. The output from initialization can be set to 7 different levels depending on the details required by the user. In general, when a particular output level is set, any information at that level and above gets picked up by logger. The default level taken by the logger is INFO.
More information on these levels can be found in the IDAES documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/logging.html
m.fs.translator.initialize(outlvl=idaeslog.WARNING)
Obtaining Simulation Results¶
In the following cell, the flowsheet will be solved using the IDAES get_solver
tool. Setting tee=True
will display the solver output.
solver = get_solver()
result = solver.solve(m, tee=True)
Ipopt 3.13.2: nlp_scaling_method=gradient-based tol=1e-06 max_iter=200 ****************************************************************************** This program contains Ipopt, a library for large-scale nonlinear optimization. Ipopt is released as open source code under the Eclipse Public License (EPL). For more information visit http://projects.coin-or.org/Ipopt 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...: 113 Number of nonzeros in inequality constraint Jacobian.: 0 Number of nonzeros in Lagrangian Hessian.............: 47 Total number of variables............................: 38 variables with only lower bounds: 12 variables with lower and upper bounds: 22 variables with only upper bounds: 0 Total number of equality constraints.................: 38 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 9.90e-01 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0 1 0.0000000e+00 9.89e-03 3.42e-01 -1.0 1.00e-02 - 9.90e-01 9.90e-01h 1 2 0.0000000e+00 9.07e-05 8.22e-01 -1.0 9.99e-05 - 9.90e-01 9.91e-01h 1 3 0.0000000e+00 2.44e-07 8.89e+02 -1.0 9.16e-07 - 9.91e-01 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....: 1.8280126324388070e-10 2.4409382604062557e-07 Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00 Overall NLP error.......: 1.8280126324388070e-10 2.4409382604062557e-07 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¶
As the following report will show, the inlet stream is represented with its five state variables (FTPx) while the outlet stream is represented with its four state variables (FcTP)
m.fs.translator.report()
==================================================================================== Unit : fs.translator Time: 0.0 ------------------------------------------------------------------------------------ Stream Table Units Inlet Outlet Total Molar Flowrate mole / second 100 - Total Mole Fraction benzene dimensionless 0.60000 - Total Mole Fraction toluene dimensionless 0.40000 - Temperature kelvin 298 298.00 Pressure pascal 1.0132e+05 1.0132e+05 Molar Flowrate benzene mole / second - 60.000 Molar Flowrate toluene mole / second - 40.000 ====================================================================================