17. 井流模型的Laplace变换数值反演

井流模型的Laplace变换数值反演

有了井流模型的Laplace 变换解后,大部分情况下很难通过 Laplace 逆变换得出解的解析形式,只有在有限的情况可以容易得出解析。这时 Laplace 变换数值反演就有了用武之地。

以下内容源自地下水动力学课程的补充材料,以 Theis 解为例,其他井流函数可以用类似方法求得。

s=\frac{Q}{4\pi T}W(u)=\frac{Q}{4\pi T}\mathscr{L}^{-1}\left\{\frac{2}{p}K_0\left(\sqrt{\frac{p}{a}}r\right)\right\}

式中,u=\frac{r^2S}{4Tt}

b=\frac{r^2}{4a},得

\frac{1}{b}W\left(\frac{1}{\frac{t}{b}}\right)=\mathscr{L}^{-1}\left\{\frac{2}{bp}K_0(2\sqrt{bp})\right\}

由 Laplace 变换性质

\mathscr{L}^{-1}\left\{F(bp)\right\}=\frac{1}{b}f\left(\frac{t}{b}\right)

t^\ast=t/bp^\ast=bp,有

W\left(\frac{1}{t^\ast}\right)=\mathscr{L}^{-1}\left\{\frac{2}{p^\ast}K_0(2\sqrt{p^\ast})\right\}=W(u)

u=0.01,即 t^\ast=\frac{1}{u}=100,可以计算出 W(0.01)

Stehfest 算法

Stehfest 方法是一种非常简单的拉普拉斯逆变换数值方法。该算法速度快,通常能给出很好的结果,尤其是对于光滑函数。值得注意的是,Stehfest 首次发表的数学模型是错误的,后来修订如下:

F(p) 为函数 f(t) 的 Laplace 变换,Stehfest 算法公式如下:

f(t)\approx\frac{\ln 2}{t}\sum\limits_{i=1}^{n} c_iF\left(\frac{i\ln 2}{t}\right)

式中,c_i 为 Stehfest 系数,按如下公式计算:

c_i=(-1)^{i+\frac{n}{2}}\sum\limits_{k=\left[\frac{i+1}{2}\right]}^{min(i,\frac{n}{2})} \frac{k^{\frac{n}{2}}(2k)!}{(\frac{n}{2}-k)!k!(k-1)!(i-k)!(2k-i)!}

先定义一个测试函数:

def timer(func):
    def func_wrapper(*args, **kwargs):
        from time import time

        time_start = time()
        result = func(*args, **kwargs)
        time_end = time()
        time_spend = time_end - time_start
        print("%s cost time: %.6f s" % (func.__name__, time_spend))
        return result

    return func_wrapper

Stehfest 算法程序

import math as math
import scipy.special as sp
'''
    This uses the Stehfest algorithm to invert a Laplace transform. See Stehfest,H.
    (1970) "Numerical inversion of Laplace transforms," Comm. ACM, Vol.13, No.1,
    pages 47-49 and 624. The approximation has the nature of an asymptotic series,
    in which n is the number of terms used. Thus, n shuld not exceed about 20, and
    n = 10 is probably sufficient for most applications. Note that n must be an even
    integer and that t = time. Beware: this works well for some transforms but very
    poorly for others. Furthermore, a value for n that is slightly too large can
    cause a dramatic decrease in accuracy.

    Copyright © Dr Bruce Hunt 2003  
'''

def stehcoef(i, n):
    nhlf = int(n/2)
    k1 = (i + 1)//2
    k2 = min(i, nhlf)
    stehcoef = 0.0
    for k in range(k1, k2 + 1):
        stehcoef = stehcoef + k**nhlf*math.factorial(2*k)/math.factorial(nhlf-k)/ \
        math.factorial(k)/math.factorial(k-1)/math.factorial(i-k)/math.factorial(2*k-i)
    return (-1)**(i + nhlf)*stehcoef

def lapinv(t, N):
    
    if N%2 != 0: N += 1
    
    lapinv = 0.0
    a = math.log(2.0)/t
    
    for i in range(1,N+1):
        lapinv = lapinv+stehcoef(i, N)*transform(i*a)
    
    return lapinv*a

验证:

def transform(p):
    return 2*sp.kv(0, 2*math.sqrt(p))/p

@timer
def test_Stehfest():
    u = []
    W = []
    for i in range(-5, 2):
        u.append(10**i)
        W.append(lapinv(10**(-i), 20))
      
    print(u)
    print(W)

test_Stehfest()
[1e-05, 0.0001, 0.001, 0.01, 0.1, 1, 10]
[10.935586387181772, 8.633328189684693, 6.331430232420058, 4.037790209571647, 1.8229829978456118, 0.21938416309114728, 4.189303016734773e-06]
test_Stehfest cost time: 0.000685 s

Talbot 算法

刚开始学习时看的是英文文献,意思是逆变换等价于复平面 Bromwich 轮廓积分,如果轮廓为围绕负实轴的抛物线,Talbot 方法可使积分快速收敛。想进一步了解 Talbot 算法可参考相关文献。

Talbot 算法用到复数计算库 cmath中的 cmath.exp()函数。

Talbot 算法程序

# -*- coding: utf-8 -*-
'''
    Talbot suggested that the Bromwich line be deformed into a contour that begins
    and ends in the left half plane, i.e., z → −∞ at both ends.
    Due to the exponential factor the integrand decays rapidly
    on such a contour. In such situations the trapezoidal rule converge
    extraordinarily rapidly.
    For example here we compute the inverse transform of F(s) = 1/(s+1) at t = 1

    >>> error = Talbot(1,24)-exp(-1)
    >>> error
      (3.3306690738754696e-015+0j)

    Talbot method is very powerful here we see an error of 3.3e-015
    with only 24 function evaluations

    Created by Fernando Damian Nieuwveldt      
    email:fdnieuwveldt@gmail.com
    Date : 25 October 2009

    Reference
    L.N.Trefethen, J.A.C.Weideman, and T.Schmelzer. Talbot quadratures
    and rational approximations. BIT. Numerical Mathematics,
    46(3):653 670, 2006.
'''
import scipy.special as sp    # scipy.special 库计算Bessel函数,如 sp.kv(n, x)等。
import cmath as cmath         # 程序中用 cmath 库实现复数运算。

def talbot(t, N):
#   Initiate the stepsize
    h = 2.0*cmath.pi/N;

#   Shift contour to the right in case there is a pole on the positive real axis : 
#   Note the contour will not be optimal since it was originally devoloped for function 
#   with singularities on the negative real axis 
#   For example take F(s) = 1/(s-1), it has a pole at s = 1, the contour needs to be shifted
#   with one unit, i.e shift  = 1. But in the test example no shifting is necessary
    
    shift = 0.0;
    ans =  0.0;
    
    if t == 0:
        print("ERROR:  Inverse transform can not be calculated for t=0")
        return ("Error")

#   The for loop is evaluating the Laplace inversion at each point theta which is based on the
#   trapezoidal rule
    for k in range(0, N):
        theta = -cmath.pi + (k + 0.5)*h

        z = shift + N/t*(0.5017*theta/cmath.tan(0.6407*theta) - 0.6122 + 0.2645j*theta)
        dz = N/t*(-0.5017*0.6407*theta/(cmath.sin(0.6407*theta)**2) + 0.5017/cmath.tan(0.6407*theta) + 0.2645j)

        ans = ans + cmath.exp(z*t)*transform(z)*dz;
        
    return ((h/(2.0j*cmath.pi))*ans).real

验证:

#  Here is the Laplace function to be inverted, should be changed manually
def transform(p):
    return 2*sp.kv(0, 2*cmath.sqrt(p))/p

N = 24

@timer
def test_talbot():
    u = []
    W = []
    for i in range(-5, 2):
        u.append(10**i)
        W.append(talbot(10**(-i), N))
      
    print(u)
    print(W)

test_talbot()
[1e-05, 0.0001, 0.001, 0.01, 0.1, 1, 10]
[10.935719800043493, 8.63322470457448, 6.331539364135962, 4.037929576537966, 1.8229239584192654, 0.21938393439543072, 4.156968879129344e-06]
test_talbot cost time: 0.001674 s

用于任意精度浮点运算的 Python 库 mpmath 中也有 Laplace 数值反演的函数 mpmath.invertlaplace(),需要注意的是程序中所用的 Bessel 函数也必须用库中的函数 mpmath.besselk()

我们知道,Theis 解的 Laplace 变换为如下形式

\overline{s}\doteq \frac{Q}{4\pi T}\frac{2}{p}K_0\left(\sqrt{\frac{p}{a}}r\right)

式中,a=T/S

井函数还可以按如下方法计算。

  • 按上式定义 Laplace 变换函数;
  • 给出参数 Q,\ T,\ S,\ r 的值,如都取值 1;
  • 给出 u 的值,如 u=[1e-05, 1e-04, 1e-03, 1e-02, 1e-01, 1, 10]
  • t=\frac{r^2S}{4Tu} 计算 t
  • 调用 talbot(t, N) 函数,返回值为降深 s
  • 井函数的值为 \frac{4 \pi T s}{Q}

代码如下:

Q, S, T, a, r = 1., 1., 1., 1., 1.

def transform(p):
    return Q*sp.kv(0, cmath.sqrt(p/a)*r)/(2.0*math.pi*T*p)

N = 24

@timer
def test_talbot2():
    u = []
    W = []
    for i in range(-5, 2):
        u1 = 10**i
        u.append(u1)
        t = r**2.*S/(4.*T*u1)
        W.append(talbot(t, N)*4.*math.pi*T/Q)
      
    print(u)
    print(W)

test_talbot2() 
[1e-05, 0.0001, 0.001, 0.01, 0.1, 1, 10]
[10.935719800043474, 8.63322470457447, 6.331539364135964, 4.037929576537967, 1.8229239584192658, 0.21938393439543072, 4.156968879129344e-06]
test_talbot2 cost time: 0.001005 s

对比计算结果可以得出,Talbot 算法比 Stehfest 算法精度高,对比其他方法数值反演更为灵活。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容