92#include "./base/base_uses.f90"
98 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'eeq_method'
100 INTEGER,
PARAMETER :: maxElem = 86
102 TYPE eeq_sparse_matrix_type
103 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: col, row
104 REAL(KIND=
dp),
ALLOCATABLE,
DIMENSION(:) ::
diag,
value
105 INTEGER :: nactive = 0
106 END TYPE eeq_sparse_matrix_type
109 REAL(kind=
dp),
PARAMETER ::
rcov(1:maxelem) = [&
110 & 0.32_dp, 0.46_dp, 1.20_dp, 0.94_dp, 0.77_dp, 0.75_dp, 0.71_dp, 0.63_dp, &
111 & 0.64_dp, 0.67_dp, 1.40_dp, 1.25_dp, 1.13_dp, 1.04_dp, 1.10_dp, 1.02_dp, &
112 & 0.99_dp, 0.96_dp, 1.76_dp, 1.54_dp, 1.33_dp, 1.22_dp, 1.21_dp, 1.10_dp, &
113 & 1.07_dp, 1.04_dp, 1.00_dp, 0.99_dp, 1.01_dp, 1.09_dp, 1.12_dp, 1.09_dp, &
114 & 1.15_dp, 1.10_dp, 1.14_dp, 1.17_dp, 1.89_dp, 1.67_dp, 1.47_dp, 1.39_dp, &
115 & 1.32_dp, 1.24_dp, 1.15_dp, 1.13_dp, 1.13_dp, 1.08_dp, 1.15_dp, 1.23_dp, &
116 & 1.28_dp, 1.26_dp, 1.26_dp, 1.23_dp, 1.32_dp, 1.31_dp, 2.09_dp, 1.76_dp, &
117 & 1.62_dp, 1.47_dp, 1.58_dp, 1.57_dp, 1.56_dp, 1.55_dp, 1.51_dp, 1.52_dp, &
118 & 1.51_dp, 1.50_dp, 1.49_dp, 1.49_dp, 1.48_dp, 1.53_dp, 1.46_dp, 1.37_dp, &
119 & 1.31_dp, 1.23_dp, 1.18_dp, 1.16_dp, 1.11_dp, 1.12_dp, 1.13_dp, 1.32_dp, &
120 & 1.30_dp, 1.30_dp, 1.36_dp, 1.31_dp, 1.38_dp, 1.42_dp]
137 INTEGER,
INTENT(IN) :: iounit, print_level
138 LOGICAL,
INTENT(IN) :: ext
140 CHARACTER(LEN=2) :: element_symbol
141 INTEGER :: enshift_type, iatom, ikind, natom
142 REAL(kind=
dp),
DIMENSION(:),
POINTER :: charges
147 mark_used(print_level)
149 CALL get_qs_env(qs_env, natom=natom, particle_set=particle_set, cell=cell)
153 cpassert(
ASSOCIATED(charges))
156 ALLOCATE (charges(natom))
161 CALL eeq_charges(qs_env, charges, eeq_sparam, 2, enshift_type)
166 IF (enshift_type == 0)
THEN
167 WRITE (unit=iounit, fmt=
"(/,T2,A)")
"EEQ Charges (External)"
168 ELSE IF (enshift_type == 1)
THEN
169 WRITE (unit=iounit, fmt=
"(/,T2,A)")
"EEQ Charges (Parametrization 2019 (Molecules))"
170 ELSE IF (enshift_type == 2)
THEN
171 WRITE (unit=iounit, fmt=
"(/,T2,A)")
"EEQ Charges (Parametrization 2019 (Crystals))"
173 cpabort(
"Unknown enshift_type")
175 WRITE (unit=iounit, fmt=
"(/,T2,A)") &
176 "# Atom Element Kind Atomic Charge"
180 element_symbol=element_symbol, &
182 WRITE (unit=iounit, fmt=
"(T4,I8,T18,A2,I10,T43,F12.4)") &
183 iatom, element_symbol, ikind, charges(iatom)
188 IF (.NOT. ext)
DEALLOCATE (charges)
202 SUBROUTINE eeq_charges(qs_env, charges, eeq_sparam, eeq_model, enshift_type, exclude, cn_max)
205 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: charges
207 INTEGER,
INTENT(IN) :: eeq_model, enshift_type
208 LOGICAL,
DIMENSION(:),
INTENT(IN),
OPTIONAL :: exclude
209 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: cn_max
211 CHARACTER(len=*),
PARAMETER :: routinen =
'eeq_charges'
213 INTEGER :: handle, iatom, ikind, iunit, jkind, &
215 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: kind_of
216 INTEGER,
DIMENSION(3) :: periodic
218 REAL(kind=
dp) :: ala, alb, eeq_energy, esg, kappa, &
219 lambda, scn, sgamma, totalcharge, xi
220 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: chia, cnumbers, efr, gam
221 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: gab
223 TYPE(
cell_type),
POINTER :: cell, cell_ref
226 TYPE(
dcnum_type),
ALLOCATABLE,
DIMENSION(:) :: dcnum
232 TYPE(
qs_kind_type),
DIMENSION(:),
POINTER :: qs_kind_set
236 CALL timeset(routinen, handle)
239 qs_kind_set=qs_kind_set, &
240 atomic_kind_set=atomic_kind_set, &
241 particle_set=particle_set, &
243 blacs_env=blacs_env, &
245 dft_control=dft_control)
246 CALL get_qs_env(qs_env, nkind=nkind, natom=natom)
249 IF (para_env%is_source() .AND. logger%iter_info%print_level >=
medium_print_level)
THEN
255 totalcharge = dft_control%charge
257 CALL get_cnumbers(qs_env, cnumbers, dcnum, .false.)
260 IF (
PRESENT(cn_max))
THEN
262 cnumbers(iatom) = log(1.0_dp + exp(cn_max)) - log(1.0_dp + exp(cn_max - cnumbers(iatom)))
267 ALLOCATE (gab(nkind, nkind), gam(nkind))
272 CALL get_eeq_data(za, eeq_model, eta=gam(ikind), rad=ala)
277 gab(ikind, jkind) = sqrt(1._dp/(ala*ala + alb*alb))
284 IF (
PRESENT(exclude))
THEN
286 IF (exclude(ikind))
THEN
287 gam(ikind) = 1.0e30_dp
288 gab(ikind, :) = 0.0_dp
289 gab(:, ikind) = 0.0_dp
296 esg = 1.0_dp + exp(sgamma)
297 ALLOCATE (chia(natom))
300 ikind = kind_of(iatom)
304 IF (enshift_type == 1)
THEN
305 scn = cnumbers(iatom)/sqrt(cnumbers(iatom) + 1.0e-14_dp)
306 ELSE IF (enshift_type == 2)
THEN
307 scn = log(esg/(esg - cnumbers(iatom)))
309 cpabort(
"Unknown enshift_type")
311 chia(iatom) = xi - kappa*scn
316 IF (
PRESENT(exclude))
THEN
318 ikind = kind_of(iatom)
319 IF (exclude(ikind)) chia(iatom) = 0.0_dp
324 IF (dft_control%apply_period_efield .OR. dft_control%apply_efield .OR. &
325 dft_control%apply_efield_field)
THEN
326 ALLOCATE (efr(natom))
327 efr(1:natom) = 0.0_dp
329 chia(1:natom) = chia(1:natom) + efr(1:natom)
335 CALL get_cell(cell, periodic=periodic)
336 do_ewald = .NOT. all(periodic == 0)
341 CALL ewald_env_set(ewald_env, poisson_section=poisson_section)
346 silent=.true., pset=
"EEQ", cell_periodic=cell%perd)
348 CALL ewald_pw_create(ewald_pw, ewald_env, cell, cell_ref, print_section=print_section)
350 CALL eeq_solver(charges, lambda, eeq_energy, &
351 particle_set, kind_of, cell, chia, gam, gab, &
352 para_env, blacs_env, dft_control, eeq_sparam, &
353 totalcharge=totalcharge, ewald=do_ewald, &
354 ewald_env=ewald_env, ewald_pw=ewald_pw, iounit=iunit, qs_env=qs_env)
358 DEALLOCATE (ewald_env, ewald_pw)
360 CALL eeq_solver(charges, lambda, eeq_energy, &
361 particle_set, kind_of, cell, chia, gam, gab, &
362 para_env, blacs_env, dft_control, eeq_sparam, &
363 totalcharge=totalcharge, iounit=iunit, qs_env=qs_env)
366 DEALLOCATE (gab, gam, chia)
368 CALL timestop(handle)
386 SUBROUTINE eeq_forces(qs_env, charges, dcharges, gradient, stress, &
387 eeq_sparam, eeq_model, enshift_type, response_only, exclude, cn_max)
390 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: charges, dcharges
391 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: gradient
392 REAL(kind=
dp),
DIMENSION(3, 3),
INTENT(INOUT) :: stress
394 INTEGER,
INTENT(IN) :: eeq_model, enshift_type
395 LOGICAL,
INTENT(IN) :: response_only
396 LOGICAL,
DIMENSION(:),
INTENT(IN),
OPTIONAL :: exclude
397 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: cn_max
399 CHARACTER(len=*),
PARAMETER :: routinen =
'eeq_forces'
401 INTEGER :: handle, i, ia, iatom, ikind, iunit, &
402 jatom, jkind, katom, natom, nkind, za, &
404 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: kind_of
405 INTEGER,
DIMENSION(3) :: periodic
406 LOGICAL :: do_ewald, use_virial
407 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: default_present
408 REAL(kind=
dp) :: ala, alb, alpha, cn, ctot, dcnpdcn, dr, dr2, drk, elag, esg, fe, gam2, &
409 gama, grc, kappa, qlam, qq, qq1, qq2, rcut, scn, sgamma, subcells, totalcharge, xi
410 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: c_radius, cnumbers, gam, qlag
411 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: epforce, gab, pair_radius
412 REAL(kind=
dp),
DIMENSION(3) :: fdik, ri, rij, rik, rj
413 REAL(kind=
dp),
DIMENSION(3, 3) :: pvir
414 REAL(kind=
dp),
DIMENSION(:),
POINTER :: chrgx, dchia
417 TYPE(
cell_type),
POINTER :: cell, cell_ref
420 TYPE(
dcnum_type),
ALLOCATABLE,
DIMENSION(:) :: dcnum
430 DIMENSION(:),
POINTER :: nl_iterator
435 TYPE(
qs_kind_type),
DIMENSION(:),
POINTER :: qs_kind_set
440 CALL timeset(routinen, handle)
443 qs_kind_set=qs_kind_set, &
444 atomic_kind_set=atomic_kind_set, &
445 particle_set=particle_set, &
447 blacs_env=blacs_env, &
452 dft_control=dft_control)
455 IF (para_env%is_source() .AND. logger%iter_info%print_level >=
medium_print_level)
THEN
461 CALL get_qs_env(qs_env, nkind=nkind, natom=natom)
462 use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
466 totalcharge = dft_control%charge
468 CALL get_cnumbers(qs_env, cnumbers, dcnum, .true.)
472 IF (
PRESENT(cn_max))
THEN
474 dcnpdcn = exp(cn_max)/(exp(cn_max) + exp(cnumbers(iatom)))
475 cnumbers(iatom) = log(1.0_dp + exp(cn_max)) - log(1.0_dp + exp(cn_max - cnumbers(iatom)))
476 DO i = 1, dcnum(iatom)%neighbors
477 dcnum(iatom)%dvals(i) = dcnum(iatom)%dvals(i)*dcnpdcn
483 ALLOCATE (gab(nkind, nkind), gam(nkind))
488 CALL get_eeq_data(za, eeq_model, eta=gam(ikind), rad=ala)
493 gab(ikind, jkind) = sqrt(1._dp/(ala*ala + alb*alb))
499 IF (
PRESENT(exclude))
THEN
501 IF (exclude(ikind))
THEN
502 gam(ikind) = 1.0e30_dp
503 gab(ikind, :) = 0.0_dp
504 gab(:, ikind) = 0.0_dp
509 ALLOCATE (qlag(natom))
511 CALL get_cell(cell, periodic=periodic)
512 do_ewald = .NOT. all(periodic == 0)
517 CALL ewald_env_set(ewald_env, poisson_section=poisson_section)
522 silent=.true., pset=
"EEQ", cell_periodic=cell%perd)
524 CALL ewald_pw_create(ewald_pw, ewald_env, cell, cell_ref, print_section=print_section)
527 particle_set, kind_of, cell, -dcharges, gam, gab, &
528 para_env, blacs_env, dft_control, eeq_sparam, &
529 ewald=do_ewald, ewald_env=ewald_env, ewald_pw=ewald_pw, iounit=iunit, qs_env=qs_env)
532 particle_set, kind_of, cell, -dcharges, gam, gab, &
533 para_env, blacs_env, dft_control, eeq_sparam, iounit=iunit, qs_env=qs_env)
537 esg = 1.0_dp + exp(sgamma)
538 ALLOCATE (chrgx(natom), dchia(natom))
540 ikind = kind_of(iatom)
544 IF (response_only)
THEN
545 ctot = -0.5_dp*qlag(iatom)
547 ctot = 0.5_dp*(charges(iatom) - qlag(iatom))
549 IF (enshift_type == 1)
THEN
550 scn = sqrt(cnumbers(iatom)) + 1.0e-14_dp
551 dchia(iatom) = -ctot*kappa/scn
552 ELSE IF (enshift_type == 2)
THEN
554 scn = 1.0_dp/(esg - cn)
555 dchia(iatom) = -ctot*kappa*scn
557 cpabort(
"Unknown enshift_type")
562 IF (dft_control%apply_period_efield)
THEN
564 ELSE IF (dft_control%apply_efield)
THEN
566 ELSE IF (dft_control%apply_efield_field)
THEN
567 cpabort(
"apply field")
571 CALL get_qs_env(qs_env=qs_env, local_particles=local_particles)
573 DO ia = 1, local_particles%n_el(ikind)
574 iatom = local_particles%list(ikind)%array(ia)
575 DO i = 1, dcnum(iatom)%neighbors
576 katom = dcnum(iatom)%nlist(i)
577 rik = dcnum(iatom)%rik(:, i)
579 IF (drk > 1.e-3_dp)
THEN
580 fdik(:) = dchia(iatom)*dcnum(iatom)%dvals(i)*rik(:)/drk
581 gradient(:, iatom) = gradient(:, iatom) - fdik(:)
582 gradient(:, katom) = gradient(:, katom) + fdik(:)
596 distribution_2d=distribution_2d, &
597 local_particles=distribution_1d, &
598 molecule_set=molecule_set)
603 ALLOCATE (c_radius(nkind), default_present(nkind), pair_radius(nkind, nkind))
605 default_present = .true.
606 ALLOCATE (atom2d(nkind))
607 CALL atom2d_build(atom2d, distribution_1d, distribution_2d, atomic_kind_set, &
608 molecule_set, .false., particle_set=particle_set)
609 CALL pair_radius_setup(default_present, default_present, c_radius, c_radius, pair_radius)
611 subcells=subcells, operator_type=
"PP", nlname=
"sab_ew")
612 DEALLOCATE (c_radius, pair_radius, default_present)
618 iatom=iatom, jatom=jatom, r=rij)
622 IF (dr > rcut .OR. dr < 1.e-6_dp) cycle
624 IF (iatom == jatom) fe = 0.5_dp
625 IF (response_only)
THEN
626 qq = -qlag(iatom)*charges(jatom)
628 qq = (0.5_dp*charges(iatom) - qlag(iatom))*charges(jatom)
630 gama = gab(ikind, jkind)
632 grc = 2._dp*gama*exp(-gam2*dr2)*
oorootpi/dr - erf(gama*dr)/dr2 &
633 - 2._dp*alpha*exp(-alpha**2*dr2)*
oorootpi/dr + erf(alpha*dr)/dr2
634 IF (response_only)
THEN
635 qq1 = -qlag(iatom)*charges(jatom)
636 qq2 = -qlag(jatom)*charges(iatom)
638 qq1 = (0.5_dp*charges(iatom) - qlag(iatom))*charges(jatom)
639 qq2 = (0.5_dp*charges(jatom) - qlag(jatom))*charges(iatom)
641 fdik(:) = -qq1*grc*rij(:)/dr
642 gradient(:, iatom) = gradient(:, iatom) + fdik(:)
643 gradient(:, jatom) = gradient(:, jatom) - fdik(:)
647 fdik(:) = qq2*grc*rij(:)/dr
648 gradient(:, iatom) = gradient(:, iatom) - fdik(:)
649 gradient(:, jatom) = gradient(:, jatom) + fdik(:)
659 DO ia = 1, local_particles%n_el(ikind)
660 iatom = local_particles%list(ikind)%array(ia)
661 ri(1:3) = particle_set(iatom)%r(1:3)
663 IF (iatom == jatom) cycle
664 jkind = kind_of(jatom)
665 IF (response_only)
THEN
666 qq = -qlag(iatom)*charges(jatom)
668 qq = (0.5_dp*charges(iatom) - qlag(iatom))*charges(jatom)
670 rj(1:3) = particle_set(jatom)%r(1:3)
671 rij(1:3) = ri(1:3) - rj(1:3)
675 gama = gab(ikind, jkind)
677 grc = 2._dp*gama*exp(-gam2*dr2)*
oorootpi/dr - erf(gama*dr)/dr2
678 fdik(:) = qq*grc*rij(:)/dr
679 gradient(:, iatom) = gradient(:, iatom) + fdik(:)
680 gradient(:, jatom) = gradient(:, jatom) - fdik(:)
688 ALLOCATE (epforce(3, natom))
690 IF (response_only)
THEN
691 dchia(1:natom) = qlag(1:natom)
693 dchia(1:natom) = -charges(1:natom) + qlag(1:natom)
695 chrgx(1:natom) = charges(1:natom)
696 CALL spme_forces(ewald_env, ewald_pw, cell, particle_set, chrgx, &
697 particle_set, dchia, epforce)
698 dchia(1:natom) = charges(1:natom)
699 chrgx(1:natom) = qlag(1:natom)
700 CALL spme_forces(ewald_env, ewald_pw, cell, particle_set, chrgx, &
701 particle_set, dchia, epforce)
702 gradient(1:3, 1:natom) = gradient(1:3, 1:natom) + epforce(1:3, 1:natom)
707 chrgx(1:natom) = charges(1:natom) - qlag(1:natom)
708 CALL spme_virial(ewald_env, ewald_pw, particle_set, cell, chrgx, pvir)
709 stress = stress - pvir
710 chrgx(1:natom) = qlag(1:natom)
711 CALL spme_virial(ewald_env, ewald_pw, particle_set, cell, chrgx, pvir)
712 stress = stress + pvir
713 IF (response_only)
THEN
714 chrgx(1:natom) = charges(1:natom)
715 CALL spme_virial(ewald_env, ewald_pw, particle_set, cell, chrgx, pvir)
716 stress = stress + pvir
722 DEALLOCATE (ewald_env, ewald_pw)
727 DEALLOCATE (gab, gam, qlag, chrgx, dchia)
729 CALL timestop(handle)
740 SUBROUTINE get_cnumbers(qs_env, cnumbers, dcnum, calculate_forces)
743 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: cnumbers
744 TYPE(
dcnum_type),
ALLOCATABLE,
DIMENSION(:) :: dcnum
745 LOGICAL,
INTENT(IN) :: calculate_forces
747 INTEGER :: ikind, natom, nkind, za
748 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: default_present
749 REAL(kind=
dp) :: subcells
750 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: c_radius
751 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: pair_radius
762 TYPE(
qs_kind_type),
DIMENSION(:),
POINTER :: qs_kind_set
765 qs_kind_set=qs_kind_set, &
766 atomic_kind_set=atomic_kind_set, &
767 particle_set=particle_set, &
769 distribution_2d=distribution_2d, &
770 local_particles=distribution_1d, &
771 molecule_set=molecule_set)
772 CALL get_qs_env(qs_env, nkind=nkind, natom=natom)
777 disp%k2 = 4._dp/3._dp
778 disp%eps_cn = 1.e-6_dp
779 disp%max_elem = maxelem
780 ALLOCATE (disp%rcov(maxelem))
781 disp%rcov(1:maxelem) =
bohr*disp%k2*
rcov(1:maxelem)
785 ALLOCATE (c_radius(nkind), default_present(nkind), pair_radius(nkind, nkind))
787 default_present = .true.
790 c_radius(ikind) = 4._dp*
rcov(za)*
bohr
792 ALLOCATE (atom2d(nkind))
793 CALL atom2d_build(atom2d, distribution_1d, distribution_2d, atomic_kind_set, &
794 molecule_set, .false., particle_set=particle_set)
795 CALL pair_radius_setup(default_present, default_present, c_radius, c_radius, pair_radius)
797 subcells=subcells, operator_type=
"PP", nlname=
"sab_cn")
798 disp%sab_cn => sab_cn
799 DEALLOCATE (c_radius, pair_radius, default_present)
803 CALL cnumber_init(qs_env, cnumbers, dcnum, 2, calculate_forces, disp_env=disp)
807 END SUBROUTINE get_cnumbers
831 SUBROUTINE eeq_solver(charges, lambda, eeq_energy, particle_set, kind_of, cell, &
832 chia, gam, gab, para_env, blacs_env, dft_control, eeq_sparam, &
833 totalcharge, ewald, ewald_env, ewald_pw, iounit, qs_env)
835 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: charges
836 REAL(kind=
dp),
INTENT(INOUT) :: lambda, eeq_energy
838 POINTER :: particle_set
839 INTEGER,
DIMENSION(:),
INTENT(IN) :: kind_of
841 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: chia, gam
842 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: gab
847 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: totalcharge
848 LOGICAL,
INTENT(IN),
OPTIONAL :: ewald
851 INTEGER,
INTENT(IN),
OPTIONAL :: iounit
854 CHARACTER(len=*),
PARAMETER :: routinen =
'eeq_solver'
856 INTEGER :: handle, ierror, iunit, natom, nkind, ns
857 LOGICAL :: do_direct, do_displ, do_ewald, &
858 do_sparse, do_sparse_auto, fm_created
859 REAL(kind=
dp) :: alpha, deth, ftime, qtot
863 CALL timeset(routinen, handle)
866 IF (
PRESENT(ewald)) do_ewald = ewald
869 IF (
PRESENT(totalcharge)) qtot = totalcharge
872 IF (
PRESENT(iounit)) iunit = iounit
875 do_direct = eeq_sparam%direct
876 natom =
SIZE(particle_set)
878 IF (dft_control%apply_period_efield .AND.
ASSOCIATED(dft_control%period_efield))
THEN
879 do_displ = dft_control%period_efield%displacement_field
881 do_sparse_auto = eeq_sparam%sparse_threshold > 0 .AND. natom >= eeq_sparam%sparse_threshold
885 do_sparse = eeq_sparam%sparse .OR. (do_sparse_auto .AND. .NOT. do_displ)
890 IF (.NOT. (do_ewald .AND. do_sparse .AND. .NOT. do_direct))
THEN
892 nrow_global=ns, ncol_global=ns)
899 cpassert(
PRESENT(ewald_env))
900 cpassert(
PRESENT(ewald_pw))
905 CALL fpbc_solver(charges, lambda, eeq_energy, eeq_mat, particle_set, &
906 kind_of, cell, chia, gam, gab, qtot, &
907 ewald_env, ewald_pw, iounit)
909 ELSE IF (do_sparse)
THEN
911 cpabort(
"Sparse periodic EEQ is not available with a displacement field")
913 cpassert(
PRESENT(qs_env))
915 CALL pbc_sparse_solver(charges, lambda, eeq_energy, particle_set, &
916 kind_of, cell, chia, gam, gab, qtot, &
917 ewald_env, ewald_pw, eeq_sparam, qs_env, ierror, iounit)
918 IF (ierror /= 0)
THEN
920 nrow_global=ns, ncol_global=ns)
924 CALL fpbc_solver(charges, lambda, eeq_energy, eeq_mat, particle_set, &
925 kind_of, cell, chia, gam, gab, qtot, &
926 ewald_env, ewald_pw, iounit)
934 CALL pbc_solver(charges, lambda, eeq_energy, eeq_mat, particle_set, &
935 kind_of, cell, chia, gam, gab, qtot, &
936 ewald_env, ewald_pw, eeq_sparam, ierror, iounit)
937 IF (ierror /= 0)
THEN
939 CALL fpbc_solver(charges, lambda, eeq_energy, eeq_mat, particle_set, &
940 kind_of, cell, chia, gam, gab, qtot, &
941 ewald_env, ewald_pw, iounit)
945 IF (qtot /= 0._dp)
THEN
948 eeq_energy = eeq_energy - 0.5_dp*qtot**2/alpha**2/deth
951 CALL mi_solver(charges, lambda, eeq_energy, eeq_mat, particle_set, kind_of, &
952 cell, chia, gam, gab, qtot, ftime)
954 WRITE (iunit,
'(A,T67,F14.3)')
" EEQ| Molecular solver time[s]", ftime
962 CALL timestop(handle)
981 SUBROUTINE mi_solver(charges, lambda, eeq_energy, eeq_mat, particle_set, kind_of, cell, &
982 chia, gam, gab, qtot, ftime)
984 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: charges
985 REAL(kind=
dp),
INTENT(INOUT) :: lambda, eeq_energy
987 TYPE(
particle_type),
DIMENSION(:),
INTENT(IN) :: particle_set
988 INTEGER,
DIMENSION(:),
INTENT(IN) :: kind_of
990 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: chia, gam
991 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: gab
992 REAL(kind=
dp),
INTENT(IN) :: qtot
993 REAL(kind=
dp),
INTENT(OUT) :: ftime
995 CHARACTER(len=*),
PARAMETER :: routinen =
'mi_solver'
997 INTEGER :: handle, ia, iac, iar, ic, ikind, ir, &
998 jkind, natom, ncloc, ncvloc, nkind, &
1000 INTEGER,
DIMENSION(:),
POINTER :: cind, cvind, rind, rvind
1001 REAL(kind=
dp) :: dr, grc, te, ti, xr
1002 REAL(kind=
dp),
DIMENSION(3) :: ri, rij, rj
1007 CALL timeset(routinen, handle)
1010 natom =
SIZE(particle_set)
1014 CALL cp_fm_get_info(eeq_mat, matrix_struct=mat_struct, para_env=para_env)
1015 CALL cp_fm_get_info(eeq_mat, nrow_local=nrloc, ncol_local=ncloc, &
1016 row_indices=rind, col_indices=cind)
1018 nrow_global=ns, ncol_global=1)
1020 CALL cp_fm_get_info(rhs_vec, nrow_local=nrvloc, ncol_local=ncvloc, &
1021 row_indices=rvind, col_indices=cvind)
1028 IF (iar > natom) cycle
1029 ikind = kind_of(iar)
1030 ri(1:3) = particle_set(iar)%r(1:3)
1033 IF (iac > natom) cycle
1034 jkind = kind_of(iac)
1035 rj(1:3) = particle_set(iac)%r(1:3)
1036 IF (iar == iac)
THEN
1037 grc = gam(ikind) + 2.0_dp*gab(ikind, ikind)*
oorootpi
1039 rij(1:3) = ri(1:3) - rj(1:3)
1040 rij =
pbc(rij, cell)
1042 grc = erf(gab(ikind, jkind)*dr)/dr
1044 eeq_mat%local_data(ir, ic) = grc
1053 IF (ia > natom)
THEN
1058 rhs_vec%local_data(ir, ic) = xr
1071 IF (ia <= natom)
THEN
1072 xr = rhs_vec%local_data(ir, ic)
1075 lambda = rhs_vec%local_data(ir, ic)
1079 CALL para_env%sum(lambda)
1080 CALL para_env%sum(charges)
1083 eeq_energy = 0.5*sum(charges(1:natom)*chia(1:natom)) - 0.5_dp*lambda*qtot
1090 CALL timestop(handle)
1092 END SUBROUTINE mi_solver
1117 SUBROUTINE pbc_sparse_solver(charges, lambda, eeq_energy, particle_set, &
1118 kind_of, cell, chia, gam, gab, qtot, &
1119 ewald_env, ewald_pw, eeq_sparam, qs_env, ierror, iounit)
1121 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: charges
1122 REAL(kind=
dp),
INTENT(INOUT) :: lambda, eeq_energy
1124 POINTER :: particle_set
1125 INTEGER,
DIMENSION(:),
INTENT(IN) :: kind_of
1127 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: chia, gam
1128 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: gab
1129 REAL(kind=
dp),
INTENT(IN) :: qtot
1134 INTEGER,
INTENT(OUT) :: ierror
1135 INTEGER,
OPTIONAL :: iounit
1137 CHARACTER(len=*),
PARAMETER :: routinen =
'pbc_sparse_solver'
1139 INTEGER :: handle, i, iter, iunit, max_iter, natom
1140 REAL(kind=
dp) :: alpha_cg, beta_cg, denom, eps_solver, &
1141 ftime, res, res_initial, rz, rz_new, &
1143 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: ap, aq, gradient, p, precond_diag, &
1145 TYPE(eeq_sparse_matrix_type) :: response
1147 CALL timeset(routinen, handle)
1151 IF (
PRESENT(iounit)) iunit = iounit
1152 natom =
SIZE(charges)
1153 max_iter = eeq_sparam%max_diis
1154 eps_solver = eeq_sparam%eps_diis
1157 CALL build_sparse_pbc_response(response, qs_env, particle_set, kind_of, cell, gam, gab, &
1158 ewald_env, eps_solver, iunit)
1160 ALLOCATE (ap(natom), aq(natom), gradient(natom), p(natom), precond_diag(natom), &
1161 residual(natom), work(natom), z(natom))
1163 precond_diag(i) = gam(kind_of(i)) + 2.0_dp*gab(kind_of(i), kind_of(i))*
oorootpi
1164 precond_diag(i) = max(precond_diag(i), sqrt(epsilon(1.0_dp)))
1168 lambda = (-qtot - sum(chia/precond_diag))/sum(1.0_dp/precond_diag)
1169 charges = -(chia + lambda)/precond_diag
1170 charges = charges + (qtot - sum(charges))/real(natom, kind=
dp)
1172 CALL apply_sparse_pbc_response(response, ewald_env, ewald_pw, cell, particle_set, &
1174 gradient(:) = aq + chia
1175 residual(:) = -gradient
1176 CALL project_eeq_charge_tangent(residual)
1177 res = norm2(residual)
1178 res_initial = max(res, sqrt(epsilon(1.0_dp)))
1181 IF (res >= eps_solver)
THEN
1182 CALL apply_eeq_constrained_diagonal_preconditioner(residual, precond_diag, z)
1184 rz = sum(residual*z)
1186 DO iter = 1, max_iter
1187 CALL apply_sparse_pbc_response(response, ewald_env, ewald_pw, cell, particle_set, &
1189 CALL project_eeq_charge_tangent(ap)
1191 IF (.NOT. (denom > sqrt(tiny(1.0_dp)) .AND. abs(denom) < huge(denom)))
THEN
1197 IF (.NOT. (abs(alpha_cg) < huge(alpha_cg)))
THEN
1201 charges = charges + alpha_cg*p
1202 residual(:) = residual - alpha_cg*ap
1204 charges = charges + (qtot - sum(charges))/real(natom, kind=
dp)
1205 CALL project_eeq_charge_tangent(residual)
1206 res = norm2(residual)
1207 IF (res < eps_solver)
EXIT
1208 IF (res > 100.0_dp*res_initial .OR. .NOT. (res < huge(res)))
THEN
1213 CALL apply_eeq_constrained_diagonal_preconditioner(residual, precond_diag, z)
1214 rz_new = sum(residual*z)
1215 IF (.NOT. (rz_new > 0.0_dp .AND. abs(rz_new) < huge(rz_new)))
THEN
1220 p(:) = z + beta_cg*p
1223 IF (iter > max_iter) ierror = 1
1226 IF (ierror == 0)
THEN
1227 CALL apply_sparse_pbc_response(response, ewald_env, ewald_pw, cell, particle_set, &
1229 gradient(:) = aq + chia
1230 lambda = -sum(gradient)/real(natom, kind=
dp)
1231 eeq_energy = 0.5_dp*sum(charges*aq) + sum(charges*chia)
1237 IF (ierror /= 0)
THEN
1238 WRITE (iunit,
'(A,T50,I6,T61,E20.5)') &
1239 " EEQ| Sparse PBC solver failed: iterations/accuracy ", iter, res
1241 WRITE (iunit,
'(A,T50,I6,T61,E20.5)') &
1242 " EEQ| Sparse PBC solver: iterations/accuracy ", iter, res
1244 WRITE (iunit,
'(A,T67,F14.3)')
" EEQ| Sparse PBC solver: time[s]", ftime
1247 DEALLOCATE (ap, aq, gradient, p, precond_diag, residual, work, z)
1248 CALL release_sparse_pbc_response(response)
1249 CALL timestop(handle)
1251 END SUBROUTINE pbc_sparse_solver
1266 SUBROUTINE build_sparse_pbc_response(response, qs_env, particle_set, kind_of, cell, gam, gab, &
1267 ewald_env, eps_solver, iunit)
1269 TYPE(eeq_sparse_matrix_type),
INTENT(OUT) :: response
1272 POINTER :: particle_set
1273 INTEGER,
DIMENSION(:),
INTENT(IN) :: kind_of
1275 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: gam
1276 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: gab
1278 REAL(kind=
dp),
INTENT(IN) :: eps_solver
1279 INTEGER,
INTENT(IN) :: iunit
1281 INTEGER :: iatom, ix, iy, iz, jatom, &
1282 n_candidates_global, n_pairs, &
1283 n_pairs_alloc, n_pairs_global, &
1284 n_unique, natom, owner
1285 INTEGER(KIND=int_8),
ALLOCATABLE,
DIMENSION(:) :: pair_key
1286 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: pair_order
1287 INTEGER,
DIMENSION(3) :: periodic
1288 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: default_present
1289 REAL(kind=
dp) :: drop_tolerance, neighbor_cutoff, rmax, &
1291 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: c_radius
1292 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: pair_radius
1293 REAL(kind=
dp),
DIMENSION(3) :: cell_extent, vertex
1294 REAL(kind=
dp),
DIMENSION(3, 3) :: hmat
1302 DIMENSION(:),
POINTER :: nl_iterator
1306 NULLIFY (atomic_kind_set, distribution_1d, distribution_2d, molecule_set, nl_iterator, sab_eeq)
1309 natom =
SIZE(particle_set)
1310 drop_tolerance = max(100.0_dp*epsilon(1.0_dp), &
1311 eps_solver/(1000.0_dp*real(max(1, natom), kind=
dp)))
1316 CALL get_cell(cell, h=hmat, periodic=periodic)
1317 WHERE (periodic /= 0)
1318 cell_extent = 0.5_dp
1320 cell_extent = 1.0_dp
1322 neighbor_cutoff = 0.0_dp
1326 vertex = matmul(hmat, cell_extent*real([ix, iy, iz], kind=
dp))
1327 neighbor_cutoff = max(neighbor_cutoff, norm2(vertex))
1331 neighbor_cutoff = min(rmax, neighbor_cutoff + &
1332 1.0e-10_dp*max(1.0_dp, neighbor_cutoff))
1334 CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set, &
1335 distribution_2d=distribution_2d, local_particles=distribution_1d, &
1336 molecule_set=molecule_set)
1337 ALLOCATE (c_radius(
SIZE(atomic_kind_set)), default_present(
SIZE(atomic_kind_set)), &
1338 pair_radius(
SIZE(atomic_kind_set),
SIZE(atomic_kind_set)), &
1339 atom2d(
SIZE(atomic_kind_set)))
1340 c_radius = 0.5_dp*neighbor_cutoff
1341 default_present = .true.
1343 CALL atom2d_build(atom2d, distribution_1d, distribution_2d, atomic_kind_set, &
1344 molecule_set, .false., particle_set=particle_set)
1345 CALL pair_radius_setup(default_present, default_present, c_radius, c_radius, pair_radius)
1347 subcells=subcells, mic=.false., symmetric=.true., &
1348 operator_type=
"PP", nlname=
"sab_eeq_sparse")
1349 DEALLOCATE (c_radius, pair_radius, default_present)
1352 ALLOCATE (response%diag(natom), source=0.0_dp)
1354 owner = mod(iatom - 1, para_env%num_pe)
1355 IF (owner == para_env%mepos)
THEN
1356 response%diag(iatom) = eeq_short_range_element(iatom, iatom, particle_set, kind_of, &
1357 cell, gam, gab, ewald_env)
1368 IF (iatom /= jatom) n_pairs_alloc = n_pairs_alloc + 1
1372 ALLOCATE (pair_key(n_pairs_alloc), pair_order(n_pairs_alloc))
1377 IF (iatom == jatom) cycle
1378 n_pairs_alloc = n_pairs_alloc + 1
1379 pair_key(n_pairs_alloc) = int(min(iatom, jatom) - 1,
int_8)*int(natom,
int_8) + &
1380 int(max(iatom, jatom),
int_8)
1385 IF (n_pairs_alloc > 0)
CALL sort(pair_key, n_pairs_alloc, pair_order)
1387 DO iatom = 1, n_pairs_alloc
1388 IF (iatom == 1)
THEN
1389 n_unique = n_unique + 1
1390 ELSE IF (pair_key(iatom) /= pair_key(iatom - 1))
THEN
1391 n_unique = n_unique + 1
1394 ALLOCATE (response%row(n_unique), response%col(n_unique), response%value(n_unique))
1396 DO iatom = 1, n_pairs_alloc
1398 IF (pair_key(iatom) == pair_key(iatom - 1)) cycle
1400 jatom = int(
modulo(pair_key(iatom) - 1_int_8, int(natom,
int_8))) + 1
1401 owner = int((pair_key(iatom) - 1_int_8)/int(natom,
int_8)) + 1
1402 value = eeq_short_range_element(owner, jatom, particle_set, kind_of, cell, &
1403 gam, gab, ewald_env)
1404 IF (abs(
value) <= drop_tolerance) cycle
1405 n_pairs = n_pairs + 1
1406 response%row(n_pairs) = owner
1407 response%col(n_pairs) = jatom
1408 response%value(n_pairs) =
value
1410 DEALLOCATE (pair_key, pair_order)
1411 response%nactive = n_pairs
1413 n_pairs_global = n_pairs
1414 CALL para_env%sum(n_pairs_global)
1415 n_candidates_global = n_unique
1416 CALL para_env%sum(n_candidates_global)
1418 WRITE (iunit,
'(A,T54,I12)')
" EEQ| Sparse short-range candidate atom pairs", n_candidates_global
1419 WRITE (iunit,
'(A,T54,I12)')
" EEQ| Sparse short-range retained atom pairs", n_pairs_global
1420 WRITE (iunit,
'(A,T61,E20.5)')
" EEQ| Sparse short-range drop tolerance", drop_tolerance
1421 WRITE (iunit,
'(A,T61,E20.5)')
" EEQ| Sparse short-range MIC cutoff", neighbor_cutoff
1424 END SUBROUTINE build_sparse_pbc_response
1438 FUNCTION eeq_short_range_element(iatom, jatom, particle_set, kind_of, cell, gam, gab, &
1439 ewald_env)
RESULT(element)
1441 INTEGER,
INTENT(IN) :: iatom, jatom
1442 TYPE(
particle_type),
DIMENSION(:),
INTENT(IN) :: particle_set
1443 INTEGER,
DIMENSION(:),
INTENT(IN) :: kind_of
1445 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: gam
1446 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: gab
1448 REAL(kind=
dp) :: element
1450 INTEGER :: ix, iy, iz
1451 INTEGER,
DIMENSION(3) :: cvec, ncell, periodic
1452 REAL(kind=
dp) :: alpha, dr, rcut, rmax
1453 REAL(kind=
dp),
DIMENSION(3) :: rij, rijl
1454 REAL(kind=
dp),
DIMENSION(3, 3) :: hmat
1458 CALL get_cell(cell, h=hmat, periodic=periodic)
1462 WHERE (periodic == 0) ncell = 0
1464 rij =
pbc(particle_set(iatom)%r - particle_set(jatom)%r, cell)
1466 DO ix = -ncell(1), ncell(1)
1467 DO iy = -ncell(2), ncell(2)
1468 DO iz = -ncell(3), ncell(3)
1470 rijl = rij + matmul(hmat, cvec)
1472 IF (dr > rmax) cycle
1473 IF (iatom == jatom .AND. dr < 1.0e-5_dp)
THEN
1474 element = element + gam(kind_of(iatom)) + &
1475 2.0_dp*gab(kind_of(iatom), kind_of(iatom))*
oorootpi - &
1477 ELSE IF (dr > 1.0e-12_dp)
THEN
1478 element = element + &
1479 (erf(gab(kind_of(iatom), kind_of(jatom))*dr) - erf(alpha*dr))/dr
1485 END FUNCTION eeq_short_range_element
1498 SUBROUTINE apply_sparse_pbc_response(response, ewald_env, ewald_pw, cell, particle_set, &
1499 charges, potential, work)
1501 TYPE(eeq_sparse_matrix_type),
INTENT(IN) :: response
1505 TYPE(
particle_type),
DIMENSION(:),
INTENT(IN) :: particle_set
1506 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN),
TARGET :: charges
1507 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: potential, work
1509 INTEGER :: i, ia, ja
1513 potential = response%diag*charges
1514 DO i = 1, response%nactive
1515 ia = response%row(i)
1516 ja = response%col(i)
1517 potential(ia) = potential(ia) + response%value(i)*charges(ja)
1518 potential(ja) = potential(ja) + response%value(i)*charges(ia)
1520 CALL para_env%sum(potential)
1522 CALL apply_potential(ewald_env, ewald_pw, cell, particle_set, charges, work)
1523 potential = potential + work
1525 END SUBROUTINE apply_sparse_pbc_response
1533 SUBROUTINE apply_eeq_constrained_diagonal_preconditioner(residual, diagonal, RESULT)
1535 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: residual, diagonal
1536 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: result
1538 REAL(kind=
dp) :: constraint_shift
1540 result = residual/diagonal
1541 constraint_shift = sum(result)/sum(1.0_dp/diagonal)
1542 result = result - constraint_shift/diagonal
1544 END SUBROUTINE apply_eeq_constrained_diagonal_preconditioner
1550 SUBROUTINE project_eeq_charge_tangent(vector)
1552 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: vector
1554 vector = vector - sum(vector)/real(
SIZE(vector), kind=
dp)
1556 END SUBROUTINE project_eeq_charge_tangent
1562 SUBROUTINE release_sparse_pbc_response(response)
1564 TYPE(eeq_sparse_matrix_type),
INTENT(INOUT) :: response
1566 IF (
ALLOCATED(response%col))
DEALLOCATE (response%col)
1567 IF (
ALLOCATED(response%row))
DEALLOCATE (response%row)
1568 IF (
ALLOCATED(response%diag))
DEALLOCATE (response%diag)
1569 IF (
ALLOCATED(response%value))
DEALLOCATE (response%value)
1570 response%nactive = 0
1572 END SUBROUTINE release_sparse_pbc_response
1593 SUBROUTINE pbc_solver(charges, lambda, eeq_energy, eeq_mat, particle_set, &
1594 kind_of, cell, chia, gam, gab, qtot, &
1595 ewald_env, ewald_pw, eeq_sparam, ierror, iounit)
1597 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: charges
1598 REAL(kind=
dp),
INTENT(INOUT) :: lambda, eeq_energy
1600 TYPE(
particle_type),
DIMENSION(:),
INTENT(IN) :: particle_set
1601 INTEGER,
DIMENSION(:),
INTENT(IN) :: kind_of
1603 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: chia, gam
1604 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: gab
1605 REAL(kind=
dp),
INTENT(IN) :: qtot
1609 INTEGER,
INTENT(OUT) :: ierror
1610 INTEGER,
OPTIONAL :: iounit
1612 CHARACTER(len=*),
PARAMETER :: routinen =
'pbc_solver'
1614 INTEGER :: ewald_type, handle, i, iac, iar, ic, ikind, info, ir, iunit, iv, ix, iy, iz, &
1615 jkind, max_diis, mdiis, natom, ncloc, ndiis, nkind, now, nrloc, ns, sdiis
1616 INTEGER,
DIMENSION(3) :: cvec, ncell, periodic
1617 INTEGER,
DIMENSION(:),
POINTER :: cind, rind
1618 REAL(kind=
dp) :: ad, alpha, astep, deth, dr, eeqn, &
1619 eps_diis, ftime, grc1, grc2, rcut, &
1620 res, resin, rmax, te, ti
1621 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: bvec, dvec
1622 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: dmat, fvec, vmat, xvec
1623 REAL(kind=
dp),
DIMENSION(3) :: ri, rij, rijl, rj
1624 REAL(kind=
dp),
DIMENSION(3, 3) :: hmat
1625 REAL(kind=
dp),
DIMENSION(:),
POINTER :: rhs, rv0, xv0
1630 CALL timeset(routinen, handle)
1636 IF (
PRESENT(iounit)) iunit = iounit
1638 natom =
SIZE(particle_set)
1641 CALL get_cell(cell=cell, deth=deth)
1642 CALL ewald_env_get(ewald_env, alpha=alpha, rcut=rcut, ewald_type=ewald_type)
1645 CALL cp_abort(__location__,
"Only SPME Ewald method available with EEQ.")
1650 CALL get_cell(cell, h=hmat, periodic=periodic)
1654 IF (periodic(1) == 0) ncell(1) = 0
1655 IF (periodic(2) == 0) ncell(2) = 0
1656 IF (periodic(3) == 0) ncell(3) = 0
1658 CALL mi_solver(charges, lambda, eeqn, eeq_mat, particle_set, kind_of, cell, &
1659 chia, gam, gab, qtot, ftime)
1661 WRITE (iunit,
'(A,T67,F14.3)')
" EEQ| Iterative PBC guess time[s]", ftime
1663 CALL cp_fm_get_info(eeq_mat, matrix_struct=mat_struct, para_env=para_env)
1668 CALL cp_fm_get_info(eeq_mat, nrow_local=nrloc, ncol_local=ncloc, &
1669 row_indices=rind, col_indices=cind)
1674 IF (iar <= natom)
THEN
1675 ikind = kind_of(iar)
1676 ri(1:3) = particle_set(iar)%r(1:3)
1680 IF (iac > natom .AND. iar > natom)
THEN
1681 eeq_mat%local_data(ir, ic) = 0.0_dp
1683 ELSE IF ((iac > natom) .OR. (iar > natom))
THEN
1684 eeq_mat%local_data(ir, ic) = 1.0_dp
1687 jkind = kind_of(iac)
1688 rj(1:3) = particle_set(iac)%r(1:3)
1689 rij(1:3) = ri(1:3) - rj(1:3)
1690 rij =
pbc(rij, cell)
1691 DO ix = -ncell(1), ncell(1)
1692 DO iy = -ncell(2), ncell(2)
1693 DO iz = -ncell(3), ncell(3)
1695 rijl = rij + matmul(hmat, cvec)
1697 IF (dr > rmax) cycle
1698 IF (iar == iac .AND. dr < 0.00001_dp)
THEN
1699 grc1 = gam(ikind) + 2.0_dp*gab(ikind, ikind)*
oorootpi - ad
1701 grc1 = erf(gab(ikind, jkind)*dr)/dr - erf(alpha*dr)/dr
1703 eeq_mat%local_data(ir, ic) = eeq_mat%local_data(ir, ic) + grc1
1712 row_indices=rind, col_indices=cind)
1717 IF (iar <= natom)
THEN
1718 ikind = kind_of(iar)
1719 ri(1:3) = particle_set(iar)%r(1:3)
1723 IF (iac > natom .AND. iar > natom)
THEN
1724 pmat%local_data(ir, ic) = 0.0_dp
1726 ELSE IF ((iac > natom) .OR. (iar > natom))
THEN
1727 pmat%local_data(ir, ic) = 1.0_dp
1730 jkind = kind_of(iac)
1731 rj(1:3) = particle_set(iac)%r(1:3)
1732 rij(1:3) = ri(1:3) - rj(1:3)
1733 rij =
pbc(rij, cell)
1734 IF (iar == iac)
THEN
1735 grc2 = gam(ikind) + 2.0_dp*gab(ikind, ikind)*
oorootpi
1737 grc2 = erf(gab(ikind, jkind)*dr)/dr
1739 pmat%local_data(ir, ic) = grc2
1749 rhs(1:natom) = chia(1:natom)
1752 ALLOCATE (xv0(ns), rv0(ns))
1754 xv0(1:natom) = charges(1:natom)
1757 max_diis = eeq_sparam%max_diis
1758 mdiis = eeq_sparam%mdiis
1759 sdiis = eeq_sparam%sdiis
1760 eps_diis = eeq_sparam%eps_diis
1761 astep = eeq_sparam%alpha
1762 ALLOCATE (xvec(ns, mdiis), fvec(ns, mdiis), bvec(ns))
1763 xvec = 0.0_dp; fvec = 0.0_dp
1764 ALLOCATE (vmat(mdiis, mdiis), dmat(mdiis + 1, mdiis + 1), dvec(mdiis + 1))
1765 dmat = 0.0_dp; dvec = 0.0_dp
1768 CALL get_energy_gradient(eeqn, eeq_mat, mmat, ewald_env, ewald_pw, &
1769 cell, particle_set, xv0, rhs, rv0)
1774 IF (res > 10._dp*resin)
EXIT
1775 IF (res < eps_diis)
EXIT
1777 now = mod(iv - 1, mdiis) + 1
1778 ndiis = min(iv, mdiis)
1779 xvec(1:ns, now) = xv0(1:ns)
1780 fvec(1:ns, now) = rv0(1:ns)
1782 vmat(now, i) = sum(fvec(:, now)*fvec(:, i))
1783 vmat(i, now) = vmat(now, i)
1785 IF (ndiis < sdiis)
THEN
1786 xv0(1:ns) = xv0(1:ns) + astep*rv0(1:ns)
1789 dvec(ndiis + 1) = 1.0_dp
1790 dmat(1:ndiis, 1:ndiis) = vmat(1:ndiis, 1:ndiis)
1791 dmat(ndiis + 1, 1:ndiis) = 1.0_dp
1792 dmat(1:ndiis, ndiis + 1) = 1.0_dp
1793 dmat(ndiis + 1, ndiis + 1) = 0.0_dp
1794 CALL invmat(dmat(1:ndiis + 1, 1:ndiis + 1), info)
1795 dvec(1:ndiis + 1) = matmul(dmat(1:ndiis + 1, 1:ndiis + 1), dvec(1:ndiis + 1))
1796 xv0(1:ns) = matmul(xvec(1:ns, 1:ndiis), dvec(1:ndiis))
1797 xv0(1:ns) = xv0(1:ns) + matmul(fvec(1:ns, 1:ndiis), dvec(1:ndiis))
1800 CALL get_energy_gradient(eeqn, eeq_mat, mmat, ewald_env, ewald_pw, &
1801 cell, particle_set, xv0, rhs, rv0)
1803 charges(1:natom) = xv0(1:natom)
1806 IF (res > eps_diis) ierror = 1
1808 DEALLOCATE (xvec, fvec, bvec)
1809 DEALLOCATE (vmat, dmat, dvec)
1810 DEALLOCATE (xv0, rv0)
1817 IF (ierror == 1)
THEN
1818 WRITE (iunit,
'(A)')
" EEQ| PBC solver failed to converge "
1820 WRITE (iunit,
'(A,T50,I4,T61,E20.5)')
" EEQ| PBC solver: iterations/accuracy ", iv, res
1822 WRITE (iunit,
'(A,T67,F14.3)')
" EEQ| Iterative PBC solver: time[s]", te - ti
1824 CALL timestop(handle)
1826 END SUBROUTINE pbc_solver
1845 SUBROUTINE fpbc_solver(charges, lambda, eeq_energy, eeq_mat, particle_set, &
1846 kind_of, cell, chia, gam, gab, qtot, ewald_env, ewald_pw, iounit)
1848 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: charges
1849 REAL(kind=
dp),
INTENT(INOUT) :: lambda, eeq_energy
1851 TYPE(
particle_type),
DIMENSION(:),
INTENT(IN) :: particle_set
1852 INTEGER,
DIMENSION(:),
INTENT(IN) :: kind_of
1854 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: chia, gam
1855 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: gab
1856 REAL(kind=
dp),
INTENT(IN) :: qtot
1859 INTEGER,
INTENT(IN),
OPTIONAL :: iounit
1861 CHARACTER(len=*),
PARAMETER :: routinen =
'fpbc_solver'
1863 INTEGER :: ewald_type, handle, ia, iac, iar, ic, &
1864 ikind, ir, iunit, ix, iy, iz, jkind, &
1865 natom, ncloc, ncvloc, nkind, nrloc, &
1867 INTEGER,
DIMENSION(3) :: cvec, ncell, periodic
1868 INTEGER,
DIMENSION(:),
POINTER :: cind, cvind, rind, rvind
1869 REAL(kind=
dp) :: ad, alpha, deth, dr, grc1, rcut, rmax, &
1871 REAL(kind=
dp),
DIMENSION(3) :: ri, rij, rijl, rj
1872 REAL(kind=
dp),
DIMENSION(3, 3) :: hmat
1873 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pval, xval
1878 CALL timeset(routinen, handle)
1882 IF (
PRESENT(iounit)) iunit = iounit
1884 natom =
SIZE(particle_set)
1888 CALL get_cell(cell=cell, deth=deth)
1889 CALL ewald_env_get(ewald_env, alpha=alpha, rcut=rcut, ewald_type=ewald_type)
1892 CALL cp_abort(__location__,
"Only SPME Ewald method available with EEQ.")
1897 CALL get_cell(cell, h=hmat, periodic=periodic)
1901 IF (periodic(1) == 0) ncell(1) = 0
1902 IF (periodic(2) == 0) ncell(2) = 0
1903 IF (periodic(3) == 0) ncell(3) = 0
1905 CALL cp_fm_get_info(eeq_mat, matrix_struct=mat_struct, para_env=para_env)
1907 CALL cp_fm_get_info(eeq_mat, nrow_local=nrloc, ncol_local=ncloc, &
1908 row_indices=rind, col_indices=cind)
1910 nrow_global=ns, ncol_global=1)
1912 CALL cp_fm_get_info(rhs_vec, nrow_local=nrvloc, ncol_local=ncvloc, &
1913 row_indices=rvind, col_indices=cvind)
1918 IF (iar <= natom)
THEN
1919 ikind = kind_of(iar)
1920 ri(1:3) = particle_set(iar)%r(1:3)
1924 IF (iac > natom .AND. iar > natom)
THEN
1925 eeq_mat%local_data(ir, ic) = 0.0_dp
1927 ELSE IF ((iac > natom) .OR. (iar > natom))
THEN
1928 eeq_mat%local_data(ir, ic) = 1.0_dp
1931 jkind = kind_of(iac)
1932 rj(1:3) = particle_set(iac)%r(1:3)
1933 rij(1:3) = ri(1:3) - rj(1:3)
1934 rij =
pbc(rij, cell)
1935 DO ix = -ncell(1), ncell(1)
1936 DO iy = -ncell(2), ncell(2)
1937 DO iz = -ncell(3), ncell(3)
1939 rijl = rij + matmul(hmat, cvec)
1941 IF (dr > rmax) cycle
1942 IF (iar == iac .AND. dr < 0.0001_dp)
THEN
1943 grc1 = gam(ikind) + 2.0_dp*gab(ikind, ikind)*
oorootpi - ad
1945 grc1 = erf(gab(ikind, jkind)*dr)/dr - erf(alpha*dr)/dr
1947 eeq_mat%local_data(ir, ic) = eeq_mat%local_data(ir, ic) + grc1
1954 ALLOCATE (xval(natom), pval(natom))
1958 CALL apply_potential(ewald_env, ewald_pw, cell, particle_set, xval, pval)
1962 IF (iar /= ia) cycle
1965 IF (iac > natom) cycle
1966 eeq_mat%local_data(ir, ic) = eeq_mat%local_data(ir, ic) + pval(iac)
1970 DEALLOCATE (xval, pval)
1978 IF (ia > natom)
THEN
1983 rhs_vec%local_data(ir, ic) = xr
1996 IF (ia <= natom)
THEN
1997 xr = rhs_vec%local_data(ir, ic)
2000 lambda = rhs_vec%local_data(ir, ic)
2004 CALL para_env%sum(lambda)
2005 CALL para_env%sum(charges)
2008 eeq_energy = 0.5*sum(charges(1:natom)*chia(1:natom)) - 0.5_dp*lambda*qtot
2015 WRITE (iunit,
'(A,T67,F14.3)')
" EEQ| Direct PBC solver: time[s]", te - ti
2017 CALL timestop(handle)
2019 END SUBROUTINE fpbc_solver
2030 SUBROUTINE apply_potential(ewald_env, ewald_pw, cell, particle_set, charges, potential)
2034 TYPE(
particle_type),
DIMENSION(:),
INTENT(IN) :: particle_set
2035 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN),
TARGET :: charges
2036 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: potential
2042 CALL spme_potential(ewald_env, ewald_pw, cell, particle_set, charges, &
2043 particle_set, potential)
2044 CALL para_env%sum(potential)
2046 END SUBROUTINE apply_potential
2061 SUBROUTINE get_energy_gradient(eeqn, fm_mat, mmat, ewald_env, ewald_pw, &
2062 cell, particle_set, charges, rhs, potential)
2063 REAL(kind=
dp),
INTENT(INOUT) :: eeqn
2068 TYPE(
particle_type),
DIMENSION(:),
INTENT(IN) :: particle_set
2069 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN),
POINTER :: charges
2070 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: rhs
2071 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: potential
2074 REAL(kind=
dp) :: lambda
2075 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: mvec
2082 CALL spme_potential(ewald_env, ewald_pw, cell, particle_set, charges(1:na), &
2083 particle_set, potential(1:na))
2084 CALL para_env%sum(potential(1:na))
2085 CALL cp_fm_matvec(fm_mat, charges, potential, alpha=1.0_dp, beta=1.0_dp)
2086 eeqn = 0.5_dp*sum(charges(1:na)*potential(1:na)) + sum(charges(1:na)*rhs(1:na))
2087 potential(1:ns) = potential(1:ns) + rhs(1:ns)
2089 CALL cp_fm_matvec(mmat, potential, mvec, alpha=-1.0_dp, beta=0.0_dp)
2090 lambda = -sum(mvec(1:na))/real(na, kind=
dp)
2091 potential(1:na) = mvec(1:na) + lambda
2094 END SUBROUTINE get_energy_gradient
2104 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: charges
2105 REAL(kind=
dp),
INTENT(OUT) :: ef_energy
2107 COMPLEX(KIND=dp) :: zdeta
2108 COMPLEX(KIND=dp),
DIMENSION(3) :: zi
2109 INTEGER :: ia, idir, natom
2111 REAL(kind=
dp) :: kr, omega, q
2112 REAL(kind=
dp),
DIMENSION(3) :: ci, dfilter, fieldpol, fpolvec, kvec, &
2114 REAL(kind=
dp),
DIMENSION(3, 3) :: hmat
2119 CALL get_qs_env(qs_env, natom=natom, dft_control=dft_control)
2120 CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set)
2122 IF (dft_control%apply_period_efield)
THEN
2123 dfield = dft_control%period_efield%displacement_field
2125 IF (
ALLOCATED(dft_control%period_efield%strength_list))
THEN
2126 cpabort(
"use of strength_list not implemented for eeq_efield_energy")
2129 fieldpol = dft_control%period_efield%polarisation
2130 fieldpol = fieldpol/norm2(fieldpol)
2131 fieldpol = -fieldpol*dft_control%period_efield%strength
2132 hmat = cell%hmat(:, :)/
twopi
2134 fpolvec(idir) = fieldpol(1)*hmat(1, idir) + fieldpol(2)*hmat(2, idir) &
2135 + fieldpol(3)*hmat(3, idir)
2138 zi(:) = cmplx(1._dp, 0._dp,
dp)
2141 ria = particle_set(ia)%r
2142 ria =
pbc(ria, cell)
2144 kvec(:) =
twopi*cell%h_inv(idir, :)
2145 kr = sum(kvec(:)*ria(:))
2146 zdeta = cmplx(cos(kr), sin(kr), kind=
dp)**q
2147 zi(idir) = zi(idir)*zdeta
2152 dfilter(1:3) = dft_control%period_efield%d_filter(1:3)
2154 ci = matmul(hmat, qi)/omega
2157 ef_energy = ef_energy + dfilter(idir)*(fieldpol(idir) - 2._dp*
twopi*ci(idir))**2
2159 ef_energy = -0.25_dp*omega/
twopi*ef_energy
2161 ef_energy = sum(fpolvec(:)*qi(:))
2164 ELSE IF (dft_control%apply_efield)
THEN
2166 fieldpol = dft_control%efield_fields(1)%efield%polarisation* &
2167 dft_control%efield_fields(1)%efield%strength
2171 ria = particle_set(ia)%r
2172 ria =
pbc(ria, cell)
2174 ef_energy = ef_energy - q*sum(fieldpol*ria)
2178 cpabort(
"apply field")
2190 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: efr
2192 INTEGER :: ia, idir, natom
2195 REAL(kind=
dp),
DIMENSION(3) :: fieldpol, fpolvec, kvec, ria
2196 REAL(kind=
dp),
DIMENSION(3, 3) :: hmat
2201 CALL get_qs_env(qs_env, natom=natom, dft_control=dft_control)
2202 CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set)
2204 IF (dft_control%apply_period_efield)
THEN
2205 dfield = dft_control%period_efield%displacement_field
2207 IF (
ALLOCATED(dft_control%period_efield%strength_list))
THEN
2208 cpabort(
"use of strength_list not implemented for eeq_efield_pot")
2211 fieldpol = dft_control%period_efield%polarisation
2212 fieldpol = fieldpol/norm2(fieldpol)
2213 fieldpol = -fieldpol*dft_control%period_efield%strength
2214 hmat = cell%hmat(:, :)/
twopi
2216 fpolvec(idir) = fieldpol(1)*hmat(1, idir) + fieldpol(2)*hmat(2, idir) &
2217 + fieldpol(3)*hmat(3, idir)
2226 ria = particle_set(ia)%r
2227 ria =
pbc(ria, cell)
2229 kvec(:) =
twopi*cell%h_inv(idir, :)
2230 kr = sum(kvec(:)*ria(:))
2231 efr(ia) = efr(ia) + kr*fpolvec(idir)
2236 ELSE IF (dft_control%apply_efield)
THEN
2238 fieldpol = dft_control%efield_fields(1)%efield%polarisation* &
2239 dft_control%efield_fields(1)%efield%strength
2242 ria = particle_set(ia)%r
2243 ria =
pbc(ria, cell)
2244 efr(ia) = -sum(fieldpol*ria)
2248 cpabort(
"apply field")
2261 SUBROUTINE eeq_dfield_pot(charges, dft_control, particle_set, cell, efr)
2262 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: charges
2264 TYPE(
particle_type),
DIMENSION(:),
INTENT(IN) :: particle_set
2266 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: efr
2268 COMPLEX(KIND=dp) :: zdeta
2269 COMPLEX(KIND=dp),
DIMENSION(3) :: zi
2270 INTEGER :: ia, idir, natom
2271 REAL(kind=
dp) :: kr, omega, q
2272 REAL(kind=
dp),
DIMENSION(3) :: ci, dfilter, fieldpol, kvec, qi, ria
2273 REAL(kind=
dp),
DIMENSION(3, 3) :: hmat
2275 natom =
SIZE(particle_set)
2277 IF (
ALLOCATED(dft_control%period_efield%strength_list))
THEN
2278 cpabort(
"use of strength_list not implemented for eeq_dfield_pot")
2281 dfilter(1:3) = dft_control%period_efield%d_filter(1:3)
2282 fieldpol = dft_control%period_efield%polarisation
2283 fieldpol = fieldpol/norm2(fieldpol)
2284 fieldpol = -fieldpol*dft_control%period_efield%strength
2285 hmat = cell%hmat(:, :)/
twopi
2288 zi(:) = cmplx(1._dp, 0._dp,
dp)
2291 ria = particle_set(ia)%r
2292 ria =
pbc(ria, cell)
2294 kvec(:) =
twopi*cell%h_inv(idir, :)
2295 kr = sum(kvec(:)*ria(:))
2296 zdeta = cmplx(cos(kr), sin(kr), kind=
dp)**q
2297 zi(idir) = zi(idir)*zdeta
2301 ci = matmul(hmat, qi)/omega
2302 ci = dfilter*(fieldpol - 2._dp*
twopi*ci)
2304 ria = particle_set(ia)%r
2305 ria =
pbc(ria, cell)
2306 efr(ia) = efr(ia) - sum(ci*ria)
2309 END SUBROUTINE eeq_dfield_pot
2319 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: charges, qlag
2321 INTEGER :: atom_a, ia, iatom, ikind, natom, nkind
2322 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: atom_of_kind
2324 REAL(kind=
dp),
DIMENSION(3) :: fieldpol
2334 dft_control=dft_control, &
2335 cell=cell, particle_set=particle_set, &
2336 nkind=nkind, natom=natom, &
2337 para_env=para_env, &
2338 local_particles=local_particles)
2340 fieldpol = dft_control%efield_fields(1)%efield%polarisation* &
2341 dft_control%efield_fields(1)%efield%strength
2343 CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set)
2348 force(ikind)%efield = 0.0_dp
2349 DO ia = 1, local_particles%n_el(ikind)
2350 iatom = local_particles%list(ikind)%array(ia)
2351 q = charges(iatom) - qlag(iatom)
2352 atom_a = atom_of_kind(iatom)
2353 force(ikind)%efield(1:3, atom_a) = -q*fieldpol(1:3)
2355 CALL para_env%sum(force(ikind)%efield)
2368 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: charges, qlag
2370 INTEGER :: atom_a, ia, iatom, ikind, natom, nkind
2371 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: atom_of_kind
2372 LOGICAL :: dfield, use_virial
2374 REAL(kind=
dp),
DIMENSION(3) :: fa, fieldpol, ria
2375 REAL(kind=
dp),
DIMENSION(3, 3) :: pve
2386 dft_control=dft_control, &
2387 cell=cell, particle_set=particle_set, &
2389 nkind=nkind, natom=natom, &
2390 para_env=para_env, &
2391 local_particles=local_particles)
2393 dfield = dft_control%period_efield%displacement_field
2394 cpassert(.NOT. dfield)
2396 IF (
ALLOCATED(dft_control%period_efield%strength_list))
THEN
2397 cpabort(
"use of strength_list not implemented for eeq_efield_force_periodic")
2400 fieldpol = dft_control%period_efield%polarisation
2401 fieldpol = fieldpol/norm2(fieldpol)
2402 fieldpol = -fieldpol*dft_control%period_efield%strength
2404 use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
2406 CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set)
2412 force(ikind)%efield = 0.0_dp
2413 DO ia = 1, local_particles%n_el(ikind)
2414 iatom = local_particles%list(ikind)%array(ia)
2415 q = charges(iatom) - qlag(iatom)
2416 fa(1:3) = q*fieldpol(1:3)
2417 atom_a = atom_of_kind(iatom)
2418 force(ikind)%efield(1:3, atom_a) = fa
2419 IF (use_virial)
THEN
2420 ria = particle_set(ia)%r
2421 ria =
pbc(ria, cell)
2426 CALL para_env%sum(force(ikind)%efield)
2428 virial%pv_virial = virial%pv_virial + pve
static GRID_HOST_DEVICE int modulo(int a, int m)
Equivalent of Fortran's MODULO, which always return a positive number. https://gcc....
Define the atomic kind types and their sub types.
subroutine, public get_atomic_kind_set(atomic_kind_set, atom_of_kind, kind_of, natom_of_kind, maxatom, natom, nshell, fist_potential_present, shell_present, shell_adiabatic, shell_check_distance, damping_present)
Get attributes of an atomic kind set.
subroutine, public get_atomic_kind(atomic_kind, fist_potential, element_symbol, name, mass, kind_number, natom, atom_list, rcov, rvdw, z, qeff, apol, cpol, mm_radius, shell, shell_active, damping)
Get attributes of an atomic kind.
Holds information on atomic properties.
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.
real(kind=dp) function, public plane_distance(h, k, l, cell)
Calculate the distance between two lattice planes as defined by a triple of Miller indices (hkl).
methods related to the blacs parallel environment
Defines control structures, which contain the parameters and the settings for the DFT-based calculati...
Basic linear algebra operations for full matrices.
subroutine, public cp_fm_solve(matrix_a, general_a)
computes the the solution to A*b=A_general using lu decomposition
subroutine, public cp_fm_invert(matrix_a, matrix_inverse, det_a, eps_svd, eigval)
Inverts a cp_fm_type matrix, optionally returning the determinant of the input matrix.
subroutine, public cp_fm_matvec(amat, xv, yv, alpha, beta)
Calculates yv = alpha*amat*xv + beta*yv where amat: fm matrix xv : vector replicated yv : vector repl...
represent the structure of a full matrix
subroutine, public cp_fm_struct_create(fmstruct, para_env, context, nrow_global, ncol_global, nrow_block, ncol_block, descriptor, first_p_pos, local_leading_dimension, template_fmstruct, square_blocks, force_block)
allocates and initializes a full matrix structure
subroutine, public cp_fm_struct_release(fmstruct)
releases a full matrix structure
represent a full matrix distributed on many processors
subroutine, public cp_fm_get_info(matrix, name, nrow_global, ncol_global, nrow_block, ncol_block, nrow_local, ncol_local, row_indices, col_indices, local_data, context, nrow_locals, ncol_locals, matrix_struct, para_env)
returns all kind of information about the full matrix
subroutine, public cp_fm_set_all(matrix, alpha, beta)
set all elements of a matrix to the same value, and optionally the diagonal to a different one
subroutine, public cp_fm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
creates a new full matrix with the given structure
various routines to log and control the output. The idea is that decisions about where to log should ...
recursive integer function, public cp_logger_get_default_unit_nr(logger, local, skip_not_ionode)
asks the default unit number of the given logger. try to use cp_logger_get_unit_nr
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
routines to handle the output, The idea is to remove the decision of wheter to output and what to out...
integer, parameter, public medium_print_level
stores a lists of integer that are local to a processor. The idea is that these integers represent ob...
stores a mapping of 2D info (e.g. matrix) on a 2D processor distribution (i.e. blacs grid) where cpus...
EEQ data from different sources.
subroutine, public get_eeq_data(za, model, chi, eta, kcn, rad)
...
Calculation of charge equilibration method.
subroutine, public eeq_efield_energy(qs_env, charges, ef_energy)
...
subroutine, public eeq_charges(qs_env, charges, eeq_sparam, eeq_model, enshift_type, exclude, cn_max)
...
subroutine, public eeq_efield_force_periodic(qs_env, charges, qlag)
...
real(kind=dp), dimension(1:maxelem), parameter rcov
subroutine, public eeq_efield_pot(qs_env, efr)
...
subroutine, public eeq_print(qs_env, iounit, print_level, ext)
...
subroutine, public eeq_forces(qs_env, charges, dcharges, gradient, stress, eeq_sparam, eeq_model, enshift_type, response_only, exclude, cn_max)
...
subroutine, public eeq_efield_force_loc(qs_env, charges, qlag)
...
subroutine, public eeq_solver(charges, lambda, eeq_energy, particle_set, kind_of, cell, chia, gam, gab, para_env, blacs_env, dft_control, eeq_sparam, totalcharge, ewald, ewald_env, ewald_pw, iounit, qs_env)
...
subroutine, public ewald_env_set(ewald_env, ewald_type, alpha, epsilon, eps_pol, gmax, ns_max, precs, o_spline, para_env, poisson_section, interaction_cutoffs, cell_hmat)
Purpose: Set the EWALD environment.
subroutine, public ewald_env_create(ewald_env, para_env)
allocates and intitializes a ewald_env
subroutine, public read_ewald_section_tb(ewald_env, ewald_section, hmat, silent, pset, cell_periodic)
Purpose: read the EWALD section for TB methods.
subroutine, public ewald_env_release(ewald_env)
releases the given ewald_env (see doc/ReferenceCounting.html)
subroutine, public ewald_env_get(ewald_env, ewald_type, alpha, eps_pol, epsilon, gmax, ns_max, o_spline, group, para_env, poisson_section, precs, rcut, do_multipoles, max_multipole, do_ipol, max_ipol_iter, interaction_cutoffs, cell_hmat)
Purpose: Get the EWALD environment.
subroutine, public ewald_pw_release(ewald_pw)
releases the memory used by the ewald_pw
subroutine, public ewald_pw_create(ewald_pw, ewald_env, cell, cell_ref, print_section)
creates the structure ewald_pw_type
Defines the basic variable types.
integer, parameter, public int_8
integer, parameter, public dp
Machine interface based on Fortran 2003 and POSIX.
real(kind=dp) function, public m_walltime()
returns time from a real-time clock, protected against rolling early/easily
Definition of mathematical constants and functions.
real(kind=dp), parameter, public oorootpi
real(kind=dp), parameter, public twopi
Collection of simple mathematical functions and subroutines.
subroutine, public invmat(a, info)
returns inverse of matrix using the lapack routines DGETRF and DGETRI
subroutine, public diag(n, a, d, v)
Diagonalize matrix a. The eigenvalues are returned in vector d and the eigenvectors are returned in m...
Interface to the message passing library MPI.
Define the data structure for the molecule information.
Define the data structure for the particle information.
Definition of physical constants:
real(kind=dp), parameter, public bohr
functions related to the poisson solver on regular grids
integer, parameter, public do_ewald_spme
Coordination number routines for dispersion pairpotentials.
subroutine, public cnumber_release(cnumbers, dcnum, derivatives)
...
subroutine, public cnumber_init(qs_env, cnumbers, dcnum, ftype, derivatives, disp_env)
...
Definition of disperson types for DFT calculations.
subroutine, public qs_dispersion_release(dispersion_env)
...
subroutine, public get_qs_env(qs_env, atomic_kind_set, qs_kind_set, cell, super_cell, cell_ref, use_ref_cell, kpoints, dft_control, mos, sab_orb, sab_all, qmmm, qmmm_periodic, mimic, sac_ae, sac_ppl, sac_lri, sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_almo, sab_kp, sab_kp_nosym, sab_cneo, particle_set, energy, force, matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, run_rtp, rtp, matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_ks_im_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, matrix_s_ri_aux_kp, matrix_s, matrix_s_ri_aux, matrix_w, matrix_p_mp2, matrix_p_mp2_admm, matrix_vhxc, rho, rho_xc, pw_env, ewald_env, ewald_pw, active_space, mpools, input, para_env, blacs_env, scf_control, rel_control, kinetic, qs_charges, vppl, xcint_weights, rho_core, rho_nlcc, rho_nlcc_g, ks_env, ks_qmmm_env, wf_history, scf_env, local_particles, local_molecules, distribution_2d, dbcsr_dist, molecule_kind_set, molecule_set, subsys, cp_subsys, oce, local_rho_set, rho_atom_set, task_list, task_list_soft, rho0_atom_set, rho0_mpole, rhoz_set, rhoz_cneo_set, ecoul_1c, rho0_s_rs, rho0_s_gs, rhoz_cneo_s_rs, rhoz_cneo_s_gs, do_kpoints, has_unit_metric, requires_mo_derivs, mo_derivs, mo_loc_history, nkind, natom, nelectron_total, nelectron_spin, efield, neighbor_list_id, linres_control, xas_env, virial, cp_ddapc_env, cp_ddapc_ewald, outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, results, se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, lri_env, lri_density, exstate_env, ec_env, harris_env, dispersion_env, gcp_env, vee, rho_external, external_vxc, mask, mp2_env, bs_env, kg_env, wanniercentres, atprop, ls_scf_env, do_transport, transport_env, v_hartree_rspace, s_mstruct_changed, rho_changed, potential_changed, forces_up_to_date, mscfg_env, almo_scf_env, gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, eeq, rhs, do_rixs, tb_tblite)
Get the QUICKSTEP environment.
Define the quickstep kind type and their sub types.
subroutine, public get_qs_kind(qs_kind, basis_set, basis_type, ncgf, nsgf, all_potential, tnadd_potential, gth_potential, sgp_potential, upf_potential, cneo_potential, se_parameter, dftb_parameter, xtb_parameter, dftb3_param, zatom, zeff, elec_conf, mao, lmax_dftb, alpha_core_charge, ccore_charge, core_charge, core_charge_radius, paw_proj_set, paw_atom, hard_radius, hard0_radius, max_rad_local, covalent_radius, vdw_radius, gpw_type_forced, harmonics, max_iso_not0, max_s_harm, grid_atom, ngrid_ang, ngrid_rad, lmax_rho0, dft_plus_u_atom, l_of_dft_plus_u, n_of_dft_plus_u, u_minus_j, hund_j, u_of_dft_plus_u, j_of_dft_plus_u, alpha_of_dft_plus_u, beta_of_dft_plus_u, j0_of_dft_plus_u, occupation_of_dft_plus_u, dispersion, bs_occupation, magnetization, no_optimize, addel, laddel, naddel, orbitals, max_scf, eps_scf, smear, u_ramping, u_minus_j_target, eps_u_ramping, proj_shell_charge, lr_atom, do_mtlr, u_j_loop, ao_coef, init_u_ramping_each_scf, reltmat, ghost, monovalent, floating, name, element_symbol, pao_basis_size, pao_model_file, pao_potentials, pao_descriptors, nelec)
Get attributes of an atomic kind.
Define the neighbor list data types and the corresponding functionality.
subroutine, public release_neighbor_list_sets(nlists)
releases an array of neighbor_list_sets
subroutine, public neighbor_list_iterator_create(iterator_set, nl, search, nthread)
Neighbor list iterator functions.
subroutine, public neighbor_list_iterator_release(iterator_set)
...
integer function, public neighbor_list_iterate(iterator_set, mepos)
...
subroutine, public get_iterator_info(iterator_set, mepos, ikind, jkind, nkind, ilist, nlist, inode, nnode, iatom, jatom, r, cell)
...
Generate the atomic neighbor lists.
subroutine, public atom2d_cleanup(atom2d)
free the internals of atom2d
subroutine, public pair_radius_setup(present_a, present_b, radius_a, radius_b, pair_radius, prmin)
...
subroutine, public build_neighbor_lists(ab_list, particle_set, atom, cell, pair_radius, subcells, mic, symmetric, molecular, subset_of_mol, current_subset, operator_type, nlname, atomb_to_keep, stable_images)
Build simple pair neighbor lists.
subroutine, public atom2d_build(atom2d, distribution_1d, distribution_2d, atomic_kind_set, molecule_set, molecule_only, particle_set)
Build some distribution structure of atoms, refactored from build_qs_neighbor_lists.
Calculate the electrostatic energy by the Smooth Particle Ewald method.
subroutine, public spme_forces(ewald_env, ewald_pw, box, particle_set_a, charges_a, particle_set_b, charges_b, forces_b)
Calculate the forces on particles B for the electrostatic interaction betrween particles A and B.
subroutine, public spme_potential(ewald_env, ewald_pw, box, particle_set_a, charges_a, particle_set_b, potential)
Calculate the electrostatic potential from particles A (charge A) at positions of particles B.
subroutine, public spme_virial(ewald_env, ewald_pw, particle_set, box, mcharge, virial)
Internal Virial for 1/2 [rho||rho] (rho=mcharge)
All kind of helpful little routines.
pure subroutine, public virial_pair_force(pv_virial, f0, force, rab)
Computes the contribution to the stress tensor from two-body pair-wise forces.
Provides all information about an atomic kind.
type for the atomic properties
Type defining parameters related to the simulation cell.
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
keeps the information about the structure of a full matrix
type of a logger, at the moment it contains just a print level starting at which level it should be l...
structure to store local (to a processor) ordered lists of integers.
distributes pairs on a 2d grid of processors
to build arrays of pointers
stores all the informations relevant to an mpi environment
Provides all information about a quickstep kind.