Files
sjy01-image-proc/vendor/github.com/nuknal/goNum/ODEDiff.go
2024-10-24 15:46:01 +08:00

121 lines
4.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ODEDiff
/*
------------------------------------------------------
作者 : Black Ghost
日期 : 2018-12-26
版本 : 0.0.0
------------------------------------------------------
差分方法求解常微分方程
理论:
对于常微分方程x''(t) = p(t)x'(t)+q(t)(t)+r(t)
机器边值x(a) = x0, x(b) = xN
使用中心差分公式可得
x_(j+1)-2xj+x_(j-1) x_(j+1)-x_(j-1)
--------------------- = pj----------------- + qj*xj+rj
h^2 2h
-h h
(---pj-1)x_(j-1) + (2+h^2*qj)xj + (---pj-1)x_(j+1) = -h^2*rj
2 2
下标j表示*(tj), tj=a+j*h(区间[a, b]等分为N等份)
整理成N-1阶线性方程组:
|2+h^2*q1 h*p1/2-1 |
|-h*p2/2-1 2+h^2*q2 h*p2/2-1 |
| -h*p3/2-1 2+h^2*q3 h*p3/2-1 |*
| ...... |
| -h*p_(N-2)/2-1 2+h^2*q_(N-2) h*p_(N-2)/2-1|
| -h*p_(N-1)/2-1 2+h^2*q_(N-1)|
[x1 x2 x3 ... x_(N-1)]' =
[-h^2*r1+e0 -h^2*r2 -h^2*r3 ... -h^2*r_(N-2) -h^2*r_(N-1)+eN]'
其中:
e0 = (h*p1/2+1)x0, eN = (h*p_(N-1)/2+1)xN
参考John H. Mathews and Kurtis D. Fink. Numerical
methods using MATLAB, 4th ed. Pearson
Education, 2004. ss 9.9
------------------------------------------------------
输入 :
funp, funq, funr 被积分函数系数
x0 初值,2x2, 按列a, b
Nn 积分步数
输出 :
sol 解矩阵, 2x(Nn+1)
err 解出标志false-未解出或达到步数上限;
true-全部解出
------------------------------------------------------
*/
package goNum
// ODEDiff 差分方法求解常微分方程
func ODEDiff(funp, funq, funr func(float64) float64, x0 Matrix, Nn int) (Matrix, bool) {
/*
差分方法求解常微分方程
输入 :
funp, funq, funr 被积分函数系数
x0 初值,2x2, 按列a, b
Nn 积分步数
输出 :
sol 解矩阵, 2x(Nn+1)
err 解出标志false-未解出或达到步数上限;
true-全部解出
*/
//判断x0维数
if (x0.Rows != 2) || (x0.Columns != 2) {
panic("Error in goNum.ODEDiff: Initial values error")
}
//判断Nn
if Nn < 1 {
panic("Error in goNum.ODEDiff: Nn must greater than zero")
} else if Nn == 1 {
return x0, true
}
sol := ZeroMatrix(2, Nn+1)
var err bool = false
Aa := ZeroMatrix(Nn-1, Nn-1)
Bb := ZeroMatrix(Nn-1, 1)
h := (x0.GetFromMatrix(0, 1) - x0.GetFromMatrix(0, 0)) / float64(Nn)
//ti
for i := 0; i < Nn+1; i++ {
sol.SetMatrix(0, i, x0.GetFromMatrix(0, 0)+h*float64(i))
}
//x0, xN
sol.SetMatrix(1, 0, x0.GetFromMatrix(1, 0))
sol.SetMatrix(1, Nn, x0.GetFromMatrix(1, 1))
//第一行
Aa.SetMatrix(0, 0, 2.0+h*h*funq(sol.GetFromMatrix(0, 1)))
Aa.SetMatrix(0, 1, h*funp(sol.GetFromMatrix(0, 1))/2.0-1.0)
e0 := (h*funp(sol.GetFromMatrix(0, 1))/2.0 + 1.0) * sol.GetFromMatrix(1, 0)
Bb.SetMatrix(0, 0, -1.0*h*h*funr(sol.GetFromMatrix(0, 1))+e0)
for i := 1; i < Nn-2; i++ {
Aa.SetMatrix(i, i-1, -1.0*h*funp(sol.GetFromMatrix(0, i+1))/2.0-1.0)
Aa.SetMatrix(i, i, 2.0+h*h*funq(sol.GetFromMatrix(0, i+1)))
Aa.SetMatrix(i, i+1, h*funp(sol.GetFromMatrix(0, i+1))/2.0-1.0)
Bb.SetMatrix(i, 0, -1.0*h*h*funr(sol.GetFromMatrix(0, i+1)))
}
//最后行
Aa.SetMatrix(Nn-2, Nn-2-1, -1.0*h*funp(sol.GetFromMatrix(0, Nn-1))/2.0-1.0)
Aa.SetMatrix(Nn-2, Nn-2, 2.0+h*h*funq(sol.GetFromMatrix(0, Nn-1)))
eN := (-1.0*h*funp(sol.GetFromMatrix(0, Nn-1))/2.0 + 1.0) * sol.GetFromMatrix(1, Nn)
Bb.SetMatrix(Nn-2, 0, -1.0*h*h*funr(sol.GetFromMatrix(0, Nn-1))+eN)
//求解线性方程组LEs_Chasing
xTemp, errTemp := LEs_Chasing(Aa, Bb)
if errTemp != true {
panic("Error in goNum.ODEDiff: Solve error")
}
//xTemp赋予sol
for i := 1; i < Nn; i++ {
sol.SetMatrix(1, i, xTemp.GetFromMatrix(i-1, 0))
}
err = true
return sol, err
}