解决一个_= BAX=B其中是天际线矩阵一种A

计算科学 稀疏矩阵 矩阵 正则 矩阵方程
2021-12-24 21:42:06

求解类型的矩阵方程,其中是以对称矩阵。AX=BAn×n

通过 Bill 给出的解决方案和对因式分解的更多研究,我使用了SH Lee提供的原型代码以及相同的测试代码:

    parameter (neqs = 5)
    real*8 au(7), ad(neqs), b(neqs), energy
    integer jp(neqs)
    data au/-2.,-2.,-3.,-1.,0.,0.,4./
    data ad/2.,3.,5.,10.,10./
    data b/0.,1.,0.,0.,0./
    data jp/0,1,2,3,7/
    CALL REDUCl(neqs,jp,ad,au)
    CALL SOLVE1(neqs,jp,ad,au,b)

结果令人满意:

解 636. 619. 292. 74. 34.

子程序 REDUC1 和 SOLVE1 如下:

SUBROUTINE  REDUCl  (N,IP,D,A)
IMPLICIT  REAL(8) (A-H,O-Z)
DIMENSION  IP(*),D(*),A(*)
!FUNCTION  :  CROUT  DECOMPOSITION  A  =  LDU
!REDUCTION  COLUMN  BY  COLUMN
DO  11  K=2,N
K1=K-1
LK=IP(K)-K1
KH=IP(K1)-LK+1
S=D(K)-A(LK+KH)*A(LK+KH)/D(KH)
DO  22  J=KH+1,K1
J1=J-1
LJ=IP(J)-J1
JH=IP(J1)-LJ+1
IF  (KH.GT.JH)  JH=KH
T=A(LK+J)
DO  33  M=JH,J1
33  T=T-A(LJ+M)*A(LK+M)
A(LK+J)=T
22  S=S-T*T/D(J)
DO  44 J=KH,K1
L=LK+J
44  A(L)=A(L)/D(J)
11  D(K)=S
RETURN
END

SUBROUTINE  SOLVE1  (N,IP,D,A,B)
IMPLICIT  REAL(8)  (A-H,O-Z)
DIMENSION  IP(*),D(*),A(*),B(*)
!FUNCTION  :  SOLVE  FOR  X,  LDUx  =  b  where  U  =  transpose  of  L
!1.  FORWARD  SUBSTITUTION  :  Lz  =  b
DO  11  J=2,N
J1=J-1
LJ=IP(J)-J1
JH=IP(J1)-LJ+1
T=B(J)
DO  22  M=JH,J1
22  T=T-A(LJ+M)*B(M)
11  B(J)=T
!2.  DIVIDING  BY  DIAGONAL  ELEMENTS  :  Dy  =  2
DO  33  K=1,N
33  B(K)=B(K)/D(K)
!BACKWARD  SUBSTITUTION  :  UX  =  y
DO  44  K=N,2,-1
K1=K-1
LK=IP(K)-K1
KH=IP(K1)-LK+1
T=B(K)
DO  44  J=KH,K1
44  B(J)=B(J)-T*A(LK+J)
RETURN
END

但是,现在我遇到了一个新问题!当我的矩阵与上面类似但在以下两种情况下失败(我得到错误的答案)时,这可以正常工作:
案例 1:

    data au/0.6801,0.3846,0.4820,1.4074,1.2731,0.7047,0.1078,0.6171,0.9063,0.5895,0.,0.5260,0.3439,0.8178/
    data ad/0.3818,0.4524,0.,1.4605,1.7593,1.1887/
    data b/1.,1.,1.,1.,1.,1./
    data jp/0,0,2,5,9,14/
    CALL REDUCl(neqs,jp,ad,au)
    CALL SOLVE1(neqs,jp,ad,au,b)

案例二:

!!C  Solve A*U = b
!!C        [1    0    0     0     0            0         ]
!!C        [0    1    0     0     0            0         ]
!!C  A =   [0    0    1     0     0            0         ]
!!         [0    0    0     1     0            0         ]
!!C        [0    0    0           1.6667E10   -0.4167E10 ]
!!C        [0    0    0    0     -0.4167E10    0.1041e10 ]
data au/-0.4166667E10/
data ad/1.,1.,1.,1.,1.6667E10,0.1041667E10/
data b/1.,1.,1.,1.,1.,1./
data jp/0,0,0,0,0,1/
Print*,au
Print*,ad
CALL REDUCl(neqs,jp,ad,au)
CALL SOLVE1(neqs,jp,ad,au,b)

我哪里错了?是由于某些分配或使用精度造成的吗?

2个回答

您的案例 2 示例中的矩阵具有比原始 5 方程示例中的矩阵高得多的条件数。因此,矩阵项定义中的错误会导致解中的较大错误。

我相信,如果您从 MATLAB 输出具有 16 位精度的矩阵,则 fortran 代码将产生与 MATLAB 相同的解决方案。也就是说,您的 fortran 代码中的auad向量中的条目需要用 16 位精度来定义,而不是发布代码中的(大约)6 位精度。

此外,您应该注意正确定义浮点常量,例如 1.d0 而不是 1.e0。这是原始 5 方程示例中的一个疏忽,由于条件数低,在这种情况下不会造成太大问题。

为了扩展 Bill Greene 的答案,Fortran 对单精度和双精度浮点数使用不同的语法。1.e0 是数字“1.0”的单精度表示,而 1.d0 是数字“1.0”的双精度表示。如果您有一个相当直截了当的问题,并且相关的条件数较低,您将不会注意到差异,因为该问题可以单精度解决。

随着问题变得越来越困难,它们需要更高的精度——这就是为什么将变量设置为双精度值是一种很好的做法;但是,如果您混合使用单精度和双精度数字,则需要注意。Fortran 将减少到最小公分母,这意味着将双精度数与单精度数相乘将得到单精度数。对于简单的问题,这不是问题,但随着问题变得更加复杂并且需要一致地使用双精度,这将表现为代码中的错误。


从这个答案复制

4.5.1 双精度指数。

双精度指数的形式是字母 D 后跟一个可选的有符号整数常量。双精度指数表示十的幂。请注意,双精度指数的形式和解释与实指数的相同,只是使用字母 D 而不是字母 E。