[英]Strange Occurance when using functions from C DLL in Python
I'm having a strange issue where I'm using DLL functions that return more or less the same float value (ie their residual is less than 1e-08), but I'm somehow seeing different behavior.我有一个奇怪的问题,我正在使用 DLL 函数返回或多或少相同的浮点值(即它们的残差小于 1e-08),但我不知何故看到了不同的行为。
Here is the general way I'm writing the function prototypes in Python;这是我在 Python 中编写 function 原型的一般方式; this should be enough information to give you an idea of how I'm doing this part.
这应该足以让您了解我是如何做这部分的。
class OWTP:
def __init__(self):
self._lib = CDLL("../Include/OWTP.dll")
protoTwoParams = CFUNCTYPE(c_double, c_double, c_double)
ptApi = (1, "P"), (1, "T")
#properties as functions of pressure and temperature
self.v_PT = protoTwoParams(("v_P_T", self._lib), ptApi)
self.u_PT = protoTwoParams(("u_P_T", self._lib), ptApi)
self.s_PT = protoTwoParams(("s_P_T", self._lib), ptApi)
self.h_PT = protoTwoParams(("h_P_T", self._lib), ptApi)
self.cp_PT = protoTwoParams(("cp_P_T", self._lib), ptApi)
self.cv_PT = protoTwoParams(("cv_P_T", self._lib), ptApi)
#much more past this point, but it's generally more of the same
Next, I'm writing a couple of classes that are intended to basically do a bunch of calculations and hold a bunch of property data.接下来,我正在编写几个类,它们基本上是为了进行一堆计算并保存一堆属性数据。
Root class根class
class ThermoProperties(ABC):
def __init__(self):
self._P = float('nan')
self._T = float('nan')
self._h = float('nan')
self._s = float('nan')
self._u = float('nan')
self._v = float('nan')
self._cp = float('nan')
self._cv = float('nan')
Concrete class混凝土 class
class OrdinaryWaterThermoProperties(ThermoProperties):
_owtp = OWTP()
def __init__(self):
super(ThermoProperties, self).__init__()
self._x = float('nan')
And now for the function in question that's on OrdinaryWaterThermoProperties
现在对于在
OrdinaryWaterThermoProperties
上有问题的 function
def Set_Tx(self, T, x):
P = self._owtp.PSat_T(T)
self._P = P
self._T = T
self._v = self._owtp.v_Tx(T,x)
self._u = self._owtp.u_Tx(T,x)
self._s = self._owtp.s_Tx(T,x)
self._h = self._owtp.h_Tx(T,x)
self._x = x
#at this point, linearly interpolate between the cps
#and cvs @ 0 and 1 vapor quality
if (x <= 1e-08):
cpLow = self._owtp.cp_Ps(P, self._s)
cvLow = self._owtp.cv_Ps(P, self._s)
else:
s = self._owtp.s_Tx(T,0)
cpLow = self._owtp.cp_Ps(P, s)
cvLow = self._owtp.cv_Ps(P, s)
if (1.0 - x <= 1e-08):
cpHigh = self._owtp.cp_Ps(P, self._s)
cvHigh = self._owtp.cv_Ps(P, self._s)
else:
s = self._owtp.s_Tx(T,1)
cpHigh = self._owtp.cp_Ps(P, s)
cvHigh = self._owtp.cv_Ps(P, s)
self._cp = cpLow + x * (cpHigh - cpLow)
self._cv = cvLow + x * (cvHigh - cvLow)
The issue is that the last 2 lines evaluate to some ridiculous number.问题是最后两行评估为一些荒谬的数字。 At first, I obviously thought that this was just an issue with the library that I wrote, but as I tried more things, I'm not so sure about that now.
起初,我显然认为这只是我编写的库的问题,但是当我尝试更多的东西时,我现在不太确定了。
This line self._s = self._owtp.s_Tx(T,x)
stores a nearly identical value (ie residual less than 1e-08) if I replace it with this self._s = self._owtp.s_Px(P,x)
, but once I do the replacement, those last 2 lines evaluate to the reference values I have.如果我用这个
self._s = self._owtp.s_Px(P,x)
替换这条线self._s = self._owtp.s_Tx(T,x)
x) ,但是一旦我进行替换,最后两行将评估为我拥有的参考值。
Is there something I've done wrong or is there something that Python does to which I'm not aware?是我做错了什么还是 Python 做了什么我不知道的事情?
I just want to know why exactly this is happening.我只是想知道为什么会发生这种情况。
Please let me know if more info is needed.如果需要更多信息,请告诉我。
Edit:编辑:
Using these commands:使用这些命令:
from properties import *
p = OrdinaryWaterThermoProperties()
p.Set_Tx(507.008845,1)
#a function that does the same thing as p.Set_Tx(), but uses a different input.
p.Set_Px(3.000021637933144,1)
I generated these outputs:我生成了这些输出:
After using p.Set_Tx(507.008845,1)
:使用
p.Set_Tx(507.008845,1)
后:
cpLow = 4.713721716228506
cvLow = 3.1991548400342227
cpHigh = -892771.9785675189
cvHigh = -892771.9785675189
self._s = 6.185784988287523
self._cp = -892771.9785675189
self._cv = -892771.9785675189
P = 3.000021637933144
T = 507.008845
After using p.Set_Px(3.000021637933144,1)
:使用
p.Set_Px(3.000021637933144,1)
后:
cpLow = 4.713721716228509
cvLow = 3.1991548400342205
cpHigh = 3.612225802173107
cvHigh = 2.328260186952078
self._s = 6.185784988287527
self._cp = 3.612225802173107
self._cv = 2.328260186952078
P = 3.000021637933144
T = 507.0088450000006
Note, that p.Set_Px(3.000021637933144,1)
produces the desired outputs of self._cp
and self._cv
.请注意,
p.Set_Px(3.000021637933144,1)
会产生self._cp
和self._cv
的所需输出。
After further investigation, it seems that there was a very small floating point error band (less than 1e-10) where self._s
was effectively infeasible in the C DLL.经过进一步调查,似乎在
self._s
DLL 中 self._s 存在一个非常小的浮点误差带(小于 1e-10)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.