Source code for OpenPinch.analysis.heat_pumps.targeting.cascade_carnot

"""Cascade Carnot HP targeting."""

import numpy as np

from ....contracts.hpr import HeatPumpTargetInputs, HPRBackendResult, HPRParsedState
from ..common._shared.streams import get_Q_vals_at_T_hpr_from_bckgrd_profile
from ..common.encoding import (
    AMBIENT_X_BOUNDS,
    encode_duty_splits,
    map_x_arr_to_T_arr,
    map_x_to_Q_amb,
)
from ..common.layout import HPRoptVectorLayout
from ..common.shared import (
    evaluate_carnot_hpr_result,
)
from ..cycles.carnot_cycles import CascadeCarnotCycle
from ..optimisation_adapter import solve_hpr_placement

__all__ = [
    "optimise_cascade_carnot_heat_pump_placement",
]


################################################################################
# Public API
################################################################################


[docs] def optimise_cascade_carnot_heat_pump_placement( args: HeatPumpTargetInputs, ) -> HPRBackendResult: """Optimise cascade Carnot stages for the prepared HPR case.""" x0_ls, bnds = _get_cascade_carnot_hp_opt_setup(args) return solve_hpr_placement( f_obj=_compute_cascade_carnot_cycle_obj, x0_ls=x0_ls, bnds=bnds, args=args, )
################################################################################ # Helper Functions ################################################################################ def _get_cascade_carnot_hp_opt_setup( args: HeatPumpTargetInputs, ) -> tuple[np.ndarray, list]: n_cond = int(args.n_cond) layout = HPRoptVectorLayout( n_cond=n_cond, n_evap=int(args.n_evap), n_heat_base=1, n_heat_split=n_cond, ) x_heat_split = encode_duty_splits( np.full(n_cond, 1.0 / max(n_cond, 1)), 1.0, ) return layout.pack( x_amb=0.0, x_cond=[0.0] * layout.n_cond, x_evap=[0.0] * layout.n_evap, x_heat_base=[1.0], x_heat_split=x_heat_split, ), layout.build_bounds( x_amb=AMBIENT_X_BOUNDS, x_cond=(0.0, 1.0), x_evap=(0.0, 1.0), x_heat_base=(0.0, 1.0), x_heat_split=(0.0, 1.0), ) def _parse_cascade_carnot_cycle_state_variables( x: np.ndarray, args: HeatPumpTargetInputs, ) -> HPRParsedState: parts = HPRoptVectorLayout( n_cond=args.n_cond, n_evap=args.n_evap, n_heat_base=1, n_heat_split=int(args.n_cond), ).unpack(x) x_amb = parts["x_amb"] x_cond = parts["x_cond"] x_evap = parts["x_evap"] Q_amb_hot, Q_amb_cold = map_x_to_Q_amb(x_amb, max(args.Q_heat_max, args.Q_cool_max)) H_cold_with_amb = args.H_cold + args.z_amb_cold * Q_amb_cold H_hot_with_amb = args.H_hot + args.z_amb_hot * Q_amb_hot T_cond = map_x_arr_to_T_arr(x_cond, args.T_cold[0], args.T_cold[-1]) T_evap = map_x_arr_to_T_arr(x_evap, args.T_hot[-1], args.T_hot[0]) Q_heat_base = float(parts["x_heat_base"][0]) * (args.Q_heat_max + Q_amb_cold) Q_heat_available = get_Q_vals_at_T_hpr_from_bckgrd_profile( T_cond, args.T_cold, H_cold_with_amb, is_cond=True, ) Q_cool_available = get_Q_vals_at_T_hpr_from_bckgrd_profile( T_evap, args.T_hot, H_hot_with_amb, is_cond=False, ) return HPRParsedState( T_cond=T_cond, T_evap=T_evap, Q_amb_hot=Q_amb_hot, Q_amb_cold=Q_amb_cold, Q_heat_base=Q_heat_base, x_heat_split=parts["x_heat_split"], Q_heat_available=Q_heat_available, Q_cool_available=Q_cool_available, ) def _compute_cascade_carnot_cycle_obj( x: np.ndarray, args: HeatPumpTargetInputs, *, debug: bool = False, ) -> HPRBackendResult: state_vars = _parse_cascade_carnot_cycle_state_variables(x, args) if not isinstance(state_vars, HPRParsedState): state_vars = HPRParsedState.model_validate(state_vars) cycle = CascadeCarnotCycle() cycle.solve( T_cond=state_vars.T_cond, T_evap=state_vars.T_evap, Q_heat_base=state_vars.Q_heat_base, x_heat_split=state_vars.x_heat_split, Q_heat_available=state_vars.Q_heat_available, Q_cool_available=state_vars.Q_cool_available, eta_ii_hpr_carnot=args.eta_ii_hpr_carnot, eta_ii_he_carnot=args.eta_ii_he_carnot, args=args, ) return evaluate_carnot_hpr_result( args=args, state=state_vars, w_net=cycle.work, w_hpr=cycle.w_hpr, w_he=cycle.w_he, heat_recovery=cycle.heat_recovery, cop_h=cycle.COP_h, Q_cond_total=cycle.Q_cond, Q_evap_total=cycle.Q_evap, Q_cond=cycle.Q_cond - cycle.Q_cond_he, Q_evap=cycle.Q_evap - cycle.Q_evap_he, Q_cond_he=cycle.Q_cond_he, Q_evap_he=cycle.Q_evap_he, penalty_terms=cycle.penalty, debug=debug, )