25#include "./base/base_uses.f90"
30 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'rirs_grid_utils'
45 CHARACTER(LEN=*),
INTENT(IN) :: element_symbol
46 INTEGER,
INTENT(IN) :: grid_select
47 CHARACTER(LEN=*),
INTENT(IN) :: grid_file_suffix
48 CHARACTER(LEN=*),
INTENT(OUT) :: filepath
50 CHARACTER(LEN=default_string_length) :: suffix
52 SELECT CASE (grid_select)
54 suffix =
"_def2-tzvp-rs.ion"
56 suffix =
"_cc-pvtz-rs.ion"
58 IF (len_trim(grid_file_suffix) > 0)
THEN
59 suffix = trim(grid_file_suffix)
64 cpabort(
"Unknown grid_select (1=def2-TZVPP, 2=cc-pVTZ, 3=user-provided).")
66 filepath =
"ri_rs_grid/"//trim(element_symbol)//trim(suffix)
75 CHARACTER(LEN=*),
INTENT(IN) :: filename
79 CALL open_file(file_name=trim(filename), unit_number=iunit, &
80 file_action=
'READ', file_status=
'OLD')
81 CALL read_rirs_grid_header(iunit, filename, npoints)
91 CHARACTER(LEN=*),
INTENT(IN) :: filename
92 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :), &
95 CHARACTER(len=*),
PARAMETER :: routinen =
'read_rirs_grid_file'
97 CHARACTER(LEN=default_path_length) :: line
98 INTEGER :: handle, ierr, iunit, l, npoints
99 LOGICAL :: found_points
101 CALL timeset(routinen, handle)
102 CALL open_file(file_name=trim(filename), unit_number=iunit, &
103 file_action=
'READ', file_status=
'OLD')
105 CALL read_rirs_grid_header(iunit, filename, npoints)
108 found_points = .false.
110 READ (iunit,
'(A)', iostat=ierr) line
112 IF (index(line,
'<grid_points>') > 0)
THEN
113 found_points = .true.
117 IF (.NOT. found_points) cpabort(
'RI-RS .ion file has no <grid_points> block: '//trim(filename))
119 ALLOCATE (points(3, npoints))
121 READ (iunit, *, iostat=ierr) points(:, l)
122 IF (ierr /= 0) cpabort(
'Invalid grid point in RI-RS .ion file: '//trim(filename))
125 CALL timestop(handle)
134 SUBROUTINE read_rirs_grid_header(iunit, filename, npoints)
135 INTEGER,
INTENT(IN) :: iunit
136 CHARACTER(LEN=*),
INTENT(IN) :: filename
137 INTEGER,
INTENT(OUT) :: npoints
139 CHARACTER(LEN=default_path_length) :: line
140 INTEGER :: colon, ierr
141 LOGICAL :: found_size
146 READ (iunit,
'(A)', iostat=ierr) line
148 IF (index(line,
'n points') > 0)
THEN
149 colon = index(line,
':')
151 READ (line(colon + 1:), *, iostat=ierr) npoints
152 found_size = ierr == 0 .AND. npoints > 0
157 IF (.NOT. found_size) cpabort(
'RI-RS .ion file has no valid n points field: '//trim(filename))
158 END SUBROUTINE read_rirs_grid_header
170 REAL(kind=
dp),
ALLOCATABLE,
INTENT(INOUT) :: points(:, :)
171 INTEGER,
INTENT(IN) :: n_select, center_atom
173 INTEGER,
INTENT(OUT) :: n_voronoi_candidates
175 REAL(kind=
dp),
ALLOCATABLE :: source_points(:, :)
177 cpassert(
SIZE(points, 1) == 3)
178 cpassert(center_atom >= 1 .AND. center_atom <=
SIZE(particle_set))
179 ALLOCATE (source_points, source=points)
180 CALL filter_grid_to_voronoi(points, center_atom, particle_set)
181 n_voronoi_candidates =
SIZE(points, 2)
182 IF (n_voronoi_candidates < n_select)
CALL move_alloc(source_points, points)
183 CALL select_grid_points(points, n_select)
192 SUBROUTINE filter_grid_to_voronoi(points, center_atom, particle_set)
193 REAL(kind=
dp),
ALLOCATABLE,
INTENT(INOUT) :: points(:, :)
194 INTEGER,
INTENT(IN) :: center_atom
197 INTEGER :: iatom, ipoint, n_keep
198 LOGICAL,
ALLOCATABLE :: keep(:)
199 REAL(kind=
dp) :: other_distance_squared, &
200 own_distance_squared, physical_point(3)
201 REAL(kind=
dp),
ALLOCATABLE :: filtered_points(:, :)
203 ALLOCATE (keep(
SIZE(points, 2)), source=.true.)
204 DO ipoint = 1,
SIZE(points, 2)
205 physical_point = particle_set(center_atom)%r + points(:, ipoint)
206 own_distance_squared = sum(points(:, ipoint)**2)
207 DO iatom = 1,
SIZE(particle_set)
208 IF (iatom == center_atom) cycle
209 other_distance_squared = sum((physical_point - particle_set(iatom)%r)**2)
210 IF (other_distance_squared < own_distance_squared)
THEN
211 keep(ipoint) = .false.
218 ALLOCATE (filtered_points(3, n_keep))
219 IF (n_keep > 0) filtered_points(:, :) = reshape(pack(points, spread(keep, 1, 3)), [3, n_keep])
220 CALL move_alloc(filtered_points, points)
221 END SUBROUTINE filter_grid_to_voronoi
228 SUBROUTINE select_grid_points(points, n_select)
229 REAL(kind=
dp),
ALLOCATABLE,
INTENT(INOUT) :: points(:, :)
230 INTEGER,
INTENT(IN) :: n_select
232 INTEGER :: candidate, i, isel, n_source
233 LOGICAL,
ALLOCATABLE :: available(:)
235 REAL(kind=
dp),
ALLOCATABLE :: nearest_squared(:), selected_points(:, :)
237 n_source =
SIZE(points, 2)
238 IF (n_select <= 0) cpabort(
"GRID_SIZE point counts must be positive.")
239 IF (n_select > n_source)
THEN
240 cpabort(
"GRID_SIZE exceeds the number of available RI-RS source-grid points.")
242 IF (n_select == n_source)
RETURN
244 ALLOCATE (available(n_source), nearest_squared(n_source), selected_points(3, n_select))
247 candidate = minloc(sum(points**2, dim=1), dim=1)
248 selected_points(:, 1) = points(:, candidate)
249 available(candidate) = .false.
250 nearest_squared(:) = sum((points - spread(selected_points(:, 1), 2, n_source))**2, dim=1)
252 DO isel = 2, n_select
254 best_distance = -1.0_dp
256 IF (available(i) .AND. nearest_squared(i) > best_distance)
THEN
258 best_distance = nearest_squared(i)
261 cpassert(candidate > 0)
262 selected_points(:, isel) = points(:, candidate)
263 available(candidate) = .false.
265 IF (available(i))
THEN
272 CALL move_alloc(selected_points, points)
273 END SUBROUTINE select_grid_points
302 dphi, cutoff_squared)
303 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: phi
304 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: grid_points
305 INTEGER,
INTENT(IN) :: atom_index
307 TYPE(
qs_kind_type),
DIMENSION(:),
POINTER :: qs_kind_set
309 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(INOUT), &
311 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: cutoff_squared
313 CHARACTER(len=*),
PARAMETER :: routinen =
'evaluate_ao_on_points'
315 INTEGER :: handle, kind_index
318 CALL timeset(routinen, handle)
319 cpassert(
SIZE(grid_points, 1) == 3)
320 cpassert(
SIZE(phi, 1) ==
SIZE(grid_points, 2))
321 IF (
PRESENT(dphi))
THEN
322 cpassert(
SIZE(dphi, 1) == 3)
323 cpassert(
SIZE(dphi, 2) ==
SIZE(phi, 1))
324 cpassert(
SIZE(dphi, 3) ==
SIZE(phi, 2))
327 kind_index = particle_set(atom_index)%atomic_kind%kind_number
328 CALL get_qs_kind(qs_kind_set(kind_index), basis_set=basis, basis_type=
'ORB')
329 IF (.NOT.
ASSOCIATED(basis))
THEN
330 CALL timestop(handle)
334 particle_set(atom_index)%r, cell, dphi, cutoff_squared)
335 CALL timestop(handle)
349 dphi, cutoff_squared)
350 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: phi
351 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: grid_points
353 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: source_position
355 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(INOUT), &
357 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: cutoff_squared
359 INTEGER :: alpha, first_sgf, ico, iend_co, ipgf, &
360 iset, isgf, ishell, istart_co, l, &
361 last_sgf, lx, ly, lz, n_cart_total, &
363 REAL(kind=
dp) :: exponent, exponential, polynomial, &
364 polynomial_derivative(3), radius2, &
367 cpassert(
ASSOCIATED(basis))
368 cpassert(
SIZE(grid_points, 1) == 3)
369 cpassert(
SIZE(phi, 1) ==
SIZE(grid_points, 2))
370 IF (
PRESENT(dphi))
THEN
371 cpassert(
SIZE(dphi, 1) == 3)
372 cpassert(
SIZE(dphi, 2) ==
SIZE(phi, 1))
373 cpassert(
SIZE(dphi, 3) ==
SIZE(phi, 2))
381 DO point = 1,
SIZE(grid_points, 2)
382 relative =
pbc(grid_points(:, point) - source_position, cell)
383 radius2 = dot_product(relative, relative)
384 IF (
PRESENT(cutoff_squared))
THEN
385 IF (radius2 > cutoff_squared) cycle
388 DO iset = 1, basis%nset
389 n_cart_total =
ncoset(basis%lmax(iset))
390 DO ishell = 1, basis%nshell(iset)
391 l = basis%l(ishell, iset)
392 istart_co =
ncoset(l - 1) + 1
394 first_sgf = basis%first_sgf(ishell, iset)
395 last_sgf = basis%last_sgf(ishell, iset)
396 DO ipgf = 1, basis%npgf(iset)
397 exponent = basis%zet(ipgf, iset)
398 exponential = exp(-exponent*radius2)
399 DO isgf = first_sgf, last_sgf
400 DO ico = istart_co, iend_co
401 row_index = (ipgf - 1)*n_cart_total + ico
402 weight = basis%sphi(row_index, isgf)
406 polynomial = relative(1)**lx*relative(2)**ly*relative(3)**lz
407 phi(point, isgf) = phi(point, isgf) + weight*polynomial*exponential
409 IF (
PRESENT(dphi))
THEN
410 polynomial_derivative = 0.0_dp
411 IF (lx > 0) polynomial_derivative(1) = real(lx,
dp)*relative(1)**(lx - 1)* &
412 relative(2)**ly*relative(3)**lz
413 IF (ly > 0) polynomial_derivative(2) = real(ly,
dp)*relative(1)**lx* &
414 relative(2)**(ly - 1)*relative(3)**lz
415 IF (lz > 0) polynomial_derivative(3) = real(lz,
dp)*relative(1)**lx* &
416 relative(2)**ly*relative(3)**(lz - 1)
418 dphi(alpha, point, isgf) = dphi(alpha, point, isgf) + weight*exponential* &
419 (polynomial_derivative(alpha) - 2.0_dp*exponent*relative(alpha)*polynomial)
double distance_squared(double *A, double *B)
Handles all functions related to the CELL.
Utility routines to open and close files. Tracking of preconnections.
subroutine, public open_file(file_name, file_status, file_form, file_action, file_position, file_pad, unit_number, debug, skip_get_unit_number, file_access)
Opens the requested file using a free unit number.
subroutine, public close_file(unit_number, file_status, keep_preconnection)
Close an open file given by its logical unit number. Optionally, keep the file and unit preconnected.
Defines the basic variable types.
integer, parameter, public dp
integer, parameter, public default_string_length
integer, parameter, public default_path_length
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.
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.
Shared RI-RS grid I/O and contracted-Gaussian evaluation utilities.
integer function, public read_rirs_grid_npoints(filename)
Read the number of points from an RI-RS grid file.
subroutine, public get_rirs_grid_filepath(element_symbol, grid_select, grid_file_suffix, filepath)
Construct the path of an RI-RS grid file.
subroutine, public initialize_rirs_grid(points, n_select, center_atom, particle_set, n_voronoi_candidates)
Build one deterministic atom-specific grid from a tabulated source grid.
subroutine, public evaluate_ao_on_points(phi, grid_points, atom_index, 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.
subroutine, public read_rirs_grid_file(filename, points)
Read Cartesian grid points from the existing CP2K RI-RS .ion format.
Type defining parameters related to the simulation cell.
Provides all information about a quickstep kind.