CoolProp 低级接口(AbstractState)实战:快速状态计算、相区指定与双根消歧的源码级指南
科学计算【免费下载链接】CoolPropThermophysical properties for the masses项目地址https://gitcode.com/gh_mirrors/co/CoolProp点击查看免费下载CoolProp 的高级接口PropsSI等以字符串解析参数便捷但开销较大低级接口则完全基于枚举值与浮点数、不使用任何字符串是高级接口内部真正调用的执行路径。本文基于仓库中的 LowLevelAPI.rst 官方文档展开逐节覆盖低级接口的核心用法——AbstractState实例的创建与复用、输入对input pairs的生成、keyed_output批量取数、相区强制指定specify_phase、多饱和根消歧update_with_guesses、高效偏导数first_partial_deriv/first_two_phase_deriv/ 饱和线导数、参考态切换以及面向无 C 类绑定语言Excel、FORTRAN、Julia 等的 C 函数层——并结合 AbstractState 头文件、CoolPropLib.h 等源码给出实现依据读完即可在性能敏感的循环与闪蒸场景中以正确的姿势使用低级接口。1. 低级接口的设计定位与实例化原则低级接口的首要价值是速度它只接受整型枚举CoolProp::parameters、CoolProp::input_pairs和双精度浮点数避开了字符串比较与解析的开销。CoolProp 的高级接口本质上就是在内部转调这套低级接口因此凡是热路径上的代码直接调用低级接口都能获得更稳定、更低延迟的表现。在 C 层面整个体系建立在一个名为AbstractState的抽象基类之上它定义了一组各物性后端property backends必须实现的协议。从 AbstractState.h 的源码结构可以看到update()被声明为纯虚函数L967而calc_specify_phase、calc_first_saturation_deriv、calc_first_two_phase_deriv等计算钩子则提供了“未实现即抛NotImplementedError”的默认行为L695-L758。这种协议式设计使得接入一个全新的物性库非常容易——只要其接口能映射到AbstractState的结构即可官方正是用同样方式接入了 REFPROP 后端。文档明确给出的使用原则每个流体或混合物只构造一个后端实例并反复调用其方法。构造函数存在可观的计算开销构造一次后应在整个程序生命周期内传递该实例对表格类后端TTSE、Bicubic见 Tabular.rst和 SVD 压缩表格后端SVDSBTL见 SVDSBTL.rst这一原则从“建议”升级为硬性要求每次构造需支付约80–140 ms的表加载成本。SVDSBTL 提供进程级内存缓存使同一进程中同流体/同选项的第二次构造便宜得多但那是缓解措施而非替代品TTSE/Bicubic 没有此缓存新进程永远要付完整加载成本在 C 中AbstractState::factory返回的是裸指针文档强烈建议用std::shared_ptr包裹让析构自动发生。2. 第一个示例C 中计算水的饱和态文档中的入门示例源码见 AbstractState1.cxx展示了低级接口最典型的应用——给定压力与干度求饱和液相性质#include CoolProp/CoolProp.h #include CoolProp/AbstractState.h #include iostream #include memory using namespace CoolProp; int main() { std::shared_ptrAbstractState Water(AbstractState::factory(HEOS, Water)); Water-update(PQ_INPUTS, 101325, 0); // SI units std::cout T: Water-T() K std::endl; std::cout rho: Water-rhomass() kg/m^3 std::endl; std::cout rho: Water-rhomolar() mol/m^3 std::endl; std::cout h: Water-hmass() J/kg std::endl; std::cout h: Water-hmolar() J/mol std::endl; std::cout s: Water-smass() J/kg/K std::endl; std::cout s: Water-smolar() J/mol/K std::endl; return EXIT_SUCCESS; }实际运行输出见 AbstractState1.cxx.outputT: 373.124 K rho: 958.367 kg/m^3 rho: 53197.5 mol/m^3 h: 419058 J/kg h: 7549.44 J/mol s: 1306.92 J/kg/K s: 23.5445 J/mol/K同样的计算若走高级接口等价于一次PropsSI(T, P, 101325, Q, 1, Water)调用。注意本例中“构造一次、多个访问器T()、rhomass()、hmass()…连取”的写法正是低开销的关键状态只算一次各属性从同一个已解析的状态中读取。3. 输入对Input Pairs与generate_update_pairAbstractState::update的第一个参数是CoolProp::input_pairs枚举值如PT_INPUTS、PQ_INPUTS、DmolarT_INPUTS完整清单定义在CoolProp::input_pairs源码文档见CoolProp::input_pairs。如果只知道两个输入变量及其数值、不确定该用哪个输入对枚举可以调用CoolProp::generate_update_pair自动生成。从 DataStructures.h 的源码看L381-L439该函数是一个模板内部按match_pair(key1, key2, ...)逐一比对两个parameters枚举顺序无关swap参数处理交换命中后返回对应枚举并把两个数值重排到与枚举定义一致的槽位例如iHmolar在前则v1为摩尔焓无效组合返回INPUT_PAIR_INVALID。这一点很重要Python 版可以多返回值C 版无法如此因此 C 侧的值交换发生在输出参数out1/out2上文档对此专门给出了 warning。Python 中的示例In [0]: import CoolProp In [0]: CoolProp.CoolProp.generate_update_pair(CoolProp.iT, 300, CoolProp.iDmolar, 1e-6) In [0]: CoolProp.DmolarT_INPUTS即把“温度 300 K 摩尔密度 1e-6 mol/m³”归一为DmolarT_INPUTS密度在前、温度在后。4.keyed_output与访问器函数两种取数方式简单输出函数如AbstractState::rhomolar与CoolProp::parameters中的键是一一对应的因此取数有两条等价路径访问器函数HEOS.p()、HEOS.rhomass()——语义清晰、编译期友好keyed_outputHEOS.keyed_output(CoolProp.iP)——可以对一组键做循环避免把一堆访问器调用硬编码在代码里AbstractState.h 中定义另有trivial_keyed_output等变体。文档示例In [0]: import CoolProp In [0]: HEOS CoolProp.AbstractState(HEOS, Water) In [0]: HEOS.update(CoolProp.DmolarT_INPUTS, 1e-6, 300) In [0]: HEOS.p() In [0]: [HEOS.keyed_output(k) for k in [CoolProp.iP, CoolProp.iHmass, CoolProp.iHmolar]]当需要“遍历一组输出键”或键集合在运行期才确定时keyed_output是唯一可扩展的写法。5. 只有低级接口才有的能力第一个例子用高级接口也能做但那样要多次调用压力-干度闪蒸而每次闪蒸都要做复杂的相平衡迭代速度很慢。更重要的是大量功能只存在于低级接口。文档给出的两类典型能力1强制相区加速闪蒸In [0]: HEOS CoolProp.AbstractState(HEOS, Water) # Do a flash call that is a very low density state point, definitely vapor In [0]: %timeit HEOS.update(CoolProp.DmolarT_INPUTS, 1e-6, 300) # Specify the phase - for some inputs (especially density-temperature), this will result in a # more direct evaluation of the equation of state without checking the saturation boundary In [0]: HEOS.specify_phase(CoolProp.iphase_gas) # We try it again - a bit faster In [0]: %timeit HEOS.update(CoolProp.DmolarT_INPUTS, 1e-6, 300) # Reset the specification of phase In [0]: HEOS.specify_phase(CoolProp.iphase_not_imposed)2混合物露点及两相组成高级接口无对应直接调用# A mixture of methane and ethane In [0]: HEOS CoolProp.AbstractState(HEOS, MethaneEthane) # Set the mole fractions of the mixture In [0]: HEOS.set_mole_fractions([0.2,0.8]) # Do the dewpoint calculation In [0]: HEOS.update(CoolProp.PQ_INPUTS, 101325, 1) # Liquid phase molar density In [0]: HEOS.saturated_liquid_keyed_output(CoolProp.iDmolar) # Vapor phase molar density In [0]: HEOS.saturated_vapor_keyed_output(CoolProp.iDmolar) # Liquid phase mole fractions In [0]: HEOS.mole_fractions_liquid() # Vapor phase mole fractions - # Should be the bulk composition back since we are doing a dewpoint calculation In [0]: HEOS.mole_fractions_vapor()6. 指定相区Imposing the Phase每次update()默认都要根据输入对判定相态可能触发一次不小的闪蒸计算。CoolProp 允许在update()前手动指定相区源码见 AbstractState.h 的specify_phase它只是转发到后端的calc_specify_phase。文档实测对DmolarT_INPUTS这类输入指定相区可带来约 10% 级别的加速——对某些输入对加速明显对另一些则几乎无收益若该输入对无论如何都要做闪蒸指定相可能被内部忽略。可用的相区常量CoolProp枚举相区常量相区含义iphase_liquidp pcrit T Tcrit饱和线以上液相区iphase_gasp pcrit T Tcrit饱和线以下气相区iphase_twophasep pcrit T Tcrit液/气两相混合iphase_supercritical_liquidp pcrit T Tcritiphase_supercritical_gasp pcrit T Tcritiphase_supercriticalp pcrit T Tcritiphase_not_imposed默认由 CoolProp 自行判定相区解除指定有两种写法# Reset the specification of phase In [0]: HEOS.specify_phase(CoolProp.iphase_not_imposed) # Or, more simply In [0]: HEOS.unspecify_phase()文档强调两点实践约束相区指定应紧邻update()调用之前且绝对关键——输入点必须确实落在所指定的相区内。若指定了错误相区update()可能抛出异常或返回错误结果相态不绝对确定时宁可让 CoolProp 自行判定、付出一些计算代价。7. 多饱和根的消歧update_with_guesses与温度猜测一部分饱和闪蒸输入对存在同一输入值对应多个温度解的情况默认update返回哪一个由区间法求解器的状态决定实现定义。文档列出的实际会出现的情形HmolarQ_INPUTS/HmassQ_INPUTS在汽相侧Q 1许多流体的饱和汽相焓 $h_g(T)$ 在远低于临界温度处出现峰值水约 540 K峰值两侧一大段焓值区间对应两个饱和温度QSmolar_INPUTS/QSmass_INPUTS汽相侧部分流体形状相同DmolarQ_INPUTS/DmassQ_INPUTS在液相侧Q 0且流体为水或重水D2O$\rho_L(T)$ 在 4 °C水/ 11 °C重水附近有极大值略低于峰值的密度值对应两个饱和温度。选择特定根的方式是调用update_with_guesses并通过CoolProp::GuessesStructure提供温度提示。从实现原理看闪蒸内部使用饱和线的Chebyshev superancillary表示构造时会被切分为可证明单调的温度子区间guess.T选中包含它的子区间TOMS748 括号法在该子区间内找到唯一根AbstractState.h 中update_with_guesses定义了该接口。水 $h_g(T)$ 峰值两侧的两根示例In [1]: import CoolProp.CoolProp as CP In [2]: HEOS CP.AbstractState(HEOS, Water) # h_g(T) on water saturated vapor has a maximum near 540 K. h_target # h_g(470 K) is also reached at some T 540 K on the falling side. In [3]: HEOS.update(CP.QT_INPUTS, 1.0, 470.0) In [4]: h_target HEOS.hmolar() # Guess near the low-T root → returns ~470 K In [5]: g CP.PyGuessesStructure(); g.T 470.0 In [6]: HEOS.update_with_guesses(CP.HmolarQ_INPUTS, h_target, 1.0, g) In [7]: HEOS.T() # Guess past the peak → returns the *other* root In [8]: g.T 620.0 In [9]: HEOS.update_with_guesses(CP.HmolarQ_INPUTS, h_target, 1.0, g) In [10]: HEOS.T()水饱和液密度峰值4 °C 附近的两根示例同一模式适用于DmolarQ_INPUTS与QSmolar_INPUTS# Water saturated-liquid density max around T ≈ 277.13 K (4 °C). # Pick a target ρ between ρ(near triple) and ρ(near peak) so two roots exist. In [11]: HEOS.update(CP.QT_INPUTS, 0.0, 277.0) In [12]: rho_near_peak HEOS.rhomolar() In [13]: HEOS.update(CP.QT_INPUTS, 0.0, 273.5) In [14]: rho_near_triple HEOS.rhomolar() In [15]: rho_target 0.5*(rho_near_peak rho_near_triple) # Guess on the rising branch → root below the peak In [16]: g.T 274.0; HEOS.update_with_guesses(CP.DmolarQ_INPUTS, rho_target, 0.0, g) In [17]: HEOS.T() # Guess on the falling branch → root above the peak In [18]: g.T 282.0; HEOS.update_with_guesses(CP.DmolarQ_INPUTS, rho_target, 0.0, g) In [19]: HEOS.T()文档给出的若干重要细节原文笔记逐条继承该功能要求流体带有 Chebyshev superancillary标准 CoolProp 构建中的每种纯流体都满足$h_{sat}(T)$、$s_{sat}(T)$ 的 Chebyshev 展开首次使用时惰性构建通过采样密度 superancillary 的节点评估 EOS并在构建时捕获当前参考态分支选择逻辑只读取guess.TGuessesStructure的其他字段对这些输入对被忽略该代码路径仅支持纯流体非伪纯流体混合物与伪纯流体会抛CoolProp::NotImplementedError首次惰性构建完成后每次调用的候选根枚举成本在微秒量级每个单调子区间内一次分段 Chebyshev TOMS748 求根首次调用会惰性构建热类caloricsuperancillary成本约10–50 ms可被后续所有调用摊薄也可以在启动时先调用一次update_with_guesses预构建。调用CoolProp::set_reference_state后缓存会失效并重新构建保证系数始终匹配当前参考态。另外两个行为变化值得注意若直接调用不带猜测的update且输入落在多根区间CoolProp 现在会抛出CoolProp::MultipleSolutionsError而非静默任选一个错误信息会列出候选温度并指向update_with_guesses单根输入照常工作想在不触发异常的前提下探测某(value, Q)是否多根用两个充分拉开的guess.T各调用一次update_with_guesses比较返回的T——差异显著即多根若多位数一致则解唯一。8. 低成本的偏导数first_partial_deriv与second_partial_deriv低级接口可以以非常低的计算成本获取偏导数接口文档见CoolProp::AbstractState::first_partial_deriv与second_partial_deriv实现入口在 AbstractState.h。文档示例PythonIn [1]: import CoolProp In [2]: HEOS CoolProp.AbstractState(HEOS, Water) In [3]: HEOS.update(CoolProp.PT_INPUTS, 101325, 300) In [4]: HEOS.cpmass() In [4]: HEOS.first_partial_deriv(CoolProp.iHmass, CoolProp.iT, CoolProp.iP) In [4]: %timeit HEOS.first_partial_deriv(CoolProp.iHmass, CoolProp.iT, CoolProp.iP) # See how much faster this is? In [4]: %timeit CoolProp.CoolProp.PropsSI(d(Hmass)/d(T)|P, P, 101325, T, 300, Water) In [4]: HEOS.first_partial_deriv(CoolProp.iSmass, CoolProp.iT, CoolProp.iDmass) # In the same way you can do second partial derivatives # This is the second mixed partial derivative of entropy with respect to density and temperature In [4]: HEOS.second_partial_deriv(CoolProp.iSmass, CoolProp.iT, CoolProp.iDmass, CoolProp.iDmass, CoolProp.iT) # This is the second partial derivative of entropy with respect to density at constant temperature In [4]: HEOS.second_partial_deriv(CoolProp.iSmass,CoolProp.iDmass,CoolProp.iT,CoolProp.iDmass,CoolProp.iT)参数语义first_partial_deriv(Of, Wrt, Constant)即 $(\partial \mathrm{Of} / \partial \mathrm{Wrt})|_{\mathrm{Constant}}$second_partial_deriv(Of, Wrt1, Constant1, Wrt2, Constant2)依次给出混合二阶偏导。由于状态已经更新过重复取导数无需再次闪蒸因此%timeit对比中低级接口显著快于等价的PropsSI导数字符串后者每次都走一次高级接口的解析与闪蒸。9. 两相与饱和线导数Thorade 导数与杠杆规则两相导数Thorade 的两相导数实现于CoolProp::AbstractState::first_two_phase_deriv沿饱和线的导数则实现于first_saturation_deriv与second_saturation_deriv。示例In [0]: import CoolProp In [0]: HEOS CoolProp.AbstractState(HEOS, Water) In [0]: HEOS.update(CoolProp.QT_INPUTS, 0, 300) # First saturation derivative calculated analytically In [0]: HEOS.first_saturation_deriv(CoolProp.iP, CoolProp.iT) In [0]: HEOS.update(CoolProp.QT_INPUTS, 0, 300 0.001); p2 HEOS.p() In [0]: HEOS.update(CoolProp.QT_INPUTS, 0, 300 - 0.001); p1 HEOS.p() # First saturation derivative calculated numerically In [0]: (p2-p1)/(2*0.001) In [0]: HEOS.update(CoolProp.QT_INPUTS, 0.1, 300) # The d(Dmass)/d(Hmass)|P two-phase derivative In [0]: HEOS.first_two_phase_deriv(CoolProp.iDmass, CoolProp.iHmass, CoolProp.iP) # The d(Dmass)/d(Hmass)|P two-phase derivative using splines In [0]: HEOS.first_two_phase_deriv_splined(CoolProp.iDmass, CoolProp.iHmass, CoolProp.iP, 0.3) # The d(Q)/d(Hmolar)|P two-phase derivative of vapor quality In [0]: HEOS.first_two_phase_deriv(CoolProp.iQ, CoolProp.iHmolar, CoolProp.iP) # The d(Q)/d(P)|Hmolar two-phase derivative of vapor quality In [0]: HEOS.first_two_phase_deriv(CoolProp.iQ, CoolProp.iP, CoolProp.iHmolar)前两组演示了“解析导数 vs 数值差分”的交叉验证后两组给出干度 $Q$ 的两相导数。文档给出了其推导依据干度导数直接来自杠杆规则$Q (h - h)/(h - h)$可得$$(\partial Q/\partial h)_p 1/(h - h), \qquad (\partial Q/\partial p)_h -[(1-Q),\mathrm{d}h/\mathrm{d}p Q,\mathrm{d}h/\mathrm{d}p]/(h - h),$$其中 $h$、$h$ 为饱和液/汽焓。配对规则摩尔干度iQ配摩尔焓iHmolar质量干度iQmass配质量焓iHmass对纯流体两者数值相等。这些导数只定义在两相穹顶内部且只通过低级接口first_two_phase_deriv提供高级接口PropsSI的导数字符串不可用。文档特别列出的限制均为实现事实这两个干度导数仅限纯流体否则抛NotImplementedError——因为推导要求 $h$、$h$ 只是压力的函数混合物有温度滑移干度相关相组成伪纯流体的泡/露点在同温下压力不同杠杆规则均不成立。对REFPROP后端的伪纯流体拒绝与否由泡/露压差判定该差值在临界点处消失故约在 $10^{-9}$ 约化温度距离 $T_c$ 以内不再拒绝在临界点处 $h - h \to 0$导数发散此时抛ValueError而非返回非有限值C 异常类型Python 包装层统一表现为ValueError表格类后端BICUBIC、TTSE不实现这两个导数请向HEOS或REFPROP实例请求。文档还附了一段绘制 $d\rho/dh|_p$ 随干度变化的完整脚本亚冷液相段 两相段含样条版本对比可原样运行import numpy as np import CoolProp import matplotlib.pyplot as plt AS CoolProp.AbstractState(HEOS,Water) # Saturated liquid AS.update(CoolProp.PQ_INPUTS, 101325, 0) Ts AS.T() h_fg AS.saturated_vapor_keyed_output(CoolProp.iHmass) - AS.saturated_liquid_keyed_output(CoolProp.iHmass) cl AS.cpmass() # Subcooled liquid x, y [], [] for T in np.linspace(Ts - 30, Ts - 0.1, 1000): AS.update(CoolProp.PT_INPUTS, 101325, T) x.append(-cl*(Ts-T)/h_fg) y.append(AS.first_partial_deriv(CoolProp.iDmass, CoolProp.iHmass, CoolProp.iP)) plt.plot(x, y, label Subcooled) # Two-phase derivatives (normal and splined) x, y1 [], [] for Q in np.linspace(0, 0.3, 1000): AS.update(CoolProp.PQ_INPUTS, 101325, Q) x.append(AS.Q()) y1.append(AS.first_two_phase_deriv_splined(CoolProp.iDmass, CoolProp.iHmass, CoolProp.iP, 0.3)) plt.plot(x, y1, label Two-phase (splined)) # Two-phase derivatives (normal and splined) x, y1 [], [] for Q in np.linspace(0.0, 0.6, 1000): AS.update(CoolProp.PQ_INPUTS, 101325, Q) x.append(AS.Q()) y1.append(AS.first_two_phase_deriv(CoolProp.iDmass, CoolProp.iHmass, CoolProp.iP)) plt.plot(x, y1, label Two-phase) plt.title(r$d\rho/dh|p$) plt.xlabel(vapor quality (-)) plt.ylabel(r$d\rho/dh|p$) plt.ylim(-0.005, 0.005) plt.legend(locbest)10. 参考态低级接口下的陷阱与演示参考态的高级接口用法见 HighLevelAPI.rst 中的参考态章节同样适用于低级接口但有一条必须警惕的行为set_reference_stateSPython 中为set_reference_state应在代码最开始调用一次之后不再变更已经由工厂函数创建的AbstractState实例不会感知后续参考态的更改——这是有意设计但容易被忽略。文档给出的演示注意 AS1/AS2 的差异In [1]: import CoolProp as CP # This one doesnt see the change in reference state In [1]: AS1 CoolProp.AbstractState(HEOS,n-Propane); In [1]: AS1.update(CoolProp.QT_INPUTS, 0, 233.15); In [1]: CoolProp.CoolProp.set_reference_state(n-Propane,ASHRAE) # This one gets the update in the reference state In [1]: AS2 CoolProp.AbstractState(HEOS,n-Propane); In [1]: AS2.update(CoolProp.QT_INPUTS, 0, 233.15); # Note how the AS1 has its default value (change in reference state is not seen) # and AS2 does see the new reference state In [1]: print({0}, {1}.format(AS1.hmass(), AS2.hmass())) # Back to the original value In [1]: CoolProp.CoolProp.set_reference_state(n-Propane,DEF)这与第 7 节的 superancillary 缓存行为相呼应切换参考态后缓存在首次惰性构建时捕获的参考态会被重建而旧实例仍按旧参考态工作。工程上的结论是固定参考态 → 再创建实例顺序不能颠倒。11. 以低级接口方式调用 REFPROP若已安装 REFPROP 库可以用与 CoolProp 完全相同的低级接口写法、仅把后端名换成REFPROP来调用它In [0]: import CoolProp In [0]: REFPROP CoolProp.AbstractState(REFPROP, WATER) In [0]: REFPROP.update(CoolProp.DmolarT_INPUTS, 1e-6, 300) In [0]: REFPROP.p(), REFPROP.hmass(), REFPROP.hmolar() In [0]: [REFPROP.keyed_output(k) for k in [CoolProp.iP, CoolProp.iHmass, CoolProp.iHmolar]]这正是第 1 节所述“协议化后端”设计的直接收益REFPROP 作为外部库被无缝映射进AbstractState结构调用方代码与HEOS版本逐字相同。12. 面向无 C 类绑定语言的 C 函数层CoolPropLib.h对无法直接实例化 C 类或其语言包装但能调用共享库的语言Excel、FORTRAN、Julia 等CoolProp 提供了一层纯 C 函数接口全部定义在 CoolPropLib.h函数名均以AbstractState开头。该接口内部生成并管理AbstractState指针外部拿到的是长整型句柄handle。关键函数在源码中的位置函数源码位置作用get_param_indexCoolPropLib.h L253参数名 →parameters整型索引get_input_pair_indexCoolPropLib.h L258输入对名 →input_pairs整型索引AbstractState_factoryCoolPropLib.h L346创建实例返回 handleAbstractState_set_fractionsCoolPropLib.h L377设置混合物摩尔分数AbstractState_updateCoolPropLib.h L523执行输入对更新AbstractState_keyed_outputCoolPropLib.h L554按键取输出AbstractState_update_and_common_outCoolPropLib.h L670批量更新 5 个常用输出AbstractState_update_and_5_outCoolPropLib.h L716批量更新 5 个用户指定输出AbstractState_freeCoolPropLib.h L366显式释放 handle以 Julia 包装为例文档原示例纯单点计算与混合物两路闪蒸julia import CoolProp julia PT_INPUTS CoolProp.get_input_pair_index(PT_INPUTS) 7 julia cpmass CoolProp.get_param_index(C) 34 julia handle CoolProp.AbstractState_factory(HEOS, Water) 0 julia CoolProp.AbstractState_update(handle,PT_INPUTS,101325, 300) julia CoolProp.AbstractState_keyed_output(handle,cpmass) 4180.635776569655 julia CoolProp.AbstractState_free(handle) julia handle CoolProp.AbstractState_factory(HEOS, WaterEthanol) 1 julia PQ_INPUTS CoolProp.get_input_pair_index(PQ_INPUTS) 2 julia T CoolProp.get_param_index(T) 18 julia CoolProp.AbstractState_set_fractions(handle, [0.4, 0.6]) julia CoolProp.AbstractState_update(handle,PQ_INPUTS,101325, 0) julia CoolProp.AbstractState_keyed_output(handle,T) 352.3522142890429 julia CoolProp.AbstractState_free(handle)AbstractState_free并非必需——受管AbstractState实例会自动释放但若要以这种方式生成成千上万乃至百万个实例定期清理是合理的做法。C 直接调用 C 层的批量基准见 HighLevelLowLevel.cxx展示了句柄接口的吞吐形态——注意这里使用了BICUBICHEOS混合后端在 20000 点的 HmassP 闪蒸循环上逐点调用update keyed_output#include CoolProp/CoolPropLib.h #include CoolProp/detail/tools.h #include vector #include time.h int main() { double t1, t2; const long buffersize 500; long errcode 0; char buffer[buffersize]; long handle AbstractState_factory(BICUBICHEOS, Water, errcode, buffer, buffersize); long _HmassP get_input_pair_index(HmassP_INPUTS); long _Dmass get_param_index(Dmass); long len 20000; std::vectordouble h linspace(700000.0, 1500000.0, len); std::vectordouble p linspace(2.8e6, 3.0e6, len); double summer 0; t1 clock(); for (long i 0; i len; i) { AbstractState_update(handle, _HmassP, h[i], p[i], errcode, buffer, buffersize); summer AbstractState_keyed_output(handle, _Dmass, errcode, buffer, buffersize); } t2 clock(); std::cout format(value(all): %0.13g, %g us/call\n, summer, ((double)(t2 - t1)) / CLOCKS_PER_SEC / double(len) * 1e6); return EXIT_SUCCESS; }实际输出HighLevelLowLevel.cxx.outputvalue(all): 8339004.432514, 0.8 us/call另有一个“批量多输出”的变体HighLevelLowLevelMulti.cxx一次调用同时取回 5 个常用输出T、P、Dmolar、Hmolar、Smolar或 5 个由get_param_index指定的用户自定义输出进一步摊薄逐点取数的句柄调用开销#include CoolProp/CoolPropLib.h #include CoolProp/detail/tools.h #include vector #include time.h int main() { const long buffer_size 1000, length 100000; long ierr; char herr[buffer_size]; long handle AbstractState_factory(BICUBICHEOS, Water, ierr, herr, buffer_size); std::vectordouble T(length), p(length), rhomolar(length), hmolar(length), smolar(length); std::vectordouble input1 linspace(700000.0, 1500000.0, length); std::vectordouble input2 linspace(2.8e6, 3.0e6, length); long input_pair get_input_pair_index(HmassP_INPUTS); double t1 clock(); AbstractState_update_and_common_out(handle, input_pair, (input1[0]), (input2[0]), length, (T[0]), (p[0]), (rhomolar[0]), (hmolar[0]), (smolar[0]), ierr, herr, buffer_size); double t2 clock(); std::cout format(value(commons): %g us/call\n, ((double)(t2 - t1)) / CLOCKS_PER_SEC / double(length) * 1e6); std::vectorlong outputs(5); outputs[0] get_param_index(T); outputs[1] get_param_index(P); outputs[2] get_param_index(Dmolar); outputs[3] get_param_index(Hmolar); outputs[4] get_param_index(Smolar); std::vectordouble out1(length), out2(length), out3(length), out4(length), out5(length); t1 clock(); AbstractState_update_and_5_out(handle, input_pair, (input1[0]), (input2[0]), length, (outputs[0]), (out1[0]), (out2[0]), (out3[0]), (out4[0]), (out5[0]), ierr, herr, buffer_size); t2 clock(); std::cout format(value(user-specified): %g us/call\n, ((double)(t2 - t1)) / CLOCKS_PER_SEC / double(length) * 1e6); }该函数层实现了低级接口的一个“有限子集”文档说明如需更多功能应向项目 issue 区提需求。13. 小结何时用低级接口如何用最对综合 LowLevelAPI.rst 与仓库源码可以把低级接口的价值与纪律浓缩为性能无字符串解析输入/输出全部枚举 浮点高级接口内部即调用它热循环中应复用同一个AbstractState实例表格类后端TTSE/Bicubic/SVDSBTL的构造成本约 80–140 ms/次决定了实例复用是硬约束输入组织update用input_pairs枚举定位输入槽位generate_update_pairDataStructures.h L381-L439负责把乱序的键值对归一化并处理 C 侧的值交换语义输出组织访问器与keyed_output等价后者支持键循环与运行期键集C 层还有update_and_common_out/update_and_5_out两个批量变体只有低级才有的能力specify_phase加速相区常量表见第 6 节指定错误相区会引发异常或错误结果务必紧邻update()前指定、混合物露点与两相组成、update_with_guesses多根消歧依赖 superancillary 单调子区间 TOMS748仅纯流体默认update遇多根现抛MultipleSolutionsError、first/second_partial_deriv低成本偏导、Thorade 两相导数与饱和线导数干度导数由杠杆规则推出限纯流体、表后端未实现、REFPROP 后端的同构调用参考态纪律set_reference_state在创建实例前调用一次已创建的实例不感知后续变更且会驱动 caloric superancillary 缓存的失效重建跨语言不能绑定 C 类的语言经CoolPropLib.h的AbstractState_*C 函数handle 模式获得 1 对 1 的低级能力AbstractState_free可选但大批量创建实例时建议定期调用。赞分享科学计算【免费下载链接】CoolPropThermophysical properties for the masses项目地址https://gitcode.com/gh_mirrors/co/CoolProp点击查看免费下载相关推荐CoolProp 高级接口High-Level API完全指南PropsSI、相位控制、混合物与偏导数实战CoolProp 高级接口High Level API完全指南PropsSI、相位控制、混合物与偏导数实战 本文以 CoolProp 官方文档《High科学计算CoolProp 快速上手指南PropsSI / HAPropsSI 物性计算与 Python 绘图实战CoolProp 快速上手指南PropsSI / HAPropsSI 物性计算与 Python 绘图实战 导读 本篇指南以 CoolProp 官方文档的 Ex科学计算ShowDoc 中的 PSR-7 接口速查七大 HTTP 消息接口方法与源码级实践ShowDoc 中的 PSR 7 接口速查七大 HTTP 消息接口方法与源码级实践 本文以 ShowDoc 仓库自带的 psr/http message 包文文档知识库后端前端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考