Coverage for backend/idaes_service/solver/custom/energy/transmissionLine.py: 60%
58 statements
« prev ^ index » next coverage.py v7.10.7, created at 2025-11-06 23:27 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2025-11-06 23:27 +0000
1# Import Pyomo libraries
2from stringprep import in_table_a1
3from pyomo import environ
4from pyomo.environ import (
5 Constraint,
6 Set,
7 Var,
8 Suffix,
9 units as pyunits,
10 atan
11)
12from pyomo.environ import Reals
13from pyomo.common.config import ConfigBlock, ConfigValue, In
14from pyomo.contrib.fbbt import interval
15from idaes.core.util.model_statistics import degrees_of_freedom
16# Import IDAES cores
17from idaes.core import (
18 declare_process_block_class,
19 UnitModelBlockData,
20 useDefault,
21 MaterialBalanceType,
22 MaterialFlowBasis,
23)
24from idaes.core.util.config import is_physical_parameter_block
25import idaes.core.util.scaling as iscale
26import idaes.logger as idaeslog
27from idaes.models.unit_models import separator
28from idaes.core.util.tables import create_stream_table_dataframe
29from idaes.core.util.exceptions import ConfigurationError, BurntToast, PropertyNotSupportedError
31from idaes.models.unit_models import separator
32#Import enum
33from enum import Enum
35# Set up logger
36_log = idaeslog.getLogger(__name__)
38import math
39# Enumerate options for balances
40class SplittingType(Enum):
41 """
42 Enum of supported material split types.
43 """
45 totalFlow = 1
46 phaseFlow = 2
47 componentFlow = 3
48 phaseComponentFlow = 4
52# When using this file the name "transmissionLine" is what is imported
53@declare_process_block_class("transmissionLine")
54class transmissionLineData(UnitModelBlockData):
55 """
56 Zero order transmission line model
57 """
59 # CONFIG are options for the unit model, this simple model only has the mandatory config options
60 CONFIG = ConfigBlock()
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 )
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()
152 # This creates blank scaling factors, which are populated later
153 self.scaling_factor = Suffix(direction=Suffix.EXPORT)
155 tmp_dict = dict(**self.config.property_package_args)
156 tmp_dict["parameters"] = self.config.property_package
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 # )
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 )
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)
187 self.power_transfer = Var(self.flowsheet().config.time,
188 initialize=1.0,
189 doc="Power transferred between busses",
190 units = pyunits.W
192 )
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]
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
211 def calculate_scaling_factors(self):
212 super().calculate_scaling_factors()
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
220 def _get_stream_table_contents(self, time_point=0):
221 """
222 Assume unit has standard configuration of 1 inlet and 1 outlet.
224 Developers should overload this as appropriate.
225 """