RMPCDMD
n_colloids_pbc.f90
Go to the documentation of this file.
1 ! This file is part of RMPCDMD
2 ! Copyright (c) 2015-2017 Pierre de Buyl and contributors
3 ! License: BSD 3-clause (see file LICENSE)
4 
26 
28  use rmpcdmd_module
29  use hdf5
30  use h5md_module
31  use threefry_module
32  use parsetext
33  use iso_c_binding
34  use omp_lib
35  implicit none
36 
37  type(pto) :: config
38 
39  type(cell_system_t) :: solvent_cells
40  type(particle_system_t) :: solvent
41  type(particle_system_t) :: colloids
42  type(neighbor_list_t) :: neigh
43  type(lj_params_t) :: solvent_colloid_lj
44  type(lj_params_t) :: colloid_lj
45 
46  integer :: rho
47  double precision :: sigma, sigma_cut, epsilon
48  integer :: error
49 
50  double precision :: mass
51  double precision :: so_max, co_max
52 
53  double precision :: e1, e2
54  double precision :: temperature, local_mass, total_mass, kin_e, v_com(3)
55  double precision :: tau, dt, T, T_init, T_final
56  integer :: N_MD_steps, N_loop, N_thermo_loop
57  integer :: colloid_sampling
58  integer :: n_extra_sorting, loop_i_last_sort
59  integer :: n_threads
60  logical :: do_hydro, do_thermostat
61 
62  type(threefry_rng_t), allocatable :: state(:)
63  type(h5md_file_t) :: hfile
64  integer(HID_T) :: params_group
65  type(particle_system_io_t) :: colloids_io
66  type(thermo_t) :: thermo_data
67  integer(HID_T) :: box_group
68  type(h5md_element_t) :: dummy_element
69 
70  integer(HID_T) :: fields_group
71  type(histogram_t) :: radial_hist
72  type(h5md_element_t) :: radial_hist_el
73 
74  double precision :: skin
75  double precision :: rsq
76  logical :: tooclose
77 
78  double precision :: total_time
79  type(timer_list_t) :: timer_list
80  integer(HID_T) :: timers_group
81 
82  integer :: i, L(3), N, N_colloids
83  integer :: j, k
84  type(args_t) :: args
85 
86  args = get_input_args()
87  call ptparse(config, args%input_file, 11)
88 
89  n_threads = omp_get_max_threads()
90  allocate(state(n_threads))
91  call threefry_rng_init(state, args%seed)
92 
93  call timer_list%init(11)
94 
95  call h5open_f(error)
96  call hfile%create(args%output_file, 'RMPCDMD::n_colloids_pbc', &
97  rmpcdmd_revision, 'Pierre de Buyl')
98  call h5gcreate_f(hfile%id, 'parameters', params_group, error)
99  call hdf5_util_write_dataset(params_group, 'seed', args%seed)
100 
101  l = ptread_ivec(config, 'L', 3, loc=params_group)
102  rho = ptread_i(config, 'rho', loc=params_group)
103  t_init = ptread_d(config, 'T', loc=params_group)
104  t = t_init
105  t_final = ptread_d(config, 'T_final', loc=params_group)
106  tau = ptread_d(config, 'tau', loc=params_group)
107  n_md_steps = ptread_i(config, 'N_MD', loc=params_group)
108  colloid_sampling = ptread_i(config, 'colloid_sampling', loc=params_group)
109  dt = tau / n_md_steps
110  n_loop = ptread_i(config, 'N_loop', loc=params_group)
111  n_thermo_loop = ptread_i(config, 'N_thermo_loop', loc=params_group)
112 
113  n_colloids = ptread_i(config, 'N_colloids', loc=params_group)
114  epsilon = ptread_d(config, 'epsilon', loc=params_group)
115  sigma = ptread_d(config, 'sigma', loc=params_group)
116  sigma_cut = sigma*2.d0**(1.d0/6.d0)
117 
118  call thermo_data%init(hfile, n_buffer=50, step=n_md_steps, time=n_md_steps*dt)
119 
120  do_hydro = ptread_l(config, 'do_hydro', loc=params_group)
121  do_thermostat = ptread_l(config, 'do_thermostat', loc=params_group)
122 
123  mass = rho * sigma**3 * 4 * 3.141/3
124  call colloids%init(n_colloids, 1, [mass])
125  colloids%species = 1
126  colloids%vel = 0
127  colloids%force = 0
128 
129  colloids_io%force_info%store = .false.
130  colloids_io%id_info%store = .false.
131  colloids_io%velocity_info%store = .true.
132  colloids_io%velocity_info%mode = ior(h5md_linear,h5md_store_time)
133  colloids_io%velocity_info%step = n_md_steps*colloid_sampling
134  colloids_io%velocity_info%time = n_md_steps*colloid_sampling*dt
135  colloids_io%position_info%store = .true.
136  colloids_io%position_info%mode = ior(h5md_linear,h5md_store_time)
137  colloids_io%position_info%step = n_md_steps*colloid_sampling
138  colloids_io%position_info%time = n_md_steps*colloid_sampling*dt
139  colloids_io%image_info%store = .true.
140  colloids_io%image_info%mode = ior(h5md_linear,h5md_store_time)
141  colloids_io%image_info%step = n_md_steps*colloid_sampling
142  colloids_io%image_info%time = n_md_steps*colloid_sampling*dt
143  colloids_io%species_info%store = .true.
144  colloids_io%species_info%mode = h5md_fixed
145  call colloids_io%init(hfile, 'colloids', colloids)
146 
147  n = rho*l(1)*l(2)*l(3) - int(rho*4*3.142/3 * sigma**3*colloids%Nmax)
148 
149  write(*,*) n, 'solvent particles'
150 
151  if (n <= 0) error stop 'Not enough volume available for solvent'
152 
153  call solvent_colloid_lj% init( reshape( [ epsilon ], [1, 1] ), &
154  reshape( [ sigma ], [1, 1] ), reshape( [ sigma_cut ], [1, 1] ) )
155 
156  epsilon = ptread_d(config, 'epsilon_colloids', loc=params_group)
157  sigma_cut = 3*sigma
158 
159  call h5gclose_f(params_group, error)
160  call ptkill(config)
161 
162  call colloid_lj% init( reshape( [ epsilon ], [1, 1] ), &
163  reshape( [ 2*sigma ], [1, 1] ), reshape( [ 2*sigma_cut ], [1, 1] ) )
164 
165  call solvent% init(n)
166  do k = 1, solvent%Nmax
167  solvent% vel(1,k) = threefry_normal(state(1))*sqrt(t)
168  solvent% vel(2,k) = threefry_normal(state(1))*sqrt(t)
169  solvent% vel(3,k) = threefry_normal(state(1))*sqrt(t)
170  end do
171  solvent% vel = solvent% vel - spread(sum(solvent% vel, dim=2)/solvent% Nmax, 2, solvent% Nmax)
172  solvent% force = 0
173  solvent% species = 1
174 
175  call solvent_cells%init(l, 1.d0)
176  call h5gcreate_f(colloids_io%group, 'box', box_group, error)
177  call h5md_write_attribute(box_group, 'dimension', 3)
178  call dummy_element%create_fixed(box_group, 'edges', solvent_cells%edges)
179  call h5gclose_f(box_group, error)
180 
181  call h5gcreate_f(hfile%id, 'fields', fields_group, error)
182  call radial_hist%init(sigma/2, 4*sigma, 100)
183  call radial_hist_el%create_time(fields_group, 'radial_histogram', radial_hist%data, &
184  h5md_linear, step=n_md_steps, time=n_md_steps*dt)
185  call h5md_write_attribute(radial_hist_el%id, 'xmin', radial_hist%xmin)
186  call h5md_write_attribute(radial_hist_el%id, 'dx', radial_hist%dx)
187  call h5gclose_f(fields_group, error)
188 
189  i = 1
190  place_colloids: do while (i<=n_colloids)
191  colloids%pos(1,i) = threefry_double(state(1))*l(1)
192  colloids%pos(2,i) = threefry_double(state(1))*l(2)
193  colloids%pos(3,i) = threefry_double(state(1))*l(3)
194 
195  tooclose = .false.
196  check_distance: do j = 1, i-1
197  rsq = sum(rel_pos(colloids%pos(:,i), colloids%pos(:,j), solvent_cells%edges)**2)
198  if (rsq < colloid_lj%sigma(1,1)**2) then
199  tooclose = .true.
200  exit check_distance
201  end if
202  end do check_distance
203 
204  if (.not. tooclose) i=i+1
205  end do place_colloids
206 
207  call solvent% random_placement(solvent_cells% edges, colloids, solvent_colloid_lj, state(1))
208 
209  call solvent% sort(solvent_cells)
210 
211  sigma_cut = sigma*2.d0**(1.d0/6.d0) ! restore because colloid sigma_cut is larger
212  skin = 0.8
213  call neigh% init(colloids% Nmax, int(250*(sigma_cut+skin)**2))
214  call neigh% make_stencil(solvent_cells, sigma_cut+skin)
215  call neigh% update_list(colloids, solvent, sigma_cut+skin, solvent_cells)
216 
217  n_extra_sorting = 0
218  loop_i_last_sort = 0
219 
220  e1 = compute_force(colloids, solvent, neigh, solvent_cells% edges, solvent_colloid_lj)
221  e2 = compute_force_n2(colloids, solvent_cells% edges, colloid_lj)
222  solvent% force_old = solvent% force
223  colloids% force_old = colloids% force
224 
225  solvent% pos_old = solvent% pos
226  colloids% pos_old = colloids% pos
227  write(*,*) 'Thermostatting for', n_thermo_loop, 'loops'
228  do i = 1, n_thermo_loop
229  if (modulo(i, 100)==0) write(*, '(i09)', advance='no') i
230  md_loop_thermo: do j = 1, n_md_steps
231  call cell_md_pos(solvent_cells, solvent, dt, md_flag=.true.)
232  do k = 1, colloids% Nmax
233  colloids% pos(:,k) = colloids% pos(:,k) + dt * colloids% vel(:,k) + dt**2 * colloids% force(:,k) / (2 * mass)
234  end do
235  so_max = cell_maximum_displacement(solvent_cells, solvent, delta_t=dt*(n_md_steps*(i-1)+j - loop_i_last_sort))
236  co_max = colloids% maximum_displacement()
237 
238  if ( (co_max >= skin*0.1) .or. (so_max >= skin*0.9) ) then
239  call cell_md_pos(solvent_cells, solvent, (n_md_steps*(i-1)+j - loop_i_last_sort)*dt, md_flag=.false.)
240  call cell_md_vel(solvent_cells, solvent, (n_md_steps*(i-1)+j - loop_i_last_sort)*dt, md_flag=.false.)
241 
242  call apply_pbc(solvent, solvent_cells% edges)
243  call apply_pbc(colloids, solvent_cells% edges)
244  call solvent% sort(solvent_cells)
245  loop_i_last_sort = n_md_steps*(i-1) + j
246  call neigh% update_list(colloids, solvent, sigma_cut+skin, solvent_cells)
247  solvent% pos_old = solvent% pos
248  colloids% pos_old = colloids% pos
249  n_extra_sorting = n_extra_sorting + 1
250  end if
251 
252  call switch(solvent% force, solvent% force_old)
253  call switch(colloids% force, colloids% force_old)
254  solvent% force = 0
255  colloids% force = 0
256  e1 = compute_force(colloids, solvent, neigh, solvent_cells% edges, solvent_colloid_lj)
257  e2 = compute_force_n2(colloids, solvent_cells% edges, colloid_lj)
258 
259  call cell_md_vel(solvent_cells, solvent, dt, md_flag=.true.)
260  colloids% vel = colloids% vel + dt * ( colloids% force + colloids% force_old ) / (2 * mass)
261 
262  end do md_loop_thermo
263 
264  call solvent_cells%random_shift(state(1))
265  call cell_md_pos(solvent_cells, solvent, (i*n_md_steps - loop_i_last_sort)*dt, md_flag=.false.)
266  call cell_md_vel(solvent_cells, solvent, (i*n_md_steps - loop_i_last_sort)*dt, md_flag=.false.)
267 
268  call apply_pbc(solvent, solvent_cells% edges)
269  call apply_pbc(colloids, solvent_cells% edges)
270  call solvent% sort(solvent_cells)
271  loop_i_last_sort = n_md_steps*i
272  call neigh% update_list(colloids, solvent, sigma_cut + skin, solvent_cells)
273  solvent% pos_old = solvent% pos
274  colloids% pos_old = colloids% pos
275 
276  call simple_mpcd_step(solvent, solvent_cells, state, &
277  thermostat=.true., t=t_init, hydro=do_hydro)
278  if (modulo(i, 10) == 0) &
279  call rescale_cells(solvent, solvent_cells, state, t_init)
280 
281  end do
282 
283  loop_i_last_sort = 0
284  write(*,*) ''
285  write(*,*) 'Running for', n_loop, 'loops'
286  do i = 1, n_loop
287  if (modulo(i, 100)==0) write(*, '(i09)', advance='no') i
288  md_loop: do j = 1, n_md_steps
289  call cell_md_pos(solvent_cells, solvent, dt, md_flag=.true.)
290  do k = 1, colloids% Nmax
291  colloids% pos(:,k) = colloids% pos(:,k) + dt * colloids% vel(:,k) + dt**2 * colloids% force(:,k) / (2 * mass)
292  end do
293  so_max = cell_maximum_displacement(solvent_cells, solvent, delta_t=dt*(n_md_steps*(i-1)+j - loop_i_last_sort))
294  co_max = colloids% maximum_displacement()
295 
296  if ( (co_max >= skin*0.1) .or. (so_max >= skin*0.9) ) then
297  call cell_md_pos(solvent_cells, solvent, (n_md_steps*(i-1)+j - loop_i_last_sort)*dt, md_flag=.false.)
298  call cell_md_vel(solvent_cells, solvent, (n_md_steps*(i-1)+j - loop_i_last_sort)*dt, md_flag=.false.)
299 
300  call apply_pbc(solvent, solvent_cells% edges)
301  call apply_pbc(colloids, solvent_cells% edges)
302  call solvent% sort(solvent_cells)
303  loop_i_last_sort = n_md_steps*(i-1) + j
304  call neigh% update_list(colloids, solvent, sigma_cut+skin, solvent_cells)
305  solvent% pos_old = solvent% pos
306  colloids% pos_old = colloids% pos
307  n_extra_sorting = n_extra_sorting + 1
308  end if
309 
310  call switch(solvent% force, solvent% force_old)
311  call switch(colloids% force, colloids% force_old)
312  solvent% force = 0
313  colloids% force = 0
314  e1 = compute_force(colloids, solvent, neigh, solvent_cells% edges, solvent_colloid_lj)
315  e2 = compute_force_n2(colloids, solvent_cells% edges, colloid_lj)
316 
317  call cell_md_vel(solvent_cells, solvent, dt, md_flag=.true.)
318  colloids% vel = colloids% vel + dt * ( colloids% force + colloids% force_old ) / (2 * mass)
319 
320  end do md_loop
321 
322  call solvent_cells%random_shift(state(1))
323  call cell_md_pos(solvent_cells, solvent, (i*n_md_steps - loop_i_last_sort)*dt, md_flag=.false.)
324  call cell_md_vel(solvent_cells, solvent, (i*n_md_steps - loop_i_last_sort)*dt, md_flag=.false.)
325 
326  call apply_pbc(solvent, solvent_cells% edges)
327  call apply_pbc(colloids, solvent_cells% edges)
328  call solvent% sort(solvent_cells)
329  loop_i_last_sort = n_md_steps*i
330  call neigh% update_list(colloids, solvent, sigma_cut + skin, solvent_cells)
331  solvent% pos_old = solvent% pos
332  colloids% pos_old = colloids% pos
333 
334  t = t_init + (i-1)*(t_final-t_init)/(n_loop-1)
335  call simple_mpcd_step(solvent, solvent_cells, state, &
336  thermostat=do_thermostat, t=t, hydro=do_hydro)
337 
338  if (modulo(i,colloid_sampling)==0) then
339  call colloids_io%velocity%append(colloids%vel)
340  call colloids_io%position%append(colloids%pos)
341  call colloids_io%image%append(colloids%image)
342  end if
343 
344  temperature = compute_temperature(solvent, solvent_cells)
345  total_mass = 0
346  kin_e = sum(solvent% vel**2)/2
347  v_com = sum(solvent% vel, dim=2)
348  do k = 1, colloids% Nmax
349  j = colloids%species(k)
350  if (j==0) cycle
351  local_mass = colloids%mass(j)
352  kin_e = kin_e + local_mass*sum(colloids% vel(:,k)**2)/2
353  v_com = v_com + local_mass*colloids%vel(:,k)
354  total_mass = total_mass + local_mass
355  end do
356  v_com = v_com / (solvent%Nmax + total_mass)
357 
358  call thermo_data%append(hfile, temperature, e1+e2, kin_e, e1+e2+kin_e, v_com)
359 
360  radial_hist%data = 0
361  call compute_radial_histogram(radial_hist, colloids%pos(:,1), &
362  solvent_cells%edges, solvent, solvent_cells)
363  call correct_radial_histogram(radial_hist)
364  call radial_hist_el%append(radial_hist%data)
365 
366  end do
367 
368  call thermo_data%append(hfile, temperature, e1+e2, kin_e, e1+e2+kin_e, &
369  v_com, add=.false., force=.true.)
370 
371  write(*,*) 'n extra sorting', n_extra_sorting
372 
373  call h5gcreate_f(hfile%id, 'timers', timers_group, error)
374  call timer_list%append(solvent%time_stream)
375  call timer_list%append(solvent%time_md_vel)
376  call timer_list%append(solvent%time_step)
377  call timer_list%append(solvent%time_count)
378  call timer_list%append(solvent%time_sort)
379  call timer_list%append(solvent%time_ct)
380  call timer_list%append(solvent%time_max_disp)
381  call timer_list%append(solvent%time_apply_pbc)
382  call timer_list%append(neigh%time_update)
383  call timer_list%append(neigh%time_force)
384  call timer_list%append(colloids%time_self_force)
385 
386  call timer_list%write(timers_group, total_time)
387 
388  call h5md_write_dataset(timers_group, 'total', total_time)
389 
390  call h5gclose_f(timers_group, error)
391 
392  call radial_hist_el%close()
393  call colloids_io%close()
394  call hfile%close()
395  call h5close_f(error)
396 
397 end program n_colloids_pbc
program n_colloids_pbc
Simulate an ensemble of spherical colloids.