简体   繁体   English

Python GEKKO:如何将函数插入求解器?

[英]Python GEKKO: how to insert a function into the solver?

I have quite a big project I want to solve with GEKKO.我有一个很大的项目想用 GEKKO 解决。 It consists of quite a large number of partial differential equations, and I have a function that uses an iterative process to calculate steady state "leak".它由相当多的偏微分方程组成,我有一个使用迭代过程来计算稳态“泄漏”的函数。 However, GEKKO runs the function only during initialization.但是,GEKKO 仅在初始化期间运行该函数。 I want GEKKO to solve this task by taking into account that function.我希望 GEKKO 通过考虑该功能来解决此任务。 It would be really hard to write this function in GEKKOs equations.在 GEKKOs 方程中写这个函数真的很难。 But without GEKKO it would be really hard to solve the Partial Differential Equations.但是如果没有 GEKKO,就很难求解偏微分方程。 So I am stuck, I would appreciate any help.所以我被卡住了,我会很感激任何帮助。

Here is a simple example I want to implement这是我要实现的一个简单示例

a = 0.01

def CalculateLeak(P,a):
    a = a - P*0.1
    print("Leak is calculated")
    return a

m = GEKKO(remote = False)
tf = 10
nt = int(tf/1) + 1
m.time = np.linspace(0,tf,nt)
P = m.Var(0.1)
m.Equation(P.dt() == P*0.1 - CalculateLeak(P,a))
m.options.IMODE = 7
m.solve(disp = False)

print("Finished")
print(a)

Below is the function I actually want to add to my project.下面是我真正想要添加到我的项目中的功能。 It calculates the adsorption amount based on P (pressure), T (temperature), y1,y2,y3,y4,y5,y6 are molar fractions.它根据 P(压力)、T(温度)计算吸附量,y1、y2、y3、y4、y5、y6 是摩尔分数。 All these variables should come from the partial differential equations solved in time by GEKKO (probably except temperature which can be assumed constant some time).所有这些变量都应该来自 GEKKO 及时求解的偏微分方程(可能除了温度,它可以假设一段时间不变)。 Every time iteration this function would calculate the amount of gas adsorbed and return to Partial Diff.每次迭代时,此函数都会计算吸附的气体量并返回到 Partial Diff。 Eq.方程。 as a source term.作为源词。

import numpy as np 
import matplotlib.pyplot as plt


def FastIAST(P_gas,T,y1,y2,y3,y4,y5,y6):
    IP1_CH4                               = 0.0016     #kmol/kg
    IP2_CH4                               = 0          #1/bar
    IP3_CH4                               = 4.2E-05    #1/bar
    IP4_CH4                               = 2922.78    #K

    IP1_C2H6                              = 0.0027     #kmol/kg
    IP2_C2H6                              = 0.0        #1/bar 
    IP3_C2H6                              = 2.66E-04   #1/bar
    IP4_C2H6                              = 2833.77    # K

    IP1_C3H8                              = 0.0062     #kmol/kg
    IP2_C3H8                              = 0.0        #1/bar 
    IP3_C3H8                              = 3.75E-04   #1/bar
    IP4_C3H8                              = 2795.28    #K

    IP1_C4H10                             = 0.007      #kmol/kg
    IP2_C4H10                             = 0.0        #1/bar 
    IP3_C4H10                             = 0.0015     #1/bar
    IP4_C4H10                             = 2600       #K

    IP1_CO2                               = 0.0028     #kmol/kg
    IP2_CO2                               = 0.0        #(kmol/kg)/bar 
    IP3_CO2                               = 0.000748   #1/bar
    IP4_CO2                               = 2084.44    #K

    IP1_N2                                = 0.0075     #kmol/kg
    IP2_N2                                = 0.0        #(kmol/kg)/bar 
    IP3_N2                                = 0.00099    #1/bar
    IP4_N2                                = 935.77     #K
    
    Q1 = IP1_CH4 - IP2_CH4*T # Isotherm max capacity CH4
    Q2 = IP1_C2H6 - IP2_C2H6*T # Isotherm max capacity C2H6
    Q3 = IP1_C3H8 - IP2_C3H8*T # Isotherm max capacity C3H8
    Q4 = IP1_C4H10 - IP2_C4H10*T # Isotherm max capacity C4H10
    Q5 = IP1_CO2 - IP2_CO2*T # Isotherm max capacity CO2
    Q6 = IP1_N2 - IP2_N2*T  # Isotherm max capacity N2


    b1 = IP3_CH4*np.exp(IP4_CH4/T) # Isotherm affinity coeff. CH4
    b2 = IP3_C2H6*np.exp(IP4_C2H6/T) # Isotherm affinity coeff. C2H6
    b3 = IP3_C3H8*np.exp(IP4_C3H8/T) # Isotherm affinity coeff. C3H8
    b4 = IP3_C4H10*np.exp(IP4_C4H10/T) # Isotherm affinity coeff. C4H10
    b5 = IP3_CO2*np.exp(IP4_CO2/T) # Isotherm affinity coeff. CO2
    b6 = IP3_N2*np.exp(IP4_N2/T) # Isotherm affinity coeff. N2
    error = 0 # 1 - there was an error in the programm, 0 - OK
    N = 6 # Number of components
    #Langmuir Isotherm
    SingleComponentCapacity = np.array([Q1,Q2,Q3,Q4,Q5,Q6]) #Langmuir Isotherm capacity of every component
    AffinityCoefficient = np.array([b1,b2,b3,b4,b5,b6]) #Langmuir Affinity Coefficient of every component
    fractionGas = np.array([y1,y2,y3,y4,y5,y6]) #Gas fraction of every component

    #Initialization
    fastiastGraphConcentration = np.zeros(N)
    fastiastGraphFraction = np.zeros(N)
    fastiastPressure = 0
    adsorbedFraction = np.zeros(N)
    adsorbedConcentration = np.zeros(N)

    #Checking..
    if (len(fractionGas) < N or len(SingleComponentCapacity) < N or len(AffinityCoefficient) < N):
        print("You have the incorrect number of components")
        error = 1
    if np.sum(fractionGas) < 0.95 or np.sum(fractionGas) > 1.05:
        error = 1
        print("The molar fractions sum is not equal to 1")

    ###Calculation###

    kappa_old = np.zeros(N)
    delta_kappa = np.ones(N)
    kappa = np.zeros(N)
    CmuT = 0


    partialPressureComponents = fractionGas*P_gas
    for k in range(N):
        CmuT += SingleComponentCapacity[k]*AffinityCoefficient[k]*partialPressureComponents[k]

    for k in range(N):
        kappa[k] = CmuT/(SingleComponentCapacity[k])

    i = 0
    while np.any((delta_kappa) > 1e-4):
        f = np.zeros(N)
        fDerivative = np.zeros(N)
        g = np.zeros(N)
        sigma = np.zeros(N)
        phi = np.zeros((N,N))
        phi = np.matrix(phi)

        for k in range(N):
            f[k] = SingleComponentCapacity[k]*(np.log(1+kappa[k]))
            fDerivative[k] = SingleComponentCapacity[k]*(1/(1+kappa[k]))

        for k in range(N-1):
            g[k] = f[k] - f[k+1]
        for k in range(N):
            g[N-1] += AffinityCoefficient[k]*partialPressureComponents[k]/kappa[k]
        g[N-1] = g[N-1] - 1 


        for k in range(N-1):
            phi[k,k] = fDerivative[k]
            phi[k,k+1] = -fDerivative[k+1]
        for k in range(0,N):
            phi[N-1,k] = - (AffinityCoefficient[k]*partialPressureComponents[k]/(kappa[k]**2))

        sigma = np.linalg.solve(phi, g)
        kappa_old = kappa
        kappa = kappa_old - sigma

        delta_kappa = np.abs(kappa-kappa_old)


        i += 1
        if i > 20 or np.any(kappa<0):
            print("No convergence")
            error = 1
            break
        if np.any(kappa < 0):
            print("No convergence")
            error = 1
            break
        adsorbedFraction = partialPressureComponents*AffinityCoefficient/kappa
        adsorbedConcentrationPure = SingleComponentCapacity*(kappa
                                      /(1+kappa))  
        
        C_total = 0
        for k in range(0,N):
            C_total += ( (adsorbedFraction[k]) / adsorbedConcentrationPure[k])
        C_total = 1/C_total
        adsorbedConcentration =  C_total*adsorbedFraction   

    fastiastGraphConcentration=np.vstack((fastiastGraphConcentration, adsorbedConcentration))
    fastiastGraphFraction=np.vstack((fastiastGraphFraction, adsorbedFraction))
    fastiastPressure=np.vstack((fastiastPressure, P_gas))
    if error == 0:
    ###Result###
        return(fastiastGraphConcentration[1,:])
    else:
        return(0)

 
FastIAST(2,298,1,0,0,0,0,0)

There is no current method to call external "black-box" functions with Gekko.目前没有使用 Gekko 调用外部“黑盒”函数的方法。 One of the reasons that Gekko performs well is that it compiles the functions to byte-code as if they were written in FORTRAN or C++ and it uses automatic differentiation to provide sparse 1st and 2nd derivatives to the solvers. Gekko 表现良好的原因之一是它将函数编译为字节码,就好像它们是用 FORTRAN 或 C++ 编写的一样,并且它使用自动微分来为求解器提供稀疏的一阶和二阶导数。 One work-around is to use a c-spline (1D) or b-spline (2D) to approximate the function if there are only one or two independent variables.如果只有一个或两个自变量,一种解决方法是使用c 样条 (1D)b 样条 (2D)来逼近函数。 The simple problem would qualify but the FastIAST has 8 independent variables so that approach wouldn't work.简单的问题可以解决,但FastIAST有 8 个独立变量,因此这种方法行不通。 There is also the deep learning library in Gekko to approximate functions of any dimension, but it may be more difficult to control the approximation error. Gekko 中也有深度学习库来逼近任意维度的函数,但可能会比较难控制逼近误差。 There are new developments coming that may allow external function calls and interfaces to other machine learning libraries that would allow function approximations.有新的发展可能允许外部函数调用和与其他机器学习库的接口,从而允许函数逼近。 As of Gekko v1.0.4, external black-box function calls aren't possible.从 Gekko v1.0.4 开始,无法调用外部黑盒函数。 Python function calls are allowed such as:允许调用 Python 函数,例如:

from gekko import GEKKO
m = GEKKO()
def f(x,c):
    y = m.sum([(xi-c)**2 for xi in x])
    return y
x1 = m.Array(m.Var,5)
p  = 2.1
m.Minimize(f(x1,p))
m.Equation(f(x1,0)<=10)
m.solve()
print(x1)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何修复 Python Gekko APMoniter 求解器错误:没有等式的方程 - How to fix Python Gekko APMoniter solver error: Equation without an equality 如何在Python Gekko中设置求解器选项(例如容错)? - How to set solver options (such as error tolerance) in Python Gekko? 在模式 6 python gekko 下运行时没有求解器显示 - no solver display while running in mode 6 python gekko 在 python 中使用 GEKKO 求解器求解约翰逊规则 - Solving Johnson rule using GEKKO solver in python 如果我的目标函数是非线性(也是指数解释)函数,我应该使用什么求解器? Python GEKKO - What solver should I use if my objective function is an nonlinear (also exponential explanation) function? Python GEKKO 如何在 Python Gekko 中最大化目标 function? - How to maximize an objective function in Python Gekko? 如何使用 GEKKO 和 APPT 检查求解器收敛性 - How to check solver convergence with GEKKO and APOPT 如何在 GEKKO 中指定 NLP 求解器设置? - How to specify NLP solver settings in GEKKO? 使用顺序求解器时,如何在 Python Gekko 中定义中间值的最大值和另一个值? - How to define maximum of Intermediate and another value in Python Gekko, when using sequential solver? Gekko 求解器不提供任何解决方案 - Gekko solver offers no solution
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM