Line | Branch | Exec | Source |
---|---|---|---|
1 | module raffle__viability | ||
2 | !! Module to determine the viability of a set of gridpoints | ||
3 | !! | ||
4 | !! This module contains procedures to determine the viability of a set of | ||
5 | !! points and update the viability based on new atoms being added to the cell. | ||
6 | #ifdef _OPENMP | ||
7 | use omp_lib | ||
8 | #endif | ||
9 | use raffle__constants, only: real32 | ||
10 | use raffle__misc_linalg, only: inverse_3x3 | ||
11 | use raffle__geom_extd, only: extended_basis_type | ||
12 | use raffle__dist_calcs, only: & | ||
13 | get_min_dist_between_point_and_atom, get_min_dist | ||
14 | use raffle__evaluator, only: evaluate_point | ||
15 | use raffle__distribs_container, only: distribs_container_type | ||
16 | implicit none | ||
17 | |||
18 | |||
19 | private | ||
20 | |||
21 | public :: get_gridpoints_and_viability, update_gridpoints_and_viability | ||
22 | |||
23 | |||
24 | contains | ||
25 | |||
26 | !############################################################################### | ||
27 | 8 | function get_gridpoints_and_viability(distribs_container, grid, bounds, & | |
28 | basis, & | ||
29 | 8 | species_index_list, & | |
30 |
2/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
8 | radius_list, grid_offset) result(points) |
31 | !! Return a list of viable gridpoints and their viability for each species. | ||
32 | !! | ||
33 | !! This function returns the viability of all viable gridpoints. | ||
34 | implicit none | ||
35 | |||
36 | ! Arguments | ||
37 | type(distribs_container_type), intent(in) :: distribs_container | ||
38 | !! Distribution function (gvector) container. | ||
39 | type(extended_basis_type), intent(in) :: basis | ||
40 | !! Structure to add atom to. | ||
41 | integer, dimension(3), intent(in) :: grid | ||
42 | !! Number of gridpoints in each direction. | ||
43 | real(real32), dimension(2,3), intent(in) :: bounds | ||
44 | !! Bounds of the unit cell. | ||
45 | real(real32), dimension(:), intent(in) :: radius_list | ||
46 | !! List of radii for each pair of elements. | ||
47 | integer, dimension(:), intent(in) :: species_index_list | ||
48 | !! List of species indices to add atoms to. | ||
49 | real(real32), dimension(3), intent(in) :: grid_offset | ||
50 | !! Offset for gridpoints. | ||
51 | real(real32), dimension(:,:), allocatable :: points | ||
52 | !! List of gridpoints. | ||
53 | |||
54 | ! Local variables | ||
55 | integer :: i, j, k, l, is, ia | ||
56 | !! Loop indices. | ||
57 | integer :: num_points | ||
58 | !! Number of gridpoints. | ||
59 | real(real32) :: min_radius | ||
60 | !! Minimum radius. | ||
61 | real(real32), dimension(3) :: grid_scale, offset | ||
62 | !! Grid scale and offset. | ||
63 | real(real32), dimension(3) :: point | ||
64 | !! Gridpoint. | ||
65 | integer, dimension(3) :: idx_lw, idx_up, idx, extent, atom_idx | ||
66 | !! Gridpoint indices. | ||
67 | integer, dimension(3) :: grid_wo_bounds | ||
68 | !! Grid size of cell without bounds. | ||
69 | 8 | integer, dimension(:,:), allocatable :: idx_list | |
70 | !! Temporary list of gridpoints. | ||
71 | real(real32), dimension(3,3) :: grid_matrix | ||
72 | !! Grid conversion matrix. | ||
73 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8 times.
|
32 | logical, dimension(product(grid)) :: viable |
74 | !! Temporary list of boolean values for gridpoints. | ||
75 | |||
76 | |||
77 | !--------------------------------------------------------------------------- | ||
78 | ! get the minimum radius for the gridpoints | ||
79 | !--------------------------------------------------------------------------- | ||
80 |
6/10✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 13 times.
✓ Branch 7 taken 8 times.
✓ Branch 8 taken 12 times.
✓ Branch 9 taken 1 times.
|
29 | min_radius = minval(radius_list) * distribs_container%radius_distance_tol(1) |
81 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8 times.
|
32 | grid_scale = ( bounds(2,:) - bounds(1,:) ) / real(grid, real32) |
82 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8 times.
|
32 | grid_wo_bounds = nint( real(grid, real32) / ( bounds(2,:) - bounds(1,:) ) ) |
83 | |||
84 | |||
85 | !--------------------------------------------------------------------------- | ||
86 | ! get the grid offset in the unit cell | ||
87 | ! i.e. the grid must perfectly intersect the | ||
88 | ! grid_offset fractional coordinate | ||
89 | !--------------------------------------------------------------------------- | ||
90 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8 times.
|
32 | offset = ( grid_offset - bounds(1,:) ) / grid_scale |
91 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8 times.
|
32 | offset = offset - nint(offset) |
92 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8 times.
|
32 | offset = bounds(1,:) + offset * grid_scale |
93 | |||
94 | |||
95 | !--------------------------------------------------------------------------- | ||
96 | ! get the extent of a sphere in terms of the grid | ||
97 | !--------------------------------------------------------------------------- | ||
98 |
4/4✓ Branch 1 taken 24 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 72 times.
✓ Branch 4 taken 24 times.
|
104 | grid_matrix = transpose(inverse_3x3(basis%lat)) |
99 | extent = ceiling( [ & | ||
100 | sum( abs( grid_matrix(1,:) ) ), & | ||
101 | sum( abs( grid_matrix(2,:) ) ), & | ||
102 | sum( abs( grid_matrix(3,:) ) ) & | ||
103 |
10/10✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 24 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 24 times.
✓ Branch 7 taken 8 times.
✓ Branch 8 taken 6 times.
✓ Branch 9 taken 18 times.
|
104 | ] * min_radius * real(grid, real32) ) |
104 | |||
105 | ! precompute sphere stencil | ||
106 | 8 | num_points = 0 | |
107 |
9/16✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 8 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 8 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 8 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 8 times.
|
32 | allocate(idx_list(1:3, product( extent * 2 + [ 1, 1, 1] ))) |
108 |
2/2✓ Branch 0 taken 106 times.
✓ Branch 1 taken 8 times.
|
114 | do i = -extent(1), extent(1), 1 |
109 |
2/2✓ Branch 0 taken 1624 times.
✓ Branch 1 taken 106 times.
|
1738 | do j = -extent(2), extent(2), 1 |
110 |
2/2✓ Branch 0 taken 27226 times.
✓ Branch 1 taken 1624 times.
|
28956 | do k = -extent(3), extent(3), 1 |
111 |
2/2✓ Branch 0 taken 81678 times.
✓ Branch 1 taken 27226 times.
|
108904 | point = matmul( [ i, j, k ] / real(grid,real32), basis%lat) |
112 |
8/8✓ Branch 0 taken 81678 times.
✓ Branch 1 taken 27226 times.
✓ Branch 2 taken 76806 times.
✓ Branch 3 taken 4872 times.
✓ Branch 4 taken 12608 times.
✓ Branch 5 taken 64198 times.
✓ Branch 6 taken 10542 times.
✓ Branch 7 taken 16684 times.
|
110528 | if ( norm2(point) .lt. min_radius ) then |
113 | 10542 | num_points = num_points + 1 | |
114 |
2/2✓ Branch 0 taken 31626 times.
✓ Branch 1 taken 10542 times.
|
42168 | idx_list(:, num_points) = [ i, j, k] |
115 | end if | ||
116 | end do | ||
117 | end do | ||
118 | end do | ||
119 | |||
120 | !--------------------------------------------------------------------------- | ||
121 | ! apply stencil to exclude gridpoints too close to atoms | ||
122 | !--------------------------------------------------------------------------- | ||
123 |
2/2✓ Branch 0 taken 223880 times.
✓ Branch 1 taken 8 times.
|
223888 | viable = .true. |
124 | !$omp parallel do default(shared) private(i,is,ia,l,atom_idx,idx) | ||
125 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 8 times.
|
18 | do is = 1, basis%nspec |
126 |
2/2✓ Branch 0 taken 88 times.
✓ Branch 1 taken 10 times.
|
106 | atom_loop: do ia = 1, basis%spec(is)%num |
127 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 40 times.
|
88 | if(.not. basis%spec(is)%atom_mask(ia)) cycle atom_loop |
128 | |||
129 | ! get the atom position in terms of the grid indices | ||
130 | atom_idx = & | ||
131 |
2/2✓ Branch 0 taken 120 times.
✓ Branch 1 taken 40 times.
|
160 | nint( ( basis%spec(is)%atom(ia,1:3) - offset ) / grid_scale ) |
132 | |||
133 | ! if any one of the indicies is always outside of the grid, skip | ||
134 |
2/2✓ Branch 0 taken 120 times.
✓ Branch 1 taken 40 times.
|
160 | idx_lw = atom_idx - extent |
135 |
2/2✓ Branch 0 taken 120 times.
✓ Branch 1 taken 40 times.
|
160 | idx_lw = modulo( idx, grid_wo_bounds ) |
136 |
2/2✓ Branch 0 taken 120 times.
✓ Branch 1 taken 40 times.
|
160 | idx_up = atom_idx + extent |
137 |
2/2✓ Branch 0 taken 120 times.
✓ Branch 1 taken 40 times.
|
160 | idx_up = modulo( idx, grid_wo_bounds ) |
138 |
2/2✓ Branch 0 taken 120 times.
✓ Branch 1 taken 40 times.
|
160 | do i = 1, 3 |
139 | if( & | ||
140 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 120 times.
|
120 | idx_lw(i) .gt. grid(i) .and. idx_up(i) .lt. grid(i) & |
141 | 40 | ) cycle atom_loop | |
142 | end do | ||
143 | |||
144 | !$omp parallel do default(shared) private(i,idx) | ||
145 |
2/2✓ Branch 0 taken 70758 times.
✓ Branch 1 taken 40 times.
|
70808 | do i = 1, num_points |
146 |
2/2✓ Branch 0 taken 212274 times.
✓ Branch 1 taken 70758 times.
|
283032 | idx = idx_list(:,i) + atom_idx |
147 |
2/2✓ Branch 0 taken 212274 times.
✓ Branch 1 taken 70758 times.
|
283032 | idx = modulo( idx, grid_wo_bounds ) |
148 |
4/6✓ Branch 0 taken 212274 times.
✓ Branch 1 taken 70758 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 212274 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 70758 times.
|
283032 | if( any( idx .ge. grid ) ) cycle |
149 | viable( & | ||
150 | idx(3) * grid(2) * grid(1) + & | ||
151 | idx(2) * grid(1) + & | ||
152 | idx(1) + 1 & | ||
153 | 70798 | ) = .false. | |
154 | end do | ||
155 | !$omp end parallel do | ||
156 | end do atom_loop | ||
157 | end do | ||
158 | !$omp end parallel do | ||
159 | |||
160 | !--------------------------------------------------------------------------- | ||
161 | ! get the viable gridpoints in the unit cell | ||
162 | !--------------------------------------------------------------------------- | ||
163 |
4/4✓ Branch 0 taken 223880 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 163366 times.
✓ Branch 3 taken 60514 times.
|
223888 | num_points = count(viable) |
164 |
10/20✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 8 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 8 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 8 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 8 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 8 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 8 times.
|
8 | allocate( points( 4 + basis%nspec, num_points) ) |
165 | 8 | j = 0 | |
166 |
2/2✓ Branch 0 taken 223880 times.
✓ Branch 1 taken 8 times.
|
223888 | do i = 1, size(viable) |
167 |
2/2✓ Branch 0 taken 60514 times.
✓ Branch 1 taken 163366 times.
|
223880 | if(.not. viable(i)) cycle |
168 | 163366 | j = j + 1 | |
169 | 163366 | idx(1) = mod( i - 1, grid(1) ) | |
170 | 163366 | idx(2) = mod( ( i - 1 ) / grid(1), grid(2) ) | |
171 | 163366 | idx(3) = ( i - 1 ) / ( grid(1) * grid(2) ) | |
172 |
2/2✓ Branch 0 taken 490098 times.
✓ Branch 1 taken 163366 times.
|
653472 | points(1:3,j) = offset + grid_scale * real(idx, real32) |
173 | end do | ||
174 | |||
175 | |||
176 | !--------------------------------------------------------------------------- | ||
177 | ! run evaluate_point for a set of points in the unit cell | ||
178 | !--------------------------------------------------------------------------- | ||
179 | !$omp parallel do default(shared) private(i,is) | ||
180 |
2/2✓ Branch 0 taken 163366 times.
✓ Branch 1 taken 8 times.
|
163374 | do i = 1, num_points |
181 | 8 | do concurrent ( is = 1 : size(species_index_list,1) ) | |
182 | points(4,i) = & | ||
183 |
10/10✓ Branch 0 taken 1139328 times.
✓ Branch 1 taken 379776 times.
✓ Branch 2 taken 1139328 times.
✓ Branch 3 taken 379776 times.
✓ Branch 5 taken 1139328 times.
✓ Branch 6 taken 379776 times.
✓ Branch 7 taken 1097291 times.
✓ Branch 8 taken 42037 times.
✓ Branch 9 taken 395216 times.
✓ Branch 10 taken 702075 times.
|
3797760 | norm2( get_min_dist(basis, [ points(1:3,i) ], .false. ) ) |
184 | points(4+is,i) = & | ||
185 | evaluate_point( distribs_container, & | ||
186 | points(1:3,i), species_index_list(is), basis, radius_list & | ||
187 |
2/2✓ Branch 0 taken 379776 times.
✓ Branch 1 taken 163366 times.
|
543142 | ) |
188 | end do | ||
189 | end do | ||
190 | !$omp end parallel do | ||
191 | |||
192 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | end function get_gridpoints_and_viability |
193 | !############################################################################### | ||
194 | |||
195 | |||
196 | !############################################################################### | ||
197 | 31 | subroutine update_gridpoints_and_viability( & | |
198 | points, distribs_container, basis, & | ||
199 | 31 | species_index_list, & | |
200 |
2/4✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
|
31 | atom, radius_list & |
201 | ) | ||
202 | !! Update the list of viable gridpoints and their viability for each | ||
203 | !! species. | ||
204 | !! | ||
205 | !! This subroutine updates the viability of all viable gridpoints. | ||
206 | implicit none | ||
207 | |||
208 | ! Arguments | ||
209 | real(real32), dimension(:,:), allocatable, intent(inout) :: points | ||
210 | !! List of gridpoints. | ||
211 | type(distribs_container_type), intent(in) :: distribs_container | ||
212 | !! Distribution function (gvector) container. | ||
213 | type(extended_basis_type), intent(in) :: basis | ||
214 | !! Structure to add atom to. | ||
215 | integer, dimension(2), intent(in) :: atom | ||
216 | !! Index of atom to add. | ||
217 | real(real32), dimension(:), intent(in) :: radius_list | ||
218 | !! List of radii for each pair of elements. | ||
219 | integer, dimension(:), intent(in) :: species_index_list | ||
220 | !! List of species indices to add atoms to. | ||
221 | |||
222 | ! Local variables | ||
223 | integer :: i, is | ||
224 | !! Loop indices. | ||
225 | integer :: num_points | ||
226 | !! Number of gridpoints. | ||
227 | integer :: num_species | ||
228 | !! Number of species. | ||
229 | real(real32) :: min_radius | ||
230 | !! Minimum radius. | ||
231 | real(real32) :: distance | ||
232 | !! Distance between atom and gridpoint. | ||
233 | 31 | integer, dimension(:), allocatable :: idx | |
234 | !! List of indices of viable gridpoints. | ||
235 | 62 | logical, dimension(size(points,dim=2)) :: viable | |
236 | !! Temporary list of gridpoints. | ||
237 | real(real32), dimension(3) :: diff | ||
238 | !! Difference between atom and gridpoint (direct coorindates). | ||
239 | real(real32), dimension(3) :: atom_pos | ||
240 | !! Position of atom in direct coordinates. | ||
241 | 31 | real(real32), dimension(:,:), allocatable :: points_tmp | |
242 | !! Temporary list of gridpoints. | ||
243 | |||
244 | |||
245 | !--------------------------------------------------------------------------- | ||
246 | ! run evaluate_point for a set of points in the unit cell | ||
247 | !--------------------------------------------------------------------------- | ||
248 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
|
31 | if(.not.allocated(points)) return |
249 | 31 | num_points = size(points,dim=2) | |
250 |
2/2✓ Branch 0 taken 281526 times.
✓ Branch 1 taken 31 times.
|
281557 | viable = .true. |
251 | min_radius = max( & | ||
252 | distribs_container%cutoff_min(1), & | ||
253 | minval(radius_list) * distribs_container%radius_distance_tol(1) & | ||
254 |
5/10✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 31 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 31 times.
✓ Branch 7 taken 31 times.
✓ Branch 8 taken 31 times.
✗ Branch 9 not taken.
|
93 | ) |
255 |
2/2✓ Branch 0 taken 93 times.
✓ Branch 1 taken 31 times.
|
124 | atom_pos = basis%spec(atom(1))%atom(atom(2),1:3) |
256 | 31 | num_species = size(species_index_list,1) | |
257 | !$omp parallel do default(shared) private(i,is,diff,distance) | ||
258 |
2/2✓ Branch 0 taken 281526 times.
✓ Branch 1 taken 31 times.
|
281557 | do i = 1, num_points |
259 |
2/2✓ Branch 0 taken 844578 times.
✓ Branch 1 taken 281526 times.
|
1126104 | diff = atom_pos - points(1:3,i) |
260 |
2/2✓ Branch 0 taken 844578 times.
✓ Branch 1 taken 281526 times.
|
1126104 | diff = diff - anint(diff) |
261 |
6/6✓ Branch 1 taken 844578 times.
✓ Branch 2 taken 281526 times.
✓ Branch 3 taken 811914 times.
✓ Branch 4 taken 32664 times.
✓ Branch 5 taken 368900 times.
✓ Branch 6 taken 443014 times.
|
1126104 | distance = norm2( matmul( diff, basis%lat ) ) |
262 |
2/2✓ Branch 0 taken 32254 times.
✓ Branch 1 taken 249272 times.
|
281557 | if( distance .lt. min_radius )then |
263 | 32254 | viable(i) = .false. | |
264 | else | ||
265 |
1/2✓ Branch 0 taken 249272 times.
✗ Branch 1 not taken.
|
249272 | if( distance .le. distribs_container%cutoff_max(1) )then |
266 | 249272 | do concurrent( is = 1 : num_species ) | |
267 | points(4+is,i) = & | ||
268 | evaluate_point( distribs_container, & | ||
269 | points(1:3,i), species_index_list(is), basis, & | ||
270 | radius_list & | ||
271 |
2/2✓ Branch 0 taken 249272 times.
✓ Branch 1 taken 249272 times.
|
498544 | ) |
272 | end do | ||
273 | end if | ||
274 | 249272 | points(4,i) = min( points(4,i), distance ) | |
275 | end if | ||
276 | end do | ||
277 | !$omp end parallel do | ||
278 | |||
279 |
4/4✓ Branch 0 taken 281526 times.
✓ Branch 1 taken 31 times.
✓ Branch 2 taken 249272 times.
✓ Branch 3 taken 32254 times.
|
281557 | num_points = count(viable) |
280 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 30 times.
|
31 | if(num_points.lt.1)then |
281 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | deallocate(points) |
282 | 1 | return | |
283 | end if | ||
284 | |||
285 |
8/12✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
✓ Branch 3 taken 280724 times.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 30 times.
✓ Branch 7 taken 280724 times.
✓ Branch 8 taken 30 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 30 times.
✓ Branch 12 taken 30 times.
✗ Branch 13 not taken.
|
561478 | idx = pack([(i, i = 1, size(viable))], viable) |
286 |
7/14✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 30 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 30 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 249272 times.
✓ Branch 11 taken 30 times.
✓ Branch 12 taken 1246360 times.
✓ Branch 13 taken 249272 times.
|
1495662 | points_tmp = points(:, idx) |
287 |
1/2✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
|
30 | call move_alloc(points_tmp, points) |
288 | |||
289 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 1 times.
|
31 | end subroutine update_gridpoints_and_viability |
290 | !############################################################################### | ||
291 | |||
292 | end module raffle__viability | ||
293 |