Coverage for backend/idaes_service/solver/custom/translator.py: 87%

41 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 

10from idaes.models.unit_models.translator import TranslatorData 

11# Import IDAES cores 

12from idaes.core import ( 

13 declare_process_block_class, 

14 UnitModelBlockData, 

15 useDefault, 

16) 

17from idaes.core.util.config import is_physical_parameter_block 

18import idaes.core.util.scaling as iscale 

19import idaes.logger as idaeslog 

20from enum import Enum 

21 

22# Set up logger 

23_log = idaeslog.getLogger(__name__) 

24 

25class TranslatorType(Enum): 

26 """ 

27 Enum of supported translator types. This allows you to change what variables are translated across. 

28 """ 

29 pressure_enthalpy = "pressure_enthalpy" 

30 pressure_vapor_fraction = "pressure_vapor_fraction" 

31 pressure_temperature = "pressure_temperature" 

32 

33 

34# When using this file the name "GenericTranslator" is what is imported 

35@declare_process_block_class("GenericTranslator") 

36class GenericTranslatorData(TranslatorData): 

37 """ 

38 GenericTranslator. 

39 

40 This is used to translate between two different property packages, and supports dropping compounds that are not present. 

41 

42 For example, if you have a stream of water/milk, and it's almost all water, this allows you to translate the stream to a water-only stream. 

43 

44 It works by fixing the temperature and pressure, and flow of each component in the outlet stream to be the same as the inlet stream. 

45  

46 """ 

47 CONFIG = TranslatorData.CONFIG() 

48 

49 CONFIG.declare( 

50 "translator_type", 

51 ConfigValue( 

52 default=TranslatorType.pressure_enthalpy.value, 

53 description="Translator type to use for translating properties", 

54 doc=""" 

55 Depending on the property packages you are using and the phases that are present, it may make sense to use different translators. 

56 This allows you to select what variables are translated across. 

57 """, 

58 ), 

59 ) 

60 

61 

62 def build(self): 

63 self.CONFIG.outlet_state_defined = False # See constraint for flow 

64 #self.CONFIG.has_phase_equilibrium = True # I don't think it matters if this is set, becuase in theory the phase equilibrium should 

65 # already have been calculated in the inlet stream. 

66 super().build() 

67 

68 # Pressure (= inlet pressure) 

69 @self.Constraint( 

70 self.flowsheet().time, 

71 doc="Pressure balance", 

72 ) 

73 def eq_outlet_pressure(b, t): 

74 return b.properties_in[t].pressure == b.properties_out[t].pressure 

75 

76 # Flow 

77 @self.Constraint( 

78 self.flowsheet().time, 

79 self.config.outlet_property_package.component_list, 

80 doc="Mass balance for the outlet", 

81 ) 

82 def eq_outlet_composition(b, t, c): 

83 return 0 == sum( 

84 b.properties_out[t].get_material_flow_terms(p, c) 

85 - b.properties_in[t].get_material_flow_terms(p, c) 

86 for p in b.properties_out[t].phase_list 

87 if (p, c) in b.properties_out[t].phase_component_set 

88 ) 

89 

90 if self.config.translator_type == TranslatorType.pressure_enthalpy.value: 

91 # Enthalpy (= inlet enthalpy) 

92 @self.Constraint( 

93 self.flowsheet().time, 

94 doc="Enthalpy balance", 

95 ) 

96 def eq_outlet_enth_mol(b, t): 

97 return ( 

98 b.properties_in[t].enth_mol == b.properties_out[t].enth_mol 

99 ) 

100 elif self.config.translator_type == TranslatorType.pressure_vapor_fraction.value: 100 ↛ 105line 100 didn't jump to line 105 because the condition on line 100 was never true

101 # Vapor fraction (= inlet vapor fraction) 

102 # TODO: We might be able to make this smoother, by extending the vapor fraction 

103 # below 0 and above 1 to make solving more reliable. See 

104 # https://github.com/waikato-ahuora-smart-energy-systems/PropertyPackages/blob/8c6ee67b9d028ba0fdd1c937d9dcda821595b7d1/property_packages/helmholtz/helmholtz_extended.py#L104 

105 @self.Constraint( 

106 self.flowsheet().time, 

107 doc="Vapor fraction balance", 

108 ) 

109 def eq_outlet_vapor_frac(b, t): 

110 return ( 

111 b.properties_in[t].vapor_frac == b.properties_out[t].vapor_frac 

112 ) 

113 elif self.config.translator_type == TranslatorType.pressure_temperature.value: 113 ↛ 124line 113 didn't jump to line 124 because the condition on line 113 was always true

114 # Temperature (= inlet temperature) 

115 @self.Constraint( 

116 self.flowsheet().time, 

117 doc="Temperature balance", 

118 ) 

119 def eq_outlet_temperature(b, t): 

120 return ( 

121 b.properties_in[t].temperature == b.properties_out[t].temperature 

122 ) 

123 else: 

124 raise ConfigurationError( 

125 f"Translator type {self.CONFIG.translator_type} is not supported." 

126 ) 

127 

128 

129