(git:f2099e5)
Loading...
Searching...
No Matches
fist_efield_methods.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \par History
10!> \author JGH
11! **************************************************************************************************
15 USE cell_types, ONLY: cell_type,&
16 pbc
26 USE kinds, ONLY: default_string_length,&
27 dp
28 USE mathconstants, ONLY: twopi,&
29 z_one,&
30 z_zero
33 USE physcon, ONLY: debye
34#include "./base/base_uses.f90"
35
36 IMPLICIT NONE
37
38 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'fist_efield_methods'
39
40 PRIVATE
41
43
44! **************************************************************************************************
45
46CONTAINS
47
48! **************************************************************************************************
49!> \brief ...
50!> \param qenergy ...
51!> \param qforce ...
52!> \param qpv ...
53!> \param atomic_kind_set ...
54!> \param particle_set ...
55!> \param cell ...
56!> \param efield ...
57!> \param use_virial ...
58!> \param iunit ...
59!> \param charges ...
60! **************************************************************************************************
61 SUBROUTINE fist_efield_energy_force(qenergy, qforce, qpv, atomic_kind_set, particle_set, cell, &
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
66 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
67 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
68 TYPE(cell_type), POINTER :: cell
69 TYPE(fist_efield_type), POINTER :: efield
70 LOGICAL, INTENT(IN), OPTIONAL :: use_virial
71 INTEGER, INTENT(IN), OPTIONAL :: iunit
72 REAL(kind=dp), DIMENSION(:), OPTIONAL, POINTER :: charges
73
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, &
81 gvec, ria
82 TYPE(atomic_kind_type), POINTER :: atomic_kind
83
84 qenergy = 0.0_dp
85 qforce = 0.0_dp
86 qpv = 0.0_dp
87
88 use_charges = .false.
89 IF (PRESENT(charges)) THEN
90 IF (ASSOCIATED(charges)) use_charges = .true.
91 END IF
92
93 IF (PRESENT(iunit)) THEN
94 iw = iunit
95 ELSE
96 iw = -1
97 END IF
98
99 IF (PRESENT(use_virial)) THEN
100 virial = use_virial
101 ELSE
102 virial = .false.
103 END IF
104
105 fieldpol = efield%polarisation
106 fieldpol = fieldpol/norm2(fieldpol)
107 fieldpol = -fieldpol*efield%strength
108
109 dfilter = efield%dfilter
110
111 dipole = 0.0_dp
112 ggamma = z_one
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)
116 ! TODO parallelization over atoms (local_particles)
117 DO i = 1, SIZE(atom_list)
118 ii = atom_list(i)
119 ria = particle_set(ii)%r(:)
120 ria = pbc(ria, cell)
121 IF (use_charges) q = charges(ii)
122 DO j = 1, 3
123 gvec = twopi*cell%h_inv(j, :)
124 theta = sum(ria(:)*gvec(:))
125 zeta = cmplx(cos(q*theta), sin(q*theta), kind=dp)
126 ggamma(j) = ggamma(j)*zeta
127 END DO
128 qforce(1:3, ii) = q
129 END DO
130 END DO
131
132 ci = atan2(aimag(ggamma), real(ggamma, kind=dp))
133 dipole = matmul(cell%hmat, ci)/twopi
134
135 IF (efield%displacement) THEN
136 ! E = (omega/8Pi)(D - 4Pi*P)^2
137 di = dipole/cell%deth
138 DO i = 1, 3
139 theta = fieldpol(i) + 2._dp*twopi*di(i)
140 qenergy = qenergy + dfilter(i)*theta**2
141 fq(i) = -dfilter(i)*theta
142 END DO
143 qenergy = 0.25_dp*cell%deth/twopi*qenergy
144 DO i = 1, SIZE(qforce, 2)
145 qforce(1:3, i) = fq(1:3)*qforce(1:3, i)
146 END DO
147 ELSE
148 ! E = -omega*E*P
149 qenergy = sum(fieldpol*dipole)
150 DO i = 1, SIZE(qforce, 2)
151 qforce(1:3, i) = -fieldpol(1:3)*qforce(1:3, i)
152 END DO
153 END IF
154
155 IF (virial) THEN
156 DO iparticle_kind = 1, SIZE(atomic_kind_set)
157 atomic_kind => atomic_kind_set(iparticle_kind)
158 CALL get_atomic_kind(atomic_kind=atomic_kind, atom_list=atom_list)
159 DO i = 1, SIZE(atom_list)
160 ii = atom_list(i)
161 ria = particle_set(ii)%r(:)
162 ria = pbc(ria, cell)
163 DO j = 1, 3
164 qpv(j, 1:3) = qpv(j, 1:3) + qforce(j, ii)*ria(1:3)
165 END DO
166 END DO
167 END DO
168 ! Stress tensor for constant D needs further investigation
169 IF (efield%displacement) THEN
170 cpabort("Stress Tensor for constant D simulation is not working")
171 END IF
172 END IF
173
174 END SUBROUTINE fist_efield_energy_force
175! **************************************************************************************************
176!> \brief Evaluates the Dipole of a classical charge distribution(point-like)
177!> possibly using the berry phase formalism
178!> \param fist_env ...
179!> \param print_section ...
180!> \param atomic_kind_set ...
181!> \param particle_set ...
182!> \param cell ...
183!> \param unit_nr ...
184!> \param charges ...
185!> \par History
186!> [01.2006] created
187!> [12.2007] tlaino - University of Zurich - debug and extended
188!> \author Teodoro Laino
189! **************************************************************************************************
190 SUBROUTINE fist_dipole(fist_env, print_section, atomic_kind_set, particle_set, &
191 cell, unit_nr, charges)
192 TYPE(fist_environment_type), POINTER :: fist_env
193 TYPE(section_vals_type), POINTER :: print_section
194 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
195 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
196 TYPE(cell_type), POINTER :: cell
197 INTEGER, INTENT(IN) :: unit_nr
198 REAL(kind=dp), DIMENSION(:), OPTIONAL, POINTER :: charges
199
200 CHARACTER(LEN=default_string_length) :: description, dipole_type
201 COMPLEX(KIND=dp) :: dzeta, dzphase(3), zeta, zphase(3)
202 COMPLEX(KIND=dp), DIMENSION(3) :: dggamma, ggamma
203 INTEGER :: i, iparticle_kind, j, reference
204 INTEGER, DIMENSION(:), POINTER :: atom_list
205 LOGICAL :: do_berry, use_charges
206 REAL(kind=dp) :: charge_tot, ci(3), dci(3), dipole(3), &
207 dipole_deriv(3), drcc(3), dria(3), &
208 dtheta, gvec(3), q, rcc(3), ria(3), &
209 theta, via(3)
210 REAL(kind=dp), DIMENSION(:), POINTER :: ref_point
211 TYPE(atomic_kind_type), POINTER :: atomic_kind
212 TYPE(cp_result_type), POINTER :: results
213
214 NULLIFY (atomic_kind)
215 ! Reference point
216 reference = section_get_ival(print_section, keyword_name="DIPOLE%REFERENCE")
217 NULLIFY (ref_point)
218 description = '[DIPOLE]'
219 CALL section_vals_val_get(print_section, "DIPOLE%REF_POINT", r_vals=ref_point)
220 CALL section_vals_val_get(print_section, "DIPOLE%PERIODIC", l_val=do_berry)
221 use_charges = .false.
222 IF (PRESENT(charges)) THEN
223 IF (ASSOCIATED(charges)) use_charges = .true.
224 END IF
225
226 CALL get_reference_point(rcc, drcc, fist_env=fist_env, reference=reference, ref_point=ref_point)
227
228 ! Dipole deriv will be the derivative of the Dipole(dM/dt=\sum e_j v_j)
229 dipole_deriv = 0.0_dp
230 dipole = 0.0_dp
231 IF (do_berry) THEN
232 dipole_type = "periodic (Berry phase)"
233 rcc = pbc(rcc, cell)
234 charge_tot = 0._dp
235 IF (use_charges) THEN
236 charge_tot = sum(charges)
237 ELSE
238 DO i = 1, SIZE(particle_set)
239 atomic_kind => particle_set(i)%atomic_kind
240 CALL get_atomic_kind(atomic_kind=atomic_kind, qeff=q)
241 charge_tot = charge_tot + q
242 END DO
243 END IF
244 ria = twopi*matmul(cell%h_inv, rcc)
245 zphase = cmplx(cos(charge_tot*ria), -sin(charge_tot*ria), kind=dp)
246
247 dria = twopi*matmul(cell%h_inv, drcc)
248 dzphase = -charge_tot*cmplx(sin(charge_tot*ria), cos(charge_tot*ria), kind=dp)*dria
249
250 ggamma = z_one
251 dggamma = z_zero
252 DO iparticle_kind = 1, SIZE(atomic_kind_set)
253 atomic_kind => atomic_kind_set(iparticle_kind)
254 CALL get_atomic_kind(atomic_kind=atomic_kind, qeff=q, atom_list=atom_list)
255
256 DO i = 1, SIZE(atom_list)
257 ria = particle_set(atom_list(i))%r(:)
258 ria = pbc(ria, cell)
259 via = particle_set(atom_list(i))%v(:)
260 IF (use_charges) q = charges(atom_list(i))
261 DO j = 1, 3
262 gvec = twopi*cell%h_inv(j, :)
263 theta = sum(ria(:)*gvec(:))
264 dtheta = sum(via(:)*gvec(:))
265 zeta = cmplx(cos(q*theta), sin(q*theta), kind=dp)
266 dzeta = q*cmplx(-sin(q*theta), cos(q*theta), kind=dp)*dtheta
267 dggamma(j) = dggamma(j)*zeta + ggamma(j)*dzeta
268 ggamma(j) = ggamma(j)*zeta
269 END DO
270 END DO
271 END DO
272 dggamma = dggamma*zphase + ggamma*dzphase
273 ggamma = ggamma*zphase
274 ci = atan2(aimag(ggamma), real(ggamma, kind=dp))
275 dci = (real(ggamma, kind=dp)*aimag(dggamma) - &
276 aimag(ggamma)*real(dggamma, kind=dp))/abs(ggamma)**2
277
278 dipole = matmul(cell%hmat, ci)/twopi
279 dipole_deriv = matmul(cell%hmat, dci)/twopi
280 CALL fist_env_get(fist_env=fist_env, results=results)
281 CALL cp_results_erase(results, description)
282 CALL put_results(results, description, dipole)
283 ELSE
284 dipole_type = "non-periodic"
285 DO i = 1, SIZE(particle_set)
286 atomic_kind => particle_set(i)%atomic_kind
287 ria = particle_set(i)%r(:) ! no pbc(particle_set(i)%r(:),cell) so that the total dipole
288 ! is the sum of the molecular dipoles
289 CALL get_atomic_kind(atomic_kind=atomic_kind, qeff=q)
290 IF (use_charges) q = charges(i)
291 dipole = dipole + q*(ria - rcc)
292 dipole_deriv(:) = dipole_deriv(:) + q*(particle_set(i)%v(:) - drcc)
293 END DO
294 CALL fist_env_get(fist_env=fist_env, results=results)
295 CALL cp_results_erase(results, description)
296 CALL put_results(results, description, dipole)
297 END IF
298 IF (unit_nr > 0) THEN
299 WRITE (unit_nr, '(/,T2,A,T31,A50)') &
300 'MM_DIPOLE| Dipole type', adjustr(trim(dipole_type))
301 WRITE (unit_nr, '(T2,A,T30,3(1X,F16.8))') &
302 'MM_DIPOLE| Moment [a.u.]', dipole(1:3)
303 WRITE (unit_nr, '(T2,A,T30,3(1X,F16.8))') &
304 'MM_DIPOLE| Moment [Debye]', dipole(1:3)*debye
305 WRITE (unit_nr, '(T2,A,T30,3(1X,F16.8))') &
306 'MM_DIPOLE| Derivative [a.u.]', dipole_deriv(1:3)
307 END IF
308
309 END SUBROUTINE fist_dipole
310
311END MODULE fist_efield_methods
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.
Definition cell_types.F:15
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.
objects that represent the structure of input sections and the data contained in an input section
integer function, public section_get_ival(section_vals, keyword_name)
...
subroutine, public section_vals_val_get(section_vals, keyword_name, i_rep_section, i_rep_val, n_rep_val, val, l_val, i_val, r_val, c_val, l_vals, i_vals, r_vals, c_vals, explicit)
returns the requested value
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
integer, parameter, public default_string_length
Definition kinds.F:57
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:
Definition physcon.F:68
real(kind=dp), parameter, public debye
Definition physcon.F:201
Provides all information about an atomic kind.
Type defining parameters related to the simulation cell.
Definition cell_types.F:60
contains arbitrary information which need to be stored