(git:374b731)
Loading...
Searching...
No Matches
pao_potentials.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 Factory routines for potentials used e.g. by pao_param_exp and pao_ml
10!> \author Ole Schuett
11! **************************************************************************************************
13 USE ai_overlap, ONLY: overlap_aab
14 USE ao_util, ONLY: exp_radius
17 USE cell_types, ONLY: cell_type,&
18 pbc
19 USE kinds, ONLY: dp
20 USE mathconstants, ONLY: gamma1
21 USE mathlib, ONLY: multinomial
22 USE orbital_pointers, ONLY: indco,&
23 ncoset,&
24 orbital_pointers_maxl => current_maxl
28 USE qs_kind_types, ONLY: get_qs_kind,&
30#include "./base/base_uses.f90"
31
32 IMPLICIT NONE
33
34 PRIVATE
35
36 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'pao_potentials'
37
39
40CONTAINS
41
42! **************************************************************************************************
43!> \brief Makes an educated guess for the initial potential based on positions of neighboring atoms
44!> \param qs_env ...
45!> \param iatom ...
46!> \param block_V ...
47! **************************************************************************************************
48 SUBROUTINE pao_guess_initial_potential(qs_env, iatom, block_V)
49 TYPE(qs_environment_type), POINTER :: qs_env
50 INTEGER, INTENT(IN) :: iatom
51 REAL(dp), DIMENSION(:, :), INTENT(OUT) :: block_v
52
53 CHARACTER(len=*), PARAMETER :: routinen = 'pao_guess_initial_potential'
54
55 INTEGER :: handle, ikind, jatom, natoms
56 REAL(dp), DIMENSION(3) :: ra, rab, rb
57 TYPE(cell_type), POINTER :: cell
58 TYPE(gto_basis_set_type), POINTER :: basis_set
59 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
60 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
61
62 CALL timeset(routinen, handle)
63
64 CALL get_qs_env(qs_env, &
65 cell=cell, &
66 particle_set=particle_set, &
67 qs_kind_set=qs_kind_set, &
68 natom=natoms)
69
70 CALL get_atomic_kind(particle_set(iatom)%atomic_kind, kind_number=ikind)
71 CALL get_qs_kind(qs_kind_set(ikind), basis_set=basis_set)
72
73 ! construct matrix block_V from neighboring atoms
74 block_v = 0.0_dp
75 DO jatom = 1, natoms
76 IF (jatom == iatom) cycle
77 ra = particle_set(iatom)%r
78 rb = particle_set(jatom)%r
79 rab = pbc(ra, rb, cell)
80 CALL pao_calc_gaussian(basis_set, block_v, rab=rab, lpot=0, beta=1.0_dp, weight=-1.0_dp)
81 END DO
82
83 CALL timestop(handle)
84 END SUBROUTINE pao_guess_initial_potential
85
86! **************************************************************************************************
87!> \brief Calculates potential term of the form r**lpot * Exp(-beta*r**2)
88!> One needs to call init_orbital_pointers(lpot) before calling pao_calc_gaussian().
89!> \param basis_set ...
90!> \param block_V potential term that is returned
91!> \param block_D derivative of potential term wrt to Rab
92!> \param Rab ...
93!> \param lpot polynomial prefactor, r**lpot
94!> \param beta exponent of the Gaussian
95!> \param weight ...
96!> \param min_shell ...
97!> \param max_shell ...
98!> \param min_l ...
99!> \param max_l ...
100! **************************************************************************************************
101 SUBROUTINE pao_calc_gaussian(basis_set, block_V, block_D, Rab, lpot, beta, weight, min_shell, max_shell, min_l, max_l)
102 TYPE(gto_basis_set_type), POINTER :: basis_set
103 REAL(dp), DIMENSION(:, :), INTENT(OUT), OPTIONAL :: block_v
104 REAL(dp), DIMENSION(:, :, :), INTENT(OUT), &
105 OPTIONAL :: block_d
106 REAL(dp), DIMENSION(3) :: rab
107 INTEGER, INTENT(IN) :: lpot
108 REAL(dp), INTENT(IN) :: beta, weight
109 INTEGER, INTENT(IN), OPTIONAL :: min_shell, max_shell, min_l, max_l
110
111 CHARACTER(len=*), PARAMETER :: routinen = 'pao_calc_gaussian'
112
113 INTEGER :: handle, i, ic, iset, ishell, ishell_abs, jset, jshell, jshell_abs, la1_max, &
114 la1_min, la2_max, la2_min, lb_max, lb_min, n, na1, na2, nb, ncfga1, ncfga2, ncfgb, &
115 npgfa1, npgfa2, npgfb
116 REAL(dp) :: coeff, norm2
117 REAL(dp), DIMENSION(:), POINTER :: rpgfa1, rpgfa2, rpgfb, zeta1, zeta2, zetb
118 REAL(dp), DIMENSION(:, :), POINTER :: new_block_v, sab
119 REAL(dp), DIMENSION(:, :, :), POINTER :: dab, new_block_d, saab
120 REAL(dp), DIMENSION(:, :, :, :), POINTER :: daab
121
122 CALL timeset(routinen, handle)
123
124 cpassert(PRESENT(block_v) .NEQV. PRESENT(block_d)) ! just to keep the code simpler
125 cpassert(PRESENT(min_shell) .EQV. PRESENT(max_shell))
126 cpassert(PRESENT(min_l) .EQV. PRESENT(max_l))
127
128 cpassert(mod(lpot, 2) == 0) ! otherwise it's not rotationally invariant
129 cpassert(orbital_pointers_maxl >= lpot) ! can't call init_orbital_pointers here, it's not thread-safe
130
131 n = basis_set%nsgf ! primary basis-size
132
133 IF (PRESENT(block_v)) THEN
134 cpassert(SIZE(block_v, 1) == n .AND. SIZE(block_v, 2) == n)
135 ALLOCATE (new_block_v(n, n))
136 new_block_v = 0.0_dp
137 END IF
138 IF (PRESENT(block_d)) THEN
139 cpassert(SIZE(block_d, 1) == n .AND. SIZE(block_d, 2) == n .AND. SIZE(block_d, 3) == 3)
140 ALLOCATE (new_block_d(n, n, 3))
141 new_block_d = 0.0_dp
142 END IF
143
144 ! setup description of potential
145 lb_min = lpot
146 lb_max = lpot
147 ncfgb = ncoset(lb_max) - ncoset(lb_min - 1)
148 npgfb = 1 ! number of exponents
149 nb = npgfb*ncfgb
150
151 ! initialize exponents
152 ALLOCATE (rpgfb(npgfb), zetb(npgfb))
153 rpgfb(1) = exp_radius(0, beta, 1.0e-12_dp, 1.0_dp) ! TODO get the EPS parameter from somewhere / precompute this elsewhere
154 zetb(1) = beta
155
156 ! loop over all set/shell combination and fill block_V
157 DO iset = 1, basis_set%nset
158 DO jset = 1, basis_set%nset
159 DO ishell = 1, basis_set%nshell(iset)
160 DO jshell = 1, basis_set%nshell(jset)
161 IF (PRESENT(min_shell) .AND. PRESENT(max_shell)) THEN
162 ishell_abs = sum(basis_set%nshell(1:iset - 1)) + ishell
163 jshell_abs = sum(basis_set%nshell(1:jset - 1)) + jshell
164 IF (min(ishell_abs, jshell_abs) /= min_shell) cycle
165 IF (max(ishell_abs, jshell_abs) /= max_shell) cycle
166 END IF
167 IF (PRESENT(min_l) .AND. PRESENT(min_l)) THEN
168 IF (min(basis_set%l(ishell, iset), basis_set%l(jshell, jset)) /= min_l) cycle
169 IF (max(basis_set%l(ishell, iset), basis_set%l(jshell, jset)) /= max_l) cycle
170 END IF
171
172 ! setup iset
173 la1_max = basis_set%l(ishell, iset)
174 la1_min = basis_set%l(ishell, iset)
175 npgfa1 = basis_set%npgf(iset)
176 ncfga1 = ncoset(la1_max) - ncoset(la1_min - 1)
177 na1 = npgfa1*ncfga1
178 zeta1 => basis_set%zet(:, iset)
179 rpgfa1 => basis_set%pgf_radius(:, iset)
180
181 ! setup jset
182 la2_max = basis_set%l(jshell, jset)
183 la2_min = basis_set%l(jshell, jset)
184 npgfa2 = basis_set%npgf(jset)
185 ncfga2 = ncoset(la2_max) - ncoset(la2_min - 1)
186 na2 = npgfa2*ncfga2
187 zeta2 => basis_set%zet(:, jset)
188 rpgfa2 => basis_set%pgf_radius(:, jset)
189
190 ! calculate integrals
191 IF (PRESENT(block_v)) THEN
192 ALLOCATE (saab(na1, na2, nb))
193 saab = 0.0_dp
194 CALL overlap_aab(la1_max=la1_max, la1_min=la1_min, npgfa1=npgfa1, rpgfa1=rpgfa1, zeta1=zeta1, &
195 la2_max=la2_max, la2_min=la2_min, npgfa2=npgfa2, rpgfa2=rpgfa2, zeta2=zeta2, &
196 lb_max=lb_max, lb_min=lb_min, npgfb=npgfb, rpgfb=rpgfb, zetb=zetb, &
197 rab=rab, saab=saab)
198 END IF
199
200 IF (PRESENT(block_d)) THEN
201 ALLOCATE (daab(na1, na2, nb, 3))
202 daab = 0.0_dp
203 CALL overlap_aab(la1_max=la1_max, la1_min=la1_min, npgfa1=npgfa1, rpgfa1=rpgfa1, zeta1=zeta1, &
204 la2_max=la2_max, la2_min=la2_min, npgfa2=npgfa2, rpgfa2=rpgfa2, zeta2=zeta2, &
205 lb_max=lb_max, lb_min=lb_min, npgfb=npgfb, rpgfb=rpgfb, zetb=zetb, &
206 rab=rab, daab=daab)
207 END IF
208
209 ! sum potential terms: POW(x**2 + y**2 + z**2, lpot/2)
210 IF (PRESENT(block_v)) THEN
211 ALLOCATE (sab(na1, na2))
212 sab = 0.0_dp
213 DO ic = 1, ncfgb
214 coeff = multinomial(lpot/2, indco(:, ncoset(lpot - 1) + ic)/2)
215 sab = sab + coeff*saab(:, :, ic)
216 END DO
217 CALL my_contract(sab=sab, block=new_block_v, basis_set=basis_set, &
218 iset=iset, ishell=ishell, jset=jset, jshell=jshell)
219 DEALLOCATE (sab, saab)
220 END IF
221
222 IF (PRESENT(block_d)) THEN
223 ALLOCATE (dab(na1, na2, 3))
224 dab = 0.0_dp
225 DO ic = 1, ncfgb
226 coeff = multinomial(lpot/2, indco(:, ncoset(lpot - 1) + ic)/2)
227 dab = dab + coeff*daab(:, :, ic, :)
228 END DO
229 DO i = 1, 3
230 CALL my_contract(sab=dab(:, :, i), block=new_block_d(:, :, i), basis_set=basis_set, &
231 iset=iset, ishell=ishell, jset=jset, jshell=jshell)
232 END DO
233 DEALLOCATE (dab, daab)
234 END IF
235 END DO
236 END DO
237 END DO
238 END DO
239
240 DEALLOCATE (rpgfb, zetb)
241
242 ! post-processing
243 norm2 = (2.0_dp*beta)**(-0.5_dp - lpot)*gamma1(lpot)
244 IF (PRESENT(block_v)) THEN
245 block_v = block_v + weight*new_block_v/sqrt(norm2)
246 DEALLOCATE (new_block_v)
247 block_v = 0.5_dp*(block_v + transpose(block_v)) ! symmetrize
248 END IF
249
250 IF (PRESENT(block_d)) THEN
251 block_d = block_d + weight*new_block_d/sqrt(norm2)
252 DEALLOCATE (new_block_d)
253 DO i = 1, 3
254 block_d(:, :, i) = 0.5_dp*(block_d(:, :, i) + transpose(block_d(:, :, i))) ! symmetrize
255 END DO
256 END IF
257
258 CALL timestop(handle)
259 END SUBROUTINE pao_calc_gaussian
260
261! **************************************************************************************************
262!> \brief Helper routine, contracts a basis block
263!> \param sab ...
264!> \param block ...
265!> \param basis_set ...
266!> \param iset ...
267!> \param ishell ...
268!> \param jset ...
269!> \param jshell ...
270! **************************************************************************************************
271 SUBROUTINE my_contract(sab, block, basis_set, iset, ishell, jset, jshell)
272 REAL(dp), DIMENSION(:, :), INTENT(IN), TARGET :: sab
273 REAL(dp), DIMENSION(:, :), INTENT(OUT), TARGET :: block
274 TYPE(gto_basis_set_type), POINTER :: basis_set
275 INTEGER, INTENT(IN) :: iset, ishell, jset, jshell
276
277 INTEGER :: a, b, c, d, ipgf, jpgf, l1, l2, n1, n2, &
278 nn1, nn2, sgfa1, sgfa2, sgla1, sgla2
279 REAL(dp), DIMENSION(:, :), POINTER :: s, t1, t2, v
280
281 ! first and last indices of given shell in block.
282 ! This matrix is in the contracted spherical basis.
283 sgfa1 = basis_set%first_sgf(ishell, iset)
284 sgla1 = basis_set%last_sgf(ishell, iset)
285 sgfa2 = basis_set%first_sgf(jshell, jset)
286 sgla2 = basis_set%last_sgf(jshell, jset)
287
288 ! prepare the result matrix
289 v => block(sgfa1:sgla1, sgfa2:sgla2)
290
291 ! Calculate strides of sphi matrix.
292 ! This matrix is in the uncontraced cartesian basis.
293 ! It contains all shells of the set.
294 ! Its index runs over all primitive gaussians of the set
295 ! and then for each gaussian over all configurations of *the entire set*. (0->lmax)
296 nn1 = ncoset(basis_set%lmax(iset))
297 nn2 = ncoset(basis_set%lmax(jset))
298
299 ! Calculate strides of sab matrix
300 ! This matrix is also in the uncontraced cartensian basis,
301 ! however it contains only a single shell.
302 ! Its index runs over all primitive gaussians of the set
303 ! and then for each gaussian over all configrations of *the given shell*.
304 l1 = basis_set%l(ishell, iset)
305 l2 = basis_set%l(jshell, jset)
306 n1 = ncoset(l1) - ncoset(l1 - 1)
307 n2 = ncoset(l2) - ncoset(l2 - 1)
308
309 DO ipgf = 1, basis_set%npgf(iset)
310 DO jpgf = 1, basis_set%npgf(jset)
311 ! prepare first trafo-matrix
312 a = (ipgf - 1)*nn1 + ncoset(l1 - 1) + 1
313 t1 => basis_set%sphi(a:a + n1 - 1, sgfa1:sgla1)
314
315 ! prepare second trafo-matrix
316 b = (jpgf - 1)*nn2 + ncoset(l2 - 1) + 1
317 t2 => basis_set%sphi(b:b + n2 - 1, sgfa2:sgla2)
318
319 ! prepare SAB matrix
320 c = (ipgf - 1)*n1 + 1
321 d = (jpgf - 1)*n2 + 1
322 s => sab(c:c + n1 - 1, d:d + n2 - 1)
323
324 ! do the transformation
325 v = v + matmul(transpose(t1), matmul(s, t2))
326 END DO
327 END DO
328
329 END SUBROUTINE my_contract
330
331END MODULE pao_potentials
Calculation of the overlap integrals over Cartesian Gaussian-type functions.
Definition ai_overlap.F:18
subroutine, public overlap_aab(la1_max, la1_min, npgfa1, rpgfa1, zeta1, la2_max, la2_min, npgfa2, rpgfa2, zeta2, lb_max, lb_min, npgfb, rpgfb, zetb, rab, saab, daab, saba, daba)
Calculation of the two-center overlap integrals [aa|b] over Cartesian Gaussian-type functions.
Definition ai_overlap.F:967
All kind of helpful little routines.
Definition ao_util.F:14
real(kind=dp) function, public exp_radius(l, alpha, threshold, prefactor, epsabs, epsrel, rlow)
The radius of a primitive Gaussian function for a given threshold is calculated. g(r) = prefactor*r**...
Definition ao_util.F:96
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), dimension(0:maxfac), parameter, public gamma1
Collection of simple mathematical functions and subroutines.
Definition mathlib.F:15
pure real(kind=dp) function, public multinomial(n, k)
Calculates the multinomial coefficients.
Definition mathlib.F:254
Provides Cartesian and spherical orbital pointers and indices.
integer, save, public current_maxl
integer, dimension(:), allocatable, public ncoset
integer, dimension(:, :), allocatable, public indco
Factory routines for potentials used e.g. by pao_param_exp and pao_ml.
subroutine, public pao_guess_initial_potential(qs_env, iatom, block_v)
Makes an educated guess for the initial potential based on positions of neighboring atoms.
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...
Define the data structure for the particle information.
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, 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_nonbond, sab_almo, sab_kp, sab_kp_nosym, 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, 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, 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, ecoul_1c, rho0_s_rs, rho0_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, 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, rhs)
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, 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.
Type defining parameters related to the simulation cell.
Definition cell_types.F:55
Provides all information about a quickstep kind.