请允许我在FORTRAN中使用Gauss和Gauss编写一个5D集成代码,但是当我编译它时,它非常慢。谁能告诉我如何提高速度吗?
MODULE GauLegMod
IMPLICIT NONE
CONTAINS
SUBROUTINE GaussLeg(n0, x, w)
Integer::i,j,n,m, dx,l,repeat_state,n0
Real(8)::x_k1,x_k,Pn,Leg_prime,Leg,x_k0,min_root
real(8)::Roots(n0),w(n0),x(n0)
Real(8),Allocatable::Roots_sorted(:),Semi_roots(:)
n = n0
IF (Mod(n,2)==0) THEN
m = n/2
dx = m + 1
ELSE
m = (n+1)/2
dx = m
END IF
Allocate( Roots_sorted(m),Semi_roots(m) )
Semi_roots = 0.0
x_k0 = 0.0
IF ( Mod(n,2)==0 ) THEN
i = 0
ELSE
i = 1
Semi_roots(i) = 0.0
END IF
DO
x_k0 = x_k0 + (0.001/dx)
repeat_state = 0
x_k = x_k0
x_k1 = x_k
DO
Call Leg_Derivative(n,x_k,Leg_prime)
x_k = x_k - (Leg(n,x_k)/Leg_prime)
IF ( ABS(x_k1-x_k)<0.00001 ) EXIT
x_k1 = x_k
END DO
DO j = 1, m
IF ( ABS(Semi_roots(j)-x_k)<=1.0E-5 ) THEN
repeat_state = 1
END IF
END DO
IF ( (repeat_state == 0) .AND. (x_k>=0.0) ) THEN
i = i + 1
Semi_roots(i) = x_k
END IF
IF (i==m) Exit
END DO
!-------------------Sorting--------------
DO i = 1, m
min_root = Minval(Semi_roots)
Semi_roots(Minloc(Semi_roots)) = Maxval(Semi_roots)
Roots_sorted(i) = min_root
END DO
Semi_roots = Roots_sorted
!-----------------------------------------
IF ( Mod(n,2)==0 ) THEN
j = 0
DO i = ((n/2)+1) , n
j = j + 1
Roots(i) = Semi_roots(j)
END DO
DO i = 1 , (n/2)
Roots(i) = -Roots(n-i+1)
END DO
ELSE
j = 0
DO i = ((n+1)/2) , n
j = j + 1
Roots(i) = Semi_roots(j)
END DO
DO i = 1 , (((n+1)/2)-1)
Roots(i) = -Roots(n-i+1)
END DO
END IF
x = Roots
!------------------------------Calculating Weights----------------------------
DO i = 1, n
w(i) = 2.0*( 1.0-(Roots(i)**2.0) ) / ( (Real(n)*Leg(n-1,Roots(i)) )**2.0 )
END DO
!-----------------------------------------------------------------------------------
END Subroutine
Subroutine Chebyshev(n0,x,w)
Implicit None
Integer::i,n0
Real(8)::w(n0),x(n0),PI
PI = 4.0*Atan(1.0)
DO i = 1 , n0
X(i) = Cos( (2.0*Real(i) - 1.0)*PI/(2.0*Real(n0)) )
W(i) = PI/Real(n0)
END DO
End Subroutine
end Module
Function Leg(n,x)
Implicit None
Integer::i,n
Real(8)::x,Pn(n+1),Leg
Pn(1) = 1.0
IF (n>=1) Pn(2) = x
DO i = 1, n - 1
Pn(i+2) = ((2.0*(i-1)+3.0)/((i-1)+2.0))*x*Pn(i+1) - (((i-1)+1.0)/((i-1)+2.0))*Pn(i)
END DO
Leg = Pn(n+1)
END Function
Subroutine Leg_Derivative(n,x,Leg_prime)
Implicit None
Integer::i,n
Real(8)::x,Leg,Leg_prime,h,xminus,xplus
h = 0.00001
xplus = x + h
xminus = x - h
Leg_prime = (Leg(n,xplus) - Leg(n,xminus)) / (2.0*h)
END Subroutine
FUNCTION V(x1, x2, x3, x4, x5)
Implicit None
REAL(8), INTENT(IN) :: x1, x2, x3, x4, x5
Real*8 ::facteur,V
facteur=x1+ x2 + x3 + x4 + x5
V =facteur! function for integration
End function V
PROGRAM GaussLeg1
USE GauLegMod
IMPLICIT NONE
REAL(8), EXTERNAL:: V
REAL(8) :: S, a1, a2, b1, b2, a3, a4, b3, b4,a5,b5,x1c,x2c,x3c,x4c,x5c,fac,fac2
REAL(8), ALLOCATABLE:: c1(:), x1(:), c2(:), x2(:), c3(:), x3(:), c4(:), x4(:), c5(:), x5(:)
INTEGER :: i, j, k, l1, m, n,n1, h,i1,i2
PRINT*, 'Enter the number of points n of the Gauss-Legendre Quadrature'
READ*, n
PRINT*, 'Enter the number of points n1 of the Gauss-Chebyshev Quadrature'
READ*, n1
Print*
Print*,' Please Wait. Calculating...'
ALLOCATE (x1(n1))
ALLOCATE (c1(n1))
ALLOCATE (x2(n))
ALLOCATE (c2(n))
ALLOCATE (x3(n))
ALLOCATE (c3(n))
ALLOCATE (x4(n1))
ALLOCATE (c4(n1))
ALLOCATE (x5(n1))
ALLOCATE (c5(n1))
a1 = 0.0 ; b1 = 2.0
a2 = 0.0 ; b2 = 2.0
a3 = 0.0 ; b3 = 2.0
a4 = 0.0 ; b4 = 2.0
a5 = 0.0 ; b5 = 2.0
CALL Chebyshev(n1, x1, c1)
CALL GaussLeg(n, x2, c2)
CALL GaussLeg(n, x3, c3)
CALL Chebyshev(n1, x4, c4)
CALL Chebyshev(n1, x5, c5)
S = 0.0
DO i = 1, n1
!
DO j = 1, n
!
DO k = 1, n
!
DO l1 = 1, n1
!
DO m = 1, n1
!
x1c = ( (b1-a1)*x1(i) / 2.0 ) + (a1+b1)/2.0
x2c = ( (b2-a2)*x2(j) / 2.0 ) + (a2+b2)/2.0
x3c = ( (b3-a3)*x3(k) / 2.0 ) + (a3+b3)/2.0
x4c = ( (b4-a4)*x4(l1) / 2.0 ) + (a4+b4)/2.0
x5c = ( (b5-a5)*x5(m) / 2.0 ) + (a5+b5)/2.0
fac = (b1-a1)*(b2-a2)*(b3-a3)*(b4-a4)*(b5-a5) / (2.0**5.0)
fac2 = (dSQRT(1.0-(X1(i)**2.0)) * dSQRT(1.0-(X4(l1)**2.0)) * dSQRT(1.0-(X5(m)**2.0)))
S = S + c1(i)*c2(j)*c3(k)*c4(l1)*c5(m)*fac*fac2*V(x1c, x2c, x3c,x4c, x5c)
END DO
END DO
END DO
END DO
END DO
write(*,*) S
END PROGRAM GaussLeg1 解析我得到160个,但代码是160.0787与许多节点。请,我需要帮助这个高斯-切比雪夫求积方法。
发布于 2021-08-24 18:41:05
只要对代码进行最小的更改,就可以解析命令行参数和计算时间。
% gfcx -o z a.f90
% ./z 40 40
160.12343539957692
Time: 8.13639 sec
% gfcx -o z -O2 -march=native -mtune=native a.f90
% ./z 40 40
160.12343539957581
Time: 0.52530 sec用gfortran 12.0.0 20210816。因此,简单地添加打开优化的选项就可以提高性能。
现在,如果我按以下顺序进行更改
2.0**5.0。相反,做2**5.在需要时,h = 0.00001d0.
h = 0.00001应该是h = 0.00001pi的值不会改变。将其作为参数计算一次,并使用正确的精度。real(8), parameter :: pi = 4 * atan(1.d0)在do-循环中,在设置了immediately.的
exit的调度。
a1 = 0、b1 = 2等在循环中用于计算(b1 - a1) / 2和(b1 + a1) / 2。然后显示fac = 1,因此删除它们.leg()和leg_derivative()放在gaulegmod模块中。现在的时代
% gfcx -o z a.f90
% ./z 40 40
160.12342053717975
Time: 3.68685 sec
% gfcx -o z -O2 -march=native -mtune=native a.f90
% ./z 40 40
160.12342053718061
Time: 0.48633 sec
% gfcx -o z -Ofast -march=native -mtune=native -ftree-vectorize a.f90
% ./z 40 40
160.12342053715955
Time: 0.23689 sechttps://stackoverflow.com/questions/68905055
复制相似问题