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,169 @@
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
+
19
+ from idaes.core.util.tables import create_stream_table_dataframe
20
+
21
+ from idaes.core.util.exceptions import ConfigurationError
22
+
23
+ # Set up logger
24
+ _log = idaeslog.getLogger(__name__)
25
+
26
+
27
+ # When using this file the name "Solar" is what is imported
28
+ @declare_process_block_class("Hydro")
29
+ class HydroData(UnitModelBlockData):
30
+ """
31
+ Zero order Link model
32
+ """
33
+
34
+ # CONFIG are options for the unit model, this simple model only has the mandatory config options
35
+ CONFIG = ConfigBlock()
36
+
37
+ CONFIG.declare(
38
+ "dynamic",
39
+ ConfigValue(
40
+ domain=In([False]),
41
+ default=False,
42
+ description="Dynamic model flag - must be False",
43
+ doc="""Indicates whether this model will be dynamic or not,
44
+ **default** = False. The Bus unit does not support dynamic
45
+ behavior, thus this must be False.""",
46
+ ),
47
+ )
48
+ CONFIG.declare(
49
+ "has_holdup",
50
+ ConfigValue(
51
+ default=False,
52
+ domain=In([False]),
53
+ description="Holdup construction flag - must be False",
54
+ doc="""Indicates whether holdup terms should be constructed or not.
55
+ **default** - False. The Bus unit does not have defined volume, thus
56
+ this must be False.""",
57
+ ),
58
+ )
59
+ CONFIG.declare(
60
+ "property_package",
61
+ ConfigValue(
62
+ default=useDefault,
63
+ domain=is_physical_parameter_block,
64
+ description="Property package to use for control volume",
65
+ doc="""Property parameter object used to define property calculations,
66
+ **default** - useDefault.
67
+ **Valid values:** {
68
+ **useDefault** - use default package from parent model or flowsheet,
69
+ **PhysicalParameterObject** - a PhysicalParameterBlock object.}""",
70
+ ),
71
+ )
72
+ CONFIG.declare(
73
+ "property_package_args",
74
+ ConfigBlock(
75
+ implicit=True,
76
+ description="Arguments to use for constructing property packages",
77
+ doc="""A ConfigBlock with arguments to be passed to a property block(s)
78
+ and used when constructing these,
79
+ **default** - None.
80
+ **Valid values:** {
81
+ see property package for documentation.}""",
82
+ ),
83
+ )
84
+
85
+ def build(self):
86
+ # build always starts by calling super().build()
87
+ # This triggers a lot of boilerplate in the background for you
88
+ super().build()
89
+
90
+ # This creates blank scaling factors, which are populated later
91
+ self.scaling_factor = Suffix(direction=Suffix.EXPORT)
92
+
93
+
94
+ # Add state blocks for inlet, outlet, and waste
95
+ # These include the state variables and any other properties on demand
96
+ # Add inlet block
97
+ tmp_dict = dict(**self.config.property_package_args)
98
+ tmp_dict["parameters"] = self.config.property_package
99
+ #tmp_dict["defined_state"] = True # inlet block is an inlet
100
+
101
+ # Add outlet
102
+ tmp_dict["defined_state"] = False # outlet is not an inlet
103
+ self.properties_out = self.config.property_package.state_block_class(
104
+ self.flowsheet().config.time,
105
+ doc="Material properties of outlet",
106
+ **tmp_dict
107
+ )
108
+
109
+ # Add ports - oftentimes users interact with these rather than the state blocks
110
+
111
+ self.add_port(name="outlet", block=self.properties_out)
112
+
113
+ # Add variable for efficiency
114
+ self.efficiency = Var(
115
+ initialize=1.0,
116
+ doc="Efficiency",
117
+ )
118
+
119
+ # Add variable for flow rate of water m3/s
120
+ self.flow_rate = Var(self.flowsheet().config.time,
121
+ initialize=1.0, units = pyunits.m**3/pyunits.s,
122
+ doc="Flow rate of water",
123
+ )
124
+
125
+ # Add variable for Static Head in meters
126
+ self.static_head = Var(
127
+ initialize=1.0, units = pyunits.m,
128
+ doc="Effective Head or height of the water column",
129
+ )
130
+ # Add variable for Cp which is density of water in kg/m3
131
+ self.Cp= 1000
132
+ # Add variable for Cg which is gravitational acceleration in m/s2
133
+ self.Cg= 9.81
134
+
135
+ # Add constraints
136
+ @self.Constraint(
137
+ self.flowsheet().time,
138
+ doc="Power usage",
139
+ )
140
+
141
+ def eq_power_balance(b, t):
142
+ return (
143
+ (self.flow_rate[t] * self.Cg * self.Cp * self.efficiency * self.static_head == b.properties_out[t].power)
144
+ )
145
+
146
+
147
+ def calculate_scaling_factors(self):
148
+ super().calculate_scaling_factors()
149
+
150
+ def initialize(blk, *args, **kwargs):
151
+ # Just propagate the power from inlet to outlet, good simple method of initialization
152
+ pass
153
+
154
+ def _get_stream_table_contents(self, time_point=0):
155
+ """
156
+ Assume unit has standard configuration of 1 inlet and 1 outlet.
157
+
158
+ Developers should overload this as appropriate.
159
+ """
160
+ try:
161
+ return create_stream_table_dataframe(
162
+ {"Outlet": self.outlet}, time_point=time_point
163
+ )
164
+ except AttributeError:
165
+ raise ConfigurationError(
166
+ f"Unit model {self.name} does not have the standard Port "
167
+ f"names (inlet and outlet). Please contact the unit model "
168
+ f"developer to develop a unit specific stream table."
169
+ )
@@ -0,0 +1,137 @@
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
+
19
+ # Set up logger
20
+ _log = idaeslog.getLogger(__name__)
21
+
22
+
23
+ # When using this file the name "Link" is what is imported
24
+ @declare_process_block_class("Link")
25
+ class LinkData(UnitModelBlockData):
26
+ """
27
+ Zero order Link model
28
+ """
29
+
30
+ # CONFIG are options for the unit model, this simple model only has the mandatory config options
31
+ CONFIG = ConfigBlock()
32
+
33
+ CONFIG.declare(
34
+ "dynamic",
35
+ ConfigValue(
36
+ domain=In([False]),
37
+ default=False,
38
+ description="Dynamic model flag - must be False",
39
+ doc="""Indicates whether this model will be dynamic or not,
40
+ **default** = False. The Bus unit does not support dynamic
41
+ behavior, thus this must be False.""",
42
+ ),
43
+ )
44
+ CONFIG.declare(
45
+ "has_holdup",
46
+ ConfigValue(
47
+ default=False,
48
+ domain=In([False]),
49
+ description="Holdup construction flag - must be False",
50
+ doc="""Indicates whether holdup terms should be constructed or not.
51
+ **default** - False. The Bus unit does not have defined volume, thus
52
+ this must be False.""",
53
+ ),
54
+ )
55
+ CONFIG.declare(
56
+ "property_package",
57
+ ConfigValue(
58
+ default=useDefault,
59
+ domain=is_physical_parameter_block,
60
+ description="Property package to use for control volume",
61
+ doc="""Property parameter object used to define property calculations,
62
+ **default** - useDefault.
63
+ **Valid values:** {
64
+ **useDefault** - use default package from parent model or flowsheet,
65
+ **PhysicalParameterObject** - a PhysicalParameterBlock object.}""",
66
+ ),
67
+ )
68
+ CONFIG.declare(
69
+ "property_package_args",
70
+ ConfigBlock(
71
+ implicit=True,
72
+ description="Arguments to use for constructing property packages",
73
+ doc="""A ConfigBlock with arguments to be passed to a property block(s)
74
+ and used when constructing these,
75
+ **default** - None.
76
+ **Valid values:** {
77
+ see property package for documentation.}""",
78
+ ),
79
+ )
80
+
81
+ def build(self):
82
+ # build always starts by calling super().build()
83
+ # This triggers a lot of boilerplate in the background for you
84
+ super().build()
85
+
86
+ # This creates blank scaling factors, which are populated later
87
+ self.scaling_factor = Suffix(direction=Suffix.EXPORT)
88
+
89
+
90
+ # Add state blocks for inlet, outlet, and waste
91
+ # These include the state variables and any other properties on demand
92
+ # Add inlet block
93
+ tmp_dict = dict(**self.config.property_package_args)
94
+ tmp_dict["parameters"] = self.config.property_package
95
+ tmp_dict["defined_state"] = True # inlet block is an inlet
96
+ self.properties_in = self.config.property_package.state_block_class(
97
+ self.flowsheet().config.time, doc="Material properties of inlet", **tmp_dict
98
+ )
99
+ # Add outlet and waste block
100
+ tmp_dict["defined_state"] = False # outlet and waste block is not an inlet
101
+ self.properties_out = self.config.property_package.state_block_class(
102
+ self.flowsheet().config.time,
103
+ doc="Material properties of outlet",
104
+ **tmp_dict
105
+ )
106
+
107
+ # Add ports - oftentimes users interact with these rather than the state blocks
108
+ self.add_port(name="inlet", block=self.properties_in)
109
+ self.add_port(name="outlet", block=self.properties_out)
110
+
111
+ # Add variable for efficiency
112
+ self.efficiency = Var(self.flowsheet().config.time,
113
+ initialize=1.0,
114
+ doc="Efficiency of the bus",
115
+ )
116
+
117
+ # Add constraints
118
+ # Usually unit models use a control volume to do the mass, energy, and momentum
119
+ # balances, however, they will be explicitly written out in this example
120
+ @self.Constraint(
121
+ self.flowsheet().time,
122
+ doc="Power usage",
123
+ )
124
+ def eq_power_balance(b, t):
125
+ return (
126
+ b.properties_in[t].power * self.efficiency[t] == b.properties_out[t].power
127
+ )
128
+
129
+
130
+ def calculate_scaling_factors(self):
131
+ super().calculate_scaling_factors()
132
+
133
+ def initialize(blk, *args, **kwargs):
134
+ # Just propagate the power from inlet to outlet, good simple method of initialization
135
+ for i in blk.properties_in.index_set():
136
+ if not blk.properties_out[i].power.fixed:
137
+ blk.properties_out[i].power = blk.properties_in[i].power.value
@@ -0,0 +1,155 @@
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.tables import create_stream_table_dataframe
9
+ from idaes.core.util.exceptions import ConfigurationError
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
+
20
+ # Set up logger
21
+ _log = idaeslog.getLogger(__name__)
22
+
23
+
24
+ # When using this file the name "Load" is what is imported
25
+ @declare_process_block_class("Load")
26
+ class loadData(UnitModelBlockData):
27
+ """
28
+ Zero order Load 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 Bus 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="outlet", block=self.properties_out)
110
+
111
+ # Add variables
112
+ self.in_power = Var(self.flowsheet().config.time,
113
+ initialize=1.0,
114
+ doc="Load voltage",
115
+ units = pyunits.W
116
+ )
117
+
118
+ # Add constraints
119
+ # Usually unit models use a control volume to do the mass, energy, and momentum
120
+ # balances, however, they will be explicitly written out in this example
121
+ @self.Constraint(
122
+ self.flowsheet().time,
123
+ doc="Power usage",
124
+ )
125
+ def eq_power_in_balance(b, t):
126
+ return (
127
+ b.properties_out[t].power == self.in_power[t] * -1
128
+ )
129
+
130
+
131
+ def calculate_scaling_factors(self):
132
+ super().calculate_scaling_factors()
133
+
134
+ def initialize(blk, *args, **kwargs):
135
+ # Just propagate the power from inlet to outlet, good simple method of initialization
136
+ for i in blk.properties_in.index_set():
137
+ if not blk.properties_out[i].power.fixed:
138
+ blk.properties_out[i].power = blk.properties_in[i].power.value
139
+
140
+ def _get_stream_table_contents(self, time_point=0):
141
+ """
142
+ Assume unit has standard configuration of 1 inlet and 1 outlet.
143
+
144
+ Developers should overload this as appropriate.
145
+ """
146
+ try:
147
+ return create_stream_table_dataframe(
148
+ {"outlet": self.outlet}, time_point=time_point
149
+ )
150
+ except AttributeError:
151
+ raise ConfigurationError(
152
+ f"Unit model {self.name} does not have the standard Port "
153
+ f"names (inlet and outlet). Please contact the unit model "
154
+ f"developer to develop a unit specific stream table."
155
+ )