(git:d2a9ebd)
Loading...
Searching...
No Matches
parallel_rng_types_unittest.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
12 USE kinds, ONLY: dp
13 USE machine, ONLY: m_walltime, &
15 USE parallel_rng_types, ONLY: gaussian, &
16 uniform, &
17 check_rng, &
22
23 IMPLICIT NONE
24
25 INTEGER :: i, nsamples, nargs, stat
26 LOGICAL :: ionode
27 REAL(kind=dp) :: t, tend, tmax, tmin, tstart, tsum, tsum2
28 TYPE(mp_comm_type) :: mpi_comm
29 TYPE(rng_stream_type) :: rng_stream
30 CHARACTER(len=32) :: arg
31
32 nsamples = 1000
33 nargs = command_argument_count()
34
35 IF (nargs > 1) then
36 error stop "Usage: parallel_rng_types_TEST [<int:nsamples>]"
37 end if
38
39 IF (nargs == 1) THEN
40 CALL get_command_argument(1, arg)
41 READ (arg, *, iostat=stat) nsamples
42 IF (stat /= 0) then
43 error stop "Usage: parallel_rng_types_TEST [<int:nsamples>]"
44 end if
45 END IF
46
47 CALL mp_world_init(mpi_comm)
48 ionode = mpi_comm%is_source()
49
50 CALL check_rng(default_output_unit, ionode)
51
52 ! Check performance
53
54 IF (ionode) THEN
55 WRITE (unit=default_output_unit, fmt="(/,/,T2,A,I10,A)") &
56 "Check distributions using", nsamples, " random numbers:"
57 END IF
58
59 ! Test uniform distribution [0,1]
60
61 rng_stream = rng_stream_type(name="Test uniform distribution [0,1]", &
62 distribution_type=uniform, &
63 extended_precision=.true.)
64
65 IF (ionode) then
66 CALL rng_stream%write(default_output_unit)
67 end if
68
69 tmax = -huge(0.0_dp)
70 tmin = +huge(0.0_dp)
71 tsum = 0.0_dp
72 tsum2 = 0.0_dp
73
74 tstart = m_walltime()
75 DO i = 1, nsamples
76 t = rng_stream%next()
77 tsum = tsum + t
78 tsum2 = tsum2 + t*t
79 IF (t > tmax) tmax = t
80 IF (t < tmin) tmin = t
81 END DO
82 tend = m_walltime()
83
84 IF (ionode) THEN
85 CALL rng_stream%write(default_output_unit, write_all=.true.)
86 WRITE (unit=default_output_unit, fmt="(/,(T4,A,F12.6))") &
87 "Minimum: ", tmin, &
88 "Maximum: ", tmax, &
89 "Average: ", tsum/real(nsamples, kind=dp), &
90 "Variance:", tsum2/real(nsamples, kind=dp), &
91 "Time [s]:", tend - tstart
92 END IF
93
94 ! Test normal Gaussian distribution
95
96 rng_stream = rng_stream_type(name="Test normal Gaussian distribution", &
97 distribution_type=gaussian, &
98 extended_precision=.true.)
99
100 IF (ionode) then
101 CALL rng_stream%write(default_output_unit)
102 end if
103
104 tmax = -huge(0.0_dp)
105 tmin = +huge(0.0_dp)
106 tsum = 0.0_dp
107 tsum2 = 0.0_dp
108
109 tstart = m_walltime()
110 DO i = 1, nsamples
111 t = rng_stream%next()
112 tsum = tsum + t
113 tsum2 = tsum2 + t*t
114 IF (t > tmax) tmax = t
115 IF (t < tmin) tmin = t
116 END DO
117 tend = m_walltime()
118
119 IF (ionode) THEN
120 CALL rng_stream%write(default_output_unit)
121 WRITE (unit=default_output_unit, fmt="(/,(T4,A,F12.6))") &
122 "Minimum: ", tmin, &
123 "Maximum: ", tmax, &
124 "Average: ", tsum/real(nsamples, kind=dp), &
125 "Variance:", tsum2/real(nsamples, kind=dp), &
126 "Time [s]:", tend - tstart
127 END IF
128
129 IF (ionode) THEN
130 CALL dump_reload_check()
131 CALL shuffle_check()
132 END IF
133
134 CALL mp_world_finalize()
135
136CONTAINS
137! **************************************************************************************************
138!> \brief ...
139! **************************************************************************************************
140 SUBROUTINE dump_reload_check()
141 TYPE(rng_stream_type) :: rng_stream
142 CHARACTER(len=rng_record_length) :: rng_record
143 REAL(KIND=dp), DIMENSION(3, 2) :: ig, ig_orig, cg, cg_orig, bg, bg_orig
144 CHARACTER(len=rng_name_length) :: name, name_orig
145 CHARACTER(len=*), PARAMETER :: serialized_string = &
146 "qtb_rng_gaussian 1 F T F 0.0000000000000000E+00&
147 & 12.0 12.0 12.0&
148 & 12.0 12.0 12.0&
149 & 12.0 12.0 12.0&
150 & 12.0 12.0 12.0&
151 & 12.0 12.0 12.0&
152 & 12.0 12.0 12.0"
153
154 WRITE (unit=default_output_unit, fmt="(/,/,T2,A)") &
155 "Checking dump and load round trip:"
156
157 rng_stream = rng_stream_type(name="Roundtrip for normal Gaussian distrib", &
158 distribution_type=gaussian, &
159 extended_precision=.true.)
160
161 CALL rng_stream%advance(7, 42)
162 CALL rng_stream%get(ig=ig_orig, cg=cg_orig, bg=bg_orig, name=name_orig)
163 CALL rng_stream%dump(rng_record)
164
165 rng_stream = rng_stream_type_from_record(rng_record)
166 CALL rng_stream%get(ig=ig, cg=cg, bg=bg, name=name)
167
168 IF (any(ig /= ig_orig) .OR. any(cg /= cg_orig) .OR. any(bg /= bg_orig) &
169 .OR. (name /= name_orig)) then
170 error stop "Stream dump and load roundtrip failed"
171 end if
172
173 WRITE (unit=default_output_unit, fmt="(T4,A)") &
174 "Roundtrip successful"
175
176 WRITE (unit=default_output_unit, fmt="(/,/,T2,A)") &
177 "Checking dumped format:"
178
179 ig(:, :) = 12.0_dp
180 rng_stream = rng_stream_type(name="qtb_rng_gaussian", &
181 distribution_type=gaussian, &
182 extended_precision=.true., &
183 seed=ig)
184
185 CALL rng_stream%dump(rng_record)
186
187 WRITE (unit=default_output_unit, fmt="(T4,A10,A433)") &
188 "EXPECTED:", serialized_string
189
190 WRITE (unit=default_output_unit, fmt="(T4,A10,A433)") &
191 "GENERATED:", rng_record
192
193 IF (rng_record /= serialized_string) then
194 error stop "Serialized record does not match the expected output"
195 end if
196
197 WRITE (unit=default_output_unit, fmt="(T4,A)") &
198 "Serialized record matches the expected output"
199
200 END SUBROUTINE dump_reload_check
201
202! **************************************************************************************************
203!> \brief ...
204! **************************************************************************************************
205 SUBROUTINE shuffle_check()
206 TYPE(rng_stream_type) :: rng_stream
207
208 INTEGER, PARAMETER :: sz = 20
209 INTEGER, DIMENSION(1:sz) :: arr, arr2, orig
210 LOGICAL, DIMENSION(1:sz) :: mask
211 INTEGER :: idx
212 REAL(KIND=dp), DIMENSION(3, 2), PARAMETER :: ig = 12.0_dp
213
214 WRITE (unit=default_output_unit, fmt="(/,/,T2,A)", advance="no") &
215 "Checking shuffle()"
216
217 rng_stream = rng_stream_type(name="shuffle() check", seed=ig)
218 orig = [(idx, idx=1, sz)]
219
220 arr = orig
221 CALL rng_stream%shuffle(arr)
222
223 IF (all(arr == orig)) then
224 error stop "shuffle failed: array was left untouched"
225 end if
226 WRITE (unit=default_output_unit, fmt="(A)", advance="no") "."
227
228 IF (any(arr /= orig(arr))) then
229 error stop "shuffle failed: the shuffled original is not the shuffled original"
230 end if
231 WRITE (unit=default_output_unit, fmt="(A)", advance="no") "."
232
233 ! sort and compare to orig
234 mask = .true.
235 DO idx = 1, size(orig)
236 IF (minval(arr, mask) /= orig(idx)) then
237 error stop "shuffle failed: there is at least one unknown index"
238 end if
239 mask(minloc(arr, mask)) = .false.
240 END DO
241 WRITE (unit=default_output_unit, fmt="(A)", advance="no") "."
242
243 arr2 = orig
244 CALL rng_stream%reset()
245 CALL rng_stream%shuffle(arr2)
246
247 IF (any(arr2 /= arr)) then
248 error stop "shuffle failed: array was shuffled differently with same rng state"
249 end if
250 WRITE (unit=default_output_unit, fmt="(A)", advance="no") "."
251
252 WRITE (unit=default_output_unit, fmt="(T4,A)") &
253 " successful"
254 END SUBROUTINE shuffle_check
255END PROGRAM parallel_rng_types_test
256! vim: set ts=3 sw=3 tw=132 :
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Machine interface based on Fortran 2003 and POSIX.
Definition machine.F:17
integer, parameter, public default_output_unit
Definition machine.F:46
real(kind=dp) function, public m_walltime()
returns time from a real-time clock, protected against rolling early/easily
Definition machine.F:141
Interface to the message passing library MPI.
subroutine, public mp_world_init(mp_comm)
initializes the system default communicator
subroutine, public mp_world_finalize()
finalizes the system default communicator
Parallel (pseudo)random number generator (RNG) for multiple streams and substreams of random numbers.
subroutine advance(self, e, c)
Advance the state by n steps, i.e. jump n steps forward, if n > 0, or backward if n < 0.
type(rng_stream_type) function, public rng_stream_type_from_record(rng_record)
Create a RNG stream from a record given as an internal file (string).
integer, parameter, public rng_name_length
integer, parameter, public rng_record_length
integer, parameter, public uniform
subroutine, public check_rng(output_unit, ionode)
...
integer, parameter, public gaussian
subroutine dump_reload_check()
...
program parallel_rng_types_test