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,230 @@
1
+ # Import Pyomo libraries
2
+ from pyomo.environ import (
3
+ Var,
4
+ Suffix,
5
+ units as pyunits,
6
+ )
7
+ from pyomo.common.config import ConfigBlock, ConfigValue, In
8
+ from idaes.core.util.exceptions import ConfigurationError
9
+
10
+ # Import IDAES cores
11
+ from idaes.core import (
12
+ declare_process_block_class,
13
+ UnitModelBlockData,
14
+ useDefault,
15
+ )
16
+ from idaes.core.util.config import is_physical_parameter_block
17
+ import idaes.core.util.scaling as iscale
18
+ import idaes.logger as idaeslog
19
+ from pyomo.util.check_units import assert_units_consistent
20
+ from pyomo.environ import value
21
+
22
+ # Set up logger
23
+ _log = idaeslog.getLogger(__name__)
24
+
25
+
26
+ # When using this file the name "Link" is what is imported
27
+ @declare_process_block_class("Storage")
28
+ class StorageData(UnitModelBlockData):
29
+ """
30
+ Zero order Link model
31
+ """
32
+
33
+ # CONFIG are options for the unit model, this simple model only has the mandatory config options
34
+ CONFIG = ConfigBlock()
35
+
36
+ CONFIG.declare(
37
+ "dynamic",
38
+ ConfigValue(
39
+ domain=In([False]),
40
+ default=False,
41
+ description="Dynamic model flag - must be False",
42
+ doc="""Indicates whether this model will be dynamic or not,
43
+ **default** = False. The Bus unit does not support dynamic
44
+ behavior, thus this must be False.""",
45
+ ),
46
+ )
47
+ CONFIG.declare(
48
+ "has_holdup",
49
+ ConfigValue(
50
+ default=False,
51
+ domain=In([False]),
52
+ description="Holdup construction flag - must be False",
53
+ doc="""Indicates whether holdup terms should be constructed or not.
54
+ **default** - False. The Bus unit does not have defined volume, thus
55
+ this must be False.""",
56
+ ),
57
+ )
58
+ CONFIG.declare(
59
+ "property_package",
60
+ ConfigValue(
61
+ default=useDefault,
62
+ domain=is_physical_parameter_block,
63
+ description="Property package to use for control volume",
64
+ doc="""Property parameter object used to define property calculations,
65
+ **default** - useDefault.
66
+ **Valid values:** {
67
+ **useDefault** - use default package from parent model or flowsheet,
68
+ **PhysicalParameterObject** - a PhysicalParameterBlock object.}""",
69
+ ),
70
+ )
71
+ CONFIG.declare(
72
+ "property_package_args",
73
+ ConfigBlock(
74
+ implicit=True,
75
+ description="Arguments to use for constructing property packages",
76
+ doc="""A ConfigBlock with arguments to be passed to a property block(s)
77
+ and used when constructing these,
78
+ **default** - None.
79
+ **Valid values:** {
80
+ see property package for documentation.}""",
81
+ ),
82
+ )
83
+
84
+ def build(self):
85
+ # build always starts by calling super().build()
86
+ # This triggers a lot of boilerplate in the background for you
87
+ super().build()
88
+
89
+ # This creates blank scaling factors, which are populated later
90
+ self.scaling_factor = Suffix(direction=Suffix.EXPORT)
91
+
92
+
93
+ # Add state blocks for inlet, outlet, and waste
94
+ # These include the state variables and any other properties on demand
95
+ # Add inlet block
96
+ tmp_dict = dict(**self.config.property_package_args)
97
+ tmp_dict["parameters"] = self.config.property_package
98
+ tmp_dict["defined_state"] = True # inlet block is an inlet
99
+ self.properties_in = self.config.property_package.state_block_class(
100
+ self.flowsheet().config.time, doc="Material properties of inlet", **tmp_dict
101
+ )
102
+ # Add outlet and waste block
103
+ tmp_dict["defined_state"] = True
104
+ self.properties_in = self.config.property_package.state_block_class(
105
+ self.flowsheet().config.time,
106
+ doc="Material properties of outlet",
107
+ **tmp_dict
108
+ )
109
+ tmp_dict["defined_state"] = False # outlet and waste block is not an inlet
110
+ self.properties_out = self.config.property_package.state_block_class(
111
+ self.flowsheet().config.time,
112
+ doc="Material properties of outlet",
113
+ **tmp_dict
114
+ )
115
+
116
+
117
+ # Add ports - oftentimes users interact with these rather than the state blocks
118
+ self.add_port(name="inlet", block=self.properties_in)
119
+ self.add_port(name="outlet", block=self.properties_out)
120
+
121
+ # Add variables:
122
+ self.charging_efficiency = Var(
123
+ self.flowsheet().config.time,
124
+ initialize=1.0,
125
+ doc="Charging Efficiency",
126
+ )
127
+ self.capacity = Var(self.flowsheet().config.time,
128
+ initialize=1.0,
129
+ units=pyunits.kWh,
130
+ doc="Capacity of the storage",
131
+ )
132
+ self.initial_SOC = Var(self.flowsheet().config.time,
133
+ initialize=0.4,
134
+ doc="Initial State of Charge",
135
+ )
136
+ self.charging_power_in = Var(self.flowsheet().config.time,
137
+ initialize=1.0,
138
+ units=pyunits.W,
139
+ doc="Power in",
140
+ )
141
+ self.charging_power_out = Var(self.flowsheet().config.time,
142
+ initialize=1.0,
143
+ units=pyunits.W,
144
+ doc="Power out",
145
+ )
146
+
147
+ @self.Expression(
148
+ self.flowsheet().time,
149
+ doc="updated state of charge",
150
+ )
151
+ def updated_SOC(b,t):
152
+ power_in = self.charging_power_in[t]
153
+ power_out = self.charging_power_out[t]
154
+ power_change = (power_in-power_out)/(pyunits.W *1000)
155
+ capacity_without_unit = self.capacity[t]/pyunits.kWh
156
+ if t == self.flowsheet().time.first():
157
+ self.updated_SOC[t] = self.initial_SOC[t] + power_change/capacity_without_unit
158
+ else:
159
+ self.updated_SOC[t] = self.updated_SOC[t-1] + power_change/capacity_without_unit
160
+
161
+ return self.updated_SOC[t]
162
+
163
+
164
+
165
+ @self.Constraint(
166
+ self.flowsheet().time,
167
+ doc="Set output power for charging",
168
+ )
169
+
170
+
171
+ @self.Constraint(
172
+ self.flowsheet().time,
173
+ doc="Set output power for discharging",
174
+ )
175
+ def set_power_out_discharge(b,t):
176
+ return b.properties_out[t].power == self.charging_power_out[t]
177
+
178
+
179
+ @self.Constraint(
180
+ self.flowsheet().time,
181
+ doc="Set output power for charging",
182
+ )
183
+ def set_power_charge(b,t):
184
+ return self.charging_power_in[t] == self.properties_in[t].power
185
+
186
+
187
+ # Add a constraint to ensure power_change is within a range
188
+ @self.Constraint(
189
+ self.flowsheet().time,
190
+ doc="Ensure power_change is within a specified range",
191
+ )
192
+ def power_change_within_range(b, t):
193
+ power_in = self.charging_power_in[t]
194
+ power_out = self.charging_power_out[t]
195
+ power_in_out = (power_in-power_out)/(pyunits.W *1000)
196
+ # power_in_out = b.properties_out[t].power / (pyunits.W * 1000)
197
+ remaining_power = power_in_out + self.initial_SOC[t] * self.capacity[t]
198
+ return remaining_power <= self.capacity[t]
199
+
200
+ @self.Constraint(
201
+ self.flowsheet().time,
202
+ doc="Ensure power_change is within capacity",
203
+ )
204
+ def power_change_above_zero(b, t):
205
+
206
+ power_in = self.charging_power_in[t]
207
+ power_out = self.charging_power_out[t]
208
+ power_in_out = (power_in-power_out)/(pyunits.W *1000)
209
+ #power_in_out = b.properties_out[t].power / (pyunits.W * 1000)
210
+ remaining_power = power_in_out + self.initial_SOC[t] * self.capacity[t]
211
+ return remaining_power >= 0
212
+
213
+ def calculate_scaling_factors(self):
214
+ super().calculate_scaling_factors()
215
+
216
+ def initialize(blk, *args, **kwargs):
217
+
218
+ for i in blk.properties_in.index_set():
219
+ if blk.initial_SOC[i].value == 0 and abs(blk.charging_power_out[i].value)> 0 and abs(blk.charging_power_in[i].value) == 0:
220
+ raise ConfigurationError(
221
+ "Warning: There is no power to discharge in the battery."
222
+ )
223
+ if blk.charging_power_in[i].value > blk.capacity[i].value:
224
+ pass
225
+ # raise ConfigurationError(
226
+ # "Warning: Battery capacity is exceeded!"
227
+ # )
228
+
229
+ def _get_stream_table_contents(self, time_point=0):
230
+ pass
File without changes
File without changes
@@ -0,0 +1,44 @@
1
+ ### Imports
2
+ from pyomo.environ import ConcreteModel, SolverFactory, SolverStatus, TerminationCondition, Block, TransformationFactory, assert_optimal_termination
3
+ from pyomo.network import SequentialDecomposition, Port, Arc
4
+ from pyomo.core.base.units_container import _PyomoUnit, units
5
+ from idaes.core import FlowsheetBlock
6
+ from idaes.core.util.model_statistics import report_statistics, degrees_of_freedom
7
+ from idaes.core.util.tables import _get_state_from_port
8
+ import idaes.logger as idaeslog
9
+ from property_packages.build_package import build_package
10
+ from idaes.models.unit_models.pressure_changer import Pump
11
+ from idaes.models.unit_models.heater import Heater
12
+ from ..power_property_package import PowerParameterBlock
13
+ from ..bus import Bus
14
+ from pyomo.environ import value
15
+
16
+ def test_bus():
17
+ m = ConcreteModel()
18
+ m.fs = FlowsheetBlock(dynamic=False)
19
+ m.fs.power_property_package = PowerParameterBlock()
20
+
21
+ m.fs.bus = Bus(
22
+ property_package=m.fs.power_property_package,
23
+ num_inlets=2,
24
+
25
+
26
+ )
27
+ m.fs.bus.inlet_1.power.fix(100 * units.kW)
28
+ m.fs.bus.inlet_2.power.fix(50 * units.kW)
29
+
30
+
31
+ m.fs.bus.eq_power_balance.pprint()
32
+
33
+ #m.fs.bus.display()
34
+
35
+ # Check that the model is fully specified
36
+ assert degrees_of_freedom(m.fs.bus) == 0
37
+
38
+ # check that it solves correctly
39
+
40
+ solver = SolverFactory("ipopt")
41
+ solver.solve(m)
42
+ print(*"Post solve power:")
43
+
44
+ assert value(m.fs.bus.properties_out[0].power)- 150e3 == 0
@@ -0,0 +1,46 @@
1
+ ### Imports
2
+ from pyomo.environ import ConcreteModel, SolverFactory, SolverStatus, TerminationCondition, Block, TransformationFactory, assert_optimal_termination
3
+ from pyomo.network import SequentialDecomposition, Port, Arc
4
+ from pyomo.core.base.units_container import _PyomoUnit, units
5
+ from idaes.core import FlowsheetBlock
6
+ from idaes.core.util.model_statistics import report_statistics, degrees_of_freedom
7
+ from idaes.core.util.tables import _get_state_from_port
8
+ import idaes.logger as idaeslog
9
+ from property_packages.build_package import build_package
10
+ from idaes.models.unit_models.pressure_changer import Pump
11
+ from idaes.models.unit_models.heater import Heater
12
+ from ..energy_mixer import EnergyMixer
13
+ from ..power_property_package import PowerParameterBlock
14
+ from pyomo.environ import value
15
+
16
+
17
+ def test_energy_mixer():
18
+ m = ConcreteModel()
19
+ m.fs = FlowsheetBlock()
20
+ m.fs.power_property_package = PowerParameterBlock()
21
+
22
+ m.fs.mixer = EnergyMixer(
23
+ property_package=m.fs.power_property_package,
24
+ num_inlets=3,
25
+ )
26
+
27
+
28
+
29
+
30
+ m.fs.mixer.inlet_1.power.fix(100 * units.kW)
31
+ m.fs.mixer.inlet_2.power.fix(1000 * units.W)
32
+ m.fs.mixer.inlet_3.power.fix(10 * units.kW)
33
+ m.fs.mixer.efficiency.fix(0.90)
34
+
35
+ # Check that the model is fully specified
36
+ assert degrees_of_freedom(m) == 0
37
+
38
+ # check that it solves correctly
39
+
40
+ solver = SolverFactory("ipopt")
41
+ solver.solve(m)
42
+ #assert m.fs.mixer.outlet.power[0].value == 111 * units.kW
43
+ assert abs(m.fs.mixer.outlet.power[0].value - 999e2) < 1e-3
44
+
45
+
46
+
@@ -0,0 +1,49 @@
1
+ ### Imports
2
+ from pyomo.environ import ConcreteModel, SolverFactory, SolverStatus, TerminationCondition, Block, TransformationFactory, assert_optimal_termination
3
+ from pyomo.network import SequentialDecomposition, Port, Arc
4
+ from pyomo.core.base.units_container import _PyomoUnit, units
5
+ from idaes.core import FlowsheetBlock
6
+ from idaes.core.util.model_statistics import report_statistics, degrees_of_freedom
7
+ from idaes.core.util.tables import _get_state_from_port
8
+ import idaes.logger as idaeslog
9
+ from property_packages.build_package import build_package
10
+ from idaes.models.unit_models.pressure_changer import Pump
11
+ from idaes.models.unit_models.heater import Heater
12
+ from ..power_property_package import PowerParameterBlock
13
+ from ..bus import Bus
14
+ from ..mainDistributionBoard import MDB
15
+ from pyomo.environ import value
16
+
17
+ def test_mdb():
18
+ m = ConcreteModel()
19
+ m.fs = FlowsheetBlock(dynamic=False)
20
+ m.fs.power_property_package = PowerParameterBlock()
21
+ m.fs.mdb = MDB(
22
+ property_package=m.fs.power_property_package,
23
+ num_inlets=1,
24
+ num_outlets=3,
25
+ )
26
+ m.fs.mdb.inlet_1.power.fix(10 * units.kW)
27
+ m.fs.mdb.priorities[0,'outlet_1'].fix(5* units.kW)
28
+ m.fs.mdb.priorities[0,'outlet_2'].fix(3* units.kW)
29
+
30
+
31
+ # Check that the model is fully specified
32
+ assert degrees_of_freedom(m.fs.mdb) == 0
33
+
34
+ # check that it solves correctly
35
+ solver = SolverFactory("ipopt")
36
+ solver.solve(m)
37
+ assert abs(value(m.fs.mdb.outlet_3.power[0])) <= 2.0005e3
38
+
39
+ #Reduce input power and check that it doesn't give power to the last outlet:
40
+ m.fs.mdb.inlet_1.power.fix(8 * units.kW)
41
+ solver = SolverFactory("ipopt")
42
+ solver.solve(m)
43
+ assert abs(value(m.fs.mdb.outlet_3.power[0])) <= 0.0005
44
+
45
+ #Increase input power and check that it gives all excess power to the last outlet:
46
+ m.fs.mdb.inlet_1.power.fix(18 * units.kW)
47
+ solver = SolverFactory("ipopt")
48
+ solver.solve(m)
49
+ assert abs(value(m.fs.mdb.outlet_3.power[0])) <= 10.0005e3
@@ -0,0 +1,187 @@
1
+ # Import Pyomo libraries
2
+ from pyomo.environ import (
3
+ Var,
4
+ Suffix,
5
+ units as pyunits,
6
+ )
7
+ from pyomo.common.config import ConfigBlock, ConfigValue, In
8
+
9
+ # Import IDAES cores
10
+ from idaes.core import (
11
+ declare_process_block_class,
12
+ UnitModelBlockData,
13
+ useDefault,
14
+ )
15
+ from idaes.core.util.config import is_physical_parameter_block
16
+ import idaes.core.util.scaling as iscale
17
+ import idaes.logger as idaeslog
18
+ from idaes.core.util.exceptions import ConfigurationError
19
+ # Set up logger
20
+ _log = idaeslog.getLogger(__name__)
21
+
22
+
23
+
24
+ # When using this file the name "Transformer" is what is imported
25
+ @declare_process_block_class("Transformer")
26
+ class TransformerData(UnitModelBlockData):
27
+ """
28
+ Zero order Transformer model
29
+ """
30
+
31
+ # CONFIG are options for the unit model, this simple model only has the mandatory config options
32
+ CONFIG = ConfigBlock()
33
+
34
+ CONFIG.declare(
35
+ "dynamic",
36
+ ConfigValue(
37
+ domain=In([False]),
38
+ default=False,
39
+ description="Dynamic model flag - must be False",
40
+ doc="""Indicates whether this model will be dynamic or not,
41
+ **default** = False. The Bus unit does not support dynamic
42
+ behavior, thus this must be False.""",
43
+ ),
44
+ )
45
+ CONFIG.declare(
46
+ "has_holdup",
47
+ ConfigValue(
48
+ default=False,
49
+ domain=In([False]),
50
+ description="Holdup construction flag - must be False",
51
+ doc="""Indicates whether holdup terms should be constructed or not.
52
+ **default** - False. The Transformer unit does not have defined volume, thus
53
+ this must be False.""",
54
+ ),
55
+ )
56
+ CONFIG.declare(
57
+ "property_package",
58
+ ConfigValue(
59
+ default=useDefault,
60
+ domain=is_physical_parameter_block,
61
+ description="Property package to use for control volume",
62
+ doc="""Property parameter object used to define property calculations,
63
+ **default** - useDefault.
64
+ **Valid values:** {
65
+ **useDefault** - use default package from parent model or flowsheet,
66
+ **PhysicalParameterObject** - a PhysicalParameterBlock object.}""",
67
+ ),
68
+ )
69
+ CONFIG.declare(
70
+ "property_package_args",
71
+ ConfigBlock(
72
+ implicit=True,
73
+ description="Arguments to use for constructing property packages",
74
+ doc="""A ConfigBlock with arguments to be passed to a property block(s)
75
+ and used when constructing these,
76
+ **default** - None.
77
+ **Valid values:** {
78
+ see property package for documentation.}""",
79
+ ),
80
+ )
81
+
82
+ def build(self):
83
+ # build always starts by calling super().build()
84
+ # This triggers a lot of boilerplate in the background for you
85
+ super().build()
86
+
87
+ # This creates blank scaling factors, which are populated later
88
+ self.scaling_factor = Suffix(direction=Suffix.EXPORT)
89
+
90
+
91
+ # Add state blocks for inlet, outlet, and waste
92
+ # These include the state variables and any other properties on demand
93
+ # Add inlet block
94
+ tmp_dict = dict(**self.config.property_package_args)
95
+ tmp_dict["parameters"] = self.config.property_package
96
+ tmp_dict["defined_state"] = True # inlet block is an inlet
97
+ self.properties_in = self.config.property_package.state_block_class(
98
+ self.flowsheet().config.time, doc="Material properties of inlet", **tmp_dict
99
+ )
100
+ # Add outlet and waste block
101
+ tmp_dict["defined_state"] = False # outlet and waste block is not an inlet
102
+ self.properties_out = self.config.property_package.state_block_class(
103
+ self.flowsheet().config.time,
104
+ doc="Material properties of outlet",
105
+ **tmp_dict
106
+ )
107
+
108
+ # Add ports - oftentimes users interact with these rather than the state blocks
109
+ self.add_port(name="inlet", block=self.properties_in)
110
+ self.add_port(name="outlet", block=self.properties_out)
111
+
112
+ # # Add variable for turns_ratio
113
+ # self.turns_ratio = Var(self.flowsheet().config.time,
114
+ # initialize=1.0,
115
+ # doc="Turns Ratio of the Transformer",
116
+ # )
117
+ # # Add variable for Load Resistance
118
+ # self.resistance = Var(self.flowsheet().config.time,
119
+ # initialize=1.0,
120
+ # doc="Load Resistance of the Transformer",
121
+ # )
122
+ self.n_capacity = Var(
123
+ self.flowsheet().config.time,
124
+ initialize=1.0,
125
+ units = pyunits.W,
126
+ doc="N Capacity of the Transformer",
127
+ )
128
+ self.voltage = Var(self.flowsheet().config.time,
129
+ initialize=1.0,
130
+ units = pyunits.V,
131
+ doc="Voltage Capacity of the Transformer",
132
+ )
133
+ self.efficiency = Var(self.flowsheet().config.time,
134
+ initialize=1.0,
135
+ units = pyunits.dimensionless,
136
+ doc="Efficiency of the Transformer",
137
+ )
138
+
139
+
140
+ # Add constraints
141
+ @self.Constraint(
142
+ self.flowsheet().time,
143
+ doc = "Power out",
144
+ )
145
+ def power_out(b, t):
146
+ return (
147
+ self.properties_out[t].power
148
+ == self.properties_in[t].power * self.efficiency[t]
149
+ )
150
+
151
+ @self.Constraint(
152
+ self.flowsheet().time,
153
+ doc = "Capacity check",
154
+ )
155
+ def capacity_check(b,t):
156
+ return abs(self.properties_in[t].power) <= self.n_capacity[t]
157
+
158
+ # @self.Constraint(
159
+ # self.flowsheet().time,
160
+ # doc="Voltage out",
161
+ # )
162
+ # def voltage_out(b, t):
163
+ # return (
164
+ # b.properties_in[t].voltage * self.turns_ratio[t] == self.properties_out[t].voltage
165
+ # )
166
+ # @self.Constraint(
167
+ # self.flowsheet().time,
168
+ # doc="Current out",
169
+ # )
170
+ # def current_out(b,t):
171
+ # return(
172
+ # self.properties_out[t].voltage / self.resistance[t] == self.properties_out[t].current
173
+ # )
174
+
175
+ def calculate_scaling_factors(self):
176
+ super().calculate_scaling_factors()
177
+
178
+ def initialize(blk, *args, **kwargs):
179
+ # Just propagate the power from inlet to outlet, good simple method of initialization
180
+ for i in blk.properties_in.index_set():
181
+ if not blk.properties_out[i].power.fixed:
182
+ blk.properties_out[i].power = blk.properties_in[i].power.value
183
+
184
+ if abs(blk.properties_in[i].power.value) > blk.n_capacity[i].value:
185
+ raise ConfigurationError(
186
+ "Danger: Input power exceeds transformer capacity. Please either increase capacity or lower input power."
187
+ )