RMPCDMD
setup_single_catalytic_fixed_sphere.f90
Go to the documentation of this file.
1 ! This file is part of RMPCDMD
2 ! Copyright (c) 2015-2016 Pierre de Buyl and contributors
3 ! License: BSD 3-clause (see file LICENSE)
4 
6  use common
7  use cell_system
10  use hilbert
11  use neighbor_list
12  use hdf5
13  use h5md_module
14  use interaction
15  use threefry_module
16  use mpcd
17  use md
18  use parsetext
19  use iso_c_binding
20  use omp_lib
21  implicit none
22 
23  type(cell_system_t) :: solvent_cells
24  type(particle_system_t) :: solvent
25  type(particle_system_t) :: colloids
26  type(neighbor_list_t) :: neigh
27  type(lj_params_t) :: solvent_colloid_lj
28 
29  integer, parameter :: N_species = 2
30 
31  integer :: rho
32  integer :: N
33  integer :: error
34 
35  double precision :: epsilon, sigma, sigma_cut
36  double precision :: mass
37 
38  double precision :: e1
39  double precision :: tau, dt , T
40  double precision :: prob
41  double precision :: skin, so_max
42  integer :: N_MD_steps, N_loop
43  integer :: n_extra_sorting
44 
45  type(pto) :: config
46 
47  integer :: i, L(3)
48  integer :: j, k
49  type(timer_t) :: varia, main
50  type(timer_t) :: time_flag, time_refuel, time_change
51  type(threefry_rng_t), allocatable :: state(:)
52  integer :: n_threads
53  type(h5md_file_t) :: hfile
54  type(h5md_element_t) :: dummy_element
55  integer(HID_T) :: fields_group
56  integer(HID_T) :: box_group
57  type(thermo_t) :: thermo_data
58  double precision :: temperature, kin_e
59  double precision :: v_com(3)
60  type(particle_system_io_t) :: solvent_io
61 
62  integer, dimension(N_species) :: n_solvent
63  type(h5md_element_t) :: n_solvent_el
64 
65  type(histogram_t) :: polar_hist
66  type(h5md_element_t) :: polar_hist_el
67 
68  logical :: rmpcd_refuel
69  double precision :: bulk_rate
70 
71  call ptparse(config,get_input_filename(),11)
72 
73  n_threads = omp_get_max_threads()
74  allocate(state(n_threads))
75  call threefry_rng_init(state, ptread_c_int64(config, 'seed'))
76 
77  call main%init('main')
78  call varia%init('varia')
79  call time_flag%init('flag')
80  call time_refuel%init('refuel')
81  call time_change%init('change')
82 
83  call h5open_f(error)
84 
85  prob = ptread_d(config,'probability')
86  rmpcd_refuel = ptread_l(config, 'rmpcd_refuel')
87  bulk_rate = ptread_d(config, 'bulk_rate')
88 
89  l = ptread_ivec(config, 'L', 3)
90  rho = ptread_i(config, 'rho')
91  n = rho *l(1)*l(2)*l(3)
92 
93  t = ptread_d(config, 'T')
94 
95  tau = ptread_d(config, 'tau')
96  n_md_steps = ptread_i(config, 'N_MD')
97  dt = tau / n_md_steps
98  n_loop = ptread_i(config, 'N_loop')
99 
100  epsilon = ptread_d(config, 'epsilon')
101  sigma = ptread_d(config, 'sigma')
102  sigma_cut = sigma*2**(1.d0/6.d0)
103  mass = rho * sigma**3 * 4 * 3.14159265/3
104 
105  call solvent_colloid_lj% init(&
106  reshape([epsilon, epsilon], [2, 1]),&
107  reshape([sigma, sigma], [2, 1]),&
108  reshape([sigma_cut, sigma_cut], [2, 1]))
109 
110  call solvent% init(n,2) !there will be 2 species of solvent particles
111 
112  call colloids% init(1,1, [mass]) !there will be 1 species of colloids
113 
114  call hfile%create(ptread_s(config, 'h5md_file'), &
115  'RMPCDMD::setup_single_catalytic_fixed_sphere', 'N/A', 'Pierre de Buyl')
116  call thermo_data%init(hfile, n_buffer=50, step=n_md_steps, time=n_md_steps*dt)
117 
118  call ptkill(config)
119 
120  colloids% species(1) = 1
121  colloids% vel = 0
122 
123  solvent_io%force_info%store = .false.
124  solvent_io%id_info%store = .false.
125  solvent_io%position_info%store = .true.
126  solvent_io%position_info%mode = ior(h5md_linear,h5md_store_time)
127  solvent_io%position_info%step = n_loop*n_md_steps
128  solvent_io%position_info%time = n_loop*n_md_steps*dt
129  solvent_io%image_info%store = .true.
130  solvent_io%image_info%mode = ior(h5md_linear,h5md_store_time)
131  solvent_io%image_info%step = n_loop*n_md_steps
132  solvent_io%image_info%time = n_loop*n_md_steps*dt
133  solvent_io%velocity_info%store = .true.
134  solvent_io%velocity_info%mode = ior(h5md_linear,h5md_store_time)
135  solvent_io%velocity_info%step = n_loop*n_md_steps
136  solvent_io%velocity_info%time = n_loop*n_md_steps*dt
137  solvent_io%species_info%store = .true.
138  solvent_io%species_info%mode = ior(h5md_linear,h5md_store_time)
139  solvent_io%species_info%step = n_loop*n_md_steps
140  solvent_io%species_info%time = n_loop*n_md_steps*dt
141  call solvent_io%init(hfile, 'solvent', solvent)
142 
143  call random_number(solvent% vel(:, :))
144  solvent% vel = (solvent% vel - 0.5d0)*sqrt(12*t)
145  solvent% vel = solvent% vel - spread(sum(solvent% vel, dim=2)/solvent% Nmax, 2, solvent% Nmax)
146  solvent% force = 0
147  solvent% species = 1
148 
149  call solvent_cells%init(l, 1.d0)
150  colloids% pos(:,1) = solvent_cells% edges/2.0
151 
152  call n_solvent_el%create_time(hfile%observables, 'n_solvent', &
153  n_solvent, h5md_linear, step=n_md_steps, &
154  time=n_md_steps*dt)
155 
156  call h5gcreate_f(solvent_io%group, 'box', box_group, error)
157  call h5md_write_attribute(box_group, 'dimension', 3)
158  call dummy_element%create_fixed(box_group, 'edges', solvent_cells%edges)
159  call h5gclose_f(box_group, error)
160 
161  call h5gcreate_f(hfile%id, 'fields', fields_group, error)
162  call polar_hist%init(0.d0, 3*sigma, 100, 2)
163  call polar_hist_el%create_time(fields_group, 'polar_histogram', polar_hist%data, &
164  h5md_linear, step=n_md_steps, time=n_md_steps*dt)
165  call h5md_write_attribute(polar_hist_el%id, 'xmin', polar_hist%xmin)
166  call h5md_write_attribute(polar_hist_el%id, 'dx', polar_hist%dx)
167  call h5gclose_f(fields_group, error)
168 
169  call solvent% random_placement(solvent_cells% edges, colloids, solvent_colloid_lj, state(1))
170 
171  call solvent% sort(solvent_cells)
172 
173  call neigh% init(colloids% Nmax, int(300*sigma**3))
174 
175  skin = 1.5
176  n_extra_sorting = 0
177 
178  call neigh% make_stencil(solvent_cells, sigma_cut+skin)
179 
180  call neigh% update_list(colloids, solvent, sigma_cut+skin, solvent_cells)
181 
182  e1 = compute_force(colloids, solvent, neigh, solvent_cells% edges, solvent_colloid_lj)
183  solvent% force_old = solvent% force
184  colloids% force_old = colloids% force
185 
186  write(*,*) 'Running for', n_loop, 'loops'
187  call main%tic()
188  do i = 1, n_loop
189  if (modulo(i,5) == 0) write(*,'(i05)',advance='no') i
190  md_loop: do j = 1, n_md_steps
191  call md_pos(solvent, dt)
192 
193  so_max = solvent% maximum_displacement()
194 
195  if ( so_max >= skin ) then
196  call varia%tic()
197  call apply_pbc(solvent, solvent_cells% edges)
198  call varia%tac()
199  call solvent% sort(solvent_cells)
200  call neigh% update_list(colloids, solvent, sigma_cut + skin, solvent_cells)
201  call varia%tic()
202  solvent% pos_old = solvent% pos
203  n_extra_sorting = n_extra_sorting + 1
204  call varia%tac()
205  end if
206 
207  call varia%tic()
208  call switch(solvent% force, solvent% force_old)
209  call switch(colloids% force, colloids% force_old)
210 
211  !$omp parallel do
212  do k = 1, solvent%Nmax
213  solvent% force(:,k) = 0
214  end do
215 
216  call varia%tac()
217  e1 = compute_force(colloids, solvent, neigh, solvent_cells% edges, solvent_colloid_lj)
218 
219  call md_vel(solvent, dt)
220 
221  call time_flag%tic()
222  call flag_particles_nl
223  call time_flag%tac()
224  call time_change%tic()
225  call change_species
226  call time_change%tac()
227 
228  end do md_loop
229 
230  call varia%tic()
231 
232  temperature = compute_temperature(solvent, solvent_cells)
233  kin_e = sum(solvent% vel**2)/2
234  v_com = sum(solvent% vel, dim=2) / solvent%Nmax
235 
236  call thermo_data%append(hfile, temperature, e1, kin_e, e1+kin_e, v_com)
237 
238  solvent_cells% origin(1) = threefry_double(state(1)) - 1
239  solvent_cells% origin(2) = threefry_double(state(1)) - 1
240  solvent_cells% origin(3) = threefry_double(state(1)) - 1
241  call varia%tac()
242 
243  call solvent% sort(solvent_cells)
244  call neigh% update_list(colloids, solvent, sigma_cut+skin, solvent_cells)
245 
246  call simple_mpcd_step(solvent, solvent_cells, state)
247 
248  ! either refuel or bulk reaction
249  call time_refuel%tic()
250  if (rmpcd_refuel) then
251  call bulk_reaction(solvent, solvent_cells, 2, 1, bulk_rate, tau, state)
252  else
253  call refuel
254  end if
255  call time_refuel%tac()
256 
257  n_solvent = 0
258  do k = 1, solvent%Nmax
259  j = solvent%species(k)
260  if (j <= 0) continue
261  n_solvent(j) = n_solvent(j) + 1
262  end do
263  call n_solvent_el%append(n_solvent)
264 
265  call update_polar_hist
266 
267  end do
268  call main%tac()
269  write(*,*) ''
270 
271  write(*,*) 'n extra sorting', n_extra_sorting
272 
273  call solvent_io%position%append(solvent%pos)
274  call solvent_io%velocity%append(solvent%vel)
275  call solvent_io%image%append(solvent%image)
276  call solvent_io%species%append(solvent%species)
277 
278  call solvent_io%close()
279  call n_solvent_el%close()
280  call hfile%close()
281  call h5close_f(error)
282 
283  write(*,'(a16,f8.3)') solvent%time_stream%name, solvent%time_stream%total
284  write(*,'(a16,f8.3)') solvent%time_step%name, solvent%time_step%total
285  write(*,'(a16,f8.3)') solvent%time_count%name, solvent%time_count%total
286  write(*,'(a16,f8.3)') solvent%time_sort%name, solvent%time_sort%total
287  write(*,'(a16,f8.3)') solvent%time_ct%name, solvent%time_ct%total
288  write(*,'(a16,f8.3)') solvent%time_md_pos%name, solvent%time_md_pos%total
289  write(*,'(a16,f8.3)') solvent%time_md_vel%name, solvent%time_md_vel%total
290  write(*,'(a16,f8.3)') solvent%time_max_disp%name, solvent%time_max_disp%total
291  write(*,'(a16,f8.3)') colloids%time_self_force%name, solvent%time_self_force%total
292  write(*,'(a16,f8.3)') neigh%time_update%name, neigh%time_update%total
293  write(*,'(a16,f8.3)') neigh%time_force%name, neigh%time_force%total
294  write(*,'(a16,f8.3)') colloids%time_max_disp%name, colloids%time_max_disp%total
295  write(*,'(a16,f8.3)') time_flag%name, time_flag%total
296  write(*,'(a16,f8.3)') time_change%name, time_change%total
297  write(*,'(a16,f8.3)') time_refuel%name, time_refuel%total
298 
299  write(*,'(a16,f8.3)') 'total', solvent%time_stream%total + solvent%time_step%total + &
300  solvent%time_count%total + solvent%time_sort%total + solvent%time_ct%total + &
301  solvent%time_md_pos%total + solvent%time_md_vel%total + &
302  solvent%time_max_disp%total + solvent%time_self_force%total + &
303  neigh%time_update%total + neigh%time_force%total + colloids%time_max_disp%total + &
304  time_flag%total + time_change%total + time_refuel%total
305 
306  write(*,'(a16,f8.3)') varia%name, varia%total
307  write(*,'(a16,f8.3)') main%name, main%total
308 
309 contains
310 
311  subroutine flag_particles_nl
312  double precision :: dist_to_C_sq
313  integer :: r, s
314  double precision :: x(3)
315 
316  do s = 1,neigh% n(1)
317  r = neigh%list(s,1)
318  if (solvent% species(r) == 1) then
319  x = rel_pos(colloids% pos(:,1),solvent% pos(:,r),solvent_cells% edges)
320  dist_to_c_sq = dot_product(x, x)
321  if (dist_to_c_sq < solvent_colloid_lj%cut_sq(1,1)) then
322  if (threefry_double(state(1)) <= prob) then
323  solvent%flags(r) = ibset(solvent%flags(r), reac_bit)
324  end if
325  end if
326  end if
327  end do
328 
329  end subroutine flag_particles_nl
330 
331  subroutine change_species
332  double precision :: dist_to_sphere_sq
333  integer :: m
334  double precision :: x(3)
335 
336  !$omp parallel do private(x, dist_to_sphere_sq)
337  do m = 1, solvent% Nmax
338  if (btest(solvent%flags(m), reac_bit)) then
339  x = rel_pos(colloids% pos(:,1), solvent% pos(:,m), solvent_cells% edges)
340  dist_to_sphere_sq = dot_product(x, x)
341  if (dist_to_sphere_sq > solvent_colloid_lj%cut_sq(1,1)) then
342  solvent% species(m) = 2
343  solvent%flags(m) = ibclr(solvent%flags(m), reac_bit)
344  end if
345  end if
346  end do
347 
348  end subroutine change_species
349 
350  subroutine refuel
351  double precision :: dist_to_C_sq
352  double precision :: dist_to_N_sq
353  double precision :: far
354  double precision :: x(3)
355  integer :: n
356 
357  far = (l(1)*0.45)**2
358 
359  !$omp parallel do private(x, dist_to_C_sq, dist_to_N_sq)
360  do n = 1,solvent% Nmax
361  if (solvent% species(n) == 2) then
362  x = rel_pos(colloids% pos(:,1), solvent% pos(:,n), solvent_cells% edges)
363  dist_to_c_sq = dot_product(x, x)
364  x= rel_pos(colloids% pos(:,2), solvent% pos(:,n), solvent_cells% edges)
365  dist_to_n_sq = dot_product(x, x)
366  if ((dist_to_c_sq > far) .and. (dist_to_n_sq > far)) then
367  solvent% species(n) = 1
368  end if
369  end if
370  end do
371  end subroutine refuel
372 
373  subroutine update_polar_hist
374  integer :: i, s
375  double precision :: r, x(3), r_up
376 
377  polar_hist%data = 0
378  do i = 1, solvent%Nmax
379  s = solvent%species(i)
380  if (s<=0) cycle
381  x = rel_pos(colloids% pos(:,1), solvent% pos(:,i), solvent_cells% edges)
382  r = sqrt(sum(x**2))
383  call polar_hist%bin(r, s)
384  end do
385 
386  do i = 1, polar_hist%n
387  r = (i-1)*polar_hist%dx
388  r_up = i*polar_hist%dx
389  polar_hist%data(:,i) = polar_hist%data(:,i) / (4.d0/3.d0*pi*(r_up**3-r**3))
390  end do
391 
392  call polar_hist_el%append(polar_hist%data)
393 
394  end subroutine update_polar_hist
395 
Derived type and routines for neighbor listing.
subroutine, public md_vel(particles, dt)
Definition: md.f90:220
character(len=max_path_length) function, public get_input_filename()
Definition: common.f90:299
double precision function, public compute_temperature(particles, cells, tz)
Compute the temperature of a mpcd solvent.
Definition: mpcd.f90:343
Data for particles.
subroutine, public simple_mpcd_step(particles, cells, state, alpha, thermostat, T, hydro)
Perform a collision.
Definition: mpcd.f90:72
subroutine, public bulk_reaction(p, c, from, to, rate, tau, state)
Apply a bulk unimolecular RMPCD reaction.
Definition: mpcd.f90:606
double precision function, public compute_force(ps1, ps2, n_list, L, lj_params)
subroutine change_species
subroutine, public apply_pbc(particles, edges)
Definition: md.f90:203
Compute compact Hilbert indices.
Definition: hilbert.f90:9
integer, parameter, public reac_bit
Definition: common.f90:49
subroutine update_polar_hist
subroutine flag_particles_nl
Utility routines.
Definition: common.f90:12
Facilities for particle data I/O.
integer, parameter dim
Definition: hilbert.f90:15
subroutine, public md_pos(particles, dt)
Definition: md.f90:62
Routines to perform MPCD dynamics.
Definition: mpcd.f90:18
Routines to perform Molecular Dynamics integration.
Definition: md.f90:13
pure double precision function, dimension(3), public rel_pos(x, y, L)
Return x-y distance with minimum image convention.
Definition: common.f90:163
Container for a histogram, e.g. p(x)
Definition: common.f90:86
Spatial cells.
Definition: cell_system.f90:11
subroutine refuel
Lennard-Jones potential definition.
Definition: interaction.f90:10
double precision, parameter, public pi
Definition: common.f90:47
program setup_single_catalytic_fixed_sphere