如何在 Fortran 中创建一个随机函数以将相同的随机分布生成到数组中?
How to make a random function in fortran to generate the same random distribution into array?
我认为我下面的代码并没有完全给我相同的随机分布。
subroutine trig_random_value()
implicit none
integer :: t, z, y, x
real(real64) :: theta, r
real(real64), parameter :: PI=4.D0*DATAN(1.D0)
integer, dimension(12) :: date_time
integer, dimension(12) :: seed
call date_and_time(values=date_time)
call random_seed
seed = date_time(6) * date_time(7) + date_time(8)
call random_seed(put = seed)
do z = 1, z_size
do y = 1, y_size
do x = 1, x_size
theta = rand()*2*PI
r = 0.1*rand()
l1(1, z, y, x) = r*cos(theta)
l2(1, z, y, x) = r*sin(theta)
theta = rand()*2*PI
r = 0.1*rand()
l1(2, z, y, x) = r*cos(theta)
l2(2, z, y, x) = r*sin(theta)
end do
end do
end do
return
end subroutine trig_random_value
根据我的代码,我尝试将值随机设为 l1(1,:,:,:)
、l1(2,:,:,:)
、l2(1,:,:,:)
和 l2(2,:,:,:)
,其中 l(t, x, y, z)是(3+1)维数组
为什么我的随机函数要使用三角函数?因为我想要循环随机化。如果我绘制 l1(1,:,:,:) vs l2(1,:,:,:) 或 l1(2,:,:,:) vs l2(2,:,:,:) 我会得到半径为 0.1
的圆形分布
那么,为什么我告诉你这不是完全相同的分布?因为我试图测量它们的方差,我得到了
variance_l1_t1 = 1.6670507752921395E-003
variance_l1_t2 = 3.3313151655785292E-003
variance_l2_t1 = 4.9965623815717321E-003
variance_l2_t2 = 6.6641054728288360E-003
注意 (variance_l1_t2 - variance_l1_t1) = (variance_l2_t1 - variance_l1_t2) = (variance_l2_t2 - variance_l2_t1) = 0.00166
这是一个很奇怪的结果。实际上,如果这个函数是好的随机函数,我应该得到几乎相同的 l1(1,:,:,:)
、l1(2,:,:,:)
、l2(1,:,:,:)
和 l2(2,:,:,:)
的方差值。可能是我做错了什么。
如何解决这个问题?
来自请求的附加信息:
real(real64) function find_variance(l)
implicit none
real(real64), dimension(z_size, y_size, x_size), intent(in) :: l
integer :: z, y, x
real(real64) :: l_avg = 0
real(real64) :: sum_val = 0
do z = 1, z_size
do y = 1, y_size
do x = 1, x_size
l_avg = l_avg + l(z, y, x)
end do
end do
end do
l_avg = l_avg/(z_size*y_size*x_size)
do z = 1, z_size
do y = 1, y_size
do x = 1, x_size
sum_val = sum_val + (l(z , y, x) - l_avg)**2
end do
end do
end do
find_variance = sum_val/(z_size*y_size*x_size)
return
end function find_variance
在现代 Fortran 中,变量的初始化如
real(real64) :: sum_val = 0
表示sum_val
是一个具有SAVE
属性的变量(类似于C中的static
),在程序启动时只初始化一次。相当于
real(real64), save :: sum_val = 0
SAVE
ed变量的值在整个运行期间一直保持不变,不会再次初始化为0。要解决此问题,只需更换
real(real64) :: sum_val !! this is a usual local variable
sum_val = 0 !! or sum_val = real( 0, real64 )
那我想应该没问题吧。请参阅 this page 了解更多详情。
在我看来,这是 Fortran 中非常令人困惑的功能之一...
我认为我下面的代码并没有完全给我相同的随机分布。
subroutine trig_random_value()
implicit none
integer :: t, z, y, x
real(real64) :: theta, r
real(real64), parameter :: PI=4.D0*DATAN(1.D0)
integer, dimension(12) :: date_time
integer, dimension(12) :: seed
call date_and_time(values=date_time)
call random_seed
seed = date_time(6) * date_time(7) + date_time(8)
call random_seed(put = seed)
do z = 1, z_size
do y = 1, y_size
do x = 1, x_size
theta = rand()*2*PI
r = 0.1*rand()
l1(1, z, y, x) = r*cos(theta)
l2(1, z, y, x) = r*sin(theta)
theta = rand()*2*PI
r = 0.1*rand()
l1(2, z, y, x) = r*cos(theta)
l2(2, z, y, x) = r*sin(theta)
end do
end do
end do
return
end subroutine trig_random_value
根据我的代码,我尝试将值随机设为 l1(1,:,:,:)
、l1(2,:,:,:)
、l2(1,:,:,:)
和 l2(2,:,:,:)
,其中 l(t, x, y, z)是(3+1)维数组
为什么我的随机函数要使用三角函数?因为我想要循环随机化。如果我绘制 l1(1,:,:,:) vs l2(1,:,:,:) 或 l1(2,:,:,:) vs l2(2,:,:,:) 我会得到半径为 0.1
的圆形分布那么,为什么我告诉你这不是完全相同的分布?因为我试图测量它们的方差,我得到了
variance_l1_t1 = 1.6670507752921395E-003
variance_l1_t2 = 3.3313151655785292E-003
variance_l2_t1 = 4.9965623815717321E-003
variance_l2_t2 = 6.6641054728288360E-003
注意 (variance_l1_t2 - variance_l1_t1) = (variance_l2_t1 - variance_l1_t2) = (variance_l2_t2 - variance_l2_t1) = 0.00166
这是一个很奇怪的结果。实际上,如果这个函数是好的随机函数,我应该得到几乎相同的 l1(1,:,:,:)
、l1(2,:,:,:)
、l2(1,:,:,:)
和 l2(2,:,:,:)
的方差值。可能是我做错了什么。
如何解决这个问题?
来自请求的附加信息:
real(real64) function find_variance(l)
implicit none
real(real64), dimension(z_size, y_size, x_size), intent(in) :: l
integer :: z, y, x
real(real64) :: l_avg = 0
real(real64) :: sum_val = 0
do z = 1, z_size
do y = 1, y_size
do x = 1, x_size
l_avg = l_avg + l(z, y, x)
end do
end do
end do
l_avg = l_avg/(z_size*y_size*x_size)
do z = 1, z_size
do y = 1, y_size
do x = 1, x_size
sum_val = sum_val + (l(z , y, x) - l_avg)**2
end do
end do
end do
find_variance = sum_val/(z_size*y_size*x_size)
return
end function find_variance
在现代 Fortran 中,变量的初始化如
real(real64) :: sum_val = 0
表示sum_val
是一个具有SAVE
属性的变量(类似于C中的static
),在程序启动时只初始化一次。相当于
real(real64), save :: sum_val = 0
SAVE
ed变量的值在整个运行期间一直保持不变,不会再次初始化为0。要解决此问题,只需更换
real(real64) :: sum_val !! this is a usual local variable
sum_val = 0 !! or sum_val = real( 0, real64 )
那我想应该没问题吧。请参阅 this page 了解更多详情。 在我看来,这是 Fortran 中非常令人困惑的功能之一...