CoolProp Function Implementation in Mathcad#
For the most part, the Mathcad wrappers follow the Python implementation and most of the examples on this site can be executed in Mathcad Prime with very little modification. There are a few key difference:
Mathcad Strings always use âdouble-quotesâ
Units (see below)
Functions can be evaluated on their own, assigned to a variable, or both at the same time,
PropsSI(âDâ, âTâ, 295.15, âPâ, 101325.0, âWaterâ) = 997.773
Ď := PropsSI(âDâ, âTâ, 295.15, âPâ, 101325.0, âWaterâ)
Ď := PropsSI(âDâ, âTâ, 295.15, âPâ, 101325.0, âWaterâ) = 997.773
Mathcad can execute equations in random order as changes are made to the worksheet. This can sometimes cause unexpected behavior if CoolProp settings are modified non-sequentially. It is a good idea to press <Ctrl>-<F9> periodically to recalculate the entire worksheet in top to bottom order.
Unfortunately, there is no way to emulate the live Python examples found elsewhere on this web site with Mathcad Prime, so the Mathcad syntax and functionality is emulated in the fixed math sections below.
A majority of these functions and examples of their use are described in the Mathcad file CoolPropFluidProperties.mcdx, found in the 8.1.0dev MathcadPrime folder on SourceForge.
High-Level Functions#
PropsSI - State Dependent Fluid Properties#
PropsSI is the basic, high-level function for returning the scalar value of a specified output property at a fixed state point.:
PropsSI("Output", "Input1", Val1, "Input2", Val2, "Fluid")
Where,
âOutputâ = Requested output property string; see Table of Valid Parameters.
âInput1â = First state-point property string.
Val1 = First state-point property value (scalar variable)
âInput2â = Second state-point property string.
Val2 = Second state-point property value (scalar variable)
âFluidâ = Fluid string (e.g, âWaterâ, âAmmoniaâ, âAir.mixâ, etc.).
Note
The Fluid string can use a backend prefix (e.g., âHEOS::â, âINCOMP::â, âREFPROP::â, etc.) to specify an alternative EOS; the default being the Helmholtz EOS (âHEOS::â) if not provided.
Note
In addition to pure and pseudo-pure fluid strings, the fluid string can be specified as a predefined mixture (e.g., âAir.mixâ) or an ad-hoc mixture, specifying each pure component and mole fraction (e.g., âO2[0.2096]&N2[0.7812]&AR[0.0092]â) where the mole fractions are in square braces [ ] and the components are delimited with â&â.
- EXAMPLE:
- \[h := PropsSI("H",\ "T",\ 300.0,\ "P",\ 500,\ "Helium") = 1562994.2\]
PropsSImulti - Multiple State Dependent Fluid Properties#
PropsSImulti will return a vector/matrix of multiple fluid output properties spanning a range of state points. The return value is an (\(m x n\)) matrix, where \(n\) is the number of columns, one for each requested property, and \(m\) is the number of rows for each state point. For the most part, the parameters of PropsSImulti are the same as PropsSI with the following exceptions.:
PropsSImulti("Outputs", "Input1", Vec1, "Input2", Vec2, "Fluid")
Where,
âOutputsâ = Requested output properties string containing a delimited list of one or more valid output property names from the Table of Valid Parameters. For this Mathcad wrapper, the delimiter can be any one of (comma, <space>, colon, semi-colon, or ampersand), but must be consistent.
Vec1, Vec2 = State point array pairs corresponding to âInput1â and âInput2â. These are single-column, \(m\)-element vector arrays and must be the same length or an error will be thrown.
EXAMPLE:
Define a fluid: Â Â Â \(fl\) := âWaterâ
Triple Points: Â Â Â Â \(T_t := 273.15\) Â Â & Â Â \(P_t := 611.655\)
Critical Points: Â Â Â \(T_c := 647.096\) Â Â & Â Â \(P_c := 2.206\cdot10^7\)
Liquid points: Â Â Â \(T_L := mean(T_t,T_c)\) Â Â & Â Â \(P_L := mean(P_t,P_c)\)
Set Vectors: Â Â Â \(Tvec := \begin{bmatrix} T_t\\ T_L \\ T_L \end{bmatrix}\) Â Â Â \(Pvec := \begin{bmatrix} P_L\\ P_L \\ P_c \end{bmatrix}\)
Calc: Â \(M := PropsSImulti("D\ H",\ "T",\ Tvec,\ "P",\ Pvec,\ fl) = \begin{bmatrix} 1005.334 & 1.115\cdot10^4\\ 886.137 & 7.987\cdot10^5 \\ 893.241 & 8.044\cdot10^5 \end{bmatrix}\)
Extract individual variables from columns: Â Â Â Â \(\rho = M^{<0>}\) Â Â & Â Â \(h = M^{<1>}\)
Props1SI - State Independent Fluid Properties#
Props1SI returns non-state-dependent properties of a fluid/mixture and does not require state point names or values. This function only requires the output property and fluid name strings.:
Props1SI("Output", "Fluid")
Where,
âOutputâ = One of the âtrivialâ output-only properties from the Table of Valid Parameters.
âFluidâ = Fluid string, as defined above for PropsSI
EXAMPLE:
Define a fluid: Â Â Â Â \(fl\) := âWaterâ
Triple Point Temperature: Â Â Â Â \(T_t := Props1SI("Ttriple",\ fl) = 273.15\)
Triple Point Pressure: Â Â Â Â Â Â Â \(P_t := Props1SI("ptriple",\ fl) = 611.655\)
Critical Temperature: Â Â Â Â Â Â Â Â \(T_c := Props1SI("Tcrit",\ fl) = 647.096\)
Critical Pressure: Â Â Â Â Â Â Â Â Â Â Â \(P_c := Props1SI("pcrit",\ fl) = 2.206\cdot10^7\)
PhaseSI - Phase Determination#
The function is used to find the fluid phase at a specified state point. The calling structure of the function is the same as PropsSI except that no âOutputâ properties are specified, given that the only output returned is a âstringâ representing the phase of the fluid.:
PhaseSI("Input1", Val1, "Input2", Val2, "Fluid")
The input parameters are the same as for PropsSI, except there is no âOutputâ parameter as it is assumed to be âPhaseâ.
Note
The PropsSI function can be used directly with the output parameter âPhaseâ, but this returns an enumerated integer value for the phase. PhaseSI returns a string that represents the phase name for that enumerated value.
EXAMPLE:
Define a fluid: Â Â Â Â Â Â Â Â Â Â Â Â Â \(fl\) := âWaterâ
Triple Point Temperature: Â Â Â Â \(T_t := Props1SI("Ttriple",\ fl) = 273.15\)
Triple Point Pressure: Â Â Â Â Â Â Â \(P_t := Props1SI("ptriple",\ fl) = 611.655\)
Critical Temperature: Â Â Â Â Â Â Â Â \(T_c := Props1SI("Tcrit",\ fl) = 647.096\)
Critical Pressure: Â Â Â Â Â Â Â Â Â Â Â \(P_c := Props1SI("pcrit",\ fl) = 2.206\cdot10^7\)
Liquid points: Â Â Â Â Â Â \(T_L := mean(T_t,T_c)\ -\ 10.0\) Â Â & Â Â \(P_L := mean(P_t,P_c)\)
Calc: Â Â Â Â Â Â Â Â Â Â Â Â Â \(PhaseSI("T",\ T_L,\ "P",\ P_L,\ fl)\) = âLiquidâ
HAPropsSI - Humid Air Fluid Properties#
HA PropsSI is used to find fluid properties of humid air. The physics behind the function is based on the analysis in ASHRAE RP-1845, which is available online: https://www.tandfonline.com/doi/abs/10.1080/10789669.2009.10390874. It employs real gas properties for both air and water, as well as the most accurate interaction parameters and enhancement factors. RP-1845 is based largely on the IAPWS-95 formulation for the properties of water. The calling structure of the function is as follows:
HAPropsSI("Output", "Input1", Val1, "Input2", Val2, "Input3", Val3)
Where,
âOutputâ = Requested output property string; see Table of Valid HA Parameters.
âInput1â = First state-point property string.
Val1 = First state-point property value (scalar variable)
âInput2â = Second state-point property string.
Val2 = Second state-point property value (scalar variable)
âInput3â = Third state-point property string.
Val3 = Third state-point property value (scalar variable)
At least one of the inputs must be âTâ (dry bulb temperature), âRâ (Relative Humidity between 0.0 and 1.0), âWâ (Humidity Ratio), or âTdpâ (dew point).
EXAMPLE:
Enthalpy @ 50% Rel. Humidity:
\(h := HAPropsSI("H",\ "T",\ 298.15,\ "P",\ 101325,\ "R",\ 0.5) = 5.042\cdot10^4\)
Pseudo-Low-Level Functions#
CoolPropâs Low-level functions require the creation of an Abstract State object and then evaluation of properties using that objectâs member functions. Mathcad does not have the ability to store objects as variables directly, so these pseudo-Low-Level functions either do not require an abstract state object, or create one temporarily for the purposes of extracting and setting CoolProp data and parameters. These wrapper functions are listed here. (A true, persistent Low-Level interface is available; see Low-Level (AbstractState) Functions below, which represents the Abstract State object as a plain numeric handle instead.)
get_global_param_string#
This function retrieves global CoolProp parameters that are set and maintained by the CoolProp library.:
get_global_param_string("GlobalParameter")
Where âGlobalParameterâ can be one of the following:
âversionâ
âgitrevisionâ
âerrstringâ
âwarnstringâ
âFluidsListâ, âfluids_listâ, âfluidslistâ ²
âincompressible_list_pureâ ²
âincompressible_list_solutionâ ²
âmixture_binary_pairs_listâ ²
âparameter_listâ - Comma delimited list of valid fluid property strings used by
PropsSIâpredefined_mixturesâ ²
âHOMEâ - Userâs $HOME or %HOME% directory
âREFPROP_versionâ (if installed)
âcubic_fluids_schemaâ
âcubic_fluids_listâ
âpcsaft_fluids_schemaâ
Note
The "errstring" option is extremely useful when using CoolProp functions in Mathcad. While the wrapper functions attempt to trap common errors and display them as meaningful Mathcad error messages, highlighting the offending parameter(s), unknown errors will display as âCoolProp Issue: Use get_global_param_string(âerrstringâ) for more infoâ. This is the only way to see the actaul CoolProp error message being thrown, even if the error is already trapped by the Mathcad wrapper.
get_fluid_param_string#
This function retrieves fluid property information for a specific fluid/mixture and its behavior and implementation depend on the backend being used.:
get_fluid_param_string("Fluid", "FluidParameter")
Where,
âFluidâ is a fluid name string that follows the rules of of the fluid definition for
PropsSI, but is typically called for Pure Fluids.- âFluidParameterâ for the HEOS (default) backend can be any of the following strings:
ânameâ - Primary fluid name
âaliasesâ - Fluid alias names that can be used to reference the fluid
âCASâ - Unique, numerical identifier assigned by the Chemical Abstract Service
âformulaâ - Chemical formula of the specified fluid
âASHRAE34â - ASHRAE classification of refrigerant toxicity and flammability
âREFPROPnameâ - Equivalent fluid name in NIST REFPROP
âBibTeX-<ref>â -
âpureâ - returns âtrueâ for pure fluids, âfalseâ for mixtures
âINCHIâ - International Chemical Identifier representation for chemical structures
âINCHI_Keyâ - 27-character hashed string used for web searching
âSMILESâ - Simplified Molecular Input Line Entry System; compact, ASCII-based notation for representing 2D/3D chemical structures
âCHEMSPIDER_IDâ - unique ChemSpider database identifier
âJSONâ - Returns the full JSON definition of the fluid (not very useful in Mathcad)
set_reference_state#
Enthalpy and entropy are relative properties! Always compare differences rather than absolute values of the enthalpy or entropy to other sources. That said, if can be useful to set the reference state values for enthalpy and entropy to one of a few standard values. This is done by the use of the low-level set_reference_state function.:
set_reference_state("refState")
A number of pre-defined reference states (ârefSateâ) can be used:
IIR:        h = 200 kJ/kg, s = 1 kJ/kg/K at 0°C
ASHRAE:   h = 0, s = 0 @ -40°C saturated liquid
NBP: Â Â Â Â Â Â h=0, s=0, for saturated liquid at 1 atmosphere
DEF: Â Â Â Â Â Â Default reference state from the fluid file
Warning
The changing of the reference state should only be done
at the very beginning of your worksheet, or
at the very beginning of a Mathcad program block, resetting it to âDEFâ at the end of the program block
or unexpected results may occur. It is not recommended to change the reference state during the course of making calculations as done here for demonstration purposes only. Further more, because of Mathcadâs top-down calculation order, switching back and forth between reference states can lead to very unexpected results (real or apparent) and is not recommended.
get_predefined_mixture_fluids#
This is not a wrapper of a CoolProp functions, but an additional helper function use to assist using predefined mixtures. This function returns a semicolon delimited string of the predefined mixture component names.:
get_predefined_mixture_fluids("mixture")
Where âmixtureâ is a predefined mixture name ending in .mix or .MIX. Mixture names are case sensitive, using the available predefined mixture names retrieved from get_global_parameter_string("predefined_mixtures").
EXAMPLES
For air: Â Â Â Â \(get\_predefined\_mixture\_fluids("Air.mix")\) = âNITROGEN;ARGON;OXYGENâ
For R401A: Â \(get\_predefined\_mixture\_fluids("R401A.mix")\) = âR22;R152A;R124â
Note
A few predefined mixtures are missing binary interaction parameters for at least one component pair. These mixtures are defined, but cannot be used, for now, for property calculations.
get_predefined_mixture_fractions#
This is not a wrapper of a CoolProp functions, but an additional helper function use to assist using predefined mixtures. This function returns a Mathcad array (column vector) of the predefined mixture component mole fractions.:
get_predefined_mixture_fractions("mixture")
Where âmixtureâ is a predefined mixture name ending in .mix or .MIX. Mixture names are case sensitive, using the available predefined mixture names retrieved from get_global_parameter_string("predefined_mixtures").
EXAMPLES
For air: Â Â Â Â \(mf_{Air}\) := \(get\_predefined\_mixture\_fractions("Air.mix")\) = \(\begin{bmatrix} 0.7812\\ 0.0092 \\ 0.2096 \end{bmatrix}\)
For R401A: Â \(mf_{R401A}\) := \(get\_predefined\_mixture\_fractions("R401A.mix")\)
           \(mf_{R401A}\) = \(\begin{bmatrix} 0.578854 \\ 0.185871 \\ 0.235274 \end{bmatrix}\)
Note
A few predefined mixtures are missing binary interaction parameters for at least one component pair. These mixtures are defined, but cannot be used, for now, for property calculations.
get_mixture_binary_pair_data#
Get binary pair interaction parameters and other info for a pair of components:
get_mixture_binary_pair_data("CAS1", "CAS2", "mix_param")
Where,
âCAS1â, âCAS2â are the CAS identifiers for the two pure fluid components. These must be CAS numbers of the format â7782-44-7â and cannot be the fluid name (in this case âOxygenâ.
- âmix_paramâ can be any of the following parameters:
âname1â - first component name (corresponding to CAS1)
âname2â - second component name (corresponding to CAS2)
âBibTeXâ - Reference for interaction parameters
âfunctionâ - function for calculating parameters (if not constants)
âtypeâ - parameter model used
âFâ - \(F\) parameter (if used)
âxiâ - \(\xi\) parameter (if used)
âbetaTâ, âbetaVâ - \(\beta_{T,ij}\) and \(\beta_{v,ij}\)
âgammaTâ, âgammaVâ - \(\gamma_{T,ij}\) and \(\gamma_{v,ij}\)
âzetaâ - \(\zeta\) parameter
Note
Error message string from CoolProp may indicate that the input CAS numbers need to be reversed to retrieve values.
apply_simple_mixing_rule#
The function apply_simpl_mixing_rule() will take either CAS strings or fluid alias strings as inputs and can be set to either âlinearâ or the âLorentz-Berthelotâ mixing rules.:
apply_simple_mixing_rule("Fluid1", "Fluid2", "rule")
Use of this function follows the python example exactly on the Fluid Properties | Mixtures page and will not be repeated here.
Set_mixture_binary_pair_data#
Changes the default parameters with the following calls:
set_mixture_binary_pair_data("CAS1", "CAS2", "param", value)
Where,
âparamâ is any of the mixing parameters as defined above under
get_mixture_binary_pair_datavalue is the value of the parameter being set.
Use of this function follows the python example exactly on the Fluid Properties | Mixtures page and will not be repeated here.
Low-Level (AbstractState) Functions#
CoolPropâs Low-Level (AbstractState) API lets a caller build one persistent fluid/mixture state and reuse it for many flashes/outputs, avoiding the cost of reconstructing the backend for every call; this matters most for tabular backends (BICUBIC/TTSE), where construction alone can cost 80-140 ms. Since Mathcad cannot hold a C++ object as a worksheet variable, the state is represented here by a plain numeric handle (a real scalar): AS_factory creates the state and returns the handle; the other AS_* functions take that handle as their first argument.
Note
All Low-Level functions in the Mathcad wrapper are implemented with the two-letter prefix AS_ for AbstractState.
Getting call order right. Natively, Mathcad recalculates by dependency/region order, not top-to-bottom sequential code, so a handle must always be created before it is used. Worksheet calculations can be forced to use top-to-bottom, left-to-right calculation order; two patterns are supported (see warning below on multi-threading):
A Mathcad program block (Programming toolbar): create the handle, make however many
AS_props/AS_props_multicalls are needed (orAS_updatefollowed by as manyAS_getcalls as needed), and release it withAS_freeat the end, all as sequential statements in one program region. Recommended when the worksheet just needs one derived result.One
AS_factorycall near the top of a worksheet, referenced by many downstream calls/plots. Use Recalculate Worksheet (<Ctrl><F9>) (a full top-to-bottom recalculation in region order, not a partial/incremental recalc) to guarantee the factory call runs before anything that reads the handle. In this pattern, avoid callingAS_freefrom an independent call: nothing guarantees it runs after every reader of the handle.AS_factoryitself is memoized: recalculating it with the sameBackend/Fluidsreturns the SAME handle rather than rebuilding the backend, so repeatedly recalculating the same call neither leaks state nor pays construction cost again (any phase constraint from a priorAS_specify_phasecall is cleared on reuse, so an edited-away call canât leave it silently in effect; mixture fractions are not reset, sinceAS_set_mole_fractions/AS_set_mass_fractionsis always re-chained afterAS_factoryfor mixtures anyway).
Examples of both calling patterns are demonstrated below.
Warning
In both usage patterns, Mathcad Primeâs multi-threading feature must be disabled (this the the default state) or unexpected results can occur. Every AS_* call that touches a handle is internally serialized by the wrapper (one global lock, held for the whole call), so that Low-Level API calls with Mathcad Primeâs Multithreaded Calculations setting enabled will not crash. However, multi-threading should be disabled to avoid unexpected results that can arise from dependency based re-calculations. A guard is used to ensure that existing abstract states are reused and not duplicated when AS_factory calls are recalculated.
AS_factory#
Creates a persistent Low-Level fluid/mixture state and returns a handle.:
AS_factory("Backend", "Fluids")
Where,
âBackendâ is the backend to use, e.g. âHEOSâ, âREFPROPâ, âBICUBIC&HEOSâ.
âFluidsâ is a
&-delimited list of fluids, e.g. âWaterâ or âMethane&Ethaneâ.
Note
Calling this again with the same âBackendâ/âFluidsâ returns the SAME handle rather than rebuilding the backend, so recalculating this call repeatedly (every worksheet recalculation re-executes it) neither leaks state nor pays construction cost again. Any phase constraint set by a prior AS_specify_phase call is cleared on reuse, so removing/changing that call in the worksheet canât leave a stale constraint in effect.
EXAMPLE:
\(h := AS\_factory("HEOS",\ "Water")\)
AS_set_mole_fractions / AS_set_mass_fractions#
Sets a mixture handleâs composition explicitly, in the stated basis.:
AS_set_mole_fractions(Handle, Fractions)
AS_set_mass_fractions(Handle, Fractions)
Where,
Handle is a handle returned by
AS_factory.Fractions is a column vector of mole (or mass) fractions, one per fluid in the mixture.
EXAMPLE:
\(hMix := AS\_factory("HEOS",\ "Methane\&Ethane")\)
\(hMix := AS\_set\_mole\_fractions(hMix,\ \begin{bmatrix} 0.5\\ 0.5 \end{bmatrix})\)
Note
Why it echoes Handle back: Both return Handle unchanged. Reassign it, e.g. h := AS_set_mole_fractions(h, x), so a downstream call that uses this callâs return value as its own Handle argument is guaranteed to run after this one.
Note
Fraction basis is caller-specified, not auto-detected: several backends (HEOS, REFPROP, Cubics, PCSAFT, Incompressible) accept either basis, via distinct, fully-implemented conversions on the underlying AbstractState: there is no single ânativeâ basis to infer. Call whichever of the two functions matches the composition you actually have on hand; use AS_mole_to_mass_fractions/AS_mass_to_mole_fractions below to convert first if you only have the other basis.
Note
Input validation: Both functions validate: that Fractions has exactly one entry per fluid in the handleâs mixture; that the entries sum to 1.0 (within 1e-6); and that the handle is actually a mixture in the first place. Calling either on a pure-fluid handle is a Custom Error, not a silent no-op.
AS_mole_to_mass_fractions / AS_mass_to_mole_fractions#
Converts an arbitrary composition between mole and mass fractions, using a Low-Level state handleâs mixture for component identities and molar masses. Unlike AS_set_mole_fractions/AS_set_mass_fractions, this doesnât read or write the handleâs own state at all: itâs a pure unit conversion on the MoleFractions/MassFractions argument, useful as a preprocessing step before AS_set_mole_fractions/AS_set_mass_fractions (e.g. converting a mass-basis composition you have on hand into the mole fractions AS_set_mole_fractions expects).:
AS_mole_to_mass_fractions(Handle, MoleFractions)
AS_mass_to_mole_fractions(Handle, MassFractions)
Where,
Handle is a handle returned by
AS_factory: only its mixtureâs component identities and molar masses are used; its own composition/state is untouched.MoleFractions/MassFractions is a column vector of the fractions to convert, one entry per fluid in the mixture, in either basis.
EXAMPLE:
\(hMix := AS\_factory("HEOS",\ "Methane\&Ethane")\)
\(xMole := \begin{bmatrix} 0.5\\ 0.5 \end{bmatrix}\)
\(hMix := AS\_set\_mole\_fractions(hMix,\ xMole)\)
\(xMass := AS\_mole\_to\_mass\_fractions(hMix, xMole) = \begin{bmatrix} 0.348\\ 0.652 \end{bmatrix}\)
\(AS\_mass\_to\_mole\_fractions(hMix, xMass) = \begin{bmatrix} 0.5\\ 0.5 \end{bmatrix}\)
Note
No new CoolPropLib export: the C++ API has a direct equivalent of this (AbstractState::calc_mass_fractions(), computing mass_i = mm_i * mole_i / sum(mm_j * mole_j) from whatever mole fractions are already set), but it isnât exposed through the public Low-Level C API this wrapper is built on, and adding it there was deliberately avoided. This function gets the same result a different way: AbstractState_fluid_names() (already used by AS_set_mole_fractions/AS_set_mass_fractions above) gives the component names, and Props1SI("molar_mass", name), a plain, handle-independent lookup already used elsewhere in this wrapper, resolves each oneâs molar mass. Both are already-public surface; nothing new was added to CoolPropLib.h for this.
Note
Self-normalizing: the conversion divides by the actual weighted sum of the input (sum(mm_j * mole_j) or sum(mass_j / mm_j)), not by an assumed 1.0, so a composition that doesnât already sum to exactly 1.0 still converts to a correctly-normalized result in the other basis, unlike AS_set_mole_fractions/AS_set_mass_fractions, which require their input to already sum to 1.0. That weighted sum does need to be nonzero, though: an all-zero (or exactly canceling) input (reachable even for a pure fluid via MoleFractions = [0]) is reported as a Custom Error rather than silently dividing by zero into a NaN result.
AS_specify_phase#
Imposes a fixed phase on a Low-Level state handle for all subsequent updates (AS_update, AS_props, AS_props_multi). Call this before any of those, once per handle. Returns Handle unchanged, so a downstream Low-Level call that uses this callâs return value as its own Handle argument depends on it.:
AS_specify_phase(Handle, Phase)
Where,
Handle is a handle returned by
AS_factory.Phase is a phase name (case sensitive): âphase_liquidâ, âphase_gasâ, âphase_twophaseâ, âphase_supercriticalâ, âphase_supercritical_gasâ, âphase_supercritical_liquidâ, âphase_critical_pointâ, âphase_unknownâ, or âphase_not_imposedâ (
CoolProp::phasesinDataStructures.h).
AS_unspecify_phase#
Removes a phase imposed by AS_specify_phase from a Low-Level state handle. Returns Handle unchanged.:
AS_unspecify_phase(Handle)
Where,
Handle is a handle returned by
AS_factory.
AS_get_phase#
The read-only complement to AS_specify_phase/AS_unspecify_phase. Returns the phase in which the handleâs current point resides as a string; one of the same "phase_..." values AS_specify_phaseâs Phase argument accepts.:
AS_get_phase(Handle, Trigger)
Where,
Handle is a handle returned by
AS_factory.Trigger is unused. Just pass a dummy integer (
0), or seeAS_mole_fractions_liquidâs note onTriggerfor a better choice.
Note
Why this is useful: confirms whether the current point is actually in the two-phase region before calling AS_get_sat_liquid/AS_get_sat_vapor/AS_mole_fractions_liquid/AS_mole_fractions_vapor rather than relying on those raising a Custom Error (LOWLEVEL_ERROR) to find out after the fact.
AS_free#
Releases a Low-Level state handle created by AS_factory. Calling this function is optional as unreleased handles are automatically cleaned up when Mathcad closes. It is intended for use as the last statement of a Mathcad program block (see above).:
AS_free(Handle)
AS_param_index#
Resolves an output parameter name (e.g. âTâ, âDmolarâ, âHmassâ) to the integer index AS_props/AS_props_multi expect. Resolve once and reuse the result, rather than passing the name string on every call.:
AS_param_index("Name")
Note
This function only needs to be called once anywhere in the worksheet, not once per program block. Its result is an ordinary Mathcad variable, so it can be defined at worksheet scope and referenced from any number of program blocks or independent math regions; it is not limited to use as a local variable inside a single Mathcad program structure.
AS_input_pair_index#
Resolves an input pair name (e.g. âPT_INPUTSâ, âHmassP_INPUTSâ) to the integer index AS_props/AS_props_multi expect.:
AS_input_pair_index("Name")
Note
Like AS_param_index, this function only needs to be called once anywhere in the worksheet and the result reused throughout. It is not limited to setting a local variable within a single Mathcad program structure.
For the full list of valid input pair names, see the CoolProp::input_pairs enum in the CoolProp source documentation.
AS_generate_update_pair#
The reverse direction from AS_input_pair_index. Given two output-parameter indices, in either order, it resolves which named input pair they form and returns that name as a string, for further use with AS_input_pair_index/AS_update/AS_props/AS_props_multi.:
AS_generate_update_pair(ParamIdx1, ParamIdx2)
Where,
ParamIdx1, ParamIdx2 are output parameter indices from
AS_param_index, in either order.
Raises a Custom Error if the two parameters donât form any known input pair.
Note
No Handle argument: unlike the other Low-Level functions, this one takes no Handle: CoolProp::generate_update_pair() (the function this wraps) is a pure lookup over the two parameter keys, not tied to any particular fluid/mixture state.
Note
No value arguments: generate_update_pair()âs own signature takes two additional values alongside the two keys, but its pair-selection logic (a long chain of key-only comparisons) never inspects them. They exist solely to get copied into its out1/out2 parameters in the resolved pairâs order, which this function doesnât surface anyway (a Mathcad Custom Function returns one value, and this one returns the resolved name). Passing values through for no purpose would just be dead arguments, so this function only takes the two indices, calling generate_update_pair() with dummy placeholder values internally. The resolved name itself already answers the ordering question out1/out2 exist for: e.g. "PT_INPUTS" unambiguously means pressure first, temperature second, regardless of which order ParamIdx1/ParamIdx2 were supplied in.
AS_update#
Updates a Low-Level state handle to a new state point without returning any output. Returns Handle unchanged, so a downstream Low-Level call that uses this functionâs return value as its own Handle argument depends on it. Pair with AS_get to update once and then read as many outputs as needed with separate calls, without re-running the flash for each one; an alternative to AS_props/AS_props_multi when many outputs are wanted from the same point.:
AS_update(Handle, InputPairIdx, Value1, Value2)
Where,
Handle is a handle returned by
AS_factory.InputPairIdx is an input pair index from
AS_input_pair_index.Value1, Value2 are the two input property values for that input pair.
AS_get#
Returns one output parameter from a Low-Level state handleâs current point, i.e. whatever AS_update (or AS_props) last set it to.:
AS_get(Handle, ParamIdx)
Where,
Handle is a handle returned by
AS_factory.ParamIdx is an output parameter index from
AS_param_index.
EXAMPLE 1 (Independent Equations - ):
Pressure and Quality at 101325 Pa, 1 kg/kg (saturated vapor), updating once and reading two outputs. This is risky. Use <Ctrl><F9> to recalculate entire worksheet:
\(h := AS\_factory("HEOS",\ "Water")\)
\(iPQ := AS\_input\_pair\_index("PQ\_INPUTS")\)
\(iT := AS\_param\_index("T")\)
\(i\rho := AS\_param\_index("Dmolar")\)
\(h := AS\_update(h,\ iPQ,\ 101325,\ 1)\)
\(T := AS\_get(h,\ iT) = 373.1\)
\(\rho := AS\_get(h,\ i\rho)\)
EXAMPLE 2 (Program Block):
Pressure and Quality at 101325 Pa, 1 kg/kg (saturated vapor), updating once and reading two outputs:
\(\begin{bmatrix} T\\ \rho \end{bmatrix} := \left\Vert \begin{array}{l} h \leftarrow AS\_factory("HEOS",\ "Water") \\ P \leftarrow 101325.0 \\ Q \leftarrow 1.0 \\ iPQ \leftarrow AS\_input\_pair\_index("PQ\_INPUTS") \\ iT \leftarrow AS\_param\_index("T") \\ i\rho \leftarrow AS\_param\_index("Dmolar") \\ h := AS\_update(h,\ iPQ,\ P,\ Q) \\ Dmolar \leftarrow AS\_get(h,\ i\rho) \\ T \leftarrow AS\_get(h,\ iT) \\ AS\_free(h) \\ return\ \begin{bmatrix} T\\ Dmolar \end{bmatrix} \end{array} \right.\)
\(T = 373.1\)
\(\rho = 33.175\)
Within the program block above, the handle (h) and all other variables local and donât exist outside the Program Block. The equation steps in the Program Block are ALWAYS called in top-down order. Even the abstract state is created and freed within the Program Block. The program returns a vector containing the calculated values for T and Dmolar.
AS_get_sat_liquid / AS_get_sat_vapor#
Like AS_get above, but read the saturated liquid/vapor side of the handleâs current point rather than the bulk state, meaningful when the current point is in the two-phase region, e.g. after a Q (quality)-based update.:
AS_get_sat_liquid(Handle, ParamIdx)
AS_get_sat_vapor(Handle, ParamIdx)
Where,
Handle is a handle returned by
AS_factory.ParamIdx is an output parameter index from
AS_param_index.
AS_get_mole_fractions#
The handleâs current bulk mole fractions, as a column vector (whatever AS_set_mole_fractions/AS_set_mass_fractions last set, or the trivial [1] for a pure fluid). Distinct from AS_mole_fractions_liquid/AS_mole_fractions_vapor below, which read the saturated liquid/vapor side of a two-phase point, not the overall composition.:
AS_get_mole_fractions(Handle, Trigger)
Where,
Handle is a handle returned by
AS_factory.Trigger is unused. Just pass a dummy integer (
0), or see the note below for a better choice.
AS_mole_fractions_liquid / AS_mole_fractions_vapor#
The saturated liquid/vapor sideâs mole fractions at the handleâs current point, as a column vector.:
AS_mole_fractions_liquid(Handle, Trigger)
AS_mole_fractions_vapor(Handle, Trigger)
Where,
Handle is a handle returned by
AS_factory.Trigger is unused. Just pass a dummy integer (
0), or see the note below for a better choice.
Requires the current point to actually be in the two-phase region (0 <= quality <= 1); raises a Custom Error otherwise.
Note
Why Trigger, when Handle is already an argument: this is not about satisfying Mathcadâs one-argument minimum. Handle already does that on its own. The real reason is that Handleâs own value never changes when the AbstractState it names is mutated in place: AS_update, AS_props, and AS_specify_phase all echo Handle back unchanged, by design (see AS_updateâs entry above). So an equation whose only input is Handle gives Mathcadâs dependency graph nothing to key a recalculation on when the underlying point moves. Wire Trigger to whatever value actually drives the state you want reflected here (e.g. the quality or mole-fraction value fed into the AS_update/AS_props call that put the state in the two-phase region this function reads), and this equation re-evaluates whenever that does, instead of needing a full Recalculate Worksheet. If this equation already references the freshly-reassigned Handle from that same update (the normal chaining idiom), that alone may already provide the dependency edge; Trigger is the explicit fallback for call shapes where it doesnât.
AS_props#
Updates a Low-Level state handle for one input point and returns one output value.:
AS_props(Handle, InputPairIdx, Value1, Value2, ParamIdx)
Where,
Handle is a handle returned by
AS_factory.InputPairIdx is an input pair index from
AS_input_pair_index.Value1, Value2 are the two input property values for that input pair.
ParamIdx is an output parameter index from
AS_param_index.
EXAMPLE:
Temperature at 101325 Pa, 1 kg/kg quality (saturated vapor):
\(h := AS\_factory("HEOS",\ "Water")\)
\(iPQ := AS\_input\_pair\_index("PQ\_INPUTS")\)
\(iT := AS\_param\_index("T")\)
\(T := AS\_props(h,\ iPQ,\ 101325,\ 1,\ iT) = 373.1\) // Similar to high-level PropsSI call
AS_props_multi#
Updates a Low-Level state handle for a range of input points and returns up to 5 requested output parameters as a table (one row per input point, one column per requested output) in a single call: the function to use when evaluating many state points against the same fluid/mixture, since it evaluates the whole array with one native flash loop rather than one Mathcad call per point.:
AS_props_multi(Handle, InputPairIdx, Value1Array, Value2Array, ParamIdxArray)
Where,
Handle is a handle returned by
AS_factory.InputPairIdx is an input pair index from
AS_input_pair_index.Value1Array, Value2Array are column vectors of the two input property values, one row per point (both must be the same length).
ParamIdxArray is a column vector of 1 to 5 output parameter indices from
AS_param_index.
AS_build_phase_envelope#
Traces the phase envelope (dew/bubble curve) for a Low-Level state handle. Call once before AS_get_phase_envelope_data on that handle. Returns Handle unchanged, so a downstream Low-Level call that uses this callâs return value as its own Handle argument depends on it.:
AS_build_phase_envelope(Handle, Level)
Where,
Handle is a handle returned by
AS_factory.Level (string) controls how much extra refining is done between traced points:
"none"(CoolPropâs own recommendation; skips refining),"fine"(default tolerances; any value other than"none"/"veryfine"behaves the same way), or"veryfine"(tighter tolerances, more points).
AS_get_phase_envelope_data#
Returns the phase envelope traced by AS_build_phase_envelope as a table: one row per point, columns T, P, rhomolar_vap, rhomolar_liq, matching the fields returned by the C++/Python get_phase_envelope_data interface, minus the per-component compositions (see the note below).:
AS_get_phase_envelope_data(Handle, Trigger)
Where,
Handle is a handle returned by
AS_factory, after a priorAS_build_phase_envelopecall.Trigger is unused. Just pass a dummy integer (
0), or seeAS_mole_fractions_liquidâs note above for a better choice.
Raises a Custom Error if AS_build_phase_envelope hasnât been called yet for this Handle.
Note
Compositions not included: the C++/Python interfaceâs x/y per-component compositions (an N x Ncomp matrix per phase) are not part of this table: that would be a meaningfully different, mixture-size-dependent shape. Not implemented for now; a dedicated getter could be added later if needed.
Note
Cricondentherm / cricondenbar: see AS_pe_tmax/AS_pe_pmax below.
AS_pe_tmax#
The cricondentherm (the point on the phase envelope traced by AS_build_phase_envelope with the highest temperature), as a 2-element column vector [T; P].:
AS_pe_tmax(Handle, Trigger)
Where,
Handle is a handle returned by
AS_factory, after a priorAS_build_phase_envelopecall.Trigger is unused. Just pass a dummy integer (
0), or seeAS_mole_fractions_liquidâs note above for a better choice.
Raises a Custom Error if AS_build_phase_envelope hasnât been called yet for this Handle.
Note
How this is computed: CoolProp tracks this same point internally while tracing the envelope (PhaseEnvelopeData::iTsat_max, set in PhaseEnvelopeRoutines::finalize()), but doesnât expose it through the public Low-Level C API this wrapper is built on. Extending that shared surface (used by every CoolProp wrapper, not just Mathcadâs) is out of scope here. Instead, this function fetches the same table AS_get_phase_envelope_data returns and scans its T column for the max, entirely on the Mathcad-wrapper side.
Note
Exactness: for most mixtures (âType Iâ, where the traced curveâs pressure rises to a single peak then falls), CoolProp doesnât just pick the closest already-traced point for the cricondentherm: it fits a spline through the nearby points, solves for where \(dT_{sat}/dP_{sat} = 0\), and inserts that exact solved point into the envelope. Since that insertion happens before this wrapper ever sees the data, the max-scan above lands on that same exact point. For other mixtures (âType IIâ), no such insertion happens, and the result is only as good as how finely the curve was traced. See AS_build_phase_envelopeâs Level argument to trace more finely if that matters.
AS_pe_pmax#
The cricondenbar (the point on the phase envelope traced by AS_build_phase_envelope with the highest pressure), as a 2-element column vector [T; P].:
AS_pe_pmax(Handle, Trigger)
Where,
Handle is a handle returned by
AS_factory, after a priorAS_build_phase_envelopecall.Trigger is unused. Just pass a dummy integer (
0), or seeAS_mole_fractions_liquidâs note above for a better choice.
Raises a Custom Error if AS_build_phase_envelope hasnât been called yet for this Handle.
See AS_pe_tmaxâs notes above: both functions work identically, this one scanning P instead of T (CoolPropâs internal counterpart is PhaseEnvelopeData::ipsat_max).
AS_backend_name#
The same short backend string (e.g. "HEOS", "REFPROP", "BICUBIC&HEOS") originally passed to AS_factoryâs Backend argument for this Handle.:
AS_backend_name(Handle, Trigger)
Where,
Handle is a handle returned by
AS_factory.Trigger is unused. Just pass a dummy integer (
0), or seeAS_mole_fractions_liquidâs note above for a better choice.
Note
Why this doesnât just call AbstractState::backend_name(): The C++/C API call returns CoolPropâs internal implementation class name for the backend (get_backend_string() in src/DataStructures.cpp maps, e.g., the enum for "HEOS" to the string "HelmholtzEOSMixtureBackend"). This is correct, but reads as an implementation detail to a Mathcad user expecting the same short string they typed into AS_factory. Recovering that short string from the long one would require CoolPropâs backend-family lookup tables, which (unlike the phase and input-pair short-description lookups this wrapper already uses elsewhere) are private to DataStructures.cpp with no public header declaring them. Simpler and more direct: the Mathcad wrapperâs own handle registry already remembers the short string verbatim (itâs the âBackendâ half of the âBackend|Fluidsâ key this Handle was registered under), so this function recovers it from there instead. AbstractState_backend_name() is still called first, purely so this function validates a dead Handle exactly like every other AS_* function does.
Note
Redundant with AS_list_states, mostly: AS_list_states already reports the short form for every currently-open handle at once, as the "Backend|Fluids" half of its key. This function is a convenience when you only have one specific Handle in scope and donât want to fetch and parse the whole registry listing just to confirm it.
AS_list_handles / AS_list_states#
An introspection pair (mainly useful for debugging) that lists every Low-Level state currently open anywhere in the worksheet, i.e. every live handle from an AS_factory call that hasnât been released via AS_free (or superseded by a later call to AS_factory with the same Backend/Fluids, per its memoization).:
AS_list_handles(Trigger)
AS_list_states(Trigger)
Where,
Trigger is unused by either function: Mathcad Custom Functions require at least one argument, and there is no argument that naturally belongs to a whole-registry snapshot, so this exists only to satisfy that requirement. Any real scalar works, e.g. a literal
0.
AS_list_handles returns a column vector of the currently-live handles; AS_list_states returns their "Backend|Fluids" keys (the same string AS_factoryâs two arguments were joined into) as one ";"-delimited string, in the same order. Both raise a Custom Error if no Low-Level states are currently open. A handle released via AS_free (or otherwise gone dead) is dropped from the listing automatically; neither function ever reports a stale handle.
Note
Why two functions: a Mathcad Custom Function can only return one value (either a complex array or a string, never both), so this is the same array-plus-parallel-string pairing already used by get_predefined_mixture_fluids/get_predefined_mixture_mole_fractions above, applied to the Low-Level registry instead of a predefined mixture.
Note
Ordering guarantee: the two functions independently snapshot the same underlying registry, ordered by its "Backend|Fluids" key: an order that depends only on which keys are currently registered, not on when each snapshot was taken. Two calls placed on the same worksheet will therefore agree, unless an AS_factory/AS_free call is evaluated in between them within the same recalculation pass.
Note
Using Trigger for recalculation: since Triggerâs value is otherwise ignored, wiring it to a handle already on the sheet (rather than a bare literal) gives Mathcad a real dependency edge, so the call re-runs whenever that handleâs defining equation does. Without that, use Recalculate Worksheet to refresh these two calls, since they otherwise have no dependency edge to anything that changed. This just helps to keep regions updated properly outside of the two supported recalcualtion usage patterns, especially when updating or entering equation calls mid-stream.
Configuration Functions#
Get/set access to CoolPropâs process-wide Configuration: the same settings the Python CoolProp.CoolProp.get_config_bool/set_config_bool family (and its int/double/string counterparts) exposes, e.g. NORMALIZE_GAS_CONSTANTS, TABULAR_NX/TABULAR_NY, ALTERNATIVE_REFPROP_PATH, PHASE_ENVELOPE_STARTING_PRESSURE_PA. These apply to both the High-Level and Low-Level functions; they are deliberately not prefixed with AS_.
Note
Every configuration key is typed at registration as exactly one of bool/int/double/string (see Configuration for the full, authoritative list of names, types, defaults, and descriptions). Mathcad has no tagged/variant type, so there are four type-specific getter/setter pairs, each committing to one return type, rather than one generic pair.
Warning
Each configuration key can only be *set* once per Mathcad Prime session
This is a deliberate design constraint, not a bug. Every configuration key is one process-wide value, shared by every worksheet open in that Mathcad Prime instance/window, and by every worksheet subsequently opened in it, until that Mathcad process exits and the Custom Function DLL is unloaded. (Separate Mathcad Prime instances on the same machine are unaffected; each loads its own copy of the DLL with its own independent CoolProp configuration.) Combined with Mathcadâs dependency-graph recalculation order (region/dependency order, not top-to-bottom source order, and not guaranteed to be stable across recalculations or across multiple worksheets), letting every config_set_* call freely overwrite a key would let a call in one worksheet silently change results in all open worksheets in the same session.
Instead, the first config_set_* call to actually reach a given key in a session wins, and that value sticks for the rest of the session:
A later call passing the same value to which that key was already set also returns
"Set": this is what makes it safe to recalculate the sameconfig_set_*statement in a worksheet over and over.A later call passing a different value does not change the configuration: the first value stays in effect. It returns the Mathcad string
"Not Set"(a plain return value, not a Custom Error; it wonât interrupt worksheet evaluation with a red error box), and also raises a CoolProp warning readable viaget_global_param_string("warnstring"), naming the key, the value that was ignored, and the value actually in effect.
This does not make which open worksheet wins deterministic: that still depends on Mathcadâs recalculation order, not on anything in either worksheetâs own contents. What it buys is that a conflict is now detectable (a different return string, plus an inspectable warning) instead of one worksheetâs setting silently overwriting anotherâs. A config_set_* call whose return value isnât captured or checked wonât visibly show that it lost: check the return, or check get_global_param_string("warnstring"), to find out.
Tip
RECOMMENDATION: When changing a CoolProp setting away from its default with Mathcad set functions,
keep only one worksheet open at a time in that Mathcad Prime window/session,
set each configuration key value only once at the top of the worksheet.
To change a configuration setting permanently, across every worksheet and every session, use the environment variable method explained below.
Warning
Set configuration before evaluating properties, not during. config_set_* only guards itself against other config_set_*/config_get_* calls; it does not hold up PropsSI, PropsSImulti, HAPropsSI, or any AS_* call, all of which also read this same global configuration. Do your config_set_* calls once, at the top of a worksheet (or in the setup portion of a program block), before any property calculation runs, then leave the configuration alone for the rest of the session. Calling a setter for a key while a property calculation that reads that key is still in flight is not something this wrapper protects against.
Placing the setter at the top of the worksheet isnât enough on its own, though: Mathcadâs automatic recalculation follows the dependency graph, not source order (the same caveat as AS_factoryâs worksheet-level pattern above), so an independent property call with no dependency edge back to the setter could still evaluate before it on a given pass. Once the setter has actually run once, its value is applied for the rest of the session regardless of order; to guarantee that first run happens before anything below it reads the result, use Recalculate Worksheet (a full top-to-bottom recalculation in region order, not a partial/incremental recalc) after adding or changing a config_set_* call, the same way AS_factoryâs own pattern already relies on it.
Tip
USING ENVIRONMENT VARIABLES TO SET CONFIGURATION
For a value that should hold for the whole session regardless of worksheet ordering, prefer an environment variable instead. CoolProp supports this natively: set a Windows environment variable named COOLPROP_ followed by the key name before launching Mathcad Prime, e.g.
COOLPROP_MIXTURE_STABILITY_ALGORITHM = 1
That value is read exactly once, when CoolProp loads, before any worksheetâs calculations run, so every worksheet in the session starts with it already applied to that key.
This only sets the starting value, though; it doesnât lock the key. A worksheetâs own config_set_* call for that same key still claims it on its first run, same as it would for any other starting value, and can change it away from what the environment variable set. If youâre relying on an environment variable to hold a value for the whole session, donât also call the matching setter for that key anywhere in your worksheets.
The four getters below (and get_config_as_json_string) are useful for confirming an environment variable actually took effect.
Note
Two keys are read-only from Mathcad, unconditionally: every config_set_* function refuses "FLOAT_PUNCTUATION" and "LIST_STRING_DELIMITER" with a Custom Error, independent of the once-per-session logic above: both are relied on by this wrapperâs own string parsing (FLOAT_PUNCTUATION controls the decimal separator CoolProp uses when formatting/parsing numbers in strings; LIST_STRING_DELIMITER is the separator this wrapper already assumes when splitting a Low-Level handleâs fluid-name list; see AS_mole_to_mass_fractions above), so changing either at runtime, even once, would silently corrupt string parsing elsewhere in this same wrapper. Both remain readable via config_get_bool/config_get_string.
config_get_bool / config_set_bool#
Reads/sets a boolean configuration value.:
config_get_bool(Key)
config_set_bool(Key, Value)
Where,
Key is the configuration key name, e.g.
"NORMALIZE_GAS_CONSTANTS","CRITICAL_SPLINES_ENABLED","SAVE_RAW_TABLES".Value (
config_set_boolonly) must be exactly1or0: Mathcad has no boolean type, and this wrapper uses Mathcadâs1/0convention for âtrueâ/âfalseâ.
config_get_bool returns 1 or 0. config_set_bool returns "Set" or "Not Set" (see the once-per-session warning above).
Note
Only Exact Integers Accepted: a Value other than exactly 1 or 0 (e.g. 2, 0.5, -1) is a Custom Error.
config_get_int / config_set_int#
Reads/sets an integer configuration value.:
config_get_int(Key)
config_set_int(Key, Value)
Where,
Key is the configuration key name, e.g.
"TABULAR_NX","TABULAR_NY","SVDSBTL_SAMPLING_THREADS","MIXTURE_STABILITY_ALGORITHM".Value (
config_set_intonly) is rounded to the nearest integer.
config_get_int returns the integer value as a real scalar. config_set_int returns "Set" or "Not Set" (see the once-per-session warning above).
Note
Value validation: Value is validated with the same finite-and-in-range checked conversion the Low-Level APIâs Handle and Index arguments use (see AS_update above) before rounding. A non-finite Value, or one too large to represent as a 32-bit integer, returns a Custom Error. Runs before the once-per-session claim logic, same as config_set_boolâs check above.
Note
One int key only accepts a small, documented set of legal values: MIXTURE_STABILITY_ALGORITHM is genuinely a 2-way choice: either 0 (Legacy) or 1 (Michelsen, the default). Any other Value returns a Custom Error with a fixed message naming both legal choices. Checked in two stages, in this order: first, is Value an exact whole number at all (checked against the RAW value, before any rounding, so 0.5 (which would otherwise round to the legal choice 1) is caught here); only once that passes is it checked against the legal set itself.
Note
``REFPROP_ERROR_THRESHOLD`` is deliberately NOT restricted this way: unlike MIXTURE_STABILITY_ALGORITHM, it isnât a small enumerated choice; itâs a threshold compared (ierr > REFPROP_ERROR_THRESHOLD) against REFPROPâs own ierr output across many internal Fortran subroutines. The sign carries the primary meaning (negative ierr = warning-only, positive = hard error), and specific magnitudes are assigned per-subroutine by REFPROP itself. Any finite, in-range integer is accepted (subject to the once-per-session claim/compare rule above).
config_get_double / config_set_double#
Reads/sets a double-valued configuration value.:
config_get_double(Key)
config_set_double(Key, Value)
Where,
Key is the configuration key name, e.g.
"R_U_CODATA","PHASE_ENVELOPE_STARTING_PRESSURE_PA","MAXIMUM_TABLE_DIRECTORY_SIZE_IN_GB","SPINODAL_MINIMUM_DELTA".Value (
config_set_doubleonly) must be finite.
config_get_double returns the value as a real scalar. config_set_double returns "Set" or "Not Set" (see the once-per-session warning above).
Note
Value validation: a non-finite Value (NaN or Infinity) returns a Custom Error, checked before the once-per-session claim logic.
config_get_string / config_set_string#
Reads/sets a string-valued configuration value.:
config_get_string(Key)
config_set_string(Key, Value)
Where,
Key is the configuration key name, e.g.
"ALTERNATIVE_REFPROP_PATH","ALTERNATIVE_TABLES_DIRECTORY","VTPR_UNIFAC_PATH".Value (
config_set_stringonly) is the string to set.
config_get_string returns the value as a Mathcad string. config_set_string returns "Set" or "Not Set" (see the once-per-session warning above).
Note
REFPROP path keys force a reload: setting ALTERNATIVE_REFPROP_PATH, ALTERNATIVE_REFPROP_HMX_BNC_PATH, or ALTERNATIVE_REFPROP_LIBRARY_PATH additionally forces REFPROP to unload (CoolProp::force_unload_REFPROP(), inside CoolProp::set_config_string() itself) so the next REFPROP call re-loads from the new path: handled underneath, and only happens on the one claiming call for that key in a session, not on every re-affirming recalculation.
Common Behavior Across All Set/Get Functions#
Note
Wrong-typed getter/setter: calling the getter/setter for the wrong value type on a given key (e.g. config_get_bool("TABULAR_NX"), an int-valued key) is a Custom Error, not a silent misread: CoolPropâs own ConfigurationItem already refuses this internally; this wrapper gives it a specific error code instead of letting it fall through to a generic one.
Note
Unrecognized key: a Key string that doesnât match any entry in CoolPropâs key list is a Custom Error on all eight functions.
get_config_as_json_string#
The four getters above read one key you already know the name of, committing to a fixed return type each, a poor fit for viewing the entire configuration at once. This function is a verbatim wrapper for CoolProp::get_config_as_json_string() instead: the same name Pythonâs CoolProp.CoolProp module already uses for it, since thereâs no per-key selection here to distinguish it from and reusing a name already familiar from the other bindings is the least surprising choice.:
get_config_as_json_string(Trigger)
Where,
Trigger is unused. Just pass a dummy integer (
0); this exists purely to satisfy Mathcadâs one-argument minimum, since this function has noKeyto use instead.
Returns every configuration key as one raw JSON object string, unmodified, e.g. {"NORMALIZE_GAS_CONSTANTS":true,"TABULAR_NX":200,...}.
Note
Mathcad has no native JSON viewer. For a readable, one-pair-per-line display, split this string on the , character following each key/value pair with a Mathcad user function (provided below) that inserts a Unicode line-break character (133) at each location. The DLL function canât embed a Unicode line-break character itself (Mathcad Prime decodes it byte-for-byte through the Windows-1252 codepage, with no Unicode awareness), so that step has to happen on the Mathcad side. See the worked example below.
EXAMPLE (get all config key values):
This function will format JSON string outputs for better display in Mathcad and only needs to be included once. This function will have to by typed in by hand as it canât be copied from here. There are alternate ways to do this, but this insert method works efficiently.
\(fmtJSON(str) := \left\Vert \begin{array}{l} v \leftarrow str2vec(str) \\ k \leftarrow 0 \\ l \leftarrow last(v) \\ for\ i \in 0 ... l \\ \left\Vert \begin{array}{l} res_k \leftarrow v_i \\ k \leftarrow k + 1 \\ if (v_i = 44)\wedge(v_{min(i + 2, l)} \ne 44) \\ \left\Vert \begin{array}{l} res_k \leftarrow 133 \\ res_{k + 1} \leftarrow 32 \\ k \leftarrow k + 2 \\ \end{array} \right\vert \\ \end{array} \right\vert \\ return\ vec2str(res) \\ \end{array} \right\vert\)
Call \(get\_config\_as\_json\_string\), formmating the output through the function above.
\(strJSON = fmtJSON(get\_config\_as\_json\_string(0))\)
\(strJSON = \begin{array}[t]{l} \{ "ALLOW_SVDSBTL\_IN\_PROPSSI":false, \\ \ \ "ALTERNATIVE\_REFPROP\_HMX\_BNC\_PATH":\ " ", \\ \ \ "ALTERNATIVE\_REFPROP\_LIBRARY\_PATH":\ " ", \\ \ \\ \ ... \\ \ \\ \ \ "VTPR\_ALWAYS\_RELOAD\_LIBRARY":false, \\ \ \ "VTPR\_UNIFAC\_PATH":" "\} \end{array}\)
This allows the user to view the state of the CoolProp configuration keys all at once. For an even better display of these settings, pass them to a multi-line, read-only, TextBox advanced control in Mathcad Prime 10 or later. The list will render in a sizable, scrollable text box window. In either case, setting the math style to a fixed spaced, 9 pt. font (Consolas or Courrier New) will provide clean output that fits on the single worksheet page.
Applying Mathcad Units to CoolProp Functions#
Mathcad has a built-in units system that allows variables and values to be defined with a specific set of units. However, Custom Functions provided through DLL add-ins are C++ functions and cannot handle Mathcadâs units on inputs or outputs to the functions. If using values with units, the appropriate unitless values in SI can be provided to the CoolProp function calls and the appropriate units applied ot the results.
Note
To strip units from a Mathcad variable, yet provide the numerical value scaled to a specific unit quantity, the a variable containing units can simply be divided by the desired units expression. The value will become unitless, but will be scaled to the specified units expression.
Example:
\(P_{psi} := 1 atm\)
\(P_{psi} / Pa\ =\ 101325\) Â Â Â (no units, but scaled to units of Pascals)
This is the technique used for plotting input ranges in a specific set of units using Mathcadâs 2D Chart Component.
A simple example of a call to PropsSI using variables with units is,
Define temperature (with units):    \(T\ :=\ 72\ °F\)
Define pressure (with units): Â Â Â Â Â Â \(P\ :=\ 1\ atm\)
Evaluate: Â Â Â \(h\ :=\ PropsSI("H",\ "T",\ \dfrac{T}{K},\ "P",\ \dfrac{P}{Pa},\ "Water")\cdot\dfrac{J}{kg}\)
Show \(h\) in English Engineering Units: Â Â Â \(h\ =\ 40.133\ \dfrac{BTU}{lb}\)
Note
Technically, if input variables are not âstrippedâ of units, they will be passed as values in Mathcadâs default Base Units, which are SI. This is compatible with CoolPropâs base units of SI and will work. However, units still have to be applied to the result and units should be stripped explicitely, as shown above since Mathcad allows the Base Units to be changed. This will guarantee consistency of units between Mathcad and CoolProp.