(git:f2099e5)
Loading...
Searching...
No Matches
gw_ri_rs_utils.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 Common setup operations used by the periodic and non-periodic GW RI-RS implementations.
10! **************************************************************************************************
14 USE cell_types, ONLY: cell_type,&
15 pbc
16 USE kinds, ONLY: dp
17 USE orbital_pointers, ONLY: indco,&
18 ncoset
20 USE physcon, ONLY: angstrom
22 USE qs_kind_types, ONLY: get_qs_kind,&
24#include "./base/base_uses.f90"
25
26 IMPLICIT NONE
27 PRIVATE
28
31
32 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'gw_ri_rs_utils'
33
34CONTAINS
35
36! **************************************************************************************************
37!> \brief Compute per-atom AO and RI basis radii from the most diffuse Gaussian
38!> primitive in the AO ("ORB") and RI auxiliary ("RI_AUX") basis sets.
39!> Stores results in bs_env%ri_rs%radius_ao_per_atom(:) and
40!> bs_env%ri_rs%radius_ri_per_atom(:) and prints a per-atom table.
41!> Radius: r_kind = sqrt(-log(eps)/alpha_min_kind), with eps = eps_filter.
42!> \param bs_env Band-structure environment containing GW parameters.
43! **************************************************************************************************
44 SUBROUTINE precompute_ri_rs_radii(bs_env)
45 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
46
47 CHARACTER(LEN=*), PARAMETER :: routinen = 'precompute_ri_rs_radii'
48 REAL(kind=dp), PARAMETER :: min_exponent_for_radius = 1.0e-3_dp
49
50 INTEGER :: handle, i, iatom, ikind, j, natom, nkind
51 INTEGER, ALLOCATABLE, DIMENSION(:) :: kind_of
52 REAL(kind=dp) :: eps
53 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: alpha_min_ao_kind, alpha_min_ri_kind
54 REAL(kind=dp), DIMENSION(:, :), POINTER :: zet_ao, zet_ri
55
56 CALL timeset(routinen, handle)
57
58 cpassert(ASSOCIATED(bs_env%ri_rs%atomic_kind_set))
59 nkind = SIZE(bs_env%ri_rs%atomic_kind_set)
60 natom = bs_env%n_atom
61 eps = bs_env%eps_filter
62
63 ALLOCATE (alpha_min_ao_kind(nkind), alpha_min_ri_kind(nkind))
64 alpha_min_ao_kind = huge(1.0_dp)
65 alpha_min_ri_kind = huge(1.0_dp)
66
67 DO ikind = 1, nkind
68 zet_ao => bs_env%basis_set_AO(ikind)%gto_basis_set%zet
69 zet_ri => bs_env%basis_set_RI(ikind)%gto_basis_set%zet
70 DO i = 1, SIZE(zet_ao, 1)
71 DO j = 1, SIZE(zet_ao, 2)
72 IF (zet_ao(i, j) > min_exponent_for_radius) THEN
73 alpha_min_ao_kind(ikind) = min(alpha_min_ao_kind(ikind), zet_ao(i, j))
74 END IF
75 END DO
76 END DO
77 DO i = 1, SIZE(zet_ri, 1)
78 DO j = 1, SIZE(zet_ri, 2)
79 IF (zet_ri(i, j) > min_exponent_for_radius) THEN
80 alpha_min_ri_kind(ikind) = min(alpha_min_ri_kind(ikind), zet_ri(i, j))
81 END IF
82 END DO
83 END DO
84 END DO
85
86 CALL get_atomic_kind_set(atomic_kind_set=bs_env%ri_rs%atomic_kind_set, kind_of=kind_of)
87
88 ALLOCATE (bs_env%ri_rs%radius_ao_per_atom(natom))
89 ALLOCATE (bs_env%ri_rs%radius_ri_per_atom(natom))
90 DO iatom = 1, natom
91 ikind = kind_of(iatom)
92 bs_env%ri_rs%radius_ao_per_atom(iatom) = sqrt(-log(eps)/alpha_min_ao_kind(ikind))
93 bs_env%ri_rs%radius_ri_per_atom(iatom) = sqrt(-log(eps)/alpha_min_ri_kind(ikind))
94 END DO
95
96 IF (bs_env%unit_nr > 0) THEN
97 WRITE (bs_env%unit_nr, '(T2,A)') 'RI-RS basis radii (Å):'
98 WRITE (bs_env%unit_nr, '(T4,A6,2X,A4,2A14)') 'Kind', 'Elem', 'r_AO (Å)', 'r_RI (Å)'
99 DO ikind = 1, nkind
100 WRITE (bs_env%unit_nr, '(T4,I6,2X,A4,2F14.4)') &
101 ikind, &
102 bs_env%ri_rs%atomic_kind_set(ikind)%element_symbol, &
103 sqrt(-log(eps)/alpha_min_ao_kind(ikind))*angstrom, &
104 sqrt(-log(eps)/alpha_min_ri_kind(ikind))*angstrom
105 END DO
106 WRITE (bs_env%unit_nr, '(A)') ' '
107 END IF
108
109 DEALLOCATE (alpha_min_ao_kind, alpha_min_ri_kind, kind_of)
110
111 CALL timestop(handle)
112
113 END SUBROUTINE precompute_ri_rs_radii
114
115!> \brief Retain source-grid points inside the Voronoi volume of one atom.
116!> \param points Source-grid coordinates on entry and Voronoi-filtered coordinates on return.
117!> \param icenter_atom Atom whose Voronoi volume is retained.
118!> \param particle_set Molecular atom positions.
119!> \param mask Optional membership mask; if present, leave points unchanged.
120!> \param atom_indices Optional subset of nuclei defining the Voronoi partition.
121! **************************************************************************************************
122 SUBROUTINE filter_grid_to_voronoi(points, icenter_atom, particle_set, mask, atom_indices)
123 REAL(kind=dp), ALLOCATABLE, INTENT(INOUT) :: points(:, :)
124 INTEGER, INTENT(IN) :: icenter_atom
125 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
126 LOGICAL, INTENT(OUT), OPTIONAL :: mask(:)
127 INTEGER, INTENT(IN), OPTIONAL :: atom_indices(:)
128
129 INTEGER :: iatom, iatom_index, ipoint, n_atoms, &
130 n_keep
131 LOGICAL, ALLOCATABLE :: keep(:)
132 REAL(kind=dp) :: displacement(3), distance2, max_radius2, &
133 tolerance
134 REAL(kind=dp), ALLOCATABLE :: filtered_points(:, :)
135
136 ALLOCATE (keep(SIZE(points, 2)), source=.true.)
137 max_radius2 = maxval(sum(points**2, dim=1))
138 n_atoms = SIZE(particle_set)
139 IF (PRESENT(atom_indices)) n_atoms = SIZE(atom_indices)
140 DO iatom_index = 1, n_atoms
141 IF (PRESENT(atom_indices)) THEN
142 iatom = atom_indices(iatom_index)
143 cpassert(iatom >= 1 .AND. iatom <= SIZE(particle_set))
144 ELSE
145 iatom = iatom_index
146 END IF
147 IF (iatom == icenter_atom) cycle
148 displacement(:) = particle_set(iatom)%r - particle_set(icenter_atom)%r
149 distance2 = sum(displacement**2)
150 ! |R_B-R_A| > 2 max_l|r_l-R_A| cannot cut this finite point set.
151 IF (distance2 > 4.0_dp*max_radius2) cycle
152 tolerance = 32.0_dp*epsilon(1.0_dp)*max(1.0_dp, distance2)
153 DO ipoint = 1, SIZE(points, 2)
154 IF (.NOT. keep(ipoint)) cycle
155 ! |r_l-R_B|² - |r_l-R_A|² = |R_B-R_A|² - 2(r_l-R_A)·(R_B-R_A).
156 IF (2.0_dp*dot_product(points(:, ipoint), displacement) > distance2 + tolerance) THEN
157 keep(ipoint) = .false.
158 ELSE IF (iatom < icenter_atom) THEN
159 IF (abs(2.0_dp*dot_product(points(:, ipoint), displacement) - distance2) <= tolerance) THEN
160 keep(ipoint) = .false.
161 END IF
162 END IF
163 END DO
164 END DO
165 IF (PRESENT(mask)) THEN
166 cpassert(SIZE(mask) == SIZE(keep))
167 mask(:) = keep
168 RETURN
169 END IF
170 n_keep = count(keep)
171 ALLOCATE (filtered_points(3, n_keep))
172 IF (n_keep > 0) filtered_points(:, :) = reshape(pack(points, spread(keep, 1, 3)), [3, n_keep])
173 CALL move_alloc(filtered_points, points)
174 END SUBROUTINE filter_grid_to_voronoi
175
176! **************************************************************************************************
177!> \brief Form C_A from nuclei within the specified radius, in global atom order.
178!> \param particle_set Molecular nuclei.
179!> \param cell Simulation cell.
180!> \param icenter_atom Central atom A.
181!> \param radius Cluster radius.
182!> \param atom_indices Cluster atom indices including A.
183! **************************************************************************************************
184 SUBROUTINE get_rirs_cluster_atoms(particle_set, cell, icenter_atom, radius, atom_indices)
185 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
186 TYPE(cell_type), POINTER :: cell
187 INTEGER, INTENT(IN) :: icenter_atom
188 REAL(kind=dp), INTENT(IN) :: radius
189 INTEGER, ALLOCATABLE, INTENT(OUT) :: atom_indices(:)
190
191 INTEGER :: iatom, ncluster
192 INTEGER, ALLOCATABLE :: work(:)
193
194 ALLOCATE (work(SIZE(particle_set)))
195 ncluster = 0
196 DO iatom = 1, SIZE(particle_set)
197 IF (sum(pbc(particle_set(iatom)%r - particle_set(icenter_atom)%r, cell)**2) <= radius**2) THEN
198 ncluster = ncluster + 1
199 work(ncluster) = iatom
200 END IF
201 END DO
202 ALLOCATE (atom_indices(ncluster), source=work(:ncluster))
203 END SUBROUTINE get_rirs_cluster_atoms
204
205! **************************************************************************************************
206!> \brief Evaluate contracted spherical AOs, and optionally their grid-coordinate derivatives.
207!>
208!> For atom A and displacement d(alpha)=r_l(alpha)-R_A(alpha), the value is
209!>
210!> ϕ_μ(r_l) = Σ_(p,c) S_(pc,μ) d_x^lx d_y^ly d_z^lz exp(-ζ_p |d|^2).
211!>
212!> The optional derivative is evaluated analytically as
213!>
214!> d ϕ_μ(r_l)/d r_(l,α)
215!> = sum_(p,c) S_(pc,mu) exp(-zeta_p |d|^2)
216!> [d polynomial_c/d d_alpha - 2 zeta_p d_alpha polynomial_c].
217!>
218!> \param phi AO values, accumulated into phi(l,mu).
219!> \param grid_points Cartesian grid points, indexed (alpha,l).
220!> \param iatom Source atom whose contracted AOs are evaluated.
221!> \param particle_set Molecular particles.
222!> \param qs_kind_set Quickstep atomic kinds containing the ORB bases.
223!> \param cell Simulation cell used for the minimum-image displacement.
224!> \param dphi Optional AO derivatives, accumulated into dphi(alpha,l,mu).
225!> \param cutoff_squared Optional squared AO cutoff radius.
226! **************************************************************************************************
227 SUBROUTINE evaluate_ao_on_points(phi, grid_points, iatom, particle_set, qs_kind_set, cell, &
228 dphi, cutoff_squared)
229 REAL(kind=dp), DIMENSION(:, :), INTENT(INOUT) :: phi
230 REAL(kind=dp), DIMENSION(:, :), INTENT(IN) :: grid_points
231 INTEGER, INTENT(IN) :: iatom
232 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
233 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
234 TYPE(cell_type), POINTER :: cell
235 REAL(kind=dp), DIMENSION(:, :, :), INTENT(INOUT), &
236 OPTIONAL :: dphi
237 REAL(kind=dp), INTENT(IN), OPTIONAL :: cutoff_squared
238
239 CHARACTER(len=*), PARAMETER :: routinen = 'evaluate_ao_on_points'
240
241 INTEGER :: handle, ikind
242 TYPE(gto_basis_set_type), POINTER :: basis
243
244 CALL timeset(routinen, handle)
245 cpassert(SIZE(grid_points, 1) == 3)
246 cpassert(SIZE(phi, 1) == SIZE(grid_points, 2))
247 IF (PRESENT(dphi)) THEN
248 cpassert(SIZE(dphi, 1) == 3)
249 cpassert(SIZE(dphi, 2) == SIZE(phi, 1))
250 cpassert(SIZE(dphi, 3) == SIZE(phi, 2))
251 END IF
252
253 ikind = particle_set(iatom)%atomic_kind%kind_number
254 CALL get_qs_kind(qs_kind_set(ikind), basis_set=basis, basis_type='ORB')
255 IF (.NOT. ASSOCIATED(basis)) THEN
256 CALL timestop(handle)
257 RETURN
258 END IF
259 CALL evaluate_ao_basis_on_points(phi, grid_points, basis, &
260 particle_set(iatom)%r, cell, dphi, cutoff_squared)
261 CALL timestop(handle)
262 END SUBROUTINE evaluate_ao_on_points
263
264! **************************************************************************************************
265!> \brief Evaluate one explicitly supplied contracted Gaussian basis on Cartesian points.
266!> \param phi AO values, accumulated into phi(l,mu).
267!> \param grid_points Cartesian grid points, indexed (alpha,l).
268!> \param basis Contracted Gaussian basis to evaluate.
269!> \param source_position Centre of the basis.
270!> \param cell Simulation cell used for the minimum-image displacement.
271!> \param dphi Optional AO derivatives, accumulated into dphi(alpha,l,mu).
272!> \param cutoff_squared Optional squared AO cutoff radius.
273! **************************************************************************************************
274 SUBROUTINE evaluate_ao_basis_on_points(phi, grid_points, basis, source_position, cell, &
275 dphi, cutoff_squared)
276 REAL(kind=dp), DIMENSION(:, :), INTENT(INOUT) :: phi
277 REAL(kind=dp), DIMENSION(:, :), INTENT(IN) :: grid_points
278 TYPE(gto_basis_set_type), POINTER :: basis
279 REAL(kind=dp), DIMENSION(3), INTENT(IN) :: source_position
280 TYPE(cell_type), POINTER :: cell
281 REAL(kind=dp), DIMENSION(:, :, :), INTENT(INOUT), &
282 OPTIONAL :: dphi
283 REAL(kind=dp), INTENT(IN), OPTIONAL :: cutoff_squared
284
285 INTEGER :: first_sgf, ialpha, ico, iend_co, ipgf, &
286 ipoint, irow, iset, isgf, ishell, &
287 istart_co, l, last_sgf, lx, ly, lz, &
288 n_cart_total
289 REAL(kind=dp) :: exponent, exponential, polynomial, &
290 polynomial_derivative(3), radius2, &
291 relative(3), weight
292
293 cpassert(ASSOCIATED(basis))
294 cpassert(SIZE(grid_points, 1) == 3)
295 cpassert(SIZE(phi, 1) == SIZE(grid_points, 2))
296 IF (PRESENT(dphi)) THEN
297 cpassert(SIZE(dphi, 1) == 3)
298 cpassert(SIZE(dphi, 2) == SIZE(phi, 1))
299 cpassert(SIZE(dphi, 3) == SIZE(phi, 2))
300 END IF
301
302 !$OMP PARALLEL DO DEFAULT(NONE) SCHEDULE(STATIC) &
303 !$OMP SHARED(phi, dphi, grid_points, cell, basis, source_position, cutoff_squared, ncoset, indco) &
304 !$OMP PRIVATE(ipoint, relative, radius2, iset, n_cart_total, ishell, l, istart_co, &
305 !$OMP iend_co, first_sgf, last_sgf, ipgf, exponent, exponential, isgf, ico, &
306 !$OMP irow, weight, lx, ly, lz, polynomial, polynomial_derivative, ialpha)
307 DO ipoint = 1, SIZE(grid_points, 2)
308 relative = pbc(grid_points(:, ipoint) - source_position, cell)
309 radius2 = dot_product(relative, relative)
310 IF (PRESENT(cutoff_squared)) THEN
311 IF (radius2 > cutoff_squared) cycle
312 END IF
313
314 DO iset = 1, basis%nset
315 n_cart_total = ncoset(basis%lmax(iset))
316 DO ishell = 1, basis%nshell(iset)
317 l = basis%l(ishell, iset)
318 istart_co = ncoset(l - 1) + 1
319 iend_co = ncoset(l)
320 first_sgf = basis%first_sgf(ishell, iset)
321 last_sgf = basis%last_sgf(ishell, iset)
322 DO ipgf = 1, basis%npgf(iset)
323 exponent = basis%zet(ipgf, iset)
324 exponential = exp(-exponent*radius2)
325 DO isgf = first_sgf, last_sgf
326 DO ico = istart_co, iend_co
327 irow = (ipgf - 1)*n_cart_total + ico
328 weight = basis%sphi(irow, isgf)
329 lx = indco(1, ico)
330 ly = indco(2, ico)
331 lz = indco(3, ico)
332 polynomial = relative(1)**lx*relative(2)**ly*relative(3)**lz
333 phi(ipoint, isgf) = phi(ipoint, isgf) + weight*polynomial*exponential
334
335 IF (PRESENT(dphi)) THEN
336 polynomial_derivative = 0.0_dp
337 IF (lx > 0) polynomial_derivative(1) = real(lx, dp)*relative(1)**(lx - 1)* &
338 relative(2)**ly*relative(3)**lz
339 IF (ly > 0) polynomial_derivative(2) = real(ly, dp)*relative(1)**lx* &
340 relative(2)**(ly - 1)*relative(3)**lz
341 IF (lz > 0) polynomial_derivative(3) = real(lz, dp)*relative(1)**lx* &
342 relative(2)**ly*relative(3)**(lz - 1)
343 DO ialpha = 1, 3
344 dphi(ialpha, ipoint, isgf) = dphi(ialpha, ipoint, isgf) + weight*exponential* &
345 (polynomial_derivative(ialpha) - &
346 2.0_dp*exponent*relative(ialpha)*polynomial)
347 END DO
348 END IF
349 END DO
350 END DO
351 END DO
352 END DO
353 END DO
354 END DO
355 !$OMP END PARALLEL DO
356 END SUBROUTINE evaluate_ao_basis_on_points
357
358END MODULE gw_ri_rs_utils
Define the atomic kind types and their sub types.
subroutine, public get_atomic_kind_set(atomic_kind_set, atom_of_kind, kind_of, natom_of_kind, maxatom, natom, nshell, fist_potential_present, shell_present, shell_adiabatic, shell_check_distance, damping_present)
Get attributes of an atomic kind set.
Handles all functions related to the CELL.
Definition cell_types.F:15
Common setup operations used by the periodic and non-periodic GW RI-RS implementations.
subroutine, public get_rirs_cluster_atoms(particle_set, cell, icenter_atom, radius, atom_indices)
Form C_A from nuclei within the specified radius, in global atom order.
subroutine, public precompute_ri_rs_radii(bs_env)
Compute per-atom AO and RI basis radii from the most diffuse Gaussian primitive in the AO ("ORB") and...
subroutine, public filter_grid_to_voronoi(points, icenter_atom, particle_set, mask, atom_indices)
Retain source-grid points inside the Voronoi volume of one atom.
subroutine, public evaluate_ao_on_points(phi, grid_points, iatom, particle_set, qs_kind_set, cell, dphi, cutoff_squared)
Evaluate contracted spherical AOs, and optionally their grid-coordinate derivatives.
subroutine, public evaluate_ao_basis_on_points(phi, grid_points, basis, source_position, cell, dphi, cutoff_squared)
Evaluate one explicitly supplied contracted Gaussian basis on Cartesian points.
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Provides Cartesian and spherical orbital pointers and indices.
integer, dimension(:), allocatable, public ncoset
integer, dimension(:, :), allocatable, public indco
Define the data structure for the particle information.
Definition of physical constants:
Definition physcon.F:68
real(kind=dp), parameter, public angstrom
Definition physcon.F:144
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, hund_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, proj_shell_charge, lr_atom, do_mtlr, u_j_loop, ao_coef, 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.
Type defining parameters related to the simulation cell.
Definition cell_types.F:60
Provides all information about a quickstep kind.