(git:f2099e5)
Loading...
Searching...
No Matches
gw_ri_rs_grid_setup_main.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 Main setup file for RI-RS grids {r_l}.
10!> \par History
11!> 09.2026 created
12! **************************************************************************************************
16 USE kinds, ONLY: dp,&
17 int_8
20 USE util, ONLY: sort
21#include "./base/base_uses.f90"
22
23 IMPLICIT NONE
24 PRIVATE
25
26 PUBLIC :: setup_ri_rs_grid
27
28 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'gw_ri_rs_grid_setup_main'
29
30CONTAINS
31
32! **************************************************************************************************
33!> \brief Get RI-RS grid points {r_l}, either by on-the-fly optimization or
34!> reading pretabulated atomic grids
35!> \param bs_env Band-structure environment containing GW RI-RS parameters.
36!> \param grid_points x,y,z RI-RS grid coordinates, size (3, ngrid)
37! **************************************************************************************************
38 SUBROUTINE setup_ri_rs_grid(bs_env, grid_points)
39 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
40 REAL(kind=dp), ALLOCATABLE, INTENT(OUT) :: grid_points(:, :)
41
42 IF (bs_env%ri_rs%grid_opt%enabled) THEN
43
44 ! Initialize Lebedev grids for every element from CP2K routines and then
45 ! optimize the coordinates of these grid points to minimize the RIRS error
46 !
47 ! [(μν|P) - Σ_l ϕ_μ(r_l) ϕ_ν(r_l) Z_lP^(A)]²
48 !
49 CALL optimize_ri_rs_grid(bs_env)
50
51 ELSE
52
53 ! Read pretabulated atom-relative RI-RS grids from the data files
54 CALL read_ri_rs_grid_from_file(bs_env)
55
56 END IF
57
58 ! Move atom-relative grids to their atomic centres and collect the global grid.
59 CALL assemble_ri_rs_grid(bs_env, grid_points)
60
61 END SUBROUTINE setup_ri_rs_grid
62
63! **************************************************************************************************
64!> \brief Move atom-relative RI-RS grids to their atomic centres and assemble the global grid.
65!> \param bs_env ...
66!> \param ri_rs_grid_points ...
67! **************************************************************************************************
68 SUBROUTINE assemble_ri_rs_grid(bs_env, ri_rs_grid_points)
69 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
70 REAL(kind=dp), ALLOCATABLE, INTENT(OUT) :: ri_rs_grid_points(:, :)
71
72 CHARACTER(LEN=*), PARAMETER :: routinen = 'assemble_ri_rs_grid'
73
74 INTEGER :: handle
75
76 CALL timeset(routinen, handle)
77
78 cpassert(ALLOCATED(bs_env%ri_rs%atomic_grids))
79 CALL assemble_ri_rs_grid_points(bs_env, ri_rs_grid_points)
80 CALL release_atomic_grids(bs_env)
81
82 CALL timestop(handle)
83
84 END SUBROUTINE assemble_ri_rs_grid
85
86! **************************************************************************************************
87!> \brief Assemble the global RI-RS grid in spatial atom order from atom-relative grids.
88!> \param bs_env ...
89!> \param ri_rs_grid_points ...
90! **************************************************************************************************
91 SUBROUTINE assemble_ri_rs_grid_points(bs_env, ri_rs_grid_points)
92 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
93 REAL(kind=dp), ALLOCATABLE, INTENT(OUT) :: ri_rs_grid_points(:, :)
94
95 INTEGER :: atom_grid_end, atom_grid_start, iatom, &
96 ilayout, natom
97 INTEGER, ALLOCATABLE :: atom_grid_offsets(:), atom_order(:)
98 REAL(kind=dp) :: atom_center(3)
99
100 natom = bs_env%n_atom
101 CALL spatial_atom_order(bs_env%ri_rs%particle_set, atom_order)
102
103 ALLOCATE (bs_env%ri_rs%grid_atom_boundaries(natom + 1), atom_grid_offsets(natom))
104 bs_env%ri_rs%n_grid_points = 0
105 DO ilayout = 1, natom
106 iatom = atom_order(ilayout)
107 atom_grid_offsets(iatom) = bs_env%ri_rs%n_grid_points + 1
108 bs_env%ri_rs%grid_atom_boundaries(ilayout) = bs_env%ri_rs%n_grid_points + 1
109 bs_env%ri_rs%n_grid_points = bs_env%ri_rs%n_grid_points + &
110 bs_env%ri_rs%atomic_grids(iatom)%npts
111 END DO
112 bs_env%ri_rs%grid_atom_boundaries(natom + 1) = bs_env%ri_rs%n_grid_points + 1
113
114 IF (bs_env%unit_nr > 0) THEN
115 WRITE (bs_env%unit_nr, fmt="(T2,A,T69,I12)") &
116 'Total grid points used for RI-RS:', bs_env%ri_rs%n_grid_points
117 WRITE (bs_env%unit_nr, "(A)") ' '
118 END IF
119
120 ALLOCATE (ri_rs_grid_points(3, bs_env%ri_rs%n_grid_points))
121 !$OMP PARALLEL DO DEFAULT(NONE) &
122 !$OMP SHARED(ri_rs_grid_points, atom_grid_offsets, bs_env, natom) &
123 !$OMP PRIVATE(iatom, atom_center, atom_grid_start, atom_grid_end) &
124 !$OMP SCHEDULE(DYNAMIC, 1)
125 DO iatom = 1, natom
126 atom_center(:) = bs_env%ri_rs%particle_set(iatom)%r(:)
127 atom_grid_start = atom_grid_offsets(iatom)
128 atom_grid_end = atom_grid_start + bs_env%ri_rs%atomic_grids(iatom)%npts - 1
129
130 ri_rs_grid_points(1, atom_grid_start:atom_grid_end) = &
131 bs_env%ri_rs%atomic_grids(iatom)%raw_points(1, :) + atom_center(1)
132 ri_rs_grid_points(2, atom_grid_start:atom_grid_end) = &
133 bs_env%ri_rs%atomic_grids(iatom)%raw_points(2, :) + atom_center(2)
134 ri_rs_grid_points(3, atom_grid_start:atom_grid_end) = &
135 bs_env%ri_rs%atomic_grids(iatom)%raw_points(3, :) + atom_center(3)
136 END DO
137 !$OMP END PARALLEL DO
138 END SUBROUTINE assemble_ri_rs_grid_points
139
140! **************************************************************************************************
141!> \brief Release the atom-relative RI-RS grids after assembling the global molecular grid.
142!> \param bs_env ...
143! **************************************************************************************************
144 SUBROUTINE release_atomic_grids(bs_env)
145 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
146
147 INTEGER :: iatom
148
149 DO iatom = 1, SIZE(bs_env%ri_rs%atomic_grids)
150 DEALLOCATE (bs_env%ri_rs%atomic_grids(iatom)%raw_points)
151 END DO
152 DEALLOCATE (bs_env%ri_rs%atomic_grids)
153 END SUBROUTINE release_atomic_grids
154
155! **************************************************************************************************
156!> \brief Order atoms by a three-dimensional Morton code so consecutive grid runs remain local.
157!> \param particle_set ...
158!> \param order ...
159! **************************************************************************************************
160 SUBROUTINE spatial_atom_order(particle_set, order)
161 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
162 INTEGER, ALLOCATABLE, DIMENSION(:), INTENT(OUT) :: order
163
164 CHARACTER(LEN=*), PARAMETER :: routinen = 'spatial_atom_order'
165 INTEGER, PARAMETER :: nbits = 21
166
167 INTEGER :: handle, iatom, idimension, natom
168 INTEGER(KIND=int_8) :: cmax, integer_coordinate(3), m1, m2, m3
169 INTEGER(KIND=int_8), ALLOCATABLE :: morton_code(:)
170 REAL(kind=dp) :: hi(3), lo(3), span(3)
171
172 CALL timeset(routinen, handle)
173
174 natom = SIZE(particle_set)
175 ALLOCATE (order(natom), morton_code(natom))
176 cmax = ishft(1_int_8, nbits) - 1_int_8
177
178 lo(:) = huge(1.0_dp)
179 hi(:) = -huge(1.0_dp)
180 DO iatom = 1, natom
181 DO idimension = 1, 3
182 lo(idimension) = min(lo(idimension), particle_set(iatom)%r(idimension))
183 hi(idimension) = max(hi(idimension), particle_set(iatom)%r(idimension))
184 END DO
185 END DO
186 span(:) = hi(:) - lo(:)
187 DO idimension = 1, 3
188 IF (span(idimension) <= 0.0_dp) span(idimension) = 1.0_dp
189 END DO
190
191 DO iatom = 1, natom
192 DO idimension = 1, 3
193 integer_coordinate(idimension) = &
194 int(((particle_set(iatom)%r(idimension) - lo(idimension))/span(idimension))* &
195 REAL(cmax, dp), int_8)
196 integer_coordinate(idimension) = &
197 min(cmax, max(0_int_8, integer_coordinate(idimension)))
198 END DO
199 CALL morton_split3(integer_coordinate(1), m1)
200 CALL morton_split3(integer_coordinate(2), m2)
201 CALL morton_split3(integer_coordinate(3), m3)
202 morton_code(iatom) = ior(ior(m1, ishft(m2, 1)), ishft(m3, 2))
203 END DO
204
205 CALL sort(morton_code, natom, order)
206 DEALLOCATE (morton_code)
207
208 CALL timestop(handle)
209
210 END SUBROUTINE spatial_atom_order
211
212! **************************************************************************************************
213!> \brief Spread the low 21 bits of an integer over every third bit of a Morton code.
214!> \param input_integer ...
215!> \param spread_integer ...
216! **************************************************************************************************
217 SUBROUTINE morton_split3(input_integer, spread_integer)
218 INTEGER(KIND=int_8), INTENT(IN) :: input_integer
219 INTEGER(KIND=int_8), INTENT(OUT) :: spread_integer
220
221 spread_integer = iand(input_integer, int(z'1FFFFF', int_8))
222 spread_integer = iand(ior(spread_integer, ishft(spread_integer, 32)), &
223 int(z'1F00000000FFFF', int_8))
224 spread_integer = iand(ior(spread_integer, ishft(spread_integer, 16)), &
225 int(z'1F0000FF0000FF', int_8))
226 spread_integer = iand(ior(spread_integer, ishft(spread_integer, 8)), &
227 int(z'100F00F00F00F00F', int_8))
228 spread_integer = iand(ior(spread_integer, ishft(spread_integer, 4)), &
229 int(z'10C30C30C30C30C3', int_8))
230 spread_integer = iand(ior(spread_integer, ishft(spread_integer, 2)), &
231 int(z'1249249249249249', int_8))
232 END SUBROUTINE morton_split3
233
Read pretabulated atom-relative RI-RS grids from data files.
subroutine, public read_ri_rs_grid_from_file(bs_env)
Read pretabulated atom-relative RI-RS grids from the CP2K data files.
Optimize automatically initialized atom-centred RI-RS grids.
subroutine, public optimize_ri_rs_grid(bs_env)
Initialize Lebedev grids and subsequently optimize their grid-point coordinates.
Main setup file for RI-RS grids {r_l}.
subroutine, public setup_ri_rs_grid(bs_env, grid_points)
Get RI-RS grid points {r_l}, either by on-the-fly optimization or reading pretabulated atomic grids.
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public int_8
Definition kinds.F:54
integer, parameter, public dp
Definition kinds.F:34
Define the data structure for the particle information.
All kind of helpful little routines.
Definition util.F:14