42 type(cell_system_t) :: solvent_cells
43 type(particle_system_t) :: solvent
44 type(particle_system_t) :: colloids
45 type(neighbor_list_t) :: neigh
46 type(lj_params_t) :: solvent_colloid_lj
47 type(lj_params_t) :: colloid_lj
48 type(lj_params_t) :: walls_colloid_lj
50 integer,
parameter :: N_species = 1
51 integer,
parameter :: N_colloid_species = 2
57 double precision :: max_cut
58 double precision :: epsilon(n_species, n_colloid_species)
59 double precision :: sigma(n_species, n_colloid_species), sigma_cut(n_species, n_colloid_species)
60 double precision :: mass(n_colloid_species)
62 logical :: do_rattle, do_harmonic
63 double precision :: harmonic_k
64 double precision :: wall_sigma(3, n_species), wall_epsilon(3, n_species), wall_shift(3)
66 double precision :: e1, e2, e3, e_wall
67 double precision :: tau, dt , T
69 double precision :: skin, co_max, so_max
70 integer :: N_MD_steps, N_loop
71 integer :: n_extra_sorting
72 integer :: loop_i_last_sort
78 type(timer_t),
target :: varia, main
79 double precision :: total_time
80 double precision :: theta
81 type(timer_list_t) :: timer_list
82 integer(HID_T) :: timers_group
84 type(threefry_rng_t),
allocatable :: state(:)
86 type(h5md_file_t) :: hfile
87 type(h5md_element_t) :: dummy_element
88 integer(HID_T) :: params_group
89 integer(HID_T) :: box_group
90 type(thermo_t) :: thermo_data
91 double precision :: temperature, kin_e
92 double precision :: v_com(3)
93 double precision :: com_pos(3)
94 double precision :: unit_r(3)
95 type(particle_system_io_t) :: dimer_io
97 integer,
parameter :: block_length = 8
98 type(axial_correlator_t) :: axial_cf
99 integer(HID_T) :: correlator_group
101 integer :: equilibration_loops
102 integer :: colloid_sampling
106 character(len=144) :: initial_condition, fluid_wall
108 args = get_input_args()
109 call ptparse(config, args%input_file, 11)
111 n_threads = omp_get_max_threads()
112 allocate(state(n_threads))
113 call threefry_rng_init(state, args%seed)
115 call main%init(
'main')
116 call varia%init(
'varia')
118 call timer_list%init(13)
119 call timer_list%append(varia)
122 call hfile%create(args%output_file,
'RMPCDMD::single_dimer', &
123 rmpcdmd_revision,
'Pierre de Buyl')
124 call h5gcreate_f(hfile%id,
'parameters', params_group, error)
125 call hdf5_util_write_dataset(params_group,
'seed', args%seed)
127 l = ptread_ivec(config,
'L', 3, loc=params_group)
128 rho = ptread_i(config,
'rho', loc=params_group)
129 n = rho *l(1)*l(2)*l(3)
131 t = ptread_d(config,
'T', loc=params_group)
132 d = ptread_d(config,
'd', loc=params_group)
133 do_rattle = ptread_l(config,
'do_rattle', loc=params_group)
134 do_harmonic = ptread_l(config,
'do_harmonic', loc=params_group)
135 harmonic_k = ptread_d(config,
'harmonic_k', loc=params_group)
137 tau = ptread_d(config,
'tau', loc=params_group)
138 n_md_steps = ptread_i(config,
'N_MD', loc=params_group)
139 colloid_sampling = ptread_i(config,
'colloid_sampling', loc=params_group)
140 if (modulo(n_md_steps, colloid_sampling) /= 0)
then 141 error stop
'colloid_sampling must divide N_MD with no remainder' 143 dt = tau / n_md_steps
144 n_loop = ptread_i(config,
'N_loop', loc=params_group)
145 equilibration_loops = ptread_i(config,
'equilibration_loops', loc=params_group)
147 sigma(1,:) = ptread_dvec(config,
'sigma', n_colloid_species, loc=params_group)
150 epsilon(1,:) = ptread_dvec(config,
'epsilon', n_colloid_species, loc=params_group)
152 sigma_cut = sigma*2**(1.d0/6.d0)
153 max_cut = maxval(sigma_cut)
155 call solvent_colloid_lj% init(epsilon, sigma, sigma_cut)
157 call colloid_lj%init(&
158 reshape([2*sigma(1,1), sigma(1,2)+sigma(1,2), sigma(1,2)+sigma(1,2), 2*sigma(1,2)], [2, 2]),&
159 reshape([2*epsilon(1,1), epsilon(1,1)+epsilon(1,2), epsilon(1,1)+epsilon(1,2), 2*epsilon(1,2)], [2, 2]),&
160 reshape([2*sigma_cut(1,1), sigma_cut(1,1)+sigma_cut(1,2), sigma(1,1)+sigma_cut(1,2), 2*sigma_cut(1,2)], [2, 2]))
166 do_zwall = ptread_l(config,
'do_zwall', loc=params_group)
167 fluid_wall =
'PERIODIC' 169 wall_sigma(3,:) = ptread_d(config,
'wall_sigma', loc=params_group)
170 wall_shift(3) = ptread_d(config,
'wall_shift', loc=params_group)
171 wall_epsilon = ptread_d(config,
'wall_epsilon', loc=params_group)
172 call walls_colloid_lj% init(wall_epsilon, &
173 wall_sigma, 3.d0**(1.d0/6.d0)*wall_sigma, wall_shift)
174 fluid_wall = ptread_s(config,
'fluid_wall', loc=params_group)
177 initial_condition = ptread_s(config,
'initial_condition', loc=params_group)
179 mass(1) = rho * sigma(1,1)**3 * 4 * 3.14159265/3
180 mass(2) = rho * sigma(1,2)**3 * 4 * 3.14159265/3
182 call solvent% init(n, n_species, system_name=
'solvent')
184 call colloids% init(2, n_colloid_species, mass, system_name=
'colloids')
186 call thermo_data%init(hfile, n_buffer=50, step=n_md_steps, time=n_md_steps*dt)
188 call h5gclose_f(params_group, error)
191 call axial_cf%init(block_length, n_loop, n_loop*n_md_steps)
193 colloids% species(1) = 1
194 colloids% species(2) = 2
198 dimer_io%force_info%store = .false.
199 dimer_io%id_info%store = .false.
200 dimer_io%position_info%store = .true.
201 dimer_io%position_info%mode = ior(h5md_linear,h5md_store_time)
202 dimer_io%position_info%step = colloid_sampling
203 dimer_io%position_info%time = colloid_sampling*dt
204 dimer_io%image_info%store = .true.
205 dimer_io%image_info%mode = ior(h5md_linear,h5md_store_time)
206 dimer_io%image_info%step = colloid_sampling
207 dimer_io%image_info%time = colloid_sampling*dt
208 dimer_io%velocity_info%store = .true.
209 dimer_io%velocity_info%mode = ior(h5md_linear,h5md_store_time)
210 dimer_io%velocity_info%step = colloid_sampling
211 dimer_io%velocity_info%time = colloid_sampling*dt
212 dimer_io%species_info%store = .true.
213 dimer_io%species_info%mode = h5md_fixed
214 call dimer_io%init(hfile,
'dimer', colloids)
216 do k = 1, solvent%Nmax
217 solvent% vel(1,k) = threefry_normal(state(1))*sqrt(t)
218 solvent% vel(2,k) = threefry_normal(state(1))*sqrt(t)
219 solvent% vel(3,k) = threefry_normal(state(1))*sqrt(t)
221 solvent% vel = solvent% vel - spread(sum(solvent% vel, dim=2)/solvent% Nmax, 2, solvent% Nmax)
225 call solvent_cells%init(l, 1.d0)
227 solvent_cells%bc = periodic_bc
228 if (trim(fluid_wall) ==
'PERIODIC')
then 229 solvent_cells%bc(3) = periodic_bc
230 else if (trim(fluid_wall) ==
'SPECULAR')
then 231 solvent_cells%bc(3) = specular_bc
232 else if (trim(fluid_wall) ==
'BOUNCE_BACK')
then 233 solvent_cells%bc(3) = bounce_back_bc
235 error stop
'unknown value for parameter fluid_wall' 238 if (initial_condition ==
'CENTER')
then 239 colloids% pos(:,1) = solvent_cells% edges/2.0
240 colloids% pos(:,2) = solvent_cells% edges/2.0
241 colloids% pos(1,2) = colloids% pos(1,2) + d
242 else if (initial_condition ==
'PLANAR_RANDOM')
then 243 theta = threefry_double(state(1))*2*pi
244 colloids%pos(3,:) = solvent_cells%edges(3)/2
245 colloids% pos(1,1) = solvent_cells%edges(1)/2.0 + d*cos(theta)/2
246 colloids% pos(2,1) = solvent_cells%edges(2)/2.0 + d*sin(theta)/2
247 colloids% pos(1,2) = solvent_cells%edges(1)/2.0 - d*cos(theta)/2
248 colloids% pos(2,2) = solvent_cells%edges(2)/2.0 - d*sin(theta)/2
250 error stop
'Unknown initial condition IC' 253 call h5gcreate_f(dimer_io%group,
'box', box_group, error)
254 call h5md_write_attribute(box_group,
'dimension', 3)
255 call dummy_element%create_fixed(box_group,
'edges', solvent_cells%edges)
256 call h5gclose_f(box_group, error)
258 call solvent% random_placement(solvent_cells% edges, colloids, solvent_colloid_lj, state(1))
260 call solvent% sort(solvent_cells)
262 call neigh% init(colloids% Nmax, int(300*maxval(sigma)**3))
268 call neigh% make_stencil(solvent_cells, max_cut+skin)
270 call neigh% update_list(colloids, solvent, max_cut+skin, solvent_cells, solvent_colloid_lj)
272 e1 = compute_force(colloids, solvent, neigh, solvent_cells% edges, solvent_colloid_lj)
273 e2 = compute_force_n2(colloids, solvent_cells% edges, colloid_lj)
274 if (do_harmonic)
then 281 e_wall = lj93_zwall(colloids, solvent_cells% edges, walls_colloid_lj)
285 solvent% force_old = solvent% force
286 colloids% force_old = colloids% force
288 call h5fflush_f(hfile%id, h5f_scope_global_f, error)
289 write(*,*)
'Running for', equilibration_loops,
'+', n_loop,
'loops' 290 write(*,*)
'mass', mass
293 do i = 0, n_loop+equilibration_loops
294 if (i==equilibration_loops) sampling = .true.
295 if (modulo(i,20) == 0)
write(*,
'(i05)',advance=
'no') i
296 md_loop:
do j = 1, n_md_steps
297 if ((do_zwall) .and. (solvent_cells%bc(3)/=periodic_bc))
then 298 call cell_md_pos_zwall(solvent_cells, solvent, dt, md_flag=.true.)
300 call cell_md_pos(solvent_cells, solvent, dt, md_flag=.true.)
306 colloids% pos_rattle = colloids% pos
307 do k=1, colloids% Nmax
308 colloids% pos(:,k) = colloids% pos(:,k) &
309 + dt * colloids% vel(:,k) + &
310 dt**2 * colloids% force(:,k) / (2 * colloids% mass(k))
314 call rattle_dimer_pos(colloids, d, dt, solvent_cells% edges)
318 so_max = cell_maximum_displacement(solvent_cells, solvent, delta_t=dt*(n_md_steps*i+j - loop_i_last_sort))
319 co_max = colloids% maximum_displacement()
321 if ( (co_max >= skin*0.1d0) .or. (so_max >= skin*0.89d0) )
then 324 if ((do_zwall) .and. (solvent_cells%bc(2)/=periodic_bc))
then 325 call cell_md_pos_zwall(solvent_cells, solvent, &
326 (n_md_steps*i+j - loop_i_last_sort)*dt, md_flag=.false.)
328 call cell_md_pos(solvent_cells, solvent, &
329 (n_md_steps*i+j - loop_i_last_sort)*dt, md_flag=.false.)
331 call cell_md_vel(solvent_cells, solvent, &
332 (n_md_steps*i+j - loop_i_last_sort)*dt, md_flag=.false.)
334 call apply_pbc(solvent, solvent_cells% edges)
335 call apply_pbc(colloids, solvent_cells% edges)
337 call solvent% sort(solvent_cells)
338 loop_i_last_sort = n_md_steps*i + j
339 call neigh% update_list(colloids, solvent, max_cut + skin, solvent_cells, solvent_colloid_lj)
342 do k = 1, solvent%Nmax
343 solvent% pos_old(:,k) = solvent% pos(:,k)
347 colloids% pos_old = colloids% pos
348 n_extra_sorting = n_extra_sorting + 1
353 call switch(solvent% force, solvent% force_old)
354 call switch(colloids% force, colloids% force_old)
357 do k = 1, solvent%Nmax
358 solvent% force(:,k) = 0
362 e1 = compute_force(colloids, solvent, neigh, solvent_cells% edges, solvent_colloid_lj)
363 e2 = compute_force_n2(colloids, solvent_cells% edges, colloid_lj)
365 if (do_zwall) e_wall = lj93_zwall(colloids, solvent_cells% edges, walls_colloid_lj)
367 call cell_md_vel(solvent_cells, solvent, dt, md_flag=.true.)
370 do k=1, colloids% Nmax
371 colloids% vel(:,k) = colloids% vel(:,k) + &
372 dt * ( colloids% force(:,k) + colloids% force_old(:,k) ) / (2 * colloids% mass(k))
376 call rattle_dimer_vel(colloids, d, dt, solvent_cells% edges)
380 v_com = sum(colloids%vel, dim=2)/2
381 unit_r = rel_pos(colloids%pos(:,1), colloids%pos(:,2), solvent_cells%edges)
382 unit_r = unit_r / norm2(unit_r)
383 call axial_cf%add_fast((i-equilibration_loops)*n_md_steps+j-1, v_com, unit_r)
386 if ((sampling) .and. (modulo(j, colloid_sampling)==0))
then 387 call dimer_io%position%append(colloids%pos)
388 call dimer_io%velocity%append(colloids%vel)
389 call dimer_io%image%append(colloids%image)
397 temperature = compute_temperature(solvent, solvent_cells)
398 kin_e = (colloids% mass(1)*sum(colloids% vel(:,1)**2) + &
399 colloids% mass(2)*sum(colloids% vel(:,2)**2))/2 + &
400 sum(solvent% vel**2)/2
401 v_com = (sum(solvent% vel, dim=2) + &
402 mass(1)*colloids%vel(:,1) + mass(2)*colloids%vel(:,2)) / &
403 (solvent%Nmax + mass(1) + mass(2))
405 call thermo_data%append(hfile, temperature, e1+e2+e3+e_wall, kin_e, e1+e2+e3+kin_e+e_wall, v_com)
407 com_pos = ( colloids%pos(:,1)+colloids%image(:,1)*solvent_cells%edges + &
408 colloids%pos(:,2)+colloids%image(:,2)*solvent_cells%edges)/2
409 call axial_cf%add(i-equilibration_loops, com_pos, unit_r)
413 call solvent_cells%random_shift(state(1))
416 call cell_md_pos(solvent_cells, solvent, ((i+1)*n_md_steps - loop_i_last_sort)*dt, md_flag=.false.)
417 call cell_md_vel(solvent_cells, solvent, ((i+1)*n_md_steps - loop_i_last_sort)*dt, md_flag=.false.)
419 call apply_pbc(solvent, solvent_cells% edges)
420 call apply_pbc(colloids, solvent_cells% edges)
421 call solvent% sort(solvent_cells)
422 loop_i_last_sort = n_md_steps*(i+1)
423 call neigh% update_list(colloids, solvent, max_cut+skin, solvent_cells, solvent_colloid_lj)
426 do k = 1, solvent%Nmax
427 solvent% pos_old(:,k) = solvent% pos(:,k)
429 colloids% pos_old = colloids% pos
432 call simple_mpcd_step(solvent, solvent_cells, state)
439 write(*,*)
'n extra sorting', n_extra_sorting
443 call h5gcreate_f(hfile%id,
'block_correlators', correlator_group, error)
444 call axial_cf%write(correlator_group, n_md_steps, n_md_steps*dt, 1, dt)
445 call h5gclose_f(correlator_group, error)
448 call timer_list%append(solvent%time_stream)
449 call timer_list%append(solvent%time_step)
450 call timer_list%append(solvent%time_count)
451 call timer_list%append(solvent%time_sort)
452 call timer_list%append(solvent%time_ct)
453 call timer_list%append(solvent%time_md_pos)
454 call timer_list%append(solvent%time_md_vel)
455 call timer_list%append(solvent%time_max_disp)
456 call timer_list%append(colloids%time_self_force)
457 call timer_list%append(neigh%time_update)
458 call timer_list%append(neigh%time_force)
459 call timer_list%append(colloids%time_max_disp)
461 call h5gcreate_f(hfile%id,
'timers', timers_group, error)
462 call timer_list%write(timers_group, total_time)
463 call h5md_write_dataset(timers_group,
'total', total_time)
464 call h5md_write_dataset(timers_group, main%name, main%total)
465 call h5gclose_f(timers_group, error)
467 call dimer_io%close()
469 call h5close_f(error)
475 double precision :: local_max_v
479 do i = 1, solvent_cells%N
481 do j = solvent_cells%cell_start(i), solvent_cells%cell_start(i) + solvent_cells%cell_count(i) - 1
482 local_max_v = max(local_max_v, norm2(solvent%vel(:,j)))
485 solvent_cells%max_v = local_max_v
490 double precision :: e
492 double precision :: f(3), x12(3), dist
494 x12 = rel_pos(colloids%pos(:,1), colloids%pos(:,2), solvent_cells%edges)
497 f = harmonic_k * (dist - d) * x12 / dist
498 colloids%force(:,1) = colloids%force(:,1) - f
499 colloids%force(:,2) = colloids%force(:,2) + f
501 e = harmonic_k * (dist - d)**2 / 2
program single_dimer
Simulate a single dimer colloid.
double precision function compute_harmonic()
subroutine compute_cell_wise_max_v