(git:9111030)
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-2026 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) THEN
142 cpabort("Not all KINDs have the same number of PAO_DESCRIPTOR sections")
143 END IF
144 weight = pao_descriptors(idesc)%weight
145 beta = pao_descriptors(idesc)%beta
146 CALL pao_calc_gaussian(basis_set, block_v=block_v, rab=rab, lpot=0, beta=beta, weight=weight)
147 END DO
148
149 ! diagonalize block_V
150 v_evecs(:, :) = block_v(:, :)
151 CALL diamat_all(v_evecs, v_evals)
152
153 ! use eigenvalues of V_block as descriptor
154 IF (PRESENT(descriptor)) THEN
155 descriptor((idesc - 1)*n + 1:idesc*n) = v_evals(:)
156 END IF
157
158 ! FORCES ----------------------------------------------------------------------------------
159 IF (PRESENT(forces)) THEN
160 cpassert(PRESENT(descr_grad))
161 block_m = 0.0_dp
162 DO k = 1, n
163 w = descr_grad((idesc - 1)*n + k)
164 block_m(:, :) = block_m(:, :) + w*matmul(v_evecs(:, k:k), transpose(v_evecs(:, k:k)))
165 END DO
166 DO jatom = 1, natoms
167 IF (jatom == iatom) cycle
168 ra = particle_set(iatom)%r
169 rb = particle_set(jatom)%r
170 rab = pbc(ra, rb, cell)
171 CALL get_atomic_kind(particle_set(jatom)%atomic_kind, kind_number=jkind)
172 CALL get_qs_kind(qs_kind_set(jkind), pao_descriptors=pao_descriptors)
173 weight = pao_descriptors(idesc)%weight
174 beta = pao_descriptors(idesc)%beta
175 block_d = 0.0_dp
176 CALL pao_calc_gaussian(basis_set, block_d=block_d, rab=rab, lpot=0, beta=beta, weight=weight)
177 DO i = 1, 3
178 forces(iatom, i) = forces(iatom, i) - sum(block_m*block_d(:, :, i))
179 forces(jatom, i) = forces(jatom, i) + sum(block_m*block_d(:, :, i))
180 END DO
181 END DO
182 END IF
183
184 END DO
185
186 CALL timestop(handle)
187 END SUBROUTINE calc_descriptor_pot
188
189! **************************************************************************************************
190!> \brief Calculates a descriptor based on the eigenvalues of local overlap matrix
191!> \param particle_set ...
192!> \param qs_kind_set ...
193!> \param cell ...
194!> \param iatom ...
195!> \param descriptor ...
196!> \param descr_grad ...
197!> \param forces ...
198! **************************************************************************************************
199 SUBROUTINE calc_descriptor_overlap(particle_set, qs_kind_set, cell, iatom, descriptor, descr_grad, forces)
200 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
201 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
202 TYPE(cell_type), POINTER :: cell
203 INTEGER, INTENT(IN) :: iatom
204 REAL(dp), ALLOCATABLE, DIMENSION(:), OPTIONAL :: descriptor
205 REAL(dp), DIMENSION(:), INTENT(IN), OPTIONAL :: descr_grad
206 REAL(dp), DIMENSION(:, :), INTENT(INOUT), OPTIONAL :: forces
207
208 CHARACTER(len=*), PARAMETER :: routinen = 'calc_descriptor_overlap'
209
210 INTEGER :: handle, idesc, ikind, j, jatom, jkind, &
211 k, katom, kkind, n, natoms, ndesc
212 INTEGER, ALLOCATABLE, DIMENSION(:) :: neighbor_order
213 REAL(dp) :: beta_sum, deriv, exponent, integral, jbeta, jweight, kbeta, kweight, &
214 normalization, rij2, rik2, rjk2, sbeta, screening_radius, screening_volume, w
215 REAL(dp), ALLOCATABLE, DIMENSION(:) :: s_evals
216 REAL(dp), ALLOCATABLE, DIMENSION(:, :) :: block_m, block_s, s_evecs
217 REAL(dp), DIMENSION(3) :: ri, rij, rik, rj, rjk, rk
218 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: neighbor_dist
219 TYPE(pao_descriptor_type), DIMENSION(:), POINTER :: ipao_descriptors, jpao_descriptors, &
220 kpao_descriptors
221
222 CALL timeset(routinen, handle)
223
224 CALL get_atomic_kind(particle_set(iatom)%atomic_kind, kind_number=ikind)
225 CALL get_qs_kind(qs_kind_set(ikind), pao_descriptors=ipao_descriptors)
226
227 natoms = SIZE(particle_set)
228 ndesc = SIZE(ipao_descriptors)
229 IF (ndesc == 0) cpabort("No PAO_DESCRIPTOR section found")
230
231 ! determine largest screening radius
232 screening_radius = 0.0_dp
233 DO idesc = 1, ndesc
234 screening_radius = max(screening_radius, ipao_descriptors(idesc)%screening_radius)
235 END DO
236
237 ! estimate maximum number of neighbors within screening
238 screening_volume = fourpi/3.0_dp*screening_radius**3
239 n = int(screening_volume/35.0_dp) ! rule of thumb
240
241 ALLOCATE (block_s(n, n), s_evals(n), s_evecs(n, n))
242 IF (PRESENT(descriptor)) ALLOCATE (descriptor(n*ndesc))
243 IF (PRESENT(forces)) ALLOCATE (block_m(n, n))
244
245 !find neighbors
246 !TODO: this is a quadratic algorithm, use a neighbor-list instead
247 ALLOCATE (neighbor_dist(natoms), neighbor_order(natoms))
248 ri = particle_set(iatom)%r
249 DO jatom = 1, natoms
250 rj = particle_set(jatom)%r
251 rij = pbc(ri, rj, cell)
252 neighbor_dist(jatom) = sqrt(sum(rij**2))
253 END DO
254 CALL sort(neighbor_dist, natoms, neighbor_order)
255 cpassert(neighbor_order(1) == iatom) !central atom should be closesd to itself
256
257 ! check if N was chosen large enough
258 IF (natoms > n) THEN
259 IF (neighbor_dist(n + 1) < screening_radius) THEN
260 cpabort("PAO heuristic for descriptor size broke down")
261 END IF
262 END IF
263
264 DO idesc = 1, ndesc
265 sbeta = ipao_descriptors(idesc)%screening
266
267 ! construct matrix S_block from neighboring atoms
268 block_s = 0.0_dp
269 DO j = 1, min(natoms, n)
270 DO k = 1, min(natoms, n)
271 jatom = neighbor_order(j)
272 katom = neighbor_order(k)
273
274 ! get weigths and betas
275 CALL get_atomic_kind(particle_set(jatom)%atomic_kind, kind_number=jkind)
276 CALL get_qs_kind(qs_kind_set(jkind), pao_descriptors=jpao_descriptors)
277 CALL get_atomic_kind(particle_set(katom)%atomic_kind, kind_number=kkind)
278 CALL get_qs_kind(qs_kind_set(kkind), pao_descriptors=kpao_descriptors)
279 IF (SIZE(jpao_descriptors) /= ndesc .OR. SIZE(kpao_descriptors) /= ndesc) THEN
280 cpabort("Not all KINDs have the same number of PAO_DESCRIPTOR sections")
281 END IF
282 jweight = jpao_descriptors(idesc)%weight
283 jbeta = jpao_descriptors(idesc)%beta
284 kweight = kpao_descriptors(idesc)%weight
285 kbeta = kpao_descriptors(idesc)%beta
286 beta_sum = sbeta + jbeta + kbeta
287
288 ! get distances
289 rj = particle_set(jatom)%r
290 rk = particle_set(katom)%r
291 rij = pbc(ri, rj, cell)
292 rik = pbc(ri, rk, cell)
293 rjk = pbc(rj, rk, cell)
294 rij2 = sum(rij**2)
295 rik2 = sum(rik**2)
296 rjk2 = sum(rjk**2)
297
298 ! calculate integral over three Gaussians
299 exponent = -(sbeta*jbeta*rij2 + sbeta*kbeta*rik2 + jbeta*kbeta*rjk2)/beta_sum
300 integral = exp(exponent)*rootpi/sqrt(beta_sum)
301 normalization = sqrt(jbeta*kbeta)/rootpi**2
302 block_s(j, k) = jweight*kweight*normalization*integral
303 END DO
304 END DO
305
306 ! diagonalize V_block
307 s_evecs(:, :) = block_s(:, :)
308 CALL diamat_all(s_evecs, s_evals)
309
310 ! use eigenvalues of S_block as descriptor
311 IF (PRESENT(descriptor)) THEN
312 descriptor((idesc - 1)*n + 1:idesc*n) = s_evals(:)
313 END IF
314
315 ! FORCES ----------------------------------------------------------------------------------
316 IF (PRESENT(forces)) THEN
317 cpassert(PRESENT(descr_grad))
318 block_m = 0.0_dp
319 DO k = 1, n
320 w = descr_grad((idesc - 1)*n + k)
321 block_m(:, :) = block_m(:, :) + w*matmul(s_evecs(:, k:k), transpose(s_evecs(:, k:k)))
322 END DO
323
324 DO j = 1, min(natoms, n)
325 DO k = 1, min(natoms, n)
326 jatom = neighbor_order(j)
327 katom = neighbor_order(k)
328
329 ! get weigths and betas
330 CALL get_atomic_kind(particle_set(jatom)%atomic_kind, kind_number=jkind)
331 CALL get_qs_kind(qs_kind_set(jkind), pao_descriptors=jpao_descriptors)
332 CALL get_atomic_kind(particle_set(katom)%atomic_kind, kind_number=kkind)
333 CALL get_qs_kind(qs_kind_set(kkind), pao_descriptors=kpao_descriptors)
334 jweight = jpao_descriptors(idesc)%weight
335 jbeta = jpao_descriptors(idesc)%beta
336 kweight = kpao_descriptors(idesc)%weight
337 kbeta = kpao_descriptors(idesc)%beta
338 beta_sum = sbeta + jbeta + kbeta
339
340 ! get distances
341 rj = particle_set(jatom)%r
342 rk = particle_set(katom)%r
343 rij = pbc(ri, rj, cell)
344 rik = pbc(ri, rk, cell)
345 rjk = pbc(rj, rk, cell)
346 rij2 = sum(rij**2)
347 rik2 = sum(rik**2)
348 rjk2 = sum(rjk**2)
349
350 ! calculate integral over three Gaussians
351 exponent = -(sbeta*jbeta*rij2 + sbeta*kbeta*rik2 + jbeta*kbeta*rjk2)/beta_sum
352 integral = exp(exponent)*rootpi/sqrt(beta_sum)
353 normalization = sqrt(jbeta*kbeta)/rootpi**2
354 deriv = 2.0_dp/beta_sum*block_m(j, k)
355 w = jweight*kweight*normalization*integral*deriv
356 forces(iatom, :) = forces(iatom, :) - sbeta*jbeta*rij*w
357 forces(jatom, :) = forces(jatom, :) + sbeta*jbeta*rij*w
358 forces(iatom, :) = forces(iatom, :) - sbeta*kbeta*rik*w
359 forces(katom, :) = forces(katom, :) + sbeta*kbeta*rik*w
360 forces(jatom, :) = forces(jatom, :) - jbeta*kbeta*rjk*w
361 forces(katom, :) = forces(katom, :) + jbeta*kbeta*rjk*w
362 END DO
363 END DO
364 END IF
365 END DO
366
367 CALL timestop(handle)
368 END SUBROUTINE calc_descriptor_overlap
369
370! **************************************************************************************************
371!> \brief Calculates a descriptor based on distance between two atoms
372!> \param particle_set ...
373!> \param qs_kind_set ...
374!> \param cell ...
375!> \param iatom ...
376!> \param descriptor ...
377!> \param descr_grad ...
378!> \param forces ...
379! **************************************************************************************************
380 SUBROUTINE calc_descriptor_r12(particle_set, qs_kind_set, cell, iatom, descriptor, descr_grad, forces)
381 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
382 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
383 TYPE(cell_type), POINTER :: cell
384 INTEGER, INTENT(IN) :: iatom
385 REAL(dp), ALLOCATABLE, DIMENSION(:), OPTIONAL :: descriptor
386 REAL(dp), DIMENSION(:), INTENT(IN), OPTIONAL :: descr_grad
387 REAL(dp), DIMENSION(:, :), INTENT(INOUT), OPTIONAL :: forces
388
389 REAL(dp), DIMENSION(3) :: g, r1, r12, r2
390
391 cpassert(SIZE(particle_set) == 2)
392
393 mark_used(qs_kind_set)
394 mark_used(iatom)
395 mark_used(cell)
396
397 r1 = particle_set(1)%r
398 r2 = particle_set(2)%r
399 r12 = pbc(r1, r2, cell)
400
401 IF (PRESENT(descriptor)) THEN
402 ALLOCATE (descriptor(1))
403 descriptor(1) = sqrt(sum(r12**2))
404 END IF
405
406 IF (PRESENT(forces)) THEN
407 cpassert(PRESENT(descr_grad))
408 g = r12/sqrt(sum(r12**2))*descr_grad(1)
409 forces(1, :) = forces(1, :) + g
410 forces(2, :) = forces(2, :) - g
411 END IF
412 END SUBROUTINE calc_descriptor_r12
413
414END 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:381
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, 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, 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, monovalent, floating, name, element_symbol, pao_basis_size, pao_model_file, 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:60
Holds information about a PAO descriptor.
Provides all information about a quickstep kind.