Coverage for backend/ahuora-builder/src/ahuora_builder/custom/custom_compressor.py: 87%

44 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2026-05-13 02:47 +0000

1# Import Pyomo libraries 

2from pyomo.environ import ( 

3 Component, 

4 Var, 

5 Suffix, 

6 units as pyunits, 

7) 

8import pyomo.environ as pyo 

9from pyomo.common.config import ConfigBlock, ConfigValue, In 

10from idaes.core.util.tables import create_stream_table_dataframe 

11from idaes.core.util.exceptions import ConfigurationError 

12# Import IDAES cores 

13from idaes.core import ( 

14 declare_process_block_class, 

15 UnitModelBlockData, 

16 useDefault, 

17) 

18from idaes.core.util.config import is_physical_parameter_block 

19import idaes.core.util.scaling as iscale 

20import idaes.logger as idaeslog 

21 

22from ..custom.updated_pressure_changer import ( 

23 

24 CompressorData, 

25) 

26 

27 

28 

29 

30# When using this file the name "CustomCompressor" is what is imported 

31@declare_process_block_class("CustomCompressor") 

32class CustomCompressorData(CompressorData): 

33 """ 

34 Zero order Load model 

35 """ 

36 

37 # CONFIG are options for the unit model, this simple model only has the mandatory config options 

38 CONFIG = CompressorData.CONFIG() 

39 

40 CONFIG.declare( 

41 "power_property_package", 

42 ConfigValue( 

43 default=useDefault, 

44 domain=is_physical_parameter_block, 

45 description="Property package to use for power", 

46 doc="""Power Property parameter object used to define power calculations, 

47 **default** - useDefault. 

48 **Valid values:** { 

49 **useDefault** - use default package from parent model or flowsheet, 

50 **PhysicalParameterObject** - a PhysicalParameterBlock object.}""", 

51 ), 

52 ) 

53 CONFIG.declare( 

54 "power_property_package_args", 

55 ConfigBlock( 

56 implicit=True, 

57 description="Arguments to use for constructing power property packages", 

58 doc="""A ConfigBlock with arguments to be passed to a property block(s) 

59 and used when constructing these, 

60 **default** - None.  

61 **Valid values:** { 

62 see property package for documentation.}""", 

63 ), 

64 ) 

65 

66 def build(self): 

67 # build always starts by calling super().build() 

68 # This triggers a lot of boilerplate in the background for you 

69 super().build() 

70 

71 # This creates blank scaling factors, which are populated later 

72 self.scaling_factor = Suffix(direction=Suffix.EXPORT) 

73 

74 

75 # Add state blocks for inlet, outlet, and waste 

76 # These include the state variables and any other properties on demand 

77 

78 tmp_dict = dict(**self.config.property_package_args) 

79 tmp_dict["parameters"] = self.config.property_package 

80 tmp_dict["defined_state"] = True # inlet block is an inlet 

81 # Add inlet block 

82 # self.properties_in = self.config.property_package.state_block_class( 

83 # self.flowsheet().config.time, doc="Material properties of inlet", **tmp_dict 

84 # ) 

85 

86 

87 # Add outlet and waste block 

88 tmp_dict["defined_state"] = False # outlet and waste block is not an inlet 

89 self.power_properties_out = self.config.power_property_package.state_block_class( 

90 self.flowsheet().config.time, 

91 doc="Material properties of outlet", 

92 **tmp_dict 

93 ) 

94 

95 # Add ports - oftentimes users interact with these rather than the state blocks 

96 self.add_port(name="power_outlet", block=self.power_properties_out) 

97 

98 # Add constraints 

99 # Usually unit models use a control volume to do the mass, energy, and momentum 

100 # balances, however, they will be explicitly written out in this example 

101 @self.Constraint( 

102 self.flowsheet().time, 

103 doc="Power out", 

104 ) 

105 def eq_power_out(b, t): 

106 return ( 

107 self.power_properties_out[t].power == self.work_mechanical[t] * -1 

108 ) 

109 

110 def diagnose(self) -> list[tuple[Component, str]]: 

111 """ 

112 Test a few common issues with the heat exchanger model and provide hints to the user. 

113 returns a list with the variable the it is most relevant to and a message describing the issue 

114 """ 

115 problems = [] 

116 inlet_vf = pyo.value(self.control_volume.properties_in[0].vapor_frac) or -1 

117 if inlet_vf < 0.9: 117 ↛ 126line 117 didn't jump to line 126 because the condition on line 117 was always true

118 problems.append( 

119 ( 

120 self.control_volume.properties_in[0].vapor_frac, 

121 f"""Inlet vapor fraction is {inlet_vf:.2f}. Compressors are typically used for gases, 

122 as liquids are incompressible. 

123 This low vapor fraction may indicate a problem with your formulation upstream.""" 

124 ) 

125 ) 

126 outlet_pressure = pyo.value(self.control_volume.properties_out[0].pressure) or 0 

127 outlet_pressure_bound = self.control_volume.properties_out[0].pressure.ub or 1e8 # 100 MPa 

128 if outlet_pressure > outlet_pressure_bound * 0.9: 128 ↛ 129line 128 didn't jump to line 129 because the condition on line 128 was never true

129 problems.append( 

130 ( 

131 self.work_mechanical, 

132 f"""Outlet pressure is {outlet_pressure:.2f} Pa, which is close to the upper bound of {outlet_pressure_bound:.2f} Pa. 

133 This may indicate that you are putting in 

134 an unreasonably large amount of work for this volume of gas""" 

135 ) 

136 ) 

137 ratioP = pyo.value(self.ratioP[0]) or 0 

138 ratioP_bound = self.ratioP[0].ub or 1e3 

139 if ratioP > ratioP_bound * 0.9: 139 ↛ 140line 139 didn't jump to line 140 because the condition on line 139 was never true

140 problems.append( 

141 ( 

142 self.work_mechanical, 

143 f"""Pressure ratio is {ratioP:.2f}, which is very high. 

144 This may indicate that you are putting in 

145 an unreasonably large amount of work for this volume of gas.""" 

146 ) 

147 ) 

148 inlet_pressure = pyo.value(self.control_volume.properties_in[0].pressure) or 0 

149 if outlet_pressure < inlet_pressure: 149 ↛ 150line 149 didn't jump to line 150 because the condition on line 149 was never true

150 problems.append( 

151 ( 

152 self.control_volume.properties_out[0].pressure, 

153 f"""Outlet pressure ({outlet_pressure:.2f} Pa) is less than inlet pressure ({inlet_pressure:.2f} Pa). 

154 Compressors should increase pressure, did you mean to use a turbine or valve instead?""" 

155 ) 

156 ) 

157 return problems 

158