34#include "./base/base_uses.f90"
38 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'fist_efield_methods'
62 efield, use_virial, iunit, charges)
63 REAL(kind=
dp),
INTENT(OUT) :: qenergy
64 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: qforce
65 REAL(kind=
dp),
DIMENSION(3, 3),
INTENT(OUT) :: qpv
70 LOGICAL,
INTENT(IN),
OPTIONAL :: use_virial
71 INTEGER,
INTENT(IN),
OPTIONAL :: iunit
72 REAL(kind=
dp),
DIMENSION(:),
OPTIONAL,
POINTER :: charges
74 COMPLEX(KIND=dp) :: zeta
75 COMPLEX(KIND=dp),
DIMENSION(3) :: ggamma
76 INTEGER :: i, ii, iparticle_kind, iw, j
77 INTEGER,
DIMENSION(:),
POINTER :: atom_list
78 LOGICAL :: use_charges, virial
79 REAL(kind=
dp) :: q, theta
80 REAL(kind=
dp),
DIMENSION(3) :: ci, dfilter, di, dipole, fieldpol, fq, &
89 IF (
PRESENT(charges))
THEN
90 IF (
ASSOCIATED(charges)) use_charges = .true.
93 IF (
PRESENT(iunit))
THEN
99 IF (
PRESENT(use_virial))
THEN
105 fieldpol = efield%polarisation
106 fieldpol = fieldpol/sqrt(dot_product(fieldpol, fieldpol))
107 fieldpol = -fieldpol*efield%strength
109 dfilter = efield%dfilter
113 DO iparticle_kind = 1,
SIZE(atomic_kind_set)
114 atomic_kind => atomic_kind_set(iparticle_kind)
115 CALL get_atomic_kind(atomic_kind=atomic_kind, qeff=q, atom_list=atom_list)
117 DO i = 1,
SIZE(atom_list)
119 ria = particle_set(ii)%r(:)
121 IF (use_charges) q = charges(ii)
123 gvec =
twopi*cell%h_inv(j, :)
124 theta = sum(ria(:)*gvec(:))
125 zeta = cmplx(cos(theta), sin(theta), kind=
dp)**(-q)
126 ggamma(j) = ggamma(j)*zeta
132 IF (all(real(ggamma, kind=
dp) /= 0.0_dp))
THEN
133 tmp = aimag(ggamma)/real(ggamma, kind=
dp)
135 dipole = matmul(cell%hmat, ci)/
twopi
138 IF (efield%displacement)
THEN
140 di = dipole/cell%deth
142 theta = fieldpol(i) - 2._dp*
twopi*di(i)
143 qenergy = qenergy + dfilter(i)*theta**2
144 fq(i) = -dfilter(i)*theta
146 qenergy = 0.25_dp*cell%deth/
twopi*qenergy
147 DO i = 1,
SIZE(qforce, 2)
148 qforce(1:3, i) = fq(1:3)*qforce(1:3, i)
152 qenergy = sum(fieldpol*dipole)
153 DO i = 1,
SIZE(qforce, 2)
154 qforce(1:3, i) = fieldpol(1:3)*qforce(1:3, i)
159 DO iparticle_kind = 1,
SIZE(atomic_kind_set)
160 atomic_kind => atomic_kind_set(iparticle_kind)
162 DO i = 1,
SIZE(atom_list)
164 ria = particle_set(ii)%r(:)
167 qpv(j, 1:3) = qpv(j, 1:3) + qforce(j, ii)*ria(1:3)
172 IF (efield%displacement)
THEN
173 cpabort(
"Stress Tensor for constant D simulation is not working")
193 SUBROUTINE fist_dipole(fist_env, print_section, atomic_kind_set, particle_set, &
194 cell, unit_nr, charges)
200 INTEGER,
INTENT(IN) :: unit_nr
201 REAL(kind=
dp),
DIMENSION(:),
OPTIONAL,
POINTER :: charges
203 CHARACTER(LEN=default_string_length) :: description, dipole_type
204 COMPLEX(KIND=dp) :: dzeta, dzphase(3), zeta, zphase(3)
205 COMPLEX(KIND=dp),
DIMENSION(3) :: dggamma, ggamma
206 INTEGER :: i, iparticle_kind, j, reference
207 INTEGER,
DIMENSION(:),
POINTER :: atom_list
208 LOGICAL :: do_berry, use_charges
209 REAL(kind=
dp) :: charge_tot, ci(3), dci(3), dipole(3), dipole_deriv(3), drcc(3), dria(3), &
210 dtheta, gvec(3), q, rcc(3), ria(3), theta, tmp(3), via(3)
211 REAL(kind=
dp),
DIMENSION(:),
POINTER :: ref_point
215 NULLIFY (atomic_kind)
217 reference =
section_get_ival(print_section, keyword_name=
"DIPOLE%REFERENCE")
219 description =
'[DIPOLE]'
222 use_charges = .false.
223 IF (
PRESENT(charges))
THEN
224 IF (
ASSOCIATED(charges)) use_charges = .true.
227 CALL get_reference_point(rcc, drcc, fist_env=fist_env, reference=reference, ref_point=ref_point)
230 dipole_deriv = 0.0_dp
233 dipole_type =
"periodic (Berry phase)"
236 IF (use_charges)
THEN
237 charge_tot = sum(charges)
239 DO i = 1,
SIZE(particle_set)
240 atomic_kind => particle_set(i)%atomic_kind
242 charge_tot = charge_tot + q
245 ria =
twopi*matmul(cell%h_inv, rcc)
246 zphase = cmplx(cos(ria), sin(ria),
dp)**charge_tot
248 dria =
twopi*matmul(cell%h_inv, drcc)
249 dzphase = charge_tot*cmplx(-sin(ria), cos(ria),
dp)**(charge_tot - 1.0_dp)*dria
253 DO iparticle_kind = 1,
SIZE(atomic_kind_set)
254 atomic_kind => atomic_kind_set(iparticle_kind)
255 CALL get_atomic_kind(atomic_kind=atomic_kind, qeff=q, atom_list=atom_list)
257 DO i = 1,
SIZE(atom_list)
258 ria = particle_set(atom_list(i))%r(:)
260 via = particle_set(atom_list(i))%v(:)
261 IF (use_charges) q = charges(atom_list(i))
263 gvec =
twopi*cell%h_inv(j, :)
264 theta = sum(ria(:)*gvec(:))
265 dtheta = sum(via(:)*gvec(:))
266 zeta = cmplx(cos(theta), sin(theta), kind=
dp)**(-q)
267 dzeta = -q*cmplx(-sin(theta), cos(theta), kind=
dp)**(-q - 1.0_dp)*dtheta
268 dggamma(j) = dggamma(j)*zeta + ggamma(j)*dzeta
269 ggamma(j) = ggamma(j)*zeta
273 dggamma = dggamma*zphase + ggamma*dzphase
274 ggamma = ggamma*zphase
275 IF (all(real(ggamma, kind=
dp) /= 0.0_dp))
THEN
276 tmp = aimag(ggamma)/real(ggamma, kind=
dp)
278 dci = (1.0_dp/(1.0_dp + tmp**2))* &
279 (aimag(dggamma)*real(ggamma, kind=
dp) - aimag(ggamma)*real(dggamma, kind=
dp))/(real(ggamma, kind=
dp))**2
281 dipole = matmul(cell%hmat, ci)/
twopi
282 dipole_deriv = matmul(cell%hmat, dci)/
twopi
288 dipole_type =
"non-periodic"
289 DO i = 1,
SIZE(particle_set)
290 atomic_kind => particle_set(i)%atomic_kind
291 ria = particle_set(i)%r(:)
294 IF (use_charges) q = charges(i)
295 dipole = dipole - q*(ria - rcc)
296 dipole_deriv(:) = dipole_deriv(:) - q*(particle_set(i)%v(:) - drcc)
302 IF (unit_nr > 0)
THEN
303 WRITE (unit_nr,
'(/,T2,A,T31,A50)') &
304 'MM_DIPOLE| Dipole type', adjustr(trim(dipole_type))
305 WRITE (unit_nr,
'(T2,A,T30,3(1X,F16.8))') &
306 'MM_DIPOLE| Moment [a.u.]', dipole(1:3)
307 WRITE (unit_nr,
'(T2,A,T30,3(1X,F16.8))') &
308 'MM_DIPOLE| Moment [Debye]', dipole(1:3)*
debye
309 WRITE (unit_nr,
'(T2,A,T30,3(1X,F16.8))') &
310 'MM_DIPOLE| Derivative [a.u.]', dipole_deriv(1:3)
Define the atomic kind types and their sub types.
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.
Handles all functions related to the CELL.
set of type/routines to handle the storage of results in force_envs
subroutine, public cp_results_erase(results, description, nval)
erase a part of result_list
set of type/routines to handle the storage of results in force_envs
subroutine, public fist_efield_energy_force(qenergy, qforce, qpv, atomic_kind_set, particle_set, cell, efield, use_virial, iunit, charges)
...
subroutine, public fist_dipole(fist_env, print_section, atomic_kind_set, particle_set, cell, unit_nr, charges)
Evaluates the Dipole of a classical charge distribution(point-like) possibly using the berry phase fo...
subroutine, public fist_env_get(fist_env, atomic_kind_set, particle_set, ewald_pw, local_particles, local_molecules, molecule_kind_set, molecule_set, cell, cell_ref, ewald_env, fist_nonbond_env, thermo, para_env, subsys, qmmm, qmmm_env, input, shell_model, shell_model_ad, shell_particle_set, core_particle_set, multipoles, results, exclusions, efield)
Purpose: Get the FIST environment.
Defines the basic variable types.
integer, parameter, public dp
integer, parameter, public default_string_length
Definition of mathematical constants and functions.
complex(kind=dp), parameter, public z_one
real(kind=dp), parameter, public twopi
complex(kind=dp), parameter, public z_zero
Calculates the moment integrals <a|r^m|b>
subroutine, public get_reference_point(rpoint, drpoint, qs_env, fist_env, reference, ref_point, ifirst, ilast)
...
Define the data structure for the particle information.
Definition of physical constants:
real(kind=dp), parameter, public debye
Provides all information about an atomic kind.
Type defining parameters related to the simulation cell.
contains arbitrary information which need to be stored