Coverage for backend/idaes_service/solver/custom/custom_turbine.py: 100%

36 statements  

« 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 

8from idaes.core.util.tables import create_stream_table_dataframe 

9from idaes.core.util.exceptions import ConfigurationError 

10# Import IDAES cores 

11from idaes.core import ( 

12 declare_process_block_class, 

13 UnitModelBlockData, 

14 useDefault, 

15) 

16from idaes.core.util.config import is_physical_parameter_block 

17import idaes.core.util.scaling as iscale 

18import idaes.logger as idaeslog 

19 

20from idaes.models.unit_models.pressure_changer import ( 

21 TurbineData, 

22) 

23from idaes.core.util.exceptions import PropertyNotSupportedError, InitializationError 

24 

25 

26# Import Python libraries 

27 

28 

29# Import Pyomo libraries 

30from pyomo.environ import ( 

31 Block, 

32 value, 

33 Var, 

34 Expression, 

35 Constraint, 

36 Reference, 

37 check_optimal_termination, 

38 Reals, 

39) 

40from pyomo.common.config import ConfigBlock, ConfigValue, In, Bool 

41from idaes.core.solvers import get_solver 

42from .thermal_utility_systems.willans_turbine import TurbineBaseData 

43from .inverted import add_inverted, initialise_inverted 

44 

45 

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

47@declare_process_block_class("CustomTurbine") 

48class CustomTurbineData(TurbineBaseData): 

49 """ 

50 Zero order Load model 

51 """ 

52 

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

54 CONFIG = TurbineBaseData.CONFIG() 

55 

56 CONFIG.declare( 

57 "power_property_package", 

58 ConfigValue( 

59 default=useDefault, 

60 domain=is_physical_parameter_block, 

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

62 doc="""Power Property parameter object used to define power 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 "power_property_package_args", 

71 ConfigBlock( 

72 implicit=True, 

73 description="Arguments to use for constructing power 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 

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 # Add inlet block 

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

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

100 # ) 

101 

102 

103 # Add outlet and waste block 

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

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

106 self.flowsheet().config.time, 

107 doc="Material properties of outlet", 

108 **tmp_dict 

109 ) 

110 

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

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

113 

114 # Add constraints 

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

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

117 @self.Constraint( 

118 self.flowsheet().time, 

119 doc="Power out", 

120 ) 

121 def eq_power_out(b, t): 

122 return ( 

123 self.power_properties_out[t].power == self.work_electrical[t] * -1 

124 ) 

125 

126 # Add inverted deltaP property 

127 add_inverted(self, "deltaP") 

128 

129 def initialize_build(self, *args, **kwargs): 

130 initialise_inverted(self, "deltaP") 

131 

132 super().initialize_build(*args, **kwargs)