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)
70 TYPE(tmc_param_type),
POINTER :: tmc_params
71 TYPE(tmc_move_type),
POINTER :: move_types
72 TYPE(rng_stream_type),
INTENT(INOUT) :: rng_stream
73 TYPE(tree_type),
POINTER :: elem
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 .GT. 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(:) .EQ.
status_ok))
106 IF (tmc_params%nr_elem_mv .EQ. 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 .EQ. 0) &
128 act_nr_elem_mv =
SIZE(elem%pos)/tmc_params%dim_per_elem
129 ALLOCATE (elem_center(tmc_params%dim_per_elem))
131 move_elements_loop:
DO
133 IF (tmc_params%nr_elem_mv .EQ. 0)
THEN
134 ind = (i - 1)*(tmc_params%dim_per_elem) + 1
136 rnd = rng_stream%next()
137 ind = tmc_params%dim_per_elem* &
138 int(rnd*(
SIZE(elem%pos)/tmc_params%dim_per_elem)) + 1
141 IF (elem%elem_stat(ind) .EQ.
status_ok)
THEN
143 DO d = 0, tmc_params%dim_per_elem - 1
144 rnd = rng_stream%next()
145 elem%pos(ind + d) = elem%pos(ind + d) + (rnd - 0.5)*2.0* &
149 elem_center = elem%pos(ind:ind + tmc_params%dim_per_elem - 1)
150 IF (.NOT. check_pos_in_subbox(pos=elem_center, &
151 subbox_center=elem%subbox_center, &
152 box_scale=elem%box_scale, tmc_params=tmc_params) &
154 move_rejected = .true.
155 EXIT move_elements_loop
159 IF (tmc_params%nr_elem_mv .GT. 0) i = i - 1
162 IF (i .GT. act_nr_elem_mv)
EXIT move_elements_loop
163 END DO move_elements_loop
164 DEALLOCATE (elem_center)
168 nr_molec = maxval(elem%mol(:))
170 IF (act_nr_elem_mv .EQ. 0) &
171 act_nr_elem_mv = nr_molec
172 ALLOCATE (mol_in_sb(nr_molec))
173 ALLOCATE (elem_center(tmc_params%dim_per_elem))
177 CALL get_mol_indeces(tmc_params=tmc_params, mol_arr=elem%mol, mol=m, &
178 start_ind=ind, end_ind=ind_e)
181 IF (check_pos_in_subbox(pos=elem_center, &
182 subbox_center=elem%subbox_center, &
183 box_scale=elem%box_scale, tmc_params=tmc_params) &
188 IF (any(mol_in_sb(:) .EQ.
status_ok))
THEN
189 ALLOCATE (direction(tmc_params%dim_per_elem))
191 move_molecule_loop:
DO
193 IF (tmc_params%nr_elem_mv .EQ. 0)
THEN
196 rnd = rng_stream%next()
197 m = int(rnd*nr_molec) + 1
199 CALL get_mol_indeces(tmc_params=tmc_params, mol_arr=elem%mol, mol=m, &
200 start_ind=ind, end_ind=ind_e)
202 IF (ind .EQ. ind_e) cycle move_molecule_loop
208 DO d = 1, tmc_params%dim_per_elem
209 rnd = rng_stream%next()
210 direction(d) = (rnd - 0.5)*2.0_dp*move_types%mv_size( &
214 elem_center(:) = elem_center(:) + direction(:)
215 IF (check_pos_in_subbox(pos=elem_center, &
216 subbox_center=elem%subbox_center, &
217 box_scale=elem%box_scale, tmc_params=tmc_params) &
220 atom_in_mol_loop:
DO i = ind, ind_e + tmc_params%dim_per_elem - 1, tmc_params%dim_per_elem
221 dim_loop:
DO d = 0, tmc_params%dim_per_elem - 1
222 elem%pos(i + d) = elem%pos(i + d) + direction(d + 1)
224 END DO atom_in_mol_loop
227 move_rejected = .true.
228 EXIT move_molecule_loop
232 IF (tmc_params%nr_elem_mv .GT. 0) counter = counter - 1
234 counter = counter + 1
235 IF (counter .GT. act_nr_elem_mv)
EXIT move_molecule_loop
236 END DO move_molecule_loop
237 DEALLOCATE (direction)
239 DEALLOCATE (elem_center)
240 DEALLOCATE (mol_in_sb)
244 nr_molec = maxval(elem%mol(:))
245 IF (act_nr_elem_mv .EQ. 0) &
246 act_nr_elem_mv = nr_molec
247 ALLOCATE (mol_in_sb(nr_molec))
248 ALLOCATE (elem_center(tmc_params%dim_per_elem))
252 CALL get_mol_indeces(tmc_params=tmc_params, mol_arr=elem%mol, mol=m, &
253 start_ind=ind, end_ind=ind_e)
256 IF (check_pos_in_subbox(pos=elem_center, &
257 subbox_center=elem%subbox_center, &
258 box_scale=elem%box_scale, tmc_params=tmc_params) &
263 IF (any(mol_in_sb(:) .EQ.
status_ok))
THEN
265 rot_molecule_loop:
DO
267 IF (tmc_params%nr_elem_mv .EQ. 0)
THEN
270 rnd = rng_stream%next()
271 m = int(rnd*nr_molec) + 1
273 CALL get_mol_indeces(tmc_params=tmc_params, mol_arr=elem%mol, mol=m, &
274 start_ind=ind, end_ind=ind_e)
276 IF (ind .EQ. ind_e) cycle rot_molecule_loop
280 CALL do_mol_rot(pos=elem%pos, ind_start=ind, ind_end=ind_e, &
281 max_angle=move_types%mv_size( &
283 move_types=move_types, rng_stream=rng_stream, &
284 dim_per_elem=tmc_params%dim_per_elem)
286 DO i = ind, ind_e + tmc_params%dim_per_elem - 1, tmc_params%dim_per_elem
287 elem_center = elem%pos(i:i + tmc_params%dim_per_elem - 1)
288 IF (check_pos_in_subbox(pos=elem_center, &
289 subbox_center=elem%subbox_center, &
290 box_scale=elem%box_scale, tmc_params=tmc_params) &
292 elem%elem_stat(i:i + tmc_params%dim_per_elem - 1) =
status_ok
294 elem%elem_stat(i:i + tmc_params%dim_per_elem - 1) =
status_frozen
299 IF (tmc_params%nr_elem_mv .GT. 0) counter = counter - 1
301 counter = counter + 1
302 IF (counter .GT. act_nr_elem_mv)
EXIT rot_molecule_loop
303 END DO rot_molecule_loop
305 DEALLOCATE (elem_center)
306 DEALLOCATE (mol_in_sb)
311 cpassert(
ASSOCIATED(tmc_params%atoms))
312 change_all_velocities_loop:
DO i = 1,
SIZE(elem%pos)
315 CALL vel_change(vel=elem%vel(i), &
316 atom_kind=tmc_params%atoms(int(i/real(tmc_params%dim_per_elem, kind=
dp)) + 1), &
318 temp=tmc_params%Temp(mv_conf), &
319 rnd_sign_change=.true., &
320 rng_stream=rng_stream)
322 END DO change_all_velocities_loop
328 CALL search_and_do_proton_displace_loop(elem=elem, &
329 short_loop=move_rejected, rng_stream=rng_stream, &
330 tmc_params=tmc_params)
335 CALL change_volume(conf=elem, t_ind=mv_conf, move_types=move_types, &
336 rng_stream=rng_stream, tmc_params=tmc_params, &
337 mv_cen_of_mass=tmc_params%mv_cen_of_mass)
342 CALL swap_atoms(conf=elem, move_types=move_types, rng_stream=rng_stream, &
343 tmc_params=tmc_params)
346 CALL cp_abort(__location__, &
347 "unknown move type "// &
348 cp_to_string(elem%move_type))
351 CALL rng_stream%get(bg=elem%rng_seed(:, :, 1), &
352 cg=elem%rng_seed(:, :, 2), ig=elem%rng_seed(:, :, 3))
365 SUBROUTINE get_mol_indeces(tmc_params, mol_arr, mol, start_ind, end_ind)
366 TYPE(tmc_param_type),
POINTER :: tmc_params
367 INTEGER,
DIMENSION(:),
INTENT(IN),
POINTER :: mol_arr
368 INTEGER,
INTENT(IN) :: mol
369 INTEGER,
INTENT(OUT) :: start_ind, end_ind
376 cpassert(
ASSOCIATED(mol_arr))
377 cpassert(mol .LE. maxval(mol_arr(:)))
379 loop_start:
DO i = 1,
SIZE(mol_arr)
380 IF (mol_arr(i) .EQ. mol)
THEN
386 loop_end:
DO i =
SIZE(mol_arr), i, -1
387 IF (mol_arr(i) .EQ. mol)
THEN
393 cpassert(all(mol_arr(start_ind:end_ind) .EQ. mol))
394 cpassert(start_ind .GT. 0)
395 cpassert(end_ind .GT. 0)
397 start_ind = (start_ind - 1)*tmc_params%dim_per_elem + 1
398 end_ind = (end_ind - 1)*tmc_params%dim_per_elem + 1
411 FUNCTION check_pos_in_subbox(pos, subbox_center, box_scale, tmc_params) &
413 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pos, subbox_center, box_scale
414 TYPE(tmc_param_type),
POINTER :: tmc_params
417 CHARACTER(LEN=*),
PARAMETER :: routinen =
'check_pos_in_subbox'
421 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: pos_tmp
423 cpassert(
ASSOCIATED(pos))
424 cpassert(
ASSOCIATED(subbox_center))
425 cpassert(
ASSOCIATED(box_scale))
427 flag = .NOT. ((tmc_params%pressure .GT. 0.0_dp) .AND. (any(box_scale .EQ. 0.0_dp)))
429 cpassert(
SIZE(pos) .EQ. 3)
430 cpassert(
SIZE(pos) .EQ.
SIZE(subbox_center))
433 CALL timeset(routinen, handle)
435 ALLOCATE (pos_tmp(
SIZE(pos)))
439 IF (.NOT. any(tmc_params%sub_box_size(:) .LE. 0.1_dp))
THEN
440 pos_tmp(:) = pos(:) - subbox_center(:)
444 IF (any(pos_tmp(:) .GE. tmc_params%sub_box_size(:)/2.0) .OR. &
445 any(pos_tmp(:) .LE. -tmc_params%sub_box_size(:)/2.0))
THEN
451 CALL timestop(handle)
452 END FUNCTION check_pos_in_subbox
465 nr_of_sub_box_elements)
466 TYPE(tmc_param_type),
POINTER :: tmc_params
467 TYPE(rng_stream_type),
INTENT(INOUT) :: rng_stream
468 TYPE(tree_type),
POINTER :: elem
469 INTEGER,
INTENT(OUT) :: nr_of_sub_box_elements
471 CHARACTER(LEN=*),
PARAMETER :: routinen =
'elements_in_new_subbox'
475 REAL(kind=
dp),
DIMENSION(3) :: box_size
476 REAL(kind=
dp),
DIMENSION(:),
POINTER :: atom_tmp, center_of_sub_box
478 NULLIFY (center_of_sub_box, atom_tmp)
480 cpassert(
ASSOCIATED(tmc_params))
481 cpassert(
ASSOCIATED(elem))
484 CALL timeset(routinen, handle)
486 IF (any(tmc_params%sub_box_size(:) .LE. 0.1_dp))
THEN
489 nr_of_sub_box_elements =
SIZE(elem%elem_stat)
491 ALLOCATE (center_of_sub_box(tmc_params%dim_per_elem))
492 ALLOCATE (atom_tmp(tmc_params%dim_per_elem))
493 nr_of_sub_box_elements = 0
495 CALL rng_stream%set(bg=elem%rng_seed(:, :, 1), cg=elem%rng_seed(:, :, 2), &
496 ig=elem%rng_seed(:, :, 3))
498 CALL get_cell(cell=tmc_params%cell, abc=box_size)
499 DO i = 1,
SIZE(tmc_params%sub_box_size)
500 rnd = rng_stream%next()
501 center_of_sub_box(i) = rnd*box_size(i)
503 elem%subbox_center(:) = center_of_sub_box(:)
505 CALL rng_stream%get(bg=elem%rng_seed(:, :, 1), cg=elem%rng_seed(:, :, 2), &
506 ig=elem%rng_seed(:, :, 3))
509 DO i = 1,
SIZE(elem%pos), tmc_params%dim_per_elem
510 atom_tmp(:) = elem%pos(i:i + tmc_params%dim_per_elem - 1)
511 IF (check_pos_in_subbox(pos=atom_tmp, &
512 subbox_center=center_of_sub_box, box_scale=elem%box_scale, &
513 tmc_params=tmc_params))
THEN
514 elem%elem_stat(i:i + tmc_params%dim_per_elem - 1) =
status_ok
515 nr_of_sub_box_elements = nr_of_sub_box_elements + 1
517 elem%elem_stat(i:i + tmc_params%dim_per_elem - 1) =
status_frozen
520 DEALLOCATE (atom_tmp)
521 DEALLOCATE (center_of_sub_box)
524 CALL timestop(handle)
538 SUBROUTINE do_mol_rot(pos, ind_start, ind_end, max_angle, move_types, &
539 rng_stream, dim_per_elem)
540 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pos
541 INTEGER :: ind_start, ind_end
542 REAL(kind=
dp) :: max_angle
543 TYPE(tmc_move_type),
POINTER :: move_types
544 TYPE(rng_stream_type),
INTENT(INOUT) :: rng_stream
545 INTEGER :: dim_per_elem
548 REAL(kind=
dp) :: a1, a2, a3, q0, q1, q2, q3, rnd
549 REAL(kind=
dp),
DIMENSION(3, 3) :: rot
550 REAL(kind=
dp),
DIMENSION(:),
POINTER :: elem_center
552 NULLIFY (elem_center)
554 cpassert(
ASSOCIATED(pos))
555 cpassert(dim_per_elem .EQ. 3)
556 cpassert(ind_start .GT. 0 .AND. ind_start .LT.
SIZE(pos))
557 cpassert(ind_end .GT. 0 .AND. ind_end .LT.
SIZE(pos))
558 cpassert(
ASSOCIATED(move_types))
559 mark_used(move_types)
562 rnd = rng_stream%next()
563 a1 = (rnd - 0.5)*2.0*max_angle
564 rnd = rng_stream%next()
565 a2 = (rnd - 0.5)*2.0*max_angle
566 rnd = rng_stream%next()
567 a3 = (rnd - 0.5)*2.0*max_angle
568 q0 = cos(a2/2)*cos((a1 + a3)/2.0_dp)
569 q1 = sin(a2/2)*cos((a1 - a3)/2.0_dp)
570 q2 = sin(a2/2)*sin((a1 - a3)/2.0_dp)
571 q3 = cos(a2/2)*sin((a1 + a3)/2.0_dp)
572 rot = reshape((/q0*q0 + q1*q1 - q2*q2 - q3*q3, 2*(q1*q2 - q0*q3), 2*(q1*q3 + q0*q2), &
573 2*(q1*q2 + q0*q3), q0*q0 - q1*q1 + q2*q2 - q3*q3, 2*(q2*q3 - q0*q1), &
574 2*(q1*q3 - q0*q2), 2*(q2*q3 + q0*q1), q0*q0 - q1*q1 - q2*q2 + q3*q3/), (/3, 3/))
576 ALLOCATE (elem_center(dim_per_elem))
582 atom_loop:
DO i = ind_start, ind_end + dim_per_elem - 1, dim_per_elem
583 pos(i:i + 2) = matmul(pos(i:i + 2) - elem_center(:), rot) + elem_center(:)
585 DEALLOCATE (elem_center)
586 END SUBROUTINE do_mol_rot
601 SUBROUTINE vel_change(vel, atom_kind, phi, temp, rnd_sign_change, rng_stream)
602 REAL(kind=
dp),
INTENT(INOUT) :: vel
603 TYPE(tmc_atom_type) :: atom_kind
604 REAL(kind=
dp),
INTENT(IN) :: phi, temp
605 LOGICAL :: rnd_sign_change
606 TYPE(rng_stream_type),
INTENT(INOUT) :: rng_stream
609 REAL(kind=
dp) :: delta_vel, kb, rnd1, rnd2, rnd3, rnd_g
615 rnd1 = rng_stream%next()
616 rnd2 = rng_stream%next()
618 rnd_g = sqrt(-2.0_dp*log(rnd1))*cos(2.0_dp*
pi*rnd2)
623 delta_vel = sqrt(kb*temp/atom_kind%mass)*rnd_g
630 rnd3 = rng_stream%next()
631 IF (rnd3 .GE. 0.5 .AND. rnd_sign_change)
THEN
636 vel = sin(phi)*delta_vel + cos(phi)*vel*d*1.0_dp
637 END SUBROUTINE vel_change
652 SUBROUTINE search_and_do_proton_displace_loop(elem, short_loop, rng_stream, &
654 TYPE(tree_type),
POINTER :: elem
655 LOGICAL :: short_loop
656 TYPE(rng_stream_type),
INTENT(INOUT) :: rng_stream
657 TYPE(tmc_param_type),
POINTER :: tmc_params
659 CHARACTER(LEN=*),
PARAMETER :: routinen =
'search_and_do_proton_displace_loop'
661 CHARACTER(LEN=1000) :: tmp_chr
662 INTEGER :: counter, donor_acceptor, handle, k, mol, &
664 INTEGER,
DIMENSION(:),
POINTER :: mol_arr
669 cpassert(
ASSOCIATED(elem))
670 cpassert(
ASSOCIATED(tmc_params))
673 CALL timeset(routinen, handle)
677 nr_mol = maxval(elem%mol(:))
679 ALLOCATE (mol_arr(nr_mol))
681 donor_acceptor = not_selected
683 IF (rng_stream%next() .LT. 0.5_dp)
THEN
684 donor_acceptor = proton_acceptor
686 donor_acceptor = proton_donor
691 rnd = rng_stream%next()
693 mol = int(rnd*nr_mol) + 1
694 counter = counter + 1
695 mol_arr(counter) = mol
699 chain_completition_loop:
DO
700 counter = counter + 1
703 CALL find_nearest_proton_acceptor_donator(elem=elem, mol=mol, &
704 donor_acceptor=donor_acceptor, tmc_params=tmc_params, &
705 rng_stream=rng_stream)
706 IF (any(mol_arr(:) .EQ. mol)) &
707 EXIT chain_completition_loop
708 mol_arr(counter) = mol
709 END DO chain_completition_loop
710 counter = counter - 1
714 IF (mol_arr(k) .EQ. mol) &
717 mol_arr(1:counter - k + 1) = mol_arr(k:counter)
718 counter = counter - k + 1
721 IF (counter .LT. 6)
THEN
722 CALL cp_warn(__location__, &
723 "short proton loop with"//cp_to_string(counter)// &
726 WRITE (tmp_chr, *) mol_arr(1:counter)
727 cpwarn(
"selected molecules:"//trim(tmp_chr))
733 CALL rotate_molecules_in_chain(tmc_params=tmc_params, elem=elem, &
734 mol_arr_in=mol_arr(1:counter), donor_acceptor=donor_acceptor)
738 CALL timestop(handle)
739 END SUBROUTINE search_and_do_proton_displace_loop
753 SUBROUTINE find_nearest_proton_acceptor_donator(elem, mol, donor_acceptor, &
754 tmc_params, rng_stream)
755 TYPE(tree_type),
POINTER :: elem
756 INTEGER :: mol, donor_acceptor
757 TYPE(tmc_param_type),
POINTER :: tmc_params
758 TYPE(rng_stream_type),
INTENT(INOUT) :: rng_stream
760 CHARACTER(LEN=*),
PARAMETER :: routinen =
'find_nearest_proton_acceptor_donator'
762 INTEGER :: handle, ind, ind_e, ind_n, mol_tmp, &
764 INTEGER,
DIMENSION(2) :: neighbor_mol
765 REAL(kind=
dp) :: dist_tmp, rnd
766 REAL(kind=
dp),
DIMENSION(:),
POINTER :: disth1, disth2, disto
768 NULLIFY (disto, disth1, disth2)
769 cpassert(
ASSOCIATED(elem))
770 cpassert(
ASSOCIATED(tmc_params))
773 CALL timeset(routinen, handle)
775 nr_mol = maxval(elem%mol)
776 ALLOCATE (disto(nr_mol))
777 ALLOCATE (disth1(nr_mol))
778 ALLOCATE (disth2(nr_mol))
781 disto(:) = huge(disto(1))
783 disth1(:) = huge(disth1(1))
785 disth2(:) = huge(disth2(1))
788 CALL get_mol_indeces(tmc_params=tmc_params, mol_arr=elem%mol, mol=mol, &
789 start_ind=ind, end_ind=ind_e)
792 list_distances:
DO mol_tmp = 1, nr_mol
793 IF (mol_tmp .EQ. mol) cycle list_distances
796 CALL get_mol_indeces(tmc_params=tmc_params, mol_arr=elem%mol, &
797 mol=mol_tmp, start_ind=ind_n, end_ind=ind_e)
799 IF (mod(ind_e - ind_n, 3) .GT. 0)
THEN
800 CALL cp_warn(__location__, &
801 "selected a molecule with more than 3 atoms, "// &
802 "the proton reordering does not support, skip molecule")
805 IF (donor_acceptor .EQ. proton_acceptor)
THEN
806 IF (check_donor_acceptor(elem=elem, i_orig=ind, i_neighbor=ind_n, &
807 tmc_params=tmc_params) .EQ. proton_acceptor)
THEN
810 x1=elem%pos(ind + tmc_params%dim_per_elem: &
811 ind + 2*tmc_params%dim_per_elem - 1), &
812 x2=elem%pos(ind_n:ind_n + tmc_params%dim_per_elem - 1), &
813 cell=tmc_params%cell, box_scale=elem%box_scale)
816 x1=elem%pos(ind + 2*tmc_params%dim_per_elem: &
817 ind + 3*tmc_params%dim_per_elem - 1), &
818 x2=elem%pos(ind_n:ind_n + tmc_params%dim_per_elem - 1), &
819 cell=tmc_params%cell, box_scale=elem%box_scale)
823 IF (donor_acceptor .EQ. proton_donor)
THEN
824 IF (check_donor_acceptor(elem=elem, i_orig=ind, i_neighbor=ind_n, &
825 tmc_params=tmc_params) .EQ. proton_donor)
THEN
828 x1=elem%pos(ind:ind + tmc_params%dim_per_elem - 1), &
829 x2=elem%pos(ind_n + tmc_params%dim_per_elem: &
830 ind_n + 2*tmc_params%dim_per_elem - 1), &
831 cell=tmc_params%cell, box_scale=elem%box_scale)
833 x1=elem%pos(ind:ind + tmc_params%dim_per_elem - 1), &
834 x2=elem%pos(ind_n + 2*tmc_params%dim_per_elem: &
835 ind_n + 3*tmc_params%dim_per_elem - 1), &
836 cell=tmc_params%cell, box_scale=elem%box_scale)
837 IF (dist_tmp .LT. disto(mol_tmp)) disto(mol_tmp) = dist_tmp
840 END DO list_distances
845 IF (donor_acceptor .EQ. proton_acceptor)
THEN
846 neighbor_mol(mol_tmp) = minloc(disth1(:), 1)
847 neighbor_mol(mol_tmp + 1) = minloc(disth2(:), 1)
849 IF (neighbor_mol(mol_tmp) .EQ. neighbor_mol(mol_tmp + 1))
THEN
850 disth1(neighbor_mol(mol_tmp)) = huge(disth1(1))
851 disth2(neighbor_mol(mol_tmp + 1)) = huge(disth2(1))
852 IF (minval(disth1(:), 1) .LT. minval(disth2(:), 1))
THEN
853 neighbor_mol(mol_tmp) = minloc(disth1(:), 1)
855 neighbor_mol(mol_tmp + 1) = minloc(disth2(:), 1)
858 mol_tmp = mol_tmp + 2
862 IF (donor_acceptor .EQ. proton_donor)
THEN
863 neighbor_mol(mol_tmp) = minloc(disto(:), 1)
864 disto(neighbor_mol(mol_tmp)) = huge(disto(1))
865 neighbor_mol(mol_tmp + 1) = minloc(disto(:), 1)
869 rnd = rng_stream%next()
871 mol_tmp = neighbor_mol(int(rnd*
SIZE(neighbor_mol(:))) + 1)
879 CALL timestop(handle)
880 END SUBROUTINE find_nearest_proton_acceptor_donator
892 FUNCTION check_donor_acceptor(elem, i_orig, i_neighbor, tmc_params) &
893 result(donor_acceptor)
894 TYPE(tree_type),
POINTER :: elem
895 INTEGER :: i_orig, i_neighbor
896 TYPE(tmc_param_type),
POINTER :: tmc_params
897 INTEGER :: donor_acceptor
899 REAL(kind=
dp),
DIMENSION(4) :: distances
901 cpassert(
ASSOCIATED(elem))
902 cpassert(i_orig .GE. 1 .AND. i_orig .LE.
SIZE(elem%pos))
903 cpassert(i_neighbor .GE. 1 .AND. i_neighbor .LE.
SIZE(elem%pos))
904 cpassert(
ASSOCIATED(tmc_params))
908 x1=elem%pos(i_neighbor:i_neighbor + tmc_params%dim_per_elem - 1), &
909 x2=elem%pos(i_orig + tmc_params%dim_per_elem: &
910 i_orig + 2*tmc_params%dim_per_elem - 1), &
911 cell=tmc_params%cell, box_scale=elem%box_scale)
914 x1=elem%pos(i_neighbor:i_neighbor + tmc_params%dim_per_elem - 1), &
915 x2=elem%pos(i_orig + 2*tmc_params%dim_per_elem: &
916 i_orig + 3*tmc_params%dim_per_elem - 1), &
917 cell=tmc_params%cell, box_scale=elem%box_scale)
920 x1=elem%pos(i_orig:i_orig + tmc_params%dim_per_elem - 1), &
921 x2=elem%pos(i_neighbor + tmc_params%dim_per_elem: &
922 i_neighbor + 2*tmc_params%dim_per_elem - 1), &
923 cell=tmc_params%cell, box_scale=elem%box_scale)
926 x1=elem%pos(i_orig:i_orig + tmc_params%dim_per_elem - 1), &
927 x2=elem%pos(i_neighbor + 2*tmc_params%dim_per_elem: &
928 i_neighbor + 3*tmc_params%dim_per_elem - 1), &
929 cell=tmc_params%cell, box_scale=elem%box_scale)
931 IF (minloc(distances(:), 1) .LE. 2)
THEN
932 donor_acceptor = proton_acceptor
934 donor_acceptor = proton_donor
936 END FUNCTION check_donor_acceptor
948 SUBROUTINE rotate_molecules_in_chain(tmc_params, elem, mol_arr_in, &
950 TYPE(tmc_param_type),
POINTER :: tmc_params
951 TYPE(tree_type),
POINTER :: elem
952 INTEGER,
DIMENSION(:) :: mol_arr_in
953 INTEGER :: donor_acceptor
955 CHARACTER(LEN=*),
PARAMETER :: routinen =
'rotate_molecules_in_chain'
957 INTEGER :: h_offset, handle, i, ind
958 INTEGER,
DIMENSION(:),
POINTER :: ind_arr
959 REAL(kind=
dp) :: dihe_angle, dist_near, tmp
960 REAL(kind=
dp),
DIMENSION(3) :: rot_axis, tmp_1, tmp_2, vec_1o, &
961 vec_2h_f, vec_2h_m, vec_2o, vec_3o, &
963 TYPE(cell_type),
POINTER :: tmp_cell
965 NULLIFY (ind_arr, tmp_cell)
967 cpassert(
ASSOCIATED(tmc_params))
968 cpassert(
ASSOCIATED(elem))
971 CALL timeset(routinen, handle)
973 ALLOCATE (ind_arr(0:
SIZE(mol_arr_in) + 1))
974 DO i = 1,
SIZE(mol_arr_in)
975 CALL get_mol_indeces(tmc_params=tmc_params, mol_arr=elem%mol, &
977 start_ind=ind_arr(i), end_ind=ind)
979 ind_arr(0) = ind_arr(
SIZE(ind_arr) - 2)
980 ind_arr(
SIZE(ind_arr) - 1) = ind_arr(1)
985 scaled_cell=tmp_cell)
988 DO i = 1,
SIZE(ind_arr) - 2
990 vec_1o(:) = elem%pos(ind_arr(i - 1):ind_arr(i - 1) + tmc_params%dim_per_elem - 1)
991 vec_2o(:) = elem%pos(ind_arr(i):ind_arr(i) + tmc_params%dim_per_elem - 1)
992 vec_3o(:) = elem%pos(ind_arr(i + 1):ind_arr(i + 1) + tmc_params%dim_per_elem - 1)
998 x1=elem%pos(ind_arr(i + donor_acceptor): &
999 ind_arr(i + donor_acceptor) + tmc_params%dim_per_elem - 1), &
1000 x2=elem%pos(ind_arr(i) + tmc_params%dim_per_elem: &
1001 ind_arr(i) + 2*tmc_params%dim_per_elem - 1), &
1002 cell=tmc_params%cell, box_scale=elem%box_scale) &
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) + 2*tmc_params%dim_per_elem: &
1008 ind_arr(i) + 3*tmc_params%dim_per_elem - 1), &
1009 cell=tmc_params%cell, box_scale=elem%box_scale) &
1011 vec_2h_m = elem%pos(ind_arr(i) + tmc_params%dim_per_elem: &
1012 ind_arr(i) + 2*tmc_params%dim_per_elem - 1)
1013 vec_2h_f = elem%pos(ind_arr(i) + 2*tmc_params%dim_per_elem: &
1014 ind_arr(i) + 3*tmc_params%dim_per_elem - 1)
1017 vec_2h_f = elem%pos(ind_arr(i) + tmc_params%dim_per_elem: &
1018 ind_arr(i) + 2*tmc_params%dim_per_elem - 1)
1019 vec_2h_m = elem%pos(ind_arr(i) + 2*tmc_params%dim_per_elem: &
1020 ind_arr(i) + 3*tmc_params%dim_per_elem - 1)
1027 tmp_1 =
pbc(vec_2o - vec_1o, tmp_cell)
1028 tmp_2 =
pbc(vec_3o - vec_2h_f, tmp_cell)
1030 dihe_angle = donor_acceptor*
dihedral_angle(tmp_1, vec_2h_f - vec_2o, tmp_2)
1031 DO ind = ind_arr(i), ind_arr(i) + tmc_params%dim_per_elem*3 - 1, tmc_params%dim_per_elem
1035 ind + tmc_params%dim_per_elem - 1) - vec_2o, &
1036 dihe_angle, vec_2h_f - vec_2o)
1040 elem%pos(ind:ind + tmc_params%dim_per_elem - 1) = vec_2o + vec_rotated
1048 dist_near = huge(dist_near)
1049 search_o_loop:
DO ind = 1,
SIZE(elem%pos), &
1050 tmc_params%dim_per_elem*3
1051 IF (ind .EQ. ind_arr(i)) cycle search_o_loop
1053 x2=elem%pos(ind:ind + tmc_params%dim_per_elem - 1), &
1054 cell=tmc_params%cell, box_scale=elem%box_scale)
1055 IF (dist_near .GT. tmp)
THEN
1057 vec_4o = elem%pos(ind:ind + tmc_params%dim_per_elem - 1)
1059 END DO search_o_loop
1060 rot_axis =
pbc(-vec_2o(:) + vec_4o(:), tmp_cell)
1061 tmp_1 =
pbc(vec_2o - vec_1o, tmp_cell)
1062 tmp_2 =
pbc(vec_3o - vec_4o, tmp_cell)
1063 dihe_angle = donor_acceptor*
dihedral_angle(tmp_1, rot_axis, tmp_2)
1064 vec_rotated =
rotate_vector(vec_2h_m - vec_2o, dihe_angle, rot_axis)
1066 elem%pos(ind_arr(i) + h_offset*tmc_params%dim_per_elem: &
1067 ind_arr(i) + (h_offset + 1)*tmc_params%dim_per_elem - 1) &
1068 = vec_2o + vec_rotated
1069 vec_rotated =
rotate_vector(vec_2h_f - vec_2o, dihe_angle, rot_axis)
1070 IF (h_offset .EQ. 1)
THEN
1075 elem%pos(ind_arr(i) + h_offset*tmc_params%dim_per_elem: &
1076 ind_arr(i) + (h_offset + 1)*tmc_params%dim_per_elem - 1) &
1077 = vec_2o + vec_rotated
1080 DEALLOCATE (tmp_cell)
1081 DEALLOCATE (ind_arr)
1083 CALL timestop(handle)
1084 END SUBROUTINE rotate_molecules_in_chain
1100 SUBROUTINE change_volume(conf, T_ind, move_types, rng_stream, tmc_params, &
1102 TYPE(tree_type),
POINTER :: conf
1104 TYPE(tmc_move_type),
POINTER :: move_types
1105 TYPE(rng_stream_type),
INTENT(INOUT) :: rng_stream
1106 TYPE(tmc_param_type),
POINTER :: tmc_params
1107 LOGICAL :: mv_cen_of_mass
1109 CHARACTER(LEN=*),
PARAMETER :: routinen =
'change_volume'
1111 INTEGER ::
atom, dir, handle, ind, ind_e, mol
1112 REAL(kind=
dp) :: rnd, vol
1113 REAL(kind=
dp),
DIMENSION(3) :: box_length_new, box_length_orig, &
1115 REAL(kind=
dp),
DIMENSION(:),
POINTER :: disp, scaling
1117 NULLIFY (scaling, disp)
1119 cpassert(
ASSOCIATED(conf))
1120 cpassert(
ASSOCIATED(move_types))
1121 cpassert(
ASSOCIATED(tmc_params))
1122 cpassert(t_ind .GT. 0 .AND. t_ind .LE. tmc_params%nr_temp)
1123 cpassert(tmc_params%dim_per_elem .EQ. 3)
1124 cpassert(tmc_params%cell%orthorhombic)
1127 CALL timeset(routinen, handle)
1129 ALLOCATE (scaling(tmc_params%dim_per_elem))
1130 ALLOCATE (disp(tmc_params%dim_per_elem))
1132 box_scale_old(:) = conf%box_scale
1134 CALL get_scaled_cell(cell=tmc_params%cell, box_scale=conf%box_scale, &
1139 IF (tmc_params%v_isotropic)
THEN
1140 CALL get_scaled_cell(cell=tmc_params%cell, box_scale=conf%box_scale, &
1141 abc=box_length_new, vol=vol)
1142 rnd = rng_stream%next()
1144 box_length_new(:) = vol**(1/real(3, kind=
dp))
1146 CALL get_scaled_cell(cell=tmc_params%cell, box_scale=conf%box_scale, &
1147 abc=box_length_new, vol=vol)
1148 rnd = rng_stream%next()
1150 rnd = rng_stream%next()
1151 dir = 1 + int(rnd*3)
1152 box_length_new(dir) = 1.0_dp
1153 box_length_new(dir) = vol/product(box_length_new(:))
1159 IF (tmc_params%v_isotropic)
THEN
1160 rnd = rng_stream%next()
1161 box_length_new(:) = box_length_new(:) + &
1162 (rnd - 0.5_dp)*2.0_dp* &
1166 rnd = rng_stream%next()
1167 dir = 1 + int(rnd*3)
1168 rnd = rng_stream%next()
1169 box_length_new(dir) = box_length_new(dir) + &
1170 (rnd - 0.5_dp)*2.0_dp* &
1178 box_scale=scaling, &
1179 abc=box_length_orig)
1181 conf%box_scale(:) = box_length_new(:)/box_length_orig(:)
1183 scaling(:) = conf%box_scale(:)/box_scale_old(:)
1185 IF (mv_cen_of_mass .EQV. .false.)
THEN
1187 DO atom = 1,
SIZE(conf%pos), tmc_params%dim_per_elem
1188 conf%pos(
atom:
atom + tmc_params%dim_per_elem - 1) = &
1189 conf%pos(
atom:
atom + tmc_params%dim_per_elem - 1)*scaling(:)
1192 DO mol = 1, maxval(conf%mol(:))
1195 cpassert(
ASSOCIATED(tmc_params%atoms))
1197 CALL get_mol_indeces(tmc_params=tmc_params, mol_arr=conf%mol, mol=mol, &
1198 start_ind=ind, end_ind=ind_e)
1200 pos=conf%pos(ind:ind_e + tmc_params%dim_per_elem - 1), &
1201 atoms=tmc_params%atoms(int(ind/real(tmc_params%dim_per_elem, kind=
dp)) + 1: &
1202 int(ind_e/real(tmc_params%dim_per_elem, kind=
dp)) + 1), &
1205 disp(:) = disp(:)*(scaling(:) - 1.0_dp)
1207 DO atom = ind, ind_e + tmc_params%dim_per_elem - 1, tmc_params%dim_per_elem
1208 conf%pos(
atom:
atom + tmc_params%dim_per_elem - 1) = &
1209 conf%pos(
atom:
atom + tmc_params%dim_per_elem - 1) + disp(:)
1214 DEALLOCATE (scaling)
1218 CALL timestop(handle)
1219 END SUBROUTINE change_volume
1230 SUBROUTINE swap_atoms(conf, move_types, rng_stream, tmc_params)
1231 TYPE(tree_type),
POINTER :: conf
1232 TYPE(tmc_move_type),
POINTER :: move_types
1233 TYPE(rng_stream_type),
INTENT(INOUT) :: rng_stream
1234 TYPE(tmc_param_type),
POINTER :: tmc_params
1236 INTEGER :: a_1, a_2, ind_1, ind_2
1238 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: pos_tmp
1240 cpassert(
ASSOCIATED(conf))
1241 cpassert(
ASSOCIATED(move_types))
1242 cpassert(
ASSOCIATED(tmc_params))
1243 cpassert(
ASSOCIATED(tmc_params%atoms))
1246 atom_search_loop:
DO
1248 a_1 = int(
SIZE(conf%pos)/real(tmc_params%dim_per_elem, kind=
dp)* &
1249 rng_stream%next()) + 1
1251 a_2 = int(
SIZE(conf%pos)/real(tmc_params%dim_per_elem, kind=
dp)* &
1252 rng_stream%next()) + 1
1254 IF (tmc_params%atoms(a_1)%name .NE. tmc_params%atoms(a_2)%name)
THEN
1256 IF (
ASSOCIATED(move_types%atom_lists))
THEN
1257 DO ind_1 = 1,
SIZE(move_types%atom_lists)
1258 IF (any(move_types%atom_lists(ind_1)%atoms(:) .EQ. &
1259 tmc_params%atoms(a_1)%name) .AND. &
1260 any(move_types%atom_lists(ind_1)%atoms(:) .EQ. &
1261 tmc_params%atoms(a_2)%name))
THEN
1263 EXIT atom_search_loop
1268 EXIT atom_search_loop
1271 END DO atom_search_loop
1274 ALLOCATE (pos_tmp(tmc_params%dim_per_elem))
1275 ind_1 = (a_1 - 1)*tmc_params%dim_per_elem + 1
1276 pos_tmp(:) = conf%pos(ind_1:ind_1 + tmc_params%dim_per_elem - 1)
1277 ind_2 = (a_2 - 1)*tmc_params%dim_per_elem + 1
1278 conf%pos(ind_1:ind_1 + tmc_params%dim_per_elem - 1) = &
1279 conf%pos(ind_2:ind_2 + tmc_params%dim_per_elem - 1)
1280 conf%pos(ind_2:ind_2 + tmc_params%dim_per_elem - 1) = pos_tmp(:)
1281 DEALLOCATE (pos_tmp)
1283 END SUBROUTINE swap_atoms
subroutine pbc(r, r_pbc, s, s_pbc, a, b, c, alpha, beta, gamma, debug, info, pbc0, h, hinv)
...
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...