Last active
January 5, 2024 05:08
-
-
Save terasakisatoshi/6baa636f926e4afccbfff9b2dffbcd03 to your computer and use it in GitHub Desktop.
main_vmc.f90
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
! gfortran -O3 -Wall -std=f2008 main_vmc.f90 && time ./a.out | |
module vmc | |
use, intrinsic :: iso_fortran_env, only: dp => real64 | |
implicit none | |
private | |
public :: metropolis_test | |
integer, parameter, private :: n_walkers = 400 | |
!! A `PARAMETER` for this `MODULE` | |
integer, parameter, private :: n_samples_burn_in = 4000 | |
!! A `PARAMETER` for this `MODULE` | |
integer, parameter, private :: n_samples = 30000 | |
!! A `PARAMETER` for this `MODULE` | |
real(dp), parameter, private :: pi = acos(-1.0_dp) | |
!! A `PARAMETER` for this `MODULE` | |
!! mathematical constant: \pi | |
real(dp), parameter, private :: pi2 = 2.0_dp * pi | |
!! A `PARAMETER` for this `MODULE` | |
!! mathematical constant: 2\pi | |
real(dp), parameter, private :: sigma = 0.4_dp | |
!! A `PARAMETER` for this `MODULE` | |
!! variance of the normal distribution | |
contains | |
subroutine metropolis_test(alpha, dE_E) | |
real(dp), intent(in) :: alpha | |
!! A dummy argument for this `SUBROUTINE` | |
real(dp), dimension(2), intent(out) :: dE_E | |
!! A dummy argument for this `SUBROUTINE` | |
real(dp) :: d_ln_psi !! A variable for this `SUBROUTINE` | |
real(dp) :: E_loc !! A variable for this `SUBROUTINE` | |
real(dp) :: E_loc_d_ln_psi !! A variable for this `SUBROUTINE` | |
real(dp), allocatable, dimension(:) :: sum_d_ln_psi !! A variable for this `SUBROUTINE` | |
real(dp), allocatable, dimension(:) :: sum_E_loc !! A variable for this `SUBROUTINE` | |
real(dp), allocatable, dimension(:) :: sum_E_loc_d_ln_psi !! A variable for this `SUBROUTINE` | |
real(dp), allocatable, dimension(:) :: rr !! A variable for this `SUBROUTINE` | |
real(dp), allocatable, dimension(:,:) :: vec !! A variable for this `SUBROUTINE` | |
real(dp), allocatable, dimension(:) :: rr_next !! A variable for this `SUBROUTINE` | |
real(dp), allocatable, dimension(:,:) :: vec_next !! A variable for this `SUBROUTINE` | |
integer :: i_s !! A support variable for this `SUBROUTINE` | |
integer :: i_w !! A support variable for this `SUBROUTINE` | |
real(dp), dimension(5) :: u !! A support variable for this `SUBROUTINE` | |
real(dp), dimension(3) :: v !! A support variable for this `SUBROUTINE` | |
!allocate( sum_d_ln_psi (n_walkers), mold=0.0_dp ) | |
!allocate( sum_E_loc (n_walkers), mold=0.0_dp ) | |
!allocate( sum_E_loc_d_ln_psi (n_walkers), mold=0.0_dp ) | |
allocate( sum_d_ln_psi (n_walkers)) | |
allocate( sum_E_loc (n_walkers)) | |
allocate( sum_E_loc_d_ln_psi (n_walkers)) | |
do i_w = 1, n_walkers | |
sum_E_loc_d_ln_psi(i_w) = 0.0_dp | |
sum_E_loc(i_w) = 0.0_dp | |
sum_d_ln_psi(i_w) = 0.0_dp | |
end do | |
allocate( rr ( n_walkers) ) | |
allocate( vec (3,n_walkers) ) | |
allocate( rr_next ( n_walkers) ) | |
allocate( vec_next (3,n_walkers) ) | |
call random_number( vec(:,:) ) | |
do concurrent (i_w = 1 : n_walkers) | |
vec (:,i_w) = 4.0_dp * ( vec(:,i_w) - 0.5_dp ) | |
rr ( i_w) = sqrt( dot_product( vec(:,i_w), vec(:,i_w) ) ) | |
end do | |
loop_sampler: &! | |
do i_s = 1, n_samples | |
loop_walker: &! | |
do i_w = 1, n_walkers | |
call random_number( u(1:5) ) | |
u(1) = sqrt( -2.0_dp * log( u(1) ) ) | |
u(2) = pi2 * u(2) | |
v(1) = u(1) * cos( u(2) ) | |
v(2) = u(1) * sin( u(2) ) | |
v(3) = sqrt( -2.0_dp * log( u(3) ) ) * cos( pi2 * u(4) ) | |
vec_next(:,i_w) = vec(:,i_w) + sigma * v(:) | |
rr_next ( i_w) = sqrt( dot_product( vec_next(:,i_w), vec_next(:,i_w) ) ) | |
if ( u(5) < exp( 2.0_dp * alpha * ( rr(i_w) - rr_next(i_w) ) ) ) then | |
vec (:,i_w) = vec_next(:,i_w) | |
rr ( i_w) = rr_next ( i_w) | |
end if | |
end do &! | |
loop_walker | |
if (i_s >= n_samples_burn_in) then | |
do i_w = 1, n_walkers | |
E_loc = - 1.0_dp / rr(i_w) - 0.5_dp * alpha * ( alpha - 2.0_dp / rr(i_w) ) | |
d_ln_psi = - rr(i_w) | |
E_loc_d_ln_psi = E_loc * d_ln_psi | |
sum_E_loc (i_w) = sum_E_loc (i_w) + E_loc | |
sum_d_ln_psi (i_w) = sum_d_ln_psi (i_w) + d_ln_psi | |
sum_E_loc_d_ln_psi (i_w) = sum_E_loc_d_ln_psi (i_w) + E_loc_d_ln_psi | |
end do | |
end if | |
end do &! | |
loop_sampler | |
associate( inv_denominator => 1.0_dp / real( n_samples - n_samples_burn_in + 1, dp ) ) | |
do concurrent (i_w = 1 : n_walkers) | |
sum_E_loc (i_w) = sum_E_loc (i_w) * inv_denominator | |
sum_d_ln_psi (i_w) = sum_d_ln_psi (i_w) * inv_denominator | |
sum_E_loc_d_ln_psi (i_w) = sum_E_loc_d_ln_psi (i_w) * inv_denominator | |
end do | |
end associate | |
E_loc = sum( sum_E_loc (:) ) / n_walkers | |
d_ln_psi = sum( sum_d_ln_psi (:) ) / n_walkers | |
E_loc_d_ln_psi = sum( sum_E_loc_d_ln_psi (:) ) / n_walkers | |
dE_E(1) = 2.0 * (E_loc_d_ln_psi - E_loc * d_ln_psi) | |
dE_E(2) = E_loc | |
end subroutine metropolis_test | |
end module vmc | |
program main | |
use, intrinsic :: iso_fortran_env, only: dp=>real64 | |
use, non_intrinsic :: vmc | |
implicit none | |
real(dp) :: alpha | |
real(dp) :: alpha_ini | |
real(dp) :: alpha_next | |
real(dp) :: alpha_plus | |
real(dp) :: alpha_minus | |
real(dp) :: E, dE, d_dE, dE_plus, dE_minus | |
real(dp) :: dE_E(2), dE_E_plus(2), dE_E_minus(2) | |
real(dp), parameter :: h = 1e-3 | |
integer :: i | |
alpha_ini = 0.8 | |
alpha = alpha_ini | |
do i = 1, 10 | |
call metropolis_test(alpha, dE_E) | |
dE = dE_E(1) | |
alpha_plus = alpha + h | |
call metropolis_test(alpha_plus, dE_E_plus) | |
dE_plus = dE_E_plus(1) | |
alpha_minus = alpha - h | |
call metropolis_test(alpha_minus, dE_E_minus) | |
dE_minus = dE_E_minus(1) | |
d_dE = (dE_plus - dE_minus) / (2.0_dp * h) | |
alpha_next = alpha - dE / d_dE | |
print *, alpha_next, alpha | |
if (abs(alpha_next - alpha) < 1e-6) then | |
alpha = alpha_next | |
exit | |
end if | |
alpha = alpha_next | |
end do | |
print *, alpha, "1.0 になってたらOK" | |
call metropolis_test(alpha, dE_E) | |
E = dE_E(2) | |
print *, E, "-0.5 になってたらOK" | |
end program main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
参考にしたコード
https://gist.github.com/DSCF-1224/3fadaac4e22efadb5c3b48e9c55e6e4d