Coverage for backend/idaes_service/solver/custom/energy/transformer.py: 37%
43 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 pyomo.environ import (
3 Var,
4 Suffix,
5 units as pyunits,
6)
7from pyomo.common.config import ConfigBlock, ConfigValue, In
9# Import IDAES cores
10from idaes.core import (
11 declare_process_block_class,
12 UnitModelBlockData,
13 useDefault,
14)
15from idaes.core.util.config import is_physical_parameter_block
16import idaes.core.util.scaling as iscale
17import idaes.logger as idaeslog
18from idaes.core.util.exceptions import ConfigurationError
19# Set up logger
20_log = idaeslog.getLogger(__name__)
24# When using this file the name "Transformer" is what is imported
25@declare_process_block_class("Transformer")
26class TransformerData(UnitModelBlockData):
27 """
28 Zero order Transformer model
29 """
31 # CONFIG are options for the unit model, this simple model only has the mandatory config options
32 CONFIG = ConfigBlock()
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 )
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()
87 # This creates blank scaling factors, which are populated later
88 self.scaling_factor = Suffix(direction=Suffix.EXPORT)
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 )
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)
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 )
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 )
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]
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 # )
175 def calculate_scaling_factors(self):
176 super().calculate_scaling_factors()
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
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 )