15. Theis 公式非線性擬合求參(最小二乘,Python)

歡迎點評!如果公式亂碼袁辈,請用瀏覽器訪問马篮,用鼠標右鍵 -> 加載映像 顯示公式秃励。

需要安裝的庫:Jupyter傍念,Jupyterlab,numpy筏餐,scipy开泽,matplotlib,ipympl魁瞪,mpl_interactions

pip 安裝:

pip install Jupyter Jupyterlab numpy scipy matplotlib ipympl mpl_interactions

以下內(nèi)容源自地下水動力學課程教學內(nèi)容穆律,程序可在 Jupyter notebook 中運行。

非線性擬合 — Theis 公式

Theis 公式是非線性的导俘,所以需要將其轉(zhuǎn)化為初始參數(shù)附近的線性形式峦耘,如用泰勒級數(shù)展開并忽略高階項,我們要從初始參數(shù)開始尋找參數(shù)變化的最優(yōu)步長旅薄。據(jù)此可使用最小二乘法擬合辅髓。

s= \frac{Q}{4\pi T}\int_u^\infty\frac{1}{y}e^{-y}dy=\frac{Q}{4\pi T}W(u)\tag{1}

取初始參數(shù) T_0S_0少梁,降深 s 的泰勒級數(shù)展開為

s(T,S)=s(T_0,S_0)+\frac{\partial{s}}{\partial{S}}\Bigg|_{S=S_0}\Delta{S}+\frac{\partial{s}}{\partial{T}}\Bigg|_{T=T_0}\Delta{T}+O(\Delta{T}^2+\Delta{S}^2) \tag{2}

式中洛口,\Delta{T} = T-T_0,\Delta{S}=S-S_0。因為 \frac{\partial{u}}{\partial{S}}=\frac{u}{S}, \frac{\partial{u}}{\partial{T}}=-\frac{u}{T} 凯沪,得

\frac{\partial{s}}{\partial{S}} = -\frac{Q}{4{\pi}T}\frac{e^{-u}}{S},\quad \frac{\partial{s}}{\partial{T}} = \frac{Q}{4{\pi}T^2}\left[-W(u)+e^{-u}\right]

a=\left.\frac{\partial{s}}{\partial{S}}\right|_{S=S_0},\quad b=\left.\frac{\partial{s}}{\partial{T}}\right|_{T=T_0},\quad c=s(T_0,S_0) \tag{3}

忽略高階無窮小第焰,(2) 式可寫為

\hat s =c +a\cdot\Delta S + b\cdot \Delta T \tag{4}

式 (4) 為 Theis 公式取參數(shù)(T_0,S_0)時參數(shù)微小變化的線性近似式。

從初始參數(shù)出發(fā)妨马,確定最優(yōu)步長 (\Delta T, \Delta S)挺举,可以得到一步優(yōu)化的參數(shù)。

(\Delta T, \Delta S) 為未知系數(shù), \hat ss 的預測值烘跺,a,b,c 根據(jù)初始參數(shù)(T_0,S_0)及觀測時間計算湘纵,由此式可構造最小二乘問題。

程序設計需要考慮以下問題

  • 最小二乘法得出的 (T_0+\Delta T,S_0+\Delta S) 有時為不合理的負值滤淳,這是需要收縮步長使參數(shù)為正值梧喷。可以用二分法縮小步長保證參數(shù)為正值;
  • 最小二乘法只是在初值的基礎上進行了一步優(yōu)化铺敌。為了得到最優(yōu)參數(shù)绊困,需要用得出的參數(shù)作為新的參數(shù)初值迭代計算;
  • 初值對計算效率有影響适刀,簡單方法是選取兩組觀測數(shù)據(jù)按 Jacob 公式計算參數(shù)初值。

直接上代碼

%matplotlib widget

import numpy as np
import matplotlib.pyplot as plt
from scipy.special import exp1

# 控制小數(shù)的顯示精度
np.set_printoptions(precision=4)

def calc_u(p, r, t):   # 計算變量 u
    S, T = p
    return r**2*S/4/T/t

# 定義井函數(shù)計算方法煤蹭,可用 scipy.special.exp1 計算. 
# 也可用多項式逼近的方法計算井函數(shù)
def theis_drawdown(p, t, Q, r):  # 計算降深
    S, T = p
    u = calc_u(p, r, t)
    s_theis = Q/4/np.pi/T*exp1(u)
    return s_theis

def theis_Dfun(p, t, s, Q, r):  # 計算 ds/dT,ds/S
    """Calculate and return ds/dS and ds/dT for the Theis equation.
    The parameters S, T are packed into the tuple p.
    """
    S, T = p
    u = calc_u(p, r, t)
    dsdS = -Q/4/np.pi/T/S*np.exp(-u)
    dsdT = Q/4/np.pi/T**2*(-exp1(u) + np.exp(-u))
    return np.array((-dsdS, -dsdT)).T   # 返回負梯度

def theis_resid(p, t, s, Q, r): # 計算降深預測誤差
    S, T = p
    return s - theis_drawdown(p, t, Q, r)

# 抽水量 Q, 觀測孔位置 r
r = 125.0  # m, 15#孔位置
Q = 1440   # m^3/d

t=np.array([10., 20., 30., 40., 60., 80., 100., 120., 150., \
            210., 270., 330., 400., 450., 645., 870., 990., 1185.]) / 1440  # 單位 day
s = np.array([0.16, 0.48, 0.54, 0.65, 0.75, 1., 1.12, 1.22, 1.36, 1.55, 1.7, \
              1.83, 1.89, 1.98, 2.17, 2.38, 2.46, 2.54])  # m

# 取數(shù)組長度
n = len(t)

# 初始參數(shù)怎么缺屎怼?最簡單方法是取中間相鄰的兩點硝皂,用 Jacob 兩點公式計算常挚。
# 取數(shù)組長度
n = len(t)
i1 = int(n/2)
i2 = i1 + 1
t1 = t[i1]
t2 = t[i2]
s1 = s[i1]
s2 = s[i2]
kk = (s1 - s2)/np.log10(t1/t2)
T0 = 0.183*Q/kk
S0 = 2.25*T0*t1/r**2/np.float_power(10, s1/kk)

p = S0, T0 
S, T = p

# 循環(huán)計數(shù)器
j = 0
while True:
    c = theis_drawdown(p, t, Q, r)
    a = theis_Dfun(p, t, s, Q, r)[:, 0]
    b = theis_Dfun(p, t, s, Q, r)[:, 1]
    X = np.vstack([a, b]).T  # 形成系數(shù)矩陣
    # 調(diào)用 np.linalg.solve
    beta = np.linalg.solve(np.dot(X.T, X), np.dot(X.T, c - s))
    DS = beta[0]
    DT = beta[1]
  
    while True:
        if S + DS < 0:    # 步子太大扯了蛋,參數(shù)為負不合理稽物!
            DS = DS/2.0  # 縮回半步
        else:
            break 
    while True:
        if T + DT < 0:    # 步長太大奄毡,參數(shù)為負數(shù)不合理!
            DT = DT/2.0  # 縮回半步
        else:
            break
    j = j + 1  # 循環(huán)計數(shù)器
    if j > 1000:  # 循環(huán)次數(shù)多贝或,程序可能有錯誤
        print('  循環(huán)超過 1000 次吼过,請先檢查程序再運行!')
        break
    if (abs(DT) < 1.0E-6) or (abs(DS) < 1.0e-8):  # 判斷計算誤差
        break
    # 新參數(shù)值
    p = S + DS, T + DT
    S, T = p

# 生成繪圖數(shù)據(jù)
x0 =[i for i in np.arange(-3, 0.1, 0.1)]
x =np.power(10, x0)
y = theis_drawdown(p, x, Q, r)
plt.style.use('default')
fig, ax = plt.subplots(dpi=100)
ax.grid(True)
ax.set_xscale("log")
ax.set_yscale("log")
ax.set_xlim(0.001, 1)
ax.set_ylim(0.1, 10)
ax.set_aspect(1)
ax.plot(t, s, 'o', label='觀測值')
ax.plot(x, y, label='擬合曲線')
plt.xlabel(r'$\log t$') 
plt.ylabel(r'$\log s$')

plt.legend(
    prop={'family': 'Kaiti', 'size': 10},
    loc=4,title="圖例",
    title_fontproperties={'family': 'Simsun'})
# 指定圖標題咪奖,顯示中文
ax.set_title("Theis公式最小二乘法求參", fontproperties={'family': 'Simsun'})  

plt.show()

# 顯示最終結(jié)果
print('循環(huán)次數(shù) = {}'.format(j))
print('T = {:.2f} m^2/d,'.format(T), 'S = {:.4e}'.format(S))
print('RSS = {:.4e}'.format(np.sqrt(np.sum((c - s)**2))))
image.png
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末盗忱,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子羊赵,更是在濱河造成了極大的恐慌趟佃,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件昧捷,死亡現(xiàn)場離奇詭異闲昭,居然都是意外死亡,警方通過查閱死者的電腦和手機靡挥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來芹血,“玉大人贮泞,你說我怎么就攤上這事♂V颍” “怎么了啃擦?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長饿悬。 經(jīng)常有香客問我令蛉,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任珠叔,我火速辦了婚禮蝎宇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘祷安。我一直安慰自己姥芥,他們只是感情好,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布汇鞭。 她就那樣靜靜地躺著凉唐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪霍骄。 梳的紋絲不亂的頭發(fā)上台囱,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機與錄音读整,去河邊找鬼簿训。 笑死,一個胖子當著我的面吹牛米间,可吹牛的內(nèi)容都是我干的强品。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼车伞,長吁一口氣:“原來是場噩夢啊……” “哼择懂!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起另玖,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤困曙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后谦去,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體慷丽,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年鳄哭,在試婚紗的時候發(fā)現(xiàn)自己被綠了要糊。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡妆丘,死狀恐怖锄俄,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情勺拣,我是刑警寧澤奶赠,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站药有,受9級特大地震影響毅戈,放射性物質(zhì)發(fā)生泄漏苹丸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一苇经、第九天 我趴在偏房一處隱蔽的房頂上張望赘理。 院中可真熱鬧,春花似錦扇单、人聲如沸商模。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽阻桅。三九已至,卻和暖如春兼都,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背稽寒。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工扮碧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人杏糙。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓慎王,卻偏偏與公主長得像,于是被迫代替她去往敵國和親宏侍。 傳聞我的和親對象是個殘疾皇子赖淤,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容