42 double precision :: mass
43 double precision :: pos(3)
44 double precision,
allocatable :: pos_body(:,:)
45 double precision :: vel(3)
46 double precision :: force(3)
47 double precision :: q(4)
48 double precision :: l(3)
49 double precision :: torque(3)
50 double precision :: i_body(3)
51 double precision :: omega_body(3)
61 subroutine md_pos(particles, dt)
63 double precision,
intent(in) :: dt
65 double precision :: dt_sq
70 call particles%time_md_pos%tic()
72 do k = 1, particles% Nmax
73 particles% pos(:,k) = particles% pos(:,k) + dt * particles% vel(:,k) + dt_sq * particles% force(:,k)
75 call particles%time_md_pos%tac()
79 subroutine cell_md_pos(cells, particles, dt, md_flag)
82 double precision,
intent(in) :: dt
83 logical,
intent(in) :: md_flag
85 double precision :: dt_sq
90 call particles%time_md_pos%tic()
93 if (cells%is_md(i) .eqv. md_flag)
then 94 do j = cells%cell_start(i), cells%cell_start(i) + cells%cell_count(i) - 1
95 particles% pos(:,j) = particles% pos(:,j) + dt * particles% vel(:,j) + dt_sq * particles% force(:,j)
100 call particles%time_md_pos%tac()
107 double precision,
intent(in) :: dt
108 logical,
intent(in) :: md_flag
110 double precision :: dt_sq
111 double precision :: Ly, x(3), v(3), overtime
119 call particles%time_md_pos%tic()
122 if (cells%is_md(i) .eqv. md_flag)
then 123 do j = cells%cell_start(i), cells%cell_start(i) + cells%cell_count(i) - 1
124 v = particles%vel(:,j)
125 x = particles%pos(:,j) + dt * v + dt_sq * particles%force(:,j)
130 else if (x(2)>ly)
then 132 overtime = (x(2)-ly)/v(2)
140 x(2) = x(2)+2*overtime*v(2)
142 particles%vel(:,j) = v
144 particles% pos(:,j) = x
149 call particles%time_md_pos%tac()
156 double precision,
intent(in) :: dt
157 logical,
intent(in) :: md_flag
159 double precision :: dt_sq
160 double precision :: Lz, x(3), v(3), overtime
168 call particles%time_md_pos%tic()
171 if (cells%is_md(i) .eqv. md_flag)
then 172 do j = cells%cell_start(i), cells%cell_start(i) + cells%cell_count(i) - 1
173 v = particles%vel(:,j)
174 x = particles%pos(:,j) + dt * v + dt_sq * particles%force(:,j)
179 else if (x(3)>lz)
then 181 overtime = (x(3)-lz)/v(3)
189 x(3) = x(3)+2*overtime*v(3)
191 particles%vel(:,j) = v
193 particles% pos(:,j) = x
198 call particles%time_md_pos%tac()
204 double precision,
intent(in) :: edges(3)
206 integer :: k, jump(3)
208 call particles%time_apply_pbc%tic()
210 do k = 1, particles% Nmax
211 jump = floor(particles% pos(:,k) / edges)
212 particles% image(:,k) = particles% image(:,k) + jump
213 particles% pos(:,k) = particles% pos(:,k) - jump*edges
215 call particles%time_apply_pbc%tac()
219 subroutine md_vel(particles, dt)
221 double precision,
intent(in) :: dt
225 call particles%time_md_vel%tic()
227 do k = 1, particles% Nmax
228 if (.not. btest(particles%flags(k),
wall_bit))
then 229 particles% vel(:,k) = particles% vel(:,k) + &
230 dt * ( particles% force(:,k) + particles% force_old(:,k) ) / 2
232 particles%flags(k) = ibclr(particles%flags(k),
wall_bit)
235 call particles%time_md_vel%tac()
239 subroutine cell_md_vel(cells, particles, dt, md_flag)
242 double precision,
intent(in) :: dt
243 logical,
intent(in) :: md_flag
247 call particles%time_md_vel%tic()
250 if (cells%is_md(i) .eqv. md_flag)
then 251 do j = cells%cell_start(i), cells%cell_start(i) + cells%cell_count(i) - 1
252 if (.not. btest(particles%flags(j),
wall_bit))
then 253 particles% vel(:,j) = particles% vel(:,j) + &
254 dt * ( particles% force(:,j) + particles% force_old(:,j) ) / 2
256 particles%flags(j) = ibclr(particles%flags(j),
wall_bit)
261 call particles%time_md_vel%tac()
267 double precision,
intent(in) :: d
268 double precision,
intent(in) :: dt
269 double precision,
intent(in) :: edges(3)
271 double precision :: g
272 double precision :: s(3)
273 double precision :: r(3)
274 double precision :: rsq, ssq, rs
275 double precision :: mass1, mass2, inv_mass
277 r =
rel_pos(p% pos_rattle(:,1),p% pos_rattle(:,2), edges)
278 s =
rel_pos(p% pos(:,1),p% pos(:,2), edges)
279 mass1 = p%mass(p%species(1))
280 mass2 = p%mass(p%species(2))
281 inv_mass = 1/mass1 + 1/mass2
283 rsq = dot_product(r,r)
284 ssq = dot_product(s,s)
285 rs = dot_product(r,s)
287 g = rs - sqrt(rs**2 - rsq*(ssq-d**2))
288 g = g / (dt * inv_mass * rsq)
290 p% pos(:,1) = p% pos(:,1) - g*dt*r/mass1
291 p% pos(:,2) = p% pos(:,2) + g*dt*r/mass2
293 p% vel(:,1) = p% vel(:,1) - g*r/mass1
294 p% vel(:,2) = p% vel(:,2) + g*r/mass2
300 double precision,
intent(in) :: d
301 double precision,
intent(in) :: dt
302 double precision,
intent(in) :: edges(3)
304 double precision :: k
305 double precision :: s(3)
306 double precision :: mass1, mass2, inv_mass
308 mass1 = p%mass(p%species(1))
309 mass2 = p%mass(p%species(2))
310 inv_mass = 1/mass1 + 1/mass2
312 s =
rel_pos(p% pos(:,1), p% pos(:,2), edges)
314 k = dot_product(p%vel(:,1)-p%vel(:,2), s) / (d**2*inv_mass)
316 p% vel(:,1) = p% vel(:,1) - k*s/mass1
317 p% vel(:,2) = p% vel(:,2) + k*s/mass2
323 integer,
intent(in) :: links(:,:)
324 double precision,
intent(in) :: distances(:)
325 double precision,
intent(in) :: dt, edges(3), precision
327 double precision :: g, d, error
328 double precision :: s(3)
329 double precision :: r(3)
330 double precision :: rsq, ssq, rs
331 double precision :: i_mass1, i_mass2, inv_mass
332 double precision,
allocatable :: i_mass(:)
333 integer,
allocatable :: im(:,:), im_r(:,:)
335 integer :: rattle_i, rattle_max, i_link, n_link
338 n_link =
size(links, dim=2)
341 allocate(i_mass(
size(p%mass)))
344 allocate(im(3,p%Nmax))
345 allocate(im_r(3,p%Nmax))
349 im(:,i1) = floor(((p%pos(:,i1)-s)/edges) + 0.5d0)
350 p%pos(:,i1) = p%pos(:,i1) - im(:,i1)*edges
353 s = p%pos_rattle(:,1)
355 im_r(:,i1) = floor(((p%pos_rattle(:,i1)-s)/edges) + 0.5d0)
356 p%pos_rattle(:,i1) = p%pos_rattle(:,i1) - im_r(:,i1)*edges
359 call p%time_rattle_pos%tic()
360 rattle_loop:
do rattle_i = 1, rattle_max
362 do i_link = 1, n_link
365 d = distances(i_link)
367 r = p%pos_rattle(:,i1)-p%pos_rattle(:,i2)
368 s = p%pos(:,i1)-p%pos(:,i2)
369 i_mass1 = i_mass(p%species(i1))
370 i_mass2 = i_mass(p%species(i2))
371 inv_mass = i_mass1 + i_mass2
373 rsq = dot_product(r,r)
374 ssq = dot_product(s,s)
375 rs = dot_product(r,s)
377 g = rs - sqrt(rs**2 - rsq*(ssq-d**2))
378 g = g / (dt * inv_mass * rsq)
380 p% pos(:,i1) = p% pos(:,i1) - g*dt*r*i_mass1
381 p% pos(:,i2) = p% pos(:,i2) + g*dt*r*i_mass2
383 p% vel(:,i1) = p% vel(:,i1) - g*r*i_mass1
384 p% vel(:,i2) = p% vel(:,i2) + g*r*i_mass2
387 do i_link = 1, n_link
390 d = distances(i_link)
391 r = p%pos(:,i1)-p%pos(:,i2)
392 g = abs(sqrt(dot_product(r,r)) - d)
393 if (g > error) error = g
395 if (error < precision)
exit rattle_loop
398 call p%time_rattle_pos%tac()
402 p%pos(:,i1) = p%pos(:,i1) + im(:,i1)*edges
406 if (rattle_i==rattle_max)
write(*,*)
'rattle_max reached in rattle_body_pos' 412 integer,
intent(in) :: links(:,:)
413 double precision,
intent(in) :: distances(:)
414 double precision,
intent(in) :: dt, edges(3), precision
416 double precision :: g, d, error
417 double precision :: s(3), k
418 double precision :: i_mass1, i_mass2, inv_mass
419 double precision,
allocatable :: i_mass(:)
420 integer,
allocatable :: im(:,:)
422 integer :: rattle_i, rattle_max, i_link, n_link
425 n_link =
size(links, dim=2)
427 allocate(i_mass(
size(p%mass)))
430 allocate(im(3,p%Nmax))
434 im(:,i1) = floor(((p%pos(:,i1)-s)/edges) + 0.5d0)
435 p%pos(:,i1) = p%pos(:,i1) - im(:,i1)*edges
438 call p%time_rattle_vel%tic()
439 rattle_loop:
do rattle_i = 1, rattle_max
441 do i_link = 1, n_link
444 d = distances(i_link)
445 i_mass1 = i_mass(p%species(i1))
446 i_mass2 = i_mass(p%species(i2))
447 inv_mass = i_mass1 + i_mass2
449 s = p%pos(:,i1)-p%pos(:,i2)
451 k = dot_product(p%vel(:,i1)-p%vel(:,i2), s) / (d**2*inv_mass)
453 p% vel(:,i1) = p% vel(:,i1) - k*s*i_mass1
454 p% vel(:,i2) = p% vel(:,i2) + k*s*i_mass2
457 do i_link = 1, n_link
460 d = distances(i_link)
461 i_mass1 = i_mass(p%species(i1))
462 i_mass2 = i_mass(p%species(i2))
463 inv_mass = i_mass1 + i_mass2
464 s = p%pos(:,i1)-p% pos(:,i2)
465 k = abs(dot_product(p%vel(:,i1)-p%vel(:,i2), s) / (d**2*inv_mass))
466 if (k>error) error = k
468 if (error < precision)
exit rattle_loop
470 call p%time_rattle_vel%tac()
473 p%pos(:,i1) = p%pos(:,i1) + im(:,i1)*edges
476 deallocate(i_mass, im)
478 if (rattle_i==rattle_max)
write(*,*)
'rattle_max reached in rattle_body_vel' 482 function lj93_zwall(particles, edges, lj_params)
result(e)
484 double precision,
intent(in) :: edges(3)
486 double precision :: e
489 double precision :: z, z_sq, f, dir
492 do i = 1, particles%Nmax
493 s = particles%species(i)
496 if (lj_params%sigma(dim, s)<0) cycle
497 z = particles%pos(dim,i)
498 if (z > edges(dim)/2)
then 499 z = edges(dim) - z - lj_params%shift(dim)
503 z = z - lj_params%shift(dim)
506 if (z_sq <= lj_params% cut_sq(dim,s))
then 507 f =
lj_force_9_3(z, z_sq, lj_params%epsilon(dim,s), lj_params%sigma(dim,s))
508 particles%force(dim,i) = particles%force(dim,i) + dir*f
509 e = e +
lj_energy_9_3(z_sq, lj_params%epsilon(dim,s), lj_params%sigma(dim,s))
518 integer,
intent(in) :: links(:,:)
519 double precision,
intent(in) :: distances(:)
520 double precision,
intent(in) :: k
521 double precision,
intent(in) :: edges(3)
522 double precision :: e
524 integer :: i, i1, i2, n_links
525 double precision :: x(3), f(3), r, r0
527 n_links =
size(distances)
529 call p%time_elastic%tic()
535 x =
rel_pos(p%pos(:,i1), p%pos(:,i2), edges)
537 e = e + k*(r-r0)**2/2
538 f = - k * (r - r0) * x / r
539 p%force(:,i1) = p%force(:,i1) + f
540 p%force(:,i2) = p%force(:,i2) - f
542 call p%time_elastic%tac()
550 integer,
intent(in) :: i_start
551 integer,
intent(in) :: i_stop
552 double precision,
intent(in) :: edges(3)
554 double precision :: mass
555 double precision :: pos(3)
558 this%i_start = i_start
564 do i = i_start, i_stop
565 mass = ps%mass(ps%species(i))
566 this%mass = this%mass + mass
567 this%pos = this%pos + mass*(ps%pos(:,i)+ps%image(:,i)*edges)
568 this%vel = this%vel + mass*ps%vel(:,i)
570 this%pos = this%pos/this%mass
571 this%vel = this%vel/this%mass
573 allocate(this%pos_body(3,i_stop-i_start+1))
576 do i = i_start, i_stop
577 mass = ps%mass(ps%species(i))
578 pos = ps%pos(:,i)+ps%image(:,i)*edges - this%pos
579 this%pos_body(:,i) = pos
580 this%I_body = this%I_body + mass*(sum(pos**2)-pos**2)
585 this%q = qnew(s=1.d0)
595 double precision :: pos(3), f(3)
600 do i = this%i_start, this%i_stop
602 this%force = this%force + f
603 pos = qrot(this%q, this%pos_body(:,i))
604 this%torque = this%torque +
cross(pos, f)
616 double precision,
intent(in) :: dt
617 double precision,
intent(in) :: treshold
618 double precision,
intent(in) :: edges(3)
620 double precision :: L(3), L_body(3), L_body_dot(3), omega_body(3), q(4), q_old(4), q_dot(4), torque_body(3)
621 double precision :: I_inv(3)
622 double precision :: old_pos(3), delta_pos(3)
626 i_inv = 1/this%I_body
632 l_body = qrot(qconj(q), l)
633 torque_body = qrot(qconj(q), this%torque)
634 omega_body = l_body*i_inv
636 l_body_dot = torque_body -
cross(omega_body, l_body)
639 l_body = l_body + dt*l_body_dot/2
640 omega_body = l_body*i_inv
641 q_dot = qmul(q, qnew(v=omega_body))/2
644 l = this%L + this%torque*dt/2
649 iterative_q:
do while (.true.)
650 l_body = qrot(qconj(q), l)
651 omega_body = i_inv*l_body
652 q_dot = qmul(q, qnew(v=omega_body))/2
653 q = this%q + q_dot*dt/2
655 if (qnorm(q-q_old)<treshold)
exit iterative_q
659 this%q = qnormalize(this%q + dt*q_dot)
661 this%pos = this%pos + this%vel*dt + this%force*dt**2/(2*this%mass)
663 do i = this%i_start, this%i_stop
664 old_pos = ps%pos(:,i)
665 ps%pos(:,i) = this%pos + qrot(this%q, this%pos_body(:,i))
666 delta_pos = ps%pos(:,i) - old_pos + edges/2
667 ps%pos(:,i) = ps%pos(:,i) - floor(delta_pos / edges)*edges
670 this%L = this%L + this%torque*dt/2
671 this%vel = this%vel + this%force*dt/(2*this%mass)
682 double precision,
intent(in) :: dt
684 double precision :: L_body(3), omega(3)
685 double precision :: pos(3)
688 this%L = this%L + this%torque*dt/2
689 l_body = qrot(qconj(this%q), this%L)
690 this%omega_body = l_body/this%I_body
691 omega = qrot(this%q, this%omega_body)
693 this%vel = this%vel + this%force*dt/(2*this%mass)
695 do i = this%i_start, this%i_stop
696 pos = qrot(this%q, this%pos_body(:,i))
697 ps%vel(:,i) = this%vel +
cross(omega, pos)
subroutine rigid_body_compute_force_torque(this, ps)
subroutine, public md_vel(particles, dt)
subroutine, public cell_md_pos(cells, particles, dt, md_flag)
subroutine rigid_body_vv2(this, ps, dt)
Perform second velocity-Verlet step for quaternion dynamics.
subroutine, public cell_md_vel(cells, particles, dt, md_flag)
subroutine, public rattle_body_pos(p, links, distances, dt, edges, precision)
subroutine rigid_body_init(this, ps, i_start, i_stop, edges)
subroutine, public rattle_dimer_vel(p, d, dt, edges)
double precision function, public lj93_zwall(particles, edges, lj_params)
pure double precision function, public lj_energy_9_3(z_sq, epsilon, sigma)
pure double precision function, dimension(3), public cross(x1, x2)
integer, parameter, public specular_bc
subroutine, public rattle_body_vel(p, links, distances, dt, edges, precision)
subroutine, public cell_md_pos_ywall(cells, particles, dt, md_flag)
subroutine, public apply_pbc(particles, edges)
subroutine, public rattle_dimer_pos(p, d, dt, edges)
integer, parameter, public wall_bit
double precision function, public elastic_network(p, links, distances, k, edges)
subroutine, public md_pos(particles, dt)
Routines to perform Molecular Dynamics integration.
subroutine rigid_body_vv1(this, ps, dt, treshold, edges)
Perform first velocity-Verlet step for quaternion dynamics.
pure double precision function, dimension(3), public rel_pos(x, y, L)
Return x-y distance with minimum image convention.
pure double precision function, public lj_force_9_3(z, z_sq, epsilon, sigma)
Container for rigid body colloid.
subroutine, public cell_md_pos_zwall(cells, particles, dt, md_flag)
Lennard-Jones potential definition.
integer, parameter, public bounce_back_bc