跳转至

Jacobi超松弛迭代法

约 348 个字 74 行代码 预计阅读时间 2 分钟

计算原理

对于线性方程组:

\[ \mathbf{A}\mathbf{x} = \mathbf{b} \]

其中 \(\mathbf{A}\)\(n \times n\) 的系数矩阵,\(\mathbf{x}\) 是未知向量,\(\mathbf{b}\) 是已知常数向量。

Jacobi 超松弛迭代法对第 \(i\) 个分量的同步迭代公式为:

\[ x_i^{(k+1)} = x_i^{(k)} - \omega \frac{1}{a_{ii}} \left( \sum_{j=1}^n a_{ij} x_j^{(k)} - b_i \right) \]

其中:

  • \(x_i^{(k)}\):第 \(k\) 次迭代的第 \(i\) 个分量
  • \(a_{ij}\):系数矩阵 \(\mathbf{A}\) 的元素
  • \(b_i\):右端向量的第 \(i\) 个分量
  • \(a_{ii}\):第 \(i\) 行的对角元
  • \(\omega\):松弛因子(超松弛 \(\omega>1\),标准Jacobi为 \(\omega=1\)
  • \(k\):当前迭代步数

有时也写作:

\[ x_i^{(k+1)} = (1-\omega) x_i^{(k)} + \frac{\omega}{a_{ii}} \left( b_i - \sum_{j \neq i} a_{ij} x_j^{(k)} \right) \]
  • 所有 \(x_i^{(k+1)}\) 都是 用上一轮 \(x_j^{(k)}\) 计算的(同步更新)
  • \(\omega=1\) 时,退化为普通 Jacobi 迭代
  • \(\omega>1\) 时为超松弛,加速收敛(但\(\omega\)过大可能发散)

Fortran数值实现

subroutine jacobi_sor(a,b,x,x0,n)
! Jacobi超松弛迭代法
    integer, intent(in) :: n
    real*8, intent(in) :: a(n,n), b(n), x0(n)
    real*8, intent(out) :: x(n)

    real*8 :: x1(n), x2(n)
    integer :: i, j, k, iter_max = 1000 ! 默认迭代次数
    real*8 :: eps = 1.0d-7 ! 默认精度
    real*8 :: omiga = 1.04d0 ! 松弛因子

    write(*,501)
    x1 = x0
    do k =1, iter_max
        do i = 1, n
            s = 0
            do j = 1, n
                s = s + a(i,j)*x1(j)
            end do
            ! 迭代更新
            x2(i) = x1(i)-omiga*(s-b(i))/a(i,i)
        end do
        ! 精度判断
        dx2 = norm2(x2 - x1) 
        if (dx2 < eps) exit

        x1 = x2
        write(*,503) k, (x2(i), i=1,n)
    end do
    x = x2

    501 format(//,18x,"Jacobi_SOR Iterative",//)
    503 format(i5, 4(3x, f12.8))
end subroutine jacobi_sor

数值案例

\[ \begin{array} { r } { \left( \begin{array} { l l l l } { 7 } & { 2 } & { 1 } & { - 2 } \\ { 9 } & { 1 5 } & { 3 } & { - 2 } \\ { - 2 } & { - 2 } & { 1 1 } & { 5 } \\ { 1 } & { 3 } & { 2 } & { 1 3 } \end{array} \right) \mathbf { x } = \left( \begin{array} { l } { 4 } \\ { 7 } \\ { - 1 } \\ { 0 } \end{array} \right) } \end{array} \]

主程序:

program main
    implicit none

    integer, parameter :: n = 4
    real*8 :: a(n,n), b(n), x(n), x0(n)

    a = reshape([ &
            7, 2, 1, -2, &
            9, 15, 3, -2, &
            -2, -2, 11, 5, &
            1, 3, 2, 13], [4,4], order=[2,1])

    b = [4.0, 7.0, -1.0, 0.0]

    x0 = 0.0d0

    call jacobi_sor(a, b, x, x0, n)

end program main

输出:

                  Jacobi_SOR Iterative


    1     0.59428571     0.48533333    -0.09454545     0.00000000
    2     0.44034771     0.11475117     0.11338251    -0.14889558
    3     0.48148565     0.16173590     0.07627040    -0.07495348
    4     0.49336413     0.15215906     0.05946363    -0.08654059
    5     0.49478866     0.14701902     0.06604866    -0.08203986
    6     0.49661801     0.14559013     0.06295508    -0.08215385
    7     0.49739517     0.14513343     0.06320843    -0.08145773
    8     0.49766899     0.14471058     0.06292982    -0.08147868
    9     0.49781886     0.14461168     0.06292268    -0.08135368
   10     0.49788045     0.14454094     0.06287352    -0.08134579
   11     0.49790866     0.14451665     0.06287002    -0.08132619
   12     0.49792109     0.14450347     0.06286164    -0.08132285
   13     0.49792675     0.14449845     0.06286025    -0.08131947
   14     0.49792923     0.14449587     0.06285883    -0.08131863
   15     0.49793035     0.14449484     0.06285847    -0.08131801
   16     0.49793085     0.14449434     0.06285821    -0.08131782
   17     0.49793107     0.14449413     0.06285813    -0.08131771
   18     0.49793117     0.14449403     0.06285809    -0.08131767

注意:子程序中默认:implicit real*8(a-z)

参考文献

  1. 宋叶志,茅永兴,赵秀杰.Fortran 95/2003科学计算与工程[M].清华大学出版社,2011.