(git:374b731)
Loading...
Searching...
No Matches
pao_ml_descriptor.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \brief Feature vectors for describing chemical environments in a rotationally invariant fashion.
10!> \author Ole Schuett
11! **************************************************************************************************
15 USE cell_types, ONLY: cell_type,&
16 pbc
17 USE kinds, ONLY: dp
18 USE mathconstants, ONLY: fourpi,&
19 rootpi
20 USE mathlib, ONLY: diamat_all
25 USE pao_types, ONLY: pao_env_type
27 USE qs_kind_types, ONLY: get_qs_kind,&
30 USE util, ONLY: sort
31#include "./base/base_uses.f90"
32
33 IMPLICIT NONE
34
35 PRIVATE
36
37 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'pao_ml_descriptor'
38
40
41CONTAINS
42
43! **************************************************************************************************
44!> \brief Calculates a descriptor for chemical environment of given atom
45!> \param pao ...
46!> \param particle_set ...
47!> \param qs_kind_set ...
48!> \param cell ...
49!> \param iatom ...
50!> \param descriptor ...
51!> \param descr_grad ...
52!> \param forces ...
53! **************************************************************************************************
54 SUBROUTINE pao_ml_calc_descriptor(pao, particle_set, qs_kind_set, cell, iatom, descriptor, descr_grad, forces)
55 TYPE(pao_env_type), POINTER :: pao
56 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
57 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
58 TYPE(cell_type), POINTER :: cell
59 INTEGER, INTENT(IN) :: iatom
60 REAL(dp), ALLOCATABLE, DIMENSION(:), OPTIONAL :: descriptor
61 REAL(dp), DIMENSION(:), INTENT(IN), OPTIONAL :: descr_grad
62 REAL(dp), DIMENSION(:, :), INTENT(INOUT), OPTIONAL :: forces
63
64 CHARACTER(len=*), PARAMETER :: routinen = 'pao_ml_calc_descriptor'
65
66 INTEGER :: handle
67
68 CALL timeset(routinen, handle)
69
70 cpassert(PRESENT(forces) .EQV. PRESENT(descr_grad))
71
72 SELECT CASE (pao%ml_descriptor)
73 CASE (pao_ml_desc_pot)
74 CALL calc_descriptor_pot(particle_set, qs_kind_set, cell, iatom, descriptor, descr_grad, forces)
76 CALL calc_descriptor_overlap(particle_set, qs_kind_set, cell, iatom, descriptor, descr_grad, forces)
77 CASE (pao_ml_desc_r12)
78 CALL calc_descriptor_r12(particle_set, qs_kind_set, cell, iatom, descriptor, descr_grad, forces)
79 CASE DEFAULT
80 cpabort("PAO: unknown descriptor")
81 END SELECT
82
83 CALL timestop(handle)
84 END SUBROUTINE pao_ml_calc_descriptor
85
86! **************************************************************************************************
87!> \brief Calculates a descriptor based on the eigenvalues of V_neighbors
88!> \param particle_set ...
89!> \param qs_kind_set ...
90!> \param cell ...
91!> \param iatom ...
92!> \param descriptor ...
93!> \param descr_grad ...
94!> \param forces ...
95! **************************************************************************************************
96 SUBROUTINE calc_descriptor_pot(particle_set, qs_kind_set, cell, iatom, descriptor, descr_grad, forces)
97 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
98 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
99 TYPE(cell_type), POINTER :: cell
100 INTEGER, INTENT(IN) :: iatom
101 REAL(dp), ALLOCATABLE, DIMENSION(:), OPTIONAL :: descriptor
102 REAL(dp), DIMENSION(:), INTENT(IN), OPTIONAL :: descr_grad
103 REAL(dp), DIMENSION(:, :), INTENT(INOUT), OPTIONAL :: forces
104
105 CHARACTER(len=*), PARAMETER :: routinen = 'calc_descriptor_pot'
106
107 INTEGER :: handle, i, idesc, ikind, jatom, jkind, &
108 k, n, natoms, ndesc
109 REAL(dp) :: beta, w, weight
110 REAL(dp), ALLOCATABLE, DIMENSION(:) :: v_evals
111 REAL(dp), ALLOCATABLE, DIMENSION(:, :) :: block_m, block_v, v_evecs
112 REAL(dp), ALLOCATABLE, DIMENSION(:, :, :) :: block_d
113 REAL(dp), DIMENSION(3) :: ra, rab, rb
114 TYPE(gto_basis_set_type), POINTER :: basis_set
115 TYPE(pao_descriptor_type), DIMENSION(:), POINTER :: pao_descriptors
116
117 CALL timeset(routinen, handle)
118
119 CALL get_atomic_kind(particle_set(iatom)%atomic_kind, kind_number=ikind)
120 CALL get_qs_kind(qs_kind_set(ikind), basis_set=basis_set, pao_descriptors=pao_descriptors)
121 n = basis_set%nsgf
122 natoms = SIZE(particle_set)
123 ndesc = SIZE(pao_descriptors)
124 IF (ndesc == 0) cpabort("No PAO_DESCRIPTOR section found")
125
126 ALLOCATE (block_v(n, n), v_evecs(n, n), v_evals(n))
127 IF (PRESENT(descriptor)) ALLOCATE (descriptor(n*ndesc))
128 IF (PRESENT(forces)) ALLOCATE (block_d(n, n, 3), block_m(n, n))
129
130 DO idesc = 1, ndesc
131
132 ! construct matrix V_block from neighboring atoms
133 block_v = 0.0_dp
134 DO jatom = 1, natoms
135 IF (jatom == iatom) cycle
136 ra = particle_set(iatom)%r
137 rb = particle_set(jatom)%r
138 rab = pbc(ra, rb, cell)
139 CALL get_atomic_kind(particle_set(jatom)%atomic_kind, kind_number=jkind)
140 CALL get_qs_kind(qs_kind_set(jkind), pao_descriptors=pao_descriptors)
141 IF (SIZE(pao_descriptors) /= ndesc) &
142 cpabort("Not all KINDs have the same number of PAO_DESCRIPTOR sections")
143 weight = pao_descriptors(idesc)%weight
144 beta = pao_descriptors(idesc)%beta
145 CALL pao_calc_gaussian(basis_set, block_v=block_v, rab=rab, lpot=0, beta=beta, weight=weight)
146 END DO
147
148 ! diagonalize block_V
149 v_evecs(:, :) = block_v(:, :)
150 CALL diamat_all(v_evecs, v_evals)
151
152 ! use eigenvalues of V_block as descriptor
153 IF (PRESENT(descriptor)) &
154 descriptor((idesc - 1)*n + 1:idesc*n) = v_evals(:)
155
156 ! FORCES ----------------------------------------------------------------------------------
157 IF (PRESENT(forces)) THEN
158 cpassert(PRESENT(descr_grad))
159 block_m = 0.0_dp
160 DO k = 1, n
161 w = descr_grad((idesc - 1)*n + k)
162 block_m(:, :) = block_m(:, :) + w*matmul(v_evecs(:, k:k), transpose(v_evecs(:, k:k)))
163 END DO
164 DO jatom = 1, natoms
165 IF (jatom == iatom) cycle
166 ra = particle_set(iatom)%r
167 rb = particle_set(jatom)%r
168 rab = pbc(ra, rb, cell)
169 CALL get_atomic_kind(particle_set(jatom)%atomic_kind, kind_number=jkind)
170 CALL get_qs_kind(qs_kind_set(jkind), pao_descriptors=pao_descriptors)
171 weight = pao_descriptors(idesc)%weight
172 beta = pao_descriptors(idesc)%beta
173 block_d = 0.0_dp
174 CALL pao_calc_gaussian(basis_set, block_d=block_d, rab=rab, lpot=0, beta=beta, weight=weight)
175 DO i = 1, 3
176 forces(iatom, i) = forces(iatom, i) - sum(block_m*block_d(:, :, i))
177 forces(jatom, i) = forces(jatom, i) + sum(block_m*block_d(:, :, i))
178 END DO
179 END DO
180 END IF
181
182 END DO
183
184 CALL timestop(handle)
185 END SUBROUTINE calc_descriptor_pot
186
187! **************************************************************************************************
188!> \brief Calculates a descriptor based on the eigenvalues of local overlap matrix
189!> \param particle_set ...
190!> \param qs_kind_set ...
191!> \param cell ...
192!> \param iatom ...
193!> \param descriptor ...
194!> \param descr_grad ...
195!> \param forces ...
196! **************************************************************************************************
197 SUBROUTINE calc_descriptor_overlap(particle_set, qs_kind_set, cell, iatom, descriptor, descr_grad, forces)
198 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
199 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
200 TYPE(cell_type), POINTER :: cell
201 INTEGER, INTENT(IN) :: iatom
202 REAL(dp), ALLOCATABLE, DIMENSION(:), OPTIONAL :: descriptor
203 REAL(dp), DIMENSION(:), INTENT(IN), OPTIONAL :: descr_grad
204 REAL(dp), DIMENSION(:, :), INTENT(INOUT), OPTIONAL :: forces
205
206 CHARACTER(len=*), PARAMETER :: routinen = 'calc_descriptor_overlap'
207
208 INTEGER :: handle, idesc, ikind, j, jatom, jkind, &
209 k, katom, kkind, n, natoms, ndesc
210 INTEGER, ALLOCATABLE, DIMENSION(:) :: neighbor_order
211 REAL(dp) :: beta_sum, deriv, exponent, integral, jbeta, jweight, kbeta, kweight, &
212 normalization, rij2, rik2, rjk2, sbeta, screening_radius, screening_volume, w
213 REAL(dp), ALLOCATABLE, DIMENSION(:) :: s_evals
214 REAL(dp), ALLOCATABLE, DIMENSION(:, :) :: block_m, block_s, s_evecs
215 REAL(dp), DIMENSION(3) :: ri, rij, rik, rj, rjk, rk
216 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: neighbor_dist
217 TYPE(pao_descriptor_type), DIMENSION(:), POINTER :: ipao_descriptors, jpao_descriptors, &
218 kpao_descriptors
219
220 CALL timeset(routinen, handle)
221
222 CALL get_atomic_kind(particle_set(iatom)%atomic_kind, kind_number=ikind)
223 CALL get_qs_kind(qs_kind_set(ikind), pao_descriptors=ipao_descriptors)
224
225 natoms = SIZE(particle_set)
226 ndesc = SIZE(ipao_descriptors)
227 IF (ndesc == 0) cpabort("No PAO_DESCRIPTOR section found")
228
229 ! determine largest screening radius
230 screening_radius = 0.0_dp
231 DO idesc = 1, ndesc
232 screening_radius = max(screening_radius, ipao_descriptors(idesc)%screening_radius)
233 END DO
234
235 ! estimate maximum number of neighbors within screening
236 screening_volume = fourpi/3.0_dp*screening_radius**3
237 n = int(screening_volume/35.0_dp) ! rule of thumb
238
239 ALLOCATE (block_s(n, n), s_evals(n), s_evecs(n, n))
240 IF (PRESENT(descriptor)) ALLOCATE (descriptor(n*ndesc))
241 IF (PRESENT(forces)) ALLOCATE (block_m(n, n))
242
243 !find neighbors
244 !TODO: this is a quadratic algorithm, use a neighbor-list instead
245 ALLOCATE (neighbor_dist(natoms), neighbor_order(natoms))
246 ri = particle_set(iatom)%r
247 DO jatom = 1, natoms
248 rj = particle_set(jatom)%r
249 rij = pbc(ri, rj, cell)
250 neighbor_dist(jatom) = sqrt(sum(rij**2))
251 END DO
252 CALL sort(neighbor_dist, natoms, neighbor_order)
253 cpassert(neighbor_order(1) == iatom) !central atom should be closesd to itself
254
255 ! check if N was chosen large enough
256 IF (natoms > n) THEN
257 IF (neighbor_dist(n + 1) < screening_radius) &
258 cpabort("PAO heuristic for descriptor size broke down")
259 END IF
260
261 DO idesc = 1, ndesc
262 sbeta = ipao_descriptors(idesc)%screening
263
264 ! construct matrix S_block from neighboring atoms
265 block_s = 0.0_dp
266 DO j = 1, min(natoms, n)
267 DO k = 1, min(natoms, n)
268 jatom = neighbor_order(j)
269 katom = neighbor_order(k)
270
271 ! get weigths and betas
272 CALL get_atomic_kind(particle_set(jatom)%atomic_kind, kind_number=jkind)
273 CALL get_qs_kind(qs_kind_set(jkind), pao_descriptors=jpao_descriptors)
274 CALL get_atomic_kind(particle_set(katom)%atomic_kind, kind_number=kkind)
275 CALL get_qs_kind(qs_kind_set(kkind), pao_descriptors=kpao_descriptors)
276 IF (SIZE(jpao_descriptors) /= ndesc .OR. SIZE(kpao_descriptors) /= ndesc) &
277 cpabort("Not all KINDs have the same number of PAO_DESCRIPTOR sections")
278 jweight = jpao_descriptors(idesc)%weight
279 jbeta = jpao_descriptors(idesc)%beta
280 kweight = kpao_descriptors(idesc)%weight
281 kbeta = kpao_descriptors(idesc)%beta
282 beta_sum = sbeta + jbeta + kbeta
283
284 ! get distances
285 rj = particle_set(jatom)%r
286 rk = particle_set(katom)%r
287 rij = pbc(ri, rj, cell)
288 rik = pbc(ri, rk, cell)
289 rjk = pbc(rj, rk, cell)
290 rij2 = sum(rij**2)
291 rik2 = sum(rik**2)
292 rjk2 = sum(rjk**2)
293
294 ! calculate integral over three Gaussians
295 exponent = -(sbeta*jbeta*rij2 + sbeta*kbeta*rik2 + jbeta*kbeta*rjk2)/beta_sum
296 integral = exp(exponent)*rootpi/sqrt(beta_sum)
297 normalization = sqrt(jbeta*kbeta)/rootpi**2
298 block_s(j, k) = jweight*kweight*normalization*integral
299 END DO
300 END DO
301
302 ! diagonalize V_block
303 s_evecs(:, :) = block_s(:, :)
304 CALL diamat_all(s_evecs, s_evals)
305
306 ! use eigenvalues of S_block as descriptor
307 IF (PRESENT(descriptor)) &
308 descriptor((idesc - 1)*n + 1:idesc*n) = s_evals(:)
309
310 ! FORCES ----------------------------------------------------------------------------------
311 IF (PRESENT(forces)) THEN
312 cpassert(PRESENT(descr_grad))
313 block_m = 0.0_dp
314 DO k = 1, n
315 w = descr_grad((idesc - 1)*n + k)
316 block_m(:, :) = block_m(:, :) + w*matmul(s_evecs(:, k:k), transpose(s_evecs(:, k:k)))
317 END DO
318
319 DO j = 1, min(natoms, n)
320 DO k = 1, min(natoms, n)
321 jatom = neighbor_order(j)
322 katom = neighbor_order(k)
323
324 ! get weigths and betas
325 CALL get_atomic_kind(particle_set(jatom)%atomic_kind, kind_number=jkind)
326 CALL get_qs_kind(qs_kind_set(jkind), pao_descriptors=jpao_descriptors)
327 CALL get_atomic_kind(particle_set(katom)%atomic_kind, kind_number=kkind)
328 CALL get_qs_kind(qs_kind_set(kkind), pao_descriptors=kpao_descriptors)
329 jweight = jpao_descriptors(idesc)%weight
330 jbeta = jpao_descriptors(idesc)%beta
331 kweight = kpao_descriptors(idesc)%weight
332 kbeta = kpao_descriptors(idesc)%beta
333 beta_sum = sbeta + jbeta + kbeta
334
335 ! get distances
336 rj = particle_set(jatom)%r
337 rk = particle_set(katom)%r
338 rij = pbc(ri, rj, cell)
339 rik = pbc(ri, rk, cell)
340 rjk = pbc(rj, rk, cell)
341 rij2 = sum(rij**2)
342 rik2 = sum(rik**2)
343 rjk2 = sum(rjk**2)
344
345 ! calculate integral over three Gaussians
346 exponent = -(sbeta*jbeta*rij2 + sbeta*kbeta*rik2 + jbeta*kbeta*rjk2)/beta_sum
347 integral = exp(exponent)*rootpi/sqrt(beta_sum)
348 normalization = sqrt(jbeta*kbeta)/rootpi**2
349 deriv = 2.0_dp/beta_sum*block_m(j, k)
350 w = jweight*kweight*normalization*integral*deriv
351 forces(iatom, :) = forces(iatom, :) - sbeta*jbeta*rij*w
352 forces(jatom, :) = forces(jatom, :) + sbeta*jbeta*rij*w
353 forces(iatom, :) = forces(iatom, :) - sbeta*kbeta*rik*w
354 forces(katom, :) = forces(katom, :) + sbeta*kbeta*rik*w
355 forces(jatom, :) = forces(jatom, :) - jbeta*kbeta*rjk*w
356 forces(katom, :) = forces(katom, :) + jbeta*kbeta*rjk*w
357 END DO
358 END DO
359 END IF
360 END DO
361
362 CALL timestop(handle)
363 END SUBROUTINE calc_descriptor_overlap
364
365! **************************************************************************************************
366!> \brief Calculates a descriptor based on distance between two atoms
367!> \param particle_set ...
368!> \param qs_kind_set ...
369!> \param cell ...
370!> \param iatom ...
371!> \param descriptor ...
372!> \param descr_grad ...
373!> \param forces ...
374! **************************************************************************************************
375 SUBROUTINE calc_descriptor_r12(particle_set, qs_kind_set, cell, iatom, descriptor, descr_grad, forces)
376 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
377 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
378 TYPE(cell_type), POINTER :: cell
379 INTEGER, INTENT(IN) :: iatom
380 REAL(dp), ALLOCATABLE, DIMENSION(:), OPTIONAL :: descriptor
381 REAL(dp), DIMENSION(:), INTENT(IN), OPTIONAL :: descr_grad
382 REAL(dp), DIMENSION(:, :), INTENT(INOUT), OPTIONAL :: forces
383
384 REAL(dp), DIMENSION(3) :: g, r1, r12, r2
385
386 cpassert(SIZE(particle_set) == 2)
387
388 mark_used(qs_kind_set)
389 mark_used(iatom)
390 mark_used(cell)
391
392 r1 = particle_set(1)%r
393 r2 = particle_set(2)%r
394 r12 = pbc(r1, r2, cell)
395
396 IF (PRESENT(descriptor)) THEN
397 ALLOCATE (descriptor(1))
398 descriptor(1) = sqrt(sum(r12**2))
399 END IF
400
401 IF (PRESENT(forces)) THEN
402 cpassert(PRESENT(descr_grad))
403 g = r12/sqrt(sum(r12**2))*descr_grad(1)
404 forces(1, :) = forces(1, :) + g
405 forces(2, :) = forces(2, :) - g
406 END IF
407 END SUBROUTINE calc_descriptor_r12
408
409END MODULE pao_ml_descriptor
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
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Definition of mathematical constants and functions.
real(kind=dp), parameter, public rootpi
real(kind=dp), parameter, public fourpi
Collection of simple mathematical functions and subroutines.
Definition mathlib.F:15
subroutine, public diamat_all(a, eigval, dac)
Diagonalize the symmetric n by n matrix a using the LAPACK library. Only the upper triangle of matrix...
Definition mathlib.F:372
integer, parameter, public pao_ml_desc_pot
Definition pao_input.F:45
integer, parameter, public pao_ml_desc_r12
Definition pao_input.F:45
integer, parameter, public pao_ml_desc_overlap
Definition pao_input.F:45
Feature vectors for describing chemical environments in a rotationally invariant fashion.
subroutine, public pao_ml_calc_descriptor(pao, particle_set, qs_kind_set, cell, iatom, descriptor, descr_grad, forces)
Calculates a descriptor for chemical environment of given atom.
Factory routines for potentials used e.g. by pao_param_exp and pao_ml.
subroutine, public pao_calc_gaussian(basis_set, block_v, block_d, rab, lpot, beta, weight, min_shell, max_shell, min_l, max_l)
Calculates potential term of the form r**lpot * Exp(-beta*r**2) One needs to call init_orbital_pointe...
Types used by the PAO machinery.
Definition pao_types.F:12
Define the data structure for the particle information.
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, se_parameter, dftb_parameter, xtb_parameter, dftb3_param, 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_r3d_rs_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, 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, init_u_ramping_each_scf, reltmat, ghost, floating, name, element_symbol, pao_basis_size, pao_potentials, pao_descriptors, nelec)
Get attributes of an atomic kind.
All kind of helpful little routines.
Definition util.F:14
Type defining parameters related to the simulation cell.
Definition cell_types.F:55
Holds information about a PAO descriptor.
Provides all information about a quickstep kind.