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 .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 "// &
 
  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)
 
  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
 
  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)
 
  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
 
  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
 
  604      REAL(kind=
dp), 
INTENT(IN)                          :: phi, temp
 
  605      LOGICAL                                            :: rnd_sign_change
 
  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, &
 
  655      LOGICAL                                            :: short_loop
 
  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__, &
 
  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)
 
  756      INTEGER                                            :: mol, donor_acceptor
 
  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)
 
  895      INTEGER                                            :: i_orig, i_neighbor
 
  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, &
 
  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, &
 
  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, &
 
 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)
 
 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
 
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.