如何在 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

SAVEed变量的值在整个运行期间一直保持不变,不会再次初始化为0。要解决此问题,只需更换

real(real64) :: sum_val       !! this is a usual local variable
sum_val = 0                   !! or sum_val = real( 0, real64 )

那我想应该没问题吧。请参阅 this page 了解更多详情。 在我看来,这是 Fortran 中非常令人困惑的功能之一...