Coverage for backend/idaes_service/solver/custom/hda_reaction.py: 74%
40 statements
« prev ^ index » next coverage.py v7.10.7, created at 2025-11-06 23:27 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2025-11-06 23:27 +0000
1#################################################################################
2# The Institute for the Design of Advanced Energy Systems Integrated Platform
3# Framework (IDAES IP) was produced under the DOE Institute for the
4# Design of Advanced Energy Systems (IDAES), and is copyright (c) 2018-2022
5# by the software owners: The Regents of the University of California, through
6# Lawrence Berkeley National Laboratory, National Technology & Engineering
7# Solutions of Sandia, LLC, Carnegie Mellon University, West Virginia University
8# Research Corporation, et al. All rights reserved.
9#
10# Please see the files COPYRIGHT.md and LICENSE.md for full copyright and
11# license information.
12#################################################################################
13"""
14Property package for the hydrodealkylation of toluene to form benzene
15"""
17# Import Python libraries
18import logging
20# Import Pyomo libraries
21from pyomo.environ import Constraint, exp, Set, Var, Param, units as pyunits
23# Import IDAES cores
24from idaes.core import (
25 declare_process_block_class,
26 MaterialFlowBasis,
27 ReactionParameterBlock,
28 ReactionBlockDataBase,
29 ReactionBlockBase,
30)
31from idaes.core.util.constants import Constants as const
32from idaes.core.util.misc import add_object_reference
34# Set up logger
35_log = logging.getLogger(__name__)
38@declare_process_block_class("HDAReactionParameterBlock")
39class HDAReactionParameterData(ReactionParameterBlock):
40 """
41 Property Parameter Block Class
42 Contains parameters and indexing sets associated with properties for
43 superheated steam.
44 """
46 def build(self):
47 """
48 Callable method for Block construction.
49 """
50 super(HDAReactionParameterData, self).build()
52 self._reaction_block_class = HDAReactionBlock
54 # List of valid phases in property package
55 self.phase_list = Set(initialize=["Vap"])
57 # Component list - a list of component identifiers
58 self.component_list = Set(
59 initialize=["benzene", "toluene", "hydrogen", "methane"]
60 )
62 # Reaction Index
63 self.rate_reaction_idx = Set(initialize=["R1"])
65 # Reaction Stoichiometry
66 self.rate_reaction_stoichiometry = {
67 ("R1", "Vap", "benzene"): 1,
68 ("R1", "Vap", "toluene"): -1,
69 ("R1", "Vap", "hydrogen"): -1,
70 ("R1", "Vap", "methane"): 1,
71 ("R1", "Liq", "benzene"): 0,
72 ("R1", "Liq", "toluene"): 0,
73 ("R1", "Liq", "hydrogen"): 0,
74 ("R1", "Liq", "methane"): 0,
75 }
77 # Arrhenius Constant
78 self.arrhenius = Var(
79 initialize=6.3e10,
80 units=pyunits.mol * pyunits.m**-3 * pyunits.s**-1 * pyunits.Pa**-1,
81 doc="Arrhenius pre-exponential factor",
82 )
83 self.arrhenius.fix()
85 # Activation Energy
86 self.energy_activation = Var(
87 initialize=217.6e3, units=pyunits.J / pyunits.mol, doc="Activation energy"
88 )
89 self.energy_activation.fix()
91 # Heat of Reaction
92 dh_rxn_dict = {"R1": -1.08e5}
93 self.dh_rxn = Param(
94 self.rate_reaction_idx,
95 initialize=dh_rxn_dict,
96 units=pyunits.J / pyunits.mol,
97 doc="Heat of reaction",
98 )
100 @classmethod
101 def define_metadata(cls, obj):
102 obj.add_properties(
103 {
104 "k_rxn": {"method": None, "units": "m^3/mol.s"},
105 "reaction_rate": {"method": None, "units": "mol/m^3.s"},
106 }
107 )
108 obj.add_default_units(
109 {
110 "time": pyunits.s,
111 "length": pyunits.m,
112 "mass": pyunits.kg,
113 "amount": pyunits.mol,
114 "temperature": pyunits.K,
115 }
116 )
119class ReactionBlock(ReactionBlockBase):
120 """
121 This Class contains methods which should be applied to Reaction Blocks as a
122 whole, rather than individual elements of indexed Reaction Blocks.
123 """
125 def initialize(blk, outlvl=0, **kwargs):
126 """
127 Initialization routine for reaction package.
128 Keyword Arguments:
129 outlvl : sets output level of initialization routine
130 * 0 = no output (default)
131 * 1 = report after each step
132 Returns:
133 None
134 """
135 if outlvl > 0:
136 _log.info("{} Initialization Complete.".format(blk.name))
139@declare_process_block_class("HDAReactionBlock", block_class=ReactionBlock)
140class HDAReactionBlockData(ReactionBlockDataBase):
141 """
142 An example reaction package for saponification of ethyl acetate
143 """
145 def build(self):
146 """
147 Callable method for Block construction
148 """
149 super(HDAReactionBlockData, self).build()
151 # Heat of reaction - no _ref as this is the actual property
152 add_object_reference(self, "dh_rxn", self.config.parameters.dh_rxn)
154 self.k_rxn = Var(
155 initialize=0.2,
156 units=pyunits.mol * pyunits.m**-3 * pyunits.s**-1 * pyunits.Pa**-1,
157 )
159 self.reaction_rate = Var(
160 self.params.rate_reaction_idx,
161 initialize=1,
162 units=pyunits.mol / pyunits.m**3 / pyunits.s,
163 )
165 self.arrhenus_equation = Constraint(
166 expr=self.k_rxn
167 == self.params.arrhenius
168 * exp(
169 -self.params.energy_activation
170 / (const.gas_constant * self.state_ref.temperature)
171 )
172 )
174 self.rate_expression = Constraint(
175 expr=self.reaction_rate["R1"]
176 == self.k_rxn
177 * self.state_ref.pressure
178 * self.state_ref.mole_frac_phase_comp["Vap", "toluene"]
179 )
181 def get_reaction_rate_basis(b):
182 return MaterialFlowBasis.molar