Skip to content
LIBRARY

Steady-state and dynamic simulation with one model

This tutorial walks through a complete vapor-compression refrigeration cycle built from HVACComponents and run through the Dyad analysis interface. The model is the CompleteCycleFixedControls example shipped with the library — a four-component refrigerant loop (compressor → condenser → expansion valve → evaporator) coupled to moist-air streams on both heat exchangers, driven by constant compressor speed and valve position.

The refrigerant is R32, supplied through the bundled SimpleRefrigerantPropertiesLibrary backend. The moist air uses the default HVACComponents.moistair medium.

The pieces involved are:

The Dyad model

This is the full CompleteCycleFixedControls component as it lives in dyad/Examples/CompleteCycleFixedControls.dyad. Drop it into a Dyad library, compile, and the analysis at the bottom of this tutorial will run against it unchanged.

dyad
"""
Complete HVAC cycle test with moist air and fixed controls.

The test models a complete vapor compression cycle with:
- Compressor (refrigerant circuit)
- Condenser (tube-fin heat exchanger with moist air)
- Linear expansion valve (LEV)
- Evaporator (tube-fin heat exchanger with moist air)
- Fixed control inputs (compressor speed, valve position)
- Air sources and sinks for both heat exchangers
"""
component CompleteCycleFixedControls
  compressor = HVACComponents.Components.Compressor(medium_data = ref_medium_data, speed_start = compressor_speed_start, m_flow_start = ref_mdot_start, hDischarge_start = h_cond_in, hSuction_start = h_evap_out, p_a_start = P_evap_out, p_b_start = P_cond_in, dp_start = P_cond_in - P_evap_out, c_vol = [0.5017699260096695, 0.20971734265244935, -0.003471916297145014, -0.4859645588775612, -0.48736361168824505, 0.03212756255276267], c_pow = [-0.26687347217418095, 34.55656142435249, 3.2225853695000795, 0.0015410753190719896, 1.0000837990733853], Vmax = 15.0e-6, Vrel = 1.0, zFw_shell = 1.0, maxPower = 3000.0, zFw = 0.92, scP = 1e-6, scCF = 1e-1, scVdot = 1e5) {^compressor}
  compressor_speed_signal = BlockComponents.Sources.Constant(k = compressor_speed_start) {^compressor_speed_signal}
  LEV = HVACComponents.Components.LEV(medium_data = ref_medium_data, dp_small = 100.0, NTheta = 3, NThresh = 3, theta = [1e-3, 5e-5, 3e-4], thresh = [30.0, 300.0, 450.0], x_t = 10.0, use_yd0 = false, yd0 = 1.0, ZCv = 1.0, LEV_position_start = LEV_position_start, p_a_start = P_cond_out, m_flow_start = ref_mdot_start, h_in_start = h_cond_out, p_b_start = P_evap_in, h_out_start = h_evap_in) {^LEV}
  LEV_position_signal = BlockComponents.Sources.Constant(k = LEV_position_start) {^LEV_position_signal}
  condenser = HVACComponents.Components.TubeFinHEX(n_seg = nSeg, n_tube = nTube, n_flows_distributor = n_flows, ref_model_structure = HVACComponents.ModelStructure.av_vb(), ref_p_in_start = P_cond_in, ref_p_out_start = P_cond_out, ref_h_in_start = h_cond_in, ref_h_out_start = h_cond_out, ref_m_flow_start = ref_mdot_start, ref_length = ref_length, ref_diameter = ref_diameter, ref_dp_nominal = ref_dp_nominal, ref_m_flow_nominal = ref_m_flow_nominal, ref_K_dp = ref_K_dp, ref_dp_exp = ref_dp_exp, ref_alpha0 = ref_alpha0, ref_alpha_vap = ref_alpha_vap, ref_alpha_2ph = ref_alpha_2ph, ref_alpha_liq = ref_alpha_liq, ref_xdot_1 = ref_xdot_1, ref_xdot_2 = ref_xdot_2, air_p_in_start = air_p_in_start, air_p_out_start = air_p_out_start, air_T_in_start = cond_air_T_in_start, air_T_out_start = cond_air_T_out_start, air_Xi_in_start = air_Xi_in_start, air_Xi_out_start = air_Xi_out_start, air_m_flow_start = air_mdot_in, air_Q_start = 50.0, wall_T_in_start = 300.15, wall_T_out_start = 300.15, wall_cp = wall_cp, wall_m = wall_m, air_htc_nominal = air_htc_nominal, air_CF_MassTransfer = air_CF_MassTransfer, air_CF_HeatTransfer = air_CF_HeatTransfer, air_kfin = air_kfin, air_Ka = air_Ka, air_k_mair = air_k_mair, air_rho_constant = air_rho_constant, airflow_Qdot_lat_start = airflow_Qdot_lat_start, airflow_Qdot_sens_start = 50.0, airflow_xsat_w_start = airflow_xsat_w_start, airflow_eta_start = airflow_eta_start, airflow_psat_w_start = airflow_psat_w_start, airflow_psat_w_1K_start = airflow_psat_w_1K_start, airflow_xsat_w_1K_start = airflow_xsat_w_1K_start, airflow_der_xsat_w_dT_start = airflow_der_xsat_w_dT_start, airflow_mtc_start = airflow_mtc_start, airflow_dgradient_start = airflow_dgradient_start, airflow_heff_start = airflow_heff_start, airflow_h_in_start = airflow_h_in_start, airflow_h_out_start = airflow_h_out_start, airflow_mcond_flow_start = airflow_mcond_flow_start, airflow_d_mean_start = airflow_d_mean_start, airflow_Q_water_start = airflow_Q_water_start, airflow_cp_mean_start = airflow_cp_mean_start, air_A = air_A, air_d0 = air_d0, air_delta = air_delta, air_S_t = air_S_t, air_S_l = air_S_l, air_At_tube = air_At_tube, air_Af_tube = air_Af_tube, ref_medium_data = ref_medium_data, air_medium_data = air_medium_data) {^condenser}
  condAirSource = HVACComponents.Components.Sources.MassFlowSource_TPhi(medium_data = air_medium_data, T_in = cond_air_T_in_start, Phi_in = phi_cond, m_flow_in = air_mdot_in, p_start = air_p_in_start) {^condAirSource}
  condAirSink = HVACComponents.Components.Sources.Boundary_pTPhi(medium_data = air_medium_data, p_in = air_p_out_start, T_in = cond_air_T_out_start, Phi_in = phi_cond, m_flow_start = -air_mdot_in) {^condAirSink}
  evaporator = HVACComponents.Components.TubeFinHEX(n_seg = nSeg, n_tube = nTube, n_flows_distributor = n_flows, ref_model_structure = HVACComponents.ModelStructure.av_vb(), ref_p_in_start = P_evap_in, ref_p_out_start = P_evap_out, ref_h_in_start = h_evap_in, ref_h_out_start = h_evap_out, ref_m_flow_start = ref_mdot_start, ref_length = ref_length, ref_diameter = ref_diameter, ref_dp_nominal = ref_dp_nominal, ref_m_flow_nominal = ref_m_flow_nominal, ref_K_dp = ref_K_dp, ref_dp_exp = ref_dp_exp, ref_alpha0 = ref_alpha0, ref_alpha_vap = ref_alpha_vap, ref_alpha_2ph = ref_alpha_2ph, ref_alpha_liq = ref_alpha_liq, ref_xdot_1 = ref_xdot_1, ref_xdot_2 = ref_xdot_2, air_p_in_start = air_p_in_start, air_p_out_start = air_p_out_start, air_T_in_start = evap_air_T_in_start, air_T_out_start = evap_air_T_out_start, air_Xi_in_start = air_Xi_in_start, air_Xi_out_start = air_Xi_out_start, air_m_flow_start = air_mdot_in, air_Q_start = -50.0, wall_T_in_start = 297.15, wall_T_out_start = 297.15, wall_cp = wall_cp, wall_m = wall_m, air_htc_nominal = air_htc_nominal, air_CF_MassTransfer = air_CF_MassTransfer, air_CF_HeatTransfer = air_CF_HeatTransfer, air_kfin = air_kfin, air_Ka = air_Ka, air_k_mair = air_k_mair, air_rho_constant = air_rho_constant, airflow_Qdot_lat_start = airflow_Qdot_lat_start, airflow_Qdot_sens_start = -50.0, airflow_xsat_w_start = airflow_xsat_w_start, airflow_eta_start = airflow_eta_start, airflow_psat_w_start = airflow_psat_w_start, airflow_psat_w_1K_start = airflow_psat_w_1K_start, airflow_xsat_w_1K_start = airflow_xsat_w_1K_start, airflow_der_xsat_w_dT_start = airflow_der_xsat_w_dT_start, airflow_mtc_start = airflow_mtc_start, airflow_dgradient_start = airflow_dgradient_start, airflow_heff_start = airflow_heff_start, airflow_h_in_start = airflow_h_in_start, airflow_h_out_start = airflow_h_out_start, airflow_mcond_flow_start = airflow_mcond_flow_start, airflow_d_mean_start = airflow_d_mean_start, airflow_Q_water_start = airflow_Q_water_start, airflow_cp_mean_start = airflow_cp_mean_start, air_A = air_A, air_d0 = air_d0, air_delta = air_delta, air_S_t = air_S_t, air_S_l = air_S_l, air_At_tube = air_At_tube, air_Af_tube = air_Af_tube, ref_medium_data = ref_medium_data, air_medium_data = air_medium_data) {^evaporator}
  evapAirSource = HVACComponents.Components.Sources.MassFlowSource_TPhi(medium_data = air_medium_data, T_in = evap_air_T_in_start, Phi_in = phi_evap, m_flow_in = air_mdot_in, p_start = air_p_in_start) {^evapAirSource}
  evapAirSink = HVACComponents.Components.Sources.Boundary_pTPhi(medium_data = air_medium_data, p_in = air_p_out_start, T_in = evap_air_T_out_start, Phi_in = phi_evap, m_flow_start = -air_mdot_in) {^evapAirSink}
  parameter P_cond_in::Pressure = 1.6e6
  parameter P_cond_out::Pressure = 1.5e6
  parameter P_evap_in::Pressure = 1.2e6
  parameter P_evap_out::Pressure = 1.1e6
  parameter h_cond_in::SpecificEnthalpy = 320e3
  parameter h_cond_out::SpecificEnthalpy = 230e3
  parameter h_evap_in::SpecificEnthalpy = 230e3
  parameter h_evap_out::SpecificEnthalpy = 330e3
  parameter ref_mdot_start::MassFlowRate = 0.0001
  parameter T_cond::Temperature = 300.15
  parameter T_evap::Temperature = 285.15
  parameter air_mdot_in::MassFlowRate = 40.0
  parameter air_p_in_start::Pressure = 101325.0
  parameter air_p_out_start::Pressure = 101225.0
  parameter phi_cond::Real = 0.5
  parameter phi_evap::Real = 0.6
  parameter cond_air_T_in_start::Temperature = 313.15
  parameter cond_air_T_out_start::Temperature = 295.15
  parameter evap_air_T_in_start::Temperature = 310.15
  parameter evap_air_T_out_start::Temperature = 291.15
  parameter compressor_speed_start::Real = 10.0
  parameter LEV_position_start::Real = 220.0
  structural parameter nTube::Integer = 1
  structural parameter nSeg::Integer = 8
  structural parameter n_flows::Integer = 4
  parameter Lt::Real = 30.0
  parameter Di::Real = 2.54e-2
  parameter Do::Real = Di + 0.5e-3
  parameter air_A::Real = 0.1
  parameter air_d0::Real = Do
  parameter air_delta::Real = 0.0001
  parameter air_S_t::Real = 0.05
  parameter air_S_l::Real = 0.05
  parameter air_At_tube::Real = 3.14159 * Do * Lt / n_flows
  parameter air_Af_tube::Real = 0.2
  parameter ref_medium_data::HVACComponents.MediaModels.AbstractRefrigerantMedium
  parameter air_medium_data::HVACComponents.MediaModels.AbstractMoistAirMedium = HVACComponents.moistair
  parameter air_Xi_in_start::Real = 0.01
  parameter air_Xi_out_start::Real = 0.01
  parameter wall_cp::SpecificHeatCapacity = 500.0
  parameter wall_m::Mass = 1.0
  parameter air_htc_nominal::Real = 50.0
  parameter air_CF_MassTransfer::Real = 1.0
  parameter air_CF_HeatTransfer::Real = 1.0
  parameter air_kfin::Real = 237.0
  parameter air_Ka::Real = 3e-3
  parameter air_k_mair::Real = 0.62198
  parameter air_rho_constant::Real = 1.1
  parameter ref_length::Length = 10.0
  parameter ref_diameter::Length = 0.01
  parameter ref_dp_nominal::Pressure = 10e3
  parameter ref_m_flow_nominal::MassFlowRate = 0.01
  parameter ref_K_dp::Real = 1.0
  parameter ref_dp_exp::Real = 2.0
  parameter ref_alpha0::Real = 1200.0
  parameter ref_alpha_vap::Real = 500.0
  parameter ref_alpha_2ph::Real = 2000.0
  parameter ref_alpha_liq::Real = 700.0
  parameter ref_xdot_1::Real = 0.05
  parameter ref_xdot_2::Real = 0.9
  parameter airflow_Qdot_lat_start::Real = 0.0
  parameter airflow_xsat_w_start::Real = 0.01
  parameter airflow_eta_start::Real = 1.8e-5
  parameter airflow_psat_w_start::Real = 2000.0
  parameter airflow_psat_w_1K_start::Real = 1900.0
  parameter airflow_xsat_w_1K_start::Real = 0.009
  parameter airflow_der_xsat_w_dT_start::Real = 0.001
  parameter airflow_mtc_start::Real = 0.01
  parameter airflow_dgradient_start::Real = 0.0
  parameter airflow_heff_start::Real = 100.0
  parameter airflow_h_in_start::SpecificEnthalpy = 55000.0
  parameter airflow_h_out_start::SpecificEnthalpy = 37000.0
  parameter airflow_mcond_flow_start::MassFlowRate = 0.0
  parameter airflow_d_mean_start::Real = 1.15
  parameter airflow_Q_water_start::HeatFlowRate = 1e-6
  parameter airflow_cp_mean_start::Real = 1020.0
relations
  connect(compressor.port_b, condenser.refPort_a) {^id11}
  connect(condenser.refPort_b, LEV.port_a) {^id12}
  connect(LEV.port_b, evaporator.refPort_a) {^id13}
  connect(evaporator.refPort_b, compressor.port_a) {^id14}
  connect(condAirSource.port, condenser.airPort_a) {^id15}
  connect(condenser.airPort_b, condAirSink.port1) {^id16}
  connect(evapAirSource.port, evaporator.airPort_a) {^id17}
  connect(evaporator.airPort_b, evapAirSink.port1) {^id18}
  connect(compressor_speed_signal.y, compressor.input_speed) {^id19}
  connect(LEV_position_signal.y, LEV.input_position) {^id20}
  guess compressor.port_a.m_flow = ref_mdot_start
  # Condenser air distributor/merger guesses
  guess condenser.air_distributor.port_a.h_outflow = 55000.0
  guess condenser.air_distributor.port_b.h_outflow = 55000.0
  guess condenser.air_distributor.port_a.Xi_outflow = 0.01
  guess condenser.air_distributor.port_b.Xi_outflow = 0.01
  guess condenser.air_merger.port_a.h_outflow = 37000.0
  guess condenser.air_merger.port_b.h_outflow = 37000.0
  guess condenser.air_merger.port_a.Xi_outflow = 0.01
  guess condenser.air_merger.port_b.Xi_outflow = 0.01
  # Evaporator air distributor/merger guesses
  guess evaporator.air_distributor.port_a.h_outflow = 55000.0
  guess evaporator.air_distributor.port_b.h_outflow = 55000.0
  guess evaporator.air_distributor.port_a.Xi_outflow = 0.01
  guess evaporator.air_distributor.port_b.Xi_outflow = 0.01
  guess evaporator.air_merger.port_a.h_outflow = 37000.0
  guess evaporator.air_merger.port_b.h_outflow = 37000.0
  guess evaporator.air_merger.port_a.Xi_outflow = 0.01
  guess evaporator.air_merger.port_b.Xi_outflow = 0.01
metadata {
  "_links": {
    "compressor": {
      "Dyad": {
        "placement": {
          "diagram": {"iconName": "default", "x1": 970, "y1": 200, "x2": 820, "y2": 350, "rot": 0}
        },
        "tags": []
      }
    },
    "compressor_speed_signal": {
      "Dyad": {
        "placement": {
          "diagram": {"iconName": "default", "x1": 1250, "y1": 200, "x2": 1150, "y2": 300, "rot": 0}
        },
        "tags": []
      }
    },
    "LEV": {
      "Dyad": {
        "placement": {
          "diagram": {"iconName": "default", "x1": 70, "y1": 200, "x2": -30, "y2": 300, "rot": 180}
        },
        "tags": []
      }
    },
    "LEV_position_signal": {
      "Dyad": {
        "placement": {
          "diagram": {"iconName": "default", "x1": -350, "y1": 150, "x2": -250, "y2": 250, "rot": 0}
        },
        "tags": []
      }
    },
    "condenser": {
      "Dyad": {
        "placement": {
          "diagram": {"iconName": "default", "x1": 550, "y1": -100, "x2": 450, "y2": 0, "rot": 0}
        },
        "tags": []
      }
    },
    "condAirSource": {
      "Dyad": {
        "placement": {
          "diagram": {"iconName": "default", "x1": 200, "y1": 70, "x2": 300, "y2": 170, "rot": 0}
        },
        "tags": []
      }
    },
    "condAirSink": {
      "Dyad": {
        "placement": {
          "diagram": {"iconName": "default", "x1": 770, "y1": -260, "x2": 670, "y2": -160, "rot": 0}
        },
        "tags": []
      }
    },
    "evaporator": {
      "Dyad": {
        "placement": {
          "diagram": {"iconName": "default", "x1": 430, "y1": 490, "x2": 530, "y2": 590, "rot": 0}
        },
        "tags": []
      }
    },
    "evapAirSource": {
      "Dyad": {
        "placement": {
          "diagram": {"iconName": "default", "x1": 170, "y1": 660, "x2": 270, "y2": 760, "rot": 0}
        },
        "tags": []
      }
    },
    "evapAirSink": {
      "Dyad": {
        "placement": {
          "diagram": {"iconName": "default", "x1": 760, "y1": 380, "x2": 660, "y2": 480, "rot": 0}
        },
        "tags": []
      }
    },
    "id11": {
      "Dyad": {
        "edges": [{"S": 1, "M": [{"x": 895, "y": -50}], "E": 2}],
        "renderStyle": "standard"
      }
    },
    "id12": {
      "Dyad": {
        "edges": [{"S": 1, "M": [{"x": 19.999999999999993, "y": -50}], "E": 2}],
        "renderStyle": "standard"
      }
    },
    "id13": {
      "Dyad": {
        "edges": [{"S": 1, "M": [{"x": 20.000000000000007, "y": 540}], "E": 2}],
        "renderStyle": "standard"
      }
    },
    "id14": {
      "Dyad": {
        "edges": [{"S": 1, "M": [{"x": 895, "y": 540}], "E": 2}],
        "renderStyle": "standard"
      }
    },
    "id15": {
      "Dyad": {
        "edges": [{"S": 1, "M": [{"x": 500, "y": 120}], "E": 2}],
        "renderStyle": "standard"
      }
    },
    "id16": {
      "Dyad": {
        "edges": [{"S": 1, "M": [{"x": 500, "y": -210}], "E": 2}],
        "renderStyle": "standard"
      }
    },
    "id17": {
      "Dyad": {
        "edges": [{"S": 1, "M": [{"x": 480, "y": 710}], "E": 2}],
        "renderStyle": "standard"
      }
    },
    "id18": {
      "Dyad": {
        "edges": [{"S": 1, "M": [{"x": 480, "y": 430}], "E": 2}],
        "renderStyle": "standard"
      }
    },
    "id19": {
      "Dyad": {
        "edges": [{"S": 1, "M": [{"x": 1040, "y": 250}, {"x": 1040, "y": 275}], "E": 2}],
        "renderStyle": "standard"
      }
    },
    "id20": {
      "Dyad": {
        "edges": [{"S": 1, "M": [{"x": -90, "y": 200}, {"x": -90, "y": 250}], "E": 2}],
        "renderStyle": "standard"
      }
    }
  }
}
end

Diagram metadata (metadata { "_links": {...} }) has been stripped from the listing above — it controls the visual layout in the Dyad Studio canvas and is irrelevant to the physics. The real source file keeps it.

Walk-through

1. The refrigerant loop

Four sub-components form a closed loop on the refrigerant side:

  • compressor (Components.Compressor) raises the refrigerant from suction (evaporator outlet) to discharge (condenser inlet). It is modelled as a quasi-static positive-displacement machine with no internal mass or energy storage — performance is given by two polynomial maps c_vol (volumetric efficiency) and c_pow (electrical power). Vmax/Vrel set displacement and clearance fraction.

  • LEV (Components.LEV) is the linear electronic expansion valve. The theta/thresh arrays parametrise the piecewise-linear Cv(position) curve, so the same model spans a wide range of opening positions while staying differentiable for the DAE solver.

  • condenser and evaporator are both Components.TubeFinHEX instances — finned-tube heat exchangers discretised into nSeg = 4 cells per tube along the refrigerant flow path. The ref_model_structure = av_vb() selects the staggered-grid finite-volume scheme where each cell carries pressure, mean enthalpy, and momentum. Initial pressures and enthalpies for each heat exchanger are taken from the cycle-level P_cond_* / h_cond_* / P_evap_* / h_evap_* parameters.

2. The air side

Each heat exchanger has its own moist-air stream. The condenser sees outdoor air, the evaporator sees indoor air:

  • condAirSource / evapAirSource are MassFlowSource_TPhi boundary conditions that fix mass flow rate, dry-bulb temperature, and relative humidity.

  • condAirSink / evapAirSink are Boundary_pTPhi pressure boundaries that close the air stream downstream of each heat exchanger.

Air-side initialisation is driven by the cond_air_T_in_start, evap_air_T_in_start, phi_cond, phi_evap, and air_mdot_in parameters at the top of the component.

3. Control inputs

Two BlockComponents.Sources.Constant blocks supply the compressor speed (compressor_speed_signal, default 10.0) and the LEV opening position (LEV_position_signal, default 220.0). They are wired into the compressor.input_speed and LEV.input_position inputs respectively. Replacing either constant with a BlockComponents.Sources.Step or BlockComponents.Sources.Ramp is enough to turn this into a control study — no other changes needed.

4. Connections

The relations block is mostly connect equations between component ports. The refrigerant loop closes in the obvious order:

compressor.port_b → condenser.refPort_a
condenser.refPort_b → LEV.port_a
LEV.port_b → evaporator.refPort_a
evaporator.refPort_b → compressor.port_a   (back to suction)

The air side stays open-ended at each heat exchanger:

condAirSource.port → condenser.airPort_a → ... → condAirSink.port1
evapAirSource.port → evaporator.airPort_a → ... → evapAirSink.port1

5. Initial guesses

The guess statements at the bottom of relations seed the nonlinear DAE initialisation. They are not equations — they only tell the solver where to start its consistent-initialisation Newton iteration. The interesting ones are inside the heat exchangers' internal air-side splitters / mergers, which sit on stream connectors whose h_outflow and Xi_outflow guesses dominate convergence quality on cold-start.

If the user changes geometry or operating point dramatically, the guesses may need to be revised — but for the values shipped with the example, the analysis below initialises cleanly.

The analysis

The companion analysis declaration sits in the same .dyad file:

dyad
analysis CompleteCycleFixedControls_SRP_Analysis
  extends TransientAnalysis(stop = 1400.0, alg = ODEAlg.Rodas5P())
  model = CompleteCycleFixedControls(
    ref_medium_data = HVACComponents.load_refrigerant_medium(
      HVACComponents.SimpleRefrigerantPropertiesLibrary("R32")
    )
  )
relations
end

This is a TransientAnalysis that integrates from t = 0 to t = 1400 s with Rodas5P — a stiff DAE solver well-suited to mixed thermal-hydraulic systems where the air-side energy balance equilibrates on a slow time scale and refrigerant pressure transients are fast.

The single override ref_medium_data = ... plugs the R32 refrigerant from the SimpleRefrigerantProperties backend into the otherwise abstract ref_medium_data parameter on the model. Swap to a different fluid by changing the string argument.

Running it

Once the library compiles:

Then, from the package root with the project activated:

julia
using HVACComponents
HVACComponents.Examples.CompleteCycleFixedControls_SRP_Analysis()

That's it. The compiled analysis returns a DyadInterface solution object — inspect fields like .sol, .sol.t, .sol[compressor.port_a.m_flow], etc. to extract trajectories.

To re-run with a different stop time or solver, pass kwargs:

julia
HVACComponents.Examples.CompleteCycleFixedControls_SRP_Analysis(
  stop = 600.0,
  abstol = 1e-7,
  reltol = 1e-7,
)

Available kwargs come from the CompleteCycleFixedControls_SRP_AnalysisSpec struct generated alongside the analysis function and mirror the TransientAnalysisSpec fields (start, stop, alg, abstol, reltol, saveat, tstops, …).

Dynamic ph plot:

Variations

The CompleteCycleFixedControls.dyad file also defines a steady-state analysis that solves for the equilibrium directly:

dyad
analysis CompleteCycleFixedControls_SteadyState
  extends SteadyStateAnalysis()
  model = CompleteCycleFixedControls(
    ref_medium_data = HVACComponents.load_refrigerant_medium(
      HVACComponents.SimpleRefrigerantPropertiesLibrary("R32")
    )
  )
relations
end

Run it the same way:

julia
HVACComponents.Examples.CompleteCycleFixedControls_SteadyState()

That returns the cycle's steady operating point without integrating transients — useful for sizing studies or as a warm-start for the transient analysis above.