fortran:高斯法求积分

module Gauss_Legendre !//高斯—勒让德积分高斯点及权重的求解模块
  implicit none
  integer, parameter :: n  = 5                           !// 设置求解高斯点的个数
  integer, parameter :: DP = selected_real_kind( p=13 )  !// 设置kind的数值
  integer, parameter :: nloop = 2000
  real(kind=DP), parameter :: eps = 1.0e-15_DP           !// 精度设置
  real(kind=DP), parameter :: h = 1.d-6
contains
  real(Kind=DP) function N_Legendre(x) !// 生成n阶勒让德多项式
    implicit none
    integer :: i
    real(Kind=DP) :: a(n), x
    a(1) = x !// 1阶勒让德多项式
    a(2) = 1.5_DP*x*x - 0.5_DP !// 2阶勒让德多项式
    do i = 3, n
      a(i) = ( dble(i+i-1)*x*a(i-1) - dble(i-1)*a(i-2) ) / dble(i) !// 利用递推关系产生n阶勒让德多项式
    end do
    N_Legendre=a(n) !//生成的n阶勒让德多项式
  end function N_Legendre

  real(Kind=DP) function N1_Legendre(x)  !// 生成n-1阶勒让德多项式 
    implicit none
    integer :: i
    real (Kind=DP) :: a(n), x
    a(1) = x
    a(2) = 1.5_DP*x**2 - 0.5_DP
    do i = 3, n - 1
      a(i) = (2*i-1)*x*a(i-1)/i - (i-1)*a(i-2)/i
    end do
    N1_Legendre = a(n-1)     
  end function N1_Legendre
  
  real(Kind=DP) function DN_Legendre(x)  !// 生成n阶勒让德多项式的导数表达式
    implicit none
    integer :: i
    real(Kind=DP) :: a(n), x
    a(1) = x  !// 1阶勒让德多项式
    a(2) = 1.5_DP*x*x - 0.5_DP !// 2阶勒让德多项式
    do i = 3, n
      a(i) = ( dble(i+i-1)*x*a(i-1) - dble(i-1)*a(i-2) ) / dble(i) !// 利用递推关系产生n阶勒让德多项式
    end do
    DN_Legendre = ( a(n-1) - x*a(n) )*dble(n) / (1.0_DP - x*x ) 
  end function DN_Legendre

  real(Kind=DP) function NewtonIteration(a, b) !// 牛顿法求解函数的解
    implicit none
    integer :: i
    real(Kind=DP) :: a, b, x, xtmp
    
    !// a,b是传递进来的划分好的有一个解存在的区间
    x = ( a + b ) / 2.d0  !// 初始估计值
    i = 0
    do 
      xtmp = x - N_Legendre(x) / DN_Legendre(x)   !// X(i+1) = Xi - f(Xi) / f'(Xi)  i = 1,2,...N
      i = i + 1
      If ( abs( xtmp-x ) < eps .and. i > nloop ) exit
      x = xtmp
    end do 
    NewtonIteration = x
  end function NewtonIteration

  subroutine root_coeff ( f_root, f_coeff )  !// 计算N阶勒让德多项式的根与去做权重系数
    implicit none
    real(Kind=DP) :: m, nstep, f_root(n), f_coeff(n) !// 定义数组,大小n由module开始声明。
    integer :: i, j
    
    j = 0   !// 赋值控制循环变量的初值           
    m = -1.d0 - h   !// 设置计算域[-1,1] 的下限,即代替-1 
    nstep = nint(2.d0/h)
    do i = 1, nstep   !// 这个循环次数应该是由步长0.000001决 定,计算方法:2000000=2/0.000001     
      If ( N_Legendre(m)*N_Legendre(m+h) < 0 ) then   !// 从下限处开始往上逐步累加
        j = j + 1    !// 记录这是第几个解
        f_root(j)  = NewtonIteration( m, m+h )!// 调用牛顿法求解程序在分好的一小段上求解,将解存储在fn(j)
        f_coeff(j) = 2.0_DP / ( dble(n) * N1_Legendre(f_root(j)) * DN_Legendre(f_root(j)) ) !// 利用公式计算高斯点的权重
      end if
      m = m + h !// 执行完一次判断m向前推进一步
    end do
  end subroutine root_coeff

end module Gauss_Legendre
        
        
program main
        use Gauss_Legendre
        implicit none
        integer       :: i 
        real(kind=DP) :: fn(n), ak(n), x, a, b, ans
        
        call root_coeff (fn ,ak)   !// 调用求高斯零点和权重的子函数
        
        a = 0.0_DP  !// 积分下限
        b = 1.0_DP  !// 积分上限
        
        ans = 0.0_DP  !// 求积分结果赋初值
        do i = 1, n 
                !// 部分高斯勒让德求积分公式
                ans = ans + ak(i) * y((a+b)/2.0_DP+(b-a)/2.0_DP*fn(i))
        end do
        ans = ans * (b-a) / 2.0_DP
        write(*, *) 'the result is ', ans 
contains
        real(kind=DP) function y(x)  !// 被积函数
                implicit none
                real(kind=DP) :: x 
                y = x**2/3.0_DP  !// 每次计算在此修改被积函数即可
        end function y
end program main

猜你喜欢

转载自blog.csdn.net/chd_lkl/article/details/86927594
今日推荐