43 type(cell_system_t) :: solvent_cells
44 type(particle_system_t) :: solvent
45 type(particle_system_t) :: colloids
46 type(neighbor_list_t) :: neigh
47 type(lj_params_t) :: solvent_colloid_lj
48 type(lj_params_t) :: colloid_lj
50 integer,
parameter :: N_species = 2
56 double precision :: sigma_N, sigma_C, max_cut
57 double precision :: epsilon(2,2)
58 double precision :: sigma(2,2), sigma_cut(2,2)
59 double precision :: mass(2)
61 double precision :: e1, e2
62 double precision :: tau, dt , T
63 double precision :: d,prob
64 double precision :: skin, co_max, so_max
65 integer :: N_MD_steps, N_loop, collide_every
66 integer :: n_extra_sorting
72 type(timer_t),
target :: varia, main, time_flag, time_refuel, time_change
73 double precision :: total_time
74 type(timer_list_t) :: timer_list
75 integer(HID_T) :: timers_group
77 type(threefry_rng_t),
allocatable :: state(:)
79 type(h5md_file_t) :: hfile
80 type(h5md_element_t) :: dummy_element
81 integer(HID_T) :: fields_group, params_group
82 integer(HID_T) :: box_group
83 type(thermo_t) :: thermo_data
84 double precision :: temperature, kin_e
85 double precision :: v_com(3)
86 double precision :: com_pos(3)
87 double precision :: unit_r(3)
88 type(particle_system_io_t) :: dimer_io
89 type(particle_system_io_t) :: solvent_io
90 double precision :: bulk_rate
93 integer,
dimension(N_species) :: n_solvent
94 type(h5md_element_t) :: n_solvent_el
96 integer,
parameter :: block_length = 8
97 type(axial_correlator_t) :: axial_cf
98 integer(HID_T) :: correlator_group
100 integer :: equilibration_loops
101 integer :: colloid_sampling
103 logical :: collision_step
104 logical :: do_hydro, do_thermostat
106 type(histogram_t) :: z_hist
107 type(h5md_element_t) :: z_hist_el
108 double precision :: cyl_shell_rmin, cyl_shell_rmax
111 args = get_input_args()
112 call ptparse(config, args%input_file, 11)
114 n_threads = omp_get_max_threads()
115 allocate(state(n_threads))
116 call threefry_rng_init(state, args%seed)
118 call main%init(
'main')
119 call varia%init(
'varia')
120 call time_flag%init(
'flag')
121 call time_refuel%init(
'refuel')
122 call time_change%init(
'change')
124 call timer_list%init(16)
125 call timer_list%append(varia)
126 call timer_list%append(time_flag)
127 call timer_list%append(time_refuel)
128 call timer_list%append(time_change)
131 call hfile%create(args%output_file,
'RMPCDMD::single_dimer_pbc', &
132 rmpcdmd_revision,
'Pierre de Buyl')
133 call h5gcreate_f(hfile%id,
'parameters', params_group, error)
134 call hdf5_util_write_dataset(params_group,
'seed', args%seed)
135 prob = ptread_d(config,
'probability', loc=params_group)
136 bulk_rmpcd = ptread_l(config,
'bulk_rmpcd', loc=params_group)
137 bulk_rate = ptread_d(config,
'bulk_rate', loc=params_group)
139 l = ptread_ivec(config,
'L', 3, loc=params_group)
140 rho = ptread_i(config,
'rho', loc=params_group)
141 n = rho *l(1)*l(2)*l(3)
143 t = ptread_d(config,
'T', loc=params_group)
144 d = ptread_d(config,
'd', loc=params_group)
146 dt = ptread_d(config,
'dt', loc=params_group)
147 n_md_steps = ptread_i(config,
'N_MD', loc=params_group)
149 collide_every = ptread_i(config,
'collide_every', loc=params_group)
150 tau = dt*n_md_steps*collide_every
152 n_loop = ptread_i(config,
'N_loop', loc=params_group)
153 equilibration_loops = ptread_i(config,
'equilibration_loops', loc=params_group)
155 colloid_sampling = ptread_i(config,
'colloid_sampling', loc=params_group)
156 if (modulo(n_md_steps, colloid_sampling) /= 0)
then 157 error stop
'colloid_sampling must divide N_MD with no remainder' 160 sigma_c = ptread_d(config,
'sigma_C', loc=params_group)
161 sigma_n = ptread_d(config,
'sigma_N', loc=params_group)
164 epsilon(:,1) = ptread_dvec(config,
'epsilon_C', 2, loc=params_group)
165 epsilon(:,2) = ptread_dvec(config,
'epsilon_N', 2, loc=params_group)
169 sigma_cut = sigma*2**(1.d0/6.d0)
170 max_cut = maxval(sigma_cut)
172 call solvent_colloid_lj% init(epsilon, sigma, sigma_cut)
174 epsilon(1,1) = ptread_d(config,
'epsilon_C_C', loc=params_group)
175 epsilon(1,2) = ptread_d(config,
'epsilon_N_C', loc=params_group)
176 epsilon(2,1) = epsilon(1,2)
177 epsilon(2,2) = ptread_d(config,
'epsilon_N_N', loc=params_group)
179 sigma(1,1) = 2*sigma_c
180 sigma(1,2) = sigma_c + sigma_n
181 sigma(2,1) = sigma_c + sigma_n
182 sigma(2,2) = 2*sigma_n
183 sigma_cut = sigma*2**(1.d0/6.d0)
185 call colloid_lj% init(epsilon, sigma, sigma_cut)
187 mass(1) = rho * sigma_c**3 * 4 * 3.14159265/3
188 mass(2) = rho * sigma_n**3 * 4 * 3.14159265/3
190 call solvent% init(n,2, system_name=
'solvent')
192 call colloids% init(2,2, mass, system_name=
'colloids')
194 call thermo_data%init(hfile, n_buffer=50, step=n_md_steps, time=n_md_steps*dt)
196 do_hydro = ptread_l(config,
'do_hydro', loc=params_group)
197 do_thermostat = ptread_l(config,
'do_thermostat', loc=params_group)
199 call h5gclose_f(params_group, error)
202 call axial_cf%init(block_length, n_loop, n_loop*n_md_steps)
204 colloids% species(1) = 1
205 colloids% species(2) = 2
209 dimer_io%force_info%store = .false.
210 dimer_io%id_info%store = .false.
211 dimer_io%position_info%store = .true.
212 dimer_io%position_info%mode = ior(h5md_linear,h5md_store_time)
213 dimer_io%position_info%step = colloid_sampling
214 dimer_io%position_info%time = colloid_sampling*dt
215 dimer_io%image_info%store = .true.
216 dimer_io%image_info%mode = ior(h5md_linear,h5md_store_time)
217 dimer_io%image_info%step = colloid_sampling
218 dimer_io%image_info%time = colloid_sampling*dt
219 dimer_io%velocity_info%store = .true.
220 dimer_io%velocity_info%mode = ior(h5md_linear,h5md_store_time)
221 dimer_io%velocity_info%step = colloid_sampling
222 dimer_io%velocity_info%time = colloid_sampling*dt
223 dimer_io%species_info%store = .true.
224 dimer_io%species_info%mode = h5md_fixed
225 call dimer_io%init(hfile,
'dimer', colloids)
227 solvent_io%force_info%store = .false.
228 solvent_io%id_info%store = .false.
229 solvent_io%position_info%store = .true.
230 solvent_io%position_info%mode = ior(h5md_linear,h5md_store_time)
231 solvent_io%position_info%step = n_loop*n_md_steps
232 solvent_io%position_info%time = n_loop*n_md_steps*dt
233 solvent_io%image_info%store = .true.
234 solvent_io%image_info%mode = ior(h5md_linear,h5md_store_time)
235 solvent_io%image_info%step = n_loop*n_md_steps
236 solvent_io%image_info%time = n_loop*n_md_steps*dt
237 solvent_io%velocity_info%store = .true.
238 solvent_io%velocity_info%mode = ior(h5md_linear,h5md_store_time)
239 solvent_io%velocity_info%step = n_loop*n_md_steps
240 solvent_io%velocity_info%time = n_loop*n_md_steps*dt
241 solvent_io%species_info%store = .true.
242 solvent_io%species_info%mode = ior(h5md_linear,h5md_store_time)
243 solvent_io%species_info%step = n_loop*n_md_steps
244 solvent_io%species_info%time = n_loop*n_md_steps*dt
245 call solvent_io%init(hfile,
'solvent', solvent)
247 do k = 1, solvent%Nmax
248 solvent% vel(1,k) = threefry_normal(state(1))*sqrt(t)
249 solvent% vel(2,k) = threefry_normal(state(1))*sqrt(t)
250 solvent% vel(3,k) = threefry_normal(state(1))*sqrt(t)
252 solvent% vel = solvent% vel - spread(sum(solvent% vel, dim=2)/solvent% Nmax, 2, solvent% Nmax)
256 call solvent_cells%init(l, 1.d0)
257 colloids% pos(:,1) = solvent_cells% edges/2.0
258 colloids% pos(:,2) = solvent_cells% edges/2.0
259 colloids% pos(1,2) = colloids% pos(1,2) + d
261 call n_solvent_el%create_time(hfile%observables,
'n_solvent', &
262 n_solvent, h5md_linear, step=n_md_steps, &
265 call h5gcreate_f(dimer_io%group,
'box', box_group, error)
266 call h5md_write_attribute(box_group,
'dimension', 3)
267 call dummy_element%create_fixed(box_group,
'edges', solvent_cells%edges)
268 call h5gclose_f(box_group, error)
270 call h5gcreate_f(solvent_io%group,
'box', box_group, error)
271 call h5md_write_attribute(box_group,
'dimension', 3)
272 call dummy_element%create_fixed(box_group,
'edges', solvent_cells%edges)
273 call h5gclose_f(box_group, error)
275 call solvent% random_placement(solvent_cells% edges, colloids, solvent_colloid_lj, state(1))
277 call solvent% sort(solvent_cells)
279 call neigh% init(colloids% Nmax, int(300*max(sigma_c,sigma_n)**3))
284 call neigh% make_stencil(solvent_cells, max_cut+skin)
286 call neigh% update_list(colloids, solvent, max_cut+skin, solvent_cells, solvent_colloid_lj)
288 cyl_shell_rmin = max(sigma_n, sigma_c)
289 cyl_shell_rmax = cyl_shell_rmin + 2
290 call h5gcreate_f(hfile%id,
'fields', fields_group, error)
291 call z_hist%init(-5.d0, 5.d0+d, 100)
292 call z_hist_el%create_time(fields_group,
'cylindrical_shell_histogram', z_hist%data, &
293 h5md_linear, step=n_md_steps, time=n_md_steps*dt)
294 call h5md_write_attribute(z_hist_el%id,
'r_min', cyl_shell_rmin)
295 call h5md_write_attribute(z_hist_el%id,
'r_max', cyl_shell_rmax)
296 call h5md_write_attribute(z_hist_el%id,
'xmin', z_hist%xmin)
297 call h5md_write_attribute(z_hist_el%id,
'dx', z_hist%dx)
298 call h5gclose_f(fields_group, error)
300 e1 = compute_force(colloids, solvent, neigh, solvent_cells% edges, solvent_colloid_lj)
301 e2 = compute_force_n2(colloids, solvent_cells% edges, colloid_lj)
302 solvent% force_old = solvent% force
303 colloids% force_old = colloids% force
305 call h5fflush_f(hfile%id, h5f_scope_global_f, error)
307 write(*,*)
'Box size', l
308 write(*,*)
'Fluid particles', n
310 write(*,*)
'MPCD tau', tau
312 write(*,*)
'RS resampling time', tau
314 write(*,*)
'Dimer mass', mass
316 write(*,*)
'Running for', equilibration_loops,
'+', n_loop,
'loops' 320 do i = 0, n_loop+equilibration_loops
321 if (i==equilibration_loops) sampling = .true.
322 if (modulo(i,20) == 0)
write(*,
'(i05)',advance=
'no') i
323 md_loop:
do j = 1, n_md_steps
324 call md_pos(solvent, dt)
328 colloids% pos_rattle = colloids% pos
329 do k=1, colloids% Nmax
330 colloids% pos(:,k) = colloids% pos(:,k) + dt * colloids% vel(:,k) + &
331 dt**2 * colloids% force(:,k) / (2 * colloids% mass(k))
334 call rattle_dimer_pos(colloids, d, dt, solvent_cells% edges)
337 so_max = solvent% maximum_displacement()
338 co_max = colloids% maximum_displacement()
340 if ( (co_max >= skin*0.1d0) .or. (so_max >= skin*0.89d0) )
then 342 call apply_pbc(solvent, solvent_cells% edges)
343 call apply_pbc(colloids, solvent_cells% edges)
345 call solvent% sort(solvent_cells)
346 call neigh% update_list(colloids, solvent, max_cut + skin, solvent_cells, solvent_colloid_lj)
349 do k = 1, solvent%Nmax
350 solvent% pos_old(:,k) = solvent% pos(:,k)
352 colloids% pos_old = colloids% pos
353 n_extra_sorting = n_extra_sorting + 1
358 call switch(solvent% force, solvent% force_old)
359 call switch(colloids% force, colloids% force_old)
362 do k = 1, solvent%Nmax
363 solvent% force(:,k) = 0
367 e1 = compute_force(colloids, solvent, neigh, solvent_cells% edges, solvent_colloid_lj)
368 e2 = compute_force_n2(colloids, solvent_cells% edges, colloid_lj)
370 call md_vel(solvent, dt)
373 do k=1, colloids% Nmax
374 colloids% vel(:,k) = colloids% vel(:,k) + &
375 dt * ( colloids% force(:,k) + colloids% force_old(:,k) ) / (2 * colloids% mass(k))
378 call rattle_dimer_vel(colloids, d, dt, solvent_cells% edges)
382 v_com = sum(colloids%vel, dim=2)/2
383 unit_r = rel_pos(colloids%pos(:,1), colloids%pos(:,2), solvent_cells%edges)
384 unit_r = unit_r / norm2(unit_r)
385 call axial_cf%add_fast((i-equilibration_loops)*n_md_steps+j-1, v_com, unit_r)
388 if ((sampling) .and. (modulo(j, colloid_sampling)==0))
then 389 call dimer_io%position%append(colloids%pos)
390 call dimer_io%velocity%append(colloids%vel)
391 call dimer_io%image%append(colloids%image)
397 call time_change%tic()
399 call time_change%tac()
403 collision_step = (modulo(i, collide_every) == 0)
408 temperature = compute_temperature(solvent, solvent_cells)
409 kin_e = (colloids% mass(1)*sum(colloids% vel(:,1)**2) + &
410 colloids% mass(2)*sum(colloids% vel(:,2)**2))/2 + &
411 sum(solvent% vel**2)/2
412 v_com = (sum(solvent% vel, dim=2) + &
413 mass(1)*colloids%vel(:,1) + mass(2)*colloids%vel(:,2)) / &
414 (solvent%Nmax + mass(1) + mass(2))
416 call thermo_data%append(hfile, temperature, e1+e2, kin_e, e1+e2+kin_e, v_com)
418 com_pos = ( colloids%pos(:,1)+colloids%image(:,1)*solvent_cells%edges + &
419 colloids%pos(:,2)+colloids%image(:,2)*solvent_cells%edges)/2
420 call axial_cf%add(i-equilibration_loops, com_pos, unit_r)
424 if (collision_step)
call solvent_cells%random_shift(state(1))
427 call apply_pbc(solvent, solvent_cells% edges)
428 call apply_pbc(colloids, solvent_cells% edges)
429 call solvent% sort(solvent_cells)
430 call neigh% update_list(colloids, solvent, max_cut+skin, solvent_cells, solvent_colloid_lj)
433 do k = 1, solvent%Nmax
434 solvent% pos_old(:,k) = solvent% pos(:,k)
436 colloids% pos_old = colloids% pos
439 if (collision_step)
call simple_mpcd_step(solvent, solvent_cells, state, &
440 thermostat=do_thermostat, t=t, hydro=do_hydro)
442 call time_refuel%tic()
444 call bulk_reaction(solvent, solvent_cells, 2, 1, bulk_rate, tau, state)
449 call time_refuel%tac()
452 do k = 1, solvent%Nmax
453 j = solvent%species(k)
455 n_solvent(j) = n_solvent(j) + 1
457 call n_solvent_el%append(n_solvent)
460 call compute_cylindrical_shell_histogram(z_hist, colloids%pos(:,1), colloids%pos(:,2), &
461 solvent_cells%edges, 2, cyl_shell_rmin, cyl_shell_rmax, solvent)
462 call z_hist_el%append(z_hist%data)
468 write(*,*)
'n extra sorting', n_extra_sorting
472 call h5gcreate_f(hfile%id,
'block_correlators', correlator_group, error)
473 call axial_cf%write(correlator_group, n_md_steps, n_md_steps*dt, 1, dt)
474 call h5gclose_f(correlator_group, error)
478 call solvent_io%position%append(solvent%pos)
479 call solvent_io%velocity%append(solvent%vel)
480 call solvent_io%image%append(solvent%image)
481 call solvent_io%species%append(solvent%species)
484 call timer_list%append(solvent%time_stream)
485 call timer_list%append(solvent%time_step)
486 call timer_list%append(solvent%time_count)
487 call timer_list%append(solvent%time_sort)
488 call timer_list%append(solvent%time_ct)
489 call timer_list%append(solvent%time_md_pos)
490 call timer_list%append(solvent%time_md_vel)
491 call timer_list%append(solvent%time_max_disp)
492 call timer_list%append(colloids%time_self_force)
493 call timer_list%append(neigh%time_update)
494 call timer_list%append(neigh%time_force)
495 call timer_list%append(colloids%time_max_disp)
497 call h5gcreate_f(hfile%id,
'timers', timers_group, error)
498 call timer_list%write(timers_group, total_time)
499 call h5md_write_dataset(timers_group,
'total', total_time)
500 call h5md_write_dataset(timers_group, main%name, main%total)
501 call h5gclose_f(timers_group, error)
503 call dimer_io%close()
504 call solvent_io%close()
505 call z_hist_el%close()
506 call n_solvent_el%close()
508 call h5close_f(error)
513 double precision :: dist_to_C_sq
515 double precision :: x(3)
519 if (solvent% species(r) == 1)
then 520 x = rel_pos(colloids% pos(:,1),solvent% pos(:,r),solvent_cells% edges)
521 dist_to_c_sq = dot_product(x, x)
522 if (dist_to_c_sq < solvent_colloid_lj%cut_sq(1,1))
then 523 solvent% flags(r) = ibset(solvent% flags(r), reac_bit)
531 double precision :: dist_to_C_sq
532 double precision :: dist_to_N_sq
534 double precision :: x(3)
538 thread_id = omp_get_thread_num() + 1
540 do m = 1, solvent% Nmax
541 if (btest(solvent% flags(m), reac_bit))
then 542 x = rel_pos(colloids% pos(:,1), solvent% pos(:,m), solvent_cells% edges)
543 dist_to_c_sq = dot_product(x, x)
544 x = rel_pos(colloids% pos(:,2), solvent% pos(:,m), solvent_cells% edges)
545 dist_to_n_sq = dot_product(x, x)
547 (dist_to_c_sq > solvent_colloid_lj%cut_sq(1,1)) &
549 (dist_to_n_sq > solvent_colloid_lj%cut_sq(1,2)) &
552 if (threefry_double(state(thread_id)) <= prob)
then 553 solvent% species(m) = 2
555 solvent%flags(m) = ibclr(solvent%flags(m), reac_bit)
564 double precision :: dist_to_C_sq
565 double precision :: dist_to_N_sq
566 double precision :: far
567 double precision :: x(3)
573 do n = 1,solvent% Nmax
574 if (solvent% species(n) == 2)
then 575 x = rel_pos(colloids% pos(:,1), solvent% pos(:,n), solvent_cells% edges)
576 dist_to_c_sq = dot_product(x, x)
577 x= rel_pos(colloids% pos(:,2), solvent% pos(:,n), solvent_cells% edges)
578 dist_to_n_sq = dot_product(x, x)
579 if ((dist_to_c_sq > far) .and. (dist_to_n_sq > far))
then 580 solvent% species(n) = 1
subroutine change_species
subroutine flag_particles_nl
program single_dimer_pbc
Simulate a single dimer nanomotor.