@@ -125,28 +125,36 @@ def map_rate_fractions(
125125
126126
127127def validate_increasing_pressure (
128- suction_pressure : list [ float ] ,
129- discharge_pressure : list [ float ] ,
130- intermediate_pressure : list [ float ] | None = None ,
128+ suction_pressure : ExpressionTimeSeriesPressure ,
129+ discharge_pressure : ExpressionTimeSeriesPressure ,
130+ intermediate_pressure : ExpressionTimeSeriesPressure | None = None ,
131131):
132- # TODO: Currently all pressures must be non-negative, meaning that we allow zero pressures. This also means that we
133- # allow zero discharge pressure, which is not physically meaningful in most cases. The compressor does no work.
134- # In the future we want to only allow positive pressures, and then we can tighten this validation to require
135- # strictly increasing pressures (i.e. suction < discharge, and suction < intermediate < discharge).
136- for i in range (len (suction_pressure )):
137- sp = suction_pressure [i ]
138- dp = discharge_pressure [i ]
139- if intermediate_pressure :
140- ip = intermediate_pressure [i ]
141- if not (sp <= ip <= dp ):
142- raise ProcessPressureRatioValidationException (
143- message = f"Invalid pressures at index { i + 1 } : suction pressure ({ sp } ) must be less than intermediate pressure ({ ip } ), which must be less than discharge pressure ({ dp } )."
144- )
145- else :
146- if not (sp <= dp ):
147- raise ProcessPressureRatioValidationException (
148- message = f"Invalid pressures at index { i + 1 } : suction pressure ({ sp } ) must be less than discharge pressure ({ dp } )."
149- )
132+ validation_mask = suction_pressure .get_validation_mask ()
133+ assert validation_mask == discharge_pressure .get_validation_mask ()
134+ suction_pressure_values = suction_pressure .get_values ()
135+ discharge_pressure_values = discharge_pressure .get_values ()
136+
137+ if intermediate_pressure is not None :
138+ assert validation_mask == intermediate_pressure .get_validation_mask ()
139+ intermediate_pressure_values = intermediate_pressure .get_values ()
140+ else :
141+ intermediate_pressure_values = None
142+
143+ for i in range (len (suction_pressure_values )):
144+ if validation_mask [i ]:
145+ sp = suction_pressure_values [i ]
146+ dp = discharge_pressure_values [i ]
147+ if intermediate_pressure_values is not None :
148+ ip = intermediate_pressure_values [i ]
149+ if not (sp <= ip <= dp ):
150+ raise ProcessPressureRatioValidationException (
151+ message = f"Invalid pressures at index { i + 1 } : suction pressure ({ sp } ) must be less than intermediate pressure ({ ip } ), which must be less than discharge pressure ({ dp } )."
152+ )
153+ else :
154+ if not (sp <= dp ):
155+ raise ProcessPressureRatioValidationException (
156+ message = f"Invalid pressures at index { i + 1 } : suction pressure ({ sp } ) must be less than discharge pressure ({ dp } )."
157+ )
150158
151159
152160class ConsumerFunctionMapper :
@@ -289,19 +297,31 @@ def _map_pump(
289297 )
290298 fluid_density = ExpressionTimeSeriesFluidDensity (time_series_expression = fluid_density_expression )
291299
300+ pressure_validation_mask = [
301+ bool (_rate * _regularity > 0 )
302+ for _rate , _regularity in zip (rate_standard_m3_day .get_stream_day_values (), period_regularity .values )
303+ if _rate is not None
304+ ]
305+
292306 suction_pressure_expression = TimeSeriesExpression (
293307 expression = model .suction_pressure , expression_evaluator = period_evaluator
294308 )
295- suction_pressure = ExpressionTimeSeriesPressure (time_series_expression = suction_pressure_expression )
309+ suction_pressure = ExpressionTimeSeriesPressure (
310+ time_series_expression = suction_pressure_expression ,
311+ validation_mask = pressure_validation_mask ,
312+ )
296313
297314 discharge_pressure_expression = TimeSeriesExpression (
298315 expression = model .discharge_pressure , expression_evaluator = period_evaluator
299316 )
300- discharge_pressure = ExpressionTimeSeriesPressure (time_series_expression = discharge_pressure_expression )
317+ discharge_pressure = ExpressionTimeSeriesPressure (
318+ time_series_expression = discharge_pressure_expression ,
319+ validation_mask = pressure_validation_mask ,
320+ )
301321
302322 validate_increasing_pressure (
303- suction_pressure = suction_pressure . get_values () ,
304- discharge_pressure = discharge_pressure . get_values () ,
323+ suction_pressure = suction_pressure ,
324+ discharge_pressure = discharge_pressure ,
305325 )
306326
307327 return PumpConsumerFunction (
@@ -333,42 +353,52 @@ def _map_multiple_streams_compressor(
333353 if model .power_loss_factor is not None
334354 else None
335355 )
356+
357+ rates_per_stream : list [TimeSeriesFlowRate ] = [
358+ ExpressionTimeSeriesFlowRate (
359+ time_series_expression = TimeSeriesExpression (
360+ rate_expression , expression_evaluator = expression_evaluator , condition = _map_condition (model )
361+ ),
362+ regularity = regularity ,
363+ consumption_rate_type = RateType .CALENDAR_DAY ,
364+ )
365+ for rate_expression in model .rate_per_stream
366+ ]
367+
368+ rates_per_stream_values = [rates .get_stream_day_values () for rates in rates_per_stream ]
369+ sum_of_rates = [sum (values ) for values in zip (* rates_per_stream_values )]
370+
371+ validation_mask = [bool (_rate * _regularity > 0 ) for _rate , _regularity in zip (sum_of_rates , regularity .values )]
372+
336373 suction_pressure = ExpressionTimeSeriesPressure (
337374 time_series_expression = TimeSeriesExpression (
338375 model .suction_pressure , expression_evaluator = expression_evaluator
339- )
376+ ),
377+ validation_mask = validation_mask ,
340378 )
341379 discharge_pressure = ExpressionTimeSeriesPressure (
342380 time_series_expression = TimeSeriesExpression (
343381 model .discharge_pressure , expression_evaluator = expression_evaluator
344- )
382+ ),
383+ validation_mask = validation_mask ,
345384 )
346385 interstage_control_pressure = (
347386 ExpressionTimeSeriesPressure (
348387 time_series_expression = TimeSeriesExpression (
349388 model .interstage_control_pressure , expression_evaluator = expression_evaluator
350- )
389+ ),
390+ validation_mask = validation_mask ,
351391 )
352392 if model .interstage_control_pressure is not None
353393 else None
354394 )
355395
356396 validate_increasing_pressure (
357- suction_pressure = suction_pressure . get_values () ,
358- discharge_pressure = discharge_pressure . get_values () ,
359- intermediate_pressure = interstage_control_pressure . get_values () ,
397+ suction_pressure = suction_pressure ,
398+ discharge_pressure = discharge_pressure ,
399+ intermediate_pressure = interstage_control_pressure ,
360400 )
361401
362- rates_per_stream : list [TimeSeriesFlowRate ] = [
363- ExpressionTimeSeriesFlowRate (
364- time_series_expression = TimeSeriesExpression (
365- rate_expression , expression_evaluator = expression_evaluator , condition = _map_condition (model )
366- ),
367- regularity = regularity ,
368- consumption_rate_type = RateType .CALENDAR_DAY ,
369- )
370- for rate_expression in model .rate_per_stream
371- ]
372402 return CompressorConsumerFunction (
373403 power_loss_factor_expression = power_loss_factor ,
374404 compressor_function = compressor_train_model ,
@@ -402,20 +432,36 @@ def _map_compressor(
402432 else None
403433 )
404434
435+ stream_day_rate = ExpressionTimeSeriesFlowRate (
436+ time_series_expression = TimeSeriesExpression (
437+ model .rate , expression_evaluator = expression_evaluator , condition = _map_condition (model )
438+ ),
439+ consumption_rate_type = RateType .CALENDAR_DAY ,
440+ regularity = regularity ,
441+ )
442+
443+ validation_mask = [
444+ bool (_rate * _regularity > 0 )
445+ for _rate , _regularity in zip (stream_day_rate .get_stream_day_values (), regularity .values )
446+ if _rate is not None
447+ ]
405448 suction_pressure = (
406449 ExpressionTimeSeriesPressure (
407450 time_series_expression = TimeSeriesExpression (
408451 model .suction_pressure , expression_evaluator = expression_evaluator
409- )
452+ ),
453+ validation_mask = validation_mask ,
410454 )
411455 if model .suction_pressure
412456 else None
413457 )
458+
414459 discharge_pressure = (
415460 ExpressionTimeSeriesPressure (
416461 time_series_expression = TimeSeriesExpression (
417462 model .discharge_pressure , expression_evaluator = expression_evaluator
418- )
463+ ),
464+ validation_mask = validation_mask ,
419465 )
420466 if model .discharge_pressure
421467 else None
@@ -425,20 +471,14 @@ def _map_compressor(
425471 suction_pressure is not None and discharge_pressure is not None
426472 ): # to handle compressor sampled which may not have pressures
427473 validate_increasing_pressure (
428- suction_pressure = suction_pressure . get_values () ,
429- discharge_pressure = discharge_pressure . get_values () ,
474+ suction_pressure = suction_pressure ,
475+ discharge_pressure = discharge_pressure ,
430476 )
431477
432478 return CompressorConsumerFunction (
433479 power_loss_factor_expression = power_loss_factor ,
434480 compressor_function = compressor_model ,
435- rate_expression = ExpressionTimeSeriesFlowRate (
436- time_series_expression = TimeSeriesExpression (
437- model .rate , expression_evaluator = expression_evaluator , condition = _map_condition (model )
438- ),
439- consumption_rate_type = RateType .CALENDAR_DAY ,
440- regularity = regularity ,
441- ),
481+ rate_expression = stream_day_rate ,
442482 suction_pressure_expression = suction_pressure ,
443483 discharge_pressure_expression = discharge_pressure ,
444484 intermediate_pressure_expression = None ,
@@ -510,25 +550,39 @@ def _map_compressor_system(
510550 for rate_expr in operational_setting .rates
511551 ]
512552
513- number_of_compressors = len (compressors )
553+ validation_mask = [
554+ [
555+ bool (_rate * _regularity > 0 )
556+ for _rate , _regularity in zip (rate .get_stream_day_values (), regularity .values )
557+ if _rate is not None
558+ ]
559+ for rate in rates
560+ ]
514561
515562 if operational_setting .suction_pressure is not None :
516563 suction_pressures = [
517564 ExpressionTimeSeriesPressure (
518565 time_series_expression = TimeSeriesExpression (
519- expression = operational_setting .suction_pressure , expression_evaluator = expression_evaluator
520- )
566+ expression = operational_setting .suction_pressure ,
567+ expression_evaluator = expression_evaluator ,
568+ ),
569+ validation_mask = mask ,
521570 )
522- ] * number_of_compressors
571+ for mask in validation_mask
572+ ]
523573 else :
524574 assert operational_setting .suction_pressures is not None
525575 suction_pressures = [
526576 ExpressionTimeSeriesPressure (
527577 time_series_expression = TimeSeriesExpression (
528578 expression = pressure_expr , expression_evaluator = expression_evaluator
529- )
579+ ),
580+ validation_mask = mask ,
581+ )
582+ for pressure_expr , mask in zip (
583+ operational_setting .suction_pressures ,
584+ validation_mask ,
530585 )
531- for pressure_expr in operational_setting .suction_pressures
532586 ]
533587
534588 if operational_setting .discharge_pressure is not None :
@@ -537,24 +591,30 @@ def _map_compressor_system(
537591 time_series_expression = TimeSeriesExpression (
538592 expression = operational_setting .discharge_pressure ,
539593 expression_evaluator = expression_evaluator ,
540- )
594+ ),
595+ validation_mask = mask ,
541596 )
542- ] * number_of_compressors
597+ for mask in validation_mask
598+ ]
543599 else :
544600 assert operational_setting .discharge_pressures is not None
545601 discharge_pressures = [
546602 ExpressionTimeSeriesPressure (
547603 time_series_expression = TimeSeriesExpression (
548604 expression = pressure_expr , expression_evaluator = expression_evaluator
549- )
605+ ),
606+ validation_mask = mask ,
607+ )
608+ for pressure_expr , mask in zip (
609+ operational_setting .discharge_pressures ,
610+ validation_mask ,
550611 )
551- for pressure_expr in operational_setting .discharge_pressures
552612 ]
553613
554614 for suction_pressure , discharge_pressure in zip (suction_pressures , discharge_pressures ):
555615 validate_increasing_pressure (
556- suction_pressure = suction_pressure . get_values () ,
557- discharge_pressure = discharge_pressure . get_values () ,
616+ suction_pressure = suction_pressure ,
617+ discharge_pressure = discharge_pressure ,
558618 )
559619
560620 core_setting = CompressorSystemOperationalSettingExpressions (
@@ -683,8 +743,8 @@ def _map_pump_system(
683743
684744 for suction_pressure , discharge_pressure in zip (suction_pressures , discharge_pressures ):
685745 validate_increasing_pressure (
686- suction_pressure = suction_pressure . get_values () ,
687- discharge_pressure = discharge_pressure . get_values () ,
746+ suction_pressure = suction_pressure ,
747+ discharge_pressure = discharge_pressure ,
688748 )
689749 operational_settings .append (
690750 PumpSystemOperationalSettingExpressions (
0 commit comments