@@ -142,6 +142,22 @@ def evaluate_given_constraints(
142142 self ,
143143 constraints : CompressorTrainEvaluationInput ,
144144 fixed_speed : float | None = None , # TODO: not used?
145+ ) -> CompressorTrainResultSingleTimeStep :
146+ try :
147+ return self ._evaluate_given_constraints_impl (constraints = constraints , fixed_speed = fixed_speed )
148+ except IllegalStateException as exc :
149+ # Unrecoverable EOS / flash failure bubbled up — mark this timestep
150+ # NOT_CALCULATED rather than crash the whole timeseries.
151+ logger .warning (
152+ "Compressor train evaluation failed for a timestep and was treated as NOT_CALCULATED: %s" ,
153+ exc ,
154+ )
155+ return CompressorTrainResultSingleTimeStep .create_empty (number_of_stages = len (self .stages ))
156+
157+ def _evaluate_given_constraints_impl (
158+ self ,
159+ constraints : CompressorTrainEvaluationInput ,
160+ fixed_speed : float | None = None ,
145161 ) -> CompressorTrainResultSingleTimeStep :
146162 self .reset_rate_modifiers ()
147163 self ._validate_nonnegative_stage_rates (constraints )
@@ -1127,12 +1143,43 @@ def find_fixed_shaft_speed_given_constraints(
11271143
11281144 def _calculate_compressor_train (_speed : float ) -> CompressorTrainResultSingleTimeStep :
11291145 self .shaft .set_speed (_speed )
1130- return self .calculate_compressor_train (
1131- constraints = constraints ,
1132- )
1146+ try :
1147+ return self .calculate_compressor_train (
1148+ constraints = constraints ,
1149+ )
1150+ except IllegalStateException as exc :
1151+ # EOS / fluid layer rejected this speed — surface as infeasible
1152+ # so the speed solver treats it like an out-of-capacity probe
1153+ # and tries something else.
1154+ logger .warning (
1155+ "Compressor speed %.1f produced an infeasible state and will be treated "
1156+ "as out-of-capacity (%s). The shaft-speed solver will try a different proposal." ,
1157+ _speed ,
1158+ exc ,
1159+ )
1160+ return CompressorTrainResultSingleTimeStep .create_infeasible (number_of_stages = len (self .stages ))
11331161
11341162 train_result_for_maximum_speed = _calculate_compressor_train (_speed = maximum_speed )
11351163
1164+ # If the EOS rejected the max-speed probe (chart_area_flag NOT_CALCULATED
1165+ # rather than a real capacity flag), bisect down to find the highest
1166+ # speed we can actually evaluate at and continue the normal speed search
1167+ # from there.
1168+ max_speed_eos_failed = (
1169+ not train_result_for_maximum_speed .within_capacity
1170+ and len (train_result_for_maximum_speed .stage_results ) > 0
1171+ and train_result_for_maximum_speed .stage_results [0 ].chart_area_flag == ChartAreaFlag .NOT_CALCULATED
1172+ )
1173+ if max_speed_eos_failed :
1174+ feasible_max_speed = maximize_x_given_boolean_condition_function (
1175+ x_min = minimum_speed ,
1176+ x_max = maximum_speed ,
1177+ bool_func = lambda s : _calculate_compressor_train (_speed = s ).within_capacity ,
1178+ )
1179+ if feasible_max_speed > minimum_speed :
1180+ maximum_speed = feasible_max_speed
1181+ train_result_for_maximum_speed = _calculate_compressor_train (_speed = maximum_speed )
1182+
11361183 if not train_result_for_maximum_speed .within_capacity :
11371184 # will not find valid result - the rate is above maximum rate, return invalid results at maximum speed
11381185 self .shaft .set_speed (maximum_speed )
0 commit comments