39#include "../base/base_uses.f90"
45 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'tmc_moves'
50 INTEGER,
PARAMETER :: not_selected = 0
51 INTEGER,
PARAMETER :: proton_donor = -1
52 INTEGER,
PARAMETER :: proton_acceptor = 1
68 SUBROUTINE change_pos(tmc_params, move_types, rng_stream, elem, mv_conf, &
69 new_subbox, move_rejected)
75 LOGICAL :: new_subbox, move_rejected
77 INTEGER :: act_nr_elem_mv, counter, d, i, ind, &
78 ind_e, m, nr_molec, nr_sub_box_elem
79 INTEGER,
DIMENSION(:),
POINTER :: mol_in_sb
81 REAL(kind=
dp),
DIMENSION(:),
POINTER :: direction, elem_center
83 NULLIFY (direction, elem_center, mol_in_sb)
85 cpassert(
ASSOCIATED(tmc_params))
86 cpassert(
ASSOCIATED(move_types))
87 cpassert(
ASSOCIATED(elem))
89 move_rejected = .false.
91 CALL rng_stream%set(bg=elem%rng_seed(:, :, 1), &
92 cg=elem%rng_seed(:, :, 2), ig=elem%rng_seed(:, :, 3))
95 IF (all(tmc_params%sub_box_size > 0.0_dp))
THEN
97 rng_stream=rng_stream, elem=elem, &
98 nr_of_sub_box_elements=nr_sub_box_elem)
105 cpassert(any(elem%elem_stat(:) ==
status_ok))
106 IF (tmc_params%nr_elem_mv == 0)
THEN
110 act_nr_elem_mv = tmc_params%nr_elem_mv
117 SELECT CASE (elem%move_type)
120 cpabort(
"gaussian adaptation is not imlemented yet.")
127 IF (act_nr_elem_mv == 0)
THEN
128 act_nr_elem_mv =
SIZE(elem%pos)/tmc_params%dim_per_elem
130 ALLOCATE (elem_center(tmc_params%dim_per_elem))
132 move_elements_loop:
DO
134 IF (tmc_params%nr_elem_mv == 0)
THEN
135 ind = (i - 1)*(tmc_params%dim_per_elem) + 1
137 rnd = rng_stream%next()
138 ind = tmc_params%dim_per_elem* &
139 int(rnd*(
SIZE(elem%pos)/tmc_params%dim_per_elem)) + 1
142 IF (elem%elem_stat(ind) ==
status_ok)
THEN
144 DO d = 0, tmc_params%dim_per_elem - 1
145 rnd = rng_stream%next()
146 elem%pos(ind + d) = elem%pos(ind + d) + (rnd - 0.5)*2.0* &
150 elem_center = elem%pos(ind:ind + tmc_params%dim_per_elem - 1)
151 IF (.NOT. check_pos_in_subbox(pos=elem_center, &
152 subbox_center=elem%subbox_center, &
153 box_scale=elem%box_scale, tmc_params=tmc_params) &
155 move_rejected = .true.
156 EXIT move_elements_loop
160 IF (tmc_params%nr_elem_mv > 0) i = i - 1
163 IF (i > act_nr_elem_mv)
EXIT move_elements_loop
164 END DO move_elements_loop
165 DEALLOCATE (elem_center)
169 nr_molec = maxval(elem%mol(:))
171 IF (act_nr_elem_mv == 0)
THEN
172 act_nr_elem_mv = nr_molec
174 ALLOCATE (mol_in_sb(nr_molec))
175 ALLOCATE (elem_center(tmc_params%dim_per_elem))
179 CALL get_mol_indeces(tmc_params=tmc_params, mol_arr=elem%mol, mol=m, &
180 start_ind=ind, end_ind=ind_e)
183 IF (check_pos_in_subbox(pos=elem_center, &
184 subbox_center=elem%subbox_center, &
185 box_scale=elem%box_scale, tmc_params=tmc_params) &
192 ALLOCATE (direction(tmc_params%dim_per_elem))
194 move_molecule_loop:
DO
196 IF (tmc_params%nr_elem_mv == 0)
THEN
199 rnd = rng_stream%next()
200 m = int(rnd*nr_molec) + 1
202 CALL get_mol_indeces(tmc_params=tmc_params, mol_arr=elem%mol, mol=m, &
203 start_ind=ind, end_ind=ind_e)
205 IF (ind == ind_e) cycle move_molecule_loop
211 DO d = 1, tmc_params%dim_per_elem
212 rnd = rng_stream%next()
213 direction(d) = (rnd - 0.5)*2.0_dp*move_types%mv_size( &
217 elem_center(:) = elem_center(:) + direction(:)
218 IF (check_pos_in_subbox(pos=elem_center, &
219 subbox_center=elem%subbox_center, &
220 box_scale=elem%box_scale, tmc_params=tmc_params) &
223 atom_in_mol_loop:
DO i = ind, ind_e + tmc_params%dim_per_elem - 1, tmc_params%dim_per_elem
224 dim_loop:
DO d = 0, tmc_params%dim_per_elem - 1
225 elem%pos(i + d) = elem%pos(i + d) + direction(d + 1)
227 END DO atom_in_mol_loop
230 move_rejected = .true.
231 EXIT move_molecule_loop
235 IF (tmc_params%nr_elem_mv > 0) counter = counter - 1
237 counter = counter + 1
238 IF (counter > act_nr_elem_mv)
EXIT move_molecule_loop
239 END DO move_molecule_loop
240 DEALLOCATE (direction)
242 DEALLOCATE (elem_center)
243 DEALLOCATE (mol_in_sb)
247 nr_molec = maxval(elem%mol(:))
248 IF (act_nr_elem_mv == 0)
THEN
249 act_nr_elem_mv = nr_molec
251 ALLOCATE (mol_in_sb(nr_molec))
252 ALLOCATE (elem_center(tmc_params%dim_per_elem))
256 CALL get_mol_indeces(tmc_params=tmc_params, mol_arr=elem%mol, mol=m, &
257 start_ind=ind, end_ind=ind_e)
260 IF (check_pos_in_subbox(pos=elem_center, &
261 subbox_center=elem%subbox_center, &
262 box_scale=elem%box_scale, tmc_params=tmc_params) &
270 rot_molecule_loop:
DO
272 IF (tmc_params%nr_elem_mv == 0)
THEN
275 rnd = rng_stream%next()
276 m = int(rnd*nr_molec) + 1
278 CALL get_mol_indeces(tmc_params=tmc_params, mol_arr=elem%mol, mol=m, &
279 start_ind=ind, end_ind=ind_e)
281 IF (ind == ind_e) cycle rot_molecule_loop
285 CALL do_mol_rot(pos=elem%pos, ind_start=ind, ind_end=ind_e, &
286 max_angle=move_types%mv_size( &
288 move_types=move_types, rng_stream=rng_stream, &
289 dim_per_elem=tmc_params%dim_per_elem)
291 DO i = ind, ind_e + tmc_params%dim_per_elem - 1, tmc_params%dim_per_elem
292 elem_center = elem%pos(i:i + tmc_params%dim_per_elem - 1)
293 IF (check_pos_in_subbox(pos=elem_center, &
294 subbox_center=elem%subbox_center, &
295 box_scale=elem%box_scale, tmc_params=tmc_params) &
297 elem%elem_stat(i:i + tmc_params%dim_per_elem - 1) =
status_ok
299 elem%elem_stat(i:i + tmc_params%dim_per_elem - 1) =
status_frozen
304 IF (tmc_params%nr_elem_mv > 0) counter = counter - 1
306 counter = counter + 1
307 IF (counter > act_nr_elem_mv)
EXIT rot_molecule_loop
308 END DO rot_molecule_loop
310 DEALLOCATE (elem_center)
311 DEALLOCATE (mol_in_sb)
316 cpassert(
ASSOCIATED(tmc_params%atoms))
317 change_all_velocities_loop:
DO i = 1,
SIZE(elem%pos)
320 CALL vel_change(vel=elem%vel(i), &
321 atom_kind=tmc_params%atoms(int(i/real(tmc_params%dim_per_elem, kind=
dp)) + 1), &
323 temp=tmc_params%Temp(mv_conf), &
324 rnd_sign_change=.true., &
325 rng_stream=rng_stream)
327 END DO change_all_velocities_loop
333 CALL search_and_do_proton_displace_loop(elem=elem, &
334 short_loop=move_rejected, rng_stream=rng_stream, &
335 tmc_params=tmc_params)
340 CALL change_volume(conf=elem, t_ind=mv_conf, move_types=move_types, &
341 rng_stream=rng_stream, tmc_params=tmc_params, &
342 mv_cen_of_mass=tmc_params%mv_cen_of_mass)
347 CALL swap_atoms(conf=elem, move_types=move_types, rng_stream=rng_stream, &
348 tmc_params=tmc_params)
351 CALL cp_abort(__location__, &
352 "unknown move type "// &
356 CALL rng_stream%get(bg=elem%rng_seed(:, :, 1), &
357 cg=elem%rng_seed(:, :, 2), ig=elem%rng_seed(:, :, 3))
370 SUBROUTINE get_mol_indeces(tmc_params, mol_arr, mol, start_ind, end_ind)
372 INTEGER,
DIMENSION(:),
INTENT(IN),
POINTER :: mol_arr
373 INTEGER,
INTENT(IN) :: mol
374 INTEGER,
INTENT(OUT) :: start_ind, end_ind
381 cpassert(
ASSOCIATED(mol_arr))
382 cpassert(mol <= maxval(mol_arr(:)))
384 loop_start:
DO i = 1,
SIZE(mol_arr)
385 IF (mol_arr(i) == mol)
THEN
391 loop_end:
DO i =
SIZE(mol_arr), i, -1
392 IF (mol_arr(i) == mol)
THEN
398 cpassert(all(mol_arr(start_ind:end_ind) == mol))
399 cpassert(start_ind > 0)
400 cpassert(end_ind > 0)
402 start_ind = (start_ind - 1)*tmc_params%dim_per_elem + 1
403 end_ind = (end_ind - 1)*tmc_params%dim_per_elem + 1
404 END SUBROUTINE get_mol_indeces
416 FUNCTION check_pos_in_subbox(pos, subbox_center, box_scale, tmc_params) &
418 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pos, subbox_center, box_scale
422 CHARACTER(LEN=*),
PARAMETER :: routinen =
'check_pos_in_subbox'
426 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: pos_tmp
428 cpassert(
ASSOCIATED(pos))
429 cpassert(
ASSOCIATED(subbox_center))
430 cpassert(
ASSOCIATED(box_scale))
432 flag = .NOT. ((tmc_params%pressure > 0.0_dp) .AND. (any(box_scale == 0.0_dp)))
434 cpassert(
SIZE(pos) == 3)
435 cpassert(
SIZE(pos) ==
SIZE(subbox_center))
438 CALL timeset(routinen, handle)
440 ALLOCATE (pos_tmp(
SIZE(pos)))
444 IF (.NOT. any(tmc_params%sub_box_size(:) <= 0.1_dp))
THEN
445 pos_tmp(:) = pos(:) - subbox_center(:)
449 IF (any(pos_tmp(:) >= tmc_params%sub_box_size(:)/2.0) .OR. &
450 any(pos_tmp(:) <= -tmc_params%sub_box_size(:)/2.0))
THEN
456 CALL timestop(handle)
457 END FUNCTION check_pos_in_subbox
470 nr_of_sub_box_elements)
474 INTEGER,
INTENT(OUT) :: nr_of_sub_box_elements
476 CHARACTER(LEN=*),
PARAMETER :: routinen =
'elements_in_new_subbox'
480 REAL(kind=
dp),
DIMENSION(3) :: box_size
481 REAL(kind=
dp),
DIMENSION(:),
POINTER :: atom_tmp, center_of_sub_box
483 NULLIFY (center_of_sub_box, atom_tmp)
485 cpassert(
ASSOCIATED(tmc_params))
486 cpassert(
ASSOCIATED(elem))
489 CALL timeset(routinen, handle)
491 IF (any(tmc_params%sub_box_size(:) <= 0.1_dp))
THEN
494 nr_of_sub_box_elements =
SIZE(elem%elem_stat)
496 ALLOCATE (center_of_sub_box(tmc_params%dim_per_elem))
497 ALLOCATE (atom_tmp(tmc_params%dim_per_elem))
498 nr_of_sub_box_elements = 0
500 CALL rng_stream%set(bg=elem%rng_seed(:, :, 1), cg=elem%rng_seed(:, :, 2), &
501 ig=elem%rng_seed(:, :, 3))
503 CALL get_cell(cell=tmc_params%cell, abc=box_size)
504 DO i = 1,
SIZE(tmc_params%sub_box_size)
505 rnd = rng_stream%next()
506 center_of_sub_box(i) = rnd*box_size(i)
508 elem%subbox_center(:) = center_of_sub_box(:)
510 CALL rng_stream%get(bg=elem%rng_seed(:, :, 1), cg=elem%rng_seed(:, :, 2), &
511 ig=elem%rng_seed(:, :, 3))
514 DO i = 1,
SIZE(elem%pos), tmc_params%dim_per_elem
515 atom_tmp(:) = elem%pos(i:i + tmc_params%dim_per_elem - 1)
516 IF (check_pos_in_subbox(pos=atom_tmp, &
517 subbox_center=center_of_sub_box, box_scale=elem%box_scale, &
518 tmc_params=tmc_params))
THEN
519 elem%elem_stat(i:i + tmc_params%dim_per_elem - 1) =
status_ok
520 nr_of_sub_box_elements = nr_of_sub_box_elements + 1
522 elem%elem_stat(i:i + tmc_params%dim_per_elem - 1) =
status_frozen
525 DEALLOCATE (atom_tmp)
526 DEALLOCATE (center_of_sub_box)
529 CALL timestop(handle)
543 SUBROUTINE do_mol_rot(pos, ind_start, ind_end, max_angle, move_types, &
544 rng_stream, dim_per_elem)
545 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pos
546 INTEGER :: ind_start, ind_end
547 REAL(kind=
dp) :: max_angle
550 INTEGER :: dim_per_elem
553 REAL(kind=
dp) :: a1, a2, a3, q0, q1, q2, q3, rnd
554 REAL(kind=
dp),
DIMENSION(3, 3) :: rot
555 REAL(kind=
dp),
DIMENSION(:),
POINTER :: elem_center
557 NULLIFY (elem_center)
559 cpassert(
ASSOCIATED(pos))
560 cpassert(dim_per_elem == 3)
561 cpassert(ind_start > 0 .AND. ind_start <
SIZE(pos))
562 cpassert(ind_end > 0 .AND. ind_end <
SIZE(pos))
563 cpassert(
ASSOCIATED(move_types))
564 mark_used(move_types)
567 rnd = rng_stream%next()
568 a1 = (rnd - 0.5)*2.0*max_angle
569 rnd = rng_stream%next()
570 a2 = (rnd - 0.5)*2.0*max_angle
571 rnd = rng_stream%next()
572 a3 = (rnd - 0.5)*2.0*max_angle
573 q0 = cos(a2/2)*cos((a1 + a3)/2.0_dp)
574 q1 = sin(a2/2)*cos((a1 - a3)/2.0_dp)
575 q2 = sin(a2/2)*sin((a1 - a3)/2.0_dp)
576 q3 = cos(a2/2)*sin((a1 + a3)/2.0_dp)
577 rot = reshape([q0*q0 + q1*q1 - q2*q2 - q3*q3, 2*(q1*q2 - q0*q3), 2*(q1*q3 + q0*q2), &
578 2*(q1*q2 + q0*q3), q0*q0 - q1*q1 + q2*q2 - q3*q3, 2*(q2*q3 - q0*q1), &
579 2*(q1*q3 - q0*q2), 2*(q2*q3 + q0*q1), q0*q0 - q1*q1 - q2*q2 + q3*q3], [3, 3])
581 ALLOCATE (elem_center(dim_per_elem))
587 atom_loop:
DO i = ind_start, ind_end + dim_per_elem - 1, dim_per_elem
588 pos(i:i + 2) = matmul(pos(i:i + 2) - elem_center(:), rot) + elem_center(:)
590 DEALLOCATE (elem_center)
591 END SUBROUTINE do_mol_rot
606 SUBROUTINE vel_change(vel, atom_kind, phi, temp, rnd_sign_change, rng_stream)
607 REAL(kind=
dp),
INTENT(INOUT) :: vel
609 REAL(kind=
dp),
INTENT(IN) :: phi, temp
610 LOGICAL :: rnd_sign_change
614 REAL(kind=
dp) :: delta_vel, kb, rnd1, rnd2, rnd3, rnd_g
620 rnd1 = rng_stream%next()
621 rnd2 = rng_stream%next()
623 rnd_g = sqrt(-2.0_dp*log(rnd1))*cos(2.0_dp*
pi*rnd2)
628 delta_vel = sqrt(kb*temp/atom_kind%mass)*rnd_g
635 rnd3 = rng_stream%next()
636 IF (rnd3 >= 0.5 .AND. rnd_sign_change)
THEN
641 vel = sin(phi)*delta_vel + cos(phi)*vel*d*1.0_dp
642 END SUBROUTINE vel_change
657 SUBROUTINE search_and_do_proton_displace_loop(elem, short_loop, rng_stream, &
660 LOGICAL :: short_loop
664 CHARACTER(LEN=*),
PARAMETER :: routinen =
'search_and_do_proton_displace_loop'
666 CHARACTER(LEN=1000) :: tmp_chr
667 INTEGER :: counter, donor_acceptor, handle, k, mol, &
669 INTEGER,
DIMENSION(:),
POINTER :: mol_arr
674 cpassert(
ASSOCIATED(elem))
675 cpassert(
ASSOCIATED(tmc_params))
678 CALL timeset(routinen, handle)
682 nr_mol = maxval(elem%mol(:))
684 ALLOCATE (mol_arr(nr_mol))
686 donor_acceptor = not_selected
688 IF (rng_stream%next() < 0.5_dp)
THEN
689 donor_acceptor = proton_acceptor
691 donor_acceptor = proton_donor
696 rnd = rng_stream%next()
698 mol = int(rnd*nr_mol) + 1
699 counter = counter + 1
700 mol_arr(counter) = mol
704 chain_completition_loop:
DO
705 counter = counter + 1
708 CALL find_nearest_proton_acceptor_donator(elem=elem, mol=mol, &
709 donor_acceptor=donor_acceptor, tmc_params=tmc_params, &
710 rng_stream=rng_stream)
711 IF (any(mol_arr(:) == mol))
THEN
712 EXIT chain_completition_loop
714 mol_arr(counter) = mol
715 END DO chain_completition_loop
716 counter = counter - 1
720 IF (mol_arr(k) == mol)
THEN
724 mol_arr(1:counter - k + 1) = mol_arr(k:counter)
725 counter = counter - k + 1
728 IF (counter < 6)
THEN
729 CALL cp_warn(__location__, &
733 WRITE (tmp_chr, *) mol_arr(1:counter)
734 cpwarn(
"selected molecules:"//trim(tmp_chr))
740 CALL rotate_molecules_in_chain(tmc_params=tmc_params, elem=elem, &
741 mol_arr_in=mol_arr(1:counter), donor_acceptor=donor_acceptor)
745 CALL timestop(handle)
746 END SUBROUTINE search_and_do_proton_displace_loop
760 SUBROUTINE find_nearest_proton_acceptor_donator(elem, mol, donor_acceptor, &
761 tmc_params, rng_stream)
763 INTEGER :: mol, donor_acceptor
767 CHARACTER(LEN=*),
PARAMETER :: routinen =
'find_nearest_proton_acceptor_donator'
769 INTEGER :: handle, ind, ind_e, ind_n, mol_tmp, &
771 INTEGER,
DIMENSION(2) :: neighbor_mol
772 REAL(kind=
dp) :: dist_tmp, rnd
773 REAL(kind=
dp),
DIMENSION(:),
POINTER :: disth1, disth2, disto
775 NULLIFY (disto, disth1, disth2)
776 cpassert(
ASSOCIATED(elem))
777 cpassert(
ASSOCIATED(tmc_params))
780 CALL timeset(routinen, handle)
782 nr_mol = maxval(elem%mol)
783 ALLOCATE (disto(nr_mol))
784 ALLOCATE (disth1(nr_mol))
785 ALLOCATE (disth2(nr_mol))
788 disto(:) = huge(disto(1))
790 disth1(:) = huge(disth1(1))
792 disth2(:) = huge(disth2(1))
795 CALL get_mol_indeces(tmc_params=tmc_params, mol_arr=elem%mol, mol=mol, &
796 start_ind=ind, end_ind=ind_e)
799 list_distances:
DO mol_tmp = 1, nr_mol
800 IF (mol_tmp == mol) cycle list_distances
803 CALL get_mol_indeces(tmc_params=tmc_params, mol_arr=elem%mol, &
804 mol=mol_tmp, start_ind=ind_n, end_ind=ind_e)
806 IF (mod(ind_e - ind_n, 3) > 0)
THEN
807 CALL cp_warn(__location__, &
808 "selected a molecule with more than 3 atoms, "// &
809 "the proton reordering does not support, skip molecule")
812 IF (donor_acceptor == proton_acceptor)
THEN
813 IF (check_donor_acceptor(elem=elem, i_orig=ind, i_neighbor=ind_n, &
814 tmc_params=tmc_params) == proton_acceptor)
THEN
817 x1=elem%pos(ind + tmc_params%dim_per_elem: &
818 ind + 2*tmc_params%dim_per_elem - 1), &
819 x2=elem%pos(ind_n:ind_n + tmc_params%dim_per_elem - 1), &
820 cell=tmc_params%cell, box_scale=elem%box_scale)
823 x1=elem%pos(ind + 2*tmc_params%dim_per_elem: &
824 ind + 3*tmc_params%dim_per_elem - 1), &
825 x2=elem%pos(ind_n:ind_n + tmc_params%dim_per_elem - 1), &
826 cell=tmc_params%cell, box_scale=elem%box_scale)
830 IF (donor_acceptor == proton_donor)
THEN
831 IF (check_donor_acceptor(elem=elem, i_orig=ind, i_neighbor=ind_n, &
832 tmc_params=tmc_params) == proton_donor)
THEN
835 x1=elem%pos(ind:ind + tmc_params%dim_per_elem - 1), &
836 x2=elem%pos(ind_n + tmc_params%dim_per_elem: &
837 ind_n + 2*tmc_params%dim_per_elem - 1), &
838 cell=tmc_params%cell, box_scale=elem%box_scale)
840 x1=elem%pos(ind:ind + tmc_params%dim_per_elem - 1), &
841 x2=elem%pos(ind_n + 2*tmc_params%dim_per_elem: &
842 ind_n + 3*tmc_params%dim_per_elem - 1), &
843 cell=tmc_params%cell, box_scale=elem%box_scale)
844 IF (dist_tmp < disto(mol_tmp)) disto(mol_tmp) = dist_tmp
847 END DO list_distances
852 IF (donor_acceptor == proton_acceptor)
THEN
853 neighbor_mol(mol_tmp) = minloc(disth1(:), 1)
854 neighbor_mol(mol_tmp + 1) = minloc(disth2(:), 1)
856 IF (neighbor_mol(mol_tmp) == neighbor_mol(mol_tmp + 1))
THEN
857 disth1(neighbor_mol(mol_tmp)) = huge(disth1(1))
858 disth2(neighbor_mol(mol_tmp + 1)) = huge(disth2(1))
859 IF (minval(disth1(:), 1) < minval(disth2(:), 1))
THEN
860 neighbor_mol(mol_tmp) = minloc(disth1(:), 1)
862 neighbor_mol(mol_tmp + 1) = minloc(disth2(:), 1)
865 mol_tmp = mol_tmp + 2
869 IF (donor_acceptor == proton_donor)
THEN
870 neighbor_mol(mol_tmp) = minloc(disto(:), 1)
871 disto(neighbor_mol(mol_tmp)) = huge(disto(1))
872 neighbor_mol(mol_tmp + 1) = minloc(disto(:), 1)
876 rnd = rng_stream%next()
878 mol_tmp = neighbor_mol(int(rnd*
SIZE(neighbor_mol(:))) + 1)
886 CALL timestop(handle)
887 END SUBROUTINE find_nearest_proton_acceptor_donator
899 FUNCTION check_donor_acceptor(elem, i_orig, i_neighbor, tmc_params) &
900 result(donor_acceptor)
902 INTEGER :: i_orig, i_neighbor
904 INTEGER :: donor_acceptor
906 REAL(kind=
dp),
DIMENSION(4) :: distances
908 cpassert(
ASSOCIATED(elem))
909 cpassert(i_orig >= 1 .AND. i_orig <=
SIZE(elem%pos))
910 cpassert(i_neighbor >= 1 .AND. i_neighbor <=
SIZE(elem%pos))
911 cpassert(
ASSOCIATED(tmc_params))
915 x1=elem%pos(i_neighbor:i_neighbor + tmc_params%dim_per_elem - 1), &
916 x2=elem%pos(i_orig + tmc_params%dim_per_elem: &
917 i_orig + 2*tmc_params%dim_per_elem - 1), &
918 cell=tmc_params%cell, box_scale=elem%box_scale)
921 x1=elem%pos(i_neighbor:i_neighbor + tmc_params%dim_per_elem - 1), &
922 x2=elem%pos(i_orig + 2*tmc_params%dim_per_elem: &
923 i_orig + 3*tmc_params%dim_per_elem - 1), &
924 cell=tmc_params%cell, box_scale=elem%box_scale)
927 x1=elem%pos(i_orig:i_orig + tmc_params%dim_per_elem - 1), &
928 x2=elem%pos(i_neighbor + tmc_params%dim_per_elem: &
929 i_neighbor + 2*tmc_params%dim_per_elem - 1), &
930 cell=tmc_params%cell, box_scale=elem%box_scale)
933 x1=elem%pos(i_orig:i_orig + tmc_params%dim_per_elem - 1), &
934 x2=elem%pos(i_neighbor + 2*tmc_params%dim_per_elem: &
935 i_neighbor + 3*tmc_params%dim_per_elem - 1), &
936 cell=tmc_params%cell, box_scale=elem%box_scale)
938 IF (minloc(distances(:), 1) <= 2)
THEN
939 donor_acceptor = proton_acceptor
941 donor_acceptor = proton_donor
943 END FUNCTION check_donor_acceptor
955 SUBROUTINE rotate_molecules_in_chain(tmc_params, elem, mol_arr_in, &
959 INTEGER,
DIMENSION(:) :: mol_arr_in
960 INTEGER :: donor_acceptor
962 CHARACTER(LEN=*),
PARAMETER :: routinen =
'rotate_molecules_in_chain'
964 INTEGER :: h_offset, handle, i, ind
965 INTEGER,
DIMENSION(:),
POINTER :: ind_arr
966 REAL(kind=
dp) :: dihe_angle, dist_near, tmp
967 REAL(kind=
dp),
DIMENSION(3) :: rot_axis, tmp_1, tmp_2, vec_1o, &
968 vec_2h_f, vec_2h_m, vec_2o, vec_3o, &
972 NULLIFY (ind_arr, tmp_cell)
974 cpassert(
ASSOCIATED(tmc_params))
975 cpassert(
ASSOCIATED(elem))
978 CALL timeset(routinen, handle)
980 ALLOCATE (ind_arr(0:
SIZE(mol_arr_in) + 1))
981 DO i = 1,
SIZE(mol_arr_in)
982 CALL get_mol_indeces(tmc_params=tmc_params, mol_arr=elem%mol, &
984 start_ind=ind_arr(i), end_ind=ind)
986 ind_arr(0) = ind_arr(
SIZE(ind_arr) - 2)
987 ind_arr(
SIZE(ind_arr) - 1) = ind_arr(1)
992 scaled_cell=tmp_cell)
995 DO i = 1,
SIZE(ind_arr) - 2
997 vec_1o(:) = elem%pos(ind_arr(i - 1):ind_arr(i - 1) + tmc_params%dim_per_elem - 1)
998 vec_2o(:) = elem%pos(ind_arr(i):ind_arr(i) + tmc_params%dim_per_elem - 1)
999 vec_3o(:) = elem%pos(ind_arr(i + 1):ind_arr(i + 1) + tmc_params%dim_per_elem - 1)
1005 x1=elem%pos(ind_arr(i + donor_acceptor): &
1006 ind_arr(i + donor_acceptor) + tmc_params%dim_per_elem - 1), &
1007 x2=elem%pos(ind_arr(i) + tmc_params%dim_per_elem: &
1008 ind_arr(i) + 2*tmc_params%dim_per_elem - 1), &
1009 cell=tmc_params%cell, box_scale=elem%box_scale) &
1012 x1=elem%pos(ind_arr(i + donor_acceptor): &
1013 ind_arr(i + donor_acceptor) + tmc_params%dim_per_elem - 1), &
1014 x2=elem%pos(ind_arr(i) + 2*tmc_params%dim_per_elem: &
1015 ind_arr(i) + 3*tmc_params%dim_per_elem - 1), &
1016 cell=tmc_params%cell, box_scale=elem%box_scale) &
1018 vec_2h_m = elem%pos(ind_arr(i) + tmc_params%dim_per_elem: &
1019 ind_arr(i) + 2*tmc_params%dim_per_elem - 1)
1020 vec_2h_f = elem%pos(ind_arr(i) + 2*tmc_params%dim_per_elem: &
1021 ind_arr(i) + 3*tmc_params%dim_per_elem - 1)
1024 vec_2h_f = elem%pos(ind_arr(i) + tmc_params%dim_per_elem: &
1025 ind_arr(i) + 2*tmc_params%dim_per_elem - 1)
1026 vec_2h_m = elem%pos(ind_arr(i) + 2*tmc_params%dim_per_elem: &
1027 ind_arr(i) + 3*tmc_params%dim_per_elem - 1)
1034 tmp_1 =
pbc(vec_2o - vec_1o, tmp_cell)
1035 tmp_2 =
pbc(vec_3o - vec_2h_f, tmp_cell)
1037 dihe_angle = donor_acceptor*
dihedral_angle(tmp_1, vec_2h_f - vec_2o, tmp_2)
1038 DO ind = ind_arr(i), ind_arr(i) + tmc_params%dim_per_elem*3 - 1, tmc_params%dim_per_elem
1042 ind + tmc_params%dim_per_elem - 1) - vec_2o, &
1043 dihe_angle, vec_2h_f - vec_2o)
1047 elem%pos(ind:ind + tmc_params%dim_per_elem - 1) = vec_2o + vec_rotated
1055 dist_near = huge(dist_near)
1056 search_o_loop:
DO ind = 1,
SIZE(elem%pos), &
1057 tmc_params%dim_per_elem*3
1058 IF (ind == ind_arr(i)) cycle search_o_loop
1060 x2=elem%pos(ind:ind + tmc_params%dim_per_elem - 1), &
1061 cell=tmc_params%cell, box_scale=elem%box_scale)
1062 IF (dist_near > tmp)
THEN
1064 vec_4o = elem%pos(ind:ind + tmc_params%dim_per_elem - 1)
1066 END DO search_o_loop
1067 rot_axis =
pbc(-vec_2o(:) + vec_4o(:), tmp_cell)
1068 tmp_1 =
pbc(vec_2o - vec_1o, tmp_cell)
1069 tmp_2 =
pbc(vec_3o - vec_4o, tmp_cell)
1070 dihe_angle = donor_acceptor*
dihedral_angle(tmp_1, rot_axis, tmp_2)
1071 vec_rotated =
rotate_vector(vec_2h_m - vec_2o, dihe_angle, rot_axis)
1073 elem%pos(ind_arr(i) + h_offset*tmc_params%dim_per_elem: &
1074 ind_arr(i) + (h_offset + 1)*tmc_params%dim_per_elem - 1) &
1075 = vec_2o + vec_rotated
1076 vec_rotated =
rotate_vector(vec_2h_f - vec_2o, dihe_angle, rot_axis)
1077 IF (h_offset == 1)
THEN
1082 elem%pos(ind_arr(i) + h_offset*tmc_params%dim_per_elem: &
1083 ind_arr(i) + (h_offset + 1)*tmc_params%dim_per_elem - 1) &
1084 = vec_2o + vec_rotated
1087 DEALLOCATE (tmp_cell)
1088 DEALLOCATE (ind_arr)
1090 CALL timestop(handle)
1091 END SUBROUTINE rotate_molecules_in_chain
1107 SUBROUTINE change_volume(conf, T_ind, move_types, rng_stream, tmc_params, &
1114 LOGICAL :: mv_cen_of_mass
1116 CHARACTER(LEN=*),
PARAMETER :: routinen =
'change_volume'
1118 INTEGER ::
atom, dir, handle, ind, ind_e, mol
1119 REAL(kind=
dp) :: rnd, vol
1120 REAL(kind=
dp),
DIMENSION(3) :: box_length_new, box_length_orig, &
1122 REAL(kind=
dp),
DIMENSION(:),
POINTER :: disp, scaling
1124 NULLIFY (scaling, disp)
1126 cpassert(
ASSOCIATED(conf))
1127 cpassert(
ASSOCIATED(move_types))
1128 cpassert(
ASSOCIATED(tmc_params))
1129 cpassert(t_ind > 0 .AND. t_ind <= tmc_params%nr_temp)
1130 cpassert(tmc_params%dim_per_elem == 3)
1131 cpassert(tmc_params%cell%orthorhombic)
1134 CALL timeset(routinen, handle)
1136 ALLOCATE (scaling(tmc_params%dim_per_elem))
1137 ALLOCATE (disp(tmc_params%dim_per_elem))
1139 box_scale_old(:) = conf%box_scale
1141 CALL get_scaled_cell(cell=tmc_params%cell, box_scale=conf%box_scale, &
1146 IF (tmc_params%v_isotropic)
THEN
1147 CALL get_scaled_cell(cell=tmc_params%cell, box_scale=conf%box_scale, &
1148 abc=box_length_new, vol=vol)
1149 rnd = rng_stream%next()
1151 box_length_new(:) = vol**(1/real(3, kind=
dp))
1153 CALL get_scaled_cell(cell=tmc_params%cell, box_scale=conf%box_scale, &
1154 abc=box_length_new, vol=vol)
1155 rnd = rng_stream%next()
1157 rnd = rng_stream%next()
1158 dir = 1 + int(rnd*3)
1159 box_length_new(dir) = 1.0_dp
1160 box_length_new(dir) = vol/product(box_length_new(:))
1166 IF (tmc_params%v_isotropic)
THEN
1167 rnd = rng_stream%next()
1168 box_length_new(:) = box_length_new(:) + &
1169 (rnd - 0.5_dp)*2.0_dp* &
1173 rnd = rng_stream%next()
1174 dir = 1 + int(rnd*3)
1175 rnd = rng_stream%next()
1176 box_length_new(dir) = box_length_new(dir) + &
1177 (rnd - 0.5_dp)*2.0_dp* &
1185 box_scale=scaling, &
1186 abc=box_length_orig)
1188 conf%box_scale(:) = box_length_new(:)/box_length_orig(:)
1190 scaling(:) = conf%box_scale(:)/box_scale_old(:)
1192 IF (mv_cen_of_mass .EQV. .false.)
THEN
1194 DO atom = 1,
SIZE(conf%pos), tmc_params%dim_per_elem
1195 conf%pos(
atom:
atom + tmc_params%dim_per_elem - 1) = &
1196 conf%pos(
atom:
atom + tmc_params%dim_per_elem - 1)*scaling(:)
1199 DO mol = 1, maxval(conf%mol(:))
1202 cpassert(
ASSOCIATED(tmc_params%atoms))
1204 CALL get_mol_indeces(tmc_params=tmc_params, mol_arr=conf%mol, mol=mol, &
1205 start_ind=ind, end_ind=ind_e)
1207 pos=conf%pos(ind:ind_e + tmc_params%dim_per_elem - 1), &
1208 atoms=tmc_params%atoms(int(ind/real(tmc_params%dim_per_elem, kind=
dp)) + 1: &
1209 int(ind_e/real(tmc_params%dim_per_elem, kind=
dp)) + 1), &
1212 disp(:) = disp(:)*(scaling(:) - 1.0_dp)
1214 DO atom = ind, ind_e + tmc_params%dim_per_elem - 1, tmc_params%dim_per_elem
1215 conf%pos(
atom:
atom + tmc_params%dim_per_elem - 1) = &
1216 conf%pos(
atom:
atom + tmc_params%dim_per_elem - 1) + disp(:)
1221 DEALLOCATE (scaling)
1225 CALL timestop(handle)
1226 END SUBROUTINE change_volume
1237 SUBROUTINE swap_atoms(conf, move_types, rng_stream, tmc_params)
1243 INTEGER :: a_1, a_2, ind_1, ind_2
1245 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: pos_tmp
1247 cpassert(
ASSOCIATED(conf))
1248 cpassert(
ASSOCIATED(move_types))
1249 cpassert(
ASSOCIATED(tmc_params))
1250 cpassert(
ASSOCIATED(tmc_params%atoms))
1253 atom_search_loop:
DO
1255 a_1 = int(
SIZE(conf%pos)/real(tmc_params%dim_per_elem, kind=
dp)* &
1256 rng_stream%next()) + 1
1258 a_2 = int(
SIZE(conf%pos)/real(tmc_params%dim_per_elem, kind=
dp)* &
1259 rng_stream%next()) + 1
1261 IF (tmc_params%atoms(a_1)%name /= tmc_params%atoms(a_2)%name)
THEN
1263 IF (
ASSOCIATED(move_types%atom_lists))
THEN
1264 DO ind_1 = 1,
SIZE(move_types%atom_lists)
1265 IF (any(move_types%atom_lists(ind_1)%atoms(:) == &
1266 tmc_params%atoms(a_1)%name) .AND. &
1267 any(move_types%atom_lists(ind_1)%atoms(:) == &
1268 tmc_params%atoms(a_2)%name))
THEN
1270 EXIT atom_search_loop
1275 EXIT atom_search_loop
1278 END DO atom_search_loop
1281 ALLOCATE (pos_tmp(tmc_params%dim_per_elem))
1282 ind_1 = (a_1 - 1)*tmc_params%dim_per_elem + 1
1283 pos_tmp(:) = conf%pos(ind_1:ind_1 + tmc_params%dim_per_elem - 1)
1284 ind_2 = (a_2 - 1)*tmc_params%dim_per_elem + 1
1285 conf%pos(ind_1:ind_1 + tmc_params%dim_per_elem - 1) = &
1286 conf%pos(ind_2:ind_2 + tmc_params%dim_per_elem - 1)
1287 conf%pos(ind_2:ind_2 + tmc_params%dim_per_elem - 1) = pos_tmp(:)
1288 DEALLOCATE (pos_tmp)
1290 END SUBROUTINE swap_atoms
Handles all functions related to the CELL.
subroutine, public get_cell(cell, alpha, beta, gamma, deth, orthorhombic, abc, periodic, h, h_inv, symmetry_id, tag)
Get informations about a simulation cell.
various routines to log and control the output. The idea is that decisions about where to log should ...
Defines the basic variable types.
integer, parameter, public dp
Definition of mathematical constants and functions.
real(kind=dp), parameter, public pi
Collection of simple mathematical functions and subroutines.
pure real(kind=dp) function, dimension(3), public rotate_vector(a, phi, b)
Rotation of the vector a about an rotation axis defined by the vector b. The rotation angle is phi (r...
pure real(kind=dp) function, public dihedral_angle(ab, bc, cd)
Returns the dihedral angle, i.e. the angle between the planes defined by the vectors (-ab,...
Parallel (pseudo)random number generator (RNG) for multiple streams and substreams of random numbers.
Definition of physical constants:
real(kind=dp), parameter, public boltzmann
real(kind=dp), parameter, public joule
calculation section for TreeMonteCarlo
subroutine, public geometrical_center(pos, center)
calculate the geometrical center of an amount of atoms array size should be multiple of dim_per_elem
subroutine, public get_scaled_cell(cell, box_scale, scaled_hmat, scaled_cell, vol, abc, vec)
handles properties and calculations of a scaled cell
subroutine, public center_of_mass(pos, atoms, center)
calculate the center of mass of an amount of atoms array size should be multiple of dim_per_elem
real(kind=dp) function, public nearest_distance(x1, x2, cell, box_scale)
neares distance of atoms within the periodic boundary condition
tree nodes creation, searching, deallocation, references etc.
integer, parameter, public mv_type_mol_rot
integer, parameter, public mv_type_volume_move
integer, parameter, public mv_type_proton_reorder
integer, parameter, public mv_type_md
integer, parameter, public mv_type_mol_trans
integer, parameter, public mv_type_atom_swap
integer, parameter, public mv_type_gausian_adapt
integer, parameter, public mv_type_atom_trans
different move types are applied
subroutine, public elements_in_new_subbox(tmc_params, rng_stream, elem, nr_of_sub_box_elements)
set a new random sub box center and counte the number of atoms in it
subroutine, public change_pos(tmc_params, move_types, rng_stream, elem, mv_conf, new_subbox, move_rejected)
applying the preselected move type
module handles definition of the tree nodes for the global and the subtrees binary tree parent elemen...
integer, parameter, public status_ok
integer, parameter, public status_frozen
module handles definition of the tree nodes for the global and the subtrees binary tree parent elemen...
Type defining parameters related to the simulation cell.