Python рудиментарный параметр и не вызываемая функция - PullRequest
2 голосов
/ 15 марта 2020
import numpy as np
from scipy.optimize import fsolve
from scipy.integrate import quad
import matplotlib.pyplot as plt

Rgas = 8.31446261815324 #Pa*m**3/mol*K

def Peng_Robinson_EOS(P,V,T,Tc,Pc,ω):
    a = (1+(0.37464+1.54226*ω-0.26992*ω**2)*(1-(T/Tc)**(1/2)))**2*Rgas**2*Tc**2/Pc #Pa*m**3
    b = 0.07780 * Rgas*Tc/Pc
    return P + a/((V+(1-np.sqrt(2))*b)*(V+(1+np.sqrt(2)))) - Rgas*T/(V-b)

def PR_Psat(T,Tc,Pc,ω,V,Pguess = 100000):
    def integral_diff (Pguess,T,Tc,Pc,ω,V):
        def Psat_integrand (V,Pguess,T,Tc,Pc,ω):
            integrand1 = fsolve(Peng_Robinson_EOS(Pguess,V,T,Tc,Pc,ω),Pguess)
            integrand2 = Pguess
            integrand  = integrand1-integrand2
            return integrand
        Vl         = fsolve(Psat_integrand(V,Pguess,T,Tc,Pc,ω),0)

        Vv_guess   = Rgas*T/Pguess
        Vv         = fsolve(Psat_integrand(V,Pguess,T,Tc,Pc,ω),Vv_guess)

        Vinf_guess = (Vl + Vv)/2
        Vinf       = fsolve(Psat_integrand(V,Pguess,T,Tc,Pc,ω),Vinf_guess)

        left       = quad(Psat_integrand(V,Pguess,T,Tc,Pc,ω),Vl,Vinf)[0]
        right      = quad(Psat_integrand(V,Pguess,T,Tc,Pc,ω),Vinf,Vv)[0]
        diff       = left + right
        return diff
    Psat = fsolve(integral_diff(Pguess,T,Tc,Pc,ω,V),Pguess)
    return Psat

У этого кода есть две проблемы.

1: теоретически PR_Psat не должно зависеть от V, поскольку все значения V, используемые в вычислениях, находятся через fsolve. Однако, поскольку Peng_Robinson_EOS зависит от V, оно Python не позволит игнорировать его в окружающих функциях. Есть ли способ устранить необходимость «указывать» V?

из более ранней версии (до того, как V был параметром всех функций), чтобы продемонстрировать:

runfile('...', wdir='...')
Traceback (most recent call last):

  File "<ipython-input-4-0875bc6411e8>", line 1, in <module>
    runfile('...', wdir='...')

  File "...\lib\site-packages\spyder\utils\site\sitecustomize.py", line 705, in runfile
    execfile(filename, namespace)

  File "...\lib\site-packages\spyder\utils\site\sitecustomize.py", line 102, in execfile
    exec(compile(f.read(), filename, 'exec'), namespace)

  File "...", line 40, in <module>
    print(PR_Psat(300,647.1,22055000,0.345))

  File "...", line 37, in PR_Psat
    Psat = fsolve(integral_diff(Pguess,T,Tc,Pc,ω),Pguess)

  File "...", line 25, in integral_diff
    Vl         = fsolve(Psat_integrand(V,Pguess,T,Tc,Pc,ω),0)

NameError: name 'V' is not defined

2 : Похоже, что Peng_Robinson рассматривается не как вызываемая функция, а как float. Я не уверен, что является причиной этого.

runfile('...', wdir='...')
Traceback (most recent call last):

  File "<ipython-input-13-0875bc6411e8>", line 1, in <module>
    runfile('...', wdir='...')

  File "C:\Users\Spencer\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 705, in runfile
    execfile(filename, namespace)

  File "...\lib\site-packages\spyder\utils\site\sitecustomize.py", line 102, in execfile
    exec(compile(f.read(), filename, 'exec'), namespace)

  File "...", line 42, in <module>
    print(PR_Psat(300,647.1,22055000,0.345,1))

  File "...", line 39, in PR_Psat
    Psat = fsolve(integral_diff(Pguess,T,Tc,Pc,ω,V),Pguess)

  File "...", line 27, in integral_diff
    Vl         = fsolve(Psat_integrand(V,Pguess,T,Tc,Pc,ω),0)

  File "...", line 23, in Psat_integrand
    integrand1 = fsolve(Peng_Robinson_EOS(Pguess,V,T,Tc,Pc,ω),Pguess)

  File "...\lib\site-packages\scipy\optimize\minpack.py", line 148, in fsolve
    res = _root_hybr(func, x0, args, jac=fprime, **options)

  File "...\lib\site-packages\scipy\optimize\minpack.py", line 214, in _root_hybr
    shape, dtype = _check_func('fsolve', 'func', func, x0, args, n, (n,))

  File "...\lib\site-packages\scipy\optimize\minpack.py", line 27, in _check_func
    res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))

TypeError: 'numpy.float64' object is not callable

Теоретически, Peng_Robinson_EOS должно, если изображено как P (V) с константой T, создать куб c регрессия. Цель PR_Psat - найти значение P, для которого отменяются интегралы между P и регрессией cubi c. (Следовательно, integral_diff подключается к fsolve)

Чтобы суммировать вопросы,

1) Есть ли способ устранить необходимость в V в PR_Psat?

2) Почему Peng_Robinson_EOS помечается как не вызываемый numpy .float64 объект?

1 Ответ

0 голосов
/ 15 марта 2020

Проблема была в синтаксической ошибке. Аргументы для fsolve и quad были неверными. Чтобы исправить обе проблемы, я переместил аргументы назад. Например,

неверно:

Vv         = fsolve(Psat_integrand(V,Pguess,T,Tc,Pc,ω),Vv_guess)

правильно:

Vv         = fsolve(Psat_integrand,Vv_guess,args=(Pguess,T,Tc,Pc,ω))

Причина, по которой Peng_Robinson_EOS называется numpy.float64, заключается в том, что с синтаксисом код в вопросе, который оценивается программой перед передачей в решатель.

Кроме того, при правильном синтаксисе V больше не является проблемой.

def PR_Psat(T,Tc,Pc,ω,Pguess = 1000):
    def integral_diff (Pguess,T,Tc,Pc,ω):
        def Psat_integrand (V,Pguess,T,Tc,Pc,ω):
            integrand1 = fsolve(Peng_Robinson_EOS,Pguess,args=(V,T,Tc,Pc,ω))
            integrand2 = Pguess
            integrand  = integrand1-integrand2
            return integrand
        Vl         = fsolve(Psat_integrand,0,args=(Pguess,T,Tc,Pc,ω))

        Vv_guess   = Rgas*T/Pguess
        Vv         = fsolve(Psat_integrand,Vv_guess,args=(Pguess,T,Tc,Pc,ω))

        Vinf_guess = (Vl + Vv)/2
        Vinf       = fsolve(Psat_integrand,Vinf_guess,args=(Pguess,T,Tc,Pc,ω))

        left       = quad(Psat_integrand,Vl,Vinf,args=(Pguess,T,Tc,Pc,ω))[0]
        right      = quad(Psat_integrand,Vinf,Vv,args=(Pguess,T,Tc,Pc,ω))[0]
        diff       = left + right
        return diff
    Psat = fsolve(integral_diff,Pguess,args=(T,Tc,Pc,ω))
    return Psat
...