From a150162cdc715f10dcadb2d3b4e26f695a27f99f Mon Sep 17 00:00:00 2001 From: cianciosa Date: Wed, 5 Jun 2024 11:04:26 -0400 Subject: [PATCH] Enable a constant random seed. Remove references to old seeds and the old rnd module. --- src/CMakeLists.txt | 1 - src/korc_c_random.cpp | 10 ++ src/korc_experimental_pdf.f90 | 6 - src/korc_initialize.f90 | 1 - src/korc_interp.f90 | 3 +- src/korc_random.f90 | 64 +++++++++++ src/korc_rnd_numbers.f90 | 177 ----------------------------- src/korc_spatial_distribution.f90 | 5 - src/korc_velocity_distribution.f90 | 1 - src/main.f90 | 5 + 10 files changed, 80 insertions(+), 193 deletions(-) delete mode 100755 src/korc_rnd_numbers.f90 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 976fb88e..11cfb18b 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -18,7 +18,6 @@ target_sources(korc $ $ $ - $ $ $ $ diff --git a/src/korc_c_random.cpp b/src/korc_c_random.cpp index a45b888e..3d2bd42d 100755 --- a/src/korc_c_random.cpp +++ b/src/korc_c_random.cpp @@ -22,6 +22,9 @@ class random_dist { void set_dist(const real_type low, const real_type high) { dist = DIST(low, high); } + void set_seed(const uint64_t seed) { + engine.seed(seed); + } real_type get_number() { return dist(engine); } @@ -66,4 +69,11 @@ extern "C" { const real_type high) { static_cast (r)->set_dist(low, high); } + void random_set_seed_U(void *r, int seed) { + static_cast (r)->set_seed(static_cast (seed)); + } + + void random_set_seed_N(void *r, int seed) { + static_cast (r)->set_seed(static_cast (seed)); + } } diff --git a/src/korc_experimental_pdf.f90 b/src/korc_experimental_pdf.f90 index 4d0dff3c..b3e4453f 100755 --- a/src/korc_experimental_pdf.f90 +++ b/src/korc_experimental_pdf.f90 @@ -4,7 +4,6 @@ MODULE korc_experimental_pdf USE korc_HDF5 USE korc_hpc use korc_coords - use korc_rnd_numbers use korc_random use korc_fields use korc_input @@ -704,7 +703,6 @@ SUBROUTINE sample_Hollmann_distribution(params,random,spp) INTEGER :: ppp INTEGER :: nsamples INTEGER :: mpierr - INTEGER,DIMENSION(33) :: seed=(/1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1/) nsamples = spp%ppp*params%mpi_params%nmpi @@ -1028,7 +1026,6 @@ subroutine sample_Hollmann_distribution_3D(params,random,spp,F) !! mpi error indicator REAL(rp) :: dg,deta LOGICAL :: accepted - INTEGER,DIMENSION(33) :: seed=(/1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1/) CALL random%uniform%set(0.0_rp,1.0_rp) @@ -1442,8 +1439,6 @@ subroutine sample_Hollmann_distribution_3D_psi(params,random,spp,F) !! mpi error indicator REAL(rp) :: dg,deta LOGICAL :: accepted - INTEGER,DIMENSION(33) :: seed=(/1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1/) - nsamples = spp%ppp*params%mpi_params%nmpi @@ -1973,7 +1968,6 @@ subroutine sample_Hollmann_distribution_1Dtransport(params,random,spp,F) !! mpi error indicator REAL(rp) :: dgmin,dgmax,deta LOGICAL :: accepted - INTEGER,DIMENSION(33) :: seed=(/1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1/) REAL(rp) :: EPHI,fRE_out,nAr0,nAr1,nAr2,nAr3,nD,nD1,ne,Te,Zeff,nRE diff --git a/src/korc_initialize.f90 b/src/korc_initialize.f90 index 0b9b7b79..e0624c8a 100755 --- a/src/korc_initialize.f90 +++ b/src/korc_initialize.f90 @@ -6,7 +6,6 @@ module korc_initialize use korc_hpc use korc_HDF5 use korc_fields - use korc_rnd_numbers use korc_spatial_distribution use korc_velocity_distribution use korc_coords diff --git a/src/korc_interp.f90 b/src/korc_interp.f90 index 32e63eb9..7dd08f9f 100755 --- a/src/korc_interp.f90 +++ b/src/korc_interp.f90 @@ -4,8 +4,7 @@ module korc_interp !! For a detailed documentation of the PSPLINE library we refer the !! user to "https://w3.pppl.gov/ntcc/PSPLINE/". use korc_types - use korc_coords - use korc_rnd_numbers + use korc_coords use korc_hpc #ifdef PSPLINE diff --git a/src/korc_random.f90 b/src/korc_random.f90 index efb9106f..f9e15748 100755 --- a/src/korc_random.f90 +++ b/src/korc_random.f90 @@ -104,6 +104,28 @@ SUBROUTINE random_set_dist_N(r, low, high) BIND(C, NAME='random_set_dist_N') END SUBROUTINE random_set_dist_N END INTERFACE + INTERFACE + SUBROUTINE random_set_seed_U(r, seed) BIND(C, NAME='random_set_seed_U') + USE, INTRINSIC :: iso_c_binding + + IMPLICIT NONE + + TYPE (C_PTR), VALUE :: r + INTEGER (C_INT), VALUE :: seed + END SUBROUTINE random_set_seed_U + END INTERFACE + + INTERFACE + SUBROUTINE random_set_seed_N(r, seed) BIND(C, NAME='random_set_seed_N') + USE, INTRINSIC :: iso_c_binding + + IMPLICIT NONE + + TYPE (C_PTR), VALUE :: r + INTEGER (C_INT), VALUE :: seed + END SUBROUTINE random_set_seed_N + END INTERFACE + !******************************************************************************* ! Class Defintions !******************************************************************************* @@ -117,6 +139,7 @@ END SUBROUTINE random_set_dist_N PROCEDURE :: get => random_U_get_random PROCEDURE :: get_array => random_U_get_randoms PROCEDURE :: set => random_U_set_dist + PROCEDURE :: seed => random_U_set_seed FINAL :: random_U_context_destruct END TYPE @@ -125,6 +148,7 @@ END SUBROUTINE random_set_dist_N PROCEDURE :: get => random_N_get_random PROCEDURE :: get_array => random_N_get_randoms PROCEDURE :: set => random_N_set_dist + PROCEDURE :: seed => random_N_set_seed FINAL :: random_N_context_destruct END TYPE @@ -361,4 +385,44 @@ SUBROUTINE random_N_set_dist(this, low, high) END SUBROUTINE + SUBROUTINE random_U_set_seed(this, seed, mpi_rank) + IMPLICIT NONE + +! Arguments + CLASS (random_U_context), INTENT(in) :: this + INTEGER, INTENT(in) :: seed + INTEGER, INTENT(IN) :: mpi_rank + +! Local Variables + INTEGER :: thread_num + +! Start of executable code +!$OMP PARALLEL DEFAULT(SHARED) PRIVATE(thread_num) + thread_num = get_thread_number() + CALL random_set_seed_U(this%states(thread_num), & + seed + mpi_rank*get_max_threads() + thread_num) +!$OMP END PARALLEL + + END SUBROUTINE + + SUBROUTINE random_N_set_seed(this, seed, mpi_rank) + IMPLICIT NONE + +! Arguments + CLASS (random_N_context), INTENT(in) :: this + INTEGER, INTENT(in) :: seed + INTEGER, INTENT(IN) :: mpi_rank + +! Local Variables + INTEGER :: thread_num + +! Start of executable code +!$OMP PARALLEL DEFAULT(SHARED) PRIVATE(thread_num) + thread_num = get_thread_number() + CALL random_set_seed_N(this%states(thread_num), & + seed + mpi_rank*get_max_threads() + thread_num) +!$OMP END PARALLEL + + END SUBROUTINE + END MODULE korc_random diff --git a/src/korc_rnd_numbers.f90 b/src/korc_rnd_numbers.f90 deleted file mode 100755 index 43fcb565..00000000 --- a/src/korc_rnd_numbers.f90 +++ /dev/null @@ -1,177 +0,0 @@ -module korc_rnd_numbers - !! @note Module with subrotuines for generating integer - !! and real random numbers.@endnote - !! This subroutines were taken from Numerical Recipes in Fortran 90, - !! and provide a way for generating random numbers of 'better quality' - !! in a faster way than build-in Fortran random generators (at least - !! better than those of Fortran 77). For more details we refer the user - !! to Numerical Recipes in Fortran 90. - -#ifdef __INTEL_COMPILER - use ifport -#endif - - use korc_types - - IMPLICIT NONE - - ! Parameters and variables used in generator of uniform random numbers - INTEGER(8), PARAMETER :: iv = 4101842887655102017_8 - INTEGER(8), PARAMETER :: iw = 1_8 - INTEGER(8), PARAMETER :: a = 4294957665_8 - INTEGER(8), PARAMETER :: b = 4294967295_8 - INTEGER(8), PARAMETER :: d = 2862933555777941757_8 - INTEGER(8), PARAMETER :: e = 7046029254386353087_8 - REAL(rp), PARAMETER :: rcoeff = 5.42101086242752217E-20_rp - - - TYPE, PRIVATE :: URAND - INTEGER(8) :: u - INTEGER(8) :: v - INTEGER(8) :: w - END TYPE URAND - - - TYPE(URAND), PRIVATE :: urand_vars - ! Parameters and variables used in generator of uniform random numbers - - - INTERFACE u_random - module procedure rand_int64,rand_int32,rand_real,rand_real_array - END INTERFACE u_random - - - PUBLIC :: init_u_random, u_random - PRIVATE :: rand_int64,rand_int32,rand_real - -CONTAINS - -subroutine init_u_random(seed) - INTEGER(8), INTENT(IN) :: seed - INTEGER(8) :: dummy_int64 - - urand_vars%u = seed**urand_vars%v - call rand_int64() - urand_vars%v = urand_vars%u - call rand_int64() - urand_vars%w = urand_vars%v - call rand_int64() -end subroutine init_u_random - - -subroutine rand_int64(irand) - INTEGER(8), OPTIONAL, INTENT(OUT) :: irand - INTEGER(8) :: x - - - urand_vars%u = urand_vars%u*d + e !u=u* 2862933555777941757LL + 7046029254386353087LL; - - urand_vars%v = IEOR(urand_vars%v,ISHFT(urand_vars%v,-17)) ! v^=v>>17; - urand_vars%v = IEOR(urand_vars%v,ISHFT(urand_vars%v,31)) ! v^=v<<31; - urand_vars%v = IEOR(urand_vars%v,ISHFT(urand_vars%v,-8)) ! v^=v>>8; - - urand_vars%w = a*IAND(urand_vars%w,b) + ISHFT(urand_vars%w,-32) ! w = 4294957665U*(w & 0xffffffff) + (w >> 32); - - x = IEOR(urand_vars%u,ISHFT(urand_vars%u,21)) ! Ullong x=u^(u<< 21); - x = IEOR(x,ISHFT(x,-35)) ! x ^= x >> 35; - x = IEOR(x,ISHFT(x,4)) ! x ^= x << 4; - - if (PRESENT(irand)) then - irand = IEOR(x + urand_vars%v,urand_vars%w) - end if -end subroutine rand_int64 - - -subroutine rand_int32(irand32) - INTEGER(4), INTENT(OUT) :: irand32 - INTEGER(8) :: irand64 - - call rand_int64(irand64) - - irand32 = INT(irand64,4) -end subroutine rand_int32 - - -subroutine rand_real_array(rrand) - REAL(rp), DIMENSION(:), INTENT(INOUT) :: rrand - INTEGER(8) :: irand64 - INTEGER :: ii ! Iterator - - do ii=1_idef,SIZE(rrand) - call rand_int64(irand64) - rrand(ii) = rcoeff*REAL(irand64,rp) + 0.5_rp - end do -end subroutine rand_real_array - - -subroutine rand_real(rrand) - REAL(rp), INTENT(OUT) :: rrand - INTEGER(8) :: irand64 - - call rand_int64(irand64) - rrand = rcoeff*REAL(irand64,rp) + 0.5_rp -end subroutine rand_real - -! FIXME: This function is now defunct. -subroutine init_random_seed(params) -#ifdef PARALLEL_RANDOM - use korc_random -#endif - TYPE(KORC_PARAMS), INTENT(IN) :: params - INTEGER, allocatable :: seed(:) - INTEGER(8), DIMENSION(8) :: dt - INTEGER(8) :: i - INTEGER(8) :: istat - INTEGER(8) :: pid - INTEGER(4) :: n - INTEGER(8) :: t - - call random_seed(size = n) - allocate(seed(n)) - ! First try if the OS provides a random number generator - open(default_unit_open, file="/dev/urandom", access="stream", & - form="unformatted", action="read", status="old", iostat=istat) - if (istat == 0) then - read(default_unit_open) seed - close(default_unit_open) - - else - ! Fallback to XOR:ing the current time and pid. The PID is - ! useful in case one launches multiple instances of the same - ! program in parallel. - call system_clock(t) - if (t == 0) then - call date_and_time(values=dt) - t = (dt(1) - 1970_8) * 365_8 * 24_8 * 60_8 * 60_8 * 1000_8 & - + dt(2) * 31_8 * 24_8 * 60_8 * 60_8 * 1000_8 & - + dt(3) * 24_8 * 60_8 * 60_8 * 1000_8 & - + dt(5) * 60_8 * 60_8 * 1000_8 & - + dt(6) * 60_8 * 1000_8 & - + dt(7) * 1000_8 & - + dt(8) - end if - pid = params%mpi_params%rank - write(output_unit_write,'("PID: ",I15)') pid - t = ieor(t, int(pid, kind(t))) - do i = 1, n - seed(i) = lcg(t) - end do - end if -contains - - ! This simple PRNG might not be good enough for real work, but is - ! sufficient for seeding a better PRNG. - function lcg(s) - INTEGER :: lcg - INTEGER(8) :: s - if (s == 0) then - s = 104729_8 - else - s = mod(s, 4294967296_8) - end if - s = mod(s * 279470273_8, 4294967291_8) - lcg = int(mod(s, int(huge(0), 8)), kind(0)) - end function lcg -end subroutine init_random_seed - -end module korc_rnd_numbers diff --git a/src/korc_spatial_distribution.f90 b/src/korc_spatial_distribution.f90 index 06b205f6..76c69212 100755 --- a/src/korc_spatial_distribution.f90 +++ b/src/korc_spatial_distribution.f90 @@ -7,7 +7,6 @@ MODULE korc_spatial_distribution USE korc_hpc use korc_fields use korc_profiles - use korc_rnd_numbers use korc_random use korc_hammersley_generator use korc_avalanche @@ -168,7 +167,6 @@ end subroutine torus ! REAL(rp), DIMENSION(:), ALLOCATABLE :: zeta !! Uniform deviates in the range \([0,2\pi]\) representing !! the uniform toroidal angle \(\zeta\) distribution of the particles. -! INTEGER,DIMENSION(33) :: seed=(/1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1/) ! ALLOCATE( theta(spp%ppp) ) ! ALLOCATE( zeta(spp%ppp) ) @@ -1294,7 +1292,6 @@ subroutine MH_psi(params,random,spp,F) !! mpi error indicator LOGICAL :: accepted - INTEGER,DIMENSION(34) :: seed=(/1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1/) if (params%mpi_params%rank.EQ.0_idef) then write(output_unit_write,*) '*** START SAMPLING ***' @@ -1695,7 +1692,6 @@ subroutine FIO_therm(params,random,spp,F,P) !! mpi error indicator LOGICAL :: accepted - INTEGER,DIMENSION(33) :: seed=(/1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1/) if (params%mpi_params%rank.EQ.0_idef) then write(output_unit_write,*) '*** START SAMPLING ***' @@ -2234,7 +2230,6 @@ subroutine BMC_radial(params,random,spp,F,P) !! mpi error indicator LOGICAL :: accepted - INTEGER,DIMENSION(33) :: seed=(/1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1/) REAL(rp) :: rm_buffer,rm_test INTEGER :: Nr_a REAL(rp), ALLOCATABLE,DIMENSION(:) :: r_a,nRE diff --git a/src/korc_velocity_distribution.f90 b/src/korc_velocity_distribution.f90 index dc7d6cc9..254ba87e 100755 --- a/src/korc_velocity_distribution.f90 +++ b/src/korc_velocity_distribution.f90 @@ -6,7 +6,6 @@ MODULE korc_velocity_distribution USE korc_HDF5 USE korc_hpc use korc_fields - use korc_rnd_numbers use korc_random use korc_hammersley_generator use korc_avalanche diff --git a/src/main.f90 b/src/main.f90 index b902a39c..0547693c 100755 --- a/src/main.f90 +++ b/src/main.f90 @@ -94,6 +94,11 @@ program main !! initializes paths and KORC parameters through [[load_korc_params]] !! on MPI processes. +if (params%SameRandSeed) then + call randoms%uniform%seed(1, params%mpi_params%rank) + call randoms%normal%seed(1, params%mpi_params%rank) +end if + if (params%mpi_params%rank .EQ. 0) then flush(output_unit_write) end if