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
47 double precision :: sigma, sigma_cut, epsilon
50 double precision :: mass
51 double precision :: so_max, co_max
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
60 logical :: do_hydro, do_thermostat
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
70 integer(HID_T) :: fields_group
71 type(histogram_t) :: radial_hist
72 type(h5md_element_t) :: radial_hist_el
74 double precision :: skin
75 double precision :: rsq
78 double precision :: total_time
79 type(timer_list_t) :: timer_list
80 integer(HID_T) :: timers_group
82 integer :: i, L(3), N, N_colloids
86 args = get_input_args()
87 call ptparse(config, args%input_file, 11)
89 n_threads = omp_get_max_threads()
90 allocate(state(n_threads))
91 call threefry_rng_init(state, args%seed)
93 call timer_list%init(11)
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)
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)
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)
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)
118 call thermo_data%init(hfile, n_buffer=50, step=n_md_steps, time=n_md_steps*dt)
120 do_hydro = ptread_l(config,
'do_hydro', loc=params_group)
121 do_thermostat = ptread_l(config,
'do_thermostat', loc=params_group)
123 mass = rho * sigma**3 * 4 * 3.141/3
124 call colloids%init(n_colloids, 1, [mass])
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)
147 n = rho*l(1)*l(2)*l(3) - int(rho*4*3.142/3 * sigma**3*colloids%Nmax)
149 write(*,*) n,
'solvent particles' 151 if (n <= 0) error stop
'Not enough volume available for solvent' 153 call solvent_colloid_lj% init( reshape( [ epsilon ], [1, 1] ), &
154 reshape( [ sigma ], [1, 1] ), reshape( [ sigma_cut ], [1, 1] ) )
156 epsilon = ptread_d(config,
'epsilon_colloids', loc=params_group)
159 call h5gclose_f(params_group, error)
162 call colloid_lj% init( reshape( [ epsilon ], [1, 1] ), &
163 reshape( [ 2*sigma ], [1, 1] ), reshape( [ 2*sigma_cut ], [1, 1] ) )
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)
171 solvent% vel = solvent% vel - spread(sum(solvent% vel, dim=2)/solvent% Nmax, 2, solvent% Nmax)
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)
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)
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)
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 202 end do check_distance
204 if (.not. tooclose) i=i+1
205 end do place_colloids
207 call solvent% random_placement(solvent_cells% edges, colloids, solvent_colloid_lj, state(1))
209 call solvent% sort(solvent_cells)
211 sigma_cut = sigma*2.d0**(1.d0/6.d0)
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)
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
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)
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()
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.)
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
252 call switch(solvent% force, solvent% force_old)
253 call switch(colloids% force, colloids% force_old)
256 e1 = compute_force(colloids, solvent, neigh, solvent_cells% edges, solvent_colloid_lj)
257 e2 = compute_force_n2(colloids, solvent_cells% edges, colloid_lj)
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)
262 end do md_loop_thermo
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.)
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
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)
285 write(*,*)
'Running for', n_loop,
'loops' 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)
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()
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.)
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
310 call switch(solvent% force, solvent% force_old)
311 call switch(colloids% force, colloids% force_old)
314 e1 = compute_force(colloids, solvent, neigh, solvent_cells% edges, solvent_colloid_lj)
315 e2 = compute_force_n2(colloids, solvent_cells% edges, colloid_lj)
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)
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.)
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
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)
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)
344 temperature = compute_temperature(solvent, solvent_cells)
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)
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
356 v_com = v_com / (solvent%Nmax + total_mass)
358 call thermo_data%append(hfile, temperature, e1+e2, kin_e, e1+e2+kin_e, v_com)
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)
368 call thermo_data%append(hfile, temperature, e1+e2, kin_e, e1+e2+kin_e, &
369 v_com, add=.false., force=.true.)
371 write(*,*)
'n extra sorting', n_extra_sorting
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)
386 call timer_list%write(timers_group, total_time)
388 call h5md_write_dataset(timers_group,
'total', total_time)
390 call h5gclose_f(timers_group, error)
392 call radial_hist_el%close()
393 call colloids_io%close()
395 call h5close_f(error)
program n_colloids_pbc
Simulate an ensemble of spherical colloids.