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,267 @@
1
+ # Import Pyomo tools
2
+ from pyomo.environ import (
3
+ Constraint,
4
+ Var,
5
+ Param,
6
+ Expression,
7
+ Reals,
8
+ NonNegativeReals,
9
+ Suffix,
10
+ )
11
+ from pyomo.environ import units as pyunits
12
+ from pyomo.common.config import ConfigBlock, ConfigValue, Bool
13
+
14
+ # Import IDAES cores
15
+ from idaes.core import (
16
+ declare_process_block_class,
17
+ MaterialFlowBasis,
18
+ PhysicalParameterBlock,
19
+ StateBlockData,
20
+ StateBlock,
21
+ MaterialBalanceType,
22
+ EnergyBalanceType,
23
+ )
24
+ from idaes.core.base.components import Component
25
+ from idaes.core.base.phases import LiquidPhase
26
+ from idaes.core.util.initialization import (
27
+ fix_state_vars,
28
+ revert_state_vars,
29
+ solve_indexed_blocks,
30
+ )
31
+ from idaes.core.base.process_base import ProcessBlockData
32
+ from idaes.core.base import property_meta
33
+ from idaes.core.util.model_statistics import (
34
+ degrees_of_freedom,
35
+ number_unfixed_variables,
36
+ )
37
+ from idaes.core.util.exceptions import PropertyPackageError
38
+ import idaes.core.util.scaling as iscale
39
+ import idaes.logger as idaeslog
40
+ from idaes.core.solvers import get_solver
41
+
42
+ # Set up logger
43
+ _log = idaeslog.getLogger(__name__)
44
+
45
+
46
+ # STEP 2
47
+
48
+ # When using this file the name "transformerParameterBlock" is what is imported
49
+ @declare_process_block_class("transformerParameterBlock")
50
+ class transformerParameterData(PhysicalParameterBlock):
51
+ CONFIG = ProcessBlockData.CONFIG()
52
+ CONFIG.declare(
53
+ "default_arguments",
54
+ ConfigBlock(
55
+ implicit=True, description="Default arguments to use with Property Package"
56
+ ),
57
+ )
58
+
59
+ def build(self):
60
+ """
61
+ Callable method for Block construction.
62
+ """
63
+ super(transformerParameterData, self).build()
64
+
65
+ self._state_block_class = transformerStateBlock
66
+
67
+ # Variables
68
+ self.current = Var(initialize=0, domain=Reals, units=pyunits.A)
69
+ self.voltage = Var(initialize=0, domain=Reals, units=pyunits.V)
70
+
71
+ # Default scaling values should be provided so that our tools can ensure the model is well-scaled
72
+ # Generally scaling factors should be such that if it is multiplied by the variable it will range between 0.01 and 100
73
+ self.set_default_scaling("current", 1e-3)
74
+ self.set_default_scaling("voltage", 1e-3)
75
+
76
+ @classmethod
77
+ def define_metadata(cls, obj):
78
+ # see https://github.com/watertap-org/watertap/blob/main/tutorials/creating_a_simple_property_model.ipynb
79
+ obj.add_properties(
80
+ {
81
+ "current": {"method": None},
82
+ "voltage": {"method": None},
83
+ }
84
+ )
85
+ obj.add_default_units(
86
+ {
87
+ "time": pyunits.s,
88
+ "length": pyunits.m,
89
+ "mass": pyunits.kg,
90
+ }
91
+ )
92
+
93
+ def build_state_block(self, *args, **kwargs):
94
+ """
95
+ Methods to construct a StateBlock associated with this
96
+ PhysicalParameterBlock. This will automatically set the parameters
97
+ construction argument for the StateBlock.
98
+
99
+ Returns:
100
+ StateBlock
101
+
102
+ """
103
+ # default = kwargs.pop("default", {})
104
+ initialize = kwargs.pop("initialize", {})
105
+
106
+ if initialize == {}:
107
+ kwargs["parameters"] = self
108
+ else:
109
+ for i in initialize.keys():
110
+ initialize[i]["parameters"] = self
111
+
112
+ return self.state_block_class( # pylint: disable=not-callable
113
+ *args, **kwargs, initialize=initialize
114
+ )
115
+
116
+ @property
117
+ def state_block_class(self):
118
+ if self._state_block_class is not None:
119
+ return self._state_block_class
120
+ else:
121
+ raise AttributeError(
122
+ "{} has not assigned a StateBlock class to be associated "
123
+ "with this property package. Please contact the developer of "
124
+ "the property package.".format(self.name)
125
+ )
126
+
127
+ # STEP 3: State Block
128
+ class _transformerStateBlock(StateBlock):
129
+ def initialize(
130
+ self,
131
+ state_args=None,
132
+ state_vars_fixed=False,
133
+ hold_state=False,
134
+ outlvl=idaeslog.NOTSET,
135
+ solver=None,
136
+ optarg=None,
137
+ ):
138
+ """
139
+ Initialization routine for property package.
140
+ Keyword Arguments:
141
+ state_args : Dictionary with initial guesses for the state vars
142
+ chosen. Note that if this method is triggered
143
+ through the control volume, and if initial guesses
144
+ were not provided at the unit model level, the
145
+ control volume passes the inlet values as initial
146
+ guess.The keys for the state_args dictionary are:
147
+
148
+ flow_mass_phase_comp : value at which to initialize
149
+ phase component flows
150
+ pressure : value at which to initialize pressure
151
+ temperature : value at which to initialize temperature
152
+
153
+ state_vars_fixed: Flag to denote if state vars have already been
154
+ fixed.
155
+ - True - states have already been fixed by the
156
+ control volume 1D. Control volume 0D
157
+ does not fix the state vars, so will
158
+ be False if this state block is used
159
+ with 0D blocks.
160
+ - False - states have not been fixed. The state
161
+ block will deal with fixing/unfixing.
162
+ hold_state : flag indicating whether the initialization routine
163
+ should unfix any state variables fixed during
164
+ initialization (default=False).
165
+ - True - states variables are not unfixed, and
166
+ a dict of returned containing flags for
167
+ which states were fixed during
168
+ initialization.
169
+ - False - state variables are unfixed after
170
+ initialization by calling the
171
+ release_state method
172
+ outlvl : sets output level of initialization routine (default=idaeslog.NOTSET)
173
+ solver : Solver object to use during initialization if None is provided
174
+ it will use the default solver for IDAES (default = None)
175
+ optarg : solver options dictionary object (default=None)
176
+ Returns:
177
+ If hold_states is True, returns a dict containing flags for
178
+ which states were fixed during initialization.
179
+ """
180
+
181
+ # Fix state variables
182
+ flags = fix_state_vars(self, state_args)
183
+ # Check that dof = 0 when state variables are fixed
184
+ for k in self.keys():
185
+ dof = degrees_of_freedom(self[k])
186
+ if dof != 0:
187
+ raise PropertyPackageError(
188
+ "\nWhile initializing {sb_name}, the degrees of freedom "
189
+ "are {dof}, when zero is required. \nInitialization assumes "
190
+ "that the state variables should be fixed and that no other "
191
+ "variables are fixed. \nIf other properties have a "
192
+ "predetermined value, use the calculate_state method "
193
+ "before using initialize to determine the values for "
194
+ "the state variables and avoid fixing the property variables."
195
+ "".format(sb_name=self.name, dof=dof)
196
+ )
197
+
198
+ # If input block, return flags, else release state
199
+ if state_vars_fixed is False:
200
+ if hold_state is True:
201
+ return flags
202
+ else:
203
+ self.release_state(flags)
204
+
205
+ def release_state(self, flags, outlvl=idaeslog.NOTSET):
206
+ """
207
+ Method to release state variables fixed during initialisation.
208
+
209
+ Keyword Arguments:
210
+ flags : dict containing information of which state variables
211
+ were fixed during initialization, and should now be
212
+ unfixed. This dict is returned by initialize if
213
+ hold_state=True.
214
+ outlvl : sets output level of of logging
215
+ """
216
+ if flags is None:
217
+ return
218
+ # Unfix state variables
219
+ for attr in flags:
220
+ if flags[attr] is True:
221
+ getattr(self, attr).unfix()
222
+ return
223
+
224
+ # STEP 4:
225
+ @declare_process_block_class("transformerStateBlock", block_class=_transformerStateBlock)
226
+ class transformerStateBlockData(StateBlockData):
227
+ def build(self):
228
+ """Callable method for Block construction."""
229
+ super(transformerStateBlockData, self).build()
230
+
231
+ self.scaling_factor = Suffix(direction=Suffix.EXPORT)
232
+
233
+ self.current = Var(
234
+ initialize=0,
235
+ domain=Reals,
236
+ units=pyunits.A,
237
+ doc="reactive power flow",
238
+ )
239
+ self.voltage = Var(
240
+ initialize=0,
241
+ domain=Reals,
242
+ units=pyunits.V,
243
+ doc="voltage",
244
+ )
245
+
246
+ # -----------------------------------------------------------------------------
247
+
248
+ def define_state_vars(self):
249
+ """Define state vars."""
250
+ return {
251
+ "current" : self.current,
252
+ "voltage": self.voltage
253
+ }
254
+
255
+
256
+ # -----------------------------------------------------------------------------
257
+ # Scaling methods
258
+ def calculate_scaling_factors(self):
259
+ super().calculate_scaling_factors()
260
+ # This doesn't do anything, but it's a good example of how to get and set scaling factors in relation to each other.
261
+ sfc = iscale.get_scaling_factor(self.current)
262
+ iscale.set_scaling_factor(self.current, sfc)
263
+ sfv = iscale.get_scaling_factor(self.voltage)
264
+ iscale.set_scaling_factor(self.voltage, sfv)
265
+
266
+
267
+
@@ -0,0 +1,228 @@
1
+ # Import Pyomo libraries
2
+ from stringprep import in_table_a1
3
+ from pyomo import environ
4
+ from pyomo.environ import (
5
+ Constraint,
6
+ Set,
7
+ Var,
8
+ Suffix,
9
+ units as pyunits,
10
+ atan
11
+ )
12
+ from pyomo.environ import Reals
13
+ from pyomo.common.config import ConfigBlock, ConfigValue, In
14
+ from pyomo.contrib.fbbt import interval
15
+ from idaes.core.util.model_statistics import degrees_of_freedom
16
+ # Import IDAES cores
17
+ from idaes.core import (
18
+ declare_process_block_class,
19
+ UnitModelBlockData,
20
+ useDefault,
21
+ MaterialBalanceType,
22
+ MaterialFlowBasis,
23
+ )
24
+ from idaes.core.util.config import is_physical_parameter_block
25
+ import idaes.core.util.scaling as iscale
26
+ import idaes.logger as idaeslog
27
+ from idaes.models.unit_models import separator
28
+ from idaes.core.util.tables import create_stream_table_dataframe
29
+ from idaes.core.util.exceptions import ConfigurationError, BurntToast, PropertyNotSupportedError
30
+
31
+ from idaes.models.unit_models import separator
32
+ #Import enum
33
+ from enum import Enum
34
+
35
+ # Set up logger
36
+ _log = idaeslog.getLogger(__name__)
37
+
38
+ import math
39
+ # Enumerate options for balances
40
+ class SplittingType(Enum):
41
+ """
42
+ Enum of supported material split types.
43
+ """
44
+
45
+ totalFlow = 1
46
+ phaseFlow = 2
47
+ componentFlow = 3
48
+ phaseComponentFlow = 4
49
+
50
+
51
+
52
+ # When using this file the name "transmissionLine" is what is imported
53
+ @declare_process_block_class("transmissionLine")
54
+ class transmissionLineData(UnitModelBlockData):
55
+ """
56
+ Zero order transmission line model
57
+ """
58
+
59
+ # CONFIG are options for the unit model, this simple model only has the mandatory config options
60
+ CONFIG = ConfigBlock()
61
+
62
+ CONFIG.declare(
63
+ "dynamic",
64
+ ConfigValue(
65
+ domain=In([False]),
66
+ default=False,
67
+ description="Dynamic model flag - must be False",
68
+ doc="""Indicates whether this model will be dynamic or not,
69
+ **default** = False. The Bus unit does not support dynamic
70
+ behavior, thus this must be False.""",
71
+ ),
72
+ )
73
+ CONFIG.declare(
74
+ "has_holdup",
75
+ ConfigValue(
76
+ default=False,
77
+ domain=In([False]),
78
+ description="Holdup construction flag - must be False",
79
+ doc="""Indicates whether holdup terms should be constructed or not.
80
+ **default** - False. The Bus unit does not have defined volume, thus
81
+ this must be False.""",
82
+ ),
83
+ )
84
+ CONFIG.declare(
85
+ "property_package",
86
+ ConfigValue(
87
+ default=useDefault,
88
+ domain=is_physical_parameter_block,
89
+ description="Property package to use for control volume",
90
+ doc="""Property parameter object used to define property calculations,
91
+ **default** - useDefault.
92
+ **Valid values:** {
93
+ **useDefault** - use default package from parent model or flowsheet,
94
+ **PhysicalParameterObject** - a PhysicalParameterBlock object.}""",
95
+ ),
96
+ )
97
+ CONFIG.declare(
98
+ "property_package_args",
99
+ ConfigBlock(
100
+ implicit=True,
101
+ description="Arguments to use for constructing property packages",
102
+ doc="""A ConfigBlock with arguments to be passed to a property block(s)
103
+ and used when constructing these,
104
+ **default** - None.
105
+ **Valid values:** {
106
+ see property package for documentation.}""",
107
+ ),
108
+ )
109
+ CONFIG.declare(
110
+ "num_inlets",
111
+ ConfigValue(
112
+ default=False,
113
+ domain=int,
114
+ description="Number of inlets to add",
115
+ doc="Number of inlets to add",
116
+ ),
117
+ )
118
+ CONFIG.declare(
119
+ "num_outlets",
120
+ ConfigValue(
121
+ default=False,
122
+ domain=int,
123
+ description="Number of outlets to add",
124
+ doc="Number of outlets to add",
125
+ ),
126
+ )
127
+ CONFIG.declare(
128
+ "material_balance_type",
129
+ ConfigValue(
130
+ default=MaterialBalanceType.useDefault,
131
+ domain=In(MaterialBalanceType),
132
+ description="Material balance construction flag",
133
+ doc="""Indicates what type of mass balance should be constructed,
134
+ **default** - MaterialBalanceType.useDefault.
135
+ **Valid values:** {
136
+ **MaterialBalanceType.useDefault - refer to property package for default
137
+ balance type
138
+ **MaterialBalanceType.none** - exclude material balances,
139
+ **MaterialBalanceType.componentPhase** - use phase component balances,
140
+ **MaterialBalanceType.componentTotal** - use total component balances,
141
+ **MaterialBalanceType.elementTotal** - use total element balances,
142
+ **MaterialBalanceType.total** - use total material balance.}""",
143
+ ),
144
+ )
145
+
146
+
147
+ def build(self):
148
+ # build always starts by calling super().build()
149
+ # This triggers a lot of boilerplate in the background for you
150
+ super().build()
151
+
152
+ # This creates blank scaling factors, which are populated later
153
+ self.scaling_factor = Suffix(direction=Suffix.EXPORT)
154
+
155
+ tmp_dict = dict(**self.config.property_package_args)
156
+ tmp_dict["parameters"] = self.config.property_package
157
+
158
+ # Add state blocks for inlet, outlet, and waste
159
+ # These include the state variables and any other properties on demand
160
+ # Add inlet block
161
+ # tmp_dict = dict(**self.config.property_package_args)
162
+ # tmp_dict["parameters"] = self.config.property_package
163
+ # tmp_dict["defined_state"] = True # inlet block is an inlet
164
+ # self.properties_in = self.config.property_package.state_block_class(
165
+ # self.flowsheet().config.time, doc="Material properties of inlet", **tmp_dict
166
+ # )
167
+
168
+ # Add outlet and waste block
169
+ tmp_dict["defined_state"] = False # outlet and waste block is not an inlet
170
+ self.properties_out = self.config.property_package.state_block_class(
171
+ self.flowsheet().config.time,
172
+ doc="Material properties of outlet",
173
+ **tmp_dict
174
+ )
175
+ # Add second outlet block
176
+ tmp_dict["defined_state"] = False
177
+ self.properties_out2 = self.config.property_package.state_block_class(
178
+ self.flowsheet().config.time, doc="Material properties of inlet", **tmp_dict
179
+ )
180
+
181
+ # Add ports - oftentimes users interact with these rather than the state blocks
182
+ # self.add_port(name="inlet_1", block=self.properties_in)
183
+ # self.add_port(name="inlet_2", block=self.properties_in2)
184
+ self.add_port(name="outlet_1", block=self.properties_out)
185
+ self.add_port(name="outlet_2", block=self.properties_out2)
186
+
187
+ self.power_transfer = Var(self.flowsheet().config.time,
188
+ initialize=1.0,
189
+ doc="Power transferred between busses",
190
+ units = pyunits.W
191
+
192
+ )
193
+
194
+ # Add constraints:
195
+ @self.Constraint(
196
+ self.flowsheet().time,
197
+ doc = "Power balance"
198
+ )
199
+ def eq_power_balance(b,t):
200
+ return self.properties_out2[t].power == self.power_transfer[t]
201
+
202
+ @self.Constraint(
203
+ self.flowsheet().time,
204
+ doc = "Power calculation"
205
+ )
206
+ def eq_power_calc(b,t):
207
+ return self.properties_out[t].power == self.power_transfer[t] * -1
208
+
209
+
210
+
211
+ def calculate_scaling_factors(self):
212
+ super().calculate_scaling_factors()
213
+
214
+ def initialize(blk, *args, **kwargs):
215
+ for i in blk.properties_out.index_set():
216
+ if not blk.properties_out[i].power.fixed:
217
+ blk.properties_out[i].power = blk.power_transfer[i].value
218
+
219
+
220
+ def _get_stream_table_contents(self, time_point=0):
221
+ """
222
+ Assume unit has standard configuration of 1 inlet and 1 outlet.
223
+
224
+ Developers should overload this as appropriate.
225
+ """
226
+
227
+
228
+
@@ -0,0 +1,206 @@
1
+ # Import Pyomo libraries
2
+ from ast import Expression
3
+ from cmath import pi
4
+ from pyomo.environ import (
5
+ Var,
6
+ Suffix,
7
+ units as pyunits,
8
+ )
9
+ from pyomo.common.config import ConfigBlock, ConfigValue, In
10
+
11
+ # Import IDAES cores
12
+ from idaes.core import (
13
+ declare_process_block_class,
14
+ UnitModelBlockData,
15
+ useDefault,
16
+ )
17
+ from idaes.core.util.config import is_physical_parameter_block
18
+ import idaes.core.util.scaling as iscale
19
+ import idaes.logger as idaeslog
20
+
21
+ from idaes.core.util.tables import create_stream_table_dataframe
22
+
23
+ from idaes.core.util.exceptions import ConfigurationError
24
+
25
+ # Set up logger
26
+ _log = idaeslog.getLogger(__name__)
27
+
28
+
29
+ # When using this file the name "Wind" is what is imported
30
+ @declare_process_block_class("Wind")
31
+ class WindData(UnitModelBlockData):
32
+ """
33
+ Zero order Link model
34
+ """
35
+
36
+ # CONFIG are options for the unit model, this simple model only has the mandatory config options
37
+ CONFIG = ConfigBlock()
38
+
39
+ CONFIG.declare(
40
+ "dynamic",
41
+ ConfigValue(
42
+ domain=In([False]),
43
+ default=False,
44
+ description="Dynamic model flag - must be False",
45
+ doc="""Indicates whether this model will be dynamic or not,
46
+ **default** = False. The Bus unit does not support dynamic
47
+ behavior, thus this must be False.""",
48
+ ),
49
+ )
50
+ CONFIG.declare(
51
+ "has_holdup",
52
+ ConfigValue(
53
+ default=False,
54
+ domain=In([False]),
55
+ description="Holdup construction flag - must be False",
56
+ doc="""Indicates whether holdup terms should be constructed or not.
57
+ **default** - False. The Bus unit does not have defined volume, thus
58
+ this must be False.""",
59
+ ),
60
+ )
61
+ CONFIG.declare(
62
+ "property_package",
63
+ ConfigValue(
64
+ default=useDefault,
65
+ domain=is_physical_parameter_block,
66
+ description="Property package to use for control volume",
67
+ doc="""Property parameter object used to define property calculations,
68
+ **default** - useDefault.
69
+ **Valid values:** {
70
+ **useDefault** - use default package from parent model or flowsheet,
71
+ **PhysicalParameterObject** - a PhysicalParameterBlock object.}""",
72
+ ),
73
+ )
74
+ CONFIG.declare(
75
+ "property_package_args",
76
+ ConfigBlock(
77
+ implicit=True,
78
+ description="Arguments to use for constructing property packages",
79
+ doc="""A ConfigBlock with arguments to be passed to a property block(s)
80
+ and used when constructing these,
81
+ **default** - None.
82
+ **Valid values:** {
83
+ see property package for documentation.}""",
84
+ ),
85
+ )
86
+
87
+ def build(self):
88
+ # build always starts by calling super().build()
89
+ # This triggers a lot of boilerplate in the background for you
90
+ super().build()
91
+
92
+ # This creates blank scaling factors, which are populated later
93
+ self.scaling_factor = Suffix(direction=Suffix.EXPORT)
94
+
95
+
96
+ # Add state blocks for inlet, outlet, and waste
97
+ # These include the state variables and any other properties on demand
98
+ # Add inlet block
99
+ tmp_dict = dict(**self.config.property_package_args)
100
+ tmp_dict["parameters"] = self.config.property_package
101
+ #tmp_dict["defined_state"] = True # inlet block is an inlet
102
+
103
+ # Add outlet
104
+ tmp_dict["defined_state"] = False # outlet is not an inlet
105
+ self.properties_out = self.config.property_package.state_block_class(
106
+ self.flowsheet().config.time,
107
+ doc="Material properties of outlet",
108
+ **tmp_dict
109
+ )
110
+
111
+ # Add ports - oftentimes users interact with these rather than the state blocks
112
+
113
+ self.add_port(name="outlet", block=self.properties_out)
114
+
115
+ # Add variable for efficiency
116
+ self.efficiency = Var(
117
+ initialize=1.0,
118
+ doc="Efficiency of the turbine",
119
+ )
120
+
121
+ # Add variable for Windspeed
122
+ self.windspeed = Var(self.flowsheet().config.time,
123
+ initialize=1.0, units = pyunits.m/pyunits.s,
124
+ doc="Speed of wind hitting the turbines",
125
+ )
126
+
127
+ # Add variable for Pressure
128
+ self.pressure = Var(self.flowsheet().config.time,
129
+ initialize=1.0, units = pyunits.Pa,
130
+ doc="Air pressure",
131
+ )
132
+
133
+ # Add variable for Temperature
134
+ self.air_temp = Var(self.flowsheet().config.time,
135
+ initialize=1.0, units = pyunits.degK,
136
+ doc="Air Temperature",
137
+ )
138
+
139
+ # Add variable for Humidity
140
+ self.humidity = Var(self.flowsheet().config.time,
141
+ initialize=1.0,
142
+ doc="Air humidity",
143
+ )
144
+
145
+ # Add variable for rotor diameter
146
+ self.rotor_diameter = Var(
147
+ initialize=1.0, units = pyunits.m,
148
+ doc="Rotor Diameter",
149
+ )
150
+
151
+ # Add variable for no. of turbines
152
+ self.turbine_count = Var(
153
+ initialize=1.0,
154
+ doc="Number of turbines",
155
+ )
156
+
157
+ # Simple expressions
158
+ self.radius = self.rotor_diameter / 2
159
+ self.area = pi * self.radius**2
160
+ self.Cp= 0.579 # Power coefficient, typically between 0.4 and 0.6 for wind turbines
161
+
162
+
163
+ # Expression indexed by time
164
+ @self.Expression(
165
+ self.flowsheet().time
166
+ )
167
+ def density(b,t):
168
+ return(
169
+ (self.pressure[t]/(287.05 * self.air_temp[t])) * (1-0.378*(self.humidity[t]))
170
+ )
171
+
172
+
173
+ # Add constraints
174
+ @self.Constraint(
175
+ self.flowsheet().time,
176
+ doc="Power usage",
177
+ )
178
+ def eq_power_balance(b, t):
179
+ return (
180
+ 0.5 * self.density[t] * self.area * self.windspeed[t]**3 * self.Cp * self.efficiency * self.turbine_count == b.properties_out[t].power
181
+ )
182
+
183
+
184
+ def calculate_scaling_factors(self):
185
+ super().calculate_scaling_factors()
186
+
187
+ def initialize(blk, *args, **kwargs):
188
+ # Just propagate the power from inlet to outlet, good simple method of initialization
189
+ pass
190
+
191
+ def _get_stream_table_contents(self, time_point=0):
192
+ """
193
+ Assume unit has standard configuration of 1 inlet and 1 outlet.
194
+
195
+ Developers should overload this as appropriate.
196
+ """
197
+ try:
198
+ return create_stream_table_dataframe(
199
+ {"Outlet": self.outlet}, time_point=time_point
200
+ )
201
+ except AttributeError:
202
+ raise ConfigurationError(
203
+ f"Unit model {self.name} does not have the standard Port "
204
+ f"names (inlet and outlet). Please contact the unit model "
205
+ f"developer to develop a unit specific stream table."
206
+ )