forked from chfenger/goNum
-
Notifications
You must be signed in to change notification settings - Fork 0
/
NLEs_SeidelIterate_test.go
133 lines (120 loc) · 3.46 KB
/
NLEs_SeidelIterate_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// NLEs_SeidelIterate_test
/*
------------------------------------------------------
作者 : Black Ghost
日期 : 2018-12-20
版本 : 0.0.0
------------------------------------------------------
多元非线性方程组Seidel迭代
理论:
Pk = x0
Fk = [f1, f2,..., fn]'
|df1/dx1 df1/dx2 ... df1/dxn|
|df2/dx1 df2/dx2 ... df2/dxn|
Jk = |... ... ... ... |
|dfn/dx1 dfn/dx2 ... dfn/dxn|
Jk*dPk = -Fk
P_(k+1) = Pk+dPk
参考:John H. Mathews and Kurtis D. Fink. Numerical
methods using MATLAB, 4th ed. Pearson
Education, 2004. ss 3.7
------------------------------------------------------
输入 :
funs 方程组,nx1
J Joccobi矩阵,nxn
x0 初值x
tol 控制误差
n 最大迭代次数
输出 :
sol 解,nx1
err 解出标志:false-未解出或达到边界;
true-全部解出
------------------------------------------------------
*/
package goNum_test
import (
"math"
"testing"
"github.com/chfenger/goNum"
)
// NLEs_SeidelIterate 多元非线性方程组Seidel迭代
func NLEs_SeidelIterate(funs, J func(goNum.Matrix) goNum.Matrix, x0 goNum.Matrix,
tol float64, n int) (goNum.Matrix, bool) {
/*
多元非线性方程组Seidel迭代
输入 :
funs 方程组,nx1
J Joccobi矩阵,nxn
x0 初值x
tol 控制误差
n 最大迭代次数
输出 :
sol 解,nx1
err 解出标志:false-未解出或达到边界;
true-全部解出
*/
//判断x维数
if x0.Columns != 1 {
panic("Error in goNum.NLEs_SeidelIterate: x0 is not a vector")
}
sol := goNum.ZeroMatrix(x0.Rows, 1) //解向量
xold := goNum.ZeroMatrix(x0.Rows, 1) //Pk
var err bool = false
//将x0赋予xold
for i := 0; i < x0.Rows; i++ {
xold.Data[i] = x0.Data[i]
sol.Data[i] = x0.Data[i]
}
//循环迭代
y := goNum.NumProductMatrix(funs(xold), -1.0)
for i := 0; i < n; i++ {
ja := J(xold)
dx, dxerr := goNum.LEs_ECPE(goNum.Matrix2ToSlices(ja), y.Data)
if dxerr != true {
panic("Error in goNum.NLEs_SeidelIterate: Solve error")
}
//求解新值
for i := 0; i < x0.Rows; i++ {
sol.Data[i] = xold.Data[i] + dx[i]
xold.Data[i] = sol.Data[i]
}
y = goNum.NumProductMatrix(funs(xold), -1.0)
//判断误差
maxy, _, _ := goNum.MaxAbs(y.Data)
if math.Abs(maxy) < tol {
err = true
return sol, err
}
}
return sol, err
}
func fun46(x0 goNum.Matrix) goNum.Matrix {
if (x0.Rows != 2) || (x0.Columns != 1) {
panic("Error in goNum.NLEs_SeidelIterate: Funs error")
}
sol := goNum.ZeroMatrix(2, 1)
x := x0.GetFromMatrix(0, 0)
y := x0.GetFromMatrix(1, 0)
sol.SetMatrix(0, 0, x*x-2.0*x-y+0.5)
sol.SetMatrix(1, 0, x*x+4.0*y*y-4.0)
return sol
}
func J46(x0 goNum.Matrix) goNum.Matrix {
if (x0.Rows != 2) || (x0.Columns != 1) {
panic("Error in goNum.NLEs_SeidelIterate: Jaccobi error")
}
sol := goNum.ZeroMatrix(2, 2)
x := x0.GetFromMatrix(0, 0)
y := x0.GetFromMatrix(1, 0)
sol.SetMatrix(0, 0, 2.0*x-2.0)
sol.SetMatrix(1, 0, 2.0*x)
sol.SetMatrix(0, 1, -1.0)
sol.SetMatrix(1, 1, 8.0*y)
return sol
}
func BenchmarkNLEs_SeidelIterate(b *testing.B) {
x46 := goNum.NewMatrix(2, 1, []float64{2.0, 0.25})
for i := 0; i < b.N; i++ {
goNum.NLEs_SeidelIterate(fun46, J46, x46, 1e-4, 1e6)
}
}