From 89f57111cf8a5390d35a54f052828a4ed71cd363 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Riedemann?= <38795484+longemen3000@users.noreply.github.com> Date: Sun, 1 Mar 2026 23:21:10 -0300 Subject: [PATCH 1/9] start of extension work --- Project.toml | 11 +++++-- ext/CoolPropUnitfulExt.jl | 57 ++++++++++++++++++++++++++++++++ src/CoolProp.jl | 69 ++++++++------------------------------- test/runtests.jl | 1 + 4 files changed, 80 insertions(+), 58 deletions(-) create mode 100644 ext/CoolPropUnitfulExt.jl diff --git a/Project.toml b/Project.toml index 8d3eb71..0846122 100644 --- a/Project.toml +++ b/Project.toml @@ -7,13 +7,20 @@ CoolProp_jll = "3351c21f-4feb-5f29-afb9-f4fcb0e27549" Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a" Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" +[weakdeps] +Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" + +[extensions] +CoolPropUnitfulExt = "Unitful" + [compat] CoolProp_jll = "6.6, 7.1" julia = "1.3" -Unitful="1" +Unitful = "1" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" [targets] -test = ["Test"] +test = ["Test", "Unitful"] diff --git a/ext/CoolPropUnitfulExt.jl b/ext/CoolPropUnitfulExt.jl new file mode 100644 index 0000000..d16a16b --- /dev/null +++ b/ext/CoolPropUnitfulExt.jl @@ -0,0 +1,57 @@ +module CoolPropUnitfulExt +using CoolProp +using Unitful + +# units for humid air +const _ha_units = Dict( + "Tdb" => Unitful.u"K", + "Twb" => Unitful.u"K", + "Tdp" => Unitful.u"K", + "D" => Unitful.u"K", + "H" => Unitful.u"J/kg", + "Hha" => Unitful.u"J/kg", + "U" => Unitful.u"J/kg", + "S" => Unitful.u"J/kg/K", + "V" => Unitful.u"m^3/kg", + "Vda" => Unitful.u"m^3/kg", + "Vha" => Unitful.u"m^3/kg", + "cp" => Unitful.u"J/kg/K", + "CV" => Unitful.u"J/kg/K", + "Cha" => Unitful.u"J/kg/K", + "CVha" => Unitful.u"J/kg/K", + "P_w" => Unitful.u"Pa", + ) + + + +function CoolProp._get_unit(param::AbstractString, is_ha::Bool,val::Unitful.Quantity) + # First check if it's a humid air parameter + if is_ha && haskey(_ha_units, param) + return _ha_units[param] + end + # Otherwise use the normal parameter info + unit_str = "-" + try + unit_str = CoolProp.get_parameter_information_string(param, "units") + catch + end + if unit_str == "-" + return Unitful.NoUnits + end + try + # The unit uses e.g. Pa-s to mean Pa*s + unit_str = replace(unit_str, "-" => "*") + parsed_unit = Unitful.uparse(unit_str) + if parsed_unit isa Unitful.Quantity + return Unitful.unit(parsed_unit) + end + return parsed_unit + catch err + @warn "Failed to parse unit $(unit_str): " err + end + return Unitful.NoUnits +end + +CoolProp._si_value(unit::Unitful.Units, value) = Unitful.ustrip(Unitful.uconvert(unit, value)) + +end #module \ No newline at end of file diff --git a/src/CoolProp.jl b/src/CoolProp.jl index 9a7b964..6cfe0bd 100644 --- a/src/CoolProp.jl +++ b/src/CoolProp.jl @@ -85,60 +85,17 @@ function PropsSI(output::AbstractString, name1::AbstractString, value1::Real, na return val end -# units for humid air -const _ha_units = Dict( - "Tdb" => Unitful.u"K", - "Twb" => Unitful.u"K", - "Tdp" => Unitful.u"K", - "D" => Unitful.u"K", - "H" => Unitful.u"J/kg", - "Hha" => Unitful.u"J/kg", - "U" => Unitful.u"J/kg", - "S" => Unitful.u"J/kg/K", - "V" => Unitful.u"m^3/kg", - "Vda" => Unitful.u"m^3/kg", - "Vha" => Unitful.u"m^3/kg", - "cp" => Unitful.u"J/kg/K", - "CV" => Unitful.u"J/kg/K", - "Cha" => Unitful.u"J/kg/K", - "CVha" => Unitful.u"J/kg/K", - "P_w" => Unitful.u"Pa", - ) - -function _get_unit(param::AbstractString, is_ha::Bool) - # First check if it's a humid air parameter - if is_ha && haskey(_ha_units, param) - return _ha_units[param] - end - # Otherwise use the normal parameter info - unit_str = "-" - try - unit_str = get_parameter_information_string(param, "units") - catch - end - if unit_str == "-" - return Unitful.NoUnits - end - try - # The unit uses e.g. Pa-s to mean Pa*s - unit_str = replace(unit_str, "-" => "*") - parsed_unit = Unitful.uparse(unit_str) - if parsed_unit isa Unitful.Quantity - return Unitful.unit(parsed_unit) - end - return parsed_unit - catch err - @warn "Failed to parse unit $(unit_str): " err - end - return Unitful.NoUnits +function _get_unit(param::AbstractString, is_ha::Bool, val::Real) + return _get_unit(param,is_ha,nothing) end -_si_value(unit, value) = Unitful.ustrip(Unitful.uconvert(unit, value)) +_get_unit(param::AbstractString, is_ha::Bool, ::Nothing) = true +_si_value(::Bool,value) = value -function PropsSI(output::AbstractString, name1::AbstractString, value1::Union{Unitful.Quantity,Real}, name2::AbstractString, value2::Union{Unitful.Quantity,Real}, fluid::AbstractString) - unit1 = _get_unit(name1,false) - unit2 = _get_unit(name2,false) - outunit = _get_unit(output,false) +function PropsSI(output::AbstractString, name1::AbstractString, value1::Number, name2::AbstractString, value2::Number, fluid::AbstractString) + unit1 = _get_unit(name1,false,value1) + unit2 = _get_unit(name2,false,value2) + outunit = _get_unit(output,false,value1*value2) return PropsSI(output, name1, _si_value(unit1,value1), name2, _si_value(unit2,value2), fluid)*outunit end @@ -713,11 +670,11 @@ function HAPropsSI(output::AbstractString, name1::AbstractString, value1::Real, return val end -function HAPropsSI(output::AbstractString, name1::AbstractString, value1::Union{Unitful.Quantity,Real}, name2::AbstractString, value2::Union{Unitful.Quantity,Real}, name3::AbstractString, value3::Union{Unitful.Quantity,Real}) - unit1 = _get_unit(name1,true) - unit2 = _get_unit(name2,true) - unit3 = _get_unit(name3,true) - outunit = _get_unit(output,true) +function HAPropsSI(output::AbstractString, name1::AbstractString, value1::Number, name2::AbstractString, value2::Number, name3::AbstractString, value3::Number) + unit1 = _get_unit(name1,true,value1) + unit2 = _get_unit(name2,true,value2) + unit3 = _get_unit(name3,true,value3) + outunit = _get_unit(output,true,value1*value2*value3) return HAPropsSI(output, name1, _si_value(unit1,value1), name2, _si_value(unit2,value2), name3, _si_value(unit3,value3))*outunit end diff --git a/test/runtests.jl b/test/runtests.jl index 3fe0876..e5c4db2 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,5 +1,6 @@ using CoolProp using Test +using Unitful include("testThrows.jl"); From 635a30ad8e568bb24cc62e42b6b49548a08a6059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Riedemann?= <38795484+longemen3000@users.noreply.github.com> Date: Sun, 1 Mar 2026 23:23:21 -0300 Subject: [PATCH 2/9] remove unitful include --- src/CoolProp.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/CoolProp.jl b/src/CoolProp.jl index 6cfe0bd..7e7ce32 100644 --- a/src/CoolProp.jl +++ b/src/CoolProp.jl @@ -1,7 +1,6 @@ #__precompile__() module CoolProp -import Unitful using CoolProp_jll #################################################################################################################### From eaff81f9b8f3763b0f90d6ab086584fcb4912619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Riedemann?= <38795484+longemen3000@users.noreply.github.com> Date: Sun, 1 Mar 2026 23:25:29 -0300 Subject: [PATCH 3/9] add include for backwards compat --- src/CoolProp.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/CoolProp.jl b/src/CoolProp.jl index 7e7ce32..9cdfdd4 100644 --- a/src/CoolProp.jl +++ b/src/CoolProp.jl @@ -1453,6 +1453,11 @@ for symorigin = [:PropsSI, :PhaseSI, :K2F, :F2K, :HAPropsSI, :AbstractState_fact @eval const $sym = $symorigin @eval export $sym, $symorigin end + +if !isdefined(Base, :get_extension) + include("../ext/CoolPropUnitfulExt.jl") +end + const set_reference_stateS = set_reference_state const set_reference_stateD = set_reference_state const set_config_string = set_config From 79632be30ba0bd1bea98039466fd7aec62fbc094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Riedemann?= <38795484+longemen3000@users.noreply.github.com> Date: Sun, 1 Mar 2026 23:32:36 -0300 Subject: [PATCH 4/9] fix error with affine units --- src/CoolProp.jl | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/CoolProp.jl b/src/CoolProp.jl index 9cdfdd4..38ce52d 100644 --- a/src/CoolProp.jl +++ b/src/CoolProp.jl @@ -94,8 +94,10 @@ _si_value(::Bool,value) = value function PropsSI(output::AbstractString, name1::AbstractString, value1::Number, name2::AbstractString, value2::Number, fluid::AbstractString) unit1 = _get_unit(name1,false,value1) unit2 = _get_unit(name2,false,value2) - outunit = _get_unit(output,false,value1*value2) - return PropsSI(output, name1, _si_value(unit1,value1), name2, _si_value(unit2,value2), fluid)*outunit + out = PropsSI(output, name1, _si_value(unit1,value1), name2, _si_value(unit2,value2), fluid) + unit1 == true && unit2 == true && (return out) + out1 != true && (return out*_get_unit(output,false,value1)) + return out*_get_unit(output,falsevalue2) end """ @@ -673,8 +675,11 @@ function HAPropsSI(output::AbstractString, name1::AbstractString, value1::Number unit1 = _get_unit(name1,true,value1) unit2 = _get_unit(name2,true,value2) unit3 = _get_unit(name3,true,value3) - outunit = _get_unit(output,true,value1*value2*value3) - return HAPropsSI(output, name1, _si_value(unit1,value1), name2, _si_value(unit2,value2), name3, _si_value(unit3,value3))*outunit + out = HAPropsSI(output, name1, _si_value(unit1,value1), name2, _si_value(unit2,value2), name3, _si_value(unit3,value3)) + unit1 == true && unit2 == true && unit3 == true && (return out) + unit1 != true && (return out*_get_unit(output,true,value1)) + unit2 != true && (return out*_get_unit(output,true,value2)) + return out*_get_unit(output,true,value3) end """ From def97de048a1e4082b924a84c2388ab09aedad56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Riedemann?= <38795484+longemen3000@users.noreply.github.com> Date: Sun, 1 Mar 2026 23:34:24 -0300 Subject: [PATCH 5/9] typo --- src/CoolProp.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CoolProp.jl b/src/CoolProp.jl index 38ce52d..8894b9e 100644 --- a/src/CoolProp.jl +++ b/src/CoolProp.jl @@ -97,7 +97,7 @@ function PropsSI(output::AbstractString, name1::AbstractString, value1::Number, out = PropsSI(output, name1, _si_value(unit1,value1), name2, _si_value(unit2,value2), fluid) unit1 == true && unit2 == true && (return out) out1 != true && (return out*_get_unit(output,false,value1)) - return out*_get_unit(output,falsevalue2) + return out*_get_unit(output,false,value2) end """ From 48d102b4562a2d70c5bacaa0916d21cdd27e3695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Riedemann?= <38795484+longemen3000@users.noreply.github.com> Date: Sun, 1 Mar 2026 23:40:14 -0300 Subject: [PATCH 6/9] typo --- src/CoolProp.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CoolProp.jl b/src/CoolProp.jl index 8894b9e..ec55026 100644 --- a/src/CoolProp.jl +++ b/src/CoolProp.jl @@ -96,7 +96,7 @@ function PropsSI(output::AbstractString, name1::AbstractString, value1::Number, unit2 = _get_unit(name2,false,value2) out = PropsSI(output, name1, _si_value(unit1,value1), name2, _si_value(unit2,value2), fluid) unit1 == true && unit2 == true && (return out) - out1 != true && (return out*_get_unit(output,false,value1)) + unit1 != true && (return out*_get_unit(output,false,value1)) return out*_get_unit(output,false,value2) end From 019edb2820cb7b740fc6b5a67be682888e280623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Riedemann?= <38795484+longemen3000@users.noreply.github.com> Date: Sun, 1 Mar 2026 23:47:02 -0300 Subject: [PATCH 7/9] fix test --- src/CoolProp.jl | 1 + test/testunits.jl | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/CoolProp.jl b/src/CoolProp.jl index ec55026..6724ef0 100644 --- a/src/CoolProp.jl +++ b/src/CoolProp.jl @@ -465,6 +465,7 @@ ParamName | Description "Bibtex-XXX" | A BibTeX key, where XXX is one of the bibtex keys used in get_BibTeXKey "pure" | "true" if the fluid is pure, "false" otherwise "formula" | The chemical formula of the fluid in LaTeX form if available, "" otherwise +"JSON" | The JSON string storing all fluid data # Note A tabular output for this function is available with `?CoolProp_fluids` diff --git a/test/testunits.jl b/test/testunits.jl index 9a16690..1016c58 100644 --- a/test/testunits.jl +++ b/test/testunits.jl @@ -7,9 +7,9 @@ let fluid="air" μ = PropsSI("VISCOSITY", "T", 293K, "P", 101325Pa, fluid) @test round(μPa*s, μ; digits=2) == 18.2μPa*s - # Test that all parameters return a unit + # Test that all parameters return a unit when an unitful number is being used for param in split(get_global_param_string("parameter_list"),',') - @test CoolProp._get_unit(param,false) isa FreeUnits + @test CoolProp._get_unit(param,false,1*K) isa FreeUnits end end From bbd89704a493a3ce021cce08548e598bb3115a87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Riedemann?= <38795484+longemen3000@users.noreply.github.com> Date: Sun, 1 Mar 2026 23:59:57 -0300 Subject: [PATCH 8/9] _get_unit: change default from true to nothing --- src/CoolProp.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/CoolProp.jl b/src/CoolProp.jl index 6724ef0..9158751 100644 --- a/src/CoolProp.jl +++ b/src/CoolProp.jl @@ -88,15 +88,15 @@ function _get_unit(param::AbstractString, is_ha::Bool, val::Real) return _get_unit(param,is_ha,nothing) end -_get_unit(param::AbstractString, is_ha::Bool, ::Nothing) = true +_get_unit(param::AbstractString, is_ha::Bool, ::Nothing) = nothing _si_value(::Bool,value) = value function PropsSI(output::AbstractString, name1::AbstractString, value1::Number, name2::AbstractString, value2::Number, fluid::AbstractString) unit1 = _get_unit(name1,false,value1) unit2 = _get_unit(name2,false,value2) out = PropsSI(output, name1, _si_value(unit1,value1), name2, _si_value(unit2,value2), fluid) - unit1 == true && unit2 == true && (return out) - unit1 != true && (return out*_get_unit(output,false,value1)) + unit1 === nothing && unit2 === nothing && (return out) + unit1 !== nothing && (return out*_get_unit(output,false,value1)) return out*_get_unit(output,false,value2) end @@ -677,9 +677,9 @@ function HAPropsSI(output::AbstractString, name1::AbstractString, value1::Number unit2 = _get_unit(name2,true,value2) unit3 = _get_unit(name3,true,value3) out = HAPropsSI(output, name1, _si_value(unit1,value1), name2, _si_value(unit2,value2), name3, _si_value(unit3,value3)) - unit1 == true && unit2 == true && unit3 == true && (return out) - unit1 != true && (return out*_get_unit(output,true,value1)) - unit2 != true && (return out*_get_unit(output,true,value2)) + unit1 === nothing && unit2 === nothing && unit3 === nothing && (return out) + unit1 !== nothing && (return out*_get_unit(output,true,value1)) + unit2 !== nothing && (return out*_get_unit(output,true,value2)) return out*_get_unit(output,true,value3) end From 78558f9fcb37c2d1724b5c36661d2a5a9d94736e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Riedemann?= <38795484+longemen3000@users.noreply.github.com> Date: Mon, 2 Mar 2026 00:26:12 -0300 Subject: [PATCH 9/9] typo --- src/CoolProp.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CoolProp.jl b/src/CoolProp.jl index 9158751..c2875c0 100644 --- a/src/CoolProp.jl +++ b/src/CoolProp.jl @@ -89,7 +89,7 @@ function _get_unit(param::AbstractString, is_ha::Bool, val::Real) end _get_unit(param::AbstractString, is_ha::Bool, ::Nothing) = nothing -_si_value(::Bool,value) = value +_si_value(::Nothing,value) = value function PropsSI(output::AbstractString, name1::AbstractString, value1::Number, name2::AbstractString, value2::Number, fluid::AbstractString) unit1 = _get_unit(name1,false,value1)