! ============================================================================== ! program : pWaveSinglePole ! version : 02-Dec-2019 ! author : Zeqing Wang ! purpose : calculate the RF spectrum of p-wave sue single pole approximation ! reference: ! ==============================================================================
! ============================================================================== ! program : param ! type : module ! version : 05-Dec-2019 ! purpose : set the precision ! comment : ! ============================================================================== module prec implicitnone integer, parameter :: rkind=16! the precision endmodule prec ! ==============================================================================
! ============================================================================== ! program : param ! type : module ! version : 05-Dec-2019 ! purpose : set the precision ! comment : ! ============================================================================== module param use prec implicitnone real(kind=rkind), parameter :: pi=acos(-1._rkind) real(kind=rkind), parameter :: beta=_rkind, mu=-_rkind, rkv=& &-1._rkind, rp=1.0/30.0 real(kind=rkind), parameter :: phi_k=0.0! phi_k 是无关的量, 不影响结果 endmodule param ! ==============================================================================
! ============================================================================== ! program : pWavesinglePole ! type : program ! version : 19-Dec-2019 ! comment : the main program ! ============================================================================== program pWaveSinglePole use prec use param implicitnone
interface function linspace(a, b, dim) result(list) use prec integer :: dim real(kind=rkind) :: a, b, list(dim) endfunction linspace endinterface
! 计时开始 callcpu_time(start)
x = linspace(-20._rkind, 10._rkind, dim) ! x = linspace(0.0_rkind, pi, dim) do i = 1, dim y(i) = sigma(x(i), k, theta_k) ! y(i) = spectrum_k_thetak(x(i), k, theta_k) print *, 'calculating...', i, 'of', dim enddo
! 计时结束 callcpu_time(end) print *, 'calculate finish! time is ', end - start, 'seconds'
! 将数据保存到文件, 用于画图 open(1, file='./data/datax.csv') write(1, *) x close(1) open(2, file='./data/datay.csv') write(2, *) y close(2) print *, 'save data finish!' endprogram pWaveSinglePole
! ============================================================================== ! program : spectrum ! type : function ! version : 19-Dec-2019 ! purpose : calculate spectrum function ! comment : 还是只有虚部 ! ============================================================================== function spectrum_k_thetak(omega, k, theta_k) use prec use param implicitnone
! ============================================================================== ! program : sigma ! type : function ! version : 18-Dec-2019 ! purpose : calculate self energy ! comment : 积掉 phi_q . 还是只有虚部 ! ============================================================================== function sigma(omega, k, theta_k) use prec use param implicitnone
contains function fun(phi_q) use prec implicitnone real(kind=rkind) :: phi_q, fun fun = sigma_phiq(omega, k, theta_k, phi_q) endfunction fun endfunction sigma ! ==============================================================================
! ============================================================================== ! program : sigma_phiq ! type : function ! version : 18-Dec-2019 ! purpose : calculate self energy ! comment : 这里把 q 积掉了, 还乘下 theta_q, phi_q 没有积 ! 再积掉 theta_q, 还乘下 phi_q 没有积 ! ============================================================================== function sigma_phiq(omega, k, theta_k, phi_q) use prec use param implicitnone
! 将没有积掉 q 的自能定义成一个 q 的函数(便于计算虚部, 去掉了分母) contains function fun(q) use prec implicitnone real(kind=rkind) :: q, fun fun = numerator_of_sigma(omega, k, q, theta_k, theta_q, phi_q) endfunction fun endfunction sigma_thetaq_phiq ! ==============================================================================
! ============================================================================== ! program : sigma_q_thetaq_phiq ! type : function ! version : 05-Dec-2019 ! purpose : calculate self energy ! comment : 这里有三个待积变量, q, theta_q, phi_q ! ============================================================================== function sigma_q_thetaq_phiq(omega, k, q, theta_k, theta_q, phi_q) use prec use param implicitnone
! ============================================================================== ! program : numerator_of_sigma ! type : function ! version : 24-Dec-2019 ! purpose : calculate self energy ! comment : 这里有三个待积变量, q, theta_q, phi_q ! function sigma_q_thetaq_phiq 去掉分母, 用于计算虚部 ! ============================================================================== function numerator_of_sigma(omega, k, q, theta_k, theta_q, phi_q) use prec use param implicitnone
! ============================================================================== ! program : cos_theta_kprime ! type : function ! version : 05-Dec-2019 ! purpose : known k, q, and the angle between k and q, calculate cos(k'), ! where k' is the angle between k and -k+q ! comment : ! ============================================================================== function cos_theta_kprime(k, q, cos_theta_kq) use prec implicitnone
real(kind=rkind), intent(in) :: k, q, cos_theta_kq real(kind=rkind) :: cos_theta_kprime
! ============================================================================== ! program : cos_theta_kq ! type : function ! version : 05-Dec-2019 ! purpose : known theta_k, theta_q, phi_k, phi_q, calculate the cosine of ! angle between k and q ! comment : ! ============================================================================== function cos_theta_kq(theta_k, theta_q, phi_k, phi_q) use prec implicitnone
! ============================================================================== ! program : sylm10 ! type : function ! version : 05-Dec-2019 ! purpose : square of spherical harmonica function ! comment : |Y_l=1 m=0(x)|^2 ! ============================================================================== function sylm10(x) use prec use param implicitnone
real(kind=rkind), intent(in) :: x real(kind=rkind) :: sylm10
! ============================================================================== ! program : cauthyGaussQuad ! type : function ! version : 05-Dec-2019 ! purpose : calculate the cauthy principal value integral of function "fun" ! from a to b with singlarity sp ! comment : ! ============================================================================== function cauthyGaussQuad(fun, a, b, n, sp) use prec implicitnone
integer, intent(in) :: n real(kind=rkind), intent(in) :: a, b, sp
! 被积函数接口 interface function fun(x) use prec implicitnone real(kind=rkind) :: x, fun endfunction fun endinterface
! ============================================================================== ! program : gaussQuad ! type : function ! version : 03-Dec-2019 ! purpose : calculate the integral of function "fun" from a to b ! comment : ! ============================================================================== function gaussQuad(fun, a, b, n) use prec implicitnone
integer, intent(in) :: n real(kind=rkind), intent(in) :: a, b
! 被积函数接口 interface function fun(x) use prec implicitnone real(kind=rkind) :: x, fun endfunction fun endinterface
! 根与权重接口 interface function node_weight(n) result(r) use prec implicitnone integer :: n real(kind=rkind) :: r(2, n) endfunction node_weight endinterface
! 计算积分 r = node_weight(n) do j = 1, n fxi(j) = fun((r(1, j)*(b - a) + a + b) / 2) enddo gaussQuad = dot_product(r(2, :), fxi) gaussQuad = gaussQuad * (b - a) / 2 endfunction gaussQuad ! ==============================================================================
! ============================================================================== ! program : node_weight ! type : function ! version : 02-Dec-2019 ! purpose : calculate the root of n-order Legendre polynomial, and weight ! comment : use the method in reference ! ============================================================================== function node_weight(n) result(r) use prec implicitnone integer :: n, i, iter, k real(kind=rkind) :: r(2, n), x, f, df, dx real(kind=rkind), parameter :: pi = acos(-1._rkind) real(kind=rkind), allocatable :: p0(:), p1(:) real(kind=rkind), allocatable :: tmp(:)
! 利用递推公式求 n 阶 Legendre 多项式的系数, 幂次从高到低排列, 结果就是数组 p1 p0 = [1._rkind] p1 = [1._rkind, 0._rkind] do i = 2, n tmp = ((2*i - 1)*[p1, 0._rkind] - (i - 1)*[0._rkind, 0._rkind, p0]) / i p0 = p1; p1 = tmp enddo
! 这个函数将 n 阶的情况的 根存在 r(1,:) 中, 权重存在 r(2, :) 中 do i = 1, n x = cos(pi*(i - .5_rkind) / (n + ._rkind)) do iter = 1, 10 f = p1(1); df = 0._rkind do k = 2, size(p1) df = f + x*df ! 得到的是 P_n'(x_0) 的值 f = p1(k) + x*f ! 得到的是 P_n(x_0) 的值 enddo dx = f/df x = x - dx if (abs(dx)<10*epsilon(dx)) exit enddo r(1, i) = x r(2, i) = 2/((1 - x**2)*df**2) enddo endfunction node_weight ! ==============================================================================
! ============================================================================== ! program : linspace ! type : function ! version : 19-Dec-2019 ! purpose : similar to 'numpy.linspace' in python ! comment : ! ============================================================================== function linspace(a, b, dim) result(list) use prec implicitnone
real(kind=rkind) :: a, b integer :: dim real(kind=rkind) :: list(dim)
integer :: i real(kind=rkind) :: diff
do i = 1, dim list(i) = i - 1! i-1 instead of i, in order to be the same as ! numpy.linspace enddo
diff = b - a list = a + list * diff/dim endfunction linspace ! ==============================================================================
! ============================================================================== ! program : deltapart ! type : function ! version : 18-Dec-2019 ! purpose : get the delta part of \int_0 ^\inf f(x) / ((x-r1)(x-r2) + i0) dx ! comment : the result is -pi * (f(r1) - f(r2)) / (r1 - r2) ! 注意, 这个程序没有得到验证! ! ============================================================================== function deltapart(fun, r1, r2) use prec use param implicitnone real(kind=rkind) :: r1, r2, deltapart
! 函数 f(x) 的接口 interface function fun(x) use prec implicitnone real(kind=rkind) :: x, fun endfunction fun endinterface