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,353 @@
1
+ from pyomo.environ import Suffix, Var, Expression, Constraint
2
+ from pyomo.common.config import ConfigBlock, ConfigValue, In
3
+ from pyomo.network import Arc, SequentialDecomposition
4
+ from pyomo.core.base.reference import Reference
5
+ import pyomo.environ as pyo
6
+
7
+ # Import IDAES cores
8
+ from idaes.core import (
9
+ declare_process_block_class,
10
+ UnitModelBlockData,
11
+ useDefault,
12
+ )
13
+ from idaes.core.util.config import is_physical_parameter_block
14
+ import idaes.logger as idaeslog
15
+ from idaes.core.util.tables import create_stream_table_dataframe
16
+ from idaes.core.util.math import smooth_max
17
+ from idaes.models.unit_models.separator import SplittingType, EnergySplittingType
18
+ from idaes.models.unit_models.mixer import Mixer
19
+ from idaes.models.unit_models.heater import Heater
20
+ from ahuora_builder.custom.custom_separator import CustomSeparator
21
+ from ahuora_builder.custom.simple_separator import SimpleSeparator
22
+ from ..inverted import add_inverted, initialise_inverted
23
+ __author__ = "Team Ahuora"
24
+
25
+ # Set up logger
26
+ _log = idaeslog.getLogger(__name__)
27
+
28
+
29
+ @declare_process_block_class("SteamHeader")
30
+ class SteamHeaderData(UnitModelBlockData):
31
+ """
32
+ Steam Header unit operation:
33
+ Mixer -> Cooler -> Phase Separator -> Simple Separator
34
+ Separates 100% liquid to condensate_outlet and 100% vapor to splitter outlets.
35
+ Uses Sequential Decomposition for optimal initialization order.
36
+ """
37
+
38
+ CONFIG = UnitModelBlockData.CONFIG()
39
+ CONFIG.declare(
40
+ "property_package",
41
+ ConfigValue(
42
+ default=useDefault,
43
+ domain=is_physical_parameter_block,
44
+ description="Property package to use for control volume",
45
+ ),
46
+ )
47
+ CONFIG.declare(
48
+ "property_package_args",
49
+ ConfigBlock(
50
+ implicit=True,
51
+ description="Arguments to use for constructing property packages",
52
+ ),
53
+ )
54
+ CONFIG.declare(
55
+ "num_inlets",
56
+ ConfigValue(
57
+ default=2,
58
+ domain=int,
59
+ description="Number of inlets to add" "Index [-1]: Steam makeup",
60
+ ),
61
+ )
62
+ CONFIG.declare(
63
+ "num_outlets",
64
+ ConfigValue(
65
+ default=2,
66
+ domain=int,
67
+ description="Number of outlets to add"
68
+ "Index [-1]: Vent"
69
+ "Index [-2]: Condensate",
70
+ ),
71
+ )
72
+
73
+ def build(self):
74
+ super().build()
75
+ self.scaling_factor = Suffix(direction=Suffix.EXPORT)
76
+
77
+ self.inlet_list = [f"inlet_{i+1}" for i in range(self.config.num_inlets)]
78
+ self.outlet_list = [
79
+ f"outlet_{i+1}" for i in range(self.config.num_outlets)
80
+ ] + ["vent"]
81
+
82
+ # Create internal units
83
+ self.mixer = Mixer(
84
+ property_package=self.config.property_package,
85
+ property_package_args=self.config.property_package_args,
86
+ num_inlets=self.config.num_inlets,
87
+ inlet_list=self.inlet_list,
88
+ )
89
+ self.cooler = Heater(
90
+ property_package=self.config.property_package,
91
+ property_package_args=self.config.property_package_args,
92
+ has_pressure_change=True,
93
+ dynamic=self.config.dynamic,
94
+ has_holdup=self.config.has_holdup,
95
+ )
96
+ self.phase_separator = CustomSeparator(
97
+ property_package=self.config.property_package,
98
+ property_package_args=self.config.property_package_args,
99
+ outlet_list=["vapor_outlet", "condensate_outlet"],
100
+ split_basis=SplittingType.phaseFlow,
101
+ energy_split_basis=EnergySplittingType.enthalpy_split,
102
+ )
103
+ self.splitter = SimpleSeparator(
104
+ property_package=self.config.property_package,
105
+ property_package_args=self.config.property_package_args,
106
+ outlet_list=self.outlet_list,
107
+ )
108
+ self.unit_ops = [self.mixer, self.cooler, self.phase_separator, self.splitter]
109
+
110
+ # Updated internal arcs
111
+ self.mixer_to_cooler_arc = Arc(
112
+ source=self.mixer.outlet, destination=self.cooler.inlet
113
+ )
114
+ self.cooler_to_separator_arc = Arc(
115
+ source=self.cooler.outlet, destination=self.phase_separator.inlet
116
+ )
117
+ self.separator_to_splitter_arc = Arc(
118
+ source=self.phase_separator.vapor_outlet, destination=self.splitter.inlet
119
+ )
120
+
121
+ self.inlet_blocks = [getattr(self.mixer, f"{i}_state") for i in self.inlet_list]
122
+ self.outlet_blocks = [getattr(self.splitter, f"{o}_state") for o in self.outlet_list]
123
+
124
+ # Declare slack variables for internal use
125
+ self.balance_flow_mol = Var(
126
+ self.flowsheet().time, initialize=0.0, doc="Balance molar flow (negative means makeup is required, positive means venting)",
127
+ units=pyo.units.mol / pyo.units.s
128
+ )
129
+
130
+ # This is only used for scaling the smooth_min/smooth_max value.
131
+ self._partial_total_flow_mol = Var(
132
+ self.flowsheet().time, initialize=0.0, doc="Partial total fixed molar flow",
133
+ units=pyo.units.mol / pyo.units.s
134
+ )
135
+
136
+ self.makeup_flow_mol = Var(
137
+ self.flowsheet().time, initialize=0.0, doc="Makeup molar flow",
138
+ units=pyo.units.mol / pyo.units.s
139
+ )
140
+
141
+
142
+ # Add inverted transformers to heat_duty and deltaP
143
+ # (so that positive values correspond to heat loss and pressure drop)
144
+
145
+ add_inverted(self.cooler, "heat_duty")
146
+ add_inverted(self.cooler, "deltaP")
147
+ # Declare additional variables and aliases to expose to the user
148
+ self.heat_duty_inverted = Reference(self.cooler.heat_duty_inverted)
149
+ self.deltaP_inverted = Reference(self.cooler.deltaP_inverted)
150
+ self.heat_duty = Reference(self.cooler.heat_duty)
151
+ self.deltaP = Reference(self.cooler.deltaP)
152
+
153
+ self.total_flow_mol = Reference(
154
+ self.cooler.control_volume.properties_out[:].flow_mol
155
+ )
156
+ self.total_flow_mass = Reference(
157
+ self.cooler.control_volume.properties_out[:].flow_mass
158
+ )
159
+ self.pressure = Reference(
160
+ self.cooler.control_volume.properties_out[:].pressure
161
+ )
162
+ self.temperature = Reference(
163
+ self.cooler.control_volume.properties_out[:].temperature
164
+ )
165
+ self.enth_mol = Reference(
166
+ self.cooler.control_volume.properties_out[:].enth_mol
167
+ )
168
+ self.enth_mass = Reference(
169
+ self.cooler.control_volume.properties_out[:].enth_mass
170
+ )
171
+ self.vapor_frac = Reference(
172
+ self.cooler.control_volume.properties_out[:].vapor_frac
173
+ )
174
+ self.split_flow = self._create_split_flow_references()
175
+
176
+ # Condensate liquid always is removed first.
177
+ self.phase_separator.split_fraction[:, "vapor_outlet", "Vap"].fix(1.0)
178
+ self.phase_separator.split_fraction[:, "vapor_outlet", "Liq"].fix(0.0)
179
+
180
+ # Additional bounds and constraints
181
+ self._additional_constraints()
182
+
183
+ # Expand arcs
184
+ pyo.TransformationFactory("network.expand_arcs").apply_to(self)
185
+
186
+ self.cooler_to_separator_arc_expanded.flow_mol_equality.deactivate()
187
+
188
+ # add an expression for the degree of superheat
189
+
190
+ @self.Expression(self.flowsheet().time)
191
+ def degree_of_superheat(self,t):
192
+ return self.splitter.mixed_state[t].temperature - self.splitter.mixed_state[t].temperature_sat
193
+
194
+ def _create_split_flow_references(self):
195
+ self.outlet_idx = pyo.Set(initialize=self.outlet_list)
196
+ # Map each (t, o) to the outlet state's flow var
197
+ ref_map = {}
198
+ for o in self.outlet_list:
199
+ if o != "vent":
200
+ outlet_state_block = getattr(self.splitter, f"{o}_state")
201
+ for t in self.flowsheet().time:
202
+ ref_map[(t, o)] = outlet_state_block[t].flow_mol
203
+
204
+ return Reference(ref_map)
205
+
206
+ def _additional_constraints(self):
207
+ """
208
+ Additional constraints.
209
+ """
210
+
211
+ """
212
+ 1) Set lower bounds on flow variables for all external ports.
213
+ """
214
+ [
215
+ state_block[t].flow_mol.setlb(0.0)
216
+ for state_block in (self.inlet_blocks + self.outlet_blocks)
217
+ for t in state_block
218
+ ]
219
+
220
+ """
221
+ 2) Add overall material balance equation.
222
+ """
223
+
224
+ # Write phase-component balances
225
+ @self.Constraint(self.flowsheet().time, doc="Material balance equation")
226
+ def material_balance_equation(b, t):
227
+ pc_set = b.outlet_blocks[0].phase_component_set
228
+ comp_ls = b.outlet_blocks[0].component_list
229
+ phase_ls = b.outlet_blocks[0].phase_list
230
+ return (
231
+ 0
232
+ == sum(
233
+ sum(
234
+ b.mixer.mixed_state[t].get_material_flow_terms(p, j)
235
+ - (b.phase_separator.mixed_state[t].get_material_flow_terms(p, j)
236
+ - b.splitter.vent_state[t].get_material_flow_terms(p, j))
237
+ for j in comp_ls
238
+ if (p, j) in pc_set
239
+ )
240
+ for p in phase_ls
241
+ )
242
+ - b.balance_flow_mol[t]
243
+ )
244
+
245
+ """
246
+ 3) Add vent flow balance (scaled by the total known flows).
247
+ """
248
+
249
+ @self.Constraint(
250
+ self.flowsheet().time,
251
+ doc="Material balance of known inlet and outlet flows. "
252
+ "Only used for scaling the steam vent min flow, doesn't actually matter.",
253
+ )
254
+ def partial_material_balance_equation(b, t):
255
+ pc_set = b.inlet_blocks[0].phase_component_set
256
+ comp_ls = b.inlet_blocks[0].component_list
257
+ phase_ls = b.inlet_blocks[0].phase_list
258
+ return (
259
+ 0
260
+ == sum(
261
+ sum(
262
+ sum(
263
+ o[t].get_material_flow_terms(p, j)
264
+ for o in b.inlet_blocks[:-1] + b.outlet_blocks[:-2]
265
+ )
266
+ for j in comp_ls
267
+ if (p, j) in pc_set
268
+ )
269
+ for p in phase_ls
270
+ )
271
+ - b._partial_total_flow_mol[t]
272
+ )
273
+
274
+ eps = 1e-5 # smoothing parameter; smaller = closer to exact max, larger = smoother
275
+ # calculate amount for vent flow: positive balance amount
276
+ @self.Constraint(self.flowsheet().time, doc="Steam vent flow balance.")
277
+ def vent_flow_balance(b, t):
278
+ return 0 == (
279
+ smooth_max(
280
+ b.balance_flow_mol[t] / (b._partial_total_flow_mol[t] + 1e-6),
281
+ 0.0,
282
+ eps,
283
+ )
284
+ * (b._partial_total_flow_mol[t] + 1e-6)
285
+ - b.splitter.vent_state[t].flow_mol
286
+ )
287
+
288
+ # if balance is negative, vent will be zero. makeup will be required.
289
+ @self.Constraint(self.flowsheet().time, doc="Steam makeup balance")
290
+ def makeup_flow_balance(b, t):
291
+ return b.makeup_flow_mol[t] == (
292
+ b.splitter.vent_state[t].flow_mol - b.balance_flow_mol[t]
293
+ )
294
+
295
+
296
+ def calculate_scaling_factors(self):
297
+ super().calculate_scaling_factors()
298
+ [getattr(o, "calculate_scaling_factors")() for o in self.unit_ops]
299
+
300
+ def initialize_build(self, outlvl=idaeslog.NOTSET, **kwargs):
301
+ """
302
+ Initialize the Steam Header unit using Sequential Decomposition to determine optimal order
303
+ """
304
+ init_log = idaeslog.getInitLogger(self.name, outlvl, tag="unit")
305
+
306
+ init_log.info(
307
+ f"Starting {self.parent_block().__class__.__name__} initialization using Sequential Decomposition"
308
+ )
309
+ # Initialize the inverted values
310
+ initialise_inverted(self.cooler, "heat_duty")
311
+ initialise_inverted(self.cooler, "deltaP")
312
+
313
+ # create Sequential Decomposition object
314
+ seq = SequentialDecomposition()
315
+ seq.options.select_tear_method = "heuristic"
316
+ seq.options.tear_method = "Wegstein"
317
+ seq.options.iterLim = 1
318
+
319
+ # create computation graph
320
+ G = seq.create_graph(self)
321
+ heuristic_tear_set = seq.tear_set_arcs(G, method="heuristic")
322
+ # get calculation order
323
+ order = seq.calculation_order(G)
324
+
325
+ for o in heuristic_tear_set:
326
+ print(o.name)
327
+
328
+ print("Initialization order:")
329
+ for o in order:
330
+ print(o[0].name)
331
+
332
+ # define unit initialisation function
333
+ def init_unit(unit):
334
+ unit.initialize(outlvl=outlvl, **kwargs)
335
+
336
+ # run sequential decomposition
337
+ seq.run(self, init_unit)
338
+
339
+ def _get_stream_table_contents(self, time_point=0):
340
+ """
341
+ Create stream table showing all inlets, outlets, and liquid outlet
342
+ """
343
+ io_dict = {}
344
+
345
+ for inlet_name in self.inlet_list:
346
+ io_dict[inlet_name] = getattr(self, inlet_name)
347
+
348
+ for outlet_name in self.outlet_list:
349
+ io_dict[outlet_name] = getattr(self, outlet_name)
350
+
351
+ io_dict["condensate_outlet"] = self.condensate_outlet
352
+
353
+ return create_stream_table_dataframe(io_dict, time_point=time_point)