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.
Files changed (167) hide show
  1. ahuora_builder/__init__.py +0 -0
  2. ahuora_builder/arc_manager.py +33 -0
  3. ahuora_builder/build_state.py +57 -0
  4. ahuora_builder/custom/PIDController.py +494 -0
  5. ahuora_builder/custom/PySMOModel.py +178 -0
  6. ahuora_builder/custom/SimpleEffectivenessHX_DH.py +727 -0
  7. ahuora_builder/custom/__init__.py +0 -0
  8. ahuora_builder/custom/add_initial_dynamics.py +35 -0
  9. ahuora_builder/custom/custom_compressor.py +107 -0
  10. ahuora_builder/custom/custom_cooler.py +33 -0
  11. ahuora_builder/custom/custom_heat_exchanger.py +183 -0
  12. ahuora_builder/custom/custom_heat_exchanger_1d.py +258 -0
  13. ahuora_builder/custom/custom_heater.py +41 -0
  14. ahuora_builder/custom/custom_pressure_changer.py +34 -0
  15. ahuora_builder/custom/custom_pump.py +107 -0
  16. ahuora_builder/custom/custom_separator.py +371 -0
  17. ahuora_builder/custom/custom_tank.py +133 -0
  18. ahuora_builder/custom/custom_turbine.py +132 -0
  19. ahuora_builder/custom/custom_valve.py +300 -0
  20. ahuora_builder/custom/custom_variable.py +29 -0
  21. ahuora_builder/custom/direct_steam_injection.py +371 -0
  22. ahuora_builder/custom/energy/__init__.py +0 -0
  23. ahuora_builder/custom/energy/acBus.py +280 -0
  24. ahuora_builder/custom/energy/ac_property_package.py +279 -0
  25. ahuora_builder/custom/energy/battery.py +170 -0
  26. ahuora_builder/custom/energy/bus.py +182 -0
  27. ahuora_builder/custom/energy/energy_mixer.py +195 -0
  28. ahuora_builder/custom/energy/energy_splitter.py +228 -0
  29. ahuora_builder/custom/energy/grid.py +173 -0
  30. ahuora_builder/custom/energy/hydro.py +169 -0
  31. ahuora_builder/custom/energy/link.py +137 -0
  32. ahuora_builder/custom/energy/load.py +155 -0
  33. ahuora_builder/custom/energy/mainDistributionBoard.py +257 -0
  34. ahuora_builder/custom/energy/power_property_package.py +253 -0
  35. ahuora_builder/custom/energy/solar.py +176 -0
  36. ahuora_builder/custom/energy/storage.py +230 -0
  37. ahuora_builder/custom/energy/storage_wrapper +0 -0
  38. ahuora_builder/custom/energy/tests/__init__.py +0 -0
  39. ahuora_builder/custom/energy/tests/test_bus.py +44 -0
  40. ahuora_builder/custom/energy/tests/test_energy_mixer.py +46 -0
  41. ahuora_builder/custom/energy/tests/test_mdb.py +49 -0
  42. ahuora_builder/custom/energy/transformer.py +187 -0
  43. ahuora_builder/custom/energy/transformer_property_package.py +267 -0
  44. ahuora_builder/custom/energy/transmissionLine.py +228 -0
  45. ahuora_builder/custom/energy/wind.py +206 -0
  46. ahuora_builder/custom/hda_ideal_VLE.py +1341 -0
  47. ahuora_builder/custom/hda_reaction.py +182 -0
  48. ahuora_builder/custom/heat_exchanger_1d_wrapper.py +31 -0
  49. ahuora_builder/custom/integration_block.py +106 -0
  50. ahuora_builder/custom/inverted.py +81 -0
  51. ahuora_builder/custom/performance_curves.py +1 -0
  52. ahuora_builder/custom/reactions/__init__.py +0 -0
  53. ahuora_builder/custom/reactions/hda_stoich.py +10 -0
  54. ahuora_builder/custom/simple_separator.py +680 -0
  55. ahuora_builder/custom/tests/__init__.py +0 -0
  56. ahuora_builder/custom/tests/test_SimpleEffectivenessHX_DH.py +91 -0
  57. ahuora_builder/custom/tests/test_custom_tank.py +70 -0
  58. ahuora_builder/custom/tests/test_direct_steam_injection.py +41 -0
  59. ahuora_builder/custom/tests/test_simple_separator.py +46 -0
  60. ahuora_builder/custom/tests/test_waterpipe.py +46 -0
  61. ahuora_builder/custom/thermal_utility_systems/desuperheater.py +624 -0
  62. ahuora_builder/custom/thermal_utility_systems/header.py +889 -0
  63. ahuora_builder/custom/thermal_utility_systems/simple_heat_pump.py +567 -0
  64. ahuora_builder/custom/thermal_utility_systems/steam_header.py +353 -0
  65. ahuora_builder/custom/thermal_utility_systems/steam_user.py +944 -0
  66. ahuora_builder/custom/thermal_utility_systems/temp.py +349 -0
  67. ahuora_builder/custom/thermal_utility_systems/tests/test_desuperheater.py +142 -0
  68. ahuora_builder/custom/thermal_utility_systems/tests/test_header.py +998 -0
  69. ahuora_builder/custom/thermal_utility_systems/tests/test_ntu_hx.py +129 -0
  70. ahuora_builder/custom/thermal_utility_systems/tests/test_simple_heat_pump.py +120 -0
  71. ahuora_builder/custom/thermal_utility_systems/tests/test_steam_header.py +703 -0
  72. ahuora_builder/custom/thermal_utility_systems/tests/test_steam_user.py +277 -0
  73. ahuora_builder/custom/thermal_utility_systems/tests/test_waterpipe.py +36 -0
  74. ahuora_builder/custom/thermal_utility_systems/tests/test_willans_turbine.py +253 -0
  75. ahuora_builder/custom/thermal_utility_systems/willans_turbine.py +804 -0
  76. ahuora_builder/custom/translator.py +129 -0
  77. ahuora_builder/custom/updated_pressure_changer.py +1404 -0
  78. ahuora_builder/custom/valve_wrapper.py +38 -0
  79. ahuora_builder/custom/water_tank_with_units.py +456 -0
  80. ahuora_builder/diagnostics/__init__.py +0 -0
  81. ahuora_builder/diagnostics/infeasibilities.py +40 -0
  82. ahuora_builder/diagnostics/tests/__init__.py +0 -0
  83. ahuora_builder/diagnostics/tests/test_infeasibilities.py +28 -0
  84. ahuora_builder/flowsheet_manager.py +542 -0
  85. ahuora_builder/flowsheet_manager_type.py +20 -0
  86. ahuora_builder/generate_python_file.py +440 -0
  87. ahuora_builder/methods/BlockContext.py +84 -0
  88. ahuora_builder/methods/__init__.py +0 -0
  89. ahuora_builder/methods/adapter.py +355 -0
  90. ahuora_builder/methods/adapter_library.py +549 -0
  91. ahuora_builder/methods/adapter_methods.py +80 -0
  92. ahuora_builder/methods/expression_parsing.py +105 -0
  93. ahuora_builder/methods/load_unit_model.py +147 -0
  94. ahuora_builder/methods/slice_manipulation.py +7 -0
  95. ahuora_builder/methods/tests/__init__.py +0 -0
  96. ahuora_builder/methods/tests/test_expression_parsing.py +15 -0
  97. ahuora_builder/methods/units_handler.py +129 -0
  98. ahuora_builder/ml_wizard.py +101 -0
  99. ahuora_builder/port_manager.py +20 -0
  100. ahuora_builder/properties_manager.py +44 -0
  101. ahuora_builder/property_package_manager.py +78 -0
  102. ahuora_builder/solver.py +38 -0
  103. ahuora_builder/tear_manager.py +98 -0
  104. ahuora_builder/tests/__init__.py +0 -0
  105. ahuora_builder/tests/test_generate_python_file/__init__.py +0 -0
  106. ahuora_builder/tests/test_generate_python_file/configurations/compressor_generated.py +63 -0
  107. ahuora_builder/tests/test_generate_python_file/configurations/heat_exchanger_generated.py +70 -0
  108. ahuora_builder/tests/test_generate_python_file/configurations/pump_generated.py +84 -0
  109. ahuora_builder/tests/test_generate_python_file/configurations/recycle_generated.py +73 -0
  110. ahuora_builder/tests/test_generate_python_file/test_generate_python_file.py +108 -0
  111. ahuora_builder/tests/test_solver/__init__.py +0 -0
  112. ahuora_builder/tests/test_solver/configurations/BT_PR.json +59 -0
  113. ahuora_builder/tests/test_solver/configurations/BT_PR_solved.json +59 -0
  114. ahuora_builder/tests/test_solver/configurations/bus.json +99 -0
  115. ahuora_builder/tests/test_solver/configurations/bus_solved.json +50 -0
  116. ahuora_builder/tests/test_solver/configurations/compound_separator.json +377 -0
  117. ahuora_builder/tests/test_solver/configurations/compound_separator_solved.json +374 -0
  118. ahuora_builder/tests/test_solver/configurations/compressor.json +38 -0
  119. ahuora_builder/tests/test_solver/configurations/compressor_solved.json +68 -0
  120. ahuora_builder/tests/test_solver/configurations/constraints.json +44 -0
  121. ahuora_builder/tests/test_solver/configurations/constraints_solved.json +59 -0
  122. ahuora_builder/tests/test_solver/configurations/control.json +39 -0
  123. ahuora_builder/tests/test_solver/configurations/control_solved.json +68 -0
  124. ahuora_builder/tests/test_solver/configurations/dynamic_tank.json +733 -0
  125. ahuora_builder/tests/test_solver/configurations/dynamic_tank_solved.json +846 -0
  126. ahuora_builder/tests/test_solver/configurations/elimination.json +39 -0
  127. ahuora_builder/tests/test_solver/configurations/elimination_solved.json +68 -0
  128. ahuora_builder/tests/test_solver/configurations/expressions.json +68 -0
  129. ahuora_builder/tests/test_solver/configurations/expressions_solved.json +104 -0
  130. ahuora_builder/tests/test_solver/configurations/header.json +1192 -0
  131. ahuora_builder/tests/test_solver/configurations/header_solved.json +761 -0
  132. ahuora_builder/tests/test_solver/configurations/heat_exchanger.json +63 -0
  133. ahuora_builder/tests/test_solver/configurations/heat_exchanger_solved.json +104 -0
  134. ahuora_builder/tests/test_solver/configurations/heat_pump.json +137 -0
  135. ahuora_builder/tests/test_solver/configurations/heat_pump_solved.json +104 -0
  136. ahuora_builder/tests/test_solver/configurations/machine_learning.json +2156 -0
  137. ahuora_builder/tests/test_solver/configurations/machine_learning_solved.json +266 -0
  138. ahuora_builder/tests/test_solver/configurations/mass_flow_tear.json +77 -0
  139. ahuora_builder/tests/test_solver/configurations/mass_flow_tear_solved.json +68 -0
  140. ahuora_builder/tests/test_solver/configurations/milk_heater.json +521 -0
  141. ahuora_builder/tests/test_solver/configurations/milk_heater_solved.json +311 -0
  142. ahuora_builder/tests/test_solver/configurations/mixer.json +44 -0
  143. ahuora_builder/tests/test_solver/configurations/mixer_solved.json +86 -0
  144. ahuora_builder/tests/test_solver/configurations/optimization.json +62 -0
  145. ahuora_builder/tests/test_solver/configurations/optimization_solved.json +59 -0
  146. ahuora_builder/tests/test_solver/configurations/propane_heat_pump.json +167 -0
  147. ahuora_builder/tests/test_solver/configurations/propane_heat_pump_solved.json +158 -0
  148. ahuora_builder/tests/test_solver/configurations/propane_recycle.json +141 -0
  149. ahuora_builder/tests/test_solver/configurations/propane_recycle_solved.json +104 -0
  150. ahuora_builder/tests/test_solver/configurations/pump.json +64 -0
  151. ahuora_builder/tests/test_solver/configurations/pump_solved.json +59 -0
  152. ahuora_builder/tests/test_solver/configurations/pump_unit_conversions.json +63 -0
  153. ahuora_builder/tests/test_solver/configurations/recycle.json +49 -0
  154. ahuora_builder/tests/test_solver/configurations/recycle_solved.json +50 -0
  155. ahuora_builder/tests/test_solver/configurations/sb_vapor_frac.json +29 -0
  156. ahuora_builder/tests/test_solver/configurations/sb_vapor_frac_solved.json +29 -0
  157. ahuora_builder/tests/test_solver/configurations/solar.json +67 -0
  158. ahuora_builder/tests/test_solver/configurations/solar_solved.json +50 -0
  159. ahuora_builder/tests/test_solver/configurations/vapor_frac_target.json +67 -0
  160. ahuora_builder/tests/test_solver/configurations/vapor_frac_target_solved.json +68 -0
  161. ahuora_builder/tests/test_solver/test_solve_models.py +250 -0
  162. ahuora_builder/timing.py +65 -0
  163. ahuora_builder/types/__init__.py +1 -0
  164. ahuora_builder/unit_model_manager.py +48 -0
  165. ahuora_builder-0.1.0.dist-info/METADATA +14 -0
  166. ahuora_builder-0.1.0.dist-info/RECORD +167 -0
  167. 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()
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"])