BraWl
Loading...
Searching...
No Matches
nested_sampling Module Reference

Functions/Subroutines

subroutine nested_sampling_main (setup, nested_sampling)
 Main nested sampling routine.
 

Function/Subroutine Documentation

◆ nested_sampling_main()

subroutine nested_sampling::nested_sampling_main ( type(run_params) setup,
type(ns_params) nested_sampling )

Main nested sampling routine.

This routine performs the nested sampling calculation. Input parameters (such as the number of walkers, random walk parameters...etc.) are read from the "ns_input.txt" file. The first section of the routine generate the initial random configurations, which is followed by the main nested sampling cycle: recording and discarding the highest energy configuration, replacing it with a new one, generated from an existing walker via a series of random swaps. The routine makes use of the pair_swap subroutine to calculate energies.

Parameters
setupDerived type containing simulation parameters
nested_samplingDerived type containing nested sampling parameters
Returns
None
Author
L. B. Partay
Date
2024

Definition at line 45 of file nested_sampling.f90.

46
47 ! Arrays for storing instances of the system, as nested sampling walkers
48 type(run_params) :: setup
49 type(ns_params) :: nested_sampling
50
51 ! Energy before and after swap and change
52 real(real64) :: e_unswapped, e_swapped, delta_e, ener_limit, rnd
53 real(real64) :: acc_ratio, rnde
54 real(real64), dimension(:), allocatable :: walker_energies
55 ! Array for all the walkers configurations, with indices of n_base, n1, n2, n3, i_walker
56 integer(array_int), dimension(:,:,:,:,:), allocatable :: ns_walkers
57
58 ! Occupancy of each site
59 integer(array_int) :: site1, site2
60 integer :: i_walker, i_step, i_iter, irnd, n_at
61 integer :: n_acc, i_max(1), extra_steps
62
63 ! Random lattice sites
64 integer, dimension(4) :: rdm1, rdm2
65
66 ! open and parse input parameters needed for nested sampling
67 call read_ns_file("ns_input.inp", nested_sampling)
68 open(35,file=nested_sampling%outfile_ener)
69
70 ! creat arrays for storing all the NS walker configurations and their energies
71 allocate(ns_walkers(setup%n_basis, 2*setup%n_1, 2*setup%n_2, 2*setup%n_3,nested_sampling%n_walkers))
72 allocate(walker_energies(nested_sampling%n_walkers))
73 walker_energies=0.0d0
74
75 write(*,'(16("-"),x,"Initialising set of walkers for NS run",x, 16("-"),/)')
76
77 ! initialise all walkers
78 do i_walker = 1,nested_sampling%n_walkers
79
80 ! Set up the energies file for ns_analyse post-procesing (script available from pymatnest package)
81 if (i_walker == 1) then
82 n_at = setup%n_1*setup%n_2*setup%n_3*setup%n_basis*setup%n_species
83 ! header for energies file
84 write(35,*) nested_sampling%n_walkers, 1, 0, 'False', n_at
85
86 endif
87
88 ! set up and generate initial random configurations for each walker
89 call initial_setup(setup, config)
90 ns_walkers(:,:,:,:,i_walker) = config
91
92 ! Calculate all the inital energies and print to screen
93 ! Add small random number to the energy to avoid configurations to be degenerate in energy
94 call random_number(rnde)
95 walker_energies(i_walker)=setup%full_energy(ns_walkers(:,:,:,:,i_walker))+rnde*1e-8
96 print*, ' Initial energy of walker ', i_walker, 'is: ', walker_energies(i_walker)
97
98 enddo
99
100 write(*,'(/,16("-"),x,"Set of walkers successfully initialised",x, 15("-"),/)')
101
102 ! Print the cell contents to screen
103 call print_particle_count(setup, ns_walkers(:,:,:,:,1), 0)
104
105 extra_steps=0
106
107 !---------------------------------!
108 ! Main NS iteration cycle !
109 !---------------------------------!
110 write(*,'(24("-"),x,"Entering main NS cycle",x, 24("-"),/)')
111 print*, 'Will do',nested_sampling%n_iter,'iterations, starting with', &
112 nested_sampling%n_steps,'MC steps initially.', new_line('a')
113
114 do i_iter = 1, nested_sampling%n_iter
115
116 ! find highest energy, which is saved and discarded from the list of walkers
117 i_max=maxloc(walker_energies)
118 ener_limit=walker_energies(i_max(1))
119
120 ! save energy to NS ener output: nested_sampling%outfile_ener
121 write(35,*) i_iter, ener_limit
122 ! save config to NS xyz output: nested_sampling%outfile_traj
123 if (mod(i_iter,nested_sampling%traj_freq)==0) then
124 call xyz_writer(nested_sampling%outfile_traj, ns_walkers(:,:,:,:,i_max(1)), setup, trajectory=.true.)
125 endif
126
127 ! print sampling stage info to screen in every 0.5*number of walkers step
128 ! also adjust the number of attempted steps if the acceptance ratio is too low.
129 if (mod(i_iter,int(nested_sampling%n_walkers/2.0))==0) then
130
131 ! acceptance ratio of the previous random walk
132 acc_ratio=real(n_acc)/real(nested_sampling%n_steps+extra_steps)
133
134 ! number of accepted steps should be such that 5% of atoms are moved
135 if ((n_acc < n_at*0.05).and.(extra_steps<nested_sampling%n_steps*100)) then
136 ! increase the extra steps to increase attempted steps
137 extra_steps = extra_steps+int(nested_sampling%n_steps)
138 print*, i_iter, ener_limit, acc_ratio, n_acc,'n_steps increased to', &
139 & nested_sampling%n_steps+extra_steps
140 else
141 print*, i_iter, ener_limit, acc_ratio, n_acc
142 endif
143
144 endif
145
146 ! Generate a new sample, starting from an existing walker and doing a set of random steps
147
148 ! pick configuration for cloning
149 call random_number(rnd)
150 irnd=ceiling(rnd*nested_sampling%n_walkers)
151 ns_walkers(:,:,:,:,i_max(1)) = ns_walkers(:,:,:,:,irnd)
152 walker_energies(i_max(1)) = walker_energies(irnd)
153
154 n_acc=0
155 i_step=0
156 ! do random walk
157 do i_step = 1, nested_sampling%n_steps+extra_steps
158
159 ! Pick random site 1 and get what atom type it accopies
160 rdm1 = setup%rdm_site()
161 site1 = ns_walkers(rdm1(1), rdm1(2), rdm1(3), rdm1(4),i_max(1))
162 do
163 ! Generate random site 2 that has different atom type
164 rdm2 = setup%rdm_site()
165 !if (acc_ratio < 0.01) then
166 ! rdm2 = ns_setup(i_max(1))%rdm_nbr(rdm1)
167 !else
168 ! rdm2 = ns_setup(i_max(1))%rdm_site()
169 !endif
170
171 site2 = ns_walkers(rdm2(1), rdm2(2), rdm2(3), rdm2(4),i_max(1))
172 if (site1 /= site2) exit ! if same type, try again
173 enddo
174
175 ! Compute the energies before and after and work out the change
176 e_unswapped = pair_energy(setup, ns_walkers(:,:,:,:,i_max(1)), rdm1, rdm2)
177 call pair_swap(ns_walkers(:,:,:,:,i_max(1)), rdm1, rdm2)
178 e_swapped = pair_energy(setup, ns_walkers(:,:,:,:,i_max(1)), rdm1, rdm2)
179
180 ! since we are always swapping different atom types, the delta_e cannot be zero
181 delta_e = e_swapped - e_unswapped
182
183 if (walker_energies(i_max(1))+delta_e < ener_limit) then
184 !accept
185 walker_energies(i_max(1))=walker_energies(i_max(1))+delta_e
186 n_acc = n_acc+1
187 else
188 !reject (swap pairs back)
189 call pair_swap(ns_walkers(:,:,:,:,i_max(1)), rdm1, rdm2)
190 endif
191
192 enddo
193 if (n_acc==0) then
194 write(*,*) "WARNING! None of the attempted swaps were accepted, hence the cloned configuration", &
195 & "remained identical to the parent."
196 write(*,*) "Consider: increasing the number of steps, use a different strategy for swapping pair or", &
197 & "decreasing the number of NS iterations (might have reached low enough energies?)"
198 endif
199
200 enddo
201 print*, new_line('a'), ' All NS iterations are done, sampling finished.'
202 close(35)
203
204 write(*,'(/,26("-"),x,"Leaving NS routine",x, 26("-"))')
205
Here is the call graph for this function: