// 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 }