Странная ситуация при использовании функций из C DLL в Python - PullRequest
0 голосов
/ 21 июня 2020

У меня странная проблема, когда я использую функции DLL, которые возвращают более или менее одинаковое значение с плавающей запятой (т.е. их остаток меньше 1e-08), но я как-то наблюдаю другое поведение.

Вот общий способ написания прототипов функций на Python; этой информации должно быть достаточно, чтобы дать вам представление о том, как я делаю эту часть.

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

Далее я пишу пару классов, которые предназначены для выполнения кучи вычислений и удержания куча данных о свойствах.

Root класс

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')

бетонный класс

class OrdinaryWaterThermoProperties(ThermoProperties):

    _owtp = OWTP()

    def __init__(self):
        super(ThermoProperties, self).__init__()
        self._x = float('nan')

А теперь для рассматриваемой функции, которая находится на OrdinaryWaterThermoProperties

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)

Проблема в том, что последние 2 строки дают какое-то нелепое число. Сначала я, очевидно, подумал, что это просто проблема с библиотекой, которую я написал, но, когда я пробовал больше вещей, я не так уверен в этом сейчас.

Эта строка self._s = self._owtp.s_Tx(T,x) хранит почти идентичное значение (т. е. остаток меньше 1e-08), если я заменю его этим self._s = self._owtp.s_Px(P,x), но как только я сделаю замену, эти последние 2 строки оцениваются как справочные значения, которые у меня есть.

Is что-то я сделал не так, или что-то, что делает Python, о чем я не знаю?

Я просто хочу знать, почему именно это происходит.

Пожалуйста, дайте мне знать, если потребуется дополнительная информация.

Изменить:

Используя эти команды:

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)

Я сгенерировал эти выходные данные:

После использования 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

После использования 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

Обратите внимание, что p.Set_Px(3.000021637933144,1) производит желаемые выходные значения self._cp и self._cv.

1 Ответ

0 голосов
/ 21 июня 2020

После дальнейшего исследования выяснилось, что имелась очень маленькая полоса ошибок с плавающей запятой (менее 1e-10), где self._s было фактически недопустимым в C DLL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...