稳定的双共轭梯度法(BiCGSTAB)

系数矩阵非对称时,线性方程组如何求解?-稳定双共轭梯度法(Bicgstab)求解线性方程组

在前面的文章和中表明共轭梯度法是求解对称正定线性方程组的一种有效方法,当针对不同的系数矩阵采用不同的预处理方式时,其可以以较少的迭代次数获得较高精度的解。然而,该方法的一个缺点就是其只能适用于对称正定系数矩阵,当系数矩阵不再是对称正定时,此方法可能失效。以下举例:
在这里插入图片描述
上面矩阵A为非对称矩阵,采用共轭梯度法求解过程如下:
在这里插入图片描述
该方程组采用共轭梯度法迭代4862次依然未收敛。因此,对于该非对称方程,可以认为,共轭梯度法几乎是失效的。在实际工程中,有限元方法形成的刚度系数以对称正定居多,但是实际上也存在非对称的可能,例如,当材料本构采用摩尔-库伦本构时,其形成的刚度矩阵就有可能会是非对称的,此时如果是使用商业软件,应当在软件中选择非对称求解器。如果是自主编程且采用迭代法求解线性方程组,则需要找到一种适用于非对称矩阵的求解方法。
在这里插入图片描述
常见的非对称系数矩阵求解方法主要有:广义最小残差法(GMRES),双共轭梯度法(Bicg)稳定双共轭梯度法(BiCGStab),稳定混合双共轭梯度法(BiCGStab(l)),这些方法相对于常规的共轭梯度法在推导上均增加了一些难度,实际推导往往较为复杂。本文不展开推导,仅对稳定双共轭梯度法(BiCGStab)的伪代码作简要粘贴。BiCGStab法的具体计算过程如下:
在这里插入图片描述

program bicgstab_main
    implicit none
    integer,parameter::n=8
    real(8)::a(n,n),b(n)
    real(8)::x(n),x0(n)
    integer::i,j
    integer,parameter::m=20
    real(8)::c(m,m),d(m)
    real(8)::y(m),y0(m)
 
 
    a=reshape((/6,5,1,2,0,0,2,1, &
                0,5,1,1,0,0,3,0,& 
                1,1,623,1,2,0,1001,2, &
                2,1,1,7,1,2,1,1,&
                0,0,2,31,6,0,2,1,&
                0,0,0,2,0,4,1,0,&
                2,3,1,1,23,1,5,213,&
                123,0,12,1,1,0,1,3/),(/n,n/))
    b=(/1,1,1,1,1,1,1,1/)
    write(*,*)"矩阵A"
    write(*,"(8f10.4)")(a(i,:),i=1,n)
    write(*,*)"向量b"
    write(*,"(f10.4)")b
    x0=100.0
    x=0.0
    call bicgstab(a,b,x,x0,n)
    end program bicgstab_main
subroutine bicgstab(a,b,x,x0,n)
    implicit none
    integer,intent(in)::n
    real(kind=8),intent(in)::a(n,n),b(n),x0(n)
    real(kind=8),intent(out)::x(n)
    real(kind=8)::p0(n),r0(n)
    real(kind=8)::tol=1.0d-6
    integer::nmax=1000
    real(kind=8)::rj(n),pj(n)
    real(kind=8)::alphaj
    real(kind=8)::r0_bar(n)
    real(kind=8)::sj(n)
    real(kind=8)::xjp1(n),xj(n)
    real(kind=8)::wj
    real(kind=8)::rjp1(n)
    real(kind=8)::betaj
    integer::n_iter
    real(kind=8)::apj(n),asj(n)
 
    r0=b-matmul(a,x0)
    r0_bar=r0
    if(abs(dot_product(r0,r0_bar))<tol) then
        write(*,*)"unvalid r0_bar,select an other!"
        return    
    endif
    p0=r0
     rj=r0
     pj=p0
     xj=x0
 
     n_iter=0
    do
        if(n_iter>nmax) then
            write(*,*)"exceed max iter!"
            exit
        endif
        alphaj=dot_product(rj,r0_bar)/dot_product(matmul(a,pj),r0_bar)
        apj=matmul(a,pj)
        sj=rj-alphaj*apj
        if(norm2(sj)<tol) then
            xjp1=xj+alphaj*pj
            x=xjp1
            exit
        endif
        asj=matmul(a,sj)
    wj=dot_product(asj,sj)/(norm2(asj))**2
    xjp1=xj+alphaj*pj+wj*sj
    rjp1=sj-wj*asj
 
    if(norm2(rjp1)<tol) then
        x=xjp1
        exit
    endif
    betaj=alphaj*dot_product(rjp1,r0_bar)/(wj*dot_product(rj,r0_bar))
    pj=rjp1+betaj*(pj-wj*apj)
    xj=xjp1
    rj=rjp1
    n_iter=n_iter+1
    write(*,*)"the",n_iter,"iter!"
    enddo
 
    write(*,*)"the solution of equation:"
    write(*,"(es18.8)")x
    end subroutine bicgstab

依据上述过程编写程序,计算前述非对称矩阵线性方程组求解结果:
在这里插入图片描述
采用matlab求解该方程组的解:
在这里插入图片描述
通过对比可知11次迭代已经获得即为准确的结果。实际上,对于该方法也可以通过一定的预处理方式,使得其所需要的迭代次数更少。
https://zhuanlan.zhihu.com/p/537095177

而由维基百科
1、未预处理的
在这里插入图片描述

2、预处理后的
在这里插入图片描述

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
共轭梯度法(BiConjugate Gradient Method)是求解线性方程组的一种迭代方法,相比于传统的共轭梯度法,它可以应用于非对称矩阵的情况。以下是该算法的设计思路及MATLAB程序实现。 算法设计: 1. 初始化 $x_0$ 和 $r_0=b-Ax_0$。 2. 初始化 $p_0=r_0$ 和 $\hat{p}_0=r_0$。 3. 对于 $k=0,1,2,...$,执行以下步骤: a. 计算 $\alpha_k=\frac{r_k^T\hat{p}_k}{p_k^TAp_k}$,更新 $x_{k+1}=x_k+\alpha_kp_k$。 b. 计算 $r_{k+1}=r_k-\alpha_kAp_k$。 c. 计算 $\beta_k=\frac{r_{k+1}^T\hat{p}_k}{r_k^T\hat{p}_k}$。 d. 计算 $p_{k+1}=r_{k+1}+\beta_kp_k$ 和 $\hat{p}_{k+1}=Ap_{k+1}+\beta_k\hat{p}_k$。 e. 如果 $r_{k+1}$ 达到了某个精度要求或者达到了最大迭代次数,则停止迭代。 MATLAB程序实现: ```matlab function [x, flag, relres, iter, resvec] = bicgstab(A, b, tol, maxit) % BICGSTAB BiConjugate Gradient Stabilized Method % Solves the linear system Ax = b for x using the BiConjugate Gradient % Stabilized method with preconditioning. % % x = bicgstab(A, b) returns the solution x of the linear system Ax = b. % % x = bicgstab(A, b, tol) specifies the tolerance of the method. Default % is 1e-6. % % x = bicgstab(A, b, tol, maxit) specifies the maximum number of iterations. % Default is min(size(A,1), 20). % % [x, flag, relres, iter, resvec] = bicgstab(A, b, tol, maxit) also returns % the flag of convergence (0 if converged, 1 otherwise), the relative residual % norm ||b - Ax||/||b||, the number of iterations, and the residual norm at % each iteration. % % Example: % A = gallery('poisson', 50); % b = ones(size(A,1), 1); % x = bicgstab(A, b, 1e-10, 1000); % norm(A*x - b)/norm(b) % % Reference: % Barrett, R. et al. (1994). Templates for the solution of linear systems. % SIAM. % % Author: % Ildeberto de los Santos Ruiz % [email protected] if nargin < 3 || isempty(tol) tol = 1e-6; end if nargin < 4 || isempty(maxit) maxit = min(size(A, 1), 20); end x = zeros(size(A, 1), 1); r = b - A*x; rho = 1; alpha = 1; omega = 1; p = zeros(size(A, 1), 1); v = zeros(size(A, 1), 1); s = zeros(size(A, 1), 1); t = zeros(size(A, 1), 1); flag = 0; iter = 0; resvec = zeros(maxit+1, 1); resvec(1) = norm(r)/norm(b); while ~flag && iter < maxit iter = iter + 1; rho1 = rho; rho = dot(r, r0); beta = (rho/rho1)*(alpha/omega); p = r + beta*(p - omega*v); v = A*p; alpha = rho/dot(r, v); h = x + alpha*p; s = r - alpha*v; if norm(s)/norm(b) < tol x = h; flag = 0; relres = norm(s)/norm(b); resvec(iter+1) = relres; break end t = A*s; omega = dot(t, s)/dot(t, t); x = h + omega*s; r = s - omega*t; if norm(r)/norm(b) < tol flag = 0; relres = norm(r)/norm(b); resvec(iter+1) = relres; break end if abs(dot(r, r0)/rho) < eps flag = 1; relres = norm(r)/norm(b); resvec(iter+1) = relres; break end resvec(iter+1) = norm(r)/norm(b); end if flag warning('Method did not converge to the desired tolerance.'); end end ``` 该程序使用了预条件的共轭梯度法BiCGSTAB)来求解线性方程组,其中 $A$ 是系数矩阵,$b$ 是右端向量,$tol$ 是迭代精度,$maxit$ 是最大迭代次数。程序返回了求解得到的解 $x$,收敛标志 $flag$,相对残差 $relres$,迭代次数 $iter$ 和每次迭代的残差 $resvec$。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值