38 #include "../base/base_uses.f90"
44 LOGICAL,
PRIVATE,
PARAMETER :: debug_this_module = .true.
45 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'helium_common'
82 TYPE(helium_solvent_type),
INTENT(IN) :: helium
83 REAL(kind=
dp),
DIMENSION(3),
INTENT(INOUT) :: r
84 LOGICAL,
OPTIONAL :: enforce
86 REAL(kind=
dp) :: cell_size, cell_size_inv, corr, rx, ry, &
89 IF (.NOT. (helium%periodic .OR.
PRESENT(enforce)))
RETURN
91 cell_size = helium%cell_size
92 cell_size_inv = helium%cell_size_inv
94 rx = r(1)*cell_size_inv
96 rx = rx - real(int(rx + 0.5_dp),
dp)
97 ELSEIF (rx < -0.5_dp)
THEN
98 rx = rx - real(int(rx - 0.5_dp),
dp)
101 ry = r(2)*cell_size_inv
102 IF (ry > 0.5_dp)
THEN
103 ry = ry - real(int(ry + 0.5_dp),
dp)
104 ELSEIF (ry < -0.5_dp)
THEN
105 ry = ry - real(int(ry - 0.5_dp),
dp)
108 rz = r(3)*cell_size_inv
109 IF (rz > 0.5_dp)
THEN
110 rz = rz - real(int(rz + 0.5_dp),
dp)
111 ELSEIF (rz < -0.5_dp)
THEN
112 rz = rz - real(int(rz - 0.5_dp),
dp)
117 IF (rx > 0.0_dp)
THEN
124 IF (ry > 0.0_dp)
THEN
131 IF (rz > 0.0_dp)
THEN
138 IF (corr > 0.75_dp)
THEN
163 PURE FUNCTION helium_pbc_r2(helium, r)
165 TYPE(helium_solvent_type),
INTENT(IN) :: helium
166 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: r
167 REAL(kind=
dp) :: helium_pbc_r2
169 REAL(kind=
dp) :: cell_size_inv, corr, rx, ry, rz
171 IF (helium%periodic)
THEN
172 cell_size_inv = helium%cell_size_inv
173 rx = abs(r(1)*cell_size_inv)
174 rx = abs(rx - real(int(rx + 0.5_dp),
dp))
175 ry = abs(r(2)*cell_size_inv)
176 ry = abs(ry - real(int(ry + 0.5_dp),
dp))
177 rz = abs(r(3)*cell_size_inv)
178 rz = abs(rz - real(int(rz + 0.5_dp),
dp))
180 corr = rx + ry + rz - 0.75_dp
181 IF (corr < 0.0_dp) corr = 0.0_dp
182 helium_pbc_r2 = helium%cell_size**2*(rx*rx + ry*ry + rz*rz - corr)
184 helium_pbc_r2 = helium%cell_size**2*(rx*rx + ry*ry + rz*rz)
187 helium_pbc_r2 = (r(1)*r(1) + r(2)*r(2) + r(3)*r(3))
189 END FUNCTION helium_pbc_r2
206 TYPE(helium_solvent_type),
INTENT(IN) :: helium
207 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a, b
208 REAL(kind=
dp),
DIMENSION(3),
INTENT(OUT) :: c
212 c(:) = a(:) + 0.5_dp*c(:)
224 SUBROUTINE helium_calc_atom_cycle_length(helium)
226 TYPE(helium_solvent_type),
INTENT(IN) :: helium
228 CHARACTER(len=*),
PARAMETER :: routinen =
'helium_calc_atom_cycle_length'
230 CHARACTER(len=default_string_length) :: err_str
231 INTEGER :: clen, curr_idx, handle, ia, start_idx
232 INTEGER,
DIMENSION(:),
POINTER :: atoms_in_cycle
233 LOGICAL :: atoms_left, path_end_reached
234 LOGICAL,
DIMENSION(:),
POINTER :: atom_was_used
236 CALL timeset(routinen, handle)
238 NULLIFY (atoms_in_cycle)
239 atoms_in_cycle => helium%itmp_atoms_1d
240 atoms_in_cycle(:) = 0
242 NULLIFY (atom_was_used)
243 atom_was_used => helium%ltmp_atoms_1d
244 atom_was_used(:) = .false.
246 helium%atom_plength(:) = 0
251 path_end_reached = .false.
253 DO ia = 1, helium%atoms
255 atoms_in_cycle(clen) = curr_idx
256 atom_was_used(curr_idx) = .true.
259 curr_idx = helium%permutation(curr_idx)
260 IF (curr_idx .EQ. start_idx)
THEN
261 path_end_reached = .true.
265 err_str =
"Permutation path is not cyclic."
266 IF (.NOT. path_end_reached)
THEN
272 helium%atom_plength(atoms_in_cycle(ia)) = clen
277 DO ia = 1, helium%atoms
278 IF (.NOT. atom_was_used(ia))
THEN
285 IF (.NOT. atoms_left)
EXIT
288 atoms_in_cycle(:) = 0
289 NULLIFY (atoms_in_cycle)
290 atom_was_used(:) = .false.
291 NULLIFY (atom_was_used)
293 CALL timestop(handle)
295 END SUBROUTINE helium_calc_atom_cycle_length
308 FUNCTION helium_calc_cycles(permutation)
RESULT(cycles)
310 INTEGER,
DIMENSION(:),
POINTER :: permutation
311 TYPE(int_arr_ptr),
DIMENSION(:),
POINTER :: cycles
313 INTEGER :: curat, ncycl, nsize, nused
314 INTEGER,
DIMENSION(:),
POINTER :: cur_cycle, used_indices
315 TYPE(int_arr_ptr),
DIMENSION(:),
POINTER :: my_cycles
317 nsize =
SIZE(permutation)
320 ALLOCATE (my_cycles(nsize))
326 DO WHILE (curat .LE. nsize)
332 nused = nused +
SIZE(cur_cycle)
333 CALL reallocate(used_indices, 1, nused)
334 used_indices(nused -
SIZE(cur_cycle) + 1:nused) = cur_cycle(1:
SIZE(cur_cycle))
338 my_cycles(ncycl)%iap => cur_cycle
344 DO WHILE (any(used_indices .EQ. curat))
350 DEALLOCATE (used_indices)
351 NULLIFY (used_indices)
354 ALLOCATE (cycles(ncycl))
355 cycles(1:ncycl) = my_cycles(1:ncycl)
357 DEALLOCATE (my_cycles)
360 END FUNCTION helium_calc_cycles
371 TYPE(helium_solvent_type),
INTENT(IN) :: helium
373 CHARACTER(len=*),
PARAMETER :: routinen =
'helium_calc_rho'
375 CHARACTER(len=default_string_length) :: msgstr
376 INTEGER :: aa, bx, by, bz, handle, ia, ib, ic, id, &
377 ii, ir, n_out_of_range, nbin
378 INTEGER,
DIMENSION(3) :: nw
379 INTEGER,
DIMENSION(:),
POINTER :: cycl_len
380 LOGICAL :: ltmp1, ltmp2, ltmp3
381 REAL(kind=
dp) :: invd3r, invdr, invp, rtmp
382 REAL(kind=
dp),
DIMENSION(3) :: maxr_half, r, vlink, vtotal, wn
383 TYPE(int_arr_ptr),
DIMENSION(:),
POINTER :: cycles
385 CALL timeset(routinen, handle)
387 maxr_half(:) = helium%rho_maxr/2.0_dp
388 invdr = 1.0_dp/helium%rho_delr
389 invd3r = invdr*invdr*invdr
390 invp = 1.0_dp/real(helium%beads,
dp)
391 nbin = helium%rho_nbin
393 CALL helium_calc_atom_cycle_length(helium)
395 cycl_len => helium%atom_plength
398 IF (.NOT. helium%rho_property(ir)%is_calculated)
THEN
406 ii = helium%rho_property(ir)%component_index(1)
407 helium%rho_incr(ii, :, :) = invp
411 DO ia = 1, helium%atoms
412 DO ib = 1, helium%beads
413 vlink(:) = helium_link_projected_area(helium, ia, ib)
415 ii = helium%rho_property(ir)%component_index(ic)
436 ii = helium%rho_property(ir)%component_index(id)
437 helium%rho_incr(ii, :, :) = 0.0_dp
440 cycles => helium_calc_cycles(helium%permutation)
441 DO ic = 1,
SIZE(cycles)
442 wn = helium_cycle_winding_number(helium, cycles(ic)%iap, helium%pos)
443 DO ia = 1,
SIZE(cycles(ic)%iap)
444 aa = cycles(ic)%iap(ia)
445 DO ib = 1, helium%beads
446 vlink(:) = helium_link_winding_number(helium, aa, ib)
448 IF (abs(wn(id)) .GT. 100.0_dp*epsilon(0.0_dp))
THEN
449 ii = helium%rho_property(ir)%component_index(id)
461 ii = helium%rho_property(ir)%component_index(id)
462 helium%rho_incr(ii, :, :) = 0.0_dp
465 cycles => helium_calc_cycles(helium%permutation)
468 DO ic = 1,
SIZE(cycles)
469 wn = helium_cycle_winding_number(helium, cycles(ic)%iap, helium%pos)
471 IF (abs(wn(id)) .GT. 100.0_dp*epsilon(0.0_dp))
THEN
472 nw(id) = nw(id) +
SIZE(cycles(ic)%iap)
477 DO ic = 1,
SIZE(cycles)
478 wn = helium_cycle_winding_number(helium, cycles(ic)%iap, helium%pos)
480 IF (abs(wn(id)) .GT. 100.0_dp*epsilon(0.0_dp))
THEN
481 DO ia = 1,
SIZE(cycles(ic)%iap)
482 aa = cycles(ic)%iap(ia)
483 DO ib = 1, helium%beads
484 IF (nw(id) .GT. 0)
THEN
485 ii = helium%rho_property(ir)%component_index(id)
486 rtmp = invp/real(nw(id),
dp)
498 DO ia = 1, helium%atoms
499 DO ib = 1, helium%beads
500 vlink(:) = helium_link_moment_of_inertia(helium, ia, ib)
502 ii = helium%rho_property(ir)%component_index(ic)
516 helium%rho_inst(:, :, :, :) = 0.0_dp
517 DO ia = 1, helium%atoms
519 DO ib = 1, helium%beads
521 r(:) = helium%pos(:, ia, ib) - helium%center(:)
525 bx = int((r(1) + maxr_half(1))*invdr) + 1
526 by = int((r(2) + maxr_half(2))*invdr) + 1
527 bz = int((r(3) + maxr_half(3))*invdr) + 1
529 ltmp1 = (0 .LT. bx) .AND. (bx .LE. nbin)
530 ltmp2 = (0 .LT. by) .AND. (by .LE. nbin)
531 ltmp3 = (0 .LT. bz) .AND. (bz .LE. nbin)
532 IF (ltmp1 .AND. ltmp2 .AND. ltmp3)
THEN
535 DO ic = 1, helium%rho_num_act
536 helium%rho_inst(ic, bx, by, bz) = helium%rho_inst(ic, bx, by, bz) + helium%rho_incr(ic, ia, ib)
539 n_out_of_range = n_out_of_range + 1
544 helium%rho_inst(:, :, :, :) = helium%rho_inst(:, :, :, :)*invd3r
548 WRITE (msgstr, *) n_out_of_range
549 msgstr =
"Number of bead positions out of range: "//trim(adjustl(msgstr))
550 IF (n_out_of_range .GT. 0)
THEN
554 CALL timestop(handle)
567 SUBROUTINE helium_norm_rho(helium, rho)
569 TYPE(helium_solvent_type),
INTENT(IN) :: helium
570 REAL(kind=
dp),
DIMENSION(:, :, :, :),
POINTER :: rho
572 CHARACTER(len=*),
PARAMETER :: routinen =
'helium_norm_rho', &
573 routinep = modulen//
':'//routinen
575 INTEGER :: ix, iy, iz, ndim
576 REAL(kind=
dp) :: invatoms, rx, ry, rz
577 REAL(kind=
dp),
DIMENSION(3) :: invmoit, invrperp, ro
579 SELECT CASE (helium%supest_denominator)
582 invatoms = 1.0_dp/real(helium%atoms,
dp)
583 rho(2, :, :, :) = rho(2, :, :, :)*invatoms
584 rho(3, :, :, :) = rho(3, :, :, :)*invatoms
585 rho(4, :, :, :) = rho(4, :, :, :)*invatoms
588 invmoit(:) = real(helium%atoms,
dp)/helium%mominer%ravr(:)
589 rho(2, :, :, :) = rho(2, :, :, :)*invmoit(1)
590 rho(3, :, :, :) = rho(3, :, :, :)*invmoit(2)
591 rho(4, :, :, :) = rho(4, :, :, :)*invmoit(3)
594 ndim = helium%rho_nbin
595 ro(:) = helium%center(:) - 0.5_dp*(helium%rho_maxr - helium%rho_delr)
599 rx = ro(1) + real(ix - 1,
dp)*helium%rho_delr
600 ry = ro(2) + real(iy - 1,
dp)*helium%rho_delr
601 rz = ro(3) + real(iz - 1,
dp)*helium%rho_delr
602 invrperp(1) = 1.0_dp/(ry*ry + rz*rz)
603 invrperp(2) = 1.0_dp/(rz*rz + rx*rx)
604 invrperp(3) = 1.0_dp/(rx*rx + ry*ry)
605 rho(2, ix, iy, iz) = rho(2, ix, iy, iz)*invrperp(1)
606 rho(3, ix, iy, iz) = rho(3, ix, iy, iz)*invrperp(2)
607 rho(4, ix, iy, iz) = rho(4, ix, iy, iz)*invrperp(3)
617 END SUBROUTINE helium_norm_rho
631 TYPE(helium_solvent_type),
INTENT(IN) :: helium
633 CHARACTER(len=*),
PARAMETER :: routinen =
'helium_calc_rdf'
635 CHARACTER(len=default_string_length) :: msgstr
636 INTEGER :: bin, handle, ia, ib, ic, ind_hehe, &
638 REAL(kind=
dp) :: invdr, nideal, ri, rlower, rupper
639 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: pref
640 REAL(kind=
dp),
DIMENSION(3) :: r, r0
642 CALL timeset(routinen, handle)
644 invdr = 1.0_dp/helium%rdf_delr
645 nbin = helium%rdf_nbin
647 helium%rdf_inst(:, :) = 0.0_dp
651 IF (helium%rdf_he_he)
THEN
653 DO ib = 1, helium%beads
654 DO ia = 1, helium%atoms
655 r0(:) = helium%pos(:, ia, ib)
657 DO ic = 1, helium%atoms
659 r(:) = helium%pos(:, ic, ib) - r0(:)
661 ri = sqrt(r(1)*r(1) + r(2)*r(2) + r(3)*r(3))
662 bin = int(ri*invdr) + 1
663 IF ((0 .LT. bin) .AND. (bin .LE. nbin))
THEN
665 helium%rdf_inst(ind_hehe, bin) = helium%rdf_inst(ind_hehe, bin) + 1.0_dp
667 n_out_of_range = n_out_of_range + 1
675 IF (helium%solute_present .AND. helium%rdf_sol_he)
THEN
676 DO ib = 1, helium%beads
677 DO ia = 1, helium%solute_atoms
678 r0(:) = helium%rdf_centers(ib, 3*(ia - 1) + 1:3*(ia - 1) + 3)
680 DO ic = 1, helium%atoms
681 r(:) = helium%pos(:, ic, ib) - r0(:)
683 ri = sqrt(r(1)*r(1) + r(2)*r(2) + r(3)*r(3))
684 bin = int(ri*invdr) + 1
685 IF ((0 .LT. bin) .AND. (bin .LE. nbin))
THEN
687 helium%rdf_inst(ind_hehe + ia, bin) = helium%rdf_inst(ind_hehe + ia, bin) + 1.0_dp
689 n_out_of_range = n_out_of_range + 1
699 IF (.NOT. helium%periodic)
THEN
700 IF (n_out_of_range .GT. 0)
THEN
701 WRITE (msgstr, *) n_out_of_range
702 msgstr =
"Number of bead positions out of range: "//trim(adjustl(msgstr))
708 ALLOCATE (pref(helium%rdf_num))
710 IF (helium%periodic)
THEN
712 pref(:) = helium%density*helium%beads*helium%atoms
714 IF (helium%rdf_he_he)
THEN
715 pref(1) = pref(1)/helium%atoms*max(helium%atoms - 1, 1)
720 pref(:) = 0.5_dp*helium%rdf_inst(:, 1)
721 DO bin = 2, helium%rdf_nbin - 1
722 pref(:) = pref(:) + helium%rdf_inst(:, bin)
724 pref(:) = pref(:) + 0.5_dp*helium%rdf_inst(:, helium%rdf_nbin)
727 pref(:) = pref(:)/helium%atoms
729 IF (helium%rdf_he_he)
THEN
730 pref(1) = pref(1)*helium%atoms/max(helium%atoms - 1, 1)
734 DO bin = 1, helium%rdf_nbin
735 rlower = real(bin - 1,
dp)*helium%rdf_delr
736 rupper = rlower + helium%rdf_delr
737 nideal = (rupper**3 - rlower**3)*4.0_dp*
pi/3.0_dp
738 helium%rdf_inst(:, bin) = helium%rdf_inst(:, bin)/nideal
741 pref(:) = 1.0_dp/pref(:)
742 DO ia = 1, helium%rdf_num
743 helium%rdf_inst(ia, :) = helium%rdf_inst(ia, :)*pref(ia)
748 CALL timestop(handle)
764 TYPE(helium_solvent_type),
INTENT(INOUT) :: helium
768 helium%plength_inst(:) = 0.0_dp
769 DO i = 1, helium%atoms
770 j = helium%permutation(i)
775 j = helium%permutation(j)
777 helium%plength_inst(k) = helium%plength_inst(k) + 1
779 helium%plength_inst(:) = helium%plength_inst(:)/helium%atoms
796 TYPE(helium_solvent_type),
INTENT(INOUT) :: helium
797 INTEGER,
INTENT(IN) :: nslices
799 INTEGER :: b, i, j, k, n
805 IF ((i >= b) .OR. (i < 1))
RETURN
806 helium%relrot = mod(helium%relrot + i, b)
808 helium%work(:, :, k) = helium%pos(:, :, k)
811 helium%pos(:, :, k - i) = helium%pos(:, :, k)
815 helium%pos(:, j, b - i + k) = helium%work(:, helium%permutation(j), k)
833 TYPE(helium_solvent_type),
INTENT(INOUT) :: helium
834 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: r, rp
835 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:), &
836 INTENT(INOUT) :: work
837 LOGICAL,
INTENT(IN),
OPTIONAL :: action
840 INTEGER :: i, j, nsp, tline
842 REAL(kind=
dp) :: a, ar, arp, b, h26, q, s, v, z
843 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :, :), &
844 POINTER :: offdiagsplines
845 TYPE(spline_data_type),
POINTER :: endpspline
847 endpspline => helium%u0
848 offdiagsplines => helium%uoffdiag
850 IF (
PRESENT(action))
THEN
851 IF (.NOT. action)
THEN
852 endpspline => helium%e0
853 offdiagsplines => helium%eoffdiag
858 ar = sqrt(helium_pbc_r2(helium, r))
859 arp = sqrt(helium_pbc_r2(helium, rp))
861 IF (helium%periodic .AND. ((ar > 0.5_dp*helium%cell_size) &
862 .OR. (arp > 0.5_dp*helium%cell_size)))
THEN
864 IF (arp > 0.5_dp*helium%cell_size)
THEN
865 IF (nocut) v = v +
helium_spline(endpspline, 0.5_dp*helium%cell_size)
869 IF (ar > 0.5_dp*helium%cell_size)
THEN
870 IF (nocut) v = v +
helium_spline(endpspline, 0.5_dp*helium%cell_size)
878 s = helium_pbc_r2(helium, r - rp)
879 q = 0.5_dp*(ar + arp)
881 nsp = ((helium%pdx + 2)*(helium%pdx + 1))/2 - 1
887 work(1:nsp) = a*offdiagsplines(1:nsp, 1, 1) + b*(offdiagsplines(1:nsp, 1, 2) - &
888 offdiagsplines(1:nsp, 2, 2)*endpspline%h26)
889 ELSE IF (q > endpspline%xn)
THEN
890 b = b*(q - endpspline%xn) + 1.0_dp
893 work(1:nsp) = b*offdiagsplines(1:nsp, 1, tline) + a*(offdiagsplines(1:nsp, 1, tline - 1) - &
894 offdiagsplines(1:nsp, 2, tline - 1)*endpspline%h26)
897 tline = int(1.0_dp - a)
898 a = a + real(tline, kind=
dp)
900 h26 = -a*b*endpspline%h26
901 work(1:nsp) = a*offdiagsplines(1:nsp, 1, tline) + b*offdiagsplines(1:nsp, 1, tline + 1) + &
902 h26*((a + 1.0_dp)*offdiagsplines(1:nsp, 2, tline) + (b + 1.0_dp)* &
903 offdiagsplines(1:nsp, 2, tline + 1))
914 b = b*s + work(tline)
937 TYPE(helium_solvent_type),
INTENT(INOUT) :: helium
938 INTEGER,
INTENT(IN) :: nchain
939 REAL(kind=
dp),
DIMENSION(3, nchain),
INTENT(INOUT) :: rchain
940 REAL(kind=
dp),
DIMENSION(nchain),
INTENT(INOUT) :: aij
941 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: vcoef
942 LOGICAL,
INTENT(IN),
OPTIONAL :: energy
945 INTEGER :: chainpos, i, j, ndim, nsp, tline
947 REAL(kind=
dp) :: a, ar, arp, b, ch, h26, q, s, totalv, v, &
949 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :, :), &
950 POINTER :: offdiagsplines
951 TYPE(spline_data_type),
POINTER :: endpspline
953 endpspline => helium%u0
954 offdiagsplines => helium%uoffdiag
956 IF (
PRESENT(energy))
THEN
958 endpspline => helium%e0
959 offdiagsplines => helium%eoffdiag
965 nsp = ((ndim + 2)*(ndim + 1))/2 - 1
966 vcoef(1:nsp + 1) = 0.0_dp
969 aij(i) = sqrt(helium_pbc_r2(helium, rchain(:, i)))
972 rchain(:, i - 1) = rchain(:, i - 1) - rchain(:, i)
973 rchain(1, i - 1) = helium_pbc_r2(helium, rchain(:, i - 1))
976 IF (helium%periodic)
THEN
977 ch = 0.5_dp*helium%cell_size
982 totalv = totalv + 0.5_dp*
helium_spline(endpspline, min(aij(1), ch))
983 totalv = totalv + 0.5_dp*
helium_spline(endpspline, min(aij(nchain), ch))
990 IF (ar < ch) totalv = totalv + 0.5_dp*
helium_spline(endpspline, ar)
992 IF (ar < ch) totalv = totalv + 0.5_dp*
helium_spline(endpspline, ar)
999 totalv = totalv + 0.5_dp*
helium_spline(endpspline, aij(nchain))
1002 DO chainpos = 1, nchain - 1
1004 arp = aij(chainpos + 1)
1005 IF (helium%periodic .AND. ((ar > 0.5_dp*helium%cell_size) &
1006 .OR. (arp > 0.5_dp*helium%cell_size)))
THEN
1009 q = 0.5_dp*(ar + arp)
1010 s = rchain(1, chainpos)
1017 vcoef(1:nsp) = a*offdiagsplines(1:nsp, 1, 1) + b*(offdiagsplines(1:nsp, 1, 2) - &
1018 offdiagsplines(1:nsp, 2, 2)*endpspline%h26)
1019 ELSE IF (q > endpspline%xn)
THEN
1020 b = b*(q - endpspline%xn) + 1.0_dp
1022 tline = endpspline%n
1023 vcoef(1:nsp) = b*offdiagsplines(1:nsp, 1, tline) + a*(offdiagsplines(1:nsp, 1, tline - 1) - &
1024 offdiagsplines(1:nsp, 2, tline - 1)*endpspline%h26)
1027 tline = int(1.0_dp - a)
1028 a = a + real(tline, kind=
dp)
1030 h26 = -a*b*endpspline%h26
1031 vcoef(1:nsp) = a*offdiagsplines(1:nsp, 1, tline) + b*offdiagsplines(1:nsp, 1, tline + 1) + &
1032 h26*((a + 1.0_dp)*offdiagsplines(1:nsp, 2, tline) + (b + 1.0_dp)* &
1033 offdiagsplines(1:nsp, 2, tline + 1))
1042 b = b*s + vcoef(tline)
1059 TYPE(helium_solvent_type),
INTENT(INOUT) :: helium
1061 INTEGER :: b, c, i, j, k, m, n, nb
1062 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: lens, order
1063 INTEGER,
DIMENSION(:),
POINTER :: perm
1064 INTEGER,
DIMENSION(:, :),
POINTER :: nmatrix
1065 REAL(kind=
dp) :: f, q, t, v
1066 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: p
1067 REAL(kind=
dp),
DIMENSION(3) :: r
1068 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ipmatrix, pmatrix, tmatrix
1069 REAL(kind=
dp),
DIMENSION(:, :, :),
POINTER :: pos
1074 ALLOCATE (order(nb))
1075 ALLOCATE (lens(2*nb))
1076 b = helium%beads - helium%bisection + 1
1077 f = -0.5_dp/(helium%hb2m*helium%tau*helium%bisection)
1078 tmatrix => helium%tmatrix
1079 pmatrix => helium%pmatrix
1080 ipmatrix => helium%ipmatrix
1081 nmatrix => helium%nmatrix
1082 perm => helium%permutation
1087 r(:) = pos(:, i, b) - pos(:, j, 1)
1089 v = v + r(1)*r(1) + r(2)*r(2) + r(3)*r(3)
1092 t = pmatrix(i, perm(i))
1095 tmatrix(i, j) = exp(pmatrix(i, j) - t)
1096 v = v + tmatrix(i, j)
1102 tmatrix(i, j) = tmatrix(i, j)*t
1103 ipmatrix(i, j) = 1.0_dp/tmatrix(i, j)
1147 p(j) = tmatrix(i, j)
1177 IF (p(j) < p(j + 1)) j = j + 1
1208 DO m = nb + 1, 2*nb - 1
1210 IF (p(j) < p(c + 1))
THEN
1220 IF (p(j) < p(c + 1))
THEN
1225 p(m + 1) = v + p(c + 1)
1236 DO m = 2*nb - 2, 1, -1
1237 lens(m) = lens(lens(m)) + 1
1246 v = v + p(j)*lens(j)
1248 print *,
"Expected number of comparisons with i=", i, v
1265 j = nb + 1 + (k - 1)/2
1266 IF (lens(c) > lens(m + 1))
THEN
1267 nmatrix(i, k) = -order(c)
1268 lens(j + 1) = lens(c) - 1
1272 nmatrix(i, k) = m - nb
1273 lens(j + 1) = lens(m + 1) - 1
1278 IF (mod(k, 2) == 1) tmatrix(i, j - nb) = v
1294 DO m = nb - 1, 1, -1
1297 IF (nmatrix(i, 2*m) > 0)
THEN
1298 p(nmatrix(i, 2*m)) = tmatrix(i, m)
1299 tmatrix(i, nmatrix(i, 2*m)) = tmatrix(i, nmatrix(i, 2*m)) + tmatrix(i, m)
1303 IF (nmatrix(i, 2*m - 1) > 0)
THEN
1304 p(nmatrix(i, 2*m - 1)) = p(m)
1305 tmatrix(i, nmatrix(i, 2*m - 1)) = tmatrix(i, nmatrix(i, 2*m - 1)) + p(m)
1314 p(k) = 1.0/ipmatrix(i, k)
1320 v = helium%rng_stream_uniform%next()
1324 IF (tmatrix(i, k) > v)
THEN
1325 k = nmatrix(i, 2*k - 1)
1333 lens(k) = lens(k) + 1
1340 q = abs((lens(j) - c*p(j))/sqrt(c*p(j)))
1348 print *,
"MAXDEV:", k, lens(k), c*p(k), v
1357 p(2*nb - 1) = 1.0_dp
1358 DO j = nb - 1, 1, -1
1360 IF (nmatrix(i, 2*j) > 0)
THEN
1362 p(c) = tmatrix(i, j)
1363 p(c + nb) = p(j + nb)
1365 c = -nmatrix(i, 2*j)
1367 IF (abs(1.0/ipmatrix(i, c) - (p(j + nb) - tmatrix(i, j))) > &
1368 10.0_dp*epsilon(1.0_dp))
THEN
1369 print *,
"Probability mismatch for particle i->j", i, c
1370 print *,
"Got", p(j + nb) - tmatrix(i, j),
"should be", 1.0/ipmatrix(i, c)
1375 IF (nmatrix(i, 2*j - 1) > 0)
THEN
1376 c = nmatrix(i, 2*j - 1)
1377 p(c + nb) = tmatrix(i, j)
1380 c = -nmatrix(i, 2*j - 1)
1382 IF (abs(1.0/ipmatrix(i, c) - (tmatrix(i, j) - p(j))) > &
1383 10.0_dp*epsilon(1.0_dp))
THEN
1384 print *,
"Probability mismatch for particle i->j", i, c
1385 print *,
"Got", tmatrix(i, j) - p(j),
"should be", 1.0/ipmatrix(i, c)
1390 print *,
"Probabilities ok"
1398 helium%pweight = 0.0_dp
1399 t = helium%rng_stream_uniform%next()
1400 helium%ptable(1) = 1 + int(t*nb)
1401 helium%ptable(2) = -1
1405 helium%iperm(perm(i)) = i
1423 TYPE(spline_data_type),
INTENT(IN) :: spl
1424 REAL(kind=
dp),
INTENT(IN) :: xx
1425 REAL(kind=
dp) :: res
1427 REAL(kind=
dp) :: a, b
1429 IF (xx < spl%x1)
THEN
1430 b = spl%invh*(xx - spl%x1)
1432 res = a*spl%y(1) + b*(spl%y(2) - spl%y2(2)*spl%h26)
1433 ELSE IF (xx > spl%xn)
THEN
1434 b = spl%invh*(xx - spl%xn) + 1.0_dp
1436 res = b*spl%y(spl%n) + a*(spl%y(spl%n - 1) - spl%y2(spl%n - 1)*spl%h26)
1454 PURE FUNCTION helium_bead_rij(helium, ia, ib, ja, jb)
RESULT(rij)
1456 TYPE(helium_solvent_type),
INTENT(IN) :: helium
1457 INTEGER,
INTENT(IN) :: ia, ib, ja, jb
1458 REAL(kind=
dp) :: rij
1460 REAL(kind=
dp) :: dx, dy, dz
1462 dx = helium%pos(1, ia, ib) - helium%pos(1, ja, jb)
1463 dy = helium%pos(2, ia, ib) - helium%pos(2, ja, jb)
1464 dz = helium%pos(3, ia, ib) - helium%pos(3, ja, jb)
1465 rij = sqrt(dx*dx + dy*dy + dz*dz)
1467 END FUNCTION helium_bead_rij
1486 TYPE(helium_solvent_type),
INTENT(INOUT) :: helium
1487 INTEGER,
INTENT(IN) :: atom_number
1488 INTEGER,
DIMENSION(:),
POINTER :: permutation
1489 INTEGER :: cycle_number
1491 INTEGER :: atom_idx, cycle_idx, cycle_num, ia, ib, &
1493 INTEGER,
DIMENSION(:),
POINTER :: cycle_index
1494 LOGICAL :: found, new_cycle
1496 NULLIFY (cycle_index)
1497 cycle_index => helium%itmp_atoms_1d
1503 DO ia = 1, helium%atoms
1516 DO ib = 1, helium%atoms*helium%beads
1521 atom_idx = permutation(atom_idx)
1523 IF (atom_idx .EQ. ia)
THEN
1528 DO ic = 1, num_cycles
1529 IF (cycle_index(ic) .EQ. cycle_idx)
THEN
1536 num_cycles = num_cycles + 1
1537 cycle_index(num_cycles) = cycle_idx
1541 IF (ia .EQ. atom_number)
THEN
1543 cycle_num = cycle_idx
1554 IF (atom_idx .LT. cycle_idx)
THEN
1555 cycle_idx = atom_idx
1563 IF (.NOT. found)
THEN
1564 cpwarn(
"helium_cycle_number: we are going to return -1, problems ahead!")
1573 DO ic = 1, num_cycles
1574 IF (cycle_index(ic) .EQ. cycle_num)
THEN
1580 NULLIFY (cycle_index)
1596 TYPE(helium_solvent_type),
INTENT(IN) :: helium
1597 INTEGER,
INTENT(IN) :: atom_number
1598 INTEGER,
DIMENSION(:),
POINTER :: permutation
1599 INTEGER :: path_length
1601 INTEGER :: atom_idx, ia
1602 LOGICAL :: path_end_reached
1604 atom_idx = atom_number
1606 path_end_reached = .false.
1607 DO ia = 1, helium%atoms
1608 path_length = path_length + 1
1609 atom_idx = permutation(atom_idx)
1610 IF (atom_idx .EQ. atom_number)
THEN
1611 path_end_reached = .true.
1616 IF (.NOT. path_end_reached)
THEN
1634 INTEGER,
INTENT(IN) :: element
1635 INTEGER,
DIMENSION(:),
INTENT(IN),
POINTER :: permutation
1636 INTEGER,
DIMENSION(:),
POINTER :: cycle
1638 INTEGER :: ia, icur, len, nsize
1639 INTEGER,
DIMENSION(:),
POINTER :: my_cycle
1640 LOGICAL :: cycle_end_reached
1642 nsize =
SIZE(permutation)
1646 ALLOCATE (my_cycle(nsize))
1651 cycle_end_reached = .false.
1654 my_cycle(len) = icur
1655 icur = permutation(icur)
1656 IF (icur .EQ. element)
THEN
1657 cycle_end_reached = .true.
1662 IF (.NOT. cycle_end_reached)
THEN
1667 ALLOCATE (cycle(len))
1668 cycle(1:len) = my_cycle(1:len)
1672 DEALLOCATE (my_cycle)
1686 TYPE(helium_solvent_type),
INTENT(IN) :: helium
1687 REAL(kind=
dp),
DIMENSION(3) :: wnum
1690 REAL(kind=
dp),
DIMENSION(3) :: rcur
1691 REAL(kind=
dp),
DIMENSION(:),
POINTER :: ri, rj
1694 DO ia = 1, helium%atoms
1696 DO ib = 1, helium%beads - 1
1697 ri => helium%pos(:, ia, ib)
1698 rj => helium%pos(:, ia, ib + 1)
1699 rcur(:) = ri(:) - rj(:)
1701 wnum(:) = wnum(:) + rcur(:)
1704 ri => helium%pos(:, ia, helium%beads)
1705 rj => helium%pos(:, helium%permutation(ia), 1)
1706 rcur(:) = ri(:) - rj(:)
1708 wnum(:) = wnum(:) + rcur(:)
1722 FUNCTION helium_link_winding_number(helium, ia, ib)
RESULT(wnum)
1724 TYPE(helium_solvent_type),
INTENT(IN) :: helium
1725 INTEGER,
INTENT(IN) :: ia, ib
1726 REAL(kind=
dp),
DIMENSION(3) :: wnum
1728 INTEGER :: ja1, ja2, jb1, jb2
1729 REAL(kind=
dp),
DIMENSION(:),
POINTER :: r1, r2
1731 IF (ib .EQ. helium%beads)
THEN
1733 ja2 = helium%permutation(ia)
1742 r1 => helium%pos(:, ja1, jb1)
1743 r2 => helium%pos(:, ja2, jb2)
1744 wnum(:) = r1(:) - r2(:)
1747 END FUNCTION helium_link_winding_number
1757 FUNCTION helium_total_winding_number_linkwise(helium)
RESULT(wnum)
1759 TYPE(helium_solvent_type),
INTENT(IN) :: helium
1760 REAL(kind=
dp),
DIMENSION(3) :: wnum
1765 DO ia = 1, helium%atoms
1766 DO ib = 1, helium%beads
1767 wnum(:) = wnum(:) + helium_link_winding_number(helium, ia, ib)
1771 END FUNCTION helium_total_winding_number_linkwise
1782 FUNCTION helium_cycle_winding_number(helium, CYCLE, pos)
RESULT(wnum)
1784 TYPE(helium_solvent_type),
INTENT(IN) :: helium
1785 INTEGER,
DIMENSION(:),
POINTER :: cycle
1786 REAL(kind=
dp),
DIMENSION(:, :, :),
POINTER :: pos
1787 REAL(kind=
dp),
DIMENSION(3) :: wnum
1789 INTEGER :: i1, i2, ia, ib, nsize
1790 REAL(kind=
dp),
DIMENSION(3) :: rcur
1791 REAL(kind=
dp),
DIMENSION(:),
POINTER :: ri, rj
1799 DO ib = 1, helium%beads - 1
1800 ri => pos(:, cycle(ia), ib)
1801 rj => pos(:, cycle(ia), ib + 1)
1802 rcur(:) = ri(:) - rj(:)
1804 wnum(:) = wnum(:) + rcur(:)
1809 IF (ia .EQ. nsize)
THEN
1814 ri => pos(:, i1, helium%beads)
1816 rcur(:) = ri(:) - rj(:)
1818 wnum(:) = wnum(:) + rcur(:)
1821 END FUNCTION helium_cycle_winding_number
1831 FUNCTION helium_total_winding_number_cyclewise(helium)
RESULT(wnum)
1833 TYPE(helium_solvent_type),
INTENT(IN) :: helium
1834 REAL(kind=
dp),
DIMENSION(3) :: wnum
1837 REAL(kind=
dp),
DIMENSION(3) :: wn
1838 TYPE(int_arr_ptr),
DIMENSION(:),
POINTER :: cycles
1843 cycles => helium_calc_cycles(helium%permutation)
1846 DO ic = 1,
SIZE(cycles)
1847 wn = helium_cycle_winding_number(helium, cycles(ic)%iap, helium%pos)
1848 wnum(:) = wnum(:) + wn(:)
1853 END FUNCTION helium_total_winding_number_cyclewise
1864 TYPE(helium_solvent_type),
INTENT(IN) :: helium
1865 REAL(kind=
dp),
DIMENSION(3) :: area
1868 REAL(kind=
dp),
DIMENSION(3) :: r1, r12, r2, rcur
1871 DO ia = 1, helium%atoms
1873 DO ib = 1, helium%beads - 1
1874 r1(:) = helium%pos(:, ia, ib)
1875 r2(:) = helium%pos(:, ia, ib + 1)
1877 r12(:) = r2(:) - r1(:)
1880 r2(:) = r1(:) + r12(:)
1882 rcur(1) = r1(2)*r2(3) - r1(3)*r2(2)
1883 rcur(2) = r1(3)*r2(1) - r1(1)*r2(3)
1884 rcur(3) = r1(1)*r2(2) - r1(2)*r2(1)
1885 area(:) = area(:) + rcur(:)
1889 r1(:) = helium%pos(:, ia, helium%beads)
1890 r2(:) = helium%pos(:, helium%permutation(ia), 1)
1892 r12(:) = r2(:) - r1(:)
1895 r2(:) = r1(:) + r12(:)
1897 rcur(1) = r1(2)*r2(3) - r1(3)*r2(2)
1898 rcur(2) = r1(3)*r2(1) - r1(1)*r2(3)
1899 rcur(3) = r1(1)*r2(2) - r1(2)*r2(1)
1900 area(:) = area(:) + rcur(:)
1902 area(:) = 0.5_dp*area(:)
1915 FUNCTION helium_link_projected_area(helium, ia, ib)
RESULT(area)
1917 TYPE(helium_solvent_type),
INTENT(IN) :: helium
1919 REAL(kind=
dp),
DIMENSION(3) :: area
1921 INTEGER :: ja1, ja2, jb1, jb2
1922 REAL(kind=
dp),
DIMENSION(3) :: r1, r12, r2
1924 IF (ib .EQ. helium%beads)
THEN
1926 ja2 = helium%permutation(ia)
1935 r1(:) = helium%pos(:, ja1, jb1)
1936 r2(:) = helium%pos(:, ja2, jb2)
1938 r12(:) = r2(:) - r1(:)
1941 r2(:) = r1(:) + r12(:)
1943 area(1) = r1(2)*r2(3) - r1(3)*r2(2)
1944 area(2) = r1(3)*r2(1) - r1(1)*r2(3)
1945 area(3) = r1(1)*r2(2) - r1(2)*r2(1)
1946 area(:) = 0.5_dp*area(:)
1948 END FUNCTION helium_link_projected_area
1958 FUNCTION helium_total_projected_area_linkwise(helium)
RESULT(area)
1960 TYPE(helium_solvent_type),
INTENT(IN) :: helium
1961 REAL(kind=
dp),
DIMENSION(3) :: area
1966 DO ia = 1, helium%atoms
1967 DO ib = 1, helium%beads
1968 area(:) = area(:) + helium_link_projected_area(helium, ia, ib)
1972 END FUNCTION helium_total_projected_area_linkwise
1982 FUNCTION helium_cycle_projected_area(helium, CYCLE)
RESULT(area)
1984 TYPE(helium_solvent_type),
INTENT(IN) :: helium
1985 INTEGER,
DIMENSION(:),
POINTER :: cycle
1986 REAL(kind=
dp),
DIMENSION(3) :: area
1988 INTEGER :: i1, i2, ia, ib, nsize
1989 REAL(kind=
dp),
DIMENSION(3) :: rcur, rsum
1990 REAL(kind=
dp),
DIMENSION(:),
POINTER :: ri, rj
1998 DO ib = 1, helium%beads - 1
1999 ri => helium%pos(:, cycle(ia), ib)
2000 rj => helium%pos(:, cycle(ia), ib + 1)
2001 rcur(1) = ri(2)*rj(3) - ri(3)*rj(2)
2002 rcur(2) = ri(3)*rj(1) - ri(1)*rj(3)
2003 rcur(3) = ri(1)*rj(2) - ri(2)*rj(1)
2004 rsum(:) = rsum(:) + rcur(:)
2009 IF (ia .EQ. nsize)
THEN
2014 ri => helium%pos(:, i1, helium%beads)
2015 rj => helium%pos(:, i2, 1)
2016 rcur(1) = ri(2)*rj(3) - ri(3)*rj(2)
2017 rcur(2) = ri(3)*rj(1) - ri(1)*rj(3)
2018 rcur(3) = ri(1)*rj(2) - ri(2)*rj(1)
2019 rsum(:) = rsum(:) + rcur(:)
2021 area(:) = 0.5_dp*rsum(:)
2023 END FUNCTION helium_cycle_projected_area
2034 FUNCTION helium_cycle_projected_area_pbc(helium, CYCLE)
RESULT(area)
2036 TYPE(helium_solvent_type),
INTENT(IN) :: helium
2037 INTEGER,
DIMENSION(:),
POINTER :: cycle
2038 REAL(kind=
dp),
DIMENSION(3) :: area
2040 INTEGER :: i1, i2, ia, ib, nsize
2041 REAL(kind=
dp),
DIMENSION(3) :: r1, r12, r2, rcur
2049 DO ib = 1, helium%beads - 1
2050 r1(:) = helium%pos(:, cycle(ia), ib)
2051 r2(:) = helium%pos(:, cycle(ia), ib + 1)
2052 r12(:) = r2(:) - r1(:)
2055 r2(:) = r1(:) + r12(:)
2056 rcur(1) = r1(2)*r2(3) - r1(3)*r2(2)
2057 rcur(2) = r1(3)*r2(1) - r1(1)*r2(3)
2058 rcur(3) = r1(1)*r2(2) - r1(2)*r2(1)
2059 area(:) = area(:) + rcur(:)
2064 IF (ia .EQ. nsize)
THEN
2069 r1(:) = helium%pos(:, i1, helium%beads)
2070 r2(:) = helium%pos(:, i2, 1)
2071 r12(:) = r2(:) - r1(:)
2074 r2(:) = r1(:) + r12(:)
2075 rcur(1) = r1(2)*r2(3) - r1(3)*r2(2)
2076 rcur(2) = r1(3)*r2(1) - r1(1)*r2(3)
2077 rcur(3) = r1(1)*r2(2) - r1(2)*r2(1)
2078 area(:) = area(:) + rcur(:)
2080 area(:) = 0.5_dp*area(:)
2082 END FUNCTION helium_cycle_projected_area_pbc
2092 FUNCTION helium_total_projected_area_cyclewise(helium)
RESULT(area)
2094 TYPE(helium_solvent_type),
INTENT(IN) :: helium
2095 REAL(kind=
dp),
DIMENSION(3) :: area
2098 REAL(kind=
dp),
DIMENSION(3) :: pa
2099 TYPE(int_arr_ptr),
DIMENSION(:),
POINTER :: cycles
2104 cycles => helium_calc_cycles(helium%permutation)
2107 DO ic = 1,
SIZE(cycles)
2108 pa = helium_cycle_projected_area(helium, cycles(ic)%iap)
2109 area(:) = area(:) + pa(:)
2112 END FUNCTION helium_total_projected_area_cyclewise
2123 TYPE(helium_solvent_type),
INTENT(IN) :: helium
2124 REAL(kind=
dp),
DIMENSION(3) :: moit
2127 REAL(kind=
dp),
DIMENSION(3) :: com, r1, r12, r2, rcur
2129 com(:) = helium%center(:)
2132 DO ia = 1, helium%atoms
2134 DO ib = 1, helium%beads - 1
2135 r1(:) = helium%pos(:, ia, ib) - com(:)
2136 r2(:) = helium%pos(:, ia, ib + 1) - com(:)
2138 r12(:) = r2(:) - r1(:)
2141 r2(:) = r1(:) + r12(:)
2143 rcur(1) = r1(2)*r2(2) + r1(3)*r2(3)
2144 rcur(2) = r1(3)*r2(3) + r1(1)*r2(1)
2145 rcur(3) = r1(1)*r2(1) + r1(2)*r2(2)
2146 moit(:) = moit(:) + rcur(:)
2150 r1(:) = helium%pos(:, ia, helium%beads) - com(:)
2151 r2(:) = helium%pos(:, helium%permutation(ia), 1) - com(:)
2153 r12(:) = r2(:) - r1(:)
2156 r2(:) = r1(:) + r12(:)
2158 rcur(1) = r1(2)*r2(2) + r1(3)*r2(3)
2159 rcur(2) = r1(3)*r2(3) + r1(1)*r2(1)
2160 rcur(3) = r1(1)*r2(1) + r1(2)*r2(2)
2161 moit(:) = moit(:) + rcur(:)
2163 moit(:) = moit(:)/helium%beads
2176 FUNCTION helium_link_moment_of_inertia(helium, ia, ib)
RESULT(moit)
2178 TYPE(helium_solvent_type),
INTENT(IN) :: helium
2179 INTEGER,
INTENT(IN) :: ia, ib
2180 REAL(kind=
dp),
DIMENSION(3) :: moit
2182 INTEGER :: ja1, ja2, jb1, jb2
2183 REAL(kind=
dp),
DIMENSION(3) :: com, r1, r12, r2
2185 com(:) = helium%center(:)
2187 IF (ib .EQ. helium%beads)
THEN
2189 ja2 = helium%permutation(ia)
2198 r1(:) = helium%pos(:, ja1, jb1) - com(:)
2199 r2(:) = helium%pos(:, ja2, jb2) - com(:)
2201 r12(:) = r2(:) - r1(:)
2204 r2(:) = r1(:) + r12(:)
2206 moit(1) = r1(2)*r2(2) + r1(3)*r2(3)
2207 moit(2) = r1(3)*r2(3) + r1(1)*r2(1)
2208 moit(3) = r1(1)*r2(1) + r1(2)*r2(2)
2209 moit(:) = moit(:)/helium%beads
2211 END FUNCTION helium_link_moment_of_inertia
2221 FUNCTION helium_total_moment_of_inertia_linkwise(helium)
RESULT(moit)
2223 TYPE(helium_solvent_type),
INTENT(IN) :: helium
2224 REAL(kind=
dp),
DIMENSION(3) :: moit
2229 DO ia = 1, helium%atoms
2230 DO ib = 1, helium%beads
2231 moit(:) = moit(:) + helium_link_moment_of_inertia(helium, ia, ib)
2235 END FUNCTION helium_total_moment_of_inertia_linkwise
2246 FUNCTION helium_cycle_moment_of_inertia(helium, CYCLE, pos)
RESULT(moit)
2248 TYPE(helium_solvent_type),
INTENT(IN) :: helium
2249 INTEGER,
DIMENSION(:),
POINTER :: cycle
2250 REAL(kind=
dp),
DIMENSION(:, :, :),
POINTER :: pos
2251 REAL(kind=
dp),
DIMENSION(3) :: moit
2253 INTEGER :: i1, i2, ia, ib, nsize
2254 REAL(kind=
dp),
DIMENSION(3) :: com, rcur, ri, rj
2263 DO ib = 1, helium%beads - 1
2264 ri = pos(:, cycle(ia), ib) - com(:)
2265 rj = pos(:, cycle(ia), ib + 1) - com(:)
2266 rcur(1) = ri(2)*rj(2) + ri(3)*rj(3)
2267 rcur(2) = ri(3)*rj(3) + ri(1)*rj(1)
2268 rcur(3) = ri(1)*rj(1) + ri(2)*rj(2)
2269 moit(:) = moit(:) + rcur(:)
2274 IF (ia .EQ. nsize)
THEN
2280 ri = pos(:, i1, helium%beads) - com(:)
2281 rj = pos(:, i2, 1) - com(:)
2282 rcur(1) = ri(2)*rj(2) + ri(3)*rj(3)
2283 rcur(2) = ri(3)*rj(3) + ri(1)*rj(1)
2284 rcur(3) = ri(1)*rj(1) + ri(2)*rj(2)
2285 moit(:) = moit(:) + rcur(:)
2287 moit(:) = moit(:)/helium%beads
2289 END FUNCTION helium_cycle_moment_of_inertia
2299 FUNCTION helium_total_moment_of_inertia_cyclewise(helium)
RESULT(moit)
2301 TYPE(helium_solvent_type),
INTENT(IN) :: helium
2302 REAL(kind=
dp),
DIMENSION(3) :: moit
2305 REAL(kind=
dp),
DIMENSION(3) :: pa
2306 TYPE(int_arr_ptr),
DIMENSION(:),
POINTER :: cycles
2311 cycles => helium_calc_cycles(helium%permutation)
2314 DO ic = 1,
SIZE(cycles)
2315 pa = helium_cycle_moment_of_inertia(helium, cycles(ic)%iap, helium%pos)
2316 moit(:) = moit(:) + pa(:)
2321 END FUNCTION helium_total_moment_of_inertia_cyclewise
2336 TYPE(helium_solvent_type),
INTENT(INOUT) :: helium
2337 TYPE(pint_env_type),
INTENT(IN) :: pint_env
2339 IF (helium%solute_present)
THEN
2342 IF (helium%periodic)
THEN
2343 helium%center(:) = (/0.0_dp, 0.0_dp, 0.0_dp/)
2364 TYPE(helium_solvent_type),
INTENT(INOUT) :: helium
2365 TYPE(pint_env_type),
INTENT(IN) :: pint_env
2369 IF (helium%solute_present .AND. helium%rdf_sol_he)
THEN
2371 DO i = 1, helium%beads
2372 j = ((i - 1)*helium%solute_beads)/helium%beads + 1
2373 helium%rdf_centers(i, :) = pint_env%x(j, :)
2388 TYPE(helium_solvent_type),
INTENT(IN) :: helium
2389 REAL(kind=
dp),
DIMENSION(3) :: com
2394 DO ia = 1, helium%atoms
2395 DO ib = 1, helium%beads
2396 com(:) = com(:) + helium%pos(:, ia, ib)
2399 com(:) = com(:)/helium%atoms/helium%beads
2412 FUNCTION helium_link_vector(helium, ia, ib)
RESULT(lvec)
2414 TYPE(helium_solvent_type),
INTENT(IN) :: helium
2415 INTEGER,
INTENT(IN) :: ia, ib
2416 REAL(kind=
dp),
DIMENSION(3) :: lvec
2418 INTEGER :: ia1, ia2, ib1, ib2
2419 REAL(kind=
dp),
DIMENSION(:),
POINTER :: r1, r2
2421 IF (ib .EQ. helium%beads)
THEN
2423 ia2 = helium%permutation(ia)
2432 r1 => helium%pos(:, ia1, ib1)
2433 r2 => helium%pos(:, ia2, ib2)
2434 lvec(:) = r2(:) - r1(:)
2437 END FUNCTION helium_link_vector
2446 PURE FUNCTION helium_rperpendicular(helium, ia, ib)
RESULT(rperp)
2448 TYPE(helium_solvent_type),
INTENT(IN) :: helium
2449 INTEGER,
INTENT(IN) :: ia, ib
2450 REAL(kind=
dp),
DIMENSION(3) :: rperp
2452 associate(ri => helium%pos(:, ia, ib))
2453 rperp(1) = sqrt(ri(2)*ri(2) + ri(3)*ri(3))
2454 rperp(2) = sqrt(ri(3)*ri(3) + ri(1)*ri(1))
2455 rperp(3) = sqrt(ri(1)*ri(1) + ri(2)*ri(2))
2458 END FUNCTION helium_rperpendicular
2469 FUNCTION helium_wnumber_to_integer(helium, wnum)
RESULT(inum)
2471 TYPE(helium_solvent_type),
INTENT(IN) :: helium
2472 REAL(kind=dp),
DIMENSION(3),
INTENT(IN) :: wnum
2473 INTEGER,
DIMENSION(3) :: inum
2475 REAL(kind=dp),
DIMENSION(3) :: wcur
2477 CALL dgemv(
'N', 3, 3, 1.0_dp, helium%cell_m_inv,
SIZE(helium%cell_m_inv, 1), wnum, 1, 0.0_dp, wcur, 1)
2478 inum(:) = nint(wcur(:))
2480 END FUNCTION helium_wnumber_to_integer
2497 TYPE(helium_solvent_type),
INTENT(IN) :: helium
2498 INTEGER,
INTENT(IN) :: atmidx
2499 REAL(kind=dp),
DIMENSION(:, :, :),
POINTER :: pos
2500 INTEGER,
DIMENSION(:),
POINTER :: permutation
2501 LOGICAL :: is_winding
2504 INTEGER,
DIMENSION(3) :: inum
2505 INTEGER,
DIMENSION(:),
POINTER :: cycle
2506 REAL(kind=dp),
DIMENSION(3) :: wnum
2508 is_winding = .false.
2511 wnum(:) = bohr*helium_cycle_winding_number(helium, cycle, pos)
2512 inum(:) = helium_wnumber_to_integer(helium, wnum)
2514 IF (abs(inum(ic)) .GT. 0)
THEN
Independent helium subroutines shared with other modules.
integer function, public helium_cycle_number(helium, atom_number, permutation)
Given the atom number and permutation state return the cycle number the atom belongs to.
real(kind=dp) function, dimension(3), public helium_total_moment_of_inertia(helium)
Return total moment of inertia divided by m_He.
pure real(kind=dp) function, dimension(3), public helium_com(helium)
Calculate center of mass.
pure subroutine, public helium_rotate(helium, nslices)
Rotate helium particles in imaginary time by nslices.
subroutine, public helium_pbc(helium, r, enforce)
General PBC routine for helium.
subroutine, public helium_boxmean_3d(helium, a, b, c)
Calculate the point equidistant from two other points a and b within the helium box - 3D version.
real(kind=dp) function, public helium_eval_chain(helium, rchain, nchain, aij, vcoef, energy)
Calculate the pair-product action or energy by evaluating the power series expansion according to Eq....
subroutine, public helium_calc_rho(helium)
Calculate helium density distribution functions and store them in heliumrho_inst.
real(kind=dp) function, public helium_eval_expansion(helium, r, rp, work, action)
Calculate the pair-product action or energy by evaluating the power series expansion according to Eq....
pure integer function, dimension(:), pointer, public helium_cycle_of(element, permutation)
Given an element of a permutation return the cycle it belongs to.
pure subroutine, public helium_calc_plength(helium)
Calculate probability distribution of the permutation lengths.
subroutine, public helium_update_transition_matrix(helium)
...
subroutine, public helium_calc_rdf(helium)
Calculate helium radial distribution functions wrt positions given by <centers> using the atomic weig...
pure subroutine, public helium_update_coord_system(helium, pint_env)
Set coordinate system, e.g. for RHO calculations.
pure integer function, public helium_path_length(helium, atom_number, permutation)
Given the atom number and permutation state return the length of the path this atom belongs to.
real(kind=dp) function, dimension(3), public helium_total_projected_area(helium)
Return total projected area.
real(kind=dp) function, public helium_spline(spl, xx)
...
real(kind=dp) function, dimension(3), public helium_total_winding_number(helium)
Return total winding number.
pure subroutine, public helium_set_rdf_coord_system(helium, pint_env)
Set coordinate system for RDF calculations.
logical function, public helium_is_winding(helium, atmidx, pos, permutation)
Given the atom index and permutation state returns .TRUE. if the atom belongs to a winding path,...
Data types representing superfluid helium.
integer, parameter, public rho_moment_of_inertia
integer, parameter, public rho_winding_number
integer, parameter, public rho_atom_number
density function identifier names
integer, parameter, public rho_winding_cycle
integer, parameter, public rho_projected_area
integer, parameter, public rho_num
number of density function identifiers
Defines the basic variable types.
integer, parameter, public dp
integer, parameter, public default_string_length
Definition of mathematical constants and functions.
real(kind=dp), parameter, public pi
Utility routines for the memory handling.
Definition of physical constants:
real(kind=dp), parameter, public angstrom
real(kind=dp), parameter, public bohr
Public path integral routines that can be called from other modules.
pure real(kind=dp) function, dimension(3), public pint_com_pos(pint_env)
Return the center of mass of the PI system.
routines for handling splines
real(kind=dp) function, public spline_value(spl, xx, y1)
calculates the spline value at a given point (and possibly the first derivative) WITHOUT checks and w...
routines for handling splines_types