// InterpSpline22 /* ------------------------------------------------------ 作者 : Black Ghost 日期 : 2018-12-9 版本 : 0.0.0 ------------------------------------------------------ 用节点处的二阶导数表示的三次样条插值函数, 二阶导数边界条件 n+1个点, n个区间 理论: 区间[x(i-1), xi]上的三次样条函数表达为: (xi-x)^3 Si(x) = ----------M(i-1) + 6*hi (x-x(i-1))^3 --------------Mi + 6*hi M(i-1) xi-x (y(i-1) - --------hi^2)------- 6 hi Mi x-x(i-1) (yi - ----hi^2)---------- 6 hi 令 Mi = hi/(hi+h(i+1)) lambdai = 1-Mi = h(i+1)/(hi+h(i+1)) 6 y(i+1)-yi yi-y(i-1) fi = -----------(---------- - -----------) hi+h(i+1) h(i+1) hi (i = 1,...,n-1) 则mi可由n-1阶线性方程组求得(利用LEs_Chasing): |2 l1 || M1 | | f1-M1*M0 | | M2 2 l2 || M2 | = | f2 | | ........ || ... | | ... | | M(n-2) 2 l(n-2)||M(n-2)| | f(n-2) | | M(n-1) 2 ||M(n-1)| |f(n-1)-l(n-1)Mn| 参考 李信真, 车刚明, 欧阳洁, 等. 计算方法. 西北工业大学 出版社, 2000, pp 124-127. ------------------------------------------------------ 输入 : A 数据点矩阵,(n+1)x3,第一列xi;第二列yi; 第三列y''i,且y''i只需给出y''0和y''n 输出 : B 插值方程系数结果矩阵,从前到后对应从0到3阶,4xn err 解出标志:false-未解出或达到步数上限; true-全部解出 ------------------------------------------------------ */ package goNum // InterpSpline22 用节点处的二阶导数表示的三次样条插值函数, 二阶导数边界条件 func InterpSpline22(A Matrix) (Matrix, bool) { /* 用节点处的二阶导数表示的三次样条插值函数, 二阶导数边界条件 输入 : A 数据点矩阵,(n+1)x3,第一列xi;第二列yi; 第三列y'i,且y'i只需给出y'0和y'n 输出 : B 插值方程系数结果矩阵,从前到后对应从0到3阶,4xn err 解出标志:false-未解出或达到步数上限; true-全部解出 */ var err bool = false n := A.Rows - 1 sol := ZeroMatrix(4, n) BA := ZeroMatrix(n-1, n-1) //对角占优的三对角矩阵 BB := ZeroMatrix(n-1, 1) //解向量 BC := ZeroMatrix(n-1, 1) //值向量 //1解插值函数的一阶导数mi //1.0.1第一行 if true { //限制变量使用范围 h1 := A.GetFromMatrix(1, 0) - A.GetFromMatrix(0, 0) h2 := A.GetFromMatrix(2, 0) - A.GetFromMatrix(1, 0) y0 := A.GetFromMatrix(0, 1) y1 := A.GetFromMatrix(1, 1) y2 := A.GetFromMatrix(2, 1) M1 := h1 / (h1 + h2) l1 := 1.0 - M1 f1 := 6.0 * ((y2-y1)/h2 - (y1-y0)/h1) / (h1 + h2) BA.SetMatrix(0, 0, 2.0) BA.SetMatrix(0, 1, l1) BC.Data[0] = f1 - M1*A.GetFromMatrix(0, 2) } //1.0.2其它行 for i := 2; i < n-1; i++ { yi_1 := A.GetFromMatrix(i-1, 0) yi := A.GetFromMatrix(i, 0) yi1 := A.GetFromMatrix(i+1, 0) hi := A.GetFromMatrix(i, 0) - A.GetFromMatrix(i-1, 0) hi1 := A.GetFromMatrix(i+1, 0) - A.GetFromMatrix(i, 0) Mi := hi / (hi + hi1) li := 1.0 - Mi fi := 6.0 * ((yi1-yi)/hi1 - (yi-yi_1)/hi) / (hi + hi1) //赋予BA BA.SetMatrix(i-1, i-2, Mi) BA.SetMatrix(i-1, i-1, 2.0) BA.SetMatrix(i-1, i, li) BC.Data[i-1] = fi } //1.0.3最后一行 if true { //i=n-1 hn_1 := A.GetFromMatrix(n-1, 0) - A.GetFromMatrix(n-2, 0) hn := A.GetFromMatrix(n, 0) - A.GetFromMatrix(n-1, 0) yn_2 := A.GetFromMatrix(n-2, 1) yn_1 := A.GetFromMatrix(n-1, 1) yn := A.GetFromMatrix(n, 1) Mn_1 := hn_1 / (hn_1 + hn) ln_1 := 1.0 - Mn_1 fn_1 := 6.0 * ((yn-yn_1)/hn - (yn_1-yn_2)/hn_1) / (hn_1 + hn) BA.SetMatrix(n-2, n-3, Mn_1) BA.SetMatrix(n-2, n-2, 2.0) BC.Data[n-2] = fn_1 - ln_1*A.GetFromMatrix(n, 2) } //1.1求解 soltemp, errtemp := LEs_Chasing(BA, BC) if errtemp != true { panic("Error in goNum.InterpSpline11: Solve Error with goNum.LEs_Chasing") } for i := 0; i < n-1; i++ { BB.Data[i] = soltemp.Data[i] } //2求解Si(x) S0 := ZeroMatrix(4, 1) S1 := ZeroMatrix(4, 1) S2 := ZeroMatrix(4, 1) S3 := ZeroMatrix(4, 1) for i := 1; i < n+1; i++ { xi_1 := A.GetFromMatrix(i-1, 0) xi := A.GetFromMatrix(i, 0) yi_1 := A.GetFromMatrix(i-1, 1) yi := A.GetFromMatrix(i, 1) Mi_1 := 0.0 Mi := 0.0 if i == 1 { Mi_1 = A.GetFromMatrix(0, 2) Mi = BB.Data[i-1] } else if i == n { Mi_1 = BB.Data[i-2] Mi = A.GetFromMatrix(n, 2) } else { Mi_1 = BB.Data[i-2] Mi = BB.Data[i-1] } hi := xi - xi_1 temp0 := ZeroMatrix(4, 1) //2.1 S0 temp0.Data[3] = -1.0 temp0.Data[2] = 3.0 * xi temp0.Data[1] = -3.0 * xi * xi temp0.Data[0] = xi * xi * xi for j := 0; j < 4; j++ { S0.Data[j] = temp0.Data[j] * Mi_1 / (6.0 * hi) } //2.1 S1 temp0.Data[3] = 1.0 temp0.Data[2] = -3.0 * xi_1 temp0.Data[1] = 3.0 * xi_1 * xi_1 temp0.Data[0] = -1.0 * xi_1 * xi_1 * xi_1 for j := 0; j < 4; j++ { S0.Data[j] = temp0.Data[j] * Mi / (6.0 * hi) } //2.2 S2 temp0 = ZeroMatrix(4, 1) temp0.Data[1] = -1.0 temp0.Data[0] = xi for j := 0; j < 4; j++ { S2.Data[j] = temp0.Data[j] * (yi_1 - Mi_1*hi*hi/6.0) / hi } //2.3 S3 temp0 = ZeroMatrix(4, 1) temp0.Data[1] = 1.0 temp0.Data[0] = -1.0 * xi_1 for j := 0; j < 4; j++ { S3.Data[j] = temp0.Data[j] * (yi - Mi*hi*hi/6.0) / hi } //2.4 Si(x) for j := 0; j < 4; j++ { sol.SetMatrix(j, i-1, S0.Data[j]+S1.Data[j]+S2.Data[j]+S3.Data[j]) } } err = true return sol, err }