高斯消元法 (2)---主元消除法

采用主元消除的方法,求解矩阵方程

GaussianElimation.f90

! GaussianElimation.f90
!-------------------------------------------------------GaussianElimation.f90
!----------------------------------------------------------------------------
!------------------该模块包含了高斯消元的主要模块---------------------------------
!--------

!引用迭代求解模块
include "Tri_eq.f90"

!m_gauss模块,需要调用tri_eq模块进行求解
module m_gauss
    use tri_eq

    contains

!solve:求解器
!-----------------------------------------------------------------------
!   输入:
!        A:系数矩阵
!        b:右向量
!        x:待求解的结果
!        N:维数

    subroutine solve(A,b,x,N)
        
        implicit real*8(a-z)
        integer::N 
        real*8::A(N,N),b(N),x(N)

        !增广矩阵Ab
        real*8::Ab(N+1,N)

        !增广矩阵赋值
        Ab(1:N,:) = A
        Ab(N+1,:) = b
        
        !求解行最简式
        call RowReduce(Ab,N)
        
        !将增广矩阵中对应的系数矩阵与右向量重新赋值给A,b
        A = Ab(1:N,:)
        b = Ab(N+1,:)

        !调用上三角求解
        call uptri(A,b,x,N)

    end subroutine

!RowReduce:化简为行最简形式
!   输入
!       Ab:增广矩阵
!       N:维数
    subroutine RowReduce(Ab,N)
        integer::i,j,N,md       !md用于标记某一列中最大值对应的行数,以便于进行交换
        real*8::Ab(N+1,N),temp

        do i = 1,N-1
            md = Max_id(Ab(i,i:N),N-i+1)+(i-1)
            if(md == 0) then    !如果某一列对应的值全为零,则跳入下一步
                cycle
            end if
            !交换最大值对应行和当前行
            call swap(Ab,N,i,md)
            !call DisplayArray(Ab,N)

            !用当前行,对其余所有行进行消元处理
            do j = i+1,N 
                temp = -Ab(i,j)/Ab(i,i)
                call Cijk(Ab,N,i,j,temp)
            end do
        end do

        !此处便于获得对角矩阵,便于求解
        !通过反带,消除上三角系数
        do j = N,2,-1
            do i = j-1,1,-1
                temp = -Ab(j,i)/Ab(j,j)
                call Cijk(Ab,N,j,i,temp)
            end do
        end do

    end subroutine

    
    !交换两行
    subroutine swap(A,N,i,j)
        implicit real*8 (a-z)
        integer::N,i,j
        real*8::A(N+1,N),temp(N+1)

        temp = A(:,i)
        A(:,i) = A(:,j)
        A(:,j) = temp
        
        return
    end subroutine

!将A的第i行乘上系数k加到第j行
    subroutine Cijk(A,N,i,j,k)
        implicit real*8 (a-z)
        integer::N,i,j
        real*8::k 
        real*8::A(N+1,N),temp(N+1)

        temp = A(:,i)*k
        A(:,j) = A(:,j) + temp
    end subroutine

!用于展示数组
    subroutine DisplayArray(A,N)
        implicit real*8(a-z)
        integer::N,i,j
        real*8 A(N+1,N)

        do i = 1,N 
            do j = 1,N+1
                write(*,'(T1,F12.8,$)') A(j,i)
            end do
            write(*,*)
        end do
    end subroutine

!一个函数方法,用于求解某一行中最大的数对应的坐标
    integer function Max_id(b,N)
        integer::i,N
        real*8::Max_Value,b(N)
        Max_id = 1
        Max_Value = abs(b(Max_id))
        do i = 2,N 
            if(Max_Value < abs(b(i))) then
                Max_id = i
            end if
        end do
        return
    end function
    
end module

Tri_eq.f90

module tri_eq
!---------------------------------------------------module comment
!   Version
!   Coded By 
!   Date:2020/03/16
!---------------------------------------------------Description
!   用于解上三角方程回带方法的模块
!---------------------------------------------------Contains
!   contains
!   1. uptri  方法函数
!   2. downtri 方法函数
!   
contains

subroutine uptri(A,b,x,N)
!---------------------------------------------------subroutine comment
!   Version
!   Coded By 
!   Date:2020/03/16
!----------------------------------------------------Description
!   purpose: 上三角回带方法
!           A x = b
!----------------------------------------------------Input
!   Input parameters:
!       A(N,N):系数矩阵
!       b(N)右向量
!       N:方程维数
!   Output parameters:
!       x 方程的根
!   Common parameters:
!
!-----------------------------------------------------
    implicit real(kind = 8) (a-z)
    integer::i,j,N 
    real*8 A(N,N),b(N),x(N)
    x(N) = b(N)/A(N,N)
    !回带
    do i = n-1,1,-1
        x(i) = b(i)
        do j  = i+1,N 
            x(i) = x(i) - A(j,i)*x(j)
        end do
        x(i) = x(i)/A(i,i)
    end do

    end subroutine uptri

subroutine downtri(A,b,x,N)
!---------------------------------------------------subroutine comment
!   Version
!   Coded By 
!   Date:2020/03/16
!----------------------------------------------------Description
!   purpose: 下三角回带方法
!           A x = b
!----------------------------------------------------Input
!   Input parameters:
!       A(N,N):系数矩阵
!       b(N)右向量
!       N:方程维数
!   Output parameters:
!       x 方程的根
!   Common parameters:
!
!-----------------------------------------------------
    implicit real(kind = 8) (a-z)
    integer::i,j,N 
    real*8 A(N,N),b(N),x(N)
    x(1) = b(1)/A(1,1)
    !回带
    do i = 2,N
        x(i) = b(i)
        do j  = 1,i-1 
            x(i) = x(i) - A(j,i)*x(j)
        end do
        x(i) = x(i)/A(i,i)
    end do

    end subroutine downtri

end module tri_eq

ReadFile.f90

module readFile
!---------------------------------------------------module comment
!   Version
!   Coded By 
!   Date:2020/03/16
!---------------------------------------------------Description
!   用于解上三角方程文件读写的模块
!---------------------------------------------------Contains
!   contains
!   1. readParameter 方法函数
!   2. writeFile 方法函数
!   
    contains

    subroutine readParameter(FileName,A,b,N,status1,status2)
        !Description:用于读取输入
        !variable declaration
        !FileName:输入文件的名字
        !msg:错误信息
        !N:维数
        !status1:打开文件状态,status2:读文件状态
        !A(N,N),b(N):系数矩阵
        character(len = 30)::FileName
        character(len = 30)::msg
        integer::N
        integer::status1,status2
        real(kind = 8) A(N,N),b(N)

        !openFile
        open(unit = 10, file = FileName, status = 'OLD', action = 'READ', IOSTAT = status1, IOMSG = msg)

        if(status1 == 0) then 
            !如果打开文件成功

            !read the parameter
            read(10,*,IOSTAT = status2) ((A(i,j),i = 1,N),j = 1,N)
            read(10,*,IOSTAT = status2) b

            !status2 /= 0,读取文件失败或达到文件末尾
            if(status2 /= 0) then
                write(*,*) "File reading Error or End"
                close(10)
                return
            end if

        end if

    end subroutine

    subroutine writeFile(FileName,X,N)   
        !Description:用于写入结果
        !variable declaration
        !FileName:写入文件的名字
        !msg:错误信息
        !N:维数
        !X:结果
 
        character(len = 30) FileName
        character(len = 30) msg 
        integer::status1, status2
        integer::N
        real(kind = 8)::X(N)
       
        !打开文件,此处使用status = 'OLD',表示该文件已经存在
        open(11,file = FileName,status = 'OLD',action = 'WRITE',IOSTAT = status1, IOMSG = msg)

        if(status1 == 0) then
            write(11,101,IOSTAT = status2) X
            101 format(T5,"方程组的解",/,T4,"x = ",6(/F12.8))
        end if

    end subroutine

end module

main.f90

include"GaussianElimation.f90"
include"ReadFile.f90"

program main
    use m_gauss
    use readFile

    !declaration
    integer,parameter::N = 6
    integer::status1,status2        !分别用于表示文件打开和读取的状态

    real*8::A(N+1,N),Aup(N,N),bup(N),x(N)

    character(len = 30)::inputFile,outputFile,msg

    inputFile = "fin.txt"
    outputFile = "fout.txt"
    open(11,file = outputFile,status = 'NEW',action = 'WRITE',IOSTAT = status1, IOMSG = msg)

    call readParameter(inputFile,Aup,bup,N,status1,status2)
    
    A(1:N,:) = Aup
    A(1+N,:) = bup

    write(*,10)
    10 format("Original Matrix")
    call DisplayArray(A,N)

    write(*,20)
    20 format("Row Reduce")
    call RowReduce(A,N)
    call DisplayArray(A,N)

    Aup = A(1:N,:)
    bup = A(1+N,:)

    write(*,"(/)")

    write(*,30)
    30 format("Solve Equation Ax = b")

    call solve(Aup,bup,x,N)

    write(*,40) x
    40 format(T5,'x = ',/,T4,6(/F12.3))
    call writeFile(outputFile,x,N)
    
end program main

输入文件fin.txt

-3.3435 -0.4946 0.3834  -4.9537 -2.4013 -3.5446
1.0198  -4.1618 4.9613  2.7491  3.0007  -3.6393
-2.3703 -2.7102 -4.2182 3.1730  -0.6859 3.6929
1.5408  4.1334  -0.5732 3.6869  4.1065  0.7970
1.8921  -3.4762 -3.9335 -4.1556 -3.1815 0.4986
2.4815  3.2582  4.6190  -1.0022 -2.3620 -3.5505

9.0537
0.0228 
-8.4177
-4.6380
10.5575
9.8252

输出文件 fout.txt

    方程组的解
   x = 
  1.26515941
  0.11026391
 -1.24520947
 -0.43379925
 -0.99093338
 -2.62011810

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值