ahuora-builder 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ahuora_builder/__init__.py +0 -0
- ahuora_builder/arc_manager.py +33 -0
- ahuora_builder/build_state.py +57 -0
- ahuora_builder/custom/PIDController.py +494 -0
- ahuora_builder/custom/PySMOModel.py +178 -0
- ahuora_builder/custom/SimpleEffectivenessHX_DH.py +727 -0
- ahuora_builder/custom/__init__.py +0 -0
- ahuora_builder/custom/add_initial_dynamics.py +35 -0
- ahuora_builder/custom/custom_compressor.py +107 -0
- ahuora_builder/custom/custom_cooler.py +33 -0
- ahuora_builder/custom/custom_heat_exchanger.py +183 -0
- ahuora_builder/custom/custom_heat_exchanger_1d.py +258 -0
- ahuora_builder/custom/custom_heater.py +41 -0
- ahuora_builder/custom/custom_pressure_changer.py +34 -0
- ahuora_builder/custom/custom_pump.py +107 -0
- ahuora_builder/custom/custom_separator.py +371 -0
- ahuora_builder/custom/custom_tank.py +133 -0
- ahuora_builder/custom/custom_turbine.py +132 -0
- ahuora_builder/custom/custom_valve.py +300 -0
- ahuora_builder/custom/custom_variable.py +29 -0
- ahuora_builder/custom/direct_steam_injection.py +371 -0
- ahuora_builder/custom/energy/__init__.py +0 -0
- ahuora_builder/custom/energy/acBus.py +280 -0
- ahuora_builder/custom/energy/ac_property_package.py +279 -0
- ahuora_builder/custom/energy/battery.py +170 -0
- ahuora_builder/custom/energy/bus.py +182 -0
- ahuora_builder/custom/energy/energy_mixer.py +195 -0
- ahuora_builder/custom/energy/energy_splitter.py +228 -0
- ahuora_builder/custom/energy/grid.py +173 -0
- ahuora_builder/custom/energy/hydro.py +169 -0
- ahuora_builder/custom/energy/link.py +137 -0
- ahuora_builder/custom/energy/load.py +155 -0
- ahuora_builder/custom/energy/mainDistributionBoard.py +257 -0
- ahuora_builder/custom/energy/power_property_package.py +253 -0
- ahuora_builder/custom/energy/solar.py +176 -0
- ahuora_builder/custom/energy/storage.py +230 -0
- ahuora_builder/custom/energy/storage_wrapper +0 -0
- ahuora_builder/custom/energy/tests/__init__.py +0 -0
- ahuora_builder/custom/energy/tests/test_bus.py +44 -0
- ahuora_builder/custom/energy/tests/test_energy_mixer.py +46 -0
- ahuora_builder/custom/energy/tests/test_mdb.py +49 -0
- ahuora_builder/custom/energy/transformer.py +187 -0
- ahuora_builder/custom/energy/transformer_property_package.py +267 -0
- ahuora_builder/custom/energy/transmissionLine.py +228 -0
- ahuora_builder/custom/energy/wind.py +206 -0
- ahuora_builder/custom/hda_ideal_VLE.py +1341 -0
- ahuora_builder/custom/hda_reaction.py +182 -0
- ahuora_builder/custom/heat_exchanger_1d_wrapper.py +31 -0
- ahuora_builder/custom/integration_block.py +106 -0
- ahuora_builder/custom/inverted.py +81 -0
- ahuora_builder/custom/performance_curves.py +1 -0
- ahuora_builder/custom/reactions/__init__.py +0 -0
- ahuora_builder/custom/reactions/hda_stoich.py +10 -0
- ahuora_builder/custom/simple_separator.py +680 -0
- ahuora_builder/custom/tests/__init__.py +0 -0
- ahuora_builder/custom/tests/test_SimpleEffectivenessHX_DH.py +91 -0
- ahuora_builder/custom/tests/test_custom_tank.py +70 -0
- ahuora_builder/custom/tests/test_direct_steam_injection.py +41 -0
- ahuora_builder/custom/tests/test_simple_separator.py +46 -0
- ahuora_builder/custom/tests/test_waterpipe.py +46 -0
- ahuora_builder/custom/thermal_utility_systems/desuperheater.py +624 -0
- ahuora_builder/custom/thermal_utility_systems/header.py +889 -0
- ahuora_builder/custom/thermal_utility_systems/simple_heat_pump.py +567 -0
- ahuora_builder/custom/thermal_utility_systems/steam_header.py +353 -0
- ahuora_builder/custom/thermal_utility_systems/steam_user.py +944 -0
- ahuora_builder/custom/thermal_utility_systems/temp.py +349 -0
- ahuora_builder/custom/thermal_utility_systems/tests/test_desuperheater.py +142 -0
- ahuora_builder/custom/thermal_utility_systems/tests/test_header.py +998 -0
- ahuora_builder/custom/thermal_utility_systems/tests/test_ntu_hx.py +129 -0
- ahuora_builder/custom/thermal_utility_systems/tests/test_simple_heat_pump.py +120 -0
- ahuora_builder/custom/thermal_utility_systems/tests/test_steam_header.py +703 -0
- ahuora_builder/custom/thermal_utility_systems/tests/test_steam_user.py +277 -0
- ahuora_builder/custom/thermal_utility_systems/tests/test_waterpipe.py +36 -0
- ahuora_builder/custom/thermal_utility_systems/tests/test_willans_turbine.py +253 -0
- ahuora_builder/custom/thermal_utility_systems/willans_turbine.py +804 -0
- ahuora_builder/custom/translator.py +129 -0
- ahuora_builder/custom/updated_pressure_changer.py +1404 -0
- ahuora_builder/custom/valve_wrapper.py +38 -0
- ahuora_builder/custom/water_tank_with_units.py +456 -0
- ahuora_builder/diagnostics/__init__.py +0 -0
- ahuora_builder/diagnostics/infeasibilities.py +40 -0
- ahuora_builder/diagnostics/tests/__init__.py +0 -0
- ahuora_builder/diagnostics/tests/test_infeasibilities.py +28 -0
- ahuora_builder/flowsheet_manager.py +542 -0
- ahuora_builder/flowsheet_manager_type.py +20 -0
- ahuora_builder/generate_python_file.py +440 -0
- ahuora_builder/methods/BlockContext.py +84 -0
- ahuora_builder/methods/__init__.py +0 -0
- ahuora_builder/methods/adapter.py +355 -0
- ahuora_builder/methods/adapter_library.py +549 -0
- ahuora_builder/methods/adapter_methods.py +80 -0
- ahuora_builder/methods/expression_parsing.py +105 -0
- ahuora_builder/methods/load_unit_model.py +147 -0
- ahuora_builder/methods/slice_manipulation.py +7 -0
- ahuora_builder/methods/tests/__init__.py +0 -0
- ahuora_builder/methods/tests/test_expression_parsing.py +15 -0
- ahuora_builder/methods/units_handler.py +129 -0
- ahuora_builder/ml_wizard.py +101 -0
- ahuora_builder/port_manager.py +20 -0
- ahuora_builder/properties_manager.py +44 -0
- ahuora_builder/property_package_manager.py +78 -0
- ahuora_builder/solver.py +38 -0
- ahuora_builder/tear_manager.py +98 -0
- ahuora_builder/tests/__init__.py +0 -0
- ahuora_builder/tests/test_generate_python_file/__init__.py +0 -0
- ahuora_builder/tests/test_generate_python_file/configurations/compressor_generated.py +63 -0
- ahuora_builder/tests/test_generate_python_file/configurations/heat_exchanger_generated.py +70 -0
- ahuora_builder/tests/test_generate_python_file/configurations/pump_generated.py +84 -0
- ahuora_builder/tests/test_generate_python_file/configurations/recycle_generated.py +73 -0
- ahuora_builder/tests/test_generate_python_file/test_generate_python_file.py +108 -0
- ahuora_builder/tests/test_solver/__init__.py +0 -0
- ahuora_builder/tests/test_solver/configurations/BT_PR.json +59 -0
- ahuora_builder/tests/test_solver/configurations/BT_PR_solved.json +59 -0
- ahuora_builder/tests/test_solver/configurations/bus.json +99 -0
- ahuora_builder/tests/test_solver/configurations/bus_solved.json +50 -0
- ahuora_builder/tests/test_solver/configurations/compound_separator.json +377 -0
- ahuora_builder/tests/test_solver/configurations/compound_separator_solved.json +374 -0
- ahuora_builder/tests/test_solver/configurations/compressor.json +38 -0
- ahuora_builder/tests/test_solver/configurations/compressor_solved.json +68 -0
- ahuora_builder/tests/test_solver/configurations/constraints.json +44 -0
- ahuora_builder/tests/test_solver/configurations/constraints_solved.json +59 -0
- ahuora_builder/tests/test_solver/configurations/control.json +39 -0
- ahuora_builder/tests/test_solver/configurations/control_solved.json +68 -0
- ahuora_builder/tests/test_solver/configurations/dynamic_tank.json +733 -0
- ahuora_builder/tests/test_solver/configurations/dynamic_tank_solved.json +846 -0
- ahuora_builder/tests/test_solver/configurations/elimination.json +39 -0
- ahuora_builder/tests/test_solver/configurations/elimination_solved.json +68 -0
- ahuora_builder/tests/test_solver/configurations/expressions.json +68 -0
- ahuora_builder/tests/test_solver/configurations/expressions_solved.json +104 -0
- ahuora_builder/tests/test_solver/configurations/header.json +1192 -0
- ahuora_builder/tests/test_solver/configurations/header_solved.json +761 -0
- ahuora_builder/tests/test_solver/configurations/heat_exchanger.json +63 -0
- ahuora_builder/tests/test_solver/configurations/heat_exchanger_solved.json +104 -0
- ahuora_builder/tests/test_solver/configurations/heat_pump.json +137 -0
- ahuora_builder/tests/test_solver/configurations/heat_pump_solved.json +104 -0
- ahuora_builder/tests/test_solver/configurations/machine_learning.json +2156 -0
- ahuora_builder/tests/test_solver/configurations/machine_learning_solved.json +266 -0
- ahuora_builder/tests/test_solver/configurations/mass_flow_tear.json +77 -0
- ahuora_builder/tests/test_solver/configurations/mass_flow_tear_solved.json +68 -0
- ahuora_builder/tests/test_solver/configurations/milk_heater.json +521 -0
- ahuora_builder/tests/test_solver/configurations/milk_heater_solved.json +311 -0
- ahuora_builder/tests/test_solver/configurations/mixer.json +44 -0
- ahuora_builder/tests/test_solver/configurations/mixer_solved.json +86 -0
- ahuora_builder/tests/test_solver/configurations/optimization.json +62 -0
- ahuora_builder/tests/test_solver/configurations/optimization_solved.json +59 -0
- ahuora_builder/tests/test_solver/configurations/propane_heat_pump.json +167 -0
- ahuora_builder/tests/test_solver/configurations/propane_heat_pump_solved.json +158 -0
- ahuora_builder/tests/test_solver/configurations/propane_recycle.json +141 -0
- ahuora_builder/tests/test_solver/configurations/propane_recycle_solved.json +104 -0
- ahuora_builder/tests/test_solver/configurations/pump.json +64 -0
- ahuora_builder/tests/test_solver/configurations/pump_solved.json +59 -0
- ahuora_builder/tests/test_solver/configurations/pump_unit_conversions.json +63 -0
- ahuora_builder/tests/test_solver/configurations/recycle.json +49 -0
- ahuora_builder/tests/test_solver/configurations/recycle_solved.json +50 -0
- ahuora_builder/tests/test_solver/configurations/sb_vapor_frac.json +29 -0
- ahuora_builder/tests/test_solver/configurations/sb_vapor_frac_solved.json +29 -0
- ahuora_builder/tests/test_solver/configurations/solar.json +67 -0
- ahuora_builder/tests/test_solver/configurations/solar_solved.json +50 -0
- ahuora_builder/tests/test_solver/configurations/vapor_frac_target.json +67 -0
- ahuora_builder/tests/test_solver/configurations/vapor_frac_target_solved.json +68 -0
- ahuora_builder/tests/test_solver/test_solve_models.py +250 -0
- ahuora_builder/timing.py +65 -0
- ahuora_builder/types/__init__.py +1 -0
- ahuora_builder/unit_model_manager.py +48 -0
- ahuora_builder-0.1.0.dist-info/METADATA +14 -0
- ahuora_builder-0.1.0.dist-info/RECORD +167 -0
- ahuora_builder-0.1.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,182 @@
|
|
|
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
|
+
"""
|
|
14
|
+
Property package for the hydrodealkylation of toluene to form benzene
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
# Import Python libraries
|
|
18
|
+
import logging
|
|
19
|
+
|
|
20
|
+
# Import Pyomo libraries
|
|
21
|
+
from pyomo.environ import Constraint, exp, Set, Var, Param, units as pyunits
|
|
22
|
+
|
|
23
|
+
# Import IDAES cores
|
|
24
|
+
from idaes.core import (
|
|
25
|
+
declare_process_block_class,
|
|
26
|
+
MaterialFlowBasis,
|
|
27
|
+
ReactionParameterBlock,
|
|
28
|
+
ReactionBlockDataBase,
|
|
29
|
+
ReactionBlockBase,
|
|
30
|
+
)
|
|
31
|
+
from idaes.core.util.constants import Constants as const
|
|
32
|
+
from idaes.core.util.misc import add_object_reference
|
|
33
|
+
|
|
34
|
+
# Set up logger
|
|
35
|
+
_log = logging.getLogger(__name__)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@declare_process_block_class("HDAReactionParameterBlock")
|
|
39
|
+
class HDAReactionParameterData(ReactionParameterBlock):
|
|
40
|
+
"""
|
|
41
|
+
Property Parameter Block Class
|
|
42
|
+
Contains parameters and indexing sets associated with properties for
|
|
43
|
+
superheated steam.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
def build(self):
|
|
47
|
+
"""
|
|
48
|
+
Callable method for Block construction.
|
|
49
|
+
"""
|
|
50
|
+
super(HDAReactionParameterData, self).build()
|
|
51
|
+
|
|
52
|
+
self._reaction_block_class = HDAReactionBlock
|
|
53
|
+
|
|
54
|
+
# List of valid phases in property package
|
|
55
|
+
self.phase_list = Set(initialize=["Vap"])
|
|
56
|
+
|
|
57
|
+
# Component list - a list of component identifiers
|
|
58
|
+
self.component_list = Set(
|
|
59
|
+
initialize=["benzene", "toluene", "hydrogen", "methane"]
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# Reaction Index
|
|
63
|
+
self.rate_reaction_idx = Set(initialize=["R1"])
|
|
64
|
+
|
|
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
|
+
}
|
|
76
|
+
|
|
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()
|
|
84
|
+
|
|
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()
|
|
90
|
+
|
|
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
|
+
)
|
|
99
|
+
|
|
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
|
+
)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class 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
|
+
"""
|
|
124
|
+
|
|
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))
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@declare_process_block_class("HDAReactionBlock", block_class=ReactionBlock)
|
|
140
|
+
class HDAReactionBlockData(ReactionBlockDataBase):
|
|
141
|
+
"""
|
|
142
|
+
An example reaction package for saponification of ethyl acetate
|
|
143
|
+
"""
|
|
144
|
+
|
|
145
|
+
def build(self):
|
|
146
|
+
"""
|
|
147
|
+
Callable method for Block construction
|
|
148
|
+
"""
|
|
149
|
+
super(HDAReactionBlockData, self).build()
|
|
150
|
+
|
|
151
|
+
# Heat of reaction - no _ref as this is the actual property
|
|
152
|
+
add_object_reference(self, "dh_rxn", self.config.parameters.dh_rxn)
|
|
153
|
+
|
|
154
|
+
self.k_rxn = Var(
|
|
155
|
+
initialize=0.2,
|
|
156
|
+
units=pyunits.mol * pyunits.m**-3 * pyunits.s**-1 * pyunits.Pa**-1,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
self.reaction_rate = Var(
|
|
160
|
+
self.params.rate_reaction_idx,
|
|
161
|
+
initialize=1,
|
|
162
|
+
units=pyunits.mol / pyunits.m**3 / pyunits.s,
|
|
163
|
+
)
|
|
164
|
+
|
|
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
|
+
)
|
|
173
|
+
|
|
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
|
+
)
|
|
180
|
+
|
|
181
|
+
def get_reaction_rate_basis(b):
|
|
182
|
+
return MaterialFlowBasis.molar
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from .custom_heat_exchanger_1d import CustomHeatExchanger1D
|
|
2
|
+
from idaes.models.unit_models.heat_exchanger import HeatExchangerFlowPattern
|
|
3
|
+
|
|
4
|
+
# Map frontend string values to IDAES enums
|
|
5
|
+
FLOW_TYPE_MAP = {
|
|
6
|
+
"countercurrent": HeatExchangerFlowPattern.countercurrent,
|
|
7
|
+
"cocurrent": HeatExchangerFlowPattern.cocurrent,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
def HeatExchanger1DWrapper(**kwargs):
|
|
11
|
+
"""
|
|
12
|
+
Wrapper for CustomHeatExchanger1D that handles string-to-enum conversion
|
|
13
|
+
and provides default values for required parameters, defaulting to collocation.
|
|
14
|
+
"""
|
|
15
|
+
# Convert flow_type string to enum
|
|
16
|
+
flow_type = kwargs.pop('flow_type', None)
|
|
17
|
+
if flow_type is None:
|
|
18
|
+
flow_type = "countercurrent"
|
|
19
|
+
|
|
20
|
+
if isinstance(flow_type, str):
|
|
21
|
+
if flow_type.lower() in FLOW_TYPE_MAP:
|
|
22
|
+
flow_type_enum = FLOW_TYPE_MAP[flow_type.lower()]
|
|
23
|
+
else:
|
|
24
|
+
raise ValueError(f"Unknown flow_type: {flow_type}. Must be one of: {list(FLOW_TYPE_MAP.keys())}")
|
|
25
|
+
else:
|
|
26
|
+
flow_type_enum = flow_type
|
|
27
|
+
|
|
28
|
+
kwargs['flow_type'] = flow_type_enum
|
|
29
|
+
|
|
30
|
+
# Return the heat exchanger with fixed parameters
|
|
31
|
+
return CustomHeatExchanger1D(**kwargs)
|
|
@@ -0,0 +1,106 @@
|
|
|
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).
|
|
5
|
+
#
|
|
6
|
+
# Copyright (c) 2018-2024 by the software owners: The Regents of the
|
|
7
|
+
# University of California, through Lawrence Berkeley National Laboratory,
|
|
8
|
+
# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon
|
|
9
|
+
# University, West Virginia University Research Corporation, et al.
|
|
10
|
+
# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md
|
|
11
|
+
# for full copyright and license information.
|
|
12
|
+
#################################################################################
|
|
13
|
+
"""
|
|
14
|
+
Base class for unit models
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from pyomo.environ import check_optimal_termination
|
|
18
|
+
from pyomo.common.config import ConfigValue
|
|
19
|
+
from pyomo.network import Port
|
|
20
|
+
|
|
21
|
+
from idaes.core.base.process_base import (
|
|
22
|
+
declare_process_block_class,
|
|
23
|
+
ProcessBlockData,
|
|
24
|
+
useDefault,
|
|
25
|
+
)
|
|
26
|
+
from idaes.core.base.property_base import StateBlock
|
|
27
|
+
from idaes.core.base.control_volume_base import (
|
|
28
|
+
ControlVolumeBlockData,
|
|
29
|
+
FlowDirection,
|
|
30
|
+
MaterialBalanceType,
|
|
31
|
+
)
|
|
32
|
+
from idaes.core.util.exceptions import (
|
|
33
|
+
BurntToast,
|
|
34
|
+
ConfigurationError,
|
|
35
|
+
BalanceTypeNotSupportedError,
|
|
36
|
+
InitializationError,
|
|
37
|
+
)
|
|
38
|
+
from idaes.core.util.tables import create_stream_table_dataframe
|
|
39
|
+
import idaes.logger as idaeslog
|
|
40
|
+
from idaes.core.solvers import get_solver
|
|
41
|
+
from idaes.core.util.config import DefaultBool
|
|
42
|
+
from idaes.core.initialization import SingleControlVolumeUnitInitializer
|
|
43
|
+
from pyomo.environ import Var, units, Expression
|
|
44
|
+
from pyomo.dae import Integral
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# Set up logger
|
|
48
|
+
_log = idaeslog.getLogger(__name__)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@declare_process_block_class("IntegrationBlock")
|
|
52
|
+
class IntegrationBlockData(ProcessBlockData):
|
|
53
|
+
"""
|
|
54
|
+
This block has no inlets or outlets, but one value that you can get the integral for.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
# Create Class ConfigBlock
|
|
58
|
+
CONFIG = ProcessBlockData.CONFIG()
|
|
59
|
+
CONFIG.declare(
|
|
60
|
+
"dynamic",
|
|
61
|
+
ConfigValue(
|
|
62
|
+
default=useDefault,
|
|
63
|
+
domain=DefaultBool,
|
|
64
|
+
description="Dynamic model flag",
|
|
65
|
+
doc="""Indicates whether this model will be dynamic or not,
|
|
66
|
+
**default** = useDefault.
|
|
67
|
+
**Valid values:** {
|
|
68
|
+
**useDefault** - get flag from parent (default = False),
|
|
69
|
+
**True** - set as a dynamic model,
|
|
70
|
+
**False** - set as a steady-state model.}""",
|
|
71
|
+
),
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
def build(self):
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
"""
|
|
78
|
+
super(IntegrationBlockData, self).build()
|
|
79
|
+
|
|
80
|
+
self.variable = Var(
|
|
81
|
+
self.flowsheet().time
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
#self.time = self.flowsheet().time
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _integral(m):
|
|
89
|
+
time_steps = sorted(self.flowsheet().time)
|
|
90
|
+
value = m.variable
|
|
91
|
+
return sum([
|
|
92
|
+
# Trapezium rule
|
|
93
|
+
# average the value at the current and next time step, then multiply by the time difference
|
|
94
|
+
0.5 * (value[time_steps[i]] + value[time_steps[i+1]]) * (time_steps[i+1] - time_steps[i])
|
|
95
|
+
for i in range(len(time_steps)-1)
|
|
96
|
+
])
|
|
97
|
+
|
|
98
|
+
self.integral = Expression(
|
|
99
|
+
rule=_integral
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
# if self.config.dynamic:
|
|
104
|
+
# # create a variable to hold the normal value, and one to hold the integral value
|
|
105
|
+
# else:
|
|
106
|
+
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
from pyomo.environ import Var, Constraint, units as pyunits, Block, Reference
|
|
2
|
+
|
|
3
|
+
def add_inverted(block: Block,component_name: str):
|
|
4
|
+
"""
|
|
5
|
+
Adds inverted variables and constraints to a block with variable component_name.
|
|
6
|
+
e.g if component_name is 'deltaP', adds deltaP_inverted variable, so we can do
|
|
7
|
+
pressure drop instead of pressure increase.
|
|
8
|
+
"""
|
|
9
|
+
inverted_component_name = f"{component_name}_inverted"
|
|
10
|
+
|
|
11
|
+
component = getattr(block, component_name)
|
|
12
|
+
|
|
13
|
+
inverted_component = Var(
|
|
14
|
+
component.index_set(),
|
|
15
|
+
# Explanation for units:
|
|
16
|
+
# Reference() turns a var/expression into a indexed object, even if it's scalar.
|
|
17
|
+
# next() gets the first item from the indexed object
|
|
18
|
+
# This is a way of getting around the fact that an indexed component
|
|
19
|
+
# will only have its units defined at the individual index level.
|
|
20
|
+
units=next(Reference(component).values()).get_units(),
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
block.add_component(inverted_component_name, inverted_component)
|
|
24
|
+
|
|
25
|
+
def _inverted_rule(b, *indexes):
|
|
26
|
+
return inverted_component[indexes] == -component[indexes]
|
|
27
|
+
|
|
28
|
+
constraint = Constraint(
|
|
29
|
+
component.index_set(),
|
|
30
|
+
rule=_inverted_rule,
|
|
31
|
+
doc=f"Inverted {component_name} Constraint",
|
|
32
|
+
)
|
|
33
|
+
block.add_component(f"{inverted_component_name}_constraint", constraint)
|
|
34
|
+
|
|
35
|
+
def initialise_inverted(block: Block, component_name: str):
|
|
36
|
+
"""
|
|
37
|
+
Initialises the inverted deltaP variables to match the deltaP variable values,
|
|
38
|
+
or vice versa (depending on which is fixed).
|
|
39
|
+
|
|
40
|
+
This is generalised so you can pass any component name.
|
|
41
|
+
"""
|
|
42
|
+
inverted_component_name = f"{component_name}_inverted"
|
|
43
|
+
component = getattr(block, component_name)
|
|
44
|
+
inverted_component = getattr(block, inverted_component_name)
|
|
45
|
+
|
|
46
|
+
for indexes in component.index_set():
|
|
47
|
+
if component[indexes].fixed:
|
|
48
|
+
# we can savely assume that the inverted variable is not
|
|
49
|
+
# fixed, otherwise this would be an overconstrained model.
|
|
50
|
+
inverted_component[indexes].value = -component[indexes].value
|
|
51
|
+
elif inverted_component[indexes].fixed:
|
|
52
|
+
component[indexes].value = -inverted_component[indexes].value
|
|
53
|
+
else:
|
|
54
|
+
# neither variable is fixed,
|
|
55
|
+
# so let's just leave them as is.
|
|
56
|
+
# Hopefully the solver can figure it out.
|
|
57
|
+
pass
|
|
58
|
+
|
|
59
|
+
def disable_inverted(block: Block, component_name: str) -> bool:
|
|
60
|
+
"""
|
|
61
|
+
Disables the inverted variables and constraints for a given component.
|
|
62
|
+
Returns True if the inverted variable was fixed, false otherwise.
|
|
63
|
+
"""
|
|
64
|
+
inverted_component_name = f"{component_name}_inverted"
|
|
65
|
+
constraint_name = f"{inverted_component_name}_constraint"
|
|
66
|
+
|
|
67
|
+
inverted_constraint = getattr(block, constraint_name)
|
|
68
|
+
|
|
69
|
+
inverted_constraint.deactivate()
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def enable_inverted(block: Block, component_name: str):
|
|
73
|
+
"""
|
|
74
|
+
Enables the inverted variables and constraints for a given component.
|
|
75
|
+
"""
|
|
76
|
+
inverted_component_name = f"{component_name}_inverted"
|
|
77
|
+
constraint_name = f"{inverted_component_name}_constraint"
|
|
78
|
+
|
|
79
|
+
inverted_constraint = getattr(block, constraint_name)
|
|
80
|
+
|
|
81
|
+
inverted_constraint.activate()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
File without changes
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from idaes.core import declare_process_block_class
|
|
2
|
+
from idaes.models.unit_models.stoichiometric_reactor import StoichiometricReactorData
|
|
3
|
+
from pyomo.environ import Var, Reference
|
|
4
|
+
|
|
5
|
+
@declare_process_block_class("HDAStoichiometricReactor")
|
|
6
|
+
class HDAStoichiometricReactorData(StoichiometricReactorData):
|
|
7
|
+
def build(self,*args, **kwargs):
|
|
8
|
+
super().build(*args, **kwargs)
|
|
9
|
+
# reaction id in https://github.com/IDAES/examples/blob/50065c4cc4de96a8dc1cad833101df2d96574ac4/idaes_examples/mod/hda/hda_reaction.py#L4
|
|
10
|
+
self.hda_extent = Reference(self.rate_reaction_extent[:,"R1"])
|