Welcome to ACHP’s documentation!¶
ACHP is an open source program written to model direct expansion and secondary loops for residential-scale systems.
It was written by Ian Bell, during his time at the Herrick Labs of Purdue University. He can be contacted with any questions or bugs.
Quickstart:
- To download the executable for ACHP, head to ACHP downloads.
- To download a PDF version of the documentation you see here, click here.
Contents of this website:
ACHP Graphical User Interface¶
Installation and Setup¶
Binaries for Windows Users (Easy way):¶
32-bit binaries including all other required packages are available from https://sourceforge.net/projects/achp/files/. Download the most recent zip file, and expand it somewhere convenient. If you have other configuration files, place them in the configs folder which is next to the ACHP.exe file
This is the easiest way to get started!
Using the source for Developers (Not for the faint of heart):¶
Step 1. Download a distribution of Python. For Windows users I strongly recommend the Python(x,y) distribution. Go to downloads and then pick the full install. I currently use the 2.6.6 version. When you are installing, I recommend going into the other section at the bottom and adding SWIG and mingw. This will allow you to recompile CoolProp if necessary. Otherwise the defaults should be fine.
For Mac OSX users, the Enthought Python Distribution (EPD) is recommended. It is free to use in 32-bit mode for academic users.
For masochists, you could download Python, and the other packages that you would need are scipy, numpy, matplotlib, and wx. It is highly recommended to use one of the above distributions.
For linux users, use your package manager to install python and the required packages.
Step 2. Download a copy of CoolProp. For Windows users, you can download an installer directly by going to CoolProp files and downloading the most recent file for your architecture. Pretty much the only architecture that is directly supported is 32bit Windows. But on other architectures, the requisite files are included.
Step 3. Download a subversion client. This allows you to interface with the subversion repository that the code is maintained in. You can use a command line subversion client (http://www.collab.net/downloads/subversion/ and download the command-line client), or use a graphical user interface. The GUI interface is a lot easier to use. I recommend TortoiseSVN. If you successfully installed CoolProp in the previous step, skip to Step 5.
Step 4. Download a copy of the CoolProp source (everyone except 32-bit Windows). If you are using a command line subversion client, type:
svn co http://coolprop.svn.sourceforge.net/svnroot/coolprop/trunk coolprop
This will pull all the CoolProp source code in the main development trunk from the servers and put it the folder coolprop. If you are using TortoiseSVN, in a Windows explorer window, right click and select SVN Checkout… then put https://achp.svn.sourceforge.net/svnroot/achp/trunk in the URL of repository and change the path if you like. Leave it to fully recursive and HEAD revision. Open a command prompt in the folder that the source resides and type:
python setup.py install
This will install CoolProp and put it in a location that Python will be able to find.
Step 5. Download a copy of the ACHP source code. If you are using TortoiseSVN, open an explorer window and right-click where you want the code to go. Select SVN Checkout…, set the URL of repository to https://achp.svn.sourceforge.net/svnroot/achp/trunk and change the path if you like. Leave it to fully recursive and HEAD revision. In a few moments you will then have the most recent set of code on your computer.
Step 6. You can now peruse the code. The components can all be found in the PyACHP subfolder and the GUI is in the GUI folder. If you want to begin development, I recommend the use of Eclipse with the plugin Pydev. The source tree includes a Pydev project file. Eclipse is included with the Python(x,y) distribution. Eclipse can be found in the pythonxy folder in the Windows start menu. Once Eclipse is opened, to get the Eclipse project opened, right click in the Pydev Package Explorer and select Import…. Then select Existing Projects into Workspace, and in the next window, click on the browse button next to the Select root directory option button. Browse to the folder that contains your ACHP source, and it should load up the project.
To run a given component, open the component in the Pydev Package explorer, click on the down-arrow on the button that looks like a play button in the toolbar, and go to Run as… and then select Python Run. This should run the component in stand-alone mode. If you want to run the cycle model, open Cycle.py and run it.
To start the graphical user interface, run GUI/ACHPMainFrame.py using the same Python run method as for a component.
Step 7. To update your code, either right click on the source folder and select SVN Update… if you are using TortoiseSVN, or open a command prompt in the main source folder and type:
svn update
Tutorial¶
Getting Started¶
In order to get started using ACHP, start the ACHP.exe executable which after showing a splash screen, should boot up into a screen that looks like

This is where a number of the important parameters can be changed.
The default configuration file that ships with ACHP is loaded from the file Default.cfg and is a direct expansion air conditioning system that is derived from the experimental and modeling work of Bo Shen [1]. At any time, the file Default.cfg can be overwritten which changes the parameters that will be loaded into ACHP when it starts.
To run the model, press the F5 key, or go into the menu to Solve->Solve (F5)
Once the model has run (you can watch the console for intermediate output while it is running), all the output fields are then populated.
In the output are things like
Main Output Screen

Temperature-Entropy plots

Pressure-Enthalpy plots

Output screens for each component

To save the data from a run to a file, click the Write to File… button on the main output screen. It will prompt you for a location to save the file. The file comprises the all the data that is output on the output screens of ACHP. It is a comma-separated file that you can open up in Excel.
Footnotes
[1] | Bo Shen, 2006, “Improvement and Validation of Unitary Air Conditioner and Heat Pump Simulation Models at Off-Design Conditions” Final Report 1173-RP Link to file |
Making Modifications¶
While it is nice to be able to see the performance of the default system, you probably want to make some changes for your own system. To do that, it is necessary to understand how ACHP is configured.
ACHP was built to be able to handle both conventional four-component air-conditioning and heat pump systems as well as secondary loop systems that use a secondary working fluid between the primary working fluid and the indoor coil. This type of system has been proposed, and is used, in large industrial scale systems.
Comments¶
In each of the input screens, if you hover your mouse over the text which describes a field, the tooltip that pops up will have further description of the field.
The user interface of ACHP is broken up into three parts - Input, Solvers, and Output. The tabs at the top of the screen allow you to move between the different parts.
Main Inputs¶
A number of different types of refrigerants can be used. The types of refrigerants that are available in ACHP are
- Working fluids that are implemented in CoolProp. A list of working fluids implmented in CoolProp can be found at the CoolProp website. These refrigerants are listed at the top of the list, before the REFPROP refrigerants
- Pure refrigerants, and defined blends from REFPROP. These fluids are listed as starting with “REFPROP-“
- Arbitrary blends of fluids from REFPROP. This functionality is achieved by creating a string which describes the blend. For instance, the fluid name “REFPROP-MIX:R32[0.697615]&R125[0.302385]” is the refrigerant R410A which is composed of a R32 and R125 mole fractions of 0.697615 and 0.302385 respectively. The syntax of the string must be followed, but can be extended if more fluids comprise the mixture. For instance, the fluid name “REFPROP-MIX:R125[0.35782]&R134a[0.038264]&R143a[0.60392]” would be the fluid name string for R404A
Since no expansion device model is employed in ACHP, the superheat is imposed as a model input. The superheat is that at the outlet of the evaporator, or in the case of the secondary loop system in cooling mode, the outlet of the internal heat exchanger.
Either the subcooling or the charge can be imposed by selecting one of the variables and providing its value, and the other one is then solved for. The convergence characteristics for subcooling imposed are slightly better than for charge imposed due to the formulation of the preconditioner. At the very least, if charge is desired to be imposed, a reasonable value for the charge should be obtained by fixing the subcooling for one point.
On the main screen of ACHP you can select whether the system is operating in cooling mode, or in heating mode, and whether a secondary loop is employed, or whether the system is a direct expansion system. As the mode and secondary loop/DX options are changed, the cycle schematic will also change.
If the cycle is a secondary loop cycle, the secondary working fluid can be selected from the dropdown box.
Heat Exchanger Inputs¶
In both secondary loop systems and direct expansion systems, there are two heat exchangers that are used to transfer heat with the indoor and outdoor air streams. The input screens for both of the heat exchangers are identical.
Currently, there are three type of fins coded - plain fin, herringbone fin and wavy lanced fin. If other fin types are needed, they must be coded into ACHP.
The inputs are divided into three subgroups - fins, tubes and air. In the fins group, you can select the fin pitch, waviness parameters of the fin, as well as the fin thickness, and fin material thermal conductivity.
In the tubes section, the geometry of the tubes and the circuits is defined. At any time, clicking on the Show Circuits… button will pop up a screen that will show an end-on view of the heat exchanger in order to demonstrate the construction of the currently defined heat exchanger. Clicking on the Select button will open up a small window that will allow you to select from standard tube dimensions.
Pump and Internal Heat Exchanger Inputs¶
In the pump and internal heat exchanger inputs pane, it is possible to set inputs for the pump and the internal heat exchanger. The pump inputs are straightforward, but the internal heat exchanger inputs need some description.
In cooling mode, either the coaxial heat exchanger or the plate heat exchanger can be used. In heating mode, the coaxial heat exchanger model has not been modified to handle condensation on the refrigerant side, so therefore it is not possible to use the coaxial heat exchanger in heating mode.
Compressor Inputs¶
The compressor model is based on a 10-coefficient compressor model as in ANSI/AHRI standard 540-2004
where \(T_s\) and \(T_d\) are refrigerant dew point temperatures in degrees Fahrenheit, the mass flow rate \(\dot m\) is in lbm/hr and the power is in Watts. The coefficients can be read in from a comma-delimited file by clicking the Load Coefficients button where the first column in the file are the coefficients \(M_1,M_2,...\) and the second column are the coefficients \(P_1,P_2,...\). If the compressor coefficients are loaded from a file, it will over-write the coefficients for the compressor present in the user interface. A sample compressor coefficient file would be:
117.316,-461.3
5.094,-18.6
-1.593,46.9
4.48E-02,-0.21
-2.14E-02,0.43
1.04E-02,-0.44
7.90E-05,2.25E-04
-5.73E-05,2.37E-03
1.79E-04,-3.32E-03
-8.08E-05,2.50E-03
Information about the compressor map can be obtained by clicking on the Info button
If the primary refrigerant is changed, an appropriate compressor map must be employed for the given primary refrigerant.
Line Set Inputs¶
The line set allows the condensing unit and the indoor coil to be physically separated.
In the line set inputs pane you can set inputs for the line set. The supply line set goes from the outdoor unit to the indoor coil, and the return line goes from the indoor coil to the outdoor unit.
Additional Functionality¶
Using Configuration Files¶
If you have a configuration that you like and would like to use at a later time in ACHP, you can save a configuration file that can be loaded back into ACHP. Once you have all the parameters as you would like them, go to File->Save Config File… or press Ctrl+s (Apple+s for OSX users). This will pop up a file selection dialog, and you can save the file somewhere.
At a later time, you can load the configuration file back into ACHP by going to File->Load Conf File… or pressing Ctrl+o (Apple+o for OSX users). Again you will get a file selection dialog and you can open your configuration file.
The configuration files are simple text files that are delimited with the delimiter “:::”. The configuration files list each of the items that are in the user interface and their current value (Also see note for developers below).
For Developers: When defining the names of items in the user interface, the first few letters of the object name determine whether it will be written to the configuration file or not, and whether it will be loaded back into the interface. The naming conventions from Visual Basic are used, so names starting with opt are option boxes, cmb are combo boxes, lbl are labels, txt are textboxes, rad are radio boxes, and chk are checkboxes. Refer to LoadGUI
to see how the user interface is constructed, and the functions ReadConfigFile and WriteConfigFile in ACHPMainFrame.py
Parametric Studies¶
One of the features built into versions 1.3 and onwards of ACHP is the flexible multi-dimensional parametric study solver. With this solver you can run multi-dimensional parametric studies. In order to activate this mode, go to the solvers Tab and switch the Solver Method to Parametric Study.
In each of the rows of the parametric study, you can select a variable that you would like to vary by selecting the variable from the combobox, and turn it on by checking the checkbox. You must then provide the values that will be used for the variable. There are two ways of doing this:
- Provide the minimum value in the Min Value/List column, the maximum value in the Max Value column, and the integer number of linearly spaced steps in the Number Steps column. This will yield a linearly spaced set of inputs that will be used.
- Provide a comma-separated list of inputs in the Min Value/List column, and put the letter “L” in the Number Steps column. This allows you to put your own values in, particularly useful if you are trying to duplicate non-linearly-spaced rating data, which was the motivating factor for this functionality
Not all variables make sense for all configurations. For instance, with a direct expansion air conditioning system, there is no secondary loop, so altering the secondary loop mass flow rate will not change anything, or may raise an error.
For Developers: If you want to add other things to the parametric study, you can open the file parametric/params.txt (path relative to ACHP.exe) and add or delete entries. You must know the name of the variable you are trying to modify, so some insight into the naming conventions of ACHP is required.
ACHP Cycle Model Description¶
Direct Expansion Cycle Solver¶
In the cycle solver, the goal is to use all the physical component models together in order to obtain the performance of the combined cycle. The process is slightly different for each of the 4 standard configurations of ACHP, but there are many common themes among the configurations. ACHP has been designed to investigate direct expansion (DX) systems as well as systems employing a secondary working loop, in both cooling and heating modes.
A number of simplifying assumptions are employed at the cycle level:
- Pressure drops in each component are calculated, but not used directly(see Pressure-Drop Correction for explanation)
- There is no charge inventory in the compressor shell
- The evaporator outlet refrigerant superheat is imposed (implies an expansion device with perfect superheat control)
- No pressure drops except for in the components considered
Direct Expansion Cooling Mode¶
The most common and straightforward system is the direct expansion cooling mode system. The schematic of this cycle is shown in this figure:
(Source code, png, hires.png, pdf)

In addition to the geometry of each component, required inputs are the superheat at the outlet of the evaporator \(\Delta T_{sh,evap}\), and either the total refrigerant charge \(m_r\) or the refrigerant subcooling at the outlet of the condenser \(\Delta T_{sc,cond}\).
The primary independent variables in the cycle solver are the saturation temperatures of the refrigerant at evaporation and condensation, given by \(T_{evap}\) and \(T_{cond}\) respectively. For pure refrigerants the saturation temperature for a given pressure is the same for saturated liquid and saturated vapor. For pseudo-pure fluids and blends, the refrigerant dew temperature is used which corresponds to saturated vapor.
Before the full cycle-solver is run, the preconditioner in section Cycle Solver Preconditioner is used to get a good guess for the temperatures \(T_{evap}\) and \(T_{cond}\) using extremely simple cycle models.
Once the preconditioner has been run, preliminary values for \(T_{evap}\) and \(T_{cond}\) are known, and the first iteration of the cycle model may begin. Execution of the cycle model follows in the same direction as the refrigerant flow. The pressure drops through low-pressure and high-pressure parts of the system are assumed to be zero initially.
The cycle analysis begins with the vapor line which returns refrigerant vapor from the evaporator that is typically in the air duct back to the condensing unit outdoors. In the first iteration of the cycle solver, the mass flow rate of refrigerant in the vapor line is not known, but the compressor map is used to provide a reasonable guess value for the mass flow rate of refrigerant. The Line Set model is used to calculate the process from point 1 to point 2. The model is run with known flow rates and an inlet temperature of \(T_{evap}+\Delta T_{sh}\) in order to calculate the state at the inlet to the compressor.
The compressor compresses refrigerant from state point 2 to state point 3. The Compressor model is used which is based on an empirical correlation with superheat correction and it yields the outlet state 3 as well as the compressor mass flow rate, compressor electrical power, etc.. The compressor model requires the temperatures \(T_{evap}\) and \(T_{cond}\) as well as the compressor inlet superheat.
The condenser takes the superheated refrigerant at state point 3 and condenses it to a subcooled refrigerant at state point 4. The Condenser model is used to calculate the process, and this condenser model is based on a moving-boundary model. The condenser model requires \(T_{cond}\) as an input, among others.
After the condenser, the subcooled refrigerant passes through the liquid-line that takes refrigerant from the condenser to the indoor coil that is inside the ductwork in the home. The Line Set model is used to model the flow that passes from state point 4 to state point 5.
The expansion device then expands the refrigerant from the high-pressure side of the system to the low-pressure side of the system. In the current iteration of ACHP, no expansion device is included. Thus the expansion device is just a constant-enthalpy throttling device that takes refrigerant from the high-side pressure at state point 5 to the low-side pressure at state point 6.
At the outlet of the expansion device, the refrigerant passes into the evaporator at some two-phase quality. The Evaporator model is used to model the performance of the evaporator. In the evaporator, refrigerant is heated by the air-stream (which cools the air stream) from state point 6 back to state point 1’, which should be superheated (note: not necessarily so at intermediate iterations of cycle model) close to state point 1. If the values of the cycle independent variables \(T_{evap}\) and \(T_{cond}\) have been well selected, the state points 1 and 1’ will be coincident.
Once the cycle model has been run around the loop from state point 1 to state point 1’, the residuals can be calculated. The residuals are terms that when the cycle model has converged should all be equal to zero.
One of the residuals that is always active is an energy balance over the cycle. You left from state point 1, and you should hopefully arrive back there if energy is conserved in the cycle. Thus, the first residual is given by
where \(h_1\) and \(h_{1'}\) are the enthalpies of the refrigerant at state points 1 and 1’ respectively.
Since there are two independent variables, there must be a second constraint, which in this case is a charge-level constraint. Either the charge is constrained directly with an imposed charge level, or indirectly with an imposed refrigerant subcooling. Thus the second residual can be given by
and a numerical solver is used to drive the residual vector \(\vec \Delta\) to sufficiently close to zero by altering \(T_{evap}\) and \(T_{cond}\) (see Multi-dimensional solver).
Pressure-Drop Correction¶
After the cycle model has iterated to convergence, the pressure drops are then considered. In reality, the pressure drop in each component results in a lower pressure at the inlet of the next component in the refrigerant loop. In terms of modeling, coupling pressure drop and the component models causes great numerical difficulties. The compromise that is employed instead is to run all the component models without pressure drop, but calculate the high-side pressure drop as the pressure drop of the condenser and liquid-line:
and similarly, the low-side pressure drop is defined by
These pressure drops are then employed to shift the saturation temperatures used in the compressor map in order to yield less refrigerant mass flow rate, and a higher compressor power.
The new effective compressor suction and discharge pressures are
and the new, effective compressor dew temperatures are
This calculated pressure drop is used until the model reaches convergence again, at which point the pressure drop tems are updated, and the model is run again. This process continues until the imposed low- and high-side pressure drops are equal to the pressure drop terms calculated from the converged cycle model.
Cycle Performance Parameters¶
The common metrics of system efficiency are
Minimal working example¶
from __future__ import print_function
from ACHP.Cycle import DXCycleClass
#Instantiate the cycle class
Cycle=DXCycleClass()
#--------------------------------------
# Cycle parameters
#--------------------------------------
Cycle.Verbosity = 0 #the idea here is to have different levels of debug output
Cycle.ImposedVariable = 'Subcooling'
Cycle.DT_sc_target = 7.0
Cycle.Mode='AC'
Cycle.Ref='R410A'
Cycle.Backend='TTSE&HEOS' #Backend for refrigerant properties calculation: 'HEOS','TTSE&HEOS','BICUBIC&HEOS','REFPROP','SRK','PR'
#--------------------------------------
# Compressor parameters
#--------------------------------------
#A 3 ton cooling capacity compressor map
M=[217.3163128,5.094492028,-0.593170311,4.38E-02,-2.14E-02,
1.04E-02,7.90E-05,-5.73E-05,1.79E-04,-8.08E-05]
P=[-561.3615705,-15.62601841,46.92506685,-0.217949552,
0.435062616,-0.442400826,2.25E-04,2.37E-03,-3.32E-03,2.50E-03]
params={
'M':M,
'P':P,
'Ref':Cycle.Ref, #Refrigerant
'Backend':Cycle.Backend, #Backend for refrigerant properties calculation
'fp':0.0, #Fraction of electrical power lost as heat to ambient
'Vdot_ratio': 1.0, #Displacement Scale factor
'Verbosity': 0, # How verbose should the debugging be [0-10]
}
Cycle.Compressor.Update(**params)
#--------------------------------------
# Condenser parameters
#--------------------------------------
Cycle.Condenser.Fins.Tubes.NTubes_per_bank=24 #number of tubes per bank=row
Cycle.Condenser.Fins.Tubes.Nbank=1 #number of banks/rows
Cycle.Condenser.Fins.Tubes.Ncircuits=3
Cycle.Condenser.Fins.Tubes.Ltube=2.252
Cycle.Condenser.Fins.Tubes.OD=0.00913
Cycle.Condenser.Fins.Tubes.ID=0.00849
Cycle.Condenser.Fins.Tubes.Pl=0.0191 #distance between center of tubes in flow direction
Cycle.Condenser.Fins.Tubes.Pt=0.0254 #distance between center of tubes orthogonal to flow direction
Cycle.Condenser.Fins.Fins.FPI=25 #Number of fins per inch
Cycle.Condenser.Fins.Fins.Pd=0.001 #2* amplitude of wavy fin
Cycle.Condenser.Fins.Fins.xf=0.001 #1/2 period of fin
Cycle.Condenser.Fins.Fins.t=0.00011 #Thickness of fin material
Cycle.Condenser.Fins.Fins.k_fin=237 #Thermal conductivity of fin material
Cycle.Condenser.Fins.Air.Vdot_ha=1.7934 #rated volumetric flowrate
Cycle.Condenser.Fins.Air.Tmean=308.15
Cycle.Condenser.Fins.Air.Tdb=308.15
Cycle.Condenser.Fins.Air.p=101325 #Condenser Air pressure in Pa
Cycle.Condenser.Fins.Air.RH=0.51
Cycle.Condenser.Fins.Air.RHmean=0.51
Cycle.Condenser.Fins.Air.FanPower=260
Cycle.Condenser.FinsType = 'WavyLouveredFins' #WavyLouveredFins, HerringboneFins, PlainFins
Cycle.Condenser.Ref=Cycle.Ref
Cycle.Condenser.Backend=Cycle.Backend
Cycle.Condenser.Verbosity=0
#--------------------------------------
# Evaporator Parameters
#--------------------------------------
Cycle.Evaporator.Fins.Tubes.NTubes_per_bank=32
Cycle.Evaporator.Fins.Tubes.Nbank=3
Cycle.Evaporator.Fins.Tubes.Ltube=0.452
Cycle.Evaporator.Fins.Tubes.OD=0.00913
Cycle.Evaporator.Fins.Tubes.ID=0.00849
Cycle.Evaporator.Fins.Tubes.Pl=0.0191
Cycle.Evaporator.Fins.Tubes.Pt=0.0254
Cycle.Evaporator.Fins.Tubes.Ncircuits=5
Cycle.Evaporator.Fins.Fins.FPI=14.5
Cycle.Evaporator.Fins.Fins.Pd=0.001
Cycle.Evaporator.Fins.Fins.xf=0.001
Cycle.Evaporator.Fins.Fins.t=0.00011
Cycle.Evaporator.Fins.Fins.k_fin=237
Cycle.Evaporator.Fins.Air.Vdot_ha=0.56319
Cycle.Evaporator.Fins.Air.Tmean=297.039
Cycle.Evaporator.Fins.Air.Tdb=297.039
Cycle.Evaporator.Fins.Air.p=101325 #Evaporator Air pressure in Pa
Cycle.Evaporator.Fins.Air.RH=0.5
Cycle.Evaporator.Fins.Air.RHmean=0.5
Cycle.Evaporator.Fins.Air.FanPower=438
Cycle.Evaporator.FinsType = 'WavyLouveredFins' #WavyLouveredFins, HerringboneFins, PlainFins
Cycle.Evaporator.Ref=Cycle.Ref
Cycle.Evaporator.Backend=Cycle.Backend
Cycle.Evaporator.Verbosity=0
Cycle.Evaporator.DT_sh=5
# ----------------------------------
# Line Set Parameters
# ----------------------------------
params={
'L':7.6,
'k_tube':0.19,
't_insul':0.02,
'k_insul':0.036,
'T_air':297,
'Ref': Cycle.Ref,
'Backend': Cycle.Backend,
'h_air':0.0000000001,
}
Cycle.LineSetSupply.Update(**params)
Cycle.LineSetReturn.Update(**params)
Cycle.LineSetSupply.OD=0.009525
Cycle.LineSetSupply.ID=0.007986
Cycle.LineSetReturn.OD=0.01905
Cycle.LineSetReturn.ID=0.017526
#Now solve
from time import time
t1=time()
Cycle.PreconditionedSolve()
print('Took '+str(time()-t1)+' seconds to run Cycle model')
print('Cycle COP is '+str(Cycle.COSP))
print('Cycle refrigerant charge is '+str(Cycle.Charge)+' kg')
which should yield the output, when run, of
Took 15.25670313835144 seconds to run Cycle model
Cycle COP is 3.20732414824
Cycle refrigerant charge is 2.0542017125183585 kg
Direct Expansion Heating Mode¶
The heat pump configuration of the system is as shown here:
(Source code, png, hires.png, pdf)

Physically, reversing valves are used to switch the mode of the system and the directions of the flows. What was the condenser of the air conditioning system becomes the evaporator of the heat pump and vice versa, and the line sets are configured in a slightly different way. Other than that, the analysis of the heat pump is directly analogous to that of the Direct Expansion Cooling Mode system.
A Preconditioner is used to get approximate values for \(T_{evap}\) and \(T_{cond}\), and using these values (which are iteratively modified using numerical methods), the solution for the cycle performance is found.
As with the cooling mode, the cycle analysis follows the refrigerant flow path around the loop.
Beginning at the outlet of the evaporator, state point 1 is known because \(T_{evap}\) and \(\Delta T_{sh}\) are known. Thus the compressor model is used directly to calculate the electrical power, refrigerant mass flow rate and state point 2.
The Line Set model is then applied to the flow from the outlet of the compressor at state point 2 to the inlet of the condenser at state point 3.
The Condenser model is used to model the condensing process from state point 3 to a subcooled state at state point 4.
The Line Set model is used to model the flow of subcooled refrigerant at state point 4 back to the expansion device at state point 5.
As in cooling mode, the expansion device is assumed to be an ideal expansion device, which means that the working process is a constant-enthalpy expansion from state point 5 to state point 6.
The Evaporator model is then used to calculate the evaporation process of refrigerant from state point 6 to state point 1’.
As in cooling mode, the residual vector is given by
with
The set of \(T_{evap}\) and \(T_{cond}\) which solve the residual equations are obtained by a multi-dimensional solver (see Multi-dimensional solver).
Cycle Performance Parameters¶
The common metrics of system efficiency are
Minimal working example¶
from __future__ import print_function
from ACHP.Cycle import DXCycleClass
from ACHP.convert_units import F2K
#Instantiate the class
Cycle=DXCycleClass()
#--------------------------------------
# Cycle parameters
#--------------------------------------
Cycle.Verbosity = 0 #the idea here is to have different levels of debug output
Cycle.ImposedVariable = 'Subcooling' #or it could be 'Charge'
Cycle.DT_sc_target = 7.0
#Cycle.Charge_target = 3.3 #uncomment for use with imposed charge
Cycle.Mode='HP'
Cycle.Ref='R410A'
Cycle.Backend='TTSE&HEOS' #Backend for refrigerant properties calculation: 'HEOS','TTSE&HEOS','BICUBIC&HEOS','REFPROP','SRK','PR'
#--------------------------------------
# Compressor parameters
#--------------------------------------
#A few 3 ton cooling capacity compressor maps
M=[217.3163128,5.094492028,-0.593170311,4.38E-02,
-2.14E-02,1.04E-02,7.90E-05,-5.73E-05,1.79E-04,-8.08E-05]
P=[-561.3615705,-15.62601841,46.92506685,-0.217949552,
0.435062616,-0.442400826,2.25E-04,2.37E-03,-3.32E-03,2.50E-03]
params={
'M':M,
'P':P,
'Ref':Cycle.Ref, #refrigerant
'Backend':Cycle.Backend, #backend for refirgerant properties calculation
'fp':0.0, #Fraction of electrical power lost as heat to ambient #shell heat loss
'Vdot_ratio': 1.0, #Displacement Scale factor #up- or downsize compressor
'Verbosity': 0, # How verbose should the debugging statements be [0 to 10]
}
Cycle.Compressor.Update(**params)
#--------------------------------------
# Condenser parameters
#--------------------------------------
Cycle.Condenser.Fins.Tubes.NTubes_per_bank=32
Cycle.Condenser.Fins.Tubes.Nbank=3
Cycle.Condenser.Fins.Tubes.Ncircuits=6
Cycle.Condenser.Fins.Tubes.Ltube=0.452
Cycle.Condenser.Fins.Tubes.OD=0.009525
Cycle.Condenser.Fins.Tubes.ID=0.0089154
Cycle.Condenser.Fins.Tubes.Pl=0.0254
Cycle.Condenser.Fins.Tubes.Pt=0.0219964
Cycle.Condenser.Fins.Fins.FPI=14.5
Cycle.Condenser.Fins.Fins.Pd=0.001
Cycle.Condenser.Fins.Fins.xf=0.001
Cycle.Condenser.Fins.Fins.t=0.00011
Cycle.Condenser.Fins.Fins.k_fin=237
Cycle.Condenser.Fins.Air.Vdot_ha=0.5663
Cycle.Condenser.Fins.Air.Tmean=F2K(70)
Cycle.Condenser.Fins.Air.Tdb=F2K(70)
Cycle.Condenser.Fins.Air.p=101325 #Condenser Air Pressure in Pa
Cycle.Condenser.Fins.Air.RH=0.51
Cycle.Condenser.Fins.Air.RHmean=0.51
Cycle.Condenser.Fins.Air.FanPower=438
Cycle.Condenser.FinsType = 'WavyLouveredFins' #WavyLouveredFins, HerringboneFins, PlainFins
Cycle.Condenser.Ref=Cycle.Ref
Cycle.Condenser.Backend=Cycle.Backend #backend for refirgerant properties calculation
Cycle.Condenser.Verbosity=0
#--------------------------------------
# Evaporator parameters
#--------------------------------------
Cycle.Evaporator.Fins.Tubes.NTubes_per_bank=41 #number of tubes per bank=row
Cycle.Evaporator.Fins.Tubes.Nbank=1 #number of banks/rows
Cycle.Evaporator.Fins.Tubes.Ncircuits=5
Cycle.Evaporator.Fins.Tubes.Ltube=2.286
Cycle.Evaporator.Fins.Tubes.OD=0.007
Cycle.Evaporator.Fins.Tubes.ID=0.0063904
Cycle.Evaporator.Fins.Tubes.Pl=0.0191 #distance between center of tubes in flow direction
Cycle.Evaporator.Fins.Tubes.Pt=0.0222 #distance between center of tubes orthogonal to flow direction
Cycle.Evaporator.Fins.Fins.FPI=25 #Number of fins per inch
Cycle.Evaporator.Fins.Fins.Pd=0.001 #2* amplitude of wavy fin
Cycle.Evaporator.Fins.Fins.xf=0.001 #1/2 period of fin
Cycle.Evaporator.Fins.Fins.t=0.00011 #Thickness of fin material
Cycle.Evaporator.Fins.Fins.k_fin=237 #Thermal conductivity of fin material
Cycle.Evaporator.Fins.Air.Vdot_ha=1.7934 #rated volumetric flowrate
Cycle.Evaporator.Fins.Air.Tmean=F2K(47)
Cycle.Evaporator.Fins.Air.Tdb=F2K(47)
Cycle.Evaporator.Fins.Air.p=101325 #Evaporator Air pressure in Pa
Cycle.Evaporator.Fins.Air.RH=0.51
Cycle.Evaporator.Fins.Air.RHmean=0.51
Cycle.Evaporator.Fins.Air.FanPower=160
Cycle.Evaporator.FinsType = 'WavyLouveredFins' #WavyLouveredFins, HerringboneFins, PlainFins
Cycle.Evaporator.Ref=Cycle.Ref
Cycle.Evaporator.Backend=Cycle.Backend #backend for refirgerant properties calculation
Cycle.Evaporator.Verbosity=0
Cycle.Evaporator.DT_sh=5
# ----------------------------------
# Line Set parameters
# ----------------------------------
params={
'L':7.6,
'k_tube':0.19,
't_insul':0.02,
'k_insul':0.036,
'T_air':297,
'Ref': Cycle.Ref,
'Backend': Cycle.Backend,
'h_air':6,
}
Cycle.LineSetSupply.Update(**params)
Cycle.LineSetReturn.Update(**params)
Cycle.LineSetSupply.OD=0.01905
Cycle.LineSetSupply.ID=0.017526
Cycle.LineSetReturn.OD=0.009525
Cycle.LineSetReturn.ID=0.007986
#Now solve
from time import time
t1=time()
Cycle.PreconditionedSolve()
#Outputs
print('Took '+str(time()-t1)+' seconds to run Cycle model')
print('Cycle coefficient of system performance is '+str(Cycle.COSP))
print('Cycle refrigerant charge is '+str(Cycle.Charge)+' kg')
which should yield the output, when run, of
Took 18.168339729309082 seconds to run Cycle model
Cycle coefficient of system performance is 3.6034037343008345
Cycle refrigerant charge is 1.719562780251362 kg
Cycle Solver Code Documentation¶
-
class
ACHP.Cycle.
DXCycleClass
[source]¶ -
Calculate
(DT_evap, DT_cond)[source]¶ Inputs are differences in temperature [K] between HX air inlet temperature and the dew temperature for the heat exchanger.
- Required Inputs:
- DT_evap:
- Difference in temperature [K] between evaporator air inlet temperature and refrigerant dew temperature
- DT_cond:
- Difference in temperature [K] between condenser air inlet temperature and refrigeant dew temperature
-
OutputList
()[source]¶ Return a list of parameters for this component for further output
- It is a list of tuples, and each tuple is formed of items:
- [0] Description of value [1] Units of value [2] The value itself
-
PreconditionedSolve
()[source]¶ Solver that will precondition by trying a range of DeltaT until the model can solve, then will kick into 2-D Newton Raphson solve
The two input variables for the system solver are the differences in temperature between the inlet air temperature of the heat exchanger and the dew temperature of the refrigerant. This is important for refrigerant blends with temperature glide during constant-pressure evaporation or condensation. Good examples of common working fluid with glide would be R404A or R410A.
-
Nomenclature
Variable | Description |
---|---|
\(COP\) | Coefficient of Performance [-] |
\(COSP\) | Coefficient of System Performance [-] |
\(h_1\) | Enthalpy at outlet of evaporator [J/kg] |
\(h_{1'}\) | Enthalpy after going around the cycle [J/kg] |
\(\dot m_r\) | Refrigerant mass flow rate [kg/s] |
\(m_r\) | Model-predicted charge [kg] |
\(m_{r,target}\) | Target refrigerant charge in system [kg] |
\(T_{evap}\) | Evaporating (dewpoint) temperature [K] |
\(T_{cond}\) | Condensing (dewpoint) temperature [K] |
\(T_{evap}^*\) | Effective evaporating temperature [K] |
\(T_{cond}^*\) | Effective condensing temperature [K] |
\(\Delta T_{sh}\) | Evaporator outlet superheat [K] |
\(\Delta T_{sc,cond}\) | Condenser outlet subcooling [K] |
\(\Delta T_{sc,cond,target}\) | Condenser outlet subcooling target [K] |
\(\Delta p_{cond}\) | Pressure drop in condenser [Pa] |
\(\Delta p_{evap}\) | Pressure drop in evaporator [Pa] |
\(\Delta p_{high}\) | Pressure drop on high-pressure side of system [Pa] |
\(\Delta p_{liquid-line}\) | Pressure drop in liquid line [Pa] |
\(\Delta p_{low}\) | Pressure drop on low-pressure side of system [Pa] |
\(\Delta p_{vapor-line}\) | Pressure drop in vapor line [Pa] |
\(p_{evap}^*\) | Effective evaporation saturation pressure [Pa] |
\(p_{cond}^*\) | Effective condensing saturation pressure [Pa] |
\(\dot Q_{evap}\) | Evaporator heat transfer rate [W] |
\(\dot W_{fan,evap}\) | Evaporator fan power [W] |
\(\dot W_{fan,cond}\) | Condenser fan power [W] |
\(\dot W_{comp}\) | Compressor power input [W] |
\(\vec \Delta_1\) | Residual vector [varied] |
Secondary Loop Cycle Solver¶
Secondary Loop Cooling Mode¶
(Source code, png, hires.png, pdf)

For secondary loops in cooling mode, there is an internal heat exchanger which physically separates the secondary loop and the refrigerant loop.
In this case, there are now three inputs, and three residuals (to be defined later). The three inputs are \(T_{g,i,cc}\), \(T_{evap}\) and \(T_{cond}\).
The two loops can be solved separately, where for the secondary loop, the inlet temperature to the cooling coil is known, and the secondary working fluid’s properties are independent of pressure.
To begin, the Cooling Coil model is employed to calculate the heat transfer rate in the cooling coil, which gives the process from state point 5 to state point 6.
The Line Set model is used to determine the heat transfer and pressure drop in the line going from state point 6 to state point 7.
The pump model is run to determine how much electrical power is consumed in the pump, which gives the state point 8, the glycol inlet to the internal heat exchanger.
The refrigerant loop is then solved. The refrigerant superheat at the outlet of the IHX is imposed as an input for the cycle. Thus state point 1 is known, and the Compressor model is used to calculate state point 2, the compressor mass flow rate, electrical power, etc..
The Condenser model is then solved using the state point 2 as the inlet, and yielding the (hopefully) subcooled refrigerant outlet state point 3.
Finally, the isenthalpic throttling process is used to determine the state point 4 at the refrigerant inlet to the IHX.
Lastly, the Plate-Heat-Exchangers model is run, using the inputs at state points 8 and 4, and yielding the refrigerant outlet state of state point 1’.
The residuals are given by an energy balance between state points 1 and 1’, an energy balance on the secondary loop, and either matching the mass or the subcooling on the refrigerant side. As in the DX system analysis, the residual vector is given by
with
The set of \(T_{g,i,cc}\), \(T_{evap}\) and \(T_{cond}\) which solve the residual equations are obtained by a multi-dimensional solver (see Multi-dimensional solver).
The common metrics of system efficiency are
from __future__ import print_function
from ACHP.Cycle import SecondaryCycleClass
# Instantiate the class
Cycle = SecondaryCycleClass()
#--------------------------------------
# Cycle parameters
#--------------------------------------
Cycle.Verbosity = 0 #the idea here is to have different levels of debug output
Cycle.ImposedVariable = 'Subcooling' #or this could be 'Charge' for imposed charge
Cycle.DT_sc_target = 7.0
#Cycle.Charge_target = 2.4 #Needed if charge is imposed, not otherwise
Cycle.Ref='R410A'
Cycle.SecLoopFluid = 'MEG'
Cycle.MassFrac_SLF = 0.21 #Mass fraction of incompressible SecLoopFluid [i.e MEG-20%]
Cycle.Backend_SLF = 'INCOMP' #backend of SecLoopFluid
Cycle.IHXType = 'PHE'# or could be 'Coaxial'
Cycle.Mode='AC'
#--------------------------------------
#--------------------------------------
# Compressor parameters
#--------------------------------------
#--------------------------------------
# A 3 ton cooling capacity compressor map
if Cycle.Ref=='R410A':
M=[217.3163128,5.094492028,-0.593170311,4.38E-02,-2.14E-02,1.04E-02,
7.90E-05,-5.73E-05,1.79E-04,-8.08E-05]
P=[-561.3615705,-15.62601841,46.92506685,-0.217949552,0.435062616,
-0.442400826,2.25E-04,2.37E-03,-3.32E-03,2.50E-03]
params={
'M':M,
'P':P,
'Ref':Cycle.Ref, #refrigerant
'fp':0.15, #Fraction of electrical power lost as heat to ambient
'Vdot_ratio': 1.0, #Displacement Scale factor to up- or downsize compressor (1=original)
'Verbosity': 0, # How verbose should the debugging statements be [0 to 10]
}
Cycle.Compressor.Update(**params)
#--------------------------------------
# Condenser parameters
#--------------------------------------
Cycle.Condenser.Fins.Tubes.NTubes_per_bank=24 #number of tubes per bank=row
Cycle.Condenser.Fins.Tubes.Nbank=1 #number of banks/rows
Cycle.Condenser.Fins.Tubes.Ncircuits=3
Cycle.Condenser.Fins.Tubes.Ltube=2.252
Cycle.Condenser.Fins.Tubes.OD=0.00913
Cycle.Condenser.Fins.Tubes.ID=0.00849
Cycle.Condenser.Fins.Tubes.Pl=0.0191 #distance between center of tubes in flow direction
Cycle.Condenser.Fins.Tubes.Pt=0.0254 #distance between center of tubes orthogonal to flow direction
Cycle.Condenser.Fins.Fins.FPI=25 #Number of fins per inch
Cycle.Condenser.Fins.Fins.Pd=0.001 #2* amplitude of wavy fin
Cycle.Condenser.Fins.Fins.xf=0.001 #1/2 period of fin
Cycle.Condenser.Fins.Fins.t=0.00011 #Thickness of fin material
Cycle.Condenser.Fins.Fins.k_fin=237 #Thermal conductivity of fin material
Cycle.Condenser.Fins.Air.Vdot_ha=1.7934 #rated volumetric flowrate
Cycle.Condenser.Fins.Air.Tmean=308.15
Cycle.Condenser.Fins.Air.Tdb=308.15 #Dry Bulb Temperature
Cycle.Condenser.Fins.Air.p=101325 #Air pressure
Cycle.Condenser.Fins.Air.RH=0.51 #Relative Humidity
Cycle.Condenser.Fins.Air.RHmean=0.51
Cycle.Condenser.Fins.Air.FanPower=260
Cycle.Condenser.FinsType = 'WavyLouveredFins' #WavyLouveredFins, HerringboneFins, PlainFins
Cycle.Condenser.Ref=Cycle.Ref
Cycle.Condenser.Verbosity=0
#--------------------------------------
# Cooling Coil parameters
#--------------------------------------
Cycle.CoolingCoil.Fins.Tubes.NTubes_per_bank=32
Cycle.CoolingCoil.Fins.Tubes.Nbank=3
Cycle.CoolingCoil.Fins.Tubes.Ncircuits=5
Cycle.CoolingCoil.Fins.Tubes.Ltube=0.452
Cycle.CoolingCoil.Fins.Tubes.OD=0.00913
Cycle.CoolingCoil.Fins.Tubes.ID=0.00849
Cycle.CoolingCoil.Fins.Tubes.Pl=0.0191
Cycle.CoolingCoil.Fins.Tubes.Pt=0.0254
Cycle.CoolingCoil.Fins.Fins.FPI=14.5
Cycle.CoolingCoil.Fins.Fins.Pd=0.001
Cycle.CoolingCoil.Fins.Fins.xf=0.001
Cycle.CoolingCoil.Fins.Fins.t=0.00011
Cycle.CoolingCoil.Fins.Fins.k_fin=237
Cycle.CoolingCoil.Fins.Air.Vdot_ha=0.56319
Cycle.CoolingCoil.Fins.Air.Tmean=297.039
Cycle.CoolingCoil.Fins.Air.Tdb=297.039
Cycle.CoolingCoil.Fins.Air.p=101325
Cycle.CoolingCoil.Fins.Air.RH=0.5
Cycle.CoolingCoil.Fins.Air.RHmean=0.5
Cycle.CoolingCoil.Fins.Air.FanPower=438
params={
'Ref_g': Cycle.SecLoopFluid,
'Backend_g': Cycle.Backend_SLF,
'MassFrac_g': Cycle.MassFrac_SLF,
'pin_g': 200,
'Verbosity':0,
'mdot_g':0.38,
'FinsType':'WavyLouveredFins' #WavyLouveredFins, HerringboneFins, PlainFins
}
Cycle.CoolingCoil.Update(**params)
params={
'ID_i':0.0278,
'OD_i':0.03415,
'ID_o':0.045,
'L':50,
'pin_g':300,
'Ref_r':Cycle.Ref,
'Ref_g':Cycle.SecLoopFluid,
'Backend_g': Cycle.Backend_SLF,
'MassFrac_g': Cycle.MassFrac_SLF,
'Verbosity':0
}
Cycle.CoaxialIHX.Update(**params)
params={
'pin_h':300000,
'Ref_h':Cycle.SecLoopFluid,
'Backend_h': Cycle.Backend_SLF,
'MassFrac_h': Cycle.MassFrac_SLF,
'Ref_c':Cycle.Ref,
#Geometric parameters
'Bp' : 0.117,
'Lp' : 0.300, #Center-to-center distance between ports
'Nplates' : 46,
'PlateAmplitude' : 0.001, #[m]
'PlateThickness' : 0.0003, #[m]
'PlateConductivity' : 15.0, #[W/m-K]
'PlateWavelength' : 0.00628, #[m]
'InclinationAngle' : 3.14159/3,#[rad]
'MoreChannels' : 'Hot', #Which stream gets the extra channel, 'Hot' or 'Cold'
'Verbosity':0,
'DT_sh':5
}
Cycle.PHEIHX.Update(**params)
params={
'eta':0.5, #Pump+motor efficiency
'mdot_g':0.38, #Flow Rate kg/s
'pin_g':300000,
'Ref_g':Cycle.SecLoopFluid,
'Backend_g': Cycle.Backend_SLF,
'MassFrac_g': Cycle.MassFrac_SLF,
'Verbosity':0,
}
Cycle.Pump.Update(**params)
params={
'L':5,
'k_tube':0.19,
't_insul':0.02,
'k_insul':0.036,
'T_air':297,
'Ref': Cycle.SecLoopFluid,
'Backend': Cycle.Backend_SLF,
'MassFrac': Cycle.MassFrac_SLF,
'pin': 300000,
'h_air':0.0000000001,
}
Cycle.LineSetSupply.Update(**params)
Cycle.LineSetReturn.Update(**params)
Cycle.LineSetSupply.OD=0.009525
Cycle.LineSetSupply.ID=0.007986
Cycle.LineSetReturn.OD=0.01905
Cycle.LineSetReturn.ID=0.017526
#Now solve
from time import time
t1=time()
Cycle.PreconditionedSolve()
#Outputs
print('Took '+str(time()-t1)+' seconds to run Cycle model')
print('Cycle coefficient of system performance is '+str(Cycle.COSP))
print('Cycle refrigerant charge is '+str(Cycle.Charge)+' kg')
which should yield the output, when run, of
Took 9.141953468322754 seconds to run Cycle model
Cycle coefficient of system performance is 2.7891650414848344
Cycle refrigerant charge is 1.4989869734994357 kg
Secondary Loop Heating Mode¶
This section is left intentionally empty
Cycle Solver Class Documentation¶
-
class
ACHP.Cycle.
SecondaryCycleClass
[source]¶ -
Calculate
(DT_evap, DT_cond, Tin_CC)[source]¶ Inputs are differences in temperature [K] between HX air inlet temperature and the dew temperature for the heat exchanger.
- Required Inputs:
- DT_evap:
- Difference in temperature [K] between cooling coil air inlet temperature and refrigerant dew temperature
- DT_cond:
- Difference in temperature [K] between condenser air inlet temperature and refrigerant dew temperature
- Tin_CC:
- Inlet “glycol” temperature to line set feeding cooling coil
-
Nomenclature
Variable | Description |
---|---|
\(COP\) | Coefficient of Performance [-] |
\(COSP\) | Coefficient of System Performance [-] |
\(h_1\) | Enthalpy at outlet of evaporator [J/kg] |
\(h_{1'}\) | Enthalpy after going around the cycle [J/kg] |
\(\dot m_r\) | Refrigerant mass flow rate [kg/s] |
\(m_r\) | Model-predicted charge [kg] |
\(m_{r,target}\) | Target refrigerant charge in system [kg] |
\(T_{cond}\) | Condensing (dewpoint) temperature [K] |
\(T_{evap}\) | Evaporating (dewpoint) temperature [K] |
\(T_{g,i,cc}\) | Glycol inlet temperature to cooling coil [K] |
\(\Delta T_{sh}\) | IHX outlet superheat [K] |
\(\Delta T_{sc,cond}\) | Condenser outlet subcooling [K] |
\(\Delta T_{sc,cond,target}\) | Condenser outlet subcooling target [K] |
\(\dot Q_{cc}\) | Cooling coil heat transfer rate [W] |
\(\dot W_{fan,cc}\) | Cooling coil fan power [W] |
\(\dot W_{fan,cond}\) | Condenser fan power [W] |
\(\dot W_{comp}\) | Compressor power input [W] |
\(\vec \Delta\) | Residual vector [varied] |
Cycle Solver Preconditioner¶
The basic idea of a preconditioner is to use an extremely simple model in order to obtain good initial values for the solver used for the cycle in ACHP.
Conventional system¶
(Source code, png, hires.png, pdf)

The following assumptions are employed in the preconditioner employed for the conventional heat pump and air conditioning models:
- Condenser air stream is the minimum capacitance rate in the condenser, and the limiting outlet state for the air in the condenser is \(T_{cond}\). [This further assumes that there is no subcooled section, but this is ok, because there is also a pinch point at the saturated liquid point, so the basic analysis still works. In the end, the preconditioner is only used to get an approximate solution anyway, so inaccuracy is acceptable, as long as it is reasonable.]
- Effectiveness of all heat exchangers is known, and fixed
- Compressor inlet superheat is fixed and known
- Compressor is adiabatic
- Evaporator is fully wet, fully dry, or a simple weighted mix of the two
- Line sets are not considered
Essentially the preconditioner operates with the same independent variables as ACHP, which are the dew temperatures of the refrigerant in the evaporator and condenser, given by the variables \(T_{evap}\) and \(T_{cond}\) respectively.
Compressor¶
For a given set of \(T_{evap}\), \(T_{cond}\), and known superheat \(\Delta T_{sh}\), the inlet state and outlet pressure for the compressor is known. Therefore, the compressor map can be used to predict the refrigerant mass flow rate as well as the compressor power. This yields the values
Condenser¶
The heat transfer rate in the condenser can therefore be given by the value
The condenser heat transfer rate based on the imposed subcooling can also be given by
Theoretically these two heat transfer rate terms should match, and consistency is imposed by the numerical solver that is employed.
Evaporator¶
As usual, the evaporator is the most complicated component due to the possibility of the evaporator coil being fully wet, fully dry, or partially wet and partially dry. As in the full evaporator model, the evaporator is first considered to be fully dry, yielding the heat transfer rate of
Then using the dry evaporator heat transfer analysis it is possible to determine the surface temperature. The \(\mathrm{UA}\) values can be obtained from
The outlet temperature of the air can be given from
which yields the air inlet surface temperature of
and the air outlet surface temperature of
If both \(T_{s,a,o}\) and \(T_{s,a,i}\) are above the dewpoint temperature of the entering air (\(T_{dp}\)), the rate of heat transfer in the evaporator is equal to the dry-analysis heat transfer rate. If both \(T_{s,a,o}\) and \(T_{s,a,i}\) are below the dewpoint of the entering air, the coil is entirely wet, for which the heat transfer rate can be obtained from
where \(h_{a,s,evap}\) is the saturated air enthalpy at \(T_{evap}\) and \(h_{a,i}\) is the enthalpy of the inlet air to the evaporator.
If the dewpoint of the inlet air is somewhere between \(T_{s,a,o}\) and \(T_{s,a,i}\), the heat transfer rate in the evaporator is given by a simple weighting. This yields the following solution for the evaporator:
Solution Method¶
The residuals to driven to zero are therefore an overall energy balance over the system, as well as matching \(\dot Q_{cond}\) and \(\dot Q_{cond,\Delta h}\). So the residual vector as a function of \(T_{evap}\) and \(T_{cond}\) can be expressed as
and a two-dimensional solver can be used to drive the norm of \(\vec{\Delta}\) to sufficiently close to zero by altering \(T_{evap}\) and \(T_{cond}\).
Heating Mode¶
In heating mode, the system schematic remains exactly the same, and the same analysis is used, but the physical geometry of the evaporator and condenser are swapped.
Secondary Loop Systems¶
(Source code, png, hires.png, pdf)

The same basic structure is employed for the preconditioner for the secondary loop systems, except that one more variable must be determined by the preconditioner. The preconditioner for the secondary loop system is used to determine the saturation temperatures \(T_{evap}\) and \(T_{cond}\), as well as the cooling coil inlet temperature \(T_{g,i,cc}\).
The same exact analysis as for the DX preconditioner is employed for the compressor and condenser, and a very similar analysis is used for the cooling coil. The cooling coil analysis mirrors that of the evaporator, as described here.
Cooling Coil¶
The cooling coil is first considered to be fully dry, yielding the heat transfer rate of
Then using the dry cooling coil heat transfer analysis it is possible to determine the surface temperature. The \(\mathrm{UA}\) values can be obtained from
The outlet temperature of the air can be given from
which yields the air inlet surface temperature of
and the air outlet surface temperature of
If both \(T_{s,a,o}\) and \(T_{s,a,i}\) are above the dewpoint temperature of the entering air (\(T_{dp}\)), the rate of heat transfer in the evaporator is equal to the dry-analysis heat transfer rate. If both \(T_{s,a,o}\) and \(T_{s,a,i}\) are below the dewpoint of the entering air, the coil is entirely wet, for which the heat transfer rate can be obtained from
where \(h_{a,s,cc}\) is the saturated air enthalpy at \(T_{g,i}\) and \(h_{a,i}\) is the enthalpy of the inlet air to the cooling coil.
If the dewpoint of the inlet air is somewhere between \(T_{s,a,o}\) and \(T_{s,a,i}\), the heat transfer rate in the cooling coil is given by a simple weighting. This yields the following solution for the cooling coil:
Internal Heat Exchanger¶
Once the cooling coil code has been run, the glycol outlet temperature of the cooling coil can be obtained from
The heat transfer rate in the internal heat exchanger is then given by
because the glycol is the limiting capacitance rate in the two-phase portion of the IHX.
Solution Method¶
The residuals to driven to zero are therefore an overall energy balance over the refrigerant loop, matching \(\dot Q_{cond}\) and \(\dot Q_{cond,\Delta h}\), and an energy balance over the secondary loop. So the residual vector as a function of \(T_{evap}\), \(T_{cond}\), and \(T_{g,i,cc}\) can be expressed as
and a three-dimensional solver can be used to drive the norm of \(\vec{\Delta}\) to sufficiently close to zero by altering \(T_{evap}\), \(T_{cond}\), and \(T_{g,i,cc}\).
The code for the preconditioners can be found in Preconditioners.py
Nomenclature
Variable | Description |
---|---|
\(\alpha_g\) | Mean glycol heat transfer coefficient [W/\(\mathrm{m}^2\)/K] |
\(\alpha_r\) | Mean refrigerant heat transfer coefficient [W/\(\mathrm{m}^2\)/K] |
\(\alpha_a\) | Mean air heat transfer coefficient [W/\(\mathrm{m}^2\)/K] |
\(\vec{\Delta}\) | Residual vector [W] |
\(\eta_a\) | Overall air-side surface efficiency [-] |
\(\varepsilon_{HX}\) | Effectiveness of heat exchangers [-] |
\(\rho_{da}\) | Density of humid air [kgda/m3] |
\(A_{a,total}\) | Total air-side surface area of evaporator (fins+tubes) [\(\mathrm{m}^2\)] |
\(A_{r,total}\) | Total refrigerant-side surface area of evaporator [\(\mathrm{m}^2\)] |
\(c_{p,a}\) | Specific heat of humid air [J/kgda/K] |
\(h_{a,s,cc}\) | Enthalpy of air saturated at \(T_{g,i,cc}\) [J/kgda] |
\(h_{a,s,sat}\) | Enthalpy of air saturated at \(T_{evap}\) [J/kgda] |
\(h_{a,i}\) | Enthalpy of air inlet to evaporator [J/kgda] |
\(h_{r,o,comp}\) | Compressor outlet enthalpy [J/kg] |
\(T_{a,i,cond}\) | Condenser air inlet dry-bulb temperature [K] |
\(T_{a,i,cc}\) | Cooling coil air inlet dry-bulb temperature [K] |
\(T_{a,o,cc}\) | Cooling coil outlet dry-bulb temperature [K] |
\(T_{a,i,evap}\) | Evaporator air inlet dry-bulb temperature [K] |
\(T_{a,o,evap}\) | Evaporator air outlet dry-bulb temperature [K] |
\(T_{g,i,cc}\) | Cooling coil glycol inlet temperature [K] |
\(T_{g,o,cc}\) | Cooling coil glycol outlet temperature [K] |
\(T_{dp}\) | Dewpoint temperature of humid air [K] |
\(T_{evap}\) | Evaporator dew temperature [K] |
\(T_{cond}\) | Condenser dew temperature [K] |
\(T_{s,a,i}\) | Surface temperature of air at air inlet [K] |
\(T_{s,a,o}\) | Surface temperature of air at air outlet [K] |
\(\Delta T_{sh}\) | Compressor suction superheat [K] |
\(\Delta T_{sc}\) | Condenser outlet subcooling [K] |
\(p_{cond}\) | Condenser pressure [Pa (abs)] |
\(\dot m_g\) | Mass flow rate of glycol [kg/s] |
\(\dot m_r\) | Mass flow rate of refrigerant [kg/s] |
\(\dot m_{a,total}\) | Mass flow rate of dry air through evaporator [kgda/s] |
\(\dot Q_{evap}\) | Evaporator heat transfer rate [W] |
\(\dot Q_{evap,dry}\) | Evaporator fully-dry heat transfer rate [W] |
\(\dot Q_{evap,wet}\) | Evaporator fully-wet heat transfer rate [W] |
\(\dot Q_{cc}\) | Cooling Coil heat transfer rate [W] |
\(\dot Q_{cc,dry}\) | Cooling Coil fully-dry heat transfer rate [W] |
\(\dot Q_{cc,wet}\) | Cooling coil fully-wet heat transfer rate [W] |
\(\dot Q_{cond}\) | Condenser heat transfer rate [W] |
\(\dot Q_{cond,\Delta h}\) | Condenser heat transfer rate from change in enthalpy [W] |
\(\dot Q_{IHX}\) | Internal Heat Exchanger heat transfer rate [W] |
\(\mathrm{UA}_a\) | Air-side \(\mathrm{UA}\) value [W/K] |
\(\mathrm{UA}_g\) | Glycol-side \(\mathrm{UA}\) value [W/K] |
\(\mathrm{UA}_r\) | Refrigerant-side \(\mathrm{UA}\) value [W/K] |
\(\dot V_{ha,cond}\) | Volumetric flow rate of humid air in condenser [m3/s ] |
\(\dot V_{ha,evap}\) | Volumetric flow rate of humid air in evaporator [m3/s ] |
\(\dot V_{ha,cc}\) | Volumetric flow rate of humid air in cooling coil [m3/s ] |
\(\dot W_{comp}\) | Electrical power of compressor [W] |
General Numerics¶
One-dimensional Secant solver¶
If you have a function \(f\), which is a function of a single variable \(x\) and the derivative of f cannot be found in a simple fashion, a secant solver can be used to find the value of \(x\) that yields the equality \(f(x)=0\).
The secant solver requires two initial guesses which set the search direction of the secant search. It is not necessarily well-behaved, and can struggle to find a solution at times. Also, if there are multiple solutions, you must start quite close to the solution that you want. All that said, it is a simple model to implement, and performs quite admirably most of the time. With the two initial guesses for \(x\) of \(x_0\) and \(x_1\), the function is evaluated at these points, yielding the functional values \(f_0=f(x_0)\) and \(f_1=f(x_1)\). The new guess for \(x\) is then found from
and the values of \(x_i\) and \(f_i\) are updated and this method is repeated until \(|f(x)|\) is small enough.
The Scientific Python package includes an implementation of this method, and a simple example of its use is
#Import the newton function (implements secant method if no function derivative provided)
In [1]: from scipy.optimize import newton
# newton(function handle, x0), also see
# http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.newton.html
In [2]: newton(lambda x: x**2-0.4,1.5)
Out[2]: 0.6324555320337425
# The exact solution - should be the same.
# a**b in Python is a to the power of b
In [3]: 0.4**0.5